Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/core/object/class_db.cpp
20957 views
1
/**************************************************************************/
2
/* class_db.cpp */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#include "class_db.h"
32
33
#include "core/config/engine.h"
34
#include "core/io/resource_loader.h"
35
#include "core/object/script_language.h"
36
#include "core/templates/sort_array.h"
37
#include "core/version.h"
38
39
#ifdef DEBUG_ENABLED
40
41
MethodDefinition D_METHODP(const char *p_name, const char *const **p_args, uint32_t p_argcount) {
42
MethodDefinition md;
43
md.name = StringName(p_name);
44
md.args.resize(p_argcount);
45
for (uint32_t i = 0; i < p_argcount; i++) {
46
md.args.write[i] = StringName(*p_args[i]);
47
}
48
return md;
49
}
50
51
#endif // DEBUG_ENABLED
52
53
ClassDB::APIType ClassDB::current_api = API_CORE;
54
HashMap<ClassDB::APIType, uint32_t> ClassDB::api_hashes_cache;
55
56
void ClassDB::set_current_api(APIType p_api) {
57
DEV_ASSERT(!api_hashes_cache.has(p_api)); // This API type may not be suitable for caching of hash if it can change later.
58
current_api = p_api;
59
}
60
61
ClassDB::APIType ClassDB::get_current_api() {
62
return current_api;
63
}
64
65
HashMap<StringName, ClassDB::ClassInfo> ClassDB::classes;
66
HashMap<StringName, StringName> ClassDB::resource_base_extensions;
67
HashMap<StringName, StringName> ClassDB::compat_classes;
68
69
#ifdef TOOLS_ENABLED
70
HashMap<StringName, ObjectGDExtension> ClassDB::placeholder_extensions;
71
72
class PlaceholderExtensionInstance {
73
StringName class_name;
74
HashMap<StringName, Variant> properties;
75
76
// Checks if a property is from a runtime class, and not a non-runtime base class.
77
bool is_runtime_property(const StringName &p_property_name) {
78
StringName current_class_name = class_name;
79
80
while (ClassDB::is_class_runtime(current_class_name)) {
81
if (ClassDB::has_property(current_class_name, p_property_name, true)) {
82
return true;
83
}
84
85
current_class_name = ClassDB::get_parent_class(current_class_name);
86
}
87
88
return false;
89
}
90
91
public:
92
PlaceholderExtensionInstance(const StringName &p_class_name) {
93
class_name = p_class_name;
94
}
95
96
void set(const StringName &p_name, const Variant &p_value, bool &r_valid) {
97
r_valid = is_runtime_property(p_name);
98
if (r_valid) {
99
properties[p_name] = p_value;
100
}
101
}
102
103
Variant get(const StringName &p_name, bool &r_valid) {
104
const Variant *value = properties.getptr(p_name);
105
Variant ret;
106
107
if (value) {
108
ret = *value;
109
r_valid = true;
110
} else {
111
r_valid = is_runtime_property(p_name);
112
if (r_valid) {
113
ret = ClassDB::class_get_default_property_value(class_name, p_name);
114
}
115
}
116
117
return ret;
118
}
119
120
static GDExtensionBool placeholder_instance_set(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionConstVariantPtr p_value) {
121
PlaceholderExtensionInstance *self = (PlaceholderExtensionInstance *)p_instance;
122
const StringName &name = *(StringName *)p_name;
123
const Variant &value = *(const Variant *)p_value;
124
125
bool valid = false;
126
self->set(name, value, valid);
127
128
return valid;
129
}
130
131
static GDExtensionBool placeholder_instance_get(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret) {
132
PlaceholderExtensionInstance *self = (PlaceholderExtensionInstance *)p_instance;
133
const StringName &name = *(StringName *)p_name;
134
Variant *value = (Variant *)r_ret;
135
136
bool valid = false;
137
*value = self->get(name, valid);
138
139
return valid;
140
}
141
142
static const GDExtensionPropertyInfo *placeholder_instance_get_property_list(GDExtensionClassInstancePtr p_instance, uint32_t *r_count) {
143
*r_count = 0;
144
return nullptr;
145
}
146
147
static void placeholder_instance_free_property_list(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list, uint32_t p_count) {
148
}
149
150
static GDExtensionBool placeholder_instance_property_can_revert(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name) {
151
return false;
152
}
153
154
static GDExtensionBool placeholder_instance_property_get_revert(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret) {
155
return false;
156
}
157
158
static GDExtensionBool placeholder_instance_validate_property(GDExtensionClassInstancePtr p_instance, GDExtensionPropertyInfo *p_property) {
159
return false;
160
}
161
162
static void placeholder_instance_notification(GDExtensionClassInstancePtr p_instance, int32_t p_what, GDExtensionBool p_reversed) {
163
}
164
165
static void placeholder_instance_to_string(GDExtensionClassInstancePtr p_instance, GDExtensionBool *r_is_valid, GDExtensionStringPtr p_out) {
166
*r_is_valid = true;
167
}
168
169
static void placeholder_instance_reference(GDExtensionClassInstancePtr p_instance) {
170
}
171
172
static void placeholder_instance_unreference(GDExtensionClassInstancePtr p_instance) {
173
}
174
175
static uint64_t placeholder_instance_get_rid(GDExtensionClassInstancePtr p_instance) {
176
return 0;
177
}
178
179
static GDExtensionObjectPtr placeholder_class_create_instance(void *p_class_userdata, GDExtensionBool p_notify_postinitialize) {
180
ClassDB::ClassInfo *ti = (ClassDB::ClassInfo *)p_class_userdata;
181
182
// Find the closest native parent, that isn't a runtime class.
183
ClassDB::ClassInfo *native_parent = ti->inherits_ptr;
184
while (native_parent->gdextension || native_parent->is_runtime) {
185
native_parent = native_parent->inherits_ptr;
186
}
187
ERR_FAIL_NULL_V(native_parent->creation_func, nullptr);
188
189
// Construct a placeholder.
190
Object *obj = native_parent->creation_func(static_cast<bool>(p_notify_postinitialize));
191
192
// ClassDB::set_object_extension_instance() won't be called for placeholders.
193
// We need need to make sure that all the things it would have done (even if
194
// done in a different way to support placeholders) will also be done here.
195
196
obj->_extension = ClassDB::get_placeholder_extension(ti->name);
197
obj->_extension_instance = memnew(PlaceholderExtensionInstance(ti->name));
198
199
obj->_reset_gdtype();
200
201
#ifdef TOOLS_ENABLED
202
if (obj->_extension->track_instance) {
203
obj->_extension->track_instance(obj->_extension->tracking_userdata, obj);
204
}
205
#endif
206
207
return obj;
208
}
209
210
static GDExtensionObjectPtr placeholder_class_recreate_instance(void *p_class_userdata, GDExtensionObjectPtr p_object) {
211
ClassDB::ClassInfo *ti = (ClassDB::ClassInfo *)p_class_userdata;
212
return memnew(PlaceholderExtensionInstance(ti->name));
213
}
214
215
static void placeholder_class_free_instance(void *p_class_userdata, GDExtensionClassInstancePtr p_instance) {
216
PlaceholderExtensionInstance *instance = (PlaceholderExtensionInstance *)p_instance;
217
memdelete(instance);
218
}
219
220
static GDExtensionClassCallVirtual placeholder_class_get_virtual(void *p_class_userdata, GDExtensionConstStringNamePtr p_name, uint32_t p_hash) {
221
return nullptr;
222
}
223
};
224
#endif
225
226
bool ClassDB::_is_parent_class(const StringName &p_class, const StringName &p_inherits) {
227
ClassInfo *c = classes.getptr(p_class);
228
while (c) {
229
if (c->name == p_inherits) {
230
return true;
231
}
232
c = c->inherits_ptr;
233
}
234
235
return false;
236
}
237
238
bool ClassDB::is_parent_class(const StringName &p_class, const StringName &p_inherits) {
239
Locker::Lock lock(Locker::STATE_READ);
240
241
return _is_parent_class(p_class, p_inherits);
242
}
243
244
// This function only sorts items added by this function.
245
// If `p_classes` is not empty before calling and a global sort is needed, caller must handle that separately.
246
void ClassDB::get_class_list(LocalVector<StringName> &p_classes) {
247
Locker::Lock lock(Locker::STATE_READ);
248
249
if (classes.is_empty()) {
250
return;
251
}
252
253
p_classes.reserve(p_classes.size() + classes.size());
254
for (const KeyValue<StringName, ClassInfo> &cls : classes) {
255
p_classes.push_back(cls.key);
256
}
257
258
SortArray<StringName, StringName::AlphCompare> sorter;
259
sorter.sort(&p_classes[p_classes.size() - classes.size()], classes.size());
260
}
261
262
#ifdef TOOLS_ENABLED
263
// This function only sorts items added by this function.
264
// If `p_classes` is not empty before calling and a global sort is needed, caller must handle that separately.
265
void ClassDB::get_extensions_class_list(LocalVector<StringName> &p_classes) {
266
Locker::Lock lock(Locker::STATE_READ);
267
268
uint32_t original_size = p_classes.size();
269
270
for (const KeyValue<StringName, ClassInfo> &E : classes) {
271
if (E.value.api != API_EXTENSION && E.value.api != API_EDITOR_EXTENSION) {
272
continue;
273
}
274
p_classes.push_back(E.key);
275
}
276
277
// Nothing appended.
278
if (p_classes.size() == original_size) {
279
return;
280
}
281
282
SortArray<StringName, StringName::AlphCompare> sorter;
283
sorter.sort(&p_classes[original_size], p_classes.size() - original_size);
284
}
285
286
void ClassDB::get_extension_class_list(const Ref<GDExtension> &p_extension, List<StringName> *p_classes) {
287
Locker::Lock lock(Locker::STATE_READ);
288
289
for (const KeyValue<StringName, ClassInfo> &E : classes) {
290
if (E.value.api != API_EXTENSION && E.value.api != API_EDITOR_EXTENSION) {
291
continue;
292
}
293
if (!E.value.gdextension || E.value.gdextension->library != p_extension.ptr()) {
294
continue;
295
}
296
p_classes->push_back(E.key);
297
}
298
299
p_classes->sort_custom<StringName::AlphCompare>();
300
}
301
#endif
302
303
void ClassDB::get_inheriters_from_class(const StringName &p_class, LocalVector<StringName> &p_classes) {
304
Locker::Lock lock(Locker::STATE_READ);
305
306
for (const KeyValue<StringName, ClassInfo> &E : classes) {
307
if (E.key != p_class && _is_parent_class(E.key, p_class)) {
308
p_classes.push_back(E.key);
309
}
310
}
311
}
312
313
void ClassDB::get_direct_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes) {
314
Locker::Lock lock(Locker::STATE_READ);
315
316
for (const KeyValue<StringName, ClassInfo> &E : classes) {
317
if (E.value.inherits == p_class) {
318
p_classes->push_back(E.key);
319
}
320
}
321
}
322
323
StringName ClassDB::get_parent_class_nocheck(const StringName &p_class) {
324
Locker::Lock lock(Locker::STATE_READ);
325
326
ClassInfo *ti = classes.getptr(p_class);
327
if (!ti) {
328
return StringName();
329
}
330
return ti->inherits;
331
}
332
333
bool ClassDB::get_inheritance_chain_nocheck(const StringName &p_class, Vector<StringName> &r_result) {
334
Locker::Lock lock(Locker::STATE_READ);
335
336
ClassInfo *start = classes.getptr(p_class);
337
if (!start) {
338
return false;
339
}
340
341
int classes_to_add = 0;
342
for (ClassInfo *ti = start; ti; ti = ti->inherits_ptr) {
343
classes_to_add++;
344
}
345
346
int64_t old_size = r_result.size();
347
r_result.resize(old_size + classes_to_add);
348
StringName *w = r_result.ptrw() + old_size;
349
for (ClassInfo *ti = start; ti; ti = ti->inherits_ptr) {
350
*w++ = ti->name;
351
}
352
353
return true;
354
}
355
356
StringName ClassDB::get_compatibility_remapped_class(const StringName &p_class) {
357
if (classes.has(p_class)) {
358
return p_class;
359
}
360
361
if (compat_classes.has(p_class)) {
362
return compat_classes[p_class];
363
}
364
365
return p_class;
366
}
367
368
StringName ClassDB::_get_parent_class(const StringName &p_class) {
369
ClassInfo *ti = classes.getptr(p_class);
370
ERR_FAIL_NULL_V_MSG(ti, StringName(), vformat("Cannot get class '%s'.", String(p_class)));
371
return ti->inherits;
372
}
373
374
StringName ClassDB::get_parent_class(const StringName &p_class) {
375
Locker::Lock lock(Locker::STATE_READ);
376
377
return _get_parent_class(p_class);
378
}
379
380
ClassDB::APIType ClassDB::get_api_type(const StringName &p_class) {
381
Locker::Lock lock(Locker::STATE_READ);
382
383
ClassInfo *ti = classes.getptr(p_class);
384
385
ERR_FAIL_NULL_V_MSG(ti, API_NONE, vformat("Cannot get class '%s'.", String(p_class)));
386
return ti->api;
387
}
388
389
uint32_t ClassDB::get_api_hash(APIType p_api) {
390
#ifdef DEBUG_ENABLED
391
Locker::Lock lock(Locker::STATE_WRITE);
392
393
if (api_hashes_cache.has(p_api)) {
394
return api_hashes_cache[p_api];
395
}
396
397
uint64_t hash = hash_murmur3_one_64(HashMapHasherDefault::hash(GODOT_VERSION_FULL_CONFIG));
398
399
List<StringName> class_list;
400
for (const KeyValue<StringName, ClassInfo> &E : classes) {
401
class_list.push_back(E.key);
402
}
403
// Must be alphabetically sorted for hash to compute.
404
class_list.sort_custom<StringName::AlphCompare>();
405
406
for (const StringName &E : class_list) {
407
ClassInfo *t = classes.getptr(E);
408
ERR_FAIL_NULL_V_MSG(t, 0, vformat("Cannot get class '%s'.", String(E)));
409
if (t->api != p_api || !t->exposed) {
410
continue;
411
}
412
hash = hash_murmur3_one_64(t->name.hash(), hash);
413
hash = hash_murmur3_one_64(t->inherits.hash(), hash);
414
415
{ //methods
416
417
List<StringName> snames;
418
419
for (const KeyValue<StringName, MethodBind *> &F : t->method_map) {
420
String name = F.key.operator String();
421
422
ERR_CONTINUE(name.is_empty());
423
424
if (name[0] == '_') {
425
continue; // Ignore non-virtual methods that start with an underscore
426
}
427
428
snames.push_back(F.key);
429
}
430
431
snames.sort_custom<StringName::AlphCompare>();
432
433
for (const StringName &F : snames) {
434
MethodBind *mb = t->method_map[F];
435
hash = hash_murmur3_one_64(mb->get_name().hash(), hash);
436
hash = hash_murmur3_one_64(mb->get_argument_count(), hash);
437
hash = hash_murmur3_one_64(mb->get_argument_type(-1), hash); //return
438
439
for (int i = 0; i < mb->get_argument_count(); i++) {
440
const PropertyInfo info = mb->get_argument_info(i);
441
hash = hash_murmur3_one_64(info.type, hash);
442
hash = hash_murmur3_one_64(info.name.hash(), hash);
443
hash = hash_murmur3_one_64(info.hint, hash);
444
hash = hash_murmur3_one_64(info.hint_string.hash(), hash);
445
}
446
447
hash = hash_murmur3_one_64(mb->get_default_argument_count(), hash);
448
449
for (int i = 0; i < mb->get_argument_count(); i++) {
450
if (mb->has_default_argument(i)) {
451
Variant da = mb->get_default_argument(i);
452
hash = hash_murmur3_one_64(da.hash(), hash);
453
}
454
}
455
456
hash = hash_murmur3_one_64(mb->get_hint_flags(), hash);
457
}
458
}
459
460
{ //constants
461
462
List<StringName> snames;
463
464
for (const KeyValue<StringName, int64_t> &F : t->constant_map) {
465
snames.push_back(F.key);
466
}
467
468
snames.sort_custom<StringName::AlphCompare>();
469
470
for (const StringName &F : snames) {
471
hash = hash_murmur3_one_64(F.hash(), hash);
472
hash = hash_murmur3_one_64(uint64_t(t->constant_map[F]), hash);
473
}
474
}
475
476
{ //signals
477
478
List<StringName> snames;
479
480
for (const KeyValue<StringName, MethodInfo> &F : t->signal_map) {
481
snames.push_back(F.key);
482
}
483
484
snames.sort_custom<StringName::AlphCompare>();
485
486
for (const StringName &F : snames) {
487
MethodInfo &mi = t->signal_map[F];
488
hash = hash_murmur3_one_64(F.hash(), hash);
489
for (const PropertyInfo &pi : mi.arguments) {
490
hash = hash_murmur3_one_64(pi.type, hash);
491
}
492
}
493
}
494
495
{ //properties
496
497
List<StringName> snames;
498
499
for (const KeyValue<StringName, PropertySetGet> &F : t->property_setget) {
500
snames.push_back(F.key);
501
}
502
503
snames.sort_custom<StringName::AlphCompare>();
504
505
for (const StringName &F : snames) {
506
PropertySetGet *psg = t->property_setget.getptr(F);
507
ERR_FAIL_NULL_V(psg, 0);
508
509
hash = hash_murmur3_one_64(F.hash(), hash);
510
hash = hash_murmur3_one_64(psg->setter.hash(), hash);
511
hash = hash_murmur3_one_64(psg->getter.hash(), hash);
512
}
513
}
514
515
//property list
516
for (const PropertyInfo &F : t->property_list) {
517
hash = hash_murmur3_one_64(F.name.hash(), hash);
518
hash = hash_murmur3_one_64(F.type, hash);
519
hash = hash_murmur3_one_64(F.hint, hash);
520
hash = hash_murmur3_one_64(F.hint_string.hash(), hash);
521
hash = hash_murmur3_one_64(F.usage, hash);
522
}
523
}
524
525
hash = hash_fmix32(hash);
526
527
// Extension API changes at runtime; let's just not cache them by now.
528
if (p_api != API_EXTENSION && p_api != API_EDITOR_EXTENSION) {
529
api_hashes_cache[p_api] = hash;
530
}
531
532
return hash;
533
#else
534
return 0;
535
#endif // DEBUG_ENABLED
536
}
537
538
bool ClassDB::class_exists(const StringName &p_class) {
539
Locker::Lock lock(Locker::STATE_READ);
540
return classes.has(p_class);
541
}
542
543
void ClassDB::add_compatibility_class(const StringName &p_class, const StringName &p_fallback) {
544
Locker::Lock lock(Locker::STATE_WRITE);
545
compat_classes[p_class] = p_fallback;
546
}
547
548
StringName ClassDB::get_compatibility_class(const StringName &p_class) {
549
if (compat_classes.has(p_class)) {
550
return compat_classes[p_class];
551
}
552
return StringName();
553
}
554
555
Object *ClassDB::_instantiate_internal(const StringName &p_class, bool p_require_real_class, bool p_notify_postinitialize, bool p_exposed_only) {
556
ClassInfo *ti;
557
{
558
Locker::Lock lock(Locker::STATE_READ);
559
ti = classes.getptr(p_class);
560
if (!_can_instantiate(ti, p_exposed_only)) {
561
if (compat_classes.has(p_class)) {
562
ti = classes.getptr(compat_classes[p_class]);
563
}
564
}
565
ERR_FAIL_NULL_V_MSG(ti, nullptr, vformat("Cannot get class '%s'.", String(p_class)));
566
ERR_FAIL_COND_V_MSG(ti->disabled, nullptr, vformat("Class '%s' is disabled.", String(p_class)));
567
#ifndef DISABLE_DEPRECATED
568
// Force legacy unexposed classes to skip the exposed check to preserve backcompat.
569
if (ti->gdextension && ti->gdextension->legacy_unexposed_class) {
570
p_exposed_only = false;
571
}
572
#endif // DISABLE_DEPRECATED
573
if (p_exposed_only) {
574
ERR_FAIL_COND_V_MSG(!ti->exposed, nullptr, vformat("Class '%s' isn't exposed.", String(p_class)));
575
}
576
ERR_FAIL_NULL_V_MSG(ti->creation_func, nullptr, vformat("Class '%s' or its base class cannot be instantiated.", String(p_class)));
577
}
578
579
#ifdef TOOLS_ENABLED
580
if ((ti->api == API_EDITOR || ti->api == API_EDITOR_EXTENSION) && !Engine::get_singleton()->is_editor_hint()) {
581
ERR_PRINT(vformat("Class '%s' can only be instantiated by editor.", String(p_class)));
582
return nullptr;
583
}
584
#endif
585
586
#ifdef TOOLS_ENABLED
587
// Try to create placeholder.
588
if (!p_require_real_class && ti->is_runtime && Engine::get_singleton()->is_editor_hint()) {
589
bool can_create_placeholder = false;
590
if (ti->gdextension) {
591
if (ti->gdextension->create_instance2) {
592
can_create_placeholder = true;
593
}
594
#ifndef DISABLE_DEPRECATED
595
else if (ti->gdextension->create_instance) {
596
can_create_placeholder = true;
597
}
598
#endif // DISABLE_DEPRECATED
599
} else if (!ti->inherits_ptr || !ti->inherits_ptr->creation_func) {
600
ERR_PRINT(vformat("Cannot make a placeholder instance of runtime class %s because its parent cannot be constructed.", ti->name));
601
} else {
602
can_create_placeholder = true;
603
}
604
605
if (can_create_placeholder) {
606
ObjectGDExtension *extension = get_placeholder_extension(ti->name);
607
return (Object *)extension->create_instance2(extension->class_userdata, p_notify_postinitialize);
608
}
609
}
610
#endif // TOOLS_ENABLED
611
612
if (ti->gdextension && ti->gdextension->create_instance2) {
613
ObjectGDExtension *extension = ti->gdextension;
614
return (Object *)extension->create_instance2(extension->class_userdata, p_notify_postinitialize);
615
}
616
#ifndef DISABLE_DEPRECATED
617
else if (ti->gdextension && ti->gdextension->create_instance) {
618
ObjectGDExtension *extension = ti->gdextension;
619
return (Object *)extension->create_instance(extension->class_userdata);
620
}
621
#endif // DISABLE_DEPRECATED
622
else {
623
return ti->creation_func(p_notify_postinitialize);
624
}
625
}
626
627
bool ClassDB::_can_instantiate(ClassInfo *p_class_info, bool p_exposed_only) {
628
if (!p_class_info) {
629
return false;
630
}
631
632
#ifndef DISABLE_DEPRECATED
633
// Force legacy unexposed classes to skip the exposed check to preserve backcompat.
634
if (p_class_info->gdextension && p_class_info->gdextension->legacy_unexposed_class) {
635
p_exposed_only = false;
636
}
637
#endif // DISABLE_DEPRECATED
638
639
if (p_exposed_only && !p_class_info->exposed) {
640
return false;
641
}
642
643
if (p_class_info->disabled || !p_class_info->creation_func) {
644
return false;
645
}
646
647
if (!p_class_info->gdextension) {
648
return true;
649
}
650
651
if (p_class_info->gdextension->create_instance2) {
652
return true;
653
}
654
655
#ifndef DISABLE_DEPRECATED
656
if (p_class_info->gdextension->create_instance) {
657
return true;
658
}
659
#endif // DISABLE_DEPRECATED
660
return false;
661
}
662
663
Object *ClassDB::instantiate(const StringName &p_class) {
664
return _instantiate_internal(p_class);
665
}
666
667
Object *ClassDB::instantiate_no_placeholders(const StringName &p_class) {
668
return _instantiate_internal(p_class, true);
669
}
670
671
Object *ClassDB::instantiate_without_postinitialization(const StringName &p_class) {
672
return _instantiate_internal(p_class, true, false);
673
}
674
675
#ifdef TOOLS_ENABLED
676
ObjectGDExtension *ClassDB::get_placeholder_extension(const StringName &p_class) {
677
ObjectGDExtension *placeholder_extension = placeholder_extensions.getptr(p_class);
678
if (placeholder_extension) {
679
return placeholder_extension;
680
}
681
682
ClassInfo *ti;
683
{
684
Locker::Lock lock(Locker::STATE_READ);
685
ti = classes.getptr(p_class);
686
if (!_can_instantiate(ti)) {
687
if (compat_classes.has(p_class)) {
688
ti = classes.getptr(compat_classes[p_class]);
689
}
690
}
691
ERR_FAIL_NULL_V_MSG(ti, nullptr, vformat("Cannot get class '%s'.", String(p_class)));
692
ERR_FAIL_COND_V_MSG(ti->disabled, nullptr, vformat("Class '%s' is disabled.", String(p_class)));
693
}
694
695
// Make a "fake" extension to act as a placeholder.
696
placeholder_extensions[p_class] = ObjectGDExtension();
697
placeholder_extension = placeholder_extensions.getptr(p_class);
698
699
placeholder_extension->is_runtime = true;
700
placeholder_extension->is_placeholder = true;
701
702
if (ti->gdextension) {
703
placeholder_extension->library = ti->gdextension->library;
704
placeholder_extension->parent = ti->gdextension->parent;
705
placeholder_extension->children = ti->gdextension->children;
706
placeholder_extension->parent_class_name = ti->gdextension->parent_class_name;
707
placeholder_extension->class_name = ti->gdextension->class_name;
708
placeholder_extension->editor_class = ti->gdextension->editor_class;
709
placeholder_extension->reloadable = ti->gdextension->reloadable;
710
placeholder_extension->is_virtual = ti->gdextension->is_virtual;
711
placeholder_extension->is_abstract = ti->gdextension->is_abstract;
712
placeholder_extension->is_exposed = ti->gdextension->is_exposed;
713
714
placeholder_extension->tracking_userdata = ti->gdextension->tracking_userdata;
715
placeholder_extension->track_instance = ti->gdextension->track_instance;
716
placeholder_extension->untrack_instance = ti->gdextension->untrack_instance;
717
} else {
718
placeholder_extension->library = nullptr;
719
placeholder_extension->parent = nullptr;
720
placeholder_extension->parent_class_name = ti->inherits;
721
placeholder_extension->class_name = ti->name;
722
placeholder_extension->editor_class = ti->api == API_EDITOR;
723
placeholder_extension->reloadable = false;
724
placeholder_extension->is_virtual = ti->is_virtual;
725
placeholder_extension->is_abstract = false;
726
placeholder_extension->is_exposed = ti->exposed;
727
}
728
729
placeholder_extension->set = &PlaceholderExtensionInstance::placeholder_instance_set;
730
placeholder_extension->get = &PlaceholderExtensionInstance::placeholder_instance_get;
731
placeholder_extension->get_property_list = &PlaceholderExtensionInstance::placeholder_instance_get_property_list;
732
placeholder_extension->free_property_list2 = &PlaceholderExtensionInstance::placeholder_instance_free_property_list;
733
placeholder_extension->property_can_revert = &PlaceholderExtensionInstance::placeholder_instance_property_can_revert;
734
placeholder_extension->property_get_revert = &PlaceholderExtensionInstance::placeholder_instance_property_get_revert;
735
placeholder_extension->validate_property = &PlaceholderExtensionInstance::placeholder_instance_validate_property;
736
#ifndef DISABLE_DEPRECATED
737
placeholder_extension->notification = nullptr;
738
placeholder_extension->free_property_list = nullptr;
739
#endif // DISABLE_DEPRECATED
740
placeholder_extension->notification2 = &PlaceholderExtensionInstance::placeholder_instance_notification;
741
placeholder_extension->to_string = &PlaceholderExtensionInstance::placeholder_instance_to_string;
742
placeholder_extension->reference = &PlaceholderExtensionInstance::placeholder_instance_reference;
743
placeholder_extension->unreference = &PlaceholderExtensionInstance::placeholder_instance_unreference;
744
placeholder_extension->get_rid = &PlaceholderExtensionInstance::placeholder_instance_get_rid;
745
746
placeholder_extension->class_userdata = ti;
747
#ifndef DISABLE_DEPRECATED
748
placeholder_extension->create_instance = nullptr;
749
#endif // DISABLE_DEPRECATED
750
placeholder_extension->create_instance2 = &PlaceholderExtensionInstance::placeholder_class_create_instance;
751
placeholder_extension->free_instance = &PlaceholderExtensionInstance::placeholder_class_free_instance;
752
#ifndef DISABLE_DEPRECATED
753
placeholder_extension->get_virtual = nullptr;
754
placeholder_extension->get_virtual_call_data = nullptr;
755
#endif // DISABLE_DEPRECATED
756
placeholder_extension->get_virtual2 = &PlaceholderExtensionInstance::placeholder_class_get_virtual;
757
placeholder_extension->get_virtual_call_data2 = nullptr;
758
placeholder_extension->call_virtual_with_data = nullptr;
759
placeholder_extension->recreate_instance = &PlaceholderExtensionInstance::placeholder_class_recreate_instance;
760
761
placeholder_extension->create_gdtype();
762
763
return placeholder_extension;
764
}
765
#endif
766
767
const GDType *ClassDB::get_gdtype(const StringName &p_class) {
768
Locker::Lock lock(Locker::STATE_READ);
769
ClassInfo *type = classes.getptr(p_class);
770
ERR_FAIL_NULL_V(type, nullptr);
771
return type->gdtype;
772
}
773
774
void ClassDB::set_object_extension_instance(Object *p_object, const StringName &p_class, GDExtensionClassInstancePtr p_instance) {
775
ERR_FAIL_NULL(p_object);
776
ClassInfo *ti;
777
{
778
Locker::Lock lock(Locker::STATE_READ);
779
ti = classes.getptr(p_class);
780
if (!_can_instantiate(ti)) {
781
if (compat_classes.has(p_class)) {
782
ti = classes.getptr(compat_classes[p_class]);
783
}
784
}
785
ERR_FAIL_NULL_MSG(ti, vformat("Cannot get class '%s'.", String(p_class)));
786
ERR_FAIL_COND_MSG(ti->disabled, vformat("Class '%s' is disabled.", String(p_class)));
787
ERR_FAIL_NULL_MSG(ti->gdextension, vformat("Class '%s' has no native extension.", String(p_class)));
788
}
789
790
p_object->_extension = ti->gdextension;
791
p_object->_extension_instance = p_instance;
792
793
p_object->_reset_gdtype();
794
795
#ifdef TOOLS_ENABLED
796
if (p_object->_extension->track_instance) {
797
p_object->_extension->track_instance(p_object->_extension->tracking_userdata, p_object);
798
}
799
#endif
800
}
801
802
bool ClassDB::can_instantiate(const StringName &p_class) {
803
String script_path;
804
{
805
Locker::Lock lock(Locker::STATE_READ);
806
807
ClassInfo *ti = classes.getptr(p_class);
808
if (!ti) {
809
if (!ScriptServer::is_global_class(p_class)) {
810
ERR_FAIL_V_MSG(false, vformat("Cannot get class '%s'.", String(p_class)));
811
}
812
script_path = ScriptServer::get_global_class_path(p_class);
813
goto use_script; // Open the lock for resource loading.
814
}
815
#ifdef TOOLS_ENABLED
816
if ((ti->api == API_EDITOR || ti->api == API_EDITOR_EXTENSION) && !Engine::get_singleton()->is_editor_hint()) {
817
return false;
818
}
819
#endif
820
return _can_instantiate(ti);
821
}
822
823
use_script:
824
Ref<Script> scr = ResourceLoader::load(script_path);
825
return scr.is_valid() && scr->is_valid() && !scr->is_abstract();
826
}
827
828
bool ClassDB::is_abstract(const StringName &p_class) {
829
String script_path;
830
{
831
Locker::Lock lock(Locker::STATE_READ);
832
833
ClassInfo *ti = classes.getptr(p_class);
834
if (!ti) {
835
if (!ScriptServer::is_global_class(p_class)) {
836
ERR_FAIL_V_MSG(false, vformat("Cannot get class '%s'.", String(p_class)));
837
}
838
script_path = ScriptServer::get_global_class_path(p_class);
839
goto use_script; // Open the lock for resource loading.
840
}
841
842
if (ti->creation_func != nullptr) {
843
return false;
844
}
845
if (!ti->gdextension) {
846
return true;
847
}
848
#ifndef DISABLE_DEPRECATED
849
return ti->gdextension->create_instance2 == nullptr && ti->gdextension->create_instance == nullptr;
850
#else
851
return ti->gdextension->create_instance2 == nullptr;
852
#endif // DISABLE_DEPRECATED
853
}
854
855
use_script:
856
Ref<Script> scr = ResourceLoader::load(script_path);
857
return scr.is_valid() && scr->is_valid() && scr->is_abstract();
858
}
859
860
bool ClassDB::is_virtual(const StringName &p_class) {
861
String script_path;
862
{
863
Locker::Lock lock(Locker::STATE_READ);
864
865
ClassInfo *ti = classes.getptr(p_class);
866
if (!ti) {
867
if (!ScriptServer::is_global_class(p_class)) {
868
ERR_FAIL_V_MSG(false, vformat("Cannot get class '%s'.", String(p_class)));
869
}
870
script_path = ScriptServer::get_global_class_path(p_class);
871
goto use_script; // Open the lock for resource loading.
872
}
873
#ifdef TOOLS_ENABLED
874
if ((ti->api == API_EDITOR || ti->api == API_EDITOR_EXTENSION) && !Engine::get_singleton()->is_editor_hint()) {
875
return false;
876
}
877
#endif
878
return (_can_instantiate(ti) && ti->is_virtual);
879
}
880
881
use_script:
882
Ref<Script> scr = ResourceLoader::load(script_path);
883
return scr.is_valid() && scr->is_valid() && scr->is_abstract();
884
}
885
886
void ClassDB::_add_class(const GDType &p_class, const GDType *p_inherits) {
887
Locker::Lock lock(Locker::STATE_WRITE);
888
889
const StringName &name = p_class.get_name();
890
891
ERR_FAIL_COND_MSG(classes.has(name), vformat("Class '%s' already exists.", name));
892
893
classes[name] = ClassInfo();
894
ClassInfo &ti = classes[name];
895
ti.name = name;
896
ti.gdtype = &p_class;
897
if (p_inherits) {
898
ti.inherits = p_inherits->get_name();
899
}
900
ti.api = current_api;
901
902
if (ti.inherits) {
903
ERR_FAIL_COND(!classes.has(ti.inherits)); //it MUST be registered.
904
ti.inherits_ptr = &classes[ti.inherits];
905
906
} else {
907
ti.inherits_ptr = nullptr;
908
}
909
}
910
911
static MethodInfo info_from_bind(MethodBind *p_method) {
912
MethodInfo minfo;
913
minfo.name = p_method->get_name();
914
minfo.id = p_method->get_method_id();
915
916
for (int i = 0; i < p_method->get_argument_count(); i++) {
917
minfo.arguments.push_back(p_method->get_argument_info(i));
918
}
919
920
minfo.return_val = p_method->get_return_info();
921
minfo.flags = p_method->get_hint_flags();
922
923
for (int i = 0; i < p_method->get_argument_count(); i++) {
924
if (p_method->has_default_argument(i)) {
925
minfo.default_arguments.push_back(p_method->get_default_argument(i));
926
}
927
}
928
929
return minfo;
930
}
931
932
void ClassDB::get_method_list(const StringName &p_class, List<MethodInfo> *p_methods, bool p_no_inheritance, bool p_exclude_from_properties) {
933
Locker::Lock lock(Locker::STATE_READ);
934
935
ClassInfo *type = classes.getptr(p_class);
936
937
while (type) {
938
if (type->disabled) {
939
if (p_no_inheritance) {
940
break;
941
}
942
943
type = type->inherits_ptr;
944
continue;
945
}
946
947
#ifdef DEBUG_ENABLED
948
for (const MethodInfo &E : type->virtual_methods) {
949
p_methods->push_back(E);
950
}
951
952
for (const StringName &E : type->method_order) {
953
if (p_exclude_from_properties && type->methods_in_properties.has(E)) {
954
continue;
955
}
956
957
MethodBind *method = type->method_map.get(E);
958
MethodInfo minfo = info_from_bind(method);
959
960
p_methods->push_back(minfo);
961
}
962
#else
963
for (KeyValue<StringName, MethodBind *> &E : type->method_map) {
964
MethodBind *m = E.value;
965
MethodInfo minfo = info_from_bind(m);
966
p_methods->push_back(minfo);
967
}
968
#endif // DEBUG_ENABLED
969
970
if (p_no_inheritance) {
971
break;
972
}
973
974
type = type->inherits_ptr;
975
}
976
}
977
978
void ClassDB::get_method_list_with_compatibility(const StringName &p_class, List<Pair<MethodInfo, uint32_t>> *p_methods, bool p_no_inheritance, bool p_exclude_from_properties) {
979
Locker::Lock lock(Locker::STATE_READ);
980
981
ClassInfo *type = classes.getptr(p_class);
982
983
while (type) {
984
if (type->disabled) {
985
if (p_no_inheritance) {
986
break;
987
}
988
989
type = type->inherits_ptr;
990
continue;
991
}
992
993
#ifdef DEBUG_ENABLED
994
for (const MethodInfo &E : type->virtual_methods) {
995
Pair<MethodInfo, uint32_t> pair(E, E.get_compatibility_hash());
996
p_methods->push_back(pair);
997
}
998
999
for (const StringName &E : type->method_order) {
1000
if (p_exclude_from_properties && type->methods_in_properties.has(E)) {
1001
continue;
1002
}
1003
1004
MethodBind *method = type->method_map.get(E);
1005
MethodInfo minfo = info_from_bind(method);
1006
1007
Pair<MethodInfo, uint32_t> pair(minfo, method->get_hash());
1008
p_methods->push_back(pair);
1009
}
1010
#else
1011
for (KeyValue<StringName, MethodBind *> &E : type->method_map) {
1012
MethodBind *method = E.value;
1013
MethodInfo minfo = info_from_bind(method);
1014
1015
Pair<MethodInfo, uint32_t> pair(minfo, method->get_hash());
1016
p_methods->push_back(pair);
1017
}
1018
#endif // DEBUG_ENABLED
1019
1020
for (const KeyValue<StringName, LocalVector<MethodBind *, unsigned int, false, false>> &E : type->method_map_compatibility) {
1021
LocalVector<MethodBind *> compat(E.value);
1022
for (MethodBind *method : compat) {
1023
MethodInfo minfo = info_from_bind(method);
1024
1025
Pair<MethodInfo, uint32_t> pair(minfo, method->get_hash());
1026
p_methods->push_back(pair);
1027
}
1028
}
1029
1030
if (p_no_inheritance) {
1031
break;
1032
}
1033
1034
type = type->inherits_ptr;
1035
}
1036
}
1037
1038
bool ClassDB::get_method_info(const StringName &p_class, const StringName &p_method, MethodInfo *r_info, bool p_no_inheritance, bool p_exclude_from_properties) {
1039
Locker::Lock lock(Locker::STATE_READ);
1040
1041
ClassInfo *type = classes.getptr(p_class);
1042
1043
while (type) {
1044
if (type->disabled) {
1045
if (p_no_inheritance) {
1046
break;
1047
}
1048
1049
type = type->inherits_ptr;
1050
continue;
1051
}
1052
1053
#ifdef DEBUG_ENABLED
1054
MethodBind **method = type->method_map.getptr(p_method);
1055
if (method && *method) {
1056
if (r_info != nullptr) {
1057
MethodInfo minfo = info_from_bind(*method);
1058
*r_info = minfo;
1059
}
1060
return true;
1061
} else if (type->virtual_methods_map.has(p_method)) {
1062
if (r_info) {
1063
*r_info = type->virtual_methods_map[p_method];
1064
}
1065
return true;
1066
}
1067
#else
1068
if (type->method_map.has(p_method)) {
1069
if (r_info) {
1070
MethodBind *m = type->method_map[p_method];
1071
MethodInfo minfo = info_from_bind(m);
1072
*r_info = minfo;
1073
}
1074
return true;
1075
}
1076
#endif // DEBUG_ENABLED
1077
1078
if (p_no_inheritance) {
1079
break;
1080
}
1081
1082
type = type->inherits_ptr;
1083
}
1084
1085
return false;
1086
}
1087
1088
MethodBind *ClassDB::get_method(const StringName &p_class, const StringName &p_name) {
1089
Locker::Lock lock(Locker::STATE_READ);
1090
1091
ClassInfo *type = classes.getptr(p_class);
1092
1093
while (type) {
1094
MethodBind **method = type->method_map.getptr(p_name);
1095
if (method && *method) {
1096
return *method;
1097
}
1098
type = type->inherits_ptr;
1099
}
1100
return nullptr;
1101
}
1102
1103
Vector<uint32_t> ClassDB::get_method_compatibility_hashes(const StringName &p_class, const StringName &p_name) {
1104
Locker::Lock lock(Locker::STATE_READ);
1105
1106
ClassInfo *type = classes.getptr(p_class);
1107
1108
while (type) {
1109
if (type->method_map_compatibility.has(p_name)) {
1110
LocalVector<MethodBind *> *c = type->method_map_compatibility.getptr(p_name);
1111
Vector<uint32_t> ret;
1112
for (uint32_t i = 0; i < c->size(); i++) {
1113
ret.push_back((*c)[i]->get_hash());
1114
}
1115
return ret;
1116
}
1117
type = type->inherits_ptr;
1118
}
1119
return Vector<uint32_t>();
1120
}
1121
1122
MethodBind *ClassDB::get_method_with_compatibility(const StringName &p_class, const StringName &p_name, uint64_t p_hash, bool *r_method_exists, bool *r_is_deprecated) {
1123
Locker::Lock lock(Locker::STATE_READ);
1124
1125
ClassInfo *type = classes.getptr(p_class);
1126
1127
while (type) {
1128
MethodBind **method = type->method_map.getptr(p_name);
1129
if (method && *method) {
1130
if (r_method_exists) {
1131
*r_method_exists = true;
1132
}
1133
if ((*method)->get_hash() == p_hash) {
1134
return *method;
1135
}
1136
}
1137
1138
LocalVector<MethodBind *> *compat = type->method_map_compatibility.getptr(p_name);
1139
if (compat) {
1140
if (r_method_exists) {
1141
*r_method_exists = true;
1142
}
1143
for (uint32_t i = 0; i < compat->size(); i++) {
1144
if ((*compat)[i]->get_hash() == p_hash) {
1145
if (r_is_deprecated) {
1146
*r_is_deprecated = true;
1147
}
1148
return (*compat)[i];
1149
}
1150
}
1151
}
1152
type = type->inherits_ptr;
1153
}
1154
return nullptr;
1155
}
1156
1157
void ClassDB::bind_integer_constant(const StringName &p_class, const StringName &p_enum, const StringName &p_name, int64_t p_constant, bool p_is_bitfield) {
1158
Locker::Lock lock(Locker::STATE_WRITE);
1159
1160
ClassInfo *type = classes.getptr(p_class);
1161
1162
ERR_FAIL_NULL(type);
1163
1164
if (type->constant_map.has(p_name)) {
1165
ERR_FAIL();
1166
}
1167
1168
type->constant_map[p_name] = p_constant;
1169
1170
String enum_name = p_enum;
1171
if (!enum_name.is_empty()) {
1172
if (enum_name.contains_char('.')) {
1173
enum_name = enum_name.get_slicec('.', 1);
1174
}
1175
1176
ClassInfo::EnumInfo *constants_list = type->enum_map.getptr(enum_name);
1177
1178
if (constants_list) {
1179
constants_list->constants.push_back(p_name);
1180
constants_list->is_bitfield = p_is_bitfield;
1181
} else {
1182
ClassInfo::EnumInfo new_list;
1183
new_list.is_bitfield = p_is_bitfield;
1184
new_list.constants.push_back(p_name);
1185
type->enum_map[enum_name] = new_list;
1186
}
1187
}
1188
1189
#ifdef DEBUG_ENABLED
1190
type->constant_order.push_back(p_name);
1191
#endif // DEBUG_ENABLED
1192
}
1193
1194
void ClassDB::get_integer_constant_list(const StringName &p_class, List<String> *p_constants, bool p_no_inheritance) {
1195
Locker::Lock lock(Locker::STATE_READ);
1196
1197
ClassInfo *type = classes.getptr(p_class);
1198
1199
while (type) {
1200
#ifdef DEBUG_ENABLED
1201
for (const StringName &E : type->constant_order) {
1202
p_constants->push_back(E);
1203
}
1204
#else
1205
1206
for (const KeyValue<StringName, int64_t> &E : type->constant_map) {
1207
p_constants->push_back(E.key);
1208
}
1209
1210
#endif // DEBUG_ENABLED
1211
if (p_no_inheritance) {
1212
break;
1213
}
1214
1215
type = type->inherits_ptr;
1216
}
1217
}
1218
1219
int64_t ClassDB::get_integer_constant(const StringName &p_class, const StringName &p_name, bool *p_success) {
1220
Locker::Lock lock(Locker::STATE_READ);
1221
1222
ClassInfo *type = classes.getptr(p_class);
1223
1224
while (type) {
1225
int64_t *constant = type->constant_map.getptr(p_name);
1226
if (constant) {
1227
if (p_success) {
1228
*p_success = true;
1229
}
1230
return *constant;
1231
}
1232
1233
type = type->inherits_ptr;
1234
}
1235
1236
if (p_success) {
1237
*p_success = false;
1238
}
1239
1240
return 0;
1241
}
1242
1243
bool ClassDB::has_integer_constant(const StringName &p_class, const StringName &p_name, bool p_no_inheritance) {
1244
Locker::Lock lock(Locker::STATE_READ);
1245
1246
ClassInfo *type = classes.getptr(p_class);
1247
1248
while (type) {
1249
if (type->constant_map.has(p_name)) {
1250
return true;
1251
}
1252
if (p_no_inheritance) {
1253
return false;
1254
}
1255
1256
type = type->inherits_ptr;
1257
}
1258
1259
return false;
1260
}
1261
1262
StringName ClassDB::get_integer_constant_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance) {
1263
Locker::Lock lock(Locker::STATE_READ);
1264
1265
ClassInfo *type = classes.getptr(p_class);
1266
1267
while (type) {
1268
for (KeyValue<StringName, ClassInfo::EnumInfo> &E : type->enum_map) {
1269
List<StringName> &constants_list = E.value.constants;
1270
const List<StringName>::Element *found = constants_list.find(p_name);
1271
if (found) {
1272
return E.key;
1273
}
1274
}
1275
1276
if (p_no_inheritance) {
1277
break;
1278
}
1279
1280
type = type->inherits_ptr;
1281
}
1282
1283
return StringName();
1284
}
1285
1286
void ClassDB::get_enum_list(const StringName &p_class, List<StringName> *p_enums, bool p_no_inheritance) {
1287
Locker::Lock lock(Locker::STATE_READ);
1288
1289
ClassInfo *type = classes.getptr(p_class);
1290
1291
while (type) {
1292
for (KeyValue<StringName, ClassInfo::EnumInfo> &E : type->enum_map) {
1293
p_enums->push_back(E.key);
1294
}
1295
1296
if (p_no_inheritance) {
1297
break;
1298
}
1299
1300
type = type->inherits_ptr;
1301
}
1302
}
1303
1304
void ClassDB::get_enum_constants(const StringName &p_class, const StringName &p_enum, List<StringName> *p_constants, bool p_no_inheritance) {
1305
Locker::Lock lock(Locker::STATE_READ);
1306
1307
ClassInfo *type = classes.getptr(p_class);
1308
1309
while (type) {
1310
const ClassInfo::EnumInfo *constants = type->enum_map.getptr(p_enum);
1311
1312
if (constants) {
1313
for (const List<StringName>::Element *E = constants->constants.front(); E; E = E->next()) {
1314
p_constants->push_back(E->get());
1315
}
1316
}
1317
1318
if (p_no_inheritance) {
1319
break;
1320
}
1321
1322
type = type->inherits_ptr;
1323
}
1324
}
1325
1326
void ClassDB::set_method_error_return_values(const StringName &p_class, const StringName &p_method, const Vector<Error> &p_values) {
1327
#ifdef DEBUG_ENABLED
1328
Locker::Lock lock(Locker::STATE_WRITE);
1329
ClassInfo *type = classes.getptr(p_class);
1330
1331
ERR_FAIL_NULL(type);
1332
1333
type->method_error_values[p_method] = p_values;
1334
#endif // DEBUG_ENABLED
1335
}
1336
1337
Vector<Error> ClassDB::get_method_error_return_values(const StringName &p_class, const StringName &p_method) {
1338
#ifdef DEBUG_ENABLED
1339
Locker::Lock lock(Locker::STATE_READ);
1340
ClassInfo *type = classes.getptr(p_class);
1341
1342
ERR_FAIL_NULL_V(type, Vector<Error>());
1343
1344
if (!type->method_error_values.has(p_method)) {
1345
return Vector<Error>();
1346
}
1347
return type->method_error_values[p_method];
1348
#else
1349
return Vector<Error>();
1350
#endif // DEBUG_ENABLED
1351
}
1352
1353
bool ClassDB::has_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance) {
1354
Locker::Lock lock(Locker::STATE_READ);
1355
1356
ClassInfo *type = classes.getptr(p_class);
1357
1358
while (type) {
1359
if (type->enum_map.has(p_name)) {
1360
return true;
1361
}
1362
if (p_no_inheritance) {
1363
return false;
1364
}
1365
1366
type = type->inherits_ptr;
1367
}
1368
1369
return false;
1370
}
1371
1372
bool ClassDB::is_enum_bitfield(const StringName &p_class, const StringName &p_name, bool p_no_inheritance) {
1373
Locker::Lock lock(Locker::STATE_READ);
1374
1375
ClassInfo *type = classes.getptr(p_class);
1376
1377
while (type) {
1378
if (type->enum_map.has(p_name) && type->enum_map[p_name].is_bitfield) {
1379
return true;
1380
}
1381
if (p_no_inheritance) {
1382
return false;
1383
}
1384
1385
type = type->inherits_ptr;
1386
}
1387
1388
return false;
1389
}
1390
1391
void ClassDB::add_signal(const StringName &p_class, const MethodInfo &p_signal) {
1392
Locker::Lock lock(Locker::STATE_WRITE);
1393
1394
ClassInfo *type = classes.getptr(p_class);
1395
ERR_FAIL_NULL(type);
1396
1397
StringName sname = p_signal.name;
1398
1399
#ifdef DEBUG_ENABLED
1400
ClassInfo *check = type;
1401
while (check) {
1402
ERR_FAIL_COND_MSG(check->signal_map.has(sname), vformat("Class '%s' already has signal '%s'.", String(p_class), String(sname)));
1403
check = check->inherits_ptr;
1404
}
1405
#endif // DEBUG_ENABLED
1406
1407
type->signal_map[sname] = p_signal;
1408
}
1409
1410
void ClassDB::get_signal_list(const StringName &p_class, List<MethodInfo> *p_signals, bool p_no_inheritance) {
1411
Locker::Lock lock(Locker::STATE_READ);
1412
1413
ClassInfo *type = classes.getptr(p_class);
1414
ERR_FAIL_NULL(type);
1415
1416
ClassInfo *check = type;
1417
1418
while (check) {
1419
for (KeyValue<StringName, MethodInfo> &E : check->signal_map) {
1420
p_signals->push_back(E.value);
1421
}
1422
1423
if (p_no_inheritance) {
1424
return;
1425
}
1426
1427
check = check->inherits_ptr;
1428
}
1429
}
1430
1431
bool ClassDB::has_signal(const StringName &p_class, const StringName &p_signal, bool p_no_inheritance) {
1432
Locker::Lock lock(Locker::STATE_READ);
1433
ClassInfo *type = classes.getptr(p_class);
1434
ClassInfo *check = type;
1435
while (check) {
1436
if (check->signal_map.has(p_signal)) {
1437
return true;
1438
}
1439
if (p_no_inheritance) {
1440
return false;
1441
}
1442
check = check->inherits_ptr;
1443
}
1444
1445
return false;
1446
}
1447
1448
bool ClassDB::get_signal(const StringName &p_class, const StringName &p_signal, MethodInfo *r_signal) {
1449
Locker::Lock lock(Locker::STATE_READ);
1450
ClassInfo *type = classes.getptr(p_class);
1451
ClassInfo *check = type;
1452
while (check) {
1453
if (check->signal_map.has(p_signal)) {
1454
if (r_signal) {
1455
*r_signal = check->signal_map[p_signal];
1456
}
1457
return true;
1458
}
1459
check = check->inherits_ptr;
1460
}
1461
1462
return false;
1463
}
1464
1465
void ClassDB::add_property_group(const StringName &p_class, const String &p_name, const String &p_prefix, int p_indent_depth) {
1466
Locker::Lock lock(Locker::STATE_WRITE);
1467
ClassInfo *type = classes.getptr(p_class);
1468
ERR_FAIL_NULL(type);
1469
1470
String prefix = p_prefix;
1471
if (p_indent_depth > 0) {
1472
prefix = vformat("%s,%d", p_prefix, p_indent_depth);
1473
}
1474
1475
type->property_list.push_back(PropertyInfo(Variant::NIL, p_name, PROPERTY_HINT_NONE, prefix, PROPERTY_USAGE_GROUP));
1476
}
1477
1478
void ClassDB::add_property_subgroup(const StringName &p_class, const String &p_name, const String &p_prefix, int p_indent_depth) {
1479
Locker::Lock lock(Locker::STATE_WRITE);
1480
ClassInfo *type = classes.getptr(p_class);
1481
ERR_FAIL_NULL(type);
1482
1483
String prefix = p_prefix;
1484
if (p_indent_depth > 0) {
1485
prefix = vformat("%s,%d", p_prefix, p_indent_depth);
1486
}
1487
1488
type->property_list.push_back(PropertyInfo(Variant::NIL, p_name, PROPERTY_HINT_NONE, prefix, PROPERTY_USAGE_SUBGROUP));
1489
}
1490
1491
void ClassDB::add_property_array_count(const StringName &p_class, const String &p_label, const StringName &p_count_property, const StringName &p_count_setter, const StringName &p_count_getter, const String &p_array_element_prefix, uint32_t p_count_usage) {
1492
add_property(p_class, PropertyInfo(Variant::INT, p_count_property, PROPERTY_HINT_NONE, "", p_count_usage | PROPERTY_USAGE_ARRAY, vformat("%s,%s", p_label, p_array_element_prefix)), p_count_setter, p_count_getter);
1493
}
1494
1495
void ClassDB::add_property_array(const StringName &p_class, const StringName &p_path, const String &p_array_element_prefix) {
1496
Locker::Lock lock(Locker::STATE_WRITE);
1497
ClassInfo *type = classes.getptr(p_class);
1498
ERR_FAIL_NULL(type);
1499
1500
type->property_list.push_back(PropertyInfo(Variant::NIL, p_path, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ARRAY, p_array_element_prefix));
1501
}
1502
1503
// NOTE: For implementation simplicity reasons, this method doesn't allow setters to have optional arguments at the end.
1504
void ClassDB::add_property(const StringName &p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index) {
1505
Locker::Lock lock(Locker::STATE_WRITE);
1506
1507
ClassInfo *type = classes.getptr(p_class);
1508
1509
ERR_FAIL_NULL(type);
1510
1511
MethodBind *mb_set = nullptr;
1512
if (p_setter) {
1513
mb_set = get_method(p_class, p_setter);
1514
#ifdef DEBUG_ENABLED
1515
1516
ERR_FAIL_NULL_MSG(mb_set, vformat("Invalid setter '%s::%s' for property '%s'.", p_class, p_setter, p_pinfo.name));
1517
1518
int exp_args = 1 + (p_index >= 0 ? 1 : 0);
1519
ERR_FAIL_COND_MSG(mb_set->get_argument_count() != exp_args, vformat("Invalid function for setter '%s::%s' for property '%s'.", p_class, p_setter, p_pinfo.name));
1520
#endif // DEBUG_ENABLED
1521
}
1522
1523
MethodBind *mb_get = nullptr;
1524
if (p_getter) {
1525
mb_get = get_method(p_class, p_getter);
1526
#ifdef DEBUG_ENABLED
1527
1528
ERR_FAIL_NULL_MSG(mb_get, vformat("Invalid getter '%s::%s' for property '%s'.", p_class, p_getter, p_pinfo.name));
1529
1530
int exp_args = 0 + (p_index >= 0 ? 1 : 0);
1531
ERR_FAIL_COND_MSG(mb_get->get_argument_count() != exp_args, vformat("Invalid function for getter '%s::%s' for property '%s'.", p_class, p_getter, p_pinfo.name));
1532
#endif // DEBUG_ENABLED
1533
}
1534
1535
#ifdef DEBUG_ENABLED
1536
ERR_FAIL_COND_MSG(type->property_setget.has(p_pinfo.name), vformat("Object '%s' already has property '%s'.", p_class, p_pinfo.name));
1537
#endif // DEBUG_ENABLED
1538
1539
type->property_list.push_back(p_pinfo);
1540
type->property_map[p_pinfo.name] = p_pinfo;
1541
#ifdef DEBUG_ENABLED
1542
if (mb_get) {
1543
type->methods_in_properties.insert(p_getter);
1544
}
1545
if (mb_set) {
1546
type->methods_in_properties.insert(p_setter);
1547
}
1548
#endif // DEBUG_ENABLED
1549
PropertySetGet psg;
1550
psg.setter = p_setter;
1551
psg.getter = p_getter;
1552
psg._setptr = mb_set;
1553
psg._getptr = mb_get;
1554
psg.index = p_index;
1555
psg.type = p_pinfo.type;
1556
1557
type->property_setget[p_pinfo.name] = psg;
1558
}
1559
1560
void ClassDB::set_property_default_value(const StringName &p_class, const StringName &p_name, const Variant &p_default) {
1561
if (!default_values.has(p_class)) {
1562
default_values[p_class] = HashMap<StringName, Variant>();
1563
}
1564
default_values[p_class][p_name] = p_default;
1565
}
1566
1567
void ClassDB::add_linked_property(const StringName &p_class, const String &p_property, const String &p_linked_property) {
1568
#ifdef TOOLS_ENABLED
1569
Locker::Lock lock(Locker::STATE_WRITE);
1570
ClassInfo *type = classes.getptr(p_class);
1571
ERR_FAIL_NULL(type);
1572
1573
ERR_FAIL_COND(!type->property_map.has(p_property));
1574
ERR_FAIL_COND(!type->property_map.has(p_linked_property));
1575
1576
if (!type->linked_properties.has(p_property)) {
1577
type->linked_properties.insert(p_property, List<StringName>());
1578
}
1579
type->linked_properties[p_property].push_back(p_linked_property);
1580
1581
#endif
1582
}
1583
1584
void ClassDB::get_property_list(const StringName &p_class, List<PropertyInfo> *p_list, bool p_no_inheritance, const Object *p_validator) {
1585
Locker::Lock lock(Locker::STATE_READ);
1586
1587
ClassInfo *type = classes.getptr(p_class);
1588
ClassInfo *check = type;
1589
while (check) {
1590
for (const PropertyInfo &pi : check->property_list) {
1591
p_list->push_back(pi);
1592
if (p_validator) {
1593
p_validator->validate_property(p_list->back()->get());
1594
}
1595
}
1596
1597
if (p_no_inheritance) {
1598
return;
1599
}
1600
check = check->inherits_ptr;
1601
}
1602
}
1603
1604
void ClassDB::get_linked_properties_info(const StringName &p_class, const StringName &p_property, List<StringName> *r_properties, bool p_no_inheritance) {
1605
#ifdef TOOLS_ENABLED
1606
ClassInfo *check = classes.getptr(p_class);
1607
while (check) {
1608
if (!check->linked_properties.has(p_property)) {
1609
return;
1610
}
1611
for (const StringName &E : check->linked_properties[p_property]) {
1612
r_properties->push_back(E);
1613
}
1614
1615
if (p_no_inheritance) {
1616
break;
1617
}
1618
check = check->inherits_ptr;
1619
}
1620
#endif
1621
}
1622
1623
bool ClassDB::get_property_info(const StringName &p_class, const StringName &p_property, PropertyInfo *r_info, bool p_no_inheritance, const Object *p_validator) {
1624
Locker::Lock lock(Locker::STATE_READ);
1625
1626
ClassInfo *check = classes.getptr(p_class);
1627
while (check) {
1628
if (check->property_map.has(p_property)) {
1629
PropertyInfo pinfo = check->property_map[p_property];
1630
if (p_validator) {
1631
p_validator->validate_property(pinfo);
1632
}
1633
if (r_info) {
1634
*r_info = pinfo;
1635
}
1636
return true;
1637
}
1638
if (p_no_inheritance) {
1639
break;
1640
}
1641
check = check->inherits_ptr;
1642
}
1643
1644
return false;
1645
}
1646
1647
bool ClassDB::set_property(Object *p_object, const StringName &p_property, const Variant &p_value, bool *r_valid) {
1648
ERR_FAIL_NULL_V(p_object, false);
1649
1650
ClassInfo *type = classes.getptr(p_object->get_class_name());
1651
ClassInfo *check = type;
1652
while (check) {
1653
const PropertySetGet *psg = check->property_setget.getptr(p_property);
1654
if (psg) {
1655
if (!psg->setter) {
1656
if (r_valid) {
1657
*r_valid = false;
1658
}
1659
return true; //return true but do nothing
1660
}
1661
1662
Callable::CallError ce;
1663
1664
if (psg->index >= 0) {
1665
Variant index = psg->index;
1666
const Variant *arg[2] = { &index, &p_value };
1667
//p_object->call(psg->setter,arg,2,ce);
1668
if (psg->_setptr) {
1669
psg->_setptr->call(p_object, arg, 2, ce);
1670
} else {
1671
p_object->callp(psg->setter, arg, 2, ce);
1672
}
1673
1674
} else {
1675
const Variant *arg[1] = { &p_value };
1676
if (psg->_setptr) {
1677
psg->_setptr->call(p_object, arg, 1, ce);
1678
} else {
1679
p_object->callp(psg->setter, arg, 1, ce);
1680
}
1681
}
1682
1683
if (r_valid) {
1684
*r_valid = ce.error == Callable::CallError::CALL_OK;
1685
}
1686
1687
return true;
1688
}
1689
1690
check = check->inherits_ptr;
1691
}
1692
1693
return false;
1694
}
1695
1696
bool ClassDB::get_property(Object *p_object, const StringName &p_property, Variant &r_value) {
1697
ERR_FAIL_NULL_V(p_object, false);
1698
1699
ClassInfo *type = classes.getptr(p_object->get_class_name());
1700
ClassInfo *check = type;
1701
while (check) {
1702
const PropertySetGet *psg = check->property_setget.getptr(p_property);
1703
if (psg) {
1704
if (!psg->getter) {
1705
return true; //return true but do nothing
1706
}
1707
1708
if (psg->index >= 0) {
1709
Variant index = psg->index;
1710
const Variant *arg[1] = { &index };
1711
Callable::CallError ce;
1712
const Variant value = p_object->callp(psg->getter, arg, 1, ce);
1713
r_value = (ce.error == Callable::CallError::CALL_OK) ? value : Variant();
1714
1715
} else {
1716
Callable::CallError ce;
1717
if (psg->_getptr) {
1718
r_value = psg->_getptr->call(p_object, nullptr, 0, ce);
1719
} else {
1720
const Variant value = p_object->callp(psg->getter, nullptr, 0, ce);
1721
r_value = (ce.error == Callable::CallError::CALL_OK) ? value : Variant();
1722
}
1723
}
1724
return true;
1725
}
1726
1727
const int64_t *c = check->constant_map.getptr(p_property); //constants count
1728
if (c) {
1729
r_value = *c;
1730
return true;
1731
}
1732
1733
if (check->method_map.has(p_property)) { //methods count
1734
r_value = Callable(p_object, p_property);
1735
return true;
1736
}
1737
1738
if (check->signal_map.has(p_property)) { //signals count
1739
r_value = Signal(p_object, p_property);
1740
return true;
1741
}
1742
1743
check = check->inherits_ptr;
1744
}
1745
1746
// The "free()" method is special, so we assume it exists and return a Callable.
1747
if (p_property == CoreStringName(free_)) {
1748
r_value = Callable(p_object, p_property);
1749
return true;
1750
}
1751
1752
return false;
1753
}
1754
1755
int ClassDB::get_property_index(const StringName &p_class, const StringName &p_property, bool *r_is_valid) {
1756
ClassInfo *type = classes.getptr(p_class);
1757
ClassInfo *check = type;
1758
while (check) {
1759
const PropertySetGet *psg = check->property_setget.getptr(p_property);
1760
if (psg) {
1761
if (r_is_valid) {
1762
*r_is_valid = true;
1763
}
1764
1765
return psg->index;
1766
}
1767
1768
check = check->inherits_ptr;
1769
}
1770
if (r_is_valid) {
1771
*r_is_valid = false;
1772
}
1773
1774
return -1;
1775
}
1776
1777
Variant::Type ClassDB::get_property_type(const StringName &p_class, const StringName &p_property, bool *r_is_valid) {
1778
ClassInfo *type = classes.getptr(p_class);
1779
ClassInfo *check = type;
1780
while (check) {
1781
const PropertySetGet *psg = check->property_setget.getptr(p_property);
1782
if (psg) {
1783
if (r_is_valid) {
1784
*r_is_valid = true;
1785
}
1786
1787
return psg->type;
1788
}
1789
1790
check = check->inherits_ptr;
1791
}
1792
if (r_is_valid) {
1793
*r_is_valid = false;
1794
}
1795
1796
return Variant::NIL;
1797
}
1798
1799
StringName ClassDB::get_property_setter(const StringName &p_class, const StringName &p_property) {
1800
ClassInfo *type = classes.getptr(p_class);
1801
ClassInfo *check = type;
1802
while (check) {
1803
const PropertySetGet *psg = check->property_setget.getptr(p_property);
1804
if (psg) {
1805
return psg->setter;
1806
}
1807
1808
check = check->inherits_ptr;
1809
}
1810
1811
return StringName();
1812
}
1813
1814
StringName ClassDB::get_property_getter(const StringName &p_class, const StringName &p_property) {
1815
ClassInfo *type = classes.getptr(p_class);
1816
ClassInfo *check = type;
1817
while (check) {
1818
const PropertySetGet *psg = check->property_setget.getptr(p_property);
1819
if (psg) {
1820
return psg->getter;
1821
}
1822
1823
check = check->inherits_ptr;
1824
}
1825
1826
return StringName();
1827
}
1828
1829
bool ClassDB::has_property(const StringName &p_class, const StringName &p_property, bool p_no_inheritance) {
1830
ClassInfo *type = classes.getptr(p_class);
1831
ClassInfo *check = type;
1832
while (check) {
1833
if (check->property_setget.has(p_property)) {
1834
return true;
1835
}
1836
1837
if (p_no_inheritance) {
1838
break;
1839
}
1840
check = check->inherits_ptr;
1841
}
1842
1843
return false;
1844
}
1845
1846
void ClassDB::set_method_flags(const StringName &p_class, const StringName &p_method, int p_flags) {
1847
Locker::Lock lock(Locker::STATE_WRITE);
1848
ClassInfo *type = classes.getptr(p_class);
1849
ClassInfo *check = type;
1850
ERR_FAIL_NULL(check);
1851
ERR_FAIL_COND(!check->method_map.has(p_method));
1852
check->method_map[p_method]->set_hint_flags(p_flags);
1853
}
1854
1855
bool ClassDB::has_method(const StringName &p_class, const StringName &p_method, bool p_no_inheritance) {
1856
ClassInfo *type = classes.getptr(p_class);
1857
ClassInfo *check = type;
1858
while (check) {
1859
if (check->method_map.has(p_method)) {
1860
return true;
1861
}
1862
if (p_no_inheritance) {
1863
return false;
1864
}
1865
check = check->inherits_ptr;
1866
}
1867
1868
return false;
1869
}
1870
1871
int ClassDB::get_method_argument_count(const StringName &p_class, const StringName &p_method, bool *r_is_valid, bool p_no_inheritance) {
1872
Locker::Lock lock(Locker::STATE_READ);
1873
1874
ClassInfo *type = classes.getptr(p_class);
1875
1876
while (type) {
1877
MethodBind **method = type->method_map.getptr(p_method);
1878
if (method && *method) {
1879
if (r_is_valid) {
1880
*r_is_valid = true;
1881
}
1882
return (*method)->get_argument_count();
1883
}
1884
if (p_no_inheritance) {
1885
break;
1886
}
1887
type = type->inherits_ptr;
1888
}
1889
1890
if (r_is_valid) {
1891
*r_is_valid = false;
1892
}
1893
return 0;
1894
}
1895
1896
void ClassDB::bind_method_custom(const StringName &p_class, MethodBind *p_method) {
1897
_bind_method_custom(p_class, p_method, false);
1898
}
1899
void ClassDB::bind_compatibility_method_custom(const StringName &p_class, MethodBind *p_method) {
1900
_bind_method_custom(p_class, p_method, true);
1901
}
1902
1903
void ClassDB::_bind_compatibility(ClassInfo *type, MethodBind *p_method) {
1904
if (!type->method_map_compatibility.has(p_method->get_name())) {
1905
type->method_map_compatibility.insert(p_method->get_name(), LocalVector<MethodBind *>());
1906
}
1907
type->method_map_compatibility[p_method->get_name()].push_back(p_method);
1908
}
1909
1910
void ClassDB::_bind_method_custom(const StringName &p_class, MethodBind *p_method, bool p_compatibility) {
1911
Locker::Lock lock(Locker::STATE_WRITE);
1912
1913
StringName method_name = p_method->get_name();
1914
1915
ClassInfo *type = classes.getptr(p_class);
1916
if (!type) {
1917
memdelete(p_method);
1918
ERR_FAIL_MSG(vformat("Couldn't bind custom method '%s' for instance '%s'.", method_name, p_class));
1919
}
1920
1921
if (p_compatibility) {
1922
_bind_compatibility(type, p_method);
1923
return;
1924
}
1925
1926
if (type->method_map.has(method_name)) {
1927
// overloading not supported
1928
memdelete(p_method);
1929
ERR_FAIL_MSG(vformat("Method already bound '%s::%s'.", p_class, method_name));
1930
}
1931
1932
#ifdef DEBUG_ENABLED
1933
type->method_order.push_back(method_name);
1934
#endif // DEBUG_ENABLED
1935
1936
type->method_map[method_name] = p_method;
1937
}
1938
1939
MethodBind *ClassDB::_bind_vararg_method(MethodBind *p_bind, const StringName &p_name, const Vector<Variant> &p_default_args, bool p_compatibility) {
1940
MethodBind *bind = p_bind;
1941
bind->set_name(p_name);
1942
bind->set_default_arguments(p_default_args);
1943
1944
String instance_type = bind->get_instance_class();
1945
1946
ClassInfo *type = classes.getptr(instance_type);
1947
if (!type) {
1948
memdelete(bind);
1949
ERR_FAIL_NULL_V(type, nullptr);
1950
}
1951
1952
if (p_compatibility) {
1953
_bind_compatibility(type, bind);
1954
return bind;
1955
}
1956
1957
if (type->method_map.has(p_name)) {
1958
memdelete(bind);
1959
// Overloading not supported
1960
ERR_FAIL_V_MSG(nullptr, vformat("Method already bound: '%s::%s'.", instance_type, p_name));
1961
}
1962
type->method_map[p_name] = bind;
1963
#ifdef DEBUG_ENABLED
1964
// FIXME: <reduz> set_return_type is no longer in MethodBind, so I guess it should be moved to vararg method bind
1965
//bind->set_return_type("Variant");
1966
type->method_order.push_back(p_name);
1967
#endif // DEBUG_ENABLED
1968
1969
return bind;
1970
}
1971
1972
#ifdef DEBUG_ENABLED
1973
MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, bool p_compatibility, const MethodDefinition &method_name, const Variant **p_defs, int p_defcount) {
1974
StringName mdname = method_name.name;
1975
#else
1976
MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, bool p_compatibility, const char *method_name, const Variant **p_defs, int p_defcount) {
1977
StringName mdname = StringName(method_name);
1978
#endif // DEBUG_ENABLED
1979
1980
Locker::Lock lock(Locker::STATE_WRITE);
1981
ERR_FAIL_NULL_V(p_bind, nullptr);
1982
p_bind->set_name(mdname);
1983
1984
String instance_type = p_bind->get_instance_class();
1985
1986
#ifdef DEBUG_ENABLED
1987
1988
ERR_FAIL_COND_V_MSG(!p_compatibility && has_method(instance_type, mdname), nullptr, vformat("Class '%s' already has a method '%s'.", String(instance_type), String(mdname)));
1989
#endif // DEBUG_ENABLED
1990
1991
ClassInfo *type = classes.getptr(instance_type);
1992
if (!type) {
1993
memdelete(p_bind);
1994
ERR_FAIL_V_MSG(nullptr, vformat("Couldn't bind method '%s' for instance '%s'.", mdname, instance_type));
1995
}
1996
1997
if (!p_compatibility && type->method_map.has(mdname)) {
1998
memdelete(p_bind);
1999
// overloading not supported
2000
ERR_FAIL_V_MSG(nullptr, vformat("Method already bound '%s::%s'.", instance_type, mdname));
2001
}
2002
2003
#ifdef DEBUG_ENABLED
2004
2005
if (method_name.args.size() > p_bind->get_argument_count()) {
2006
memdelete(p_bind);
2007
ERR_FAIL_V_MSG(nullptr, vformat("Method definition provides more arguments than the method actually has '%s::%s'.", instance_type, mdname));
2008
}
2009
2010
if (p_defcount > p_bind->get_argument_count()) {
2011
memdelete(p_bind);
2012
ERR_FAIL_V_MSG(nullptr, vformat("Method definition for '%s::%s' provides more default arguments than the method has arguments.", instance_type, mdname));
2013
}
2014
2015
p_bind->set_argument_names(method_name.args);
2016
2017
if (!p_compatibility) {
2018
type->method_order.push_back(mdname);
2019
}
2020
#endif // DEBUG_ENABLED
2021
2022
if (p_compatibility) {
2023
_bind_compatibility(type, p_bind);
2024
} else {
2025
type->method_map[mdname] = p_bind;
2026
}
2027
2028
Vector<Variant> defvals;
2029
2030
defvals.resize(p_defcount);
2031
for (int i = 0; i < p_defcount; i++) {
2032
defvals.write[i] = *p_defs[i];
2033
}
2034
2035
p_bind->set_default_arguments(defvals);
2036
p_bind->set_hint_flags(p_flags);
2037
return p_bind;
2038
}
2039
2040
void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_method, bool p_virtual, const Vector<String> &p_arg_names, bool p_object_core) {
2041
ERR_FAIL_COND_MSG(!classes.has(p_class), vformat("Request for nonexistent class '%s'.", p_class));
2042
2043
Locker::Lock lock(Locker::STATE_WRITE);
2044
2045
#ifdef DEBUG_ENABLED
2046
MethodInfo mi = p_method;
2047
if (p_virtual) {
2048
mi.flags |= METHOD_FLAG_VIRTUAL;
2049
}
2050
if (p_object_core) {
2051
mi.flags |= METHOD_FLAG_OBJECT_CORE;
2052
}
2053
2054
if (!p_object_core) {
2055
if (p_arg_names.size() != mi.arguments.size()) {
2056
WARN_PRINT(vformat("Mismatch argument name count for virtual method: '%s::%s'.", String(p_class), p_method.name));
2057
} else {
2058
for (int64_t i = 0; i < p_arg_names.size(); ++i) {
2059
mi.arguments.write[i].name = p_arg_names[i];
2060
}
2061
}
2062
}
2063
2064
if (classes[p_class].virtual_methods_map.has(p_method.name)) {
2065
// overloading not supported
2066
ERR_FAIL_MSG(vformat("Virtual method already bound '%s::%s'.", String(p_class), p_method.name));
2067
}
2068
classes[p_class].virtual_methods.push_back(mi);
2069
classes[p_class].virtual_methods_map[p_method.name] = mi;
2070
2071
#endif // DEBUG_ENABLED
2072
}
2073
2074
void ClassDB::add_virtual_compatibility_method(const StringName &p_class, const MethodInfo &p_method, bool p_virtual, const Vector<String> &p_arg_names, bool p_object_core) {
2075
ERR_FAIL_COND_MSG(!classes.has(p_class), vformat("Request for nonexistent class '%s'.", p_class));
2076
2077
Locker::Lock lock(Locker::STATE_WRITE);
2078
2079
HashMap<StringName, Vector<uint32_t>> &virtual_methods_compat = classes[p_class].virtual_methods_compat;
2080
2081
Vector<uint32_t> *compat_hashes = virtual_methods_compat.getptr(p_method.name);
2082
if (!compat_hashes) {
2083
virtual_methods_compat[p_method.name] = Vector<uint32_t>();
2084
compat_hashes = &virtual_methods_compat[p_method.name];
2085
}
2086
2087
compat_hashes->push_back(p_method.get_compatibility_hash());
2088
}
2089
2090
void ClassDB::get_virtual_methods(const StringName &p_class, List<MethodInfo> *p_methods, bool p_no_inheritance) {
2091
ERR_FAIL_COND_MSG(!classes.has(p_class), vformat("Request for nonexistent class '%s'.", p_class));
2092
2093
#ifdef DEBUG_ENABLED
2094
2095
ClassInfo *type = classes.getptr(p_class);
2096
ClassInfo *check = type;
2097
while (check) {
2098
for (const MethodInfo &E : check->virtual_methods) {
2099
p_methods->push_back(E);
2100
}
2101
2102
if (p_no_inheritance) {
2103
return;
2104
}
2105
check = check->inherits_ptr;
2106
}
2107
2108
#endif // DEBUG_ENABLED
2109
}
2110
2111
Vector<uint32_t> ClassDB::get_virtual_method_compatibility_hashes(const StringName &p_class, const StringName &p_name) {
2112
Locker::Lock lock(Locker::STATE_READ);
2113
2114
ClassInfo *type = classes.getptr(p_class);
2115
2116
while (type) {
2117
if (type->virtual_methods_compat.has(p_name)) {
2118
Vector<uint32_t> *compat_hashes = type->virtual_methods_compat.getptr(p_name);
2119
if (compat_hashes) {
2120
return *compat_hashes;
2121
}
2122
break;
2123
}
2124
type = type->inherits_ptr;
2125
}
2126
2127
return Vector<uint32_t>();
2128
}
2129
2130
void ClassDB::add_extension_class_virtual_method(const StringName &p_class, const GDExtensionClassVirtualMethodInfo *p_method_info) {
2131
ERR_FAIL_COND_MSG(!classes.has(p_class), vformat("Request for nonexistent class '%s'.", p_class));
2132
2133
#ifdef DEBUG_ENABLED
2134
PackedStringArray arg_names;
2135
2136
MethodInfo mi;
2137
mi.name = *reinterpret_cast<StringName *>(p_method_info->name);
2138
mi.return_val = PropertyInfo(p_method_info->return_value);
2139
mi.return_val_metadata = p_method_info->return_value_metadata;
2140
mi.flags = p_method_info->method_flags;
2141
for (int i = 0; i < (int)p_method_info->argument_count; i++) {
2142
PropertyInfo arg(p_method_info->arguments[i]);
2143
mi.arguments.push_back(arg);
2144
mi.arguments_metadata.push_back(p_method_info->arguments_metadata[i]);
2145
arg_names.push_back(arg.name);
2146
}
2147
2148
add_virtual_method(p_class, mi, true, arg_names);
2149
#endif // DEBUG_ENABLED
2150
}
2151
2152
void ClassDB::set_class_enabled(const StringName &p_class, bool p_enable) {
2153
Locker::Lock lock(Locker::STATE_WRITE);
2154
2155
ERR_FAIL_COND_MSG(!classes.has(p_class), vformat("Request for nonexistent class '%s'.", p_class));
2156
classes[p_class].disabled = !p_enable;
2157
}
2158
2159
bool ClassDB::is_class_enabled(const StringName &p_class) {
2160
Locker::Lock lock(Locker::STATE_READ);
2161
2162
ClassInfo *ti = classes.getptr(p_class);
2163
if (!ti || !ti->creation_func) {
2164
if (compat_classes.has(p_class)) {
2165
ti = classes.getptr(compat_classes[p_class]);
2166
}
2167
}
2168
2169
ERR_FAIL_NULL_V_MSG(ti, false, vformat("Cannot get class '%s'.", String(p_class)));
2170
return !ti->disabled;
2171
}
2172
2173
bool ClassDB::is_class_exposed(const StringName &p_class) {
2174
Locker::Lock lock(Locker::STATE_READ);
2175
2176
ClassInfo *ti = classes.getptr(p_class);
2177
ERR_FAIL_NULL_V_MSG(ti, false, vformat("Cannot get class '%s'.", String(p_class)));
2178
return ti->exposed;
2179
}
2180
2181
bool ClassDB::is_class_reloadable(const StringName &p_class) {
2182
Locker::Lock lock(Locker::STATE_READ);
2183
2184
ClassInfo *ti = classes.getptr(p_class);
2185
ERR_FAIL_NULL_V_MSG(ti, false, vformat("Cannot get class '%s'.", String(p_class)));
2186
return ti->reloadable;
2187
}
2188
2189
bool ClassDB::is_class_runtime(const StringName &p_class) {
2190
Locker::Lock lock(Locker::STATE_READ);
2191
2192
ClassInfo *ti = classes.getptr(p_class);
2193
ERR_FAIL_NULL_V_MSG(ti, false, vformat("Cannot get class '%s'.", String(p_class)));
2194
return ti->is_runtime;
2195
}
2196
2197
#ifdef TOOLS_ENABLED
2198
void ClassDB::add_class_dependency(const StringName &p_class, const StringName &p_dependency) {
2199
Locker::Lock lock(Locker::STATE_WRITE);
2200
2201
ERR_FAIL_COND_MSG(!classes.has(p_class), vformat("Request for nonexistent class '%s'.", p_class));
2202
if (classes[p_class].dependency_list.find(p_dependency)) {
2203
ERR_FAIL();
2204
}
2205
2206
classes[p_class].dependency_list.push_back(p_dependency);
2207
}
2208
2209
void ClassDB::get_class_dependencies(const StringName &p_class, List<StringName> *r_rependencies) {
2210
Locker::Lock lock(Locker::STATE_READ);
2211
2212
ClassInfo *ti = classes.getptr(p_class);
2213
ERR_FAIL_NULL_MSG(ti, vformat("Cannot get class '%s'.", String(p_class)));
2214
2215
for (const StringName &dep : ti->dependency_list) {
2216
r_rependencies->push_back(dep);
2217
}
2218
}
2219
#endif // TOOLS_ENABLED
2220
2221
void ClassDB::add_resource_base_extension(const StringName &p_extension, const StringName &p_class) {
2222
if (resource_base_extensions.has(p_extension)) {
2223
return;
2224
}
2225
2226
resource_base_extensions[p_extension] = p_class;
2227
}
2228
2229
void ClassDB::get_resource_base_extensions(List<String> *p_extensions) {
2230
for (const KeyValue<StringName, StringName> &E : resource_base_extensions) {
2231
p_extensions->push_back(E.key);
2232
}
2233
}
2234
2235
bool ClassDB::is_resource_extension(const StringName &p_extension) {
2236
return resource_base_extensions.has(p_extension);
2237
}
2238
2239
void ClassDB::get_extensions_for_type(const StringName &p_class, List<String> *p_extensions) {
2240
for (const KeyValue<StringName, StringName> &E : resource_base_extensions) {
2241
if (is_parent_class(p_class, E.value) || is_parent_class(E.value, p_class)) {
2242
p_extensions->push_back(E.key);
2243
}
2244
}
2245
}
2246
2247
HashMap<StringName, HashMap<StringName, Variant>> ClassDB::default_values;
2248
HashSet<StringName> ClassDB::default_values_cached;
2249
2250
Variant ClassDB::class_get_default_property_value(const StringName &p_class, const StringName &p_property, bool *r_valid) {
2251
if (!default_values_cached.has(p_class)) {
2252
if (!default_values.has(p_class)) {
2253
default_values[p_class] = HashMap<StringName, Variant>();
2254
}
2255
2256
Object *c = nullptr;
2257
bool cleanup_c = false;
2258
2259
if (Engine::get_singleton()->has_singleton(p_class)) {
2260
c = Engine::get_singleton()->get_singleton_object(p_class);
2261
cleanup_c = false;
2262
} else if (ClassDB::can_instantiate(p_class) && !ClassDB::is_virtual(p_class)) { // Keep this condition in sync with doc_tools.cpp get_documentation_default_value.
2263
c = ClassDB::instantiate_no_placeholders(p_class);
2264
cleanup_c = true;
2265
}
2266
2267
if (c) {
2268
List<PropertyInfo> plist;
2269
c->get_property_list(&plist);
2270
for (const PropertyInfo &E : plist) {
2271
if (E.usage & (PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR)) {
2272
if (!default_values[p_class].has(E.name)) {
2273
Variant v = c->get(E.name);
2274
default_values[p_class][E.name] = v;
2275
}
2276
}
2277
}
2278
2279
if (cleanup_c) {
2280
memdelete(c);
2281
}
2282
}
2283
2284
default_values_cached.insert(p_class);
2285
}
2286
2287
if (!default_values.has(p_class)) {
2288
if (r_valid != nullptr) {
2289
*r_valid = false;
2290
}
2291
return Variant();
2292
}
2293
2294
if (!default_values[p_class].has(p_property)) {
2295
if (r_valid != nullptr) {
2296
*r_valid = false;
2297
}
2298
return Variant();
2299
}
2300
2301
if (r_valid != nullptr) {
2302
*r_valid = true;
2303
}
2304
2305
Variant var = default_values[p_class][p_property];
2306
2307
#ifdef DEBUG_ENABLED
2308
// Some properties may have an instantiated Object as default value,
2309
// (like Path2D's `curve` used to have), but that's not a good practice.
2310
// Instead, those properties should use PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT
2311
// to be auto-instantiated when created in the editor with the following method:
2312
// EditorNode::get_editor_data().instantiate_object_properties(obj);
2313
if (var.get_type() == Variant::OBJECT) {
2314
Object *obj = var.get_validated_object();
2315
if (obj) {
2316
WARN_PRINT(vformat("Instantiated %s used as default value for %s's \"%s\" property.", obj->get_class(), p_class, p_property));
2317
}
2318
}
2319
#endif // DEBUG_ENABLED
2320
2321
return var;
2322
}
2323
2324
void ClassDB::register_extension_class(ObjectGDExtension *p_extension) {
2325
GLOBAL_LOCK_FUNCTION;
2326
2327
ERR_FAIL_COND_MSG(classes.has(p_extension->class_name), vformat("Class already registered: '%s'.", String(p_extension->class_name)));
2328
ERR_FAIL_COND_MSG(!classes.has(p_extension->parent_class_name), vformat("Parent class name for extension class not found: '%s'.", String(p_extension->parent_class_name)));
2329
2330
ClassInfo *parent = classes.getptr(p_extension->parent_class_name);
2331
2332
#ifdef TOOLS_ENABLED
2333
// @todo This is a limitation of the current implementation, but it should be possible to remove.
2334
ERR_FAIL_COND_MSG(p_extension->is_runtime && parent->gdextension && !parent->is_runtime, vformat("Extension runtime class '%s' cannot descend from '%s' which isn't also a runtime class.", String(p_extension->class_name), parent->name));
2335
#endif
2336
2337
ClassInfo c;
2338
c.api = p_extension->editor_class ? API_EDITOR_EXTENSION : API_EXTENSION;
2339
c.gdextension = p_extension;
2340
c.name = p_extension->class_name;
2341
c.is_virtual = p_extension->is_virtual;
2342
if (!p_extension->is_abstract) {
2343
// Find the closest ancestor which is either non-abstract or native (or both).
2344
ClassInfo *concrete_ancestor = parent;
2345
while (concrete_ancestor->creation_func == nullptr &&
2346
concrete_ancestor->inherits_ptr != nullptr &&
2347
concrete_ancestor->gdextension != nullptr) {
2348
concrete_ancestor = concrete_ancestor->inherits_ptr;
2349
}
2350
ERR_FAIL_NULL_MSG(concrete_ancestor->creation_func, vformat("Extension class '%s' cannot extend native abstract class '%s'.", String(p_extension->class_name), String(concrete_ancestor->name)));
2351
c.creation_func = concrete_ancestor->creation_func;
2352
}
2353
c.inherits = parent->name;
2354
c.class_ptr = parent->class_ptr;
2355
c.inherits_ptr = parent;
2356
c.exposed = p_extension->is_exposed;
2357
if (c.exposed) {
2358
// The parent classes should be exposed if it has an exposed child class.
2359
while (parent && !parent->exposed) {
2360
parent->exposed = true;
2361
parent = classes.getptr(parent->name);
2362
}
2363
}
2364
c.reloadable = p_extension->reloadable;
2365
#ifdef TOOLS_ENABLED
2366
c.is_runtime = p_extension->is_runtime;
2367
#endif
2368
2369
c.gdtype = p_extension->gdtype;
2370
2371
classes[p_extension->class_name] = c;
2372
}
2373
2374
void ClassDB::unregister_extension_class(const StringName &p_class, bool p_free_method_binds) {
2375
ClassInfo *c = classes.getptr(p_class);
2376
ERR_FAIL_NULL_MSG(c, vformat("Class '%s' does not exist.", String(p_class)));
2377
if (p_free_method_binds) {
2378
for (KeyValue<StringName, MethodBind *> &F : c->method_map) {
2379
memdelete(F.value);
2380
}
2381
}
2382
classes.erase(p_class);
2383
default_values_cached.erase(p_class);
2384
default_values.erase(p_class);
2385
#ifdef TOOLS_ENABLED
2386
placeholder_extensions.erase(p_class);
2387
#endif
2388
}
2389
2390
HashMap<StringName, ClassDB::NativeStruct> ClassDB::native_structs;
2391
void ClassDB::register_native_struct(const StringName &p_name, const String &p_code, uint64_t p_current_size) {
2392
NativeStruct ns;
2393
ns.ccode = p_code;
2394
ns.struct_size = p_current_size;
2395
native_structs[p_name] = ns;
2396
}
2397
2398
void ClassDB::get_native_struct_list(List<StringName> *r_names) {
2399
for (const KeyValue<StringName, NativeStruct> &E : native_structs) {
2400
r_names->push_back(E.key);
2401
}
2402
}
2403
2404
String ClassDB::get_native_struct_code(const StringName &p_name) {
2405
ERR_FAIL_COND_V(!native_structs.has(p_name), String());
2406
return native_structs[p_name].ccode;
2407
}
2408
2409
uint64_t ClassDB::get_native_struct_size(const StringName &p_name) {
2410
ERR_FAIL_COND_V(!native_structs.has(p_name), 0);
2411
return native_structs[p_name].struct_size;
2412
}
2413
2414
Object *ClassDB::_instantiate_allow_unexposed(const StringName &p_class) {
2415
return _instantiate_internal(p_class, false, true, false);
2416
}
2417
2418
void ClassDB::cleanup_defaults() {
2419
default_values.clear();
2420
default_values_cached.clear();
2421
}
2422
2423
LocalVector<GDType **> ClassDB::gdtype_autorelease_pool;
2424
void ClassDB::cleanup() {
2425
//OBJTYPE_LOCK; hah not here
2426
2427
for (KeyValue<StringName, ClassInfo> &E : classes) {
2428
ClassInfo &ti = E.value;
2429
2430
for (KeyValue<StringName, MethodBind *> &F : ti.method_map) {
2431
memdelete(F.value);
2432
}
2433
for (KeyValue<StringName, LocalVector<MethodBind *>> &F : ti.method_map_compatibility) {
2434
for (uint32_t i = 0; i < F.value.size(); i++) {
2435
memdelete(F.value[i]);
2436
}
2437
}
2438
}
2439
2440
classes.clear();
2441
resource_base_extensions.clear();
2442
compat_classes.clear();
2443
native_structs.clear();
2444
2445
for (GDType **type : gdtype_autorelease_pool) {
2446
if (!type) {
2447
WARN_PRINT("GDType in autorelease pool was cleaned up before being auto-released. Ignoring.");
2448
}
2449
memdelete(*type);
2450
*type = nullptr;
2451
}
2452
gdtype_autorelease_pool.clear();
2453
}
2454
2455
// Array to use in optional parameters on methods and the DEFVAL_ARRAY macro.
2456
Array ClassDB::default_array_arg = Array::create_read_only();
2457
2458
bool ClassDB::is_default_array_arg(const Array &p_array) {
2459
return p_array.is_same_instance(default_array_arg);
2460
}
2461
2462
//
2463
2464
ClassDB::Locker::Lock::Lock(Locker::State p_state) {
2465
DEV_ASSERT(p_state != STATE_UNLOCKED);
2466
if (p_state == STATE_READ) {
2467
if (Locker::thread_state == STATE_UNLOCKED) {
2468
state = STATE_READ;
2469
Locker::thread_state = STATE_READ;
2470
Locker::lock.read_lock();
2471
}
2472
} else if (p_state == STATE_WRITE) {
2473
if (Locker::thread_state == STATE_UNLOCKED) {
2474
state = STATE_WRITE;
2475
Locker::thread_state = STATE_WRITE;
2476
Locker::lock.write_lock();
2477
} else if (Locker::thread_state == STATE_READ) {
2478
CRASH_NOW_MSG("Lock can't be upgraded from read to write.");
2479
}
2480
}
2481
}
2482
2483
ClassDB::Locker::Lock::~Lock() {
2484
if (state == STATE_READ) {
2485
Locker::lock.read_unlock();
2486
Locker::thread_state = STATE_UNLOCKED;
2487
} else if (state == STATE_WRITE) {
2488
Locker::lock.write_unlock();
2489
Locker::thread_state = STATE_UNLOCKED;
2490
}
2491
}
2492
2493