1 /*************************************************************************/
2 /*  object.cpp                                                           */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
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/class_db.h"
34 #include "core/core_string_names.h"
35 #include "core/message_queue.h"
36 #include "core/object_rc.h"
37 #include "core/os/os.h"
38 #include "core/print_string.h"
39 #include "core/resource.h"
40 #include "core/script_language.h"
41 #include "core/translation.h"
42 
43 #ifdef DEBUG_ENABLED
44 
45 struct _ObjectDebugLock {
46 
47 	Object *obj;
48 
_ObjectDebugLock_ObjectDebugLock49 	_ObjectDebugLock(Object *p_obj) {
50 		obj = p_obj;
51 		obj->_lock_index.ref();
52 	}
~_ObjectDebugLock_ObjectDebugLock53 	~_ObjectDebugLock() {
54 		obj->_lock_index.unref();
55 	}
56 };
57 
58 #define OBJ_DEBUG_LOCK _ObjectDebugLock _debug_lock(this);
59 
60 #else
61 
62 #define OBJ_DEBUG_LOCK
63 
64 #endif
65 
operator Dictionary() const66 PropertyInfo::operator Dictionary() const {
67 
68 	Dictionary d;
69 	d["name"] = name;
70 	d["class_name"] = class_name;
71 	d["type"] = type;
72 	d["hint"] = hint;
73 	d["hint_string"] = hint_string;
74 	d["usage"] = usage;
75 	return d;
76 }
77 
from_dict(const Dictionary & p_dict)78 PropertyInfo PropertyInfo::from_dict(const Dictionary &p_dict) {
79 
80 	PropertyInfo pi;
81 
82 	if (p_dict.has("type"))
83 		pi.type = Variant::Type(int(p_dict["type"]));
84 
85 	if (p_dict.has("name"))
86 		pi.name = p_dict["name"];
87 
88 	if (p_dict.has("class_name"))
89 		pi.class_name = p_dict["class_name"];
90 
91 	if (p_dict.has("hint"))
92 		pi.hint = PropertyHint(int(p_dict["hint"]));
93 
94 	if (p_dict.has("hint_string"))
95 
96 		pi.hint_string = p_dict["hint_string"];
97 
98 	if (p_dict.has("usage"))
99 		pi.usage = p_dict["usage"];
100 
101 	return pi;
102 }
103 
convert_property_list(const List<PropertyInfo> * p_list)104 Array convert_property_list(const List<PropertyInfo> *p_list) {
105 
106 	Array va;
107 	for (const List<PropertyInfo>::Element *E = p_list->front(); E; E = E->next()) {
108 
109 		va.push_back(Dictionary(E->get()));
110 	}
111 
112 	return va;
113 }
114 
operator Dictionary() const115 MethodInfo::operator Dictionary() const {
116 
117 	Dictionary d;
118 	d["name"] = name;
119 	d["args"] = convert_property_list(&arguments);
120 	Array da;
121 	for (int i = 0; i < default_arguments.size(); i++)
122 		da.push_back(default_arguments[i]);
123 	d["default_args"] = da;
124 	d["flags"] = flags;
125 	d["id"] = id;
126 	Dictionary r = return_val;
127 	d["return"] = r;
128 	return d;
129 }
130 
MethodInfo()131 MethodInfo::MethodInfo() :
132 		flags(METHOD_FLAG_NORMAL),
133 		id(0) {
134 }
135 
from_dict(const Dictionary & p_dict)136 MethodInfo MethodInfo::from_dict(const Dictionary &p_dict) {
137 
138 	MethodInfo mi;
139 
140 	if (p_dict.has("name"))
141 		mi.name = p_dict["name"];
142 	Array args;
143 	if (p_dict.has("args")) {
144 		args = p_dict["args"];
145 	}
146 
147 	for (int i = 0; i < args.size(); i++) {
148 		Dictionary d = args[i];
149 		mi.arguments.push_back(PropertyInfo::from_dict(d));
150 	}
151 	Array defargs;
152 	if (p_dict.has("default_args")) {
153 		defargs = p_dict["default_args"];
154 	}
155 	for (int i = 0; i < defargs.size(); i++) {
156 		mi.default_arguments.push_back(defargs[i]);
157 	}
158 
159 	if (p_dict.has("return")) {
160 		mi.return_val = PropertyInfo::from_dict(p_dict["return"]);
161 	}
162 
163 	if (p_dict.has("flags"))
164 		mi.flags = p_dict["flags"];
165 
166 	return mi;
167 }
168 
MethodInfo(const String & p_name)169 MethodInfo::MethodInfo(const String &p_name) :
170 		name(p_name),
171 		flags(METHOD_FLAG_NORMAL),
172 		id(0) {
173 }
MethodInfo(const String & p_name,const PropertyInfo & p_param1)174 MethodInfo::MethodInfo(const String &p_name, const PropertyInfo &p_param1) :
175 		name(p_name),
176 		flags(METHOD_FLAG_NORMAL),
177 		id(0) {
178 	arguments.push_back(p_param1);
179 }
MethodInfo(const String & p_name,const PropertyInfo & p_param1,const PropertyInfo & p_param2)180 MethodInfo::MethodInfo(const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2) :
181 		name(p_name),
182 		flags(METHOD_FLAG_NORMAL),
183 		id(0) {
184 	arguments.push_back(p_param1);
185 	arguments.push_back(p_param2);
186 }
187 
MethodInfo(const String & p_name,const PropertyInfo & p_param1,const PropertyInfo & p_param2,const PropertyInfo & p_param3)188 MethodInfo::MethodInfo(const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3) :
189 		name(p_name),
190 		flags(METHOD_FLAG_NORMAL),
191 		id(0) {
192 	arguments.push_back(p_param1);
193 	arguments.push_back(p_param2);
194 	arguments.push_back(p_param3);
195 }
196 
MethodInfo(const String & p_name,const PropertyInfo & p_param1,const PropertyInfo & p_param2,const PropertyInfo & p_param3,const PropertyInfo & p_param4)197 MethodInfo::MethodInfo(const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4) :
198 		name(p_name),
199 		flags(METHOD_FLAG_NORMAL),
200 		id(0) {
201 	arguments.push_back(p_param1);
202 	arguments.push_back(p_param2);
203 	arguments.push_back(p_param3);
204 	arguments.push_back(p_param4);
205 }
206 
MethodInfo(const String & p_name,const PropertyInfo & p_param1,const PropertyInfo & p_param2,const PropertyInfo & p_param3,const PropertyInfo & p_param4,const PropertyInfo & p_param5)207 MethodInfo::MethodInfo(const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4, const PropertyInfo &p_param5) :
208 		name(p_name),
209 		flags(METHOD_FLAG_NORMAL),
210 		id(0) {
211 	arguments.push_back(p_param1);
212 	arguments.push_back(p_param2);
213 	arguments.push_back(p_param3);
214 	arguments.push_back(p_param4);
215 	arguments.push_back(p_param5);
216 }
217 
MethodInfo(Variant::Type ret)218 MethodInfo::MethodInfo(Variant::Type ret) :
219 		flags(METHOD_FLAG_NORMAL),
220 		id(0) {
221 	return_val.type = ret;
222 }
223 
MethodInfo(Variant::Type ret,const String & p_name)224 MethodInfo::MethodInfo(Variant::Type ret, const String &p_name) :
225 		name(p_name),
226 		flags(METHOD_FLAG_NORMAL),
227 		id(0) {
228 	return_val.type = ret;
229 }
MethodInfo(Variant::Type ret,const String & p_name,const PropertyInfo & p_param1)230 MethodInfo::MethodInfo(Variant::Type ret, const String &p_name, const PropertyInfo &p_param1) :
231 		name(p_name),
232 		flags(METHOD_FLAG_NORMAL),
233 		id(0) {
234 	return_val.type = ret;
235 	arguments.push_back(p_param1);
236 }
MethodInfo(Variant::Type ret,const String & p_name,const PropertyInfo & p_param1,const PropertyInfo & p_param2)237 MethodInfo::MethodInfo(Variant::Type ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2) :
238 		name(p_name),
239 		flags(METHOD_FLAG_NORMAL),
240 		id(0) {
241 	return_val.type = ret;
242 	arguments.push_back(p_param1);
243 	arguments.push_back(p_param2);
244 }
245 
MethodInfo(Variant::Type ret,const String & p_name,const PropertyInfo & p_param1,const PropertyInfo & p_param2,const PropertyInfo & p_param3)246 MethodInfo::MethodInfo(Variant::Type ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3) :
247 		name(p_name),
248 		flags(METHOD_FLAG_NORMAL),
249 		id(0) {
250 	return_val.type = ret;
251 	arguments.push_back(p_param1);
252 	arguments.push_back(p_param2);
253 	arguments.push_back(p_param3);
254 }
255 
MethodInfo(Variant::Type ret,const String & p_name,const PropertyInfo & p_param1,const PropertyInfo & p_param2,const PropertyInfo & p_param3,const PropertyInfo & p_param4)256 MethodInfo::MethodInfo(Variant::Type ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4) :
257 		name(p_name),
258 		flags(METHOD_FLAG_NORMAL),
259 		id(0) {
260 	return_val.type = ret;
261 	arguments.push_back(p_param1);
262 	arguments.push_back(p_param2);
263 	arguments.push_back(p_param3);
264 	arguments.push_back(p_param4);
265 }
266 
MethodInfo(Variant::Type ret,const String & p_name,const PropertyInfo & p_param1,const PropertyInfo & p_param2,const PropertyInfo & p_param3,const PropertyInfo & p_param4,const PropertyInfo & p_param5)267 MethodInfo::MethodInfo(Variant::Type ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4, const PropertyInfo &p_param5) :
268 		name(p_name),
269 		flags(METHOD_FLAG_NORMAL),
270 		id(0) {
271 	return_val.type = ret;
272 	arguments.push_back(p_param1);
273 	arguments.push_back(p_param2);
274 	arguments.push_back(p_param3);
275 	arguments.push_back(p_param4);
276 	arguments.push_back(p_param5);
277 }
278 
MethodInfo(const PropertyInfo & p_ret,const String & p_name)279 MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name) :
280 		name(p_name),
281 		return_val(p_ret),
282 		flags(METHOD_FLAG_NORMAL),
283 		id(0) {
284 }
285 
MethodInfo(const PropertyInfo & p_ret,const String & p_name,const PropertyInfo & p_param1)286 MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1) :
287 		name(p_name),
288 		return_val(p_ret),
289 		flags(METHOD_FLAG_NORMAL),
290 		id(0) {
291 	arguments.push_back(p_param1);
292 }
293 
MethodInfo(const PropertyInfo & p_ret,const String & p_name,const PropertyInfo & p_param1,const PropertyInfo & p_param2)294 MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2) :
295 		name(p_name),
296 		return_val(p_ret),
297 		flags(METHOD_FLAG_NORMAL),
298 		id(0) {
299 	arguments.push_back(p_param1);
300 	arguments.push_back(p_param2);
301 }
302 
MethodInfo(const PropertyInfo & p_ret,const String & p_name,const PropertyInfo & p_param1,const PropertyInfo & p_param2,const PropertyInfo & p_param3)303 MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3) :
304 		name(p_name),
305 		return_val(p_ret),
306 		flags(METHOD_FLAG_NORMAL),
307 		id(0) {
308 	arguments.push_back(p_param1);
309 	arguments.push_back(p_param2);
310 	arguments.push_back(p_param3);
311 }
312 
MethodInfo(const PropertyInfo & p_ret,const String & p_name,const PropertyInfo & p_param1,const PropertyInfo & p_param2,const PropertyInfo & p_param3,const PropertyInfo & p_param4)313 MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4) :
314 		name(p_name),
315 		return_val(p_ret),
316 		flags(METHOD_FLAG_NORMAL),
317 		id(0) {
318 	arguments.push_back(p_param1);
319 	arguments.push_back(p_param2);
320 	arguments.push_back(p_param3);
321 	arguments.push_back(p_param4);
322 }
323 
MethodInfo(const PropertyInfo & p_ret,const String & p_name,const PropertyInfo & p_param1,const PropertyInfo & p_param2,const PropertyInfo & p_param3,const PropertyInfo & p_param4,const PropertyInfo & p_param5)324 MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4, const PropertyInfo &p_param5) :
325 		name(p_name),
326 		return_val(p_ret),
327 		flags(METHOD_FLAG_NORMAL),
328 		id(0) {
329 	arguments.push_back(p_param1);
330 	arguments.push_back(p_param2);
331 	arguments.push_back(p_param3);
332 	arguments.push_back(p_param4);
333 	arguments.push_back(p_param5);
334 }
335 
operator Variant() const336 Object::Connection::operator Variant() const {
337 
338 	Dictionary d;
339 	d["source"] = source;
340 	d["signal"] = signal;
341 	d["target"] = target;
342 	d["method"] = method;
343 	d["flags"] = flags;
344 	d["binds"] = binds;
345 	return d;
346 }
347 
operator <(const Connection & p_conn) const348 bool Object::Connection::operator<(const Connection &p_conn) const {
349 
350 	if (source == p_conn.source) {
351 
352 		if (signal == p_conn.signal) {
353 
354 			if (target == p_conn.target) {
355 
356 				return method < p_conn.method;
357 			} else {
358 
359 				return target < p_conn.target;
360 			}
361 		} else
362 			return signal < p_conn.signal;
363 	} else {
364 		return source < p_conn.source;
365 	}
366 }
Connection(const Variant & p_variant)367 Object::Connection::Connection(const Variant &p_variant) {
368 
369 	Dictionary d = p_variant;
370 	if (d.has("source"))
371 		source = d["source"];
372 	if (d.has("signal"))
373 		signal = d["signal"];
374 	if (d.has("target"))
375 		target = d["target"];
376 	if (d.has("method"))
377 		method = d["method"];
378 	if (d.has("flags"))
379 		flags = d["flags"];
380 	if (d.has("binds"))
381 		binds = d["binds"];
382 }
383 
_predelete()384 bool Object::_predelete() {
385 
386 	_predelete_ok = 1;
387 	notification(NOTIFICATION_PREDELETE, true);
388 	if (_predelete_ok) {
389 		_class_ptr = NULL; //must restore so destructors can access class ptr correctly
390 	}
391 	return _predelete_ok;
392 }
393 
_postinitialize()394 void Object::_postinitialize() {
395 	_class_ptr = _get_class_namev();
396 	_initialize_classv();
397 	notification(NOTIFICATION_POSTINITIALIZE);
398 }
399 
get_valid_parents_static(List<String> * p_parents)400 void Object::get_valid_parents_static(List<String> *p_parents) {
401 }
_get_valid_parents_static(List<String> * p_parents)402 void Object::_get_valid_parents_static(List<String> *p_parents) {
403 }
404 
set(const StringName & p_name,const Variant & p_value,bool * r_valid)405 void Object::set(const StringName &p_name, const Variant &p_value, bool *r_valid) {
406 
407 #ifdef TOOLS_ENABLED
408 
409 	_edited = true;
410 #endif
411 
412 	if (script_instance) {
413 
414 		if (script_instance->set(p_name, p_value)) {
415 			if (r_valid)
416 				*r_valid = true;
417 			return;
418 		}
419 	}
420 
421 	//try built-in setgetter
422 	{
423 		if (ClassDB::set_property(this, p_name, p_value, r_valid)) {
424 			/*
425 			if (r_valid)
426 				*r_valid=true;
427 			*/
428 			return;
429 		}
430 	}
431 
432 	if (p_name == CoreStringNames::get_singleton()->_script) {
433 		set_script(p_value);
434 		if (r_valid)
435 			*r_valid = true;
436 		return;
437 
438 	} else if (p_name == CoreStringNames::get_singleton()->_meta) {
439 		//set_meta(p_name,p_value);
440 		metadata = p_value.duplicate();
441 		if (r_valid)
442 			*r_valid = true;
443 		return;
444 	}
445 
446 	//something inside the object... :|
447 	bool success = _setv(p_name, p_value);
448 	if (success) {
449 		if (r_valid)
450 			*r_valid = true;
451 		return;
452 	}
453 
454 	{
455 		bool valid;
456 		setvar(p_name, p_value, &valid);
457 		if (valid) {
458 			if (r_valid)
459 				*r_valid = true;
460 			return;
461 		}
462 	}
463 
464 #ifdef TOOLS_ENABLED
465 	if (script_instance) {
466 		bool valid;
467 		script_instance->property_set_fallback(p_name, p_value, &valid);
468 		if (valid) {
469 			if (r_valid)
470 				*r_valid = true;
471 			return;
472 		}
473 	}
474 #endif
475 
476 	if (r_valid)
477 		*r_valid = false;
478 }
479 
get(const StringName & p_name,bool * r_valid) const480 Variant Object::get(const StringName &p_name, bool *r_valid) const {
481 
482 	Variant ret;
483 
484 	if (script_instance) {
485 
486 		if (script_instance->get(p_name, ret)) {
487 			if (r_valid)
488 				*r_valid = true;
489 			return ret;
490 		}
491 	}
492 
493 	//try built-in setgetter
494 	{
495 		if (ClassDB::get_property(const_cast<Object *>(this), p_name, ret)) {
496 			if (r_valid)
497 				*r_valid = true;
498 			return ret;
499 		}
500 	}
501 
502 	if (p_name == CoreStringNames::get_singleton()->_script) {
503 		ret = get_script();
504 		if (r_valid)
505 			*r_valid = true;
506 		return ret;
507 
508 	} else if (p_name == CoreStringNames::get_singleton()->_meta) {
509 		ret = metadata;
510 		if (r_valid)
511 			*r_valid = true;
512 		return ret;
513 
514 	} else {
515 		//something inside the object... :|
516 		bool success = _getv(p_name, ret);
517 		if (success) {
518 			if (r_valid)
519 				*r_valid = true;
520 			return ret;
521 		}
522 
523 		//if nothing else, use getvar
524 		{
525 			bool valid;
526 			ret = getvar(p_name, &valid);
527 			if (valid) {
528 				if (r_valid)
529 					*r_valid = true;
530 				return ret;
531 			}
532 		}
533 
534 #ifdef TOOLS_ENABLED
535 		if (script_instance) {
536 			bool valid;
537 			ret = script_instance->property_get_fallback(p_name, &valid);
538 			if (valid) {
539 				if (r_valid)
540 					*r_valid = true;
541 				return ret;
542 			}
543 		}
544 #endif
545 
546 		if (r_valid)
547 			*r_valid = false;
548 		return Variant();
549 	}
550 }
551 
set_indexed(const Vector<StringName> & p_names,const Variant & p_value,bool * r_valid)552 void Object::set_indexed(const Vector<StringName> &p_names, const Variant &p_value, bool *r_valid) {
553 	if (p_names.empty()) {
554 		if (r_valid)
555 			*r_valid = false;
556 		return;
557 	}
558 	if (p_names.size() == 1) {
559 		set(p_names[0], p_value, r_valid);
560 		return;
561 	}
562 
563 	bool valid = false;
564 	if (!r_valid) r_valid = &valid;
565 
566 	List<Variant> value_stack;
567 
568 	value_stack.push_back(get(p_names[0], r_valid));
569 
570 	if (!*r_valid) {
571 		value_stack.clear();
572 		return;
573 	}
574 
575 	for (int i = 1; i < p_names.size() - 1; i++) {
576 		value_stack.push_back(value_stack.back()->get().get_named(p_names[i], r_valid));
577 
578 		if (!*r_valid) {
579 			value_stack.clear();
580 			return;
581 		}
582 	}
583 
584 	value_stack.push_back(p_value); // p_names[p_names.size() - 1]
585 
586 	for (int i = p_names.size() - 1; i > 0; i--) {
587 
588 		value_stack.back()->prev()->get().set_named(p_names[i], value_stack.back()->get(), r_valid);
589 		value_stack.pop_back();
590 
591 		if (!*r_valid) {
592 			value_stack.clear();
593 			return;
594 		}
595 	}
596 
597 	set(p_names[0], value_stack.back()->get(), r_valid);
598 	value_stack.pop_back();
599 
600 	ERR_FAIL_COND(!value_stack.empty());
601 }
602 
get_indexed(const Vector<StringName> & p_names,bool * r_valid) const603 Variant Object::get_indexed(const Vector<StringName> &p_names, bool *r_valid) const {
604 	if (p_names.empty()) {
605 		if (r_valid)
606 			*r_valid = false;
607 		return Variant();
608 	}
609 	bool valid = false;
610 
611 	Variant current_value = get(p_names[0], &valid);
612 	for (int i = 1; i < p_names.size(); i++) {
613 		current_value = current_value.get_named(p_names[i], &valid);
614 
615 		if (!valid)
616 			break;
617 	}
618 	if (r_valid)
619 		*r_valid = valid;
620 
621 	return current_value;
622 }
623 
get_property_list(List<PropertyInfo> * p_list,bool p_reversed) const624 void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) const {
625 
626 	if (script_instance && p_reversed) {
627 		p_list->push_back(PropertyInfo(Variant::NIL, "Script Variables", PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY));
628 		script_instance->get_property_list(p_list);
629 	}
630 
631 	_get_property_listv(p_list, p_reversed);
632 
633 	if (!is_class("Script")) { // can still be set, but this is for userfriendlyness
634 #ifdef TOOLS_ENABLED
635 		p_list->push_back(PropertyInfo(Variant::NIL, "Script", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
636 #endif
637 		p_list->push_back(PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script", PROPERTY_USAGE_DEFAULT));
638 	}
639 	if (!metadata.empty()) {
640 		p_list->push_back(PropertyInfo(Variant::DICTIONARY, "__meta__", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
641 	}
642 	if (script_instance && !p_reversed) {
643 		p_list->push_back(PropertyInfo(Variant::NIL, "Script Variables", PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY));
644 		script_instance->get_property_list(p_list);
645 	}
646 }
647 
_validate_property(PropertyInfo & property) const648 void Object::_validate_property(PropertyInfo &property) const {
649 }
650 
get_method_list(List<MethodInfo> * p_list) const651 void Object::get_method_list(List<MethodInfo> *p_list) const {
652 
653 	ClassDB::get_method_list(get_class_name(), p_list);
654 	if (script_instance) {
655 		script_instance->get_method_list(p_list);
656 	}
657 }
658 
_call_bind(const Variant ** p_args,int p_argcount,Variant::CallError & r_error)659 Variant Object::_call_bind(const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
660 
661 	if (p_argcount < 1) {
662 		r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
663 		r_error.argument = 0;
664 		return Variant();
665 	}
666 
667 	if (p_args[0]->get_type() != Variant::STRING) {
668 		r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
669 		r_error.argument = 0;
670 		r_error.expected = Variant::STRING;
671 		return Variant();
672 	}
673 
674 	StringName method = *p_args[0];
675 
676 	return call(method, &p_args[1], p_argcount - 1, r_error);
677 }
678 
_call_deferred_bind(const Variant ** p_args,int p_argcount,Variant::CallError & r_error)679 Variant Object::_call_deferred_bind(const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
680 
681 	if (p_argcount < 1) {
682 		r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
683 		r_error.argument = 0;
684 		return Variant();
685 	}
686 
687 	if (p_args[0]->get_type() != Variant::STRING) {
688 		r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
689 		r_error.argument = 0;
690 		r_error.expected = Variant::STRING;
691 		return Variant();
692 	}
693 
694 	r_error.error = Variant::CallError::CALL_OK;
695 
696 	StringName method = *p_args[0];
697 
698 	MessageQueue::get_singleton()->push_call(get_instance_id(), method, &p_args[1], p_argcount - 1, true);
699 
700 	return Variant();
701 }
702 
703 #ifdef DEBUG_ENABLED
_test_call_error(const StringName & p_func,const Variant::CallError & error)704 static void _test_call_error(const StringName &p_func, const Variant::CallError &error) {
705 
706 	switch (error.error) {
707 
708 		case Variant::CallError::CALL_OK:
709 		case Variant::CallError::CALL_ERROR_INVALID_METHOD:
710 			break;
711 		case Variant::CallError::CALL_ERROR_INVALID_ARGUMENT: {
712 
713 			ERR_FAIL_MSG("Error calling function: " + String(p_func) + " - Invalid type for argument " + itos(error.argument) + ", expected " + Variant::get_type_name(error.expected) + ".");
714 			break;
715 		}
716 		case Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS: {
717 
718 			ERR_FAIL_MSG("Error calling function: " + String(p_func) + " - Too many arguments, expected " + itos(error.argument) + ".");
719 			break;
720 		}
721 		case Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS: {
722 
723 			ERR_FAIL_MSG("Error calling function: " + String(p_func) + " - Too few arguments, expected " + itos(error.argument) + ".");
724 			break;
725 		}
726 		case Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL:
727 			break;
728 	}
729 }
730 #else
731 
732 #define _test_call_error(m_str, m_err)
733 
734 #endif
735 
call_multilevel(const StringName & p_method,const Variant ** p_args,int p_argcount)736 void Object::call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount) {
737 
738 	if (p_method == CoreStringNames::get_singleton()->_free) {
739 #ifdef DEBUG_ENABLED
740 		ERR_FAIL_COND_MSG(Object::cast_to<Reference>(this), "Can't 'free' a reference.");
741 
742 		ERR_FAIL_COND_MSG(_lock_index.get() > 1, "Object is locked and can't be freed.");
743 #endif
744 
745 		//must be here, must be before everything,
746 		memdelete(this);
747 		return;
748 	}
749 
750 	//Variant ret;
751 	OBJ_DEBUG_LOCK
752 
753 	Variant::CallError error;
754 
755 	if (script_instance) {
756 		script_instance->call_multilevel(p_method, p_args, p_argcount);
757 		//_test_call_error(p_method,error);
758 	}
759 
760 	MethodBind *method = ClassDB::get_method(get_class_name(), p_method);
761 
762 	if (method) {
763 
764 		method->call(this, p_args, p_argcount, error);
765 		_test_call_error(p_method, error);
766 	}
767 }
768 
call_multilevel_reversed(const StringName & p_method,const Variant ** p_args,int p_argcount)769 void Object::call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount) {
770 
771 	MethodBind *method = ClassDB::get_method(get_class_name(), p_method);
772 
773 	Variant::CallError error;
774 	OBJ_DEBUG_LOCK
775 
776 	if (method) {
777 
778 		method->call(this, p_args, p_argcount, error);
779 		_test_call_error(p_method, error);
780 	}
781 
782 	//Variant ret;
783 
784 	if (script_instance) {
785 		script_instance->call_multilevel_reversed(p_method, p_args, p_argcount);
786 		//_test_call_error(p_method,error);
787 	}
788 }
789 
has_method(const StringName & p_method) const790 bool Object::has_method(const StringName &p_method) const {
791 
792 	if (p_method == CoreStringNames::get_singleton()->_free) {
793 		return true;
794 	}
795 
796 	if (script_instance && script_instance->has_method(p_method)) {
797 		return true;
798 	}
799 
800 	MethodBind *method = ClassDB::get_method(get_class_name(), p_method);
801 
802 	return method != NULL;
803 }
804 
getvar(const Variant & p_key,bool * r_valid) const805 Variant Object::getvar(const Variant &p_key, bool *r_valid) const {
806 
807 	if (r_valid)
808 		*r_valid = false;
809 	return Variant();
810 }
setvar(const Variant & p_key,const Variant & p_value,bool * r_valid)811 void Object::setvar(const Variant &p_key, const Variant &p_value, bool *r_valid) {
812 
813 	if (r_valid)
814 		*r_valid = false;
815 }
816 
callv(const StringName & p_method,const Array & p_args)817 Variant Object::callv(const StringName &p_method, const Array &p_args) {
818 	const Variant **argptrs = NULL;
819 
820 	if (p_args.size() > 0) {
821 		argptrs = (const Variant **)alloca(sizeof(Variant *) * p_args.size());
822 		for (int i = 0; i < p_args.size(); i++) {
823 			argptrs[i] = &p_args[i];
824 		}
825 	}
826 
827 	Variant::CallError ce;
828 	Variant ret = call(p_method, argptrs, p_args.size(), ce);
829 	if (ce.error != Variant::CallError::CALL_OK) {
830 		ERR_FAIL_V_MSG(Variant(), "Error calling method from 'callv': " + Variant::get_call_error_text(this, p_method, argptrs, p_args.size(), ce) + ".");
831 	}
832 	return ret;
833 }
834 
call(const StringName & p_name,VARIANT_ARG_DECLARE)835 Variant Object::call(const StringName &p_name, VARIANT_ARG_DECLARE) {
836 
837 	VARIANT_ARGPTRS;
838 
839 	int argc = 0;
840 	for (int i = 0; i < VARIANT_ARG_MAX; i++) {
841 		if (argptr[i]->get_type() == Variant::NIL)
842 			break;
843 		argc++;
844 	}
845 
846 	Variant::CallError error;
847 
848 	Variant ret = call(p_name, argptr, argc, error);
849 	return ret;
850 }
851 
call_multilevel(const StringName & p_name,VARIANT_ARG_DECLARE)852 void Object::call_multilevel(const StringName &p_name, VARIANT_ARG_DECLARE) {
853 
854 	VARIANT_ARGPTRS;
855 
856 	int argc = 0;
857 	for (int i = 0; i < VARIANT_ARG_MAX; i++) {
858 		if (argptr[i]->get_type() == Variant::NIL)
859 			break;
860 		argc++;
861 	}
862 
863 	//Variant::CallError error;
864 	call_multilevel(p_name, argptr, argc);
865 }
866 
call(const StringName & p_method,const Variant ** p_args,int p_argcount,Variant::CallError & r_error)867 Variant Object::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
868 
869 	r_error.error = Variant::CallError::CALL_OK;
870 
871 	if (p_method == CoreStringNames::get_singleton()->_free) {
872 //free must be here, before anything, always ready
873 #ifdef DEBUG_ENABLED
874 		if (p_argcount != 0) {
875 			r_error.argument = 0;
876 			r_error.error = Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
877 			return Variant();
878 		}
879 		if (Object::cast_to<Reference>(this)) {
880 			r_error.argument = 0;
881 			r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
882 			ERR_FAIL_V_MSG(Variant(), "Can't 'free' a reference.");
883 		}
884 
885 		if (_lock_index.get() > 1) {
886 			r_error.argument = 0;
887 			r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
888 			ERR_FAIL_V_MSG(Variant(), "Object is locked and can't be freed.");
889 		}
890 
891 #endif
892 		//must be here, must be before everything,
893 		memdelete(this);
894 		r_error.error = Variant::CallError::CALL_OK;
895 		return Variant();
896 	}
897 
898 	Variant ret;
899 	OBJ_DEBUG_LOCK
900 	if (script_instance) {
901 		ret = script_instance->call(p_method, p_args, p_argcount, r_error);
902 		//force jumptable
903 		switch (r_error.error) {
904 
905 			case Variant::CallError::CALL_OK:
906 				return ret;
907 			case Variant::CallError::CALL_ERROR_INVALID_METHOD:
908 				break;
909 			case Variant::CallError::CALL_ERROR_INVALID_ARGUMENT:
910 			case Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS:
911 			case Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS:
912 				return ret;
913 			case Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL: {
914 			}
915 		}
916 	}
917 
918 	MethodBind *method = ClassDB::get_method(get_class_name(), p_method);
919 
920 	if (method) {
921 
922 		ret = method->call(this, p_args, p_argcount, r_error);
923 	} else {
924 		r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
925 	}
926 
927 	return ret;
928 }
929 
notification(int p_notification,bool p_reversed)930 void Object::notification(int p_notification, bool p_reversed) {
931 
932 	_notificationv(p_notification, p_reversed);
933 
934 	if (script_instance) {
935 		script_instance->notification(p_notification);
936 	}
937 }
938 
to_string()939 String Object::to_string() {
940 	if (script_instance) {
941 		bool valid;
942 		String ret = script_instance->to_string(&valid);
943 		if (valid)
944 			return ret;
945 	}
946 	return "[" + get_class() + ":" + itos(get_instance_id()) + "]";
947 }
948 
_changed_callback(Object * p_changed,const char * p_prop)949 void Object::_changed_callback(Object *p_changed, const char *p_prop) {
950 }
951 
add_change_receptor(Object * p_receptor)952 void Object::add_change_receptor(Object *p_receptor) {
953 
954 	change_receptors.insert(p_receptor);
955 }
956 
remove_change_receptor(Object * p_receptor)957 void Object::remove_change_receptor(Object *p_receptor) {
958 
959 	change_receptors.erase(p_receptor);
960 }
961 
property_list_changed_notify()962 void Object::property_list_changed_notify() {
963 
964 	_change_notify();
965 }
966 
cancel_delete()967 void Object::cancel_delete() {
968 
969 	_predelete_ok = true;
970 }
971 
972 #ifdef DEBUG_ENABLED
_use_rc()973 ObjectRC *Object::_use_rc() {
974 
975 	// The RC object is lazily created the first time it's requested;
976 	// that way, there's no need to allocate and release it at all if this Object
977 	// is not being referred by any Variant at all.
978 
979 	// Although when dealing with Objects from multiple threads some locking
980 	// mechanism should be used, this at least makes safe the case of first
981 	// assignment.
982 
983 	ObjectRC *rc = nullptr;
984 	ObjectRC *const creating = reinterpret_cast<ObjectRC *>(1);
985 	if (unlikely(_rc.compare_exchange_strong(rc, creating, std::memory_order_acq_rel))) {
986 		// Not created yet
987 		rc = memnew(ObjectRC(this));
988 		_rc.store(rc, std::memory_order_release);
989 		return rc;
990 	}
991 
992 	// Spin-wait until we know it's created (or just return if it's already created)
993 	for (;;) {
994 		if (likely(rc != creating)) {
995 			rc->increment();
996 			return rc;
997 		}
998 		rc = _rc.load(std::memory_order_acquire);
999 	}
1000 }
1001 #endif
1002 
set_script_and_instance(const RefPtr & p_script,ScriptInstance * p_instance)1003 void Object::set_script_and_instance(const RefPtr &p_script, ScriptInstance *p_instance) {
1004 
1005 	//this function is not meant to be used in any of these ways
1006 	ERR_FAIL_COND(p_script.is_null());
1007 	ERR_FAIL_COND(!p_instance);
1008 	ERR_FAIL_COND(script_instance != NULL || !script.is_null());
1009 
1010 	script = p_script;
1011 	script_instance = p_instance;
1012 }
1013 
set_script(const RefPtr & p_script)1014 void Object::set_script(const RefPtr &p_script) {
1015 
1016 	if (script == p_script)
1017 		return;
1018 
1019 	if (script_instance) {
1020 		memdelete(script_instance);
1021 		script_instance = NULL;
1022 	}
1023 
1024 	script = p_script;
1025 	Ref<Script> s(script);
1026 
1027 	if (!s.is_null()) {
1028 		if (s->can_instance()) {
1029 			OBJ_DEBUG_LOCK
1030 			script_instance = s->instance_create(this);
1031 		} else if (Engine::get_singleton()->is_editor_hint()) {
1032 			OBJ_DEBUG_LOCK
1033 			script_instance = s->placeholder_instance_create(this);
1034 		}
1035 	}
1036 
1037 	_change_notify(); //scripts may add variables, so refresh is desired
1038 	emit_signal(CoreStringNames::get_singleton()->script_changed);
1039 }
1040 
set_script_instance(ScriptInstance * p_instance)1041 void Object::set_script_instance(ScriptInstance *p_instance) {
1042 
1043 	if (script_instance == p_instance)
1044 		return;
1045 
1046 	if (script_instance)
1047 		memdelete(script_instance);
1048 
1049 	script_instance = p_instance;
1050 
1051 	if (p_instance)
1052 		script = p_instance->get_script().get_ref_ptr();
1053 	else
1054 		script = RefPtr();
1055 }
1056 
get_script() const1057 RefPtr Object::get_script() const {
1058 
1059 	return script;
1060 }
1061 
has_meta(const String & p_name) const1062 bool Object::has_meta(const String &p_name) const {
1063 
1064 	return metadata.has(p_name);
1065 }
1066 
set_meta(const String & p_name,const Variant & p_value)1067 void Object::set_meta(const String &p_name, const Variant &p_value) {
1068 
1069 	if (p_value.get_type() == Variant::NIL) {
1070 		metadata.erase(p_name);
1071 		return;
1072 	};
1073 
1074 	metadata[p_name] = p_value;
1075 }
1076 
get_meta(const String & p_name) const1077 Variant Object::get_meta(const String &p_name) const {
1078 
1079 	ERR_FAIL_COND_V(!metadata.has(p_name), Variant());
1080 	return metadata[p_name];
1081 }
1082 
remove_meta(const String & p_name)1083 void Object::remove_meta(const String &p_name) {
1084 	metadata.erase(p_name);
1085 }
1086 
_get_property_list_bind() const1087 Array Object::_get_property_list_bind() const {
1088 
1089 	List<PropertyInfo> lpi;
1090 	get_property_list(&lpi);
1091 	return convert_property_list(&lpi);
1092 }
1093 
_get_method_list_bind() const1094 Array Object::_get_method_list_bind() const {
1095 
1096 	List<MethodInfo> ml;
1097 	get_method_list(&ml);
1098 	Array ret;
1099 
1100 	for (List<MethodInfo>::Element *E = ml.front(); E; E = E->next()) {
1101 
1102 		Dictionary d = E->get();
1103 		//va.push_back(d);
1104 		ret.push_back(d);
1105 	}
1106 
1107 	return ret;
1108 }
1109 
_get_meta_list_bind() const1110 PoolVector<String> Object::_get_meta_list_bind() const {
1111 
1112 	PoolVector<String> _metaret;
1113 
1114 	List<Variant> keys;
1115 	metadata.get_key_list(&keys);
1116 	for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
1117 
1118 		_metaret.push_back(E->get());
1119 	}
1120 
1121 	return _metaret;
1122 }
get_meta_list(List<String> * p_list) const1123 void Object::get_meta_list(List<String> *p_list) const {
1124 
1125 	List<Variant> keys;
1126 	metadata.get_key_list(&keys);
1127 	for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
1128 
1129 		p_list->push_back(E->get());
1130 	}
1131 }
1132 
add_user_signal(const MethodInfo & p_signal)1133 void Object::add_user_signal(const MethodInfo &p_signal) {
1134 
1135 	ERR_FAIL_COND_MSG(p_signal.name == "", "Signal name cannot be empty.");
1136 	ERR_FAIL_COND_MSG(ClassDB::has_signal(get_class_name(), p_signal.name), "User signal's name conflicts with a built-in signal of '" + get_class_name() + "'.");
1137 	ERR_FAIL_COND_MSG(signal_map.has(p_signal.name), "Trying to add already existing signal '" + p_signal.name + "'.");
1138 	Signal s;
1139 	s.user = p_signal;
1140 	signal_map[p_signal.name] = s;
1141 }
1142 
_has_user_signal(const StringName & p_name) const1143 bool Object::_has_user_signal(const StringName &p_name) const {
1144 
1145 	if (!signal_map.has(p_name))
1146 		return false;
1147 	return signal_map[p_name].user.name.length() > 0;
1148 }
1149 
1150 struct _ObjectSignalDisconnectData {
1151 
1152 	StringName signal;
1153 	Object *target;
1154 	StringName method;
1155 };
1156 
_emit_signal(const Variant ** p_args,int p_argcount,Variant::CallError & r_error)1157 Variant Object::_emit_signal(const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
1158 
1159 	r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
1160 
1161 	ERR_FAIL_COND_V(p_argcount < 1, Variant());
1162 	if (p_args[0]->get_type() != Variant::STRING) {
1163 		r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
1164 		r_error.argument = 0;
1165 		r_error.expected = Variant::STRING;
1166 		ERR_FAIL_COND_V(p_args[0]->get_type() != Variant::STRING, Variant());
1167 	}
1168 
1169 	r_error.error = Variant::CallError::CALL_OK;
1170 
1171 	StringName signal = *p_args[0];
1172 
1173 	const Variant **args = NULL;
1174 
1175 	int argc = p_argcount - 1;
1176 	if (argc) {
1177 		args = &p_args[1];
1178 	}
1179 
1180 	emit_signal(signal, args, argc);
1181 
1182 	return Variant();
1183 }
1184 
emit_signal(const StringName & p_name,const Variant ** p_args,int p_argcount)1185 Error Object::emit_signal(const StringName &p_name, const Variant **p_args, int p_argcount) {
1186 
1187 	if (_block_signals)
1188 		return ERR_CANT_ACQUIRE_RESOURCE; //no emit, signals blocked
1189 
1190 	Signal *s = signal_map.getptr(p_name);
1191 	if (!s) {
1192 #ifdef DEBUG_ENABLED
1193 		bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_name);
1194 		//check in script
1195 		ERR_FAIL_COND_V_MSG(!signal_is_valid && !script.is_null() && !Ref<Script>(script)->has_script_signal(p_name), ERR_UNAVAILABLE, "Can't emit non-existing signal " + String("\"") + p_name + "\".");
1196 #endif
1197 		//not connected? just return
1198 		return ERR_UNAVAILABLE;
1199 	}
1200 
1201 	List<_ObjectSignalDisconnectData> disconnect_data;
1202 
1203 	//copy on write will ensure that disconnecting the signal or even deleting the object will not affect the signal calling.
1204 	//this happens automatically and will not change the performance of calling.
1205 	//awesome, isn't it?
1206 	VMap<Signal::Target, Signal::Slot> slot_map = s->slot_map;
1207 
1208 	int ssize = slot_map.size();
1209 
1210 	OBJ_DEBUG_LOCK
1211 
1212 	Vector<const Variant *> bind_mem;
1213 
1214 	Error err = OK;
1215 
1216 	for (int i = 0; i < ssize; i++) {
1217 
1218 		const Connection &c = slot_map.getv(i).conn;
1219 
1220 		Object *target = ObjectDB::get_instance(slot_map.getk(i)._id);
1221 		if (!target) {
1222 			// Target might have been deleted during signal callback, this is expected and OK.
1223 			continue;
1224 		}
1225 
1226 		const Variant **args = p_args;
1227 		int argc = p_argcount;
1228 
1229 		if (c.binds.size()) {
1230 			//handle binds
1231 			bind_mem.resize(p_argcount + c.binds.size());
1232 
1233 			for (int j = 0; j < p_argcount; j++) {
1234 				bind_mem.write[j] = p_args[j];
1235 			}
1236 			for (int j = 0; j < c.binds.size(); j++) {
1237 				bind_mem.write[p_argcount + j] = &c.binds[j];
1238 			}
1239 
1240 			args = (const Variant **)bind_mem.ptr();
1241 			argc = bind_mem.size();
1242 		}
1243 
1244 		if (c.flags & CONNECT_DEFERRED) {
1245 			MessageQueue::get_singleton()->push_call(target->get_instance_id(), c.method, args, argc, true);
1246 		} else {
1247 			Variant::CallError ce;
1248 			_emitting = true;
1249 			target->call(c.method, args, argc, ce);
1250 			_emitting = false;
1251 
1252 			if (ce.error != Variant::CallError::CALL_OK) {
1253 #ifdef DEBUG_ENABLED
1254 				if (c.flags & CONNECT_PERSIST && Engine::get_singleton()->is_editor_hint() && (script.is_null() || !Ref<Script>(script)->is_tool()))
1255 					continue;
1256 #endif
1257 				if (ce.error == Variant::CallError::CALL_ERROR_INVALID_METHOD && !ClassDB::class_exists(target->get_class_name())) {
1258 					//most likely object is not initialized yet, do not throw error.
1259 				} else {
1260 					ERR_PRINTS("Error calling method from signal '" + String(p_name) + "': " + Variant::get_call_error_text(target, c.method, args, argc, ce) + ".");
1261 					err = ERR_METHOD_NOT_FOUND;
1262 				}
1263 			}
1264 		}
1265 
1266 		bool disconnect = c.flags & CONNECT_ONESHOT;
1267 #ifdef TOOLS_ENABLED
1268 		if (disconnect && (c.flags & CONNECT_PERSIST) && Engine::get_singleton()->is_editor_hint()) {
1269 			//this signal was connected from the editor, and is being edited. just don't disconnect for now
1270 			disconnect = false;
1271 		}
1272 #endif
1273 		if (disconnect) {
1274 
1275 			_ObjectSignalDisconnectData dd;
1276 			dd.signal = p_name;
1277 			dd.target = target;
1278 			dd.method = c.method;
1279 			disconnect_data.push_back(dd);
1280 		}
1281 	}
1282 
1283 	while (!disconnect_data.empty()) {
1284 
1285 		const _ObjectSignalDisconnectData &dd = disconnect_data.front()->get();
1286 		disconnect(dd.signal, dd.target, dd.method);
1287 		disconnect_data.pop_front();
1288 	}
1289 
1290 	return err;
1291 }
1292 
emit_signal(const StringName & p_name,VARIANT_ARG_DECLARE)1293 Error Object::emit_signal(const StringName &p_name, VARIANT_ARG_DECLARE) {
1294 
1295 	VARIANT_ARGPTRS;
1296 
1297 	int argc = 0;
1298 
1299 	for (int i = 0; i < VARIANT_ARG_MAX; i++) {
1300 
1301 		if (argptr[i]->get_type() == Variant::NIL)
1302 			break;
1303 		argc++;
1304 	}
1305 
1306 	return emit_signal(p_name, argptr, argc);
1307 }
1308 
_add_user_signal(const String & p_name,const Array & p_args)1309 void Object::_add_user_signal(const String &p_name, const Array &p_args) {
1310 
1311 	// this version of add_user_signal is meant to be used from scripts or external apis
1312 	// without access to ADD_SIGNAL in bind_methods
1313 	// added events are per instance, as opposed to the other ones, which are global
1314 
1315 	MethodInfo mi;
1316 	mi.name = p_name;
1317 
1318 	for (int i = 0; i < p_args.size(); i++) {
1319 
1320 		Dictionary d = p_args[i];
1321 		PropertyInfo param;
1322 
1323 		if (d.has("name"))
1324 			param.name = d["name"];
1325 		if (d.has("type"))
1326 			param.type = (Variant::Type)(int)d["type"];
1327 
1328 		mi.arguments.push_back(param);
1329 	}
1330 
1331 	add_user_signal(mi);
1332 }
1333 
_get_signal_list() const1334 Array Object::_get_signal_list() const {
1335 
1336 	List<MethodInfo> signal_list;
1337 	get_signal_list(&signal_list);
1338 
1339 	Array ret;
1340 	for (List<MethodInfo>::Element *E = signal_list.front(); E; E = E->next()) {
1341 
1342 		ret.push_back(Dictionary(E->get()));
1343 	}
1344 
1345 	return ret;
1346 }
1347 
_get_signal_connection_list(const String & p_signal) const1348 Array Object::_get_signal_connection_list(const String &p_signal) const {
1349 
1350 	List<Connection> conns;
1351 	get_all_signal_connections(&conns);
1352 
1353 	Array ret;
1354 
1355 	for (List<Connection>::Element *E = conns.front(); E; E = E->next()) {
1356 
1357 		Connection &c = E->get();
1358 		if (c.signal == p_signal) {
1359 			Dictionary rc;
1360 			rc["signal"] = c.signal;
1361 			rc["method"] = c.method;
1362 			rc["source"] = c.source;
1363 			rc["target"] = c.target;
1364 			rc["binds"] = c.binds;
1365 			rc["flags"] = c.flags;
1366 			ret.push_back(rc);
1367 		}
1368 	}
1369 
1370 	return ret;
1371 }
1372 
_get_incoming_connections() const1373 Array Object::_get_incoming_connections() const {
1374 
1375 	Array ret;
1376 	int connections_amount = connections.size();
1377 	for (int idx_conn = 0; idx_conn < connections_amount; idx_conn++) {
1378 		Dictionary conn_data;
1379 		conn_data["source"] = connections[idx_conn].source;
1380 		conn_data["signal_name"] = connections[idx_conn].signal;
1381 		conn_data["method_name"] = connections[idx_conn].method;
1382 		ret.push_back(conn_data);
1383 	}
1384 
1385 	return ret;
1386 }
1387 
has_signal(const StringName & p_name) const1388 bool Object::has_signal(const StringName &p_name) const {
1389 	if (!script.is_null()) {
1390 		Ref<Script> scr = script;
1391 		if (scr.is_valid() && scr->has_script_signal(p_name)) {
1392 			return true;
1393 		}
1394 	}
1395 
1396 	if (ClassDB::has_signal(get_class_name(), p_name)) {
1397 		return true;
1398 	}
1399 
1400 	if (_has_user_signal(p_name)) {
1401 		return true;
1402 	}
1403 
1404 	return false;
1405 }
1406 
get_signal_list(List<MethodInfo> * p_signals) const1407 void Object::get_signal_list(List<MethodInfo> *p_signals) const {
1408 
1409 	if (!script.is_null()) {
1410 		Ref<Script> scr = script;
1411 		if (scr.is_valid()) {
1412 			scr->get_script_signal_list(p_signals);
1413 		}
1414 	}
1415 
1416 	ClassDB::get_signal_list(get_class_name(), p_signals);
1417 	//find maybe usersignals?
1418 	const StringName *S = NULL;
1419 
1420 	while ((S = signal_map.next(S))) {
1421 
1422 		if (signal_map[*S].user.name != "") {
1423 			//user signal
1424 			p_signals->push_back(signal_map[*S].user);
1425 		}
1426 	}
1427 }
1428 
get_all_signal_connections(List<Connection> * p_connections) const1429 void Object::get_all_signal_connections(List<Connection> *p_connections) const {
1430 
1431 	const StringName *S = NULL;
1432 
1433 	while ((S = signal_map.next(S))) {
1434 
1435 		const Signal *s = &signal_map[*S];
1436 
1437 		for (int i = 0; i < s->slot_map.size(); i++) {
1438 
1439 			p_connections->push_back(s->slot_map.getv(i).conn);
1440 		}
1441 	}
1442 }
1443 
get_signal_connection_list(const StringName & p_signal,List<Connection> * p_connections) const1444 void Object::get_signal_connection_list(const StringName &p_signal, List<Connection> *p_connections) const {
1445 
1446 	const Signal *s = signal_map.getptr(p_signal);
1447 	if (!s)
1448 		return; //nothing
1449 
1450 	for (int i = 0; i < s->slot_map.size(); i++)
1451 		p_connections->push_back(s->slot_map.getv(i).conn);
1452 }
1453 
get_persistent_signal_connection_count() const1454 int Object::get_persistent_signal_connection_count() const {
1455 
1456 	int count = 0;
1457 	const StringName *S = NULL;
1458 
1459 	while ((S = signal_map.next(S))) {
1460 
1461 		const Signal *s = &signal_map[*S];
1462 
1463 		for (int i = 0; i < s->slot_map.size(); i++) {
1464 			if (s->slot_map.getv(i).conn.flags & CONNECT_PERSIST) {
1465 				count += 1;
1466 			}
1467 		}
1468 	}
1469 
1470 	return count;
1471 }
1472 
get_signals_connected_to_this(List<Connection> * p_connections) const1473 void Object::get_signals_connected_to_this(List<Connection> *p_connections) const {
1474 
1475 	for (const List<Connection>::Element *E = connections.front(); E; E = E->next()) {
1476 		p_connections->push_back(E->get());
1477 	}
1478 }
1479 
connect(const StringName & p_signal,Object * p_to_object,const StringName & p_to_method,const Vector<Variant> & p_binds,uint32_t p_flags)1480 Error Object::connect(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method, const Vector<Variant> &p_binds, uint32_t p_flags) {
1481 
1482 	ERR_FAIL_NULL_V(p_to_object, ERR_INVALID_PARAMETER);
1483 
1484 	Signal *s = signal_map.getptr(p_signal);
1485 	if (!s) {
1486 		bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_signal);
1487 		//check in script
1488 		if (!signal_is_valid && !script.is_null()) {
1489 
1490 			if (Ref<Script>(script)->has_script_signal(p_signal)) {
1491 				signal_is_valid = true;
1492 			}
1493 #ifdef TOOLS_ENABLED
1494 			else {
1495 				//allow connecting signals anyway if script is invalid, see issue #17070
1496 				if (!Ref<Script>(script)->is_valid()) {
1497 					signal_is_valid = true;
1498 				}
1499 			}
1500 #endif
1501 		}
1502 
1503 		ERR_FAIL_COND_V_MSG(!signal_is_valid, ERR_INVALID_PARAMETER, "In Object of type '" + String(get_class()) + "': Attempt to connect nonexistent signal '" + p_signal + "' to method '" + p_to_object->get_class() + "." + p_to_method + "'.");
1504 
1505 		signal_map[p_signal] = Signal();
1506 		s = &signal_map[p_signal];
1507 	}
1508 
1509 	Signal::Target target(p_to_object->get_instance_id(), p_to_method);
1510 	if (s->slot_map.has(target)) {
1511 		if (p_flags & CONNECT_REFERENCE_COUNTED) {
1512 			s->slot_map[target].reference_count++;
1513 			return OK;
1514 		} else {
1515 			ERR_FAIL_V_MSG(ERR_INVALID_PARAMETER, "Signal '" + p_signal + "' is already connected to given method '" + p_to_method + "' in that object.");
1516 		}
1517 	}
1518 
1519 	Signal::Slot slot;
1520 
1521 	Connection conn;
1522 	conn.source = this;
1523 	conn.target = p_to_object;
1524 	conn.method = p_to_method;
1525 	conn.signal = p_signal;
1526 	conn.flags = p_flags;
1527 	conn.binds = p_binds;
1528 	slot.conn = conn;
1529 	slot.cE = p_to_object->connections.push_back(conn);
1530 	if (p_flags & CONNECT_REFERENCE_COUNTED) {
1531 		slot.reference_count = 1;
1532 	}
1533 
1534 	s->slot_map[target] = slot;
1535 
1536 	return OK;
1537 }
1538 
is_connected(const StringName & p_signal,Object * p_to_object,const StringName & p_to_method) const1539 bool Object::is_connected(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method) const {
1540 
1541 	ERR_FAIL_NULL_V(p_to_object, false);
1542 	const Signal *s = signal_map.getptr(p_signal);
1543 	if (!s) {
1544 		bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_signal);
1545 		if (signal_is_valid)
1546 			return false;
1547 
1548 		if (!script.is_null() && Ref<Script>(script)->has_script_signal(p_signal))
1549 			return false;
1550 
1551 		ERR_FAIL_V_MSG(false, "Nonexistent signal: " + p_signal + ".");
1552 	}
1553 
1554 	Signal::Target target(p_to_object->get_instance_id(), p_to_method);
1555 
1556 	return s->slot_map.has(target);
1557 	//const Map<Signal::Target,Signal::Slot>::Element *E = s->slot_map.find(target);
1558 	//return (E!=NULL);
1559 }
1560 
disconnect(const StringName & p_signal,Object * p_to_object,const StringName & p_to_method)1561 void Object::disconnect(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method) {
1562 
1563 	_disconnect(p_signal, p_to_object, p_to_method);
1564 }
_disconnect(const StringName & p_signal,Object * p_to_object,const StringName & p_to_method,bool p_force)1565 void Object::_disconnect(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method, bool p_force) {
1566 
1567 	ERR_FAIL_NULL(p_to_object);
1568 	Signal *s = signal_map.getptr(p_signal);
1569 	ERR_FAIL_COND_MSG(!s, vformat("Nonexistent signal '%s' in %s.", p_signal, to_string()));
1570 
1571 	Signal::Target target(p_to_object->get_instance_id(), p_to_method);
1572 
1573 	ERR_FAIL_COND_MSG(!s->slot_map.has(target), "Disconnecting nonexistent signal '" + p_signal + "', slot: " + itos(target._id) + ":" + target.method + ".");
1574 
1575 	Signal::Slot *slot = &s->slot_map[target];
1576 
1577 	if (!p_force) {
1578 		slot->reference_count--; // by default is zero, if it was not referenced it will go below it
1579 		if (slot->reference_count >= 0) {
1580 			return;
1581 		}
1582 	}
1583 
1584 	p_to_object->connections.erase(slot->cE);
1585 	s->slot_map.erase(target);
1586 
1587 	if (s->slot_map.empty() && ClassDB::has_signal(get_class_name(), p_signal)) {
1588 		//not user signal, delete
1589 		signal_map.erase(p_signal);
1590 	}
1591 }
1592 
_set_bind(const String & p_set,const Variant & p_value)1593 void Object::_set_bind(const String &p_set, const Variant &p_value) {
1594 
1595 	set(p_set, p_value);
1596 }
1597 
_get_bind(const String & p_name) const1598 Variant Object::_get_bind(const String &p_name) const {
1599 
1600 	return get(p_name);
1601 }
1602 
_set_indexed_bind(const NodePath & p_name,const Variant & p_value)1603 void Object::_set_indexed_bind(const NodePath &p_name, const Variant &p_value) {
1604 
1605 	set_indexed(p_name.get_as_property_path().get_subnames(), p_value);
1606 }
1607 
_get_indexed_bind(const NodePath & p_name) const1608 Variant Object::_get_indexed_bind(const NodePath &p_name) const {
1609 
1610 	return get_indexed(p_name.get_as_property_path().get_subnames());
1611 }
1612 
initialize_class()1613 void Object::initialize_class() {
1614 
1615 	static bool initialized = false;
1616 	if (initialized)
1617 		return;
1618 	ClassDB::_add_class<Object>();
1619 	_bind_methods();
1620 	initialized = true;
1621 }
1622 
tr(const StringName & p_message) const1623 StringName Object::tr(const StringName &p_message) const {
1624 
1625 	if (!_can_translate || !TranslationServer::get_singleton())
1626 		return p_message;
1627 
1628 	return TranslationServer::get_singleton()->translate(p_message);
1629 }
1630 
_clear_internal_resource_paths(const Variant & p_var)1631 void Object::_clear_internal_resource_paths(const Variant &p_var) {
1632 
1633 	switch (p_var.get_type()) {
1634 
1635 		case Variant::OBJECT: {
1636 
1637 			RES r = p_var;
1638 			if (!r.is_valid())
1639 				return;
1640 
1641 			if (!r->get_path().begins_with("res://") || r->get_path().find("::") == -1)
1642 				return; //not an internal resource
1643 
1644 			Object *object = p_var;
1645 			if (!object)
1646 				return;
1647 
1648 			r->set_path("");
1649 			r->clear_internal_resource_paths();
1650 		} break;
1651 		case Variant::ARRAY: {
1652 
1653 			Array a = p_var;
1654 			for (int i = 0; i < a.size(); i++) {
1655 				_clear_internal_resource_paths(a[i]);
1656 			}
1657 
1658 		} break;
1659 		case Variant::DICTIONARY: {
1660 
1661 			Dictionary d = p_var;
1662 			List<Variant> keys;
1663 			d.get_key_list(&keys);
1664 
1665 			for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
1666 
1667 				_clear_internal_resource_paths(E->get());
1668 				_clear_internal_resource_paths(d[E->get()]);
1669 			}
1670 		} break;
1671 		default: {
1672 		}
1673 	}
1674 }
1675 
1676 #ifdef TOOLS_ENABLED
editor_set_section_unfold(const String & p_section,bool p_unfolded)1677 void Object::editor_set_section_unfold(const String &p_section, bool p_unfolded) {
1678 
1679 	set_edited(true);
1680 	if (p_unfolded)
1681 		editor_section_folding.insert(p_section);
1682 	else
1683 		editor_section_folding.erase(p_section);
1684 }
1685 
editor_is_section_unfolded(const String & p_section)1686 bool Object::editor_is_section_unfolded(const String &p_section) {
1687 
1688 	return editor_section_folding.has(p_section);
1689 }
1690 
1691 #endif
1692 
clear_internal_resource_paths()1693 void Object::clear_internal_resource_paths() {
1694 
1695 	List<PropertyInfo> pinfo;
1696 
1697 	get_property_list(&pinfo);
1698 
1699 	for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
1700 
1701 		_clear_internal_resource_paths(get(E->get().name));
1702 	}
1703 }
1704 
_bind_methods()1705 void Object::_bind_methods() {
1706 
1707 	ClassDB::bind_method(D_METHOD("get_class"), &Object::get_class);
1708 	ClassDB::bind_method(D_METHOD("is_class", "class"), &Object::is_class);
1709 	ClassDB::bind_method(D_METHOD("set", "property", "value"), &Object::_set_bind);
1710 	ClassDB::bind_method(D_METHOD("get", "property"), &Object::_get_bind);
1711 	ClassDB::bind_method(D_METHOD("set_indexed", "property", "value"), &Object::_set_indexed_bind);
1712 	ClassDB::bind_method(D_METHOD("get_indexed", "property"), &Object::_get_indexed_bind);
1713 	ClassDB::bind_method(D_METHOD("get_property_list"), &Object::_get_property_list_bind);
1714 	ClassDB::bind_method(D_METHOD("get_method_list"), &Object::_get_method_list_bind);
1715 	ClassDB::bind_method(D_METHOD("notification", "what", "reversed"), &Object::notification, DEFVAL(false));
1716 	ClassDB::bind_method(D_METHOD("to_string"), &Object::to_string);
1717 	ClassDB::bind_method(D_METHOD("get_instance_id"), &Object::get_instance_id);
1718 
1719 	ClassDB::bind_method(D_METHOD("set_script", "script"), &Object::set_script);
1720 	ClassDB::bind_method(D_METHOD("get_script"), &Object::get_script);
1721 
1722 	ClassDB::bind_method(D_METHOD("set_meta", "name", "value"), &Object::set_meta);
1723 	ClassDB::bind_method(D_METHOD("remove_meta", "name"), &Object::remove_meta);
1724 	ClassDB::bind_method(D_METHOD("get_meta", "name"), &Object::get_meta);
1725 	ClassDB::bind_method(D_METHOD("has_meta", "name"), &Object::has_meta);
1726 	ClassDB::bind_method(D_METHOD("get_meta_list"), &Object::_get_meta_list_bind);
1727 
1728 	ClassDB::bind_method(D_METHOD("add_user_signal", "signal", "arguments"), &Object::_add_user_signal, DEFVAL(Array()));
1729 	ClassDB::bind_method(D_METHOD("has_user_signal", "signal"), &Object::_has_user_signal);
1730 
1731 	{
1732 		MethodInfo mi;
1733 		mi.name = "emit_signal";
1734 		mi.arguments.push_back(PropertyInfo(Variant::STRING, "signal"));
1735 
1736 		ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "emit_signal", &Object::_emit_signal, mi, varray(), false);
1737 	}
1738 
1739 	{
1740 		MethodInfo mi;
1741 		mi.name = "call";
1742 		mi.arguments.push_back(PropertyInfo(Variant::STRING, "method"));
1743 
1744 		ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "call", &Object::_call_bind, mi);
1745 	}
1746 
1747 	{
1748 		MethodInfo mi;
1749 		mi.name = "call_deferred";
1750 		mi.arguments.push_back(PropertyInfo(Variant::STRING, "method"));
1751 
1752 		ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "call_deferred", &Object::_call_deferred_bind, mi, varray(), false);
1753 	}
1754 
1755 	ClassDB::bind_method(D_METHOD("set_deferred", "property", "value"), &Object::set_deferred);
1756 
1757 	ClassDB::bind_method(D_METHOD("callv", "method", "arg_array"), &Object::callv);
1758 
1759 	ClassDB::bind_method(D_METHOD("has_method", "method"), &Object::has_method);
1760 
1761 	ClassDB::bind_method(D_METHOD("has_signal", "signal"), &Object::has_signal);
1762 	ClassDB::bind_method(D_METHOD("get_signal_list"), &Object::_get_signal_list);
1763 	ClassDB::bind_method(D_METHOD("get_signal_connection_list", "signal"), &Object::_get_signal_connection_list);
1764 	ClassDB::bind_method(D_METHOD("get_incoming_connections"), &Object::_get_incoming_connections);
1765 
1766 	ClassDB::bind_method(D_METHOD("connect", "signal", "target", "method", "binds", "flags"), &Object::connect, DEFVAL(Array()), DEFVAL(0));
1767 	ClassDB::bind_method(D_METHOD("disconnect", "signal", "target", "method"), &Object::disconnect);
1768 	ClassDB::bind_method(D_METHOD("is_connected", "signal", "target", "method"), &Object::is_connected);
1769 
1770 	ClassDB::bind_method(D_METHOD("set_block_signals", "enable"), &Object::set_block_signals);
1771 	ClassDB::bind_method(D_METHOD("is_blocking_signals"), &Object::is_blocking_signals);
1772 	ClassDB::bind_method(D_METHOD("property_list_changed_notify"), &Object::property_list_changed_notify);
1773 
1774 	ClassDB::bind_method(D_METHOD("set_message_translation", "enable"), &Object::set_message_translation);
1775 	ClassDB::bind_method(D_METHOD("can_translate_messages"), &Object::can_translate_messages);
1776 	ClassDB::bind_method(D_METHOD("tr", "message"), &Object::tr);
1777 
1778 	ClassDB::bind_method(D_METHOD("is_queued_for_deletion"), &Object::is_queued_for_deletion);
1779 
1780 	ClassDB::add_virtual_method("Object", MethodInfo("free"), false);
1781 
1782 	ADD_SIGNAL(MethodInfo("script_changed"));
1783 
1784 	BIND_VMETHOD(MethodInfo("_notification", PropertyInfo(Variant::INT, "what")));
1785 	BIND_VMETHOD(MethodInfo(Variant::BOOL, "_set", PropertyInfo(Variant::STRING, "property"), PropertyInfo(Variant::NIL, "value")));
1786 #ifdef TOOLS_ENABLED
1787 	MethodInfo miget("_get", PropertyInfo(Variant::STRING, "property"));
1788 	miget.return_val.name = "Variant";
1789 	miget.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
1790 	BIND_VMETHOD(miget);
1791 
1792 	MethodInfo plget("_get_property_list");
1793 
1794 	plget.return_val.type = Variant::ARRAY;
1795 	BIND_VMETHOD(plget);
1796 
1797 #endif
1798 	BIND_VMETHOD(MethodInfo("_init"));
1799 	BIND_VMETHOD(MethodInfo(Variant::STRING, "_to_string"));
1800 
1801 	BIND_CONSTANT(NOTIFICATION_POSTINITIALIZE);
1802 	BIND_CONSTANT(NOTIFICATION_PREDELETE);
1803 
1804 	BIND_ENUM_CONSTANT(CONNECT_DEFERRED);
1805 	BIND_ENUM_CONSTANT(CONNECT_PERSIST);
1806 	BIND_ENUM_CONSTANT(CONNECT_ONESHOT);
1807 	BIND_ENUM_CONSTANT(CONNECT_REFERENCE_COUNTED);
1808 }
1809 
call_deferred(const StringName & p_method,VARIANT_ARG_DECLARE)1810 void Object::call_deferred(const StringName &p_method, VARIANT_ARG_DECLARE) {
1811 
1812 	MessageQueue::get_singleton()->push_call(this, p_method, VARIANT_ARG_PASS);
1813 }
1814 
set_deferred(const StringName & p_property,const Variant & p_value)1815 void Object::set_deferred(const StringName &p_property, const Variant &p_value) {
1816 	MessageQueue::get_singleton()->push_set(this, p_property, p_value);
1817 }
1818 
set_block_signals(bool p_block)1819 void Object::set_block_signals(bool p_block) {
1820 
1821 	_block_signals = p_block;
1822 }
1823 
is_blocking_signals() const1824 bool Object::is_blocking_signals() const {
1825 
1826 	return _block_signals;
1827 }
1828 
get_translatable_strings(List<String> * p_strings) const1829 void Object::get_translatable_strings(List<String> *p_strings) const {
1830 
1831 	List<PropertyInfo> plist;
1832 	get_property_list(&plist);
1833 
1834 	for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
1835 
1836 		if (!(E->get().usage & PROPERTY_USAGE_INTERNATIONALIZED))
1837 			continue;
1838 
1839 		String text = get(E->get().name);
1840 
1841 		if (text == "")
1842 			continue;
1843 
1844 		p_strings->push_back(text);
1845 	}
1846 }
1847 
get_static_property_type(const StringName & p_property,bool * r_valid) const1848 Variant::Type Object::get_static_property_type(const StringName &p_property, bool *r_valid) const {
1849 
1850 	bool valid;
1851 	Variant::Type t = ClassDB::get_property_type(get_class_name(), p_property, &valid);
1852 	if (valid) {
1853 		if (r_valid)
1854 			*r_valid = true;
1855 		return t;
1856 	}
1857 
1858 	if (get_script_instance()) {
1859 		return get_script_instance()->get_property_type(p_property, r_valid);
1860 	}
1861 	if (r_valid)
1862 		*r_valid = false;
1863 
1864 	return Variant::NIL;
1865 }
1866 
get_static_property_type_indexed(const Vector<StringName> & p_path,bool * r_valid) const1867 Variant::Type Object::get_static_property_type_indexed(const Vector<StringName> &p_path, bool *r_valid) const {
1868 
1869 	if (p_path.size() == 0) {
1870 		if (r_valid)
1871 			*r_valid = false;
1872 
1873 		return Variant::NIL;
1874 	}
1875 
1876 	bool valid = false;
1877 	Variant::Type t = get_static_property_type(p_path[0], &valid);
1878 	if (!valid) {
1879 		if (r_valid)
1880 			*r_valid = false;
1881 
1882 		return Variant::NIL;
1883 	}
1884 
1885 	Variant::CallError ce;
1886 	Variant check = Variant::construct(t, NULL, 0, ce);
1887 
1888 	for (int i = 1; i < p_path.size(); i++) {
1889 		if (check.get_type() == Variant::OBJECT || check.get_type() == Variant::DICTIONARY || check.get_type() == Variant::ARRAY) {
1890 			// We cannot be sure about the type of properties this types can have
1891 			if (r_valid)
1892 				*r_valid = false;
1893 			return Variant::NIL;
1894 		}
1895 
1896 		check = check.get_named(p_path[i], &valid);
1897 
1898 		if (!valid) {
1899 			if (r_valid)
1900 				*r_valid = false;
1901 			return Variant::NIL;
1902 		}
1903 	}
1904 
1905 	if (r_valid)
1906 		*r_valid = true;
1907 
1908 	return check.get_type();
1909 }
1910 
is_queued_for_deletion() const1911 bool Object::is_queued_for_deletion() const {
1912 	return _is_queued_for_deletion;
1913 }
1914 
1915 #ifdef TOOLS_ENABLED
set_edited(bool p_edited)1916 void Object::set_edited(bool p_edited) {
1917 
1918 	_edited = p_edited;
1919 	_edited_version++;
1920 }
1921 
is_edited() const1922 bool Object::is_edited() const {
1923 
1924 	return _edited;
1925 }
1926 
get_edited_version() const1927 uint32_t Object::get_edited_version() const {
1928 
1929 	return _edited_version;
1930 }
1931 #endif
1932 
get_script_instance_binding(int p_script_language_index)1933 void *Object::get_script_instance_binding(int p_script_language_index) {
1934 #ifdef DEBUG_ENABLED
1935 	ERR_FAIL_INDEX_V(p_script_language_index, MAX_SCRIPT_INSTANCE_BINDINGS, NULL);
1936 #endif
1937 
1938 	//it's up to the script language to make this thread safe, if the function is called twice due to threads being out of syncro
1939 	//just return the same pointer.
1940 	//if you want to put a big lock in the entire function and keep allocated pointers in a map or something, feel free to do it
1941 	//as it should not really affect performance much (won't be called too often), as in far most caes the condition below will be false afterwards
1942 
1943 	if (!_script_instance_bindings[p_script_language_index]) {
1944 		void *script_data = ScriptServer::get_language(p_script_language_index)->alloc_instance_binding_data(this);
1945 		if (script_data) {
1946 			atomic_increment(&instance_binding_count);
1947 			_script_instance_bindings[p_script_language_index] = script_data;
1948 		}
1949 	}
1950 
1951 	return _script_instance_bindings[p_script_language_index];
1952 }
1953 
has_script_instance_binding(int p_script_language_index)1954 bool Object::has_script_instance_binding(int p_script_language_index) {
1955 
1956 	return _script_instance_bindings[p_script_language_index] != NULL;
1957 }
1958 
set_script_instance_binding(int p_script_language_index,void * p_data)1959 void Object::set_script_instance_binding(int p_script_language_index, void *p_data) {
1960 #ifdef DEBUG_ENABLED
1961 	CRASH_COND(_script_instance_bindings[p_script_language_index] != NULL);
1962 #endif
1963 	_script_instance_bindings[p_script_language_index] = p_data;
1964 }
1965 
Object()1966 Object::Object() {
1967 
1968 	_class_ptr = NULL;
1969 	_block_signals = false;
1970 	_predelete_ok = 0;
1971 	_instance_id = 0;
1972 	_instance_id = ObjectDB::add_instance(this);
1973 	_can_translate = true;
1974 	_is_queued_for_deletion = false;
1975 	_emitting = false;
1976 	instance_binding_count = 0;
1977 	memset(_script_instance_bindings, 0, sizeof(void *) * MAX_SCRIPT_INSTANCE_BINDINGS);
1978 	script_instance = NULL;
1979 #ifdef DEBUG_ENABLED
1980 	_rc.store(nullptr, std::memory_order_release);
1981 #endif
1982 #ifdef TOOLS_ENABLED
1983 
1984 	_edited = false;
1985 	_edited_version = 0;
1986 #endif
1987 
1988 #ifdef DEBUG_ENABLED
1989 	_lock_index.init(1);
1990 #endif
1991 }
1992 
~Object()1993 Object::~Object() {
1994 
1995 #ifdef DEBUG_ENABLED
1996 	ObjectRC *rc = _rc.load(std::memory_order_acquire);
1997 	if (rc) {
1998 		if (rc->invalidate()) {
1999 			memdelete(rc);
2000 		}
2001 	}
2002 #endif
2003 
2004 	if (script_instance)
2005 		memdelete(script_instance);
2006 	script_instance = NULL;
2007 
2008 	const StringName *S = NULL;
2009 
2010 	if (_emitting) {
2011 		//@todo this may need to actually reach the debugger prioritarily somehow because it may crash before
2012 		ERR_PRINTS("Object " + to_string() + " 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.");
2013 	}
2014 
2015 	while ((S = signal_map.next(NULL))) {
2016 
2017 		Signal *s = &signal_map[*S];
2018 
2019 		//brute force disconnect for performance
2020 		int slot_count = s->slot_map.size();
2021 		const VMap<Signal::Target, Signal::Slot>::Pair *slot_list = s->slot_map.get_array();
2022 
2023 		for (int i = 0; i < slot_count; i++) {
2024 
2025 			slot_list[i].value.conn.target->connections.erase(slot_list[i].value.cE);
2026 		}
2027 
2028 		signal_map.erase(*S);
2029 	}
2030 
2031 	//signals from nodes that connect to this node
2032 	while (connections.size()) {
2033 
2034 		Connection c = connections.front()->get();
2035 		c.source->_disconnect(c.signal, c.target, c.method, true);
2036 	}
2037 
2038 	ObjectDB::remove_instance(this);
2039 	_instance_id = 0;
2040 	_predelete_ok = 2;
2041 
2042 	if (!ScriptServer::are_languages_finished()) {
2043 		for (int i = 0; i < MAX_SCRIPT_INSTANCE_BINDINGS; i++) {
2044 			if (_script_instance_bindings[i]) {
2045 				ScriptServer::get_language(i)->free_instance_binding_data(_script_instance_bindings[i]);
2046 			}
2047 		}
2048 	}
2049 }
2050 
predelete_handler(Object * p_object)2051 bool predelete_handler(Object *p_object) {
2052 
2053 	return p_object->_predelete();
2054 }
2055 
postinitialize_handler(Object * p_object)2056 void postinitialize_handler(Object *p_object) {
2057 
2058 	p_object->_postinitialize();
2059 }
2060 
2061 HashMap<ObjectID, Object *> ObjectDB::instances;
2062 ObjectID ObjectDB::instance_counter = 1;
2063 HashMap<Object *, ObjectID, ObjectDB::ObjectPtrHash> ObjectDB::instance_checks;
add_instance(Object * p_object)2064 ObjectID ObjectDB::add_instance(Object *p_object) {
2065 
2066 	ERR_FAIL_COND_V(p_object->get_instance_id() != 0, 0);
2067 
2068 	rw_lock->write_lock();
2069 	ObjectID instance_id = ++instance_counter;
2070 	instances[instance_id] = p_object;
2071 	instance_checks[p_object] = instance_id;
2072 
2073 	rw_lock->write_unlock();
2074 
2075 	return instance_id;
2076 }
2077 
remove_instance(Object * p_object)2078 void ObjectDB::remove_instance(Object *p_object) {
2079 
2080 	rw_lock->write_lock();
2081 
2082 	instances.erase(p_object->get_instance_id());
2083 	instance_checks.erase(p_object);
2084 
2085 	rw_lock->write_unlock();
2086 }
get_instance(ObjectID p_instance_id)2087 Object *ObjectDB::get_instance(ObjectID p_instance_id) {
2088 
2089 	rw_lock->read_lock();
2090 	Object **obj = instances.getptr(p_instance_id);
2091 	rw_lock->read_unlock();
2092 
2093 	if (!obj)
2094 		return NULL;
2095 	return *obj;
2096 }
2097 
debug_objects(DebugFunc p_func)2098 void ObjectDB::debug_objects(DebugFunc p_func) {
2099 
2100 	rw_lock->read_lock();
2101 
2102 	const ObjectID *K = NULL;
2103 	while ((K = instances.next(K))) {
2104 
2105 		p_func(instances[*K]);
2106 	}
2107 
2108 	rw_lock->read_unlock();
2109 }
2110 
get_argument_options(const StringName & p_function,int p_idx,List<String> * r_options) const2111 void Object::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const {
2112 }
2113 
get_object_count()2114 int ObjectDB::get_object_count() {
2115 
2116 	rw_lock->read_lock();
2117 	int count = instances.size();
2118 	rw_lock->read_unlock();
2119 
2120 	return count;
2121 }
2122 
2123 RWLock *ObjectDB::rw_lock = NULL;
2124 
setup()2125 void ObjectDB::setup() {
2126 
2127 	rw_lock = RWLock::create();
2128 }
2129 
cleanup()2130 void ObjectDB::cleanup() {
2131 
2132 	rw_lock->write_lock();
2133 	if (instances.size()) {
2134 
2135 		WARN_PRINT("ObjectDB instances leaked at exit (run with --verbose for details).");
2136 		if (OS::get_singleton()->is_stdout_verbose()) {
2137 			// Ensure calling the native classes because if a leaked instance has a script
2138 			// that overrides any of those methods, it'd not be OK to call them at this point,
2139 			// now the scripting languages have already been terminated.
2140 			MethodBind *node_get_name = ClassDB::get_method("Node", "get_name");
2141 			MethodBind *resource_get_path = ClassDB::get_method("Resource", "get_path");
2142 			Variant::CallError call_error;
2143 
2144 			const ObjectID *K = NULL;
2145 			while ((K = instances.next(K))) {
2146 
2147 				String extra_info;
2148 				if (instances[*K]->is_class("Node"))
2149 					extra_info = " - Node name: " + String(node_get_name->call(instances[*K], NULL, 0, call_error));
2150 				if (instances[*K]->is_class("Resource"))
2151 					extra_info = " - Resource path: " + String(resource_get_path->call(instances[*K], NULL, 0, call_error));
2152 				print_line("Leaked instance: " + String(instances[*K]->get_class()) + ":" + itos(*K) + extra_info);
2153 			}
2154 			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()`).");
2155 		}
2156 	}
2157 	instances.clear();
2158 	instance_checks.clear();
2159 	rw_lock->write_unlock();
2160 	memdelete(rw_lock);
2161 }
2162