Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/core/object/object.cpp
9903 views
1
/**************************************************************************/
2
/* object.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 "object.h"
32
33
#include "core/extension/gdextension_manager.h"
34
#include "core/io/resource.h"
35
#include "core/object/class_db.h"
36
#include "core/object/message_queue.h"
37
#include "core/object/script_language.h"
38
#include "core/os/os.h"
39
#include "core/string/print_string.h"
40
#include "core/string/translation_server.h"
41
#include "core/variant/typed_array.h"
42
43
#ifdef DEBUG_ENABLED
44
45
struct _ObjectDebugLock {
46
ObjectID obj_id;
47
48
_ObjectDebugLock(Object *p_obj) {
49
obj_id = p_obj->get_instance_id();
50
p_obj->_lock_index.ref();
51
}
52
~_ObjectDebugLock() {
53
Object *obj_ptr = ObjectDB::get_instance(obj_id);
54
if (likely(obj_ptr)) {
55
obj_ptr->_lock_index.unref();
56
}
57
}
58
};
59
60
#define OBJ_DEBUG_LOCK _ObjectDebugLock _debug_lock(this);
61
62
#else
63
64
#define OBJ_DEBUG_LOCK
65
66
#endif
67
68
struct _ObjectSignalLock {
69
Mutex *mutex;
70
_ObjectSignalLock(const Object *const p_obj) {
71
mutex = p_obj->signal_mutex;
72
if (mutex) {
73
mutex->lock();
74
}
75
}
76
~_ObjectSignalLock() {
77
if (mutex) {
78
mutex->unlock();
79
}
80
}
81
};
82
83
#define OBJ_SIGNAL_LOCK _ObjectSignalLock _signal_lock(this);
84
85
PropertyInfo::operator Dictionary() const {
86
Dictionary d;
87
d["name"] = name;
88
d["class_name"] = class_name;
89
d["type"] = type;
90
d["hint"] = hint;
91
d["hint_string"] = hint_string;
92
d["usage"] = usage;
93
return d;
94
}
95
96
PropertyInfo PropertyInfo::from_dict(const Dictionary &p_dict) {
97
PropertyInfo pi;
98
99
if (p_dict.has("type")) {
100
pi.type = Variant::Type(int(p_dict["type"]));
101
}
102
103
if (p_dict.has("name")) {
104
pi.name = p_dict["name"];
105
}
106
107
if (p_dict.has("class_name")) {
108
pi.class_name = p_dict["class_name"];
109
}
110
111
if (p_dict.has("hint")) {
112
pi.hint = PropertyHint(int(p_dict["hint"]));
113
}
114
115
if (p_dict.has("hint_string")) {
116
pi.hint_string = p_dict["hint_string"];
117
}
118
119
if (p_dict.has("usage")) {
120
pi.usage = p_dict["usage"];
121
}
122
123
return pi;
124
}
125
126
TypedArray<Dictionary> convert_property_list(const List<PropertyInfo> *p_list) {
127
TypedArray<Dictionary> va;
128
for (const List<PropertyInfo>::Element *E = p_list->front(); E; E = E->next()) {
129
va.push_back(Dictionary(E->get()));
130
}
131
132
return va;
133
}
134
135
TypedArray<Dictionary> convert_property_list(const Vector<PropertyInfo> &p_vector) {
136
TypedArray<Dictionary> va;
137
for (const PropertyInfo &E : p_vector) {
138
va.push_back(Dictionary(E));
139
}
140
141
return va;
142
}
143
144
MethodInfo::operator Dictionary() const {
145
Dictionary d;
146
d["name"] = name;
147
d["args"] = convert_property_list(arguments);
148
Array da;
149
for (int i = 0; i < default_arguments.size(); i++) {
150
da.push_back(default_arguments[i]);
151
}
152
d["default_args"] = da;
153
d["flags"] = flags;
154
d["id"] = id;
155
Dictionary r = return_val;
156
d["return"] = r;
157
return d;
158
}
159
160
MethodInfo MethodInfo::from_dict(const Dictionary &p_dict) {
161
MethodInfo mi;
162
163
if (p_dict.has("name")) {
164
mi.name = p_dict["name"];
165
}
166
Array args;
167
if (p_dict.has("args")) {
168
args = p_dict["args"];
169
}
170
171
for (const Variant &arg : args) {
172
Dictionary d = arg;
173
mi.arguments.push_back(PropertyInfo::from_dict(d));
174
}
175
Array defargs;
176
if (p_dict.has("default_args")) {
177
defargs = p_dict["default_args"];
178
}
179
for (const Variant &defarg : defargs) {
180
mi.default_arguments.push_back(defarg);
181
}
182
183
if (p_dict.has("return")) {
184
mi.return_val = PropertyInfo::from_dict(p_dict["return"]);
185
}
186
187
if (p_dict.has("flags")) {
188
mi.flags = p_dict["flags"];
189
}
190
191
return mi;
192
}
193
194
uint32_t MethodInfo::get_compatibility_hash() const {
195
bool has_return = (return_val.type != Variant::NIL) || (return_val.usage & PROPERTY_USAGE_NIL_IS_VARIANT);
196
197
uint32_t hash = hash_murmur3_one_32(has_return);
198
hash = hash_murmur3_one_32(arguments.size(), hash);
199
200
if (has_return) {
201
hash = hash_murmur3_one_32(return_val.type, hash);
202
if (return_val.class_name != StringName()) {
203
hash = hash_murmur3_one_32(return_val.class_name.hash(), hash);
204
}
205
}
206
207
for (const PropertyInfo &arg : arguments) {
208
hash = hash_murmur3_one_32(arg.type, hash);
209
if (arg.class_name != StringName()) {
210
hash = hash_murmur3_one_32(arg.class_name.hash(), hash);
211
}
212
}
213
214
hash = hash_murmur3_one_32(default_arguments.size(), hash);
215
for (const Variant &v : default_arguments) {
216
hash = hash_murmur3_one_32(v.hash(), hash);
217
}
218
219
hash = hash_murmur3_one_32(flags & METHOD_FLAG_CONST ? 1 : 0, hash);
220
hash = hash_murmur3_one_32(flags & METHOD_FLAG_VARARG ? 1 : 0, hash);
221
222
return hash_fmix32(hash);
223
}
224
225
Object::Connection::operator Variant() const {
226
Dictionary d;
227
d["signal"] = signal;
228
d["callable"] = callable;
229
d["flags"] = flags;
230
return d;
231
}
232
233
bool Object::Connection::operator<(const Connection &p_conn) const {
234
if (signal == p_conn.signal) {
235
return callable < p_conn.callable;
236
} else {
237
return signal < p_conn.signal;
238
}
239
}
240
241
Object::Connection::Connection(const Variant &p_variant) {
242
Dictionary d = p_variant;
243
if (d.has("signal")) {
244
signal = d["signal"];
245
}
246
if (d.has("callable")) {
247
callable = d["callable"];
248
}
249
if (d.has("flags")) {
250
flags = d["flags"];
251
}
252
}
253
254
bool Object::_predelete() {
255
_predelete_ok = 1;
256
notification(NOTIFICATION_PREDELETE, true);
257
if (_predelete_ok) {
258
_class_name_ptr = nullptr; // Must restore, so constructors/destructors have proper class name access at each stage.
259
notification(NOTIFICATION_PREDELETE_CLEANUP, true);
260
}
261
return _predelete_ok;
262
}
263
264
void Object::cancel_free() {
265
_predelete_ok = false;
266
}
267
268
void Object::_initialize() {
269
// Cache the class name in the object for quick reference.
270
_class_name_ptr = _get_class_namev();
271
_initialize_classv();
272
}
273
274
void Object::_postinitialize() {
275
if (_uses_signal_mutex()) {
276
signal_mutex = memnew(Mutex);
277
}
278
notification(NOTIFICATION_POSTINITIALIZE);
279
}
280
281
void Object::set(const StringName &p_name, const Variant &p_value, bool *r_valid) {
282
#ifdef TOOLS_ENABLED
283
284
_edited = true;
285
#endif
286
287
if (script_instance) {
288
if (script_instance->set(p_name, p_value)) {
289
if (r_valid) {
290
*r_valid = true;
291
}
292
return;
293
}
294
}
295
296
if (_extension && _extension->set) {
297
if (_extension->set(_extension_instance, (GDExtensionConstStringNamePtr)&p_name, (GDExtensionConstVariantPtr)&p_value)) {
298
if (r_valid) {
299
*r_valid = true;
300
}
301
return;
302
}
303
}
304
305
// Try built-in setter.
306
{
307
if (ClassDB::set_property(this, p_name, p_value, r_valid)) {
308
return;
309
}
310
}
311
312
if (p_name == CoreStringName(script)) {
313
set_script(p_value);
314
if (r_valid) {
315
*r_valid = true;
316
}
317
return;
318
319
} else {
320
Variant **V = metadata_properties.getptr(p_name);
321
if (V) {
322
**V = p_value;
323
if (r_valid) {
324
*r_valid = true;
325
}
326
return;
327
} else if (p_name.operator String().begins_with("metadata/")) {
328
// Must exist, otherwise duplicate() will not work.
329
set_meta(p_name.operator String().replace_first("metadata/", ""), p_value);
330
if (r_valid) {
331
*r_valid = true;
332
}
333
return;
334
}
335
}
336
337
#ifdef TOOLS_ENABLED
338
if (script_instance) {
339
bool valid;
340
script_instance->property_set_fallback(p_name, p_value, &valid);
341
if (valid) {
342
if (r_valid) {
343
*r_valid = true;
344
}
345
return;
346
}
347
}
348
#endif
349
350
// Something inside the object... :|
351
bool success = _setv(p_name, p_value);
352
if (success) {
353
if (r_valid) {
354
*r_valid = true;
355
}
356
return;
357
}
358
359
if (r_valid) {
360
*r_valid = false;
361
}
362
}
363
364
Variant Object::get(const StringName &p_name, bool *r_valid) const {
365
Variant ret;
366
367
if (script_instance) {
368
if (script_instance->get(p_name, ret)) {
369
if (r_valid) {
370
*r_valid = true;
371
}
372
return ret;
373
}
374
}
375
if (_extension && _extension->get) {
376
if (_extension->get(_extension_instance, (GDExtensionConstStringNamePtr)&p_name, (GDExtensionVariantPtr)&ret)) {
377
if (r_valid) {
378
*r_valid = true;
379
}
380
return ret;
381
}
382
}
383
384
// Try built-in getter.
385
{
386
if (ClassDB::get_property(const_cast<Object *>(this), p_name, ret)) {
387
if (r_valid) {
388
*r_valid = true;
389
}
390
return ret;
391
}
392
}
393
394
if (p_name == CoreStringName(script)) {
395
ret = get_script();
396
if (r_valid) {
397
*r_valid = true;
398
}
399
return ret;
400
}
401
402
const Variant *const *V = metadata_properties.getptr(p_name);
403
404
if (V) {
405
ret = **V;
406
if (r_valid) {
407
*r_valid = true;
408
}
409
return ret;
410
411
} else {
412
#ifdef TOOLS_ENABLED
413
if (script_instance) {
414
bool valid;
415
ret = script_instance->property_get_fallback(p_name, &valid);
416
if (valid) {
417
if (r_valid) {
418
*r_valid = true;
419
}
420
return ret;
421
}
422
}
423
#endif
424
// Something inside the object... :|
425
bool success = _getv(p_name, ret);
426
if (success) {
427
if (r_valid) {
428
*r_valid = true;
429
}
430
return ret;
431
}
432
433
if (r_valid) {
434
*r_valid = false;
435
}
436
return Variant();
437
}
438
}
439
440
void Object::set_indexed(const Vector<StringName> &p_names, const Variant &p_value, bool *r_valid) {
441
if (p_names.is_empty()) {
442
if (r_valid) {
443
*r_valid = false;
444
}
445
return;
446
}
447
if (p_names.size() == 1) {
448
set(p_names[0], p_value, r_valid);
449
return;
450
}
451
452
bool valid = false;
453
if (!r_valid) {
454
r_valid = &valid;
455
}
456
457
List<Variant> value_stack;
458
459
value_stack.push_back(get(p_names[0], r_valid));
460
461
if (!*r_valid) {
462
value_stack.clear();
463
return;
464
}
465
466
for (int i = 1; i < p_names.size() - 1; i++) {
467
value_stack.push_back(value_stack.back()->get().get_named(p_names[i], valid));
468
if (r_valid) {
469
*r_valid = valid;
470
}
471
472
if (!valid) {
473
value_stack.clear();
474
return;
475
}
476
}
477
478
value_stack.push_back(p_value); // p_names[p_names.size() - 1]
479
480
for (int i = p_names.size() - 1; i > 0; i--) {
481
value_stack.back()->prev()->get().set_named(p_names[i], value_stack.back()->get(), valid);
482
value_stack.pop_back();
483
484
if (r_valid) {
485
*r_valid = valid;
486
}
487
if (!valid) {
488
value_stack.clear();
489
return;
490
}
491
}
492
493
set(p_names[0], value_stack.back()->get(), r_valid);
494
value_stack.pop_back();
495
496
ERR_FAIL_COND(!value_stack.is_empty());
497
}
498
499
Variant Object::get_indexed(const Vector<StringName> &p_names, bool *r_valid) const {
500
if (p_names.is_empty()) {
501
if (r_valid) {
502
*r_valid = false;
503
}
504
return Variant();
505
}
506
bool valid = false;
507
508
Variant current_value = get(p_names[0], &valid);
509
for (int i = 1; i < p_names.size(); i++) {
510
current_value = current_value.get_named(p_names[i], valid);
511
512
if (!valid) {
513
break;
514
}
515
}
516
if (r_valid) {
517
*r_valid = valid;
518
}
519
520
return current_value;
521
}
522
523
void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) const {
524
if (script_instance && p_reversed) {
525
script_instance->get_property_list(p_list);
526
}
527
528
if (_extension) {
529
const ObjectGDExtension *current_extension = _extension;
530
while (current_extension) {
531
p_list->push_back(PropertyInfo(Variant::NIL, current_extension->class_name, PROPERTY_HINT_NONE, current_extension->class_name, PROPERTY_USAGE_CATEGORY));
532
533
ClassDB::get_property_list(current_extension->class_name, p_list, true, this);
534
535
if (current_extension->get_property_list) {
536
#ifdef TOOLS_ENABLED
537
// If this is a placeholder, we can't call into the GDExtension on the parent class,
538
// because we don't have a real instance of the class to give it.
539
if (likely(!_extension->is_placeholder)) {
540
#endif
541
uint32_t pcount;
542
const GDExtensionPropertyInfo *pinfo = current_extension->get_property_list(_extension_instance, &pcount);
543
for (uint32_t i = 0; i < pcount; i++) {
544
p_list->push_back(PropertyInfo(pinfo[i]));
545
}
546
if (current_extension->free_property_list2) {
547
current_extension->free_property_list2(_extension_instance, pinfo, pcount);
548
}
549
#ifndef DISABLE_DEPRECATED
550
else if (current_extension->free_property_list) {
551
current_extension->free_property_list(_extension_instance, pinfo);
552
}
553
#endif // DISABLE_DEPRECATED
554
#ifdef TOOLS_ENABLED
555
}
556
#endif
557
}
558
559
current_extension = current_extension->parent;
560
}
561
}
562
563
_get_property_listv(p_list, p_reversed);
564
565
if (!is_class("Script")) { // can still be set, but this is for user-friendliness
566
p_list->push_back(PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NEVER_DUPLICATE));
567
}
568
569
if (script_instance && !p_reversed) {
570
script_instance->get_property_list(p_list);
571
}
572
573
for (const KeyValue<StringName, Variant> &K : metadata) {
574
PropertyInfo pi = PropertyInfo(K.value.get_type(), "metadata/" + K.key.operator String());
575
if (K.value.get_type() == Variant::OBJECT) {
576
pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
577
Object *obj = K.value;
578
if (Object::cast_to<Script>(obj)) {
579
pi.hint_string = "Script";
580
pi.usage |= PROPERTY_USAGE_NEVER_DUPLICATE;
581
} else {
582
pi.hint_string = "Resource";
583
}
584
}
585
p_list->push_back(pi);
586
}
587
}
588
589
void Object::validate_property(PropertyInfo &p_property) const {
590
_validate_propertyv(p_property);
591
592
if (_extension && _extension->validate_property) {
593
// GDExtension uses a StringName rather than a String for property name.
594
StringName prop_name = p_property.name;
595
GDExtensionPropertyInfo gdext_prop = {
596
(GDExtensionVariantType)p_property.type,
597
&prop_name,
598
&p_property.class_name,
599
(uint32_t)p_property.hint,
600
&p_property.hint_string,
601
p_property.usage,
602
};
603
if (_extension->validate_property(_extension_instance, &gdext_prop)) {
604
p_property.type = (Variant::Type)gdext_prop.type;
605
p_property.name = *reinterpret_cast<StringName *>(gdext_prop.name);
606
p_property.class_name = *reinterpret_cast<StringName *>(gdext_prop.class_name);
607
p_property.hint = (PropertyHint)gdext_prop.hint;
608
p_property.hint_string = *reinterpret_cast<String *>(gdext_prop.hint_string);
609
p_property.usage = gdext_prop.usage;
610
};
611
}
612
613
if (script_instance) { // Call it last to allow user altering already validated properties.
614
script_instance->validate_property(p_property);
615
}
616
}
617
618
bool Object::property_can_revert(const StringName &p_name) const {
619
if (script_instance) {
620
if (script_instance->property_can_revert(p_name)) {
621
return true;
622
}
623
}
624
625
if (_extension && _extension->property_can_revert) {
626
if (_extension->property_can_revert(_extension_instance, (GDExtensionConstStringNamePtr)&p_name)) {
627
return true;
628
}
629
}
630
631
return _property_can_revertv(p_name);
632
}
633
634
Variant Object::property_get_revert(const StringName &p_name) const {
635
Variant ret;
636
637
if (script_instance) {
638
if (script_instance->property_get_revert(p_name, ret)) {
639
return ret;
640
}
641
}
642
643
if (_extension && _extension->property_get_revert) {
644
if (_extension->property_get_revert(_extension_instance, (GDExtensionConstStringNamePtr)&p_name, (GDExtensionVariantPtr)&ret)) {
645
return ret;
646
}
647
}
648
649
if (_property_get_revertv(p_name, ret)) {
650
return ret;
651
}
652
return Variant();
653
}
654
655
void Object::get_method_list(List<MethodInfo> *p_list) const {
656
ClassDB::get_method_list(get_class_name(), p_list);
657
if (script_instance) {
658
script_instance->get_method_list(p_list);
659
}
660
}
661
662
Variant Object::_call_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
663
if (p_argcount < 1) {
664
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
665
r_error.expected = 1;
666
return Variant();
667
}
668
669
if (!p_args[0]->is_string()) {
670
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
671
r_error.argument = 0;
672
r_error.expected = Variant::STRING_NAME;
673
return Variant();
674
}
675
676
StringName method = *p_args[0];
677
678
return callp(method, &p_args[1], p_argcount - 1, r_error);
679
}
680
681
Variant Object::_call_deferred_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
682
if (p_argcount < 1) {
683
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
684
r_error.expected = 1;
685
return Variant();
686
}
687
688
if (!p_args[0]->is_string()) {
689
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
690
r_error.argument = 0;
691
r_error.expected = Variant::STRING_NAME;
692
return Variant();
693
}
694
695
r_error.error = Callable::CallError::CALL_OK;
696
697
StringName method = *p_args[0];
698
699
MessageQueue::get_singleton()->push_callp(get_instance_id(), method, &p_args[1], p_argcount - 1, true);
700
701
return Variant();
702
}
703
704
bool Object::has_method(const StringName &p_method) const {
705
if (p_method == CoreStringName(free_)) {
706
return true;
707
}
708
709
if (script_instance && script_instance->has_method(p_method)) {
710
return true;
711
}
712
713
MethodBind *method = ClassDB::get_method(get_class_name(), p_method);
714
if (method != nullptr) {
715
return true;
716
}
717
718
const Script *scr = Object::cast_to<Script>(this);
719
if (scr != nullptr) {
720
return scr->has_static_method(p_method);
721
}
722
723
return false;
724
}
725
726
int Object::_get_method_argument_count_bind(const StringName &p_method) const {
727
return get_method_argument_count(p_method);
728
}
729
730
int Object::get_method_argument_count(const StringName &p_method, bool *r_is_valid) const {
731
if (p_method == CoreStringName(free_)) {
732
if (r_is_valid) {
733
*r_is_valid = true;
734
}
735
return 0;
736
}
737
738
if (script_instance) {
739
bool valid = false;
740
int ret = script_instance->get_method_argument_count(p_method, &valid);
741
if (valid) {
742
if (r_is_valid) {
743
*r_is_valid = true;
744
}
745
return ret;
746
}
747
}
748
749
{
750
bool valid = false;
751
int ret = ClassDB::get_method_argument_count(get_class_name(), p_method, &valid);
752
if (valid) {
753
if (r_is_valid) {
754
*r_is_valid = true;
755
}
756
return ret;
757
}
758
}
759
760
const Script *scr = Object::cast_to<Script>(this);
761
while (scr != nullptr) {
762
bool valid = false;
763
int ret = scr->get_script_method_argument_count(p_method, &valid);
764
if (valid) {
765
if (r_is_valid) {
766
*r_is_valid = true;
767
}
768
return ret;
769
}
770
scr = scr->get_base_script().ptr();
771
}
772
773
if (r_is_valid) {
774
*r_is_valid = false;
775
}
776
return 0;
777
}
778
779
Variant Object::getvar(const Variant &p_key, bool *r_valid) const {
780
if (r_valid) {
781
*r_valid = false;
782
}
783
784
if (p_key.is_string()) {
785
return get(p_key, r_valid);
786
}
787
return Variant();
788
}
789
790
void Object::setvar(const Variant &p_key, const Variant &p_value, bool *r_valid) {
791
if (r_valid) {
792
*r_valid = false;
793
}
794
if (p_key.is_string()) {
795
return set(p_key, p_value, r_valid);
796
}
797
}
798
799
Variant Object::callv(const StringName &p_method, const Array &p_args) {
800
const Variant **argptrs = nullptr;
801
802
if (p_args.size() > 0) {
803
argptrs = (const Variant **)alloca(sizeof(Variant *) * p_args.size());
804
for (int i = 0; i < p_args.size(); i++) {
805
argptrs[i] = &p_args[i];
806
}
807
}
808
809
Callable::CallError ce;
810
const Variant ret = callp(p_method, argptrs, p_args.size(), ce);
811
if (ce.error != Callable::CallError::CALL_OK) {
812
ERR_FAIL_V_MSG(Variant(), vformat("Error calling method from 'callv': %s.", Variant::get_call_error_text(this, p_method, argptrs, p_args.size(), ce)));
813
}
814
return ret;
815
}
816
817
Variant Object::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
818
r_error.error = Callable::CallError::CALL_OK;
819
820
if (p_method == CoreStringName(free_)) {
821
//free must be here, before anything, always ready
822
#ifdef DEBUG_ENABLED
823
if (p_argcount != 0) {
824
r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
825
r_error.expected = 0;
826
return Variant();
827
}
828
if (is_ref_counted()) {
829
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
830
ERR_FAIL_V_MSG(Variant(), "Can't free a RefCounted object.");
831
}
832
833
if (_lock_index.get() > 1) {
834
r_error.argument = 0;
835
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
836
ERR_FAIL_V_MSG(Variant(), "Object is locked and can't be freed.");
837
}
838
839
#endif
840
//must be here, must be before everything,
841
memdelete(this);
842
r_error.error = Callable::CallError::CALL_OK;
843
return Variant();
844
}
845
846
Variant ret;
847
OBJ_DEBUG_LOCK
848
849
if (script_instance) {
850
ret = script_instance->callp(p_method, p_args, p_argcount, r_error);
851
// Force jump table.
852
switch (r_error.error) {
853
case Callable::CallError::CALL_OK:
854
return ret;
855
case Callable::CallError::CALL_ERROR_INVALID_METHOD:
856
break;
857
case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT:
858
case Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS:
859
case Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS:
860
case Callable::CallError::CALL_ERROR_METHOD_NOT_CONST:
861
return ret;
862
case Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL: {
863
}
864
}
865
}
866
867
//extension does not need this, because all methods are registered in MethodBind
868
869
MethodBind *method = ClassDB::get_method(get_class_name(), p_method);
870
871
if (method) {
872
ret = method->call(this, p_args, p_argcount, r_error);
873
} else {
874
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
875
}
876
877
return ret;
878
}
879
880
Variant Object::call_const(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
881
r_error.error = Callable::CallError::CALL_OK;
882
883
if (p_method == CoreStringName(free_)) {
884
// Free is not const, so fail.
885
r_error.error = Callable::CallError::CALL_ERROR_METHOD_NOT_CONST;
886
return Variant();
887
}
888
889
Variant ret;
890
OBJ_DEBUG_LOCK
891
892
if (script_instance) {
893
ret = script_instance->call_const(p_method, p_args, p_argcount, r_error);
894
//force jumptable
895
switch (r_error.error) {
896
case Callable::CallError::CALL_OK:
897
return ret;
898
case Callable::CallError::CALL_ERROR_INVALID_METHOD:
899
break;
900
case Callable::CallError::CALL_ERROR_METHOD_NOT_CONST:
901
break;
902
case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT:
903
case Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS:
904
case Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS:
905
return ret;
906
case Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL: {
907
}
908
}
909
}
910
911
//extension does not need this, because all methods are registered in MethodBind
912
913
MethodBind *method = ClassDB::get_method(get_class_name(), p_method);
914
915
if (method) {
916
if (!method->is_const()) {
917
r_error.error = Callable::CallError::CALL_ERROR_METHOD_NOT_CONST;
918
return ret;
919
}
920
ret = method->call(this, p_args, p_argcount, r_error);
921
} else {
922
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
923
}
924
925
return ret;
926
}
927
928
void Object::_notification_forward(int p_notification) {
929
// Notify classes starting with Object and ending with most derived subclass.
930
// e.g. Object -> Node -> Node3D
931
_notification_forwardv(p_notification);
932
933
if (_extension) {
934
if (_extension->notification2) {
935
_extension->notification2(_extension_instance, p_notification, static_cast<GDExtensionBool>(false));
936
#ifndef DISABLE_DEPRECATED
937
} else if (_extension->notification) {
938
_extension->notification(_extension_instance, p_notification);
939
#endif // DISABLE_DEPRECATED
940
}
941
}
942
943
if (script_instance) {
944
script_instance->notification(p_notification, false);
945
}
946
}
947
948
void Object::_notification_backward(int p_notification) {
949
if (script_instance) {
950
script_instance->notification(p_notification, true);
951
}
952
953
if (_extension) {
954
if (_extension->notification2) {
955
_extension->notification2(_extension_instance, p_notification, static_cast<GDExtensionBool>(true));
956
#ifndef DISABLE_DEPRECATED
957
} else if (_extension->notification) {
958
_extension->notification(_extension_instance, p_notification);
959
#endif // DISABLE_DEPRECATED
960
}
961
}
962
963
// Notify classes starting with most derived subclass and ending in Object.
964
// e.g. Node3D -> Node -> Object
965
_notification_backwardv(p_notification);
966
}
967
968
String Object::to_string() {
969
// Keep this method in sync with `Node::to_string`.
970
if (script_instance) {
971
bool valid;
972
String ret = script_instance->to_string(&valid);
973
if (valid) {
974
return ret;
975
}
976
}
977
if (_extension && _extension->to_string) {
978
String ret;
979
GDExtensionBool is_valid;
980
_extension->to_string(_extension_instance, &is_valid, &ret);
981
if (is_valid) {
982
return ret;
983
}
984
}
985
return "<" + get_class() + "#" + itos(get_instance_id()) + ">";
986
}
987
988
void Object::set_script_and_instance(const Variant &p_script, ScriptInstance *p_instance) {
989
//this function is not meant to be used in any of these ways
990
ERR_FAIL_COND(p_script.is_null());
991
ERR_FAIL_NULL(p_instance);
992
ERR_FAIL_COND(script_instance != nullptr || !script.is_null());
993
994
script = p_script;
995
script_instance = p_instance;
996
}
997
998
void Object::set_script(const Variant &p_script) {
999
if (script == p_script) {
1000
return;
1001
}
1002
1003
Ref<Script> s = p_script;
1004
if (!p_script.is_null()) {
1005
ERR_FAIL_COND_MSG(s.is_null(), "Cannot set object script. Parameter should be null or a reference to a valid script.");
1006
ERR_FAIL_COND_MSG(s->is_abstract(), vformat("Cannot set object script. Script '%s' should not be abstract.", s->get_path()));
1007
}
1008
1009
script = p_script;
1010
1011
if (script_instance) {
1012
memdelete(script_instance);
1013
script_instance = nullptr;
1014
}
1015
1016
if (s.is_valid()) {
1017
if (s->can_instantiate()) {
1018
OBJ_DEBUG_LOCK
1019
script_instance = s->instance_create(this);
1020
} else if (Engine::get_singleton()->is_editor_hint()) {
1021
OBJ_DEBUG_LOCK
1022
script_instance = s->placeholder_instance_create(this);
1023
}
1024
}
1025
1026
notify_property_list_changed(); //scripts may add variables, so refresh is desired
1027
emit_signal(CoreStringName(script_changed));
1028
}
1029
1030
void Object::set_script_instance(ScriptInstance *p_instance) {
1031
if (script_instance == p_instance) {
1032
return;
1033
}
1034
1035
if (script_instance) {
1036
memdelete(script_instance);
1037
}
1038
1039
script_instance = p_instance;
1040
1041
if (p_instance) {
1042
script = p_instance->get_script();
1043
} else {
1044
script = Variant();
1045
}
1046
}
1047
1048
Variant Object::get_script() const {
1049
return script;
1050
}
1051
1052
bool Object::has_meta(const StringName &p_name) const {
1053
return metadata.has(p_name);
1054
}
1055
1056
void Object::set_meta(const StringName &p_name, const Variant &p_value) {
1057
if (p_value.get_type() == Variant::NIL) {
1058
if (metadata.has(p_name)) {
1059
metadata.erase(p_name);
1060
1061
const String &sname = p_name;
1062
metadata_properties.erase("metadata/" + sname);
1063
if (!sname.begins_with("_")) {
1064
// Metadata starting with _ don't show up in the inspector, so no need to update.
1065
notify_property_list_changed();
1066
}
1067
}
1068
return;
1069
}
1070
1071
HashMap<StringName, Variant>::Iterator E = metadata.find(p_name);
1072
if (E) {
1073
E->value = p_value;
1074
} else {
1075
ERR_FAIL_COND_MSG(!p_name.operator String().is_valid_ascii_identifier(), vformat("Invalid metadata identifier: '%s'.", p_name));
1076
Variant *V = &metadata.insert(p_name, p_value)->value;
1077
1078
const String &sname = p_name;
1079
metadata_properties["metadata/" + sname] = V;
1080
if (!sname.begins_with("_")) {
1081
notify_property_list_changed();
1082
}
1083
}
1084
}
1085
1086
Variant Object::get_meta(const StringName &p_name, const Variant &p_default) const {
1087
if (!metadata.has(p_name)) {
1088
if (p_default != Variant()) {
1089
return p_default;
1090
} else {
1091
ERR_FAIL_V_MSG(Variant(), vformat("The object does not have any 'meta' values with the key '%s'.", p_name));
1092
}
1093
}
1094
return metadata[p_name];
1095
}
1096
1097
void Object::remove_meta(const StringName &p_name) {
1098
set_meta(p_name, Variant());
1099
}
1100
1101
void Object::merge_meta_from(const Object *p_src) {
1102
List<StringName> meta_keys;
1103
p_src->get_meta_list(&meta_keys);
1104
for (const StringName &key : meta_keys) {
1105
set_meta(key, p_src->get_meta(key));
1106
}
1107
}
1108
1109
TypedArray<Dictionary> Object::_get_property_list_bind() const {
1110
List<PropertyInfo> lpi;
1111
get_property_list(&lpi);
1112
return convert_property_list(&lpi);
1113
}
1114
1115
TypedArray<Dictionary> Object::_get_method_list_bind() const {
1116
List<MethodInfo> ml;
1117
get_method_list(&ml);
1118
TypedArray<Dictionary> ret;
1119
1120
for (const MethodInfo &mi : ml) {
1121
Dictionary d = mi;
1122
//va.push_back(d);
1123
ret.push_back(d);
1124
}
1125
1126
return ret;
1127
}
1128
1129
TypedArray<StringName> Object::_get_meta_list_bind() const {
1130
TypedArray<StringName> _metaret;
1131
1132
for (const KeyValue<StringName, Variant> &K : metadata) {
1133
_metaret.push_back(K.key);
1134
}
1135
1136
return _metaret;
1137
}
1138
1139
void Object::get_meta_list(List<StringName> *p_list) const {
1140
for (const KeyValue<StringName, Variant> &K : metadata) {
1141
p_list->push_back(K.key);
1142
}
1143
}
1144
1145
void Object::add_user_signal(const MethodInfo &p_signal) {
1146
ERR_FAIL_COND_MSG(p_signal.name.is_empty(), "Signal name cannot be empty.");
1147
ERR_FAIL_COND_MSG(ClassDB::has_signal(get_class_name(), p_signal.name), vformat("User signal's name conflicts with a built-in signal of '%s'.", get_class_name()));
1148
1149
OBJ_SIGNAL_LOCK
1150
1151
ERR_FAIL_COND_MSG(signal_map.has(p_signal.name), vformat("Trying to add already existing signal '%s'.", p_signal.name));
1152
SignalData s;
1153
s.user = p_signal;
1154
signal_map[p_signal.name] = s;
1155
}
1156
1157
bool Object::_has_user_signal(const StringName &p_name) const {
1158
OBJ_SIGNAL_LOCK
1159
1160
if (!signal_map.has(p_name)) {
1161
return false;
1162
}
1163
return signal_map[p_name].user.name.length() > 0;
1164
}
1165
1166
void Object::_remove_user_signal(const StringName &p_name) {
1167
OBJ_SIGNAL_LOCK
1168
1169
SignalData *s = signal_map.getptr(p_name);
1170
ERR_FAIL_NULL_MSG(s, "Provided signal does not exist.");
1171
ERR_FAIL_COND_MSG(!s->removable, "Signal is not removable (not added with add_user_signal).");
1172
for (const KeyValue<Callable, SignalData::Slot> &slot_kv : s->slot_map) {
1173
Object *target = slot_kv.key.get_object();
1174
if (likely(target)) {
1175
target->connections.erase(slot_kv.value.cE);
1176
}
1177
}
1178
1179
signal_map.erase(p_name);
1180
}
1181
1182
Error Object::_emit_signal(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
1183
if (unlikely(p_argcount < 1)) {
1184
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
1185
r_error.expected = 1;
1186
ERR_FAIL_V(Error::ERR_INVALID_PARAMETER);
1187
}
1188
1189
if (unlikely(!p_args[0]->is_string())) {
1190
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
1191
r_error.argument = 0;
1192
r_error.expected = Variant::STRING_NAME;
1193
ERR_FAIL_V(Error::ERR_INVALID_PARAMETER);
1194
}
1195
1196
r_error.error = Callable::CallError::CALL_OK;
1197
1198
StringName signal = *p_args[0];
1199
1200
const Variant **args = nullptr;
1201
1202
int argc = p_argcount - 1;
1203
if (argc) {
1204
args = &p_args[1];
1205
}
1206
1207
return emit_signalp(signal, args, argc);
1208
}
1209
1210
Error Object::emit_signalp(const StringName &p_name, const Variant **p_args, int p_argcount) {
1211
if (_block_signals) {
1212
return ERR_CANT_ACQUIRE_RESOURCE; //no emit, signals blocked
1213
}
1214
1215
constexpr int MAX_SLOTS_ON_STACK = 5;
1216
// Don't default initialize the Callable objects on the stack, just reserve the space - we'll memnew_placement() them later.
1217
alignas(Callable) uint8_t slot_callable_stack[sizeof(Callable) * MAX_SLOTS_ON_STACK];
1218
uint32_t slot_flags_stack[MAX_SLOTS_ON_STACK];
1219
1220
Callable *slot_callables = (Callable *)slot_callable_stack;
1221
uint32_t *slot_flags = slot_flags_stack;
1222
uint32_t slot_count = 0;
1223
1224
{
1225
OBJ_SIGNAL_LOCK
1226
1227
SignalData *s = signal_map.getptr(p_name);
1228
if (!s) {
1229
#ifdef DEBUG_ENABLED
1230
bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_name);
1231
//check in script
1232
ERR_FAIL_COND_V_MSG(!signal_is_valid && !script.is_null() && !Ref<Script>(script)->has_script_signal(p_name), ERR_UNAVAILABLE, vformat("Can't emit non-existing signal \"%s\".", p_name));
1233
#endif
1234
//not connected? just return
1235
return ERR_UNAVAILABLE;
1236
}
1237
1238
if (s->slot_map.size() > MAX_SLOTS_ON_STACK) {
1239
slot_callables = (Callable *)memalloc(sizeof(Callable) * s->slot_map.size());
1240
slot_flags = (uint32_t *)memalloc(sizeof(uint32_t) * s->slot_map.size());
1241
}
1242
1243
// Ensure that disconnecting the signal or even deleting the object
1244
// will not affect the signal calling.
1245
for (const KeyValue<Callable, SignalData::Slot> &slot_kv : s->slot_map) {
1246
memnew_placement(&slot_callables[slot_count], Callable(slot_kv.value.conn.callable));
1247
slot_flags[slot_count] = slot_kv.value.conn.flags;
1248
++slot_count;
1249
}
1250
1251
DEV_ASSERT(slot_count == s->slot_map.size());
1252
1253
// Disconnect all one-shot connections before emitting to prevent recursion.
1254
for (uint32_t i = 0; i < slot_count; ++i) {
1255
bool disconnect = slot_flags[i] & CONNECT_ONE_SHOT;
1256
#ifdef TOOLS_ENABLED
1257
if (disconnect && (slot_flags[i] & CONNECT_PERSIST) && Engine::get_singleton()->is_editor_hint()) {
1258
// This signal was connected from the editor, and is being edited. Just don't disconnect for now.
1259
disconnect = false;
1260
}
1261
#endif
1262
if (disconnect) {
1263
_disconnect(p_name, slot_callables[i]);
1264
}
1265
}
1266
}
1267
1268
OBJ_DEBUG_LOCK
1269
1270
// If this is a ref-counted object, prevent it from being destroyed during signal
1271
// emission, which is needed in certain edge cases; e.g., GH-73889 and GH-109471.
1272
// Moreover, since signals can be emitted from constructors (classic example being
1273
// notify_property_list_changed), we must be careful not to do the ref init ourselves,
1274
// which would lead to the object being destroyed at the end of this function.
1275
bool pending_unref = Object::cast_to<RefCounted>(this) ? ((RefCounted *)this)->reference() : false;
1276
1277
Error err = OK;
1278
1279
for (uint32_t i = 0; i < slot_count; ++i) {
1280
const Callable &callable = slot_callables[i];
1281
const uint32_t &flags = slot_flags[i];
1282
1283
if (!callable.is_valid()) {
1284
// Target might have been deleted during signal callback, this is expected and OK.
1285
continue;
1286
}
1287
1288
const Variant **args = p_args;
1289
int argc = p_argcount;
1290
1291
if (flags & CONNECT_DEFERRED) {
1292
MessageQueue::get_singleton()->push_callablep(callable, args, argc, true);
1293
} else {
1294
Callable::CallError ce;
1295
_emitting = true;
1296
Variant ret;
1297
callable.callp(args, argc, ret, ce);
1298
_emitting = false;
1299
1300
if (ce.error != Callable::CallError::CALL_OK) {
1301
#ifdef DEBUG_ENABLED
1302
if (flags & CONNECT_PERSIST && Engine::get_singleton()->is_editor_hint() && (script.is_null() || !Ref<Script>(script)->is_tool())) {
1303
continue;
1304
}
1305
#endif
1306
Object *target = callable.get_object();
1307
if (ce.error == Callable::CallError::CALL_ERROR_INVALID_METHOD && target && !ClassDB::class_exists(target->get_class_name())) {
1308
//most likely object is not initialized yet, do not throw error.
1309
} else {
1310
ERR_PRINT(vformat("Error calling from signal '%s' to callable: %s.", String(p_name), Variant::get_callable_error_text(callable, args, argc, ce)));
1311
err = ERR_METHOD_NOT_FOUND;
1312
}
1313
}
1314
}
1315
}
1316
1317
for (uint32_t i = 0; i < slot_count; ++i) {
1318
slot_callables[i].~Callable();
1319
}
1320
1321
if (slot_callables != (Callable *)slot_callable_stack) {
1322
memfree(slot_callables);
1323
memfree(slot_flags);
1324
}
1325
1326
if (pending_unref) {
1327
// We have to do the same Ref<T> would do. We can't just use Ref<T>
1328
// because it would do the init ref logic, which is something this function
1329
// shouldn't do, as explained above.
1330
if (((RefCounted *)this)->unreference()) {
1331
memdelete(this);
1332
}
1333
}
1334
1335
return err;
1336
}
1337
1338
void Object::_add_user_signal(const String &p_name, const Array &p_args) {
1339
// this version of add_user_signal is meant to be used from scripts or external apis
1340
// without access to ADD_SIGNAL in bind_methods
1341
// added events are per instance, as opposed to the other ones, which are global
1342
1343
OBJ_SIGNAL_LOCK
1344
1345
MethodInfo mi;
1346
mi.name = p_name;
1347
1348
for (const Variant &arg : p_args) {
1349
Dictionary d = arg;
1350
PropertyInfo param;
1351
1352
if (d.has("name")) {
1353
param.name = d["name"];
1354
}
1355
if (d.has("type")) {
1356
param.type = (Variant::Type)(int)d["type"];
1357
}
1358
1359
mi.arguments.push_back(param);
1360
}
1361
1362
add_user_signal(mi);
1363
1364
if (signal_map.has(p_name)) {
1365
signal_map.getptr(p_name)->removable = true;
1366
}
1367
}
1368
1369
TypedArray<Dictionary> Object::_get_signal_list() const {
1370
List<MethodInfo> signal_list;
1371
get_signal_list(&signal_list);
1372
1373
TypedArray<Dictionary> ret;
1374
for (const MethodInfo &E : signal_list) {
1375
ret.push_back(Dictionary(E));
1376
}
1377
1378
return ret;
1379
}
1380
1381
TypedArray<Dictionary> Object::_get_signal_connection_list(const StringName &p_signal) const {
1382
List<Connection> conns;
1383
get_all_signal_connections(&conns);
1384
1385
TypedArray<Dictionary> ret;
1386
1387
for (const Connection &c : conns) {
1388
if (c.signal.get_name() == p_signal) {
1389
ret.push_back(c);
1390
}
1391
}
1392
1393
return ret;
1394
}
1395
1396
TypedArray<Dictionary> Object::_get_incoming_connections() const {
1397
TypedArray<Dictionary> ret;
1398
for (const Object::Connection &connection : connections) {
1399
ret.push_back(connection);
1400
}
1401
1402
return ret;
1403
}
1404
1405
bool Object::has_signal(const StringName &p_name) const {
1406
if (!script.is_null()) {
1407
Ref<Script> scr = script;
1408
if (scr.is_valid() && scr->has_script_signal(p_name)) {
1409
return true;
1410
}
1411
}
1412
1413
if (ClassDB::has_signal(get_class_name(), p_name)) {
1414
return true;
1415
}
1416
1417
if (_has_user_signal(p_name)) {
1418
return true;
1419
}
1420
1421
return false;
1422
}
1423
1424
void Object::get_signal_list(List<MethodInfo> *p_signals) const {
1425
OBJ_SIGNAL_LOCK
1426
1427
if (!script.is_null()) {
1428
Ref<Script> scr = script;
1429
if (scr.is_valid()) {
1430
scr->get_script_signal_list(p_signals);
1431
}
1432
}
1433
1434
ClassDB::get_signal_list(get_class_name(), p_signals);
1435
//find maybe usersignals?
1436
1437
for (const KeyValue<StringName, SignalData> &E : signal_map) {
1438
if (!E.value.user.name.is_empty()) {
1439
//user signal
1440
p_signals->push_back(E.value.user);
1441
}
1442
}
1443
}
1444
1445
void Object::get_all_signal_connections(List<Connection> *p_connections) const {
1446
OBJ_SIGNAL_LOCK
1447
1448
for (const KeyValue<StringName, SignalData> &E : signal_map) {
1449
const SignalData *s = &E.value;
1450
1451
for (const KeyValue<Callable, SignalData::Slot> &slot_kv : s->slot_map) {
1452
p_connections->push_back(slot_kv.value.conn);
1453
}
1454
}
1455
}
1456
1457
void Object::get_signal_connection_list(const StringName &p_signal, List<Connection> *p_connections) const {
1458
OBJ_SIGNAL_LOCK
1459
1460
const SignalData *s = signal_map.getptr(p_signal);
1461
if (!s) {
1462
return; //nothing
1463
}
1464
1465
for (const KeyValue<Callable, SignalData::Slot> &slot_kv : s->slot_map) {
1466
p_connections->push_back(slot_kv.value.conn);
1467
}
1468
}
1469
1470
int Object::get_persistent_signal_connection_count() const {
1471
OBJ_SIGNAL_LOCK
1472
int count = 0;
1473
1474
for (const KeyValue<StringName, SignalData> &E : signal_map) {
1475
const SignalData *s = &E.value;
1476
1477
for (const KeyValue<Callable, SignalData::Slot> &slot_kv : s->slot_map) {
1478
if (slot_kv.value.conn.flags & CONNECT_PERSIST) {
1479
count += 1;
1480
}
1481
}
1482
}
1483
1484
return count;
1485
}
1486
1487
void Object::get_signals_connected_to_this(List<Connection> *p_connections) const {
1488
OBJ_SIGNAL_LOCK
1489
1490
for (const Connection &E : connections) {
1491
p_connections->push_back(E);
1492
}
1493
}
1494
1495
Error Object::connect(const StringName &p_signal, const Callable &p_callable, uint32_t p_flags) {
1496
ERR_FAIL_COND_V_MSG(p_callable.is_null(), ERR_INVALID_PARAMETER, vformat("Cannot connect to '%s': the provided callable is null.", p_signal));
1497
OBJ_SIGNAL_LOCK
1498
1499
if (p_callable.is_standard()) {
1500
// FIXME: This branch should probably removed in favor of the `is_valid()` branch, but there exist some classes
1501
// that call `connect()` before they are fully registered with ClassDB. Until all such classes can be found
1502
// and registered soon enough this branch is needed to allow `connect()` to succeed.
1503
ERR_FAIL_NULL_V_MSG(p_callable.get_object(), ERR_INVALID_PARAMETER, vformat("Cannot connect to '%s' to callable '%s': the callable object is null.", p_signal, p_callable));
1504
} else {
1505
ERR_FAIL_COND_V_MSG(!p_callable.is_valid(), ERR_INVALID_PARAMETER, vformat("Cannot connect to '%s': the provided callable is not valid: '%s'.", p_signal, p_callable));
1506
}
1507
1508
SignalData *s = signal_map.getptr(p_signal);
1509
if (!s) {
1510
bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_signal);
1511
//check in script
1512
if (!signal_is_valid && !script.is_null()) {
1513
if (Ref<Script>(script)->has_script_signal(p_signal)) {
1514
signal_is_valid = true;
1515
}
1516
#ifdef TOOLS_ENABLED
1517
else {
1518
//allow connecting signals anyway if script is invalid, see issue #17070
1519
if (!Ref<Script>(script)->is_valid()) {
1520
signal_is_valid = true;
1521
}
1522
}
1523
#endif
1524
}
1525
1526
ERR_FAIL_COND_V_MSG(!signal_is_valid, ERR_INVALID_PARAMETER, vformat("In Object of type '%s': Attempt to connect nonexistent signal '%s' to callable '%s'.", String(get_class()), p_signal, p_callable));
1527
1528
signal_map[p_signal] = SignalData();
1529
s = &signal_map[p_signal];
1530
}
1531
1532
//compare with the base callable, so binds can be ignored
1533
if (s->slot_map.has(*p_callable.get_base_comparator())) {
1534
if (p_flags & CONNECT_REFERENCE_COUNTED) {
1535
s->slot_map[*p_callable.get_base_comparator()].reference_count++;
1536
return OK;
1537
} else {
1538
ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, vformat("Signal '%s' is already connected to given callable '%s' in that object.", p_signal, p_callable));
1539
}
1540
}
1541
1542
Object *target_object = p_callable.get_object();
1543
1544
SignalData::Slot slot;
1545
1546
Connection conn;
1547
conn.callable = p_callable;
1548
conn.signal = ::Signal(this, p_signal);
1549
conn.flags = p_flags;
1550
slot.conn = conn;
1551
if (target_object) {
1552
slot.cE = target_object->connections.push_back(conn);
1553
}
1554
if (p_flags & CONNECT_REFERENCE_COUNTED) {
1555
slot.reference_count = 1;
1556
}
1557
1558
//use callable version as key, so binds can be ignored
1559
s->slot_map[*p_callable.get_base_comparator()] = slot;
1560
1561
return OK;
1562
}
1563
1564
bool Object::is_connected(const StringName &p_signal, const Callable &p_callable) const {
1565
ERR_FAIL_COND_V_MSG(p_callable.is_null(), false, vformat("Cannot determine if connected to '%s': the provided callable is null.", p_signal)); // Should use `is_null`, see note in `connect` about the use of `is_valid`.
1566
OBJ_SIGNAL_LOCK
1567
1568
const SignalData *s = signal_map.getptr(p_signal);
1569
if (!s) {
1570
bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_signal);
1571
if (signal_is_valid) {
1572
return false;
1573
}
1574
1575
if (!script.is_null() && Ref<Script>(script)->has_script_signal(p_signal)) {
1576
return false;
1577
}
1578
1579
ERR_FAIL_V_MSG(false, vformat("Nonexistent signal: '%s'.", p_signal));
1580
}
1581
1582
return s->slot_map.has(*p_callable.get_base_comparator());
1583
}
1584
1585
bool Object::has_connections(const StringName &p_signal) const {
1586
OBJ_SIGNAL_LOCK
1587
1588
const SignalData *s = signal_map.getptr(p_signal);
1589
if (!s) {
1590
bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_signal);
1591
if (signal_is_valid) {
1592
return false;
1593
}
1594
1595
if (!script.is_null() && Ref<Script>(script)->has_script_signal(p_signal)) {
1596
return false;
1597
}
1598
1599
ERR_FAIL_V_MSG(false, vformat("Nonexistent signal: '%s'.", p_signal));
1600
}
1601
1602
return !s->slot_map.is_empty();
1603
}
1604
1605
void Object::disconnect(const StringName &p_signal, const Callable &p_callable) {
1606
_disconnect(p_signal, p_callable);
1607
}
1608
1609
bool Object::_disconnect(const StringName &p_signal, const Callable &p_callable, bool p_force) {
1610
ERR_FAIL_COND_V_MSG(p_callable.is_null(), false, vformat("Cannot disconnect from '%s': the provided callable is null.", p_signal)); // Should use `is_null`, see note in `connect` about the use of `is_valid`.
1611
OBJ_SIGNAL_LOCK
1612
1613
SignalData *s = signal_map.getptr(p_signal);
1614
if (!s) {
1615
bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_signal) ||
1616
(!script.is_null() && Ref<Script>(script)->has_script_signal(p_signal));
1617
ERR_FAIL_COND_V_MSG(signal_is_valid, false, vformat("Attempt to disconnect a nonexistent connection from '%s'. Signal: '%s', callable: '%s'.", to_string(), p_signal, p_callable));
1618
}
1619
ERR_FAIL_NULL_V_MSG(s, false, vformat("Disconnecting nonexistent signal '%s' in '%s'.", p_signal, to_string()));
1620
1621
ERR_FAIL_COND_V_MSG(!s->slot_map.has(*p_callable.get_base_comparator()), false, vformat("Attempt to disconnect a nonexistent connection from '%s'. Signal: '%s', callable: '%s'.", to_string(), p_signal, p_callable));
1622
1623
SignalData::Slot *slot = &s->slot_map[*p_callable.get_base_comparator()];
1624
1625
if (!p_force) {
1626
slot->reference_count--; // by default is zero, if it was not referenced it will go below it
1627
if (slot->reference_count > 0) {
1628
return false;
1629
}
1630
}
1631
1632
if (slot->cE) {
1633
Object *target_object = p_callable.get_object();
1634
if (target_object) {
1635
target_object->connections.erase(slot->cE);
1636
}
1637
}
1638
1639
s->slot_map.erase(*p_callable.get_base_comparator());
1640
1641
if (s->slot_map.is_empty() && ClassDB::has_signal(get_class_name(), p_signal)) {
1642
//not user signal, delete
1643
signal_map.erase(p_signal);
1644
}
1645
1646
return true;
1647
}
1648
1649
bool Object::_uses_signal_mutex() const {
1650
return true;
1651
}
1652
1653
void Object::_set_bind(const StringName &p_set, const Variant &p_value) {
1654
set(p_set, p_value);
1655
}
1656
1657
Variant Object::_get_bind(const StringName &p_name) const {
1658
return get(p_name);
1659
}
1660
1661
void Object::_set_indexed_bind(const NodePath &p_name, const Variant &p_value) {
1662
set_indexed(p_name.get_as_property_path().get_subnames(), p_value);
1663
}
1664
1665
Variant Object::_get_indexed_bind(const NodePath &p_name) const {
1666
return get_indexed(p_name.get_as_property_path().get_subnames());
1667
}
1668
1669
void Object::initialize_class() {
1670
static bool initialized = false;
1671
if (initialized) {
1672
return;
1673
}
1674
_add_class_to_classdb(get_class_static(), StringName());
1675
_bind_methods();
1676
_bind_compatibility_methods();
1677
initialized = true;
1678
}
1679
1680
StringName Object::get_translation_domain() const {
1681
return _translation_domain;
1682
}
1683
1684
void Object::set_translation_domain(const StringName &p_domain) {
1685
_translation_domain = p_domain;
1686
}
1687
1688
String Object::tr(const StringName &p_message, const StringName &p_context) const {
1689
if (!_can_translate || !TranslationServer::get_singleton()) {
1690
return p_message;
1691
}
1692
1693
const Ref<TranslationDomain> domain = TranslationServer::get_singleton()->get_or_add_domain(get_translation_domain());
1694
return domain->translate(p_message, p_context);
1695
}
1696
1697
String Object::tr_n(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context) const {
1698
if (!_can_translate || !TranslationServer::get_singleton()) {
1699
// Return message based on English plural rule if translation is not possible.
1700
if (p_n == 1) {
1701
return p_message;
1702
}
1703
return p_message_plural;
1704
}
1705
1706
const Ref<TranslationDomain> domain = TranslationServer::get_singleton()->get_or_add_domain(get_translation_domain());
1707
return domain->translate_plural(p_message, p_message_plural, p_n, p_context);
1708
}
1709
1710
void Object::_clear_internal_resource_paths(const Variant &p_var) {
1711
switch (p_var.get_type()) {
1712
case Variant::OBJECT: {
1713
Ref<Resource> r = p_var;
1714
if (r.is_null()) {
1715
return;
1716
}
1717
1718
if (!r->is_built_in()) {
1719
return; //not an internal resource
1720
}
1721
1722
Object *object = p_var;
1723
if (!object) {
1724
return;
1725
}
1726
1727
r->set_path("");
1728
r->clear_internal_resource_paths();
1729
} break;
1730
case Variant::ARRAY: {
1731
Array a = p_var;
1732
for (const Variant &var : a) {
1733
_clear_internal_resource_paths(var);
1734
}
1735
1736
} break;
1737
case Variant::DICTIONARY: {
1738
Dictionary d = p_var;
1739
1740
for (const KeyValue<Variant, Variant> &kv : d) {
1741
_clear_internal_resource_paths(kv.key);
1742
_clear_internal_resource_paths(kv.value);
1743
}
1744
} break;
1745
default: {
1746
}
1747
}
1748
}
1749
1750
void Object::_add_class_to_classdb(const StringName &p_class, const StringName &p_inherits) {
1751
ClassDB::_add_class(p_class, p_inherits);
1752
}
1753
1754
void Object::_get_property_list_from_classdb(const StringName &p_class, List<PropertyInfo> *p_list, bool p_no_inheritance, const Object *p_validator) {
1755
ClassDB::get_property_list(p_class, p_list, p_no_inheritance, p_validator);
1756
}
1757
1758
#ifdef TOOLS_ENABLED
1759
void Object::editor_set_section_unfold(const String &p_section, bool p_unfolded, bool p_initializing) {
1760
if (!p_initializing) {
1761
set_edited(true);
1762
}
1763
1764
if (p_unfolded) {
1765
editor_section_folding.insert(p_section);
1766
} else {
1767
editor_section_folding.erase(p_section);
1768
}
1769
}
1770
1771
bool Object::editor_is_section_unfolded(const String &p_section) {
1772
return editor_section_folding.has(p_section);
1773
}
1774
1775
#endif
1776
1777
void Object::clear_internal_resource_paths() {
1778
List<PropertyInfo> pinfo;
1779
1780
get_property_list(&pinfo);
1781
1782
for (const PropertyInfo &E : pinfo) {
1783
_clear_internal_resource_paths(get(E.name));
1784
}
1785
}
1786
1787
void Object::notify_property_list_changed() {
1788
emit_signal(CoreStringName(property_list_changed));
1789
}
1790
1791
void Object::_bind_methods() {
1792
ClassDB::bind_method(D_METHOD("get_class"), &Object::get_class);
1793
ClassDB::bind_method(D_METHOD("is_class", "class"), &Object::is_class);
1794
ClassDB::bind_method(D_METHOD("set", "property", "value"), &Object::_set_bind);
1795
ClassDB::bind_method(D_METHOD("get", "property"), &Object::_get_bind);
1796
ClassDB::bind_method(D_METHOD("set_indexed", "property_path", "value"), &Object::_set_indexed_bind);
1797
ClassDB::bind_method(D_METHOD("get_indexed", "property_path"), &Object::_get_indexed_bind);
1798
ClassDB::bind_method(D_METHOD("get_property_list"), &Object::_get_property_list_bind);
1799
ClassDB::bind_method(D_METHOD("get_method_list"), &Object::_get_method_list_bind);
1800
ClassDB::bind_method(D_METHOD("property_can_revert", "property"), &Object::property_can_revert);
1801
ClassDB::bind_method(D_METHOD("property_get_revert", "property"), &Object::property_get_revert);
1802
ClassDB::bind_method(D_METHOD("notification", "what", "reversed"), &Object::notification, DEFVAL(false));
1803
ClassDB::bind_method(D_METHOD("to_string"), &Object::to_string);
1804
ClassDB::bind_method(D_METHOD("get_instance_id"), &Object::get_instance_id);
1805
1806
ClassDB::bind_method(D_METHOD("set_script", "script"), &Object::set_script);
1807
ClassDB::bind_method(D_METHOD("get_script"), &Object::get_script);
1808
1809
ClassDB::bind_method(D_METHOD("set_meta", "name", "value"), &Object::set_meta);
1810
ClassDB::bind_method(D_METHOD("remove_meta", "name"), &Object::remove_meta);
1811
ClassDB::bind_method(D_METHOD("get_meta", "name", "default"), &Object::get_meta, DEFVAL(Variant()));
1812
ClassDB::bind_method(D_METHOD("has_meta", "name"), &Object::has_meta);
1813
ClassDB::bind_method(D_METHOD("get_meta_list"), &Object::_get_meta_list_bind);
1814
1815
ClassDB::bind_method(D_METHOD("add_user_signal", "signal", "arguments"), &Object::_add_user_signal, DEFVAL(Array()));
1816
ClassDB::bind_method(D_METHOD("has_user_signal", "signal"), &Object::_has_user_signal);
1817
ClassDB::bind_method(D_METHOD("remove_user_signal", "signal"), &Object::_remove_user_signal);
1818
1819
{
1820
MethodInfo mi;
1821
mi.name = "emit_signal";
1822
mi.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "signal"));
1823
1824
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "emit_signal", &Object::_emit_signal, mi, varray(), false);
1825
}
1826
1827
{
1828
MethodInfo mi;
1829
mi.name = "call";
1830
mi.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "method"));
1831
1832
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "call", &Object::_call_bind, mi);
1833
}
1834
1835
{
1836
MethodInfo mi;
1837
mi.name = "call_deferred";
1838
mi.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "method"));
1839
1840
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "call_deferred", &Object::_call_deferred_bind, mi, varray(), false);
1841
}
1842
1843
ClassDB::bind_method(D_METHOD("set_deferred", "property", "value"), &Object::set_deferred);
1844
1845
ClassDB::bind_method(D_METHOD("callv", "method", "arg_array"), &Object::callv);
1846
1847
ClassDB::bind_method(D_METHOD("has_method", "method"), &Object::has_method);
1848
1849
ClassDB::bind_method(D_METHOD("get_method_argument_count", "method"), &Object::_get_method_argument_count_bind);
1850
1851
ClassDB::bind_method(D_METHOD("has_signal", "signal"), &Object::has_signal);
1852
ClassDB::bind_method(D_METHOD("get_signal_list"), &Object::_get_signal_list);
1853
ClassDB::bind_method(D_METHOD("get_signal_connection_list", "signal"), &Object::_get_signal_connection_list);
1854
ClassDB::bind_method(D_METHOD("get_incoming_connections"), &Object::_get_incoming_connections);
1855
1856
ClassDB::bind_method(D_METHOD("connect", "signal", "callable", "flags"), &Object::connect, DEFVAL(0));
1857
ClassDB::bind_method(D_METHOD("disconnect", "signal", "callable"), &Object::disconnect);
1858
ClassDB::bind_method(D_METHOD("is_connected", "signal", "callable"), &Object::is_connected);
1859
ClassDB::bind_method(D_METHOD("has_connections", "signal"), &Object::has_connections);
1860
1861
ClassDB::bind_method(D_METHOD("set_block_signals", "enable"), &Object::set_block_signals);
1862
ClassDB::bind_method(D_METHOD("is_blocking_signals"), &Object::is_blocking_signals);
1863
ClassDB::bind_method(D_METHOD("notify_property_list_changed"), &Object::notify_property_list_changed);
1864
1865
ClassDB::bind_method(D_METHOD("set_message_translation", "enable"), &Object::set_message_translation);
1866
ClassDB::bind_method(D_METHOD("can_translate_messages"), &Object::can_translate_messages);
1867
ClassDB::bind_method(D_METHOD("tr", "message", "context"), &Object::tr, DEFVAL(StringName()));
1868
ClassDB::bind_method(D_METHOD("tr_n", "message", "plural_message", "n", "context"), &Object::tr_n, DEFVAL(StringName()));
1869
ClassDB::bind_method(D_METHOD("get_translation_domain"), &Object::get_translation_domain);
1870
ClassDB::bind_method(D_METHOD("set_translation_domain", "domain"), &Object::set_translation_domain);
1871
1872
ClassDB::bind_method(D_METHOD("is_queued_for_deletion"), &Object::is_queued_for_deletion);
1873
ClassDB::bind_method(D_METHOD("cancel_free"), &Object::cancel_free);
1874
1875
ClassDB::add_virtual_method("Object", MethodInfo("free"), false);
1876
1877
ADD_SIGNAL(MethodInfo("script_changed"));
1878
ADD_SIGNAL(MethodInfo("property_list_changed"));
1879
1880
#define BIND_OBJ_CORE_METHOD(m_method) \
1881
::ClassDB::add_virtual_method(get_class_static(), m_method, true, Vector<String>(), true);
1882
1883
BIND_OBJ_CORE_METHOD(MethodInfo("_init"));
1884
1885
BIND_OBJ_CORE_METHOD(MethodInfo(Variant::STRING, "_to_string"));
1886
1887
{
1888
MethodInfo mi("_notification");
1889
mi.arguments.push_back(PropertyInfo(Variant::INT, "what"));
1890
mi.arguments_metadata.push_back(GodotTypeInfo::Metadata::METADATA_INT_IS_INT32);
1891
BIND_OBJ_CORE_METHOD(mi);
1892
}
1893
1894
{
1895
MethodInfo mi("_set");
1896
mi.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "property"));
1897
mi.arguments.push_back(PropertyInfo(Variant::NIL, "value", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT));
1898
mi.return_val.type = Variant::BOOL;
1899
BIND_OBJ_CORE_METHOD(mi);
1900
}
1901
1902
#ifdef TOOLS_ENABLED
1903
{
1904
MethodInfo mi("_get");
1905
mi.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "property"));
1906
mi.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
1907
BIND_OBJ_CORE_METHOD(mi);
1908
}
1909
1910
{
1911
MethodInfo mi("_get_property_list");
1912
mi.return_val.type = Variant::ARRAY;
1913
mi.return_val.hint = PROPERTY_HINT_ARRAY_TYPE;
1914
mi.return_val.hint_string = "Dictionary";
1915
BIND_OBJ_CORE_METHOD(mi);
1916
}
1917
1918
BIND_OBJ_CORE_METHOD(MethodInfo(Variant::NIL, "_validate_property", PropertyInfo(Variant::DICTIONARY, "property")));
1919
1920
BIND_OBJ_CORE_METHOD(MethodInfo(Variant::BOOL, "_property_can_revert", PropertyInfo(Variant::STRING_NAME, "property")));
1921
1922
{
1923
MethodInfo mi("_property_get_revert");
1924
mi.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "property"));
1925
mi.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
1926
BIND_OBJ_CORE_METHOD(mi);
1927
}
1928
1929
// These are actually `Variant` methods, but that doesn't matter since scripts can't inherit built-in types.
1930
1931
BIND_OBJ_CORE_METHOD(MethodInfo(Variant::BOOL, "_iter_init", PropertyInfo(Variant::ARRAY, "iter")));
1932
1933
BIND_OBJ_CORE_METHOD(MethodInfo(Variant::BOOL, "_iter_next", PropertyInfo(Variant::ARRAY, "iter")));
1934
1935
{
1936
MethodInfo mi("_iter_get");
1937
mi.arguments.push_back(PropertyInfo(Variant::NIL, "iter", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT));
1938
mi.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
1939
BIND_OBJ_CORE_METHOD(mi);
1940
}
1941
#endif
1942
1943
BIND_CONSTANT(NOTIFICATION_POSTINITIALIZE);
1944
BIND_CONSTANT(NOTIFICATION_PREDELETE);
1945
BIND_CONSTANT(NOTIFICATION_EXTENSION_RELOADED);
1946
1947
BIND_ENUM_CONSTANT(CONNECT_DEFERRED);
1948
BIND_ENUM_CONSTANT(CONNECT_PERSIST);
1949
BIND_ENUM_CONSTANT(CONNECT_ONE_SHOT);
1950
BIND_ENUM_CONSTANT(CONNECT_REFERENCE_COUNTED);
1951
BIND_ENUM_CONSTANT(CONNECT_APPEND_SOURCE_OBJECT);
1952
}
1953
1954
void Object::set_deferred(const StringName &p_property, const Variant &p_value) {
1955
MessageQueue::get_singleton()->push_set(this, p_property, p_value);
1956
}
1957
1958
void Object::set_block_signals(bool p_block) {
1959
_block_signals = p_block;
1960
}
1961
1962
bool Object::is_blocking_signals() const {
1963
return _block_signals;
1964
}
1965
1966
Variant::Type Object::get_static_property_type(const StringName &p_property, bool *r_valid) const {
1967
bool valid;
1968
Variant::Type t = ClassDB::get_property_type(get_class_name(), p_property, &valid);
1969
if (valid) {
1970
if (r_valid) {
1971
*r_valid = true;
1972
}
1973
return t;
1974
}
1975
1976
if (get_script_instance()) {
1977
return get_script_instance()->get_property_type(p_property, r_valid);
1978
}
1979
if (r_valid) {
1980
*r_valid = false;
1981
}
1982
1983
return Variant::NIL;
1984
}
1985
1986
Variant::Type Object::get_static_property_type_indexed(const Vector<StringName> &p_path, bool *r_valid) const {
1987
if (p_path.is_empty()) {
1988
if (r_valid) {
1989
*r_valid = false;
1990
}
1991
1992
return Variant::NIL;
1993
}
1994
1995
bool valid = false;
1996
Variant::Type t = get_static_property_type(p_path[0], &valid);
1997
if (!valid) {
1998
if (r_valid) {
1999
*r_valid = false;
2000
}
2001
2002
return Variant::NIL;
2003
}
2004
2005
Callable::CallError ce;
2006
Variant check;
2007
Variant::construct(t, check, nullptr, 0, ce);
2008
2009
for (int i = 1; i < p_path.size(); i++) {
2010
if (check.get_type() == Variant::OBJECT || check.get_type() == Variant::DICTIONARY || check.get_type() == Variant::ARRAY) {
2011
// We cannot be sure about the type of properties this type can have
2012
if (r_valid) {
2013
*r_valid = false;
2014
}
2015
return Variant::NIL;
2016
}
2017
2018
check = check.get_named(p_path[i], valid);
2019
2020
if (!valid) {
2021
if (r_valid) {
2022
*r_valid = false;
2023
}
2024
return Variant::NIL;
2025
}
2026
}
2027
2028
if (r_valid) {
2029
*r_valid = true;
2030
}
2031
2032
return check.get_type();
2033
}
2034
2035
bool Object::is_queued_for_deletion() const {
2036
return _is_queued_for_deletion;
2037
}
2038
2039
#ifdef TOOLS_ENABLED
2040
void Object::set_edited(bool p_edited) {
2041
_edited = p_edited;
2042
_edited_version++;
2043
}
2044
2045
bool Object::is_edited() const {
2046
return _edited;
2047
}
2048
2049
uint32_t Object::get_edited_version() const {
2050
return _edited_version;
2051
}
2052
#endif
2053
2054
const StringName &Object::get_class_name() const {
2055
if (_extension) {
2056
// Can't put inside the unlikely as constructor can run it.
2057
return _extension->class_name;
2058
}
2059
2060
if (unlikely(!_class_name_ptr)) {
2061
// While class is initializing / deinitializing, constructors and destructors
2062
// need access to the proper class at the proper stage.
2063
return *_get_class_namev();
2064
}
2065
return *_class_name_ptr;
2066
}
2067
2068
StringName Object::get_class_name_for_extension(const GDExtension *p_library) const {
2069
#ifdef TOOLS_ENABLED
2070
// If this is the library this extension comes from and it's a placeholder, we
2071
// have to return the closest native parent's class name, so that it doesn't try to
2072
// use this like the real object.
2073
if (unlikely(_extension && _extension->library == p_library && _extension->is_placeholder)) {
2074
const StringName *class_name = _get_class_namev();
2075
return *class_name;
2076
}
2077
#endif
2078
2079
// Only return the class name per the extension if it matches the given p_library.
2080
if (_extension && _extension->library == p_library) {
2081
return _extension->class_name;
2082
}
2083
2084
// Extensions only have wrapper classes for classes exposed in ClassDB.
2085
const StringName *class_name = _get_class_namev();
2086
if (ClassDB::is_class_exposed(*class_name)) {
2087
return *class_name;
2088
}
2089
2090
// Find the nearest parent class that's exposed.
2091
StringName parent_class = ClassDB::get_parent_class(*class_name);
2092
while (parent_class != StringName()) {
2093
if (ClassDB::is_class_exposed(parent_class)) {
2094
return parent_class;
2095
}
2096
parent_class = ClassDB::get_parent_class(parent_class);
2097
}
2098
2099
return SNAME("Object");
2100
}
2101
2102
void Object::set_instance_binding(void *p_token, void *p_binding, const GDExtensionInstanceBindingCallbacks *p_callbacks) {
2103
// This is only meant to be used on creation by the binder, but we also
2104
// need to account for reloading (where the 'binding' will be cleared).
2105
ERR_FAIL_COND(_instance_bindings != nullptr && _instance_bindings[0].binding != nullptr);
2106
if (_instance_bindings == nullptr) {
2107
_instance_bindings = (InstanceBinding *)memalloc(sizeof(InstanceBinding));
2108
_instance_binding_count = 1;
2109
}
2110
_instance_bindings[0].binding = p_binding;
2111
_instance_bindings[0].free_callback = p_callbacks->free_callback;
2112
_instance_bindings[0].reference_callback = p_callbacks->reference_callback;
2113
_instance_bindings[0].token = p_token;
2114
}
2115
2116
void *Object::get_instance_binding(void *p_token, const GDExtensionInstanceBindingCallbacks *p_callbacks) {
2117
void *binding = nullptr;
2118
MutexLock instance_binding_lock(_instance_binding_mutex);
2119
for (uint32_t i = 0; i < _instance_binding_count; i++) {
2120
if (_instance_bindings[i].token == p_token) {
2121
binding = _instance_bindings[i].binding;
2122
break;
2123
}
2124
}
2125
if (unlikely(!binding && p_callbacks)) {
2126
uint32_t current_size = next_power_of_2(_instance_binding_count);
2127
uint32_t new_size = next_power_of_2(_instance_binding_count + 1);
2128
2129
if (current_size == 0 || new_size > current_size) {
2130
_instance_bindings = (InstanceBinding *)memrealloc(_instance_bindings, new_size * sizeof(InstanceBinding));
2131
}
2132
2133
_instance_bindings[_instance_binding_count].free_callback = p_callbacks->free_callback;
2134
_instance_bindings[_instance_binding_count].reference_callback = p_callbacks->reference_callback;
2135
_instance_bindings[_instance_binding_count].token = p_token;
2136
2137
binding = p_callbacks->create_callback(p_token, this);
2138
_instance_bindings[_instance_binding_count].binding = binding;
2139
2140
#ifdef TOOLS_ENABLED
2141
if (!_extension && Engine::get_singleton()->is_extension_reloading_enabled()) {
2142
GDExtensionManager::get_singleton()->track_instance_binding(p_token, this);
2143
}
2144
#endif
2145
2146
_instance_binding_count++;
2147
}
2148
2149
return binding;
2150
}
2151
2152
bool Object::has_instance_binding(void *p_token) {
2153
bool found = false;
2154
MutexLock instance_binding_lock(_instance_binding_mutex);
2155
for (uint32_t i = 0; i < _instance_binding_count; i++) {
2156
if (_instance_bindings[i].token == p_token) {
2157
found = true;
2158
break;
2159
}
2160
}
2161
2162
return found;
2163
}
2164
2165
void Object::free_instance_binding(void *p_token) {
2166
bool found = false;
2167
MutexLock instance_binding_lock(_instance_binding_mutex);
2168
for (uint32_t i = 0; i < _instance_binding_count; i++) {
2169
if (!found && _instance_bindings[i].token == p_token) {
2170
if (_instance_bindings[i].free_callback) {
2171
_instance_bindings[i].free_callback(_instance_bindings[i].token, this, _instance_bindings[i].binding);
2172
}
2173
found = true;
2174
}
2175
if (found) {
2176
if (i + 1 < _instance_binding_count) {
2177
_instance_bindings[i] = _instance_bindings[i + 1];
2178
} else {
2179
_instance_bindings[i] = { nullptr };
2180
}
2181
}
2182
}
2183
if (found) {
2184
_instance_binding_count--;
2185
}
2186
}
2187
2188
#ifdef TOOLS_ENABLED
2189
void Object::clear_internal_extension() {
2190
ERR_FAIL_NULL(_extension);
2191
2192
// Free the instance inside the GDExtension.
2193
if (_extension->free_instance) {
2194
_extension->free_instance(_extension->class_userdata, _extension_instance);
2195
}
2196
_extension = nullptr;
2197
_extension_instance = nullptr;
2198
2199
// Clear the instance bindings.
2200
_instance_binding_mutex.lock();
2201
if (_instance_bindings) {
2202
if (_instance_bindings[0].free_callback) {
2203
_instance_bindings[0].free_callback(_instance_bindings[0].token, this, _instance_bindings[0].binding);
2204
}
2205
_instance_bindings[0].binding = nullptr;
2206
_instance_bindings[0].token = nullptr;
2207
_instance_bindings[0].free_callback = nullptr;
2208
_instance_bindings[0].reference_callback = nullptr;
2209
}
2210
_instance_binding_mutex.unlock();
2211
2212
// Clear the virtual methods.
2213
while (virtual_method_list) {
2214
(*virtual_method_list->method) = nullptr;
2215
virtual_method_list = virtual_method_list->next;
2216
}
2217
}
2218
2219
void Object::reset_internal_extension(ObjectGDExtension *p_extension) {
2220
ERR_FAIL_COND(_extension != nullptr);
2221
2222
if (p_extension) {
2223
_extension_instance = p_extension->recreate_instance ? p_extension->recreate_instance(p_extension->class_userdata, (GDExtensionObjectPtr)this) : nullptr;
2224
ERR_FAIL_NULL_MSG(_extension_instance, "Unable to recreate GDExtension instance - does this extension support hot reloading?");
2225
_extension = p_extension;
2226
}
2227
}
2228
#endif
2229
2230
void Object::_construct_object(bool p_reference) {
2231
type_is_reference = p_reference;
2232
_instance_id = ObjectDB::add_instance(this);
2233
2234
#ifdef DEBUG_ENABLED
2235
_lock_index.init(1);
2236
#endif
2237
}
2238
2239
Object::Object(bool p_reference) {
2240
_construct_object(p_reference);
2241
}
2242
2243
Object::Object() {
2244
_construct_object(false);
2245
}
2246
2247
void Object::detach_from_objectdb() {
2248
if (_instance_id != ObjectID()) {
2249
ObjectDB::remove_instance(this);
2250
_instance_id = ObjectID();
2251
}
2252
}
2253
2254
void Object::assign_class_name_static(const Span<char> &p_name, StringName &r_target) {
2255
static BinaryMutex _mutex;
2256
MutexLock lock(_mutex);
2257
if (r_target) {
2258
// Already assigned while we were waiting for the mutex.
2259
return;
2260
}
2261
r_target = StringName(p_name.ptr(), true);
2262
}
2263
2264
Object::~Object() {
2265
if (script_instance) {
2266
memdelete(script_instance);
2267
}
2268
script_instance = nullptr;
2269
2270
if (_extension) {
2271
#ifdef TOOLS_ENABLED
2272
if (_extension->untrack_instance) {
2273
_extension->untrack_instance(_extension->tracking_userdata, this);
2274
}
2275
#endif
2276
if (_extension->free_instance) {
2277
_extension->free_instance(_extension->class_userdata, _extension_instance);
2278
}
2279
_extension = nullptr;
2280
_extension_instance = nullptr;
2281
}
2282
#ifdef TOOLS_ENABLED
2283
else if (_instance_bindings != nullptr) {
2284
Engine *engine = Engine::get_singleton();
2285
GDExtensionManager *gdextension_manager = GDExtensionManager::get_singleton();
2286
if (engine && gdextension_manager && engine->is_extension_reloading_enabled()) {
2287
for (uint32_t i = 0; i < _instance_binding_count; i++) {
2288
gdextension_manager->untrack_instance_binding(_instance_bindings[i].token, this);
2289
}
2290
}
2291
}
2292
#endif
2293
2294
if (_emitting) {
2295
//@todo this may need to actually reach the debugger prioritarily somehow because it may crash before
2296
ERR_PRINT(vformat("Object '%s' was freed or unreferenced while a signal is being emitted from it. Try connecting to the signal using 'CONNECT_DEFERRED' flag, or use queue_free() to free the object (if this object is a Node) to avoid this error and potential crashes.", to_string()));
2297
}
2298
2299
{
2300
OBJ_SIGNAL_LOCK
2301
// Drop all connections to the signals of this object.
2302
while (signal_map.size()) {
2303
// Avoid regular iteration so erasing is safe.
2304
KeyValue<StringName, SignalData> &E = *signal_map.begin();
2305
SignalData *s = &E.value;
2306
2307
for (const KeyValue<Callable, SignalData::Slot> &slot_kv : s->slot_map) {
2308
Object *target = slot_kv.value.conn.callable.get_object();
2309
if (likely(target)) {
2310
target->connections.erase(slot_kv.value.cE);
2311
}
2312
}
2313
2314
signal_map.erase(E.key);
2315
}
2316
2317
// Disconnect signals that connect to this object.
2318
while (connections.size()) {
2319
Connection c = connections.front()->get();
2320
Object *obj = c.callable.get_object();
2321
bool disconnected = false;
2322
if (likely(obj)) {
2323
disconnected = c.signal.get_object()->_disconnect(c.signal.get_name(), c.callable, true);
2324
}
2325
if (unlikely(!disconnected)) {
2326
// If the disconnect has failed, abandon the connection to avoid getting trapped in an infinite loop here.
2327
connections.pop_front();
2328
}
2329
}
2330
}
2331
2332
if (_instance_id != ObjectID()) {
2333
ObjectDB::remove_instance(this);
2334
_instance_id = ObjectID();
2335
}
2336
_predelete_ok = 2;
2337
2338
if (_instance_bindings != nullptr) {
2339
for (uint32_t i = 0; i < _instance_binding_count; i++) {
2340
if (_instance_bindings[i].free_callback) {
2341
_instance_bindings[i].free_callback(_instance_bindings[i].token, this, _instance_bindings[i].binding);
2342
}
2343
}
2344
memfree(_instance_bindings);
2345
}
2346
2347
if (signal_mutex) {
2348
memdelete(signal_mutex);
2349
}
2350
}
2351
2352
bool predelete_handler(Object *p_object) {
2353
return p_object->_predelete();
2354
}
2355
2356
void postinitialize_handler(Object *p_object) {
2357
p_object->_initialize();
2358
p_object->_postinitialize();
2359
}
2360
2361
void ObjectDB::debug_objects(DebugFunc p_func) {
2362
spin_lock.lock();
2363
2364
for (uint32_t i = 0, count = slot_count; i < slot_max && count != 0; i++) {
2365
if (object_slots[i].validator) {
2366
p_func(object_slots[i].object);
2367
count--;
2368
}
2369
}
2370
spin_lock.unlock();
2371
}
2372
2373
#ifdef TOOLS_ENABLED
2374
void Object::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const {
2375
const String pf = p_function;
2376
if (p_idx == 0) {
2377
if (pf == "connect" || pf == "is_connected" || pf == "disconnect" || pf == "emit_signal" || pf == "has_signal") {
2378
List<MethodInfo> signals;
2379
get_signal_list(&signals);
2380
for (const MethodInfo &E : signals) {
2381
r_options->push_back(E.name.quote());
2382
}
2383
} else if (pf == "call" || pf == "call_deferred" || pf == "callv" || pf == "has_method") {
2384
List<MethodInfo> methods;
2385
get_method_list(&methods);
2386
for (const MethodInfo &E : methods) {
2387
if (E.name.begins_with("_") && !(E.flags & METHOD_FLAG_VIRTUAL)) {
2388
continue;
2389
}
2390
r_options->push_back(E.name.quote());
2391
}
2392
} else if (pf == "set" || pf == "set_deferred" || pf == "get") {
2393
List<PropertyInfo> properties;
2394
get_property_list(&properties);
2395
for (const PropertyInfo &E : properties) {
2396
if (E.usage & PROPERTY_USAGE_DEFAULT && !(E.usage & PROPERTY_USAGE_INTERNAL)) {
2397
r_options->push_back(E.name.quote());
2398
}
2399
}
2400
} else if (pf == "set_meta" || pf == "get_meta" || pf == "has_meta" || pf == "remove_meta") {
2401
for (const KeyValue<StringName, Variant> &K : metadata) {
2402
r_options->push_back(String(K.key).quote());
2403
}
2404
}
2405
} else if (p_idx == 2) {
2406
if (pf == "connect") {
2407
// Ideally, the constants should be inferred by the parameter.
2408
// But a parameter's PropertyInfo does not store the enum they come from, so this will do for now.
2409
List<StringName> constants;
2410
ClassDB::get_enum_constants("Object", "ConnectFlags", &constants);
2411
for (const StringName &E : constants) {
2412
r_options->push_back(String(E));
2413
}
2414
}
2415
}
2416
}
2417
#endif
2418
2419
SpinLock ObjectDB::spin_lock;
2420
uint32_t ObjectDB::slot_count = 0;
2421
uint32_t ObjectDB::slot_max = 0;
2422
ObjectDB::ObjectSlot *ObjectDB::object_slots = nullptr;
2423
uint64_t ObjectDB::validator_counter = 0;
2424
2425
int ObjectDB::get_object_count() {
2426
return slot_count;
2427
}
2428
2429
ObjectID ObjectDB::add_instance(Object *p_object) {
2430
spin_lock.lock();
2431
if (unlikely(slot_count == slot_max)) {
2432
CRASH_COND(slot_count == (1 << OBJECTDB_SLOT_MAX_COUNT_BITS));
2433
2434
uint32_t new_slot_max = slot_max > 0 ? slot_max * 2 : 1;
2435
object_slots = (ObjectSlot *)memrealloc(object_slots, sizeof(ObjectSlot) * new_slot_max);
2436
for (uint32_t i = slot_max; i < new_slot_max; i++) {
2437
object_slots[i].object = nullptr;
2438
object_slots[i].is_ref_counted = false;
2439
object_slots[i].next_free = i;
2440
object_slots[i].validator = 0;
2441
}
2442
slot_max = new_slot_max;
2443
}
2444
2445
uint32_t slot = object_slots[slot_count].next_free;
2446
if (object_slots[slot].object != nullptr) {
2447
spin_lock.unlock();
2448
ERR_FAIL_COND_V(object_slots[slot].object != nullptr, ObjectID());
2449
}
2450
object_slots[slot].object = p_object;
2451
object_slots[slot].is_ref_counted = p_object->is_ref_counted();
2452
validator_counter = (validator_counter + 1) & OBJECTDB_VALIDATOR_MASK;
2453
if (unlikely(validator_counter == 0)) {
2454
validator_counter = 1;
2455
}
2456
object_slots[slot].validator = validator_counter;
2457
2458
uint64_t id = validator_counter;
2459
id <<= OBJECTDB_SLOT_MAX_COUNT_BITS;
2460
id |= uint64_t(slot);
2461
2462
if (p_object->is_ref_counted()) {
2463
id |= OBJECTDB_REFERENCE_BIT;
2464
}
2465
2466
slot_count++;
2467
2468
spin_lock.unlock();
2469
2470
return ObjectID(id);
2471
}
2472
2473
void ObjectDB::remove_instance(Object *p_object) {
2474
uint64_t t = p_object->get_instance_id();
2475
uint32_t slot = t & OBJECTDB_SLOT_MAX_COUNT_MASK; //slot is always valid on valid object
2476
2477
spin_lock.lock();
2478
2479
#ifdef DEBUG_ENABLED
2480
2481
if (object_slots[slot].object != p_object) {
2482
spin_lock.unlock();
2483
ERR_FAIL_COND(object_slots[slot].object != p_object);
2484
}
2485
{
2486
uint64_t validator = (t >> OBJECTDB_SLOT_MAX_COUNT_BITS) & OBJECTDB_VALIDATOR_MASK;
2487
if (object_slots[slot].validator != validator) {
2488
spin_lock.unlock();
2489
ERR_FAIL_COND(object_slots[slot].validator != validator);
2490
}
2491
}
2492
2493
#endif
2494
//decrease slot count
2495
slot_count--;
2496
//set the free slot properly
2497
object_slots[slot_count].next_free = slot;
2498
//invalidate, so checks against it fail
2499
object_slots[slot].validator = 0;
2500
object_slots[slot].is_ref_counted = false;
2501
object_slots[slot].object = nullptr;
2502
2503
spin_lock.unlock();
2504
}
2505
2506
void ObjectDB::setup() {
2507
//nothing to do now
2508
}
2509
2510
void ObjectDB::cleanup() {
2511
spin_lock.lock();
2512
2513
if (slot_count > 0) {
2514
WARN_PRINT("ObjectDB instances leaked at exit (run with --verbose for details).");
2515
if (OS::get_singleton()->is_stdout_verbose()) {
2516
// Ensure calling the native classes because if a leaked instance has a script
2517
// that overrides any of those methods, it'd not be OK to call them at this point,
2518
// now the scripting languages have already been terminated.
2519
MethodBind *node_get_path = ClassDB::get_method("Node", "get_path");
2520
MethodBind *resource_get_path = ClassDB::get_method("Resource", "get_path");
2521
Callable::CallError call_error;
2522
2523
for (uint32_t i = 0, count = slot_count; i < slot_max && count != 0; i++) {
2524
if (object_slots[i].validator) {
2525
Object *obj = object_slots[i].object;
2526
2527
String extra_info;
2528
if (obj->is_class("Node")) {
2529
extra_info = " - Node path: " + String(node_get_path->call(obj, nullptr, 0, call_error));
2530
}
2531
if (obj->is_class("Resource")) {
2532
extra_info = " - Resource path: " + String(resource_get_path->call(obj, nullptr, 0, call_error));
2533
}
2534
2535
uint64_t id = uint64_t(i) | (uint64_t(object_slots[i].validator) << OBJECTDB_SLOT_MAX_COUNT_BITS) | (object_slots[i].is_ref_counted ? OBJECTDB_REFERENCE_BIT : 0);
2536
DEV_ASSERT(id == (uint64_t)obj->get_instance_id()); // We could just use the id from the object, but this check may help catching memory corruption catastrophes.
2537
print_line("Leaked instance: " + String(obj->get_class()) + ":" + uitos(id) + extra_info);
2538
2539
count--;
2540
}
2541
}
2542
print_line("Hint: Leaked instances typically happen when nodes are removed from the scene tree (with `remove_child()`) but not freed (with `free()` or `queue_free()`).");
2543
}
2544
}
2545
2546
if (object_slots) {
2547
memfree(object_slots);
2548
}
2549
2550
spin_lock.unlock();
2551
}
2552
2553