1 /*************************************************************************/
2 /*  object.h                                                             */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2019 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 #ifndef OBJECT_H
31 #define OBJECT_H
32 
33 #include "list.h"
34 #include "map.h"
35 #include "set.h"
36 #include "variant.h"
37 #include "vmap.h"
38 
39 #define VARIANT_ARG_LIST const Variant &p_arg1 = Variant(), const Variant &p_arg2 = Variant(), const Variant &p_arg3 = Variant(), const Variant &p_arg4 = Variant(), const Variant &p_arg5 = Variant()
40 #define VARIANT_ARG_PASS p_arg1, p_arg2, p_arg3, p_arg4, p_arg5
41 #define VARIANT_ARG_DECLARE const Variant &p_arg1, const Variant &p_arg2, const Variant &p_arg3, const Variant &p_arg4, const Variant &p_arg5
42 #define VARIANT_ARG_MAX 5
43 #define VARIANT_ARGPTRS const Variant *argptr[5] = { &p_arg1, &p_arg2, &p_arg3, &p_arg4, &p_arg5 };
44 #define VARIANT_ARGPTRS_PASS *argptr[0], *argptr[1], *argptr[2], *argptr[3], *argptr[4]
45 #define VARIANT_ARGS_FROM_ARRAY(m_arr) m_arr[0], m_arr[1], m_arr[2], m_arr[3], m_arr[4]
46 
47 /**
48 @author Juan Linietsky <reduzio@gmail.com>
49 */
50 
51 enum PropertyHint {
52 	PROPERTY_HINT_NONE, ///< no hint provided.
53 	PROPERTY_HINT_RANGE, ///< hint_text = "min,max,step,slider; //slider is optional"
54 	PROPERTY_HINT_EXP_RANGE, ///< hint_text = "min,max,step", exponential edit
55 	PROPERTY_HINT_ENUM, ///< hint_text= "val1,val2,val3,etc"
56 	PROPERTY_HINT_EXP_EASING, /// exponential easing funciton (Math::ease)
57 	PROPERTY_HINT_LENGTH, ///< hint_text= "length" (as integer)
58 	PROPERTY_HINT_SPRITE_FRAME,
59 	PROPERTY_HINT_KEY_ACCEL, ///< hint_text= "length" (as integer)
60 	PROPERTY_HINT_FLAGS, ///< hint_text= "flag1,flag2,etc" (as bit flags)
61 	PROPERTY_HINT_ALL_FLAGS,
62 	PROPERTY_HINT_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,"
63 	PROPERTY_HINT_DIR, ///< a directort path must be passed
64 	PROPERTY_HINT_GLOBAL_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,"
65 	PROPERTY_HINT_GLOBAL_DIR, ///< a directort path must be passed
66 	PROPERTY_HINT_RESOURCE_TYPE, ///< a resource object type
67 	PROPERTY_HINT_MULTILINE_TEXT, ///< used for string properties that can contain multiple lines
68 	PROPERTY_HINT_COLOR_NO_ALPHA, ///< used for ignoring alpha component when editing a color
69 	PROPERTY_HINT_IMAGE_COMPRESS_LOSSY,
70 	PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS,
71 	PROPERTY_HINT_OBJECT_ID,
72 	PROPERTY_HINT_MAX,
73 };
74 
75 enum PropertyUsageFlags {
76 
77 	PROPERTY_USAGE_STORAGE = 1,
78 	PROPERTY_USAGE_EDITOR = 2,
79 	PROPERTY_USAGE_NETWORK = 4,
80 	PROPERTY_USAGE_EDITOR_HELPER = 8,
81 	PROPERTY_USAGE_CHECKABLE = 16, //used for editing global variables
82 	PROPERTY_USAGE_CHECKED = 32, //used for editing global variables
83 	PROPERTY_USAGE_INTERNATIONALIZED = 64, //hint for internationalized strings
84 	PROPERTY_USAGE_BUNDLE = 128, //used for optimized bundles
85 	PROPERTY_USAGE_CATEGORY = 256,
86 	PROPERTY_USAGE_STORE_IF_NONZERO = 512, //only store if nonzero
87 	PROPERTY_USAGE_STORE_IF_NONONE = 1024, //only store if false
88 	PROPERTY_USAGE_NO_INSTANCE_STATE = 2048,
89 	PROPERTY_USAGE_RESTART_IF_CHANGED = 4096,
90 	PROPERTY_USAGE_SCRIPT_VARIABLE = 8192,
91 	PROPERTY_USAGE_STORE_IF_NULL = 16384,
92 	PROPERTY_USAGE_ANIMATE_AS_TRIGGER = 32768,
93 
94 	PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE = 1 << 17,
95 
96 	PROPERTY_USAGE_DEFAULT = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK,
97 	PROPERTY_USAGE_DEFAULT_INTL = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK | PROPERTY_USAGE_INTERNATIONALIZED,
98 	PROPERTY_USAGE_NOEDITOR = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_NETWORK,
99 };
100 
101 #define ADD_SIGNAL(m_signal) ObjectTypeDB::add_signal(get_type_static(), m_signal)
102 #define ADD_PROPERTY(m_property, m_setter, m_getter) ObjectTypeDB::add_property(get_type_static(), m_property, m_setter, m_getter)
103 #define ADD_PROPERTYI(m_property, m_setter, m_getter, m_index) ObjectTypeDB::add_property(get_type_static(), m_property, m_setter, m_getter, m_index)
104 #define ADD_PROPERTYNZ(m_property, m_setter, m_getter) ObjectTypeDB::add_property(get_type_static(), (m_property).added_usage(PROPERTY_USAGE_STORE_IF_NONZERO), m_setter, m_getter)
105 #define ADD_PROPERTYINZ(m_property, m_setter, m_getter, m_index) ObjectTypeDB::add_property(get_type_static(), (m_property).added_usage(PROPERTY_USAGE_STORE_IF_NONZERO), m_setter, m_getter, m_index)
106 #define ADD_PROPERTYNO(m_property, m_setter, m_getter) ObjectTypeDB::add_property(get_type_static(), (m_property).added_usage(PROPERTY_USAGE_STORE_IF_NONONE), m_setter, m_getter)
107 #define ADD_PROPERTYINO(m_property, m_setter, m_getter, m_index) ObjectTypeDB::add_property(get_type_static(), (m_property).added_usage(PROPERTY_USAGE_STORE_IF_NONONE), m_setter, m_getter, m_index)
108 
109 struct PropertyInfo {
110 
111 	Variant::Type type;
112 	String name;
113 	PropertyHint hint;
114 	String hint_string;
115 	uint32_t usage;
116 
added_usagePropertyInfo117 	_FORCE_INLINE_ PropertyInfo added_usage(int p_fl) const {
118 		PropertyInfo pi = *this;
119 		pi.usage |= p_fl;
120 		return pi;
121 	}
122 
PropertyInfoPropertyInfo123 	PropertyInfo() {
124 		type = Variant::NIL;
125 		hint = PROPERTY_HINT_NONE;
126 		usage = PROPERTY_USAGE_DEFAULT;
127 	}
128 	PropertyInfo(Variant::Type p_type, const String p_name, PropertyHint p_hint = PROPERTY_HINT_NONE, const String &p_hint_string = "", uint32_t p_usage = PROPERTY_USAGE_DEFAULT) {
129 		type = p_type;
130 		name = p_name;
131 		hint = p_hint;
132 		hint_string = p_hint_string;
133 		usage = p_usage;
134 	}
135 	bool operator<(const PropertyInfo &p_info) const {
136 		return name < p_info.name;
137 	}
138 };
139 
140 Array convert_property_list(const List<PropertyInfo> *p_list);
141 
142 struct MethodInfo {
143 
144 	String name;
145 	List<PropertyInfo> arguments;
146 	Vector<Variant> default_arguments;
147 	PropertyInfo return_val;
148 	uint32_t flags;
149 	int id;
150 
151 	inline bool operator<(const MethodInfo &p_method) const { return id == p_method.id ? (name < p_method.name) : (id < p_method.id); }
152 
153 	MethodInfo();
154 	MethodInfo(const String &p_name);
155 	MethodInfo(const String &p_name, const PropertyInfo &p_param1);
156 	MethodInfo(const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2);
157 	MethodInfo(const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3);
158 	MethodInfo(const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4);
159 	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);
160 	MethodInfo(Variant::Type ret);
161 	MethodInfo(Variant::Type ret, const String &p_name);
162 	MethodInfo(Variant::Type ret, const String &p_name, const PropertyInfo &p_param1);
163 	MethodInfo(Variant::Type ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2);
164 	MethodInfo(Variant::Type ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3);
165 	MethodInfo(Variant::Type ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4);
166 	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);
167 };
168 
169 // old cast_to
170 //if ( is_type(T::get_type_static()) )
171 //return static_cast<T*>(this);
172 ////else
173 //return NULL;
174 
175 /*
176    the following is an uncomprehensible blob of hacks and workarounds to compensate for many of the fallencies in C++. As a plus, this macro pretty much alone defines the object model.
177 */
178 
179 #define REVERSE_GET_PROPERTY_LIST                                  \
180 public:                                                            \
181 	_FORCE_INLINE_ bool _is_gpl_reversed() const { return true; }; \
182                                                                    \
183 private:
184 
185 #define UNREVERSE_GET_PROPERTY_LIST                                 \
186 public:                                                             \
187 	_FORCE_INLINE_ bool _is_gpl_reversed() const { return false; }; \
188                                                                     \
189 private:
190 
191 #define OBJ_TYPE(m_type, m_inherits)                                                                                                 \
192 private:                                                                                                                             \
193 	void operator=(const m_type &p_rval) {}                                                                                          \
194 	mutable StringName _type_name;                                                                                                   \
195 	friend class ObjectTypeDB;                                                                                                       \
196                                                                                                                                      \
197 public:                                                                                                                              \
198 	virtual String get_type() const {                                                                                                \
199 		return String(#m_type);                                                                                                      \
200 	}                                                                                                                                \
201 	virtual const StringName *_get_type_namev() const {                                                                              \
202 		if (!_type_name)                                                                                                             \
203 			_type_name = get_type_static();                                                                                          \
204 		return &_type_name;                                                                                                          \
205 	}                                                                                                                                \
206 	static _FORCE_INLINE_ void *get_type_ptr_static() {                                                                              \
207 		static int ptr;                                                                                                              \
208 		return &ptr;                                                                                                                 \
209 	}                                                                                                                                \
210 	static _FORCE_INLINE_ String get_type_static() {                                                                                 \
211 		return String(#m_type);                                                                                                      \
212 	}                                                                                                                                \
213 	static _FORCE_INLINE_ String get_parent_type_static() {                                                                          \
214 		return m_inherits::get_type_static();                                                                                        \
215 	}                                                                                                                                \
216 	static void get_inheritance_list_static(List<String> *p_inheritance_list) {                                                      \
217 		m_inherits::get_inheritance_list_static(p_inheritance_list);                                                                 \
218 		p_inheritance_list->push_back(String(#m_type));                                                                              \
219 	}                                                                                                                                \
220 	static String get_category_static() {                                                                                            \
221 		String category = m_inherits::get_category_static();                                                                         \
222 		if (_get_category != m_inherits::_get_category) {                                                                            \
223 			if (category != "")                                                                                                      \
224 				category += "/";                                                                                                     \
225 			category += _get_category();                                                                                             \
226 		}                                                                                                                            \
227 		return category;                                                                                                             \
228 	}                                                                                                                                \
229 	static String inherits_static() {                                                                                                \
230 		return String(#m_inherits);                                                                                                  \
231 	}                                                                                                                                \
232 	virtual bool is_type(const String &p_type) const { return (p_type == (#m_type)) ? true : m_inherits::is_type(p_type); }          \
233 	virtual bool is_type_ptr(void *p_ptr) const { return (p_ptr == get_type_ptr_static()) ? true : m_inherits::is_type_ptr(p_ptr); } \
234                                                                                                                                      \
235 	static void get_valid_parents_static(List<String> *p_parents) {                                                                  \
236                                                                                                                                      \
237 		if (m_type::_get_valid_parents_static != m_inherits::_get_valid_parents_static) {                                            \
238 			m_type::_get_valid_parents_static(p_parents);                                                                            \
239 		}                                                                                                                            \
240                                                                                                                                      \
241 		m_inherits::get_valid_parents_static(p_parents);                                                                             \
242 	}                                                                                                                                \
243                                                                                                                                      \
244 protected:                                                                                                                           \
245 	_FORCE_INLINE_ static void (*_get_bind_methods())() {                                                                            \
246 		return &m_type::_bind_methods;                                                                                               \
247 	}                                                                                                                                \
248                                                                                                                                      \
249 public:                                                                                                                              \
250 	static void initialize_type() {                                                                                                  \
251 		static bool initialized = false;                                                                                             \
252 		if (initialized)                                                                                                             \
253 			return;                                                                                                                  \
254 		m_inherits::initialize_type();                                                                                               \
255 		ObjectTypeDB::_add_type<m_type>();                                                                                           \
256 		if (m_type::_get_bind_methods() != m_inherits::_get_bind_methods())                                                          \
257 			_bind_methods();                                                                                                         \
258 		initialized = true;                                                                                                          \
259 	}                                                                                                                                \
260                                                                                                                                      \
261 protected:                                                                                                                           \
262 	virtual void _initialize_typev() {                                                                                               \
263 		initialize_type();                                                                                                           \
264 	}                                                                                                                                \
265 	_FORCE_INLINE_ bool (Object::*(_get_get() const))(const StringName &p_name, Variant &) const {                                   \
266 		return (bool (Object::*)(const StringName &, Variant &) const) & m_type::_get;                                               \
267 	}                                                                                                                                \
268 	virtual bool _getv(const StringName &p_name, Variant &r_ret) const {                                                             \
269 		if (m_type::_get_get() != m_inherits::_get_get()) {                                                                          \
270 			if (_get(p_name, r_ret))                                                                                                 \
271 				return true;                                                                                                         \
272 		}                                                                                                                            \
273 		return m_inherits::_getv(p_name, r_ret);                                                                                     \
274 	}                                                                                                                                \
275 	_FORCE_INLINE_ bool (Object::*(_get_set() const))(const StringName &p_name, const Variant &p_property) {                         \
276 		return (bool (Object::*)(const StringName &, const Variant &)) & m_type::_set;                                               \
277 	}                                                                                                                                \
278 	virtual bool _setv(const StringName &p_name, const Variant &p_property) {                                                        \
279 		if (m_inherits::_setv(p_name, p_property)) return true;                                                                      \
280 		if (m_type::_get_set() != m_inherits::_get_set()) {                                                                          \
281 			return _set(p_name, p_property);                                                                                         \
282 		}                                                                                                                            \
283 		return false;                                                                                                                \
284 	}                                                                                                                                \
285 	_FORCE_INLINE_ void (Object::*(_get_get_property_list() const))(List<PropertyInfo> * p_list) const {                             \
286 		return (void (Object::*)(List<PropertyInfo> *) const) & m_type::_get_property_list;                                          \
287 	}                                                                                                                                \
288 	virtual void _get_property_listv(List<PropertyInfo> *p_list, bool p_reversed) const {                                            \
289 		if (!p_reversed) {                                                                                                           \
290 			m_inherits::_get_property_listv(p_list, p_reversed);                                                                     \
291 		}                                                                                                                            \
292 		p_list->push_back(PropertyInfo(Variant::NIL, get_type_static(), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY));     \
293 		if (!_is_gpl_reversed())                                                                                                     \
294 			ObjectTypeDB::get_property_list(#m_type, p_list, true, this);                                                            \
295 		if (m_type::_get_get_property_list() != m_inherits::_get_get_property_list()) {                                              \
296 			_get_property_list(p_list);                                                                                              \
297 		}                                                                                                                            \
298 		if (_is_gpl_reversed())                                                                                                      \
299 			ObjectTypeDB::get_property_list(#m_type, p_list, true, this);                                                            \
300 		if (p_reversed) {                                                                                                            \
301 			m_inherits::_get_property_listv(p_list, p_reversed);                                                                     \
302 		}                                                                                                                            \
303 	}                                                                                                                                \
304 	_FORCE_INLINE_ void (Object::*(_get_notification() const))(int) {                                                                \
305 		return (void (Object::*)(int)) & m_type::_notification;                                                                      \
306 	}                                                                                                                                \
307 	virtual void _notificationv(int p_notification, bool p_reversed) {                                                               \
308 		if (!p_reversed)                                                                                                             \
309 			m_inherits::_notificationv(p_notification, p_reversed);                                                                  \
310 		if (m_type::_get_notification() != m_inherits::_get_notification()) {                                                        \
311 			_notification(p_notification);                                                                                           \
312 		}                                                                                                                            \
313 		if (p_reversed)                                                                                                              \
314 			m_inherits::_notificationv(p_notification, p_reversed);                                                                  \
315 	}                                                                                                                                \
316                                                                                                                                      \
317 private:
318 
319 #define OBJ_CATEGORY(m_category)                                        \
320 protected:                                                              \
321 	_FORCE_INLINE_ static String _get_category() { return m_category; } \
322                                                                         \
323 private:
324 
325 #define OBJ_SAVE_TYPE(m_type)                                \
326 public:                                                      \
327 	virtual String get_save_type() const { return #m_type; } \
328                                                              \
329 private:
330 
331 class ScriptInstance;
332 typedef uint32_t ObjectID;
333 
334 class Object {
335 public:
336 	enum ConnectFlags {
337 
338 		CONNECT_DEFERRED = 1,
339 		CONNECT_PERSIST = 2, // hint for scene to save this connection
340 		CONNECT_ONESHOT = 4
341 	};
342 
343 	struct Connection {
344 
345 		Object *source;
346 		StringName signal;
347 		Object *target;
348 		StringName method;
349 		uint32_t flags;
350 		Vector<Variant> binds;
351 		bool operator<(const Connection &p_conn) const;
352 
353 		operator Variant() const;
ConnectionConnection354 		Connection() {
355 			source = NULL;
356 			target = NULL;
357 			flags = 0;
358 		}
359 		Connection(const Variant &p_variant);
360 	};
361 
362 private:
363 #ifdef DEBUG_ENABLED
364 	friend class _ObjectDebugLock;
365 #endif
366 	friend bool predelete_handler(Object *);
367 	friend void postinitialize_handler(Object *);
368 
369 	struct Signal {
370 
371 		struct Target {
372 
373 			ObjectID _id;
374 			StringName method;
375 
376 			_FORCE_INLINE_ bool operator<(const Target &p_target) const { return (_id == p_target._id) ? (method < p_target.method) : (_id < p_target._id); }
377 
TargetSignal::Target378 			Target(const ObjectID &p_id, const StringName &p_method) {
379 				_id = p_id;
380 				method = p_method;
381 			}
TargetSignal::Target382 			Target() { _id = 0; }
383 		};
384 
385 		struct Slot {
386 
387 			Connection conn;
388 			List<Connection>::Element *cE;
389 		};
390 
391 		MethodInfo user;
392 		VMap<Target, Slot> slot_map;
393 		int lock;
SignalSignal394 		Signal() { lock = 0; }
395 	};
396 
397 	HashMap<StringName, Signal, StringNameHasher> signal_map;
398 	List<Connection> connections;
399 #ifdef DEBUG_ENABLED
400 	SafeRefCount _lock_index;
401 #endif
402 	bool _block_signals;
403 	int _predelete_ok;
404 	Set<Object *> change_receptors;
405 	uint32_t _instance_ID;
406 	bool _predelete();
407 	void _postinitialize();
408 	bool _can_translate;
409 #ifdef TOOLS_ENABLED
410 	bool _edited;
411 	uint32_t _edited_version;
412 #endif
413 	ScriptInstance *script_instance;
414 	RefPtr script;
415 	Dictionary metadata;
416 	mutable StringName _type_name;
417 	mutable const StringName *_type_ptr;
418 
419 	void _add_user_signal(const String &p_name, const Array &p_pargs = Array());
420 	bool _has_user_signal(const StringName &p_name) const;
421 	Variant _emit_signal(const Variant **p_args, int p_argcount, Variant::CallError &r_error);
422 	Array _get_signal_list() const;
423 	Array _get_signal_connection_list(const String &p_signal) const;
424 	void _set_bind(const String &p_set, const Variant &p_value);
425 	Variant _get_bind(const String &p_name) const;
426 
427 	void property_list_changed_notify();
428 
429 protected:
_use_builtin_script()430 	virtual bool _use_builtin_script() const { return false; }
_initialize_typev()431 	virtual void _initialize_typev() { initialize_type(); }
_setv(const StringName & p_name,const Variant & p_property)432 	virtual bool _setv(const StringName &p_name, const Variant &p_property) { return false; };
_getv(const StringName & p_name,Variant & r_property)433 	virtual bool _getv(const StringName &p_name, Variant &r_property) const { return false; };
_get_property_listv(List<PropertyInfo> * p_list,bool p_reversed)434 	virtual void _get_property_listv(List<PropertyInfo> *p_list, bool p_reversed) const {};
_notificationv(int p_notification,bool p_reversed)435 	virtual void _notificationv(int p_notification, bool p_reversed){};
436 
_get_category()437 	static String _get_category() { return ""; }
438 	static void _bind_methods();
_set(const StringName & p_name,const Variant & p_property)439 	bool _set(const StringName &p_name, const Variant &p_property) { return false; };
_get(const StringName & p_name,Variant & r_property)440 	bool _get(const StringName &p_name, Variant &r_property) const { return false; };
_get_property_list(List<PropertyInfo> * p_list)441 	void _get_property_list(List<PropertyInfo> *p_list) const {};
_notification(int p_notification)442 	void _notification(int p_notification){};
443 
_get_bind_methods()444 	_FORCE_INLINE_ static void (*_get_bind_methods())() {
445 		return &Object::_bind_methods;
446 	}
447 	_FORCE_INLINE_ bool (Object::*(_get_get() const))(const StringName &p_name, Variant &r_ret) const {
448 		return &Object::_get;
449 	}
450 	_FORCE_INLINE_ bool (Object::*(_get_set() const))(const StringName &p_name, const Variant &p_property) {
451 		return &Object::_set;
452 	}
453 	_FORCE_INLINE_ void (Object::*(_get_get_property_list() const))(List<PropertyInfo> *p_list) const {
454 		return &Object::_get_property_list;
455 	}
456 	_FORCE_INLINE_ void (Object::*(_get_notification() const))(int) {
457 		return &Object::_notification;
458 	}
459 	static void get_valid_parents_static(List<String> *p_parents);
460 	static void _get_valid_parents_static(List<String> *p_parents);
461 
462 	void cancel_delete();
463 
464 	virtual void _changed_callback(Object *p_changed, const char *p_prop);
465 
466 	//Variant _call_bind(const StringName& p_name, const Variant& p_arg1 = Variant(), const Variant& p_arg2 = Variant(), const Variant& p_arg3 = Variant(), const Variant& p_arg4 = Variant());
467 	//void _call_deferred_bind(const StringName& p_name, const Variant& p_arg1 = Variant(), const Variant& p_arg2 = Variant(), const Variant& p_arg3 = Variant(), const Variant& p_arg4 = Variant());
468 
469 	Variant _call_bind(const Variant **p_args, int p_argcount, Variant::CallError &r_error);
470 	Variant _call_deferred_bind(const Variant **p_args, int p_argcount, Variant::CallError &r_error);
471 
_get_type_namev()472 	virtual const StringName *_get_type_namev() const {
473 		if (!_type_name)
474 			_type_name = get_type_static();
475 		return &_type_name;
476 	}
477 
478 	DVector<String> _get_meta_list_bind() const;
479 	Array _get_property_list_bind() const;
480 	Array _get_method_list_bind() const;
481 
482 	void _clear_internal_resource_paths(const Variant &p_var);
483 
484 	friend class ObjectTypeDB;
485 	virtual void _validate_property(PropertyInfo &property) const;
486 
487 public: //should be protected, but bug in clang++
488 	static void initialize_type();
register_custom_data_to_otdb()489 	_FORCE_INLINE_ static void register_custom_data_to_otdb(){};
490 
491 public:
492 #ifdef TOOLS_ENABLED
493 	_FORCE_INLINE_ void _change_notify(const char *p_property = "") {
494 		_edited = true;
495 		for (Set<Object *>::Element *E = change_receptors.front(); E; E = E->next())
496 			((Object *)(E->get()))->_changed_callback(this, p_property);
497 	}
498 #else
499 	_FORCE_INLINE_ void _change_notify(const char *p_what = "") {}
500 #endif
get_type_ptr_static()501 	static void *get_type_ptr_static() {
502 		static int ptr;
503 		return &ptr;
504 	}
505 
_is_gpl_reversed()506 	bool _is_gpl_reversed() const { return false; }
507 
get_instance_ID()508 	_FORCE_INLINE_ ObjectID get_instance_ID() const { return _instance_ID; }
509 	// this is used for editors
510 
511 	void add_change_receptor(Object *p_receptor);
512 	void remove_change_receptor(Object *p_receptor);
513 
514 // TODO: ensure 'this' is never NULL since it's UB, but by now, avoid warning flood
515 #ifdef __clang__
516 #pragma clang diagnostic push
517 #pragma clang diagnostic ignored "-Wundefined-bool-conversion"
518 #endif
519 
520 	template <class T>
cast_to()521 	T *cast_to() {
522 
523 #ifndef NO_SAFE_CAST
524 		return SAFE_CAST<T *>(this);
525 #else
526 		if (!this)
527 			return NULL;
528 		if (is_type_ptr(T::get_type_ptr_static()))
529 			return static_cast<T *>(this);
530 		else
531 			return NULL;
532 #endif
533 	}
534 
535 	template <class T>
cast_to()536 	const T *cast_to() const {
537 
538 #ifndef NO_SAFE_CAST
539 		return SAFE_CAST<const T *>(this);
540 #else
541 		if (!this)
542 			return NULL;
543 		if (is_type_ptr(T::get_type_ptr_static()))
544 			return static_cast<const T *>(this);
545 		else
546 			return NULL;
547 #endif
548 	}
549 
550 #ifdef __clang__
551 #pragma clang diagnostic pop
552 #endif
553 
554 	enum {
555 
556 		NOTIFICATION_POSTINITIALIZE = 0,
557 		NOTIFICATION_PREDELETE = 1
558 	};
559 
560 	/* TYPE API */
get_inheritance_list_static(List<String> * p_inheritance_list)561 	static void get_inheritance_list_static(List<String> *p_inheritance_list) { p_inheritance_list->push_back("Object"); }
562 
get_type_static()563 	static String get_type_static() { return "Object"; }
get_parent_type_static()564 	static String get_parent_type_static() { return String(); }
get_category_static()565 	static String get_category_static() { return String(); }
566 
get_type()567 	virtual String get_type() const { return "Object"; }
get_save_type()568 	virtual String get_save_type() const { return get_type(); } //type stored when saving
569 
is_type(const String & p_type)570 	virtual bool is_type(const String &p_type) const { return (p_type == "Object"); }
is_type_ptr(void * p_ptr)571 	virtual bool is_type_ptr(void *p_ptr) const { return get_type_ptr_static() == p_ptr; }
572 
get_type_name()573 	_FORCE_INLINE_ const StringName &get_type_name() const {
574 		if (!_type_ptr) {
575 			return *_get_type_namev();
576 		} else {
577 			return *_type_ptr;
578 		}
579 	}
580 
581 	/* IAPI */
582 	//	void set(const String& p_name, const Variant& p_value);
583 	//	Variant get(const String& p_name) const;
584 
585 	void set(const StringName &p_name, const Variant &p_value, bool *r_valid = NULL);
586 	Variant get(const StringName &p_name, bool *r_valid = NULL) const;
587 
588 	void get_property_list(List<PropertyInfo> *p_list, bool p_reversed = false) const;
589 
590 	bool has_method(const StringName &p_method) const;
591 	void get_method_list(List<MethodInfo> *p_list) const;
592 	Variant callv(const StringName &p_method, const Array &p_args);
593 	virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error);
594 	virtual void call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount);
595 	virtual void call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount);
596 	Variant call(const StringName &p_name, VARIANT_ARG_LIST); // C++ helper
597 	void call_multilevel(const StringName &p_name, VARIANT_ARG_LIST); // C++ helper
598 
599 	void notification(int p_notification, bool p_reversed = false);
600 
601 	//used mainly by script, get and set all INCLUDING string
602 	virtual Variant getvar(const Variant &p_key, bool *r_valid = NULL) const;
603 	virtual void setvar(const Variant &p_key, const Variant &p_value, bool *r_valid = NULL);
604 
605 	/* SCRIPT */
606 
607 	void set_script(const RefPtr &p_script);
608 	RefPtr get_script() const;
609 
610 	/* SCRIPT */
611 
612 	bool has_meta(const String &p_name) const;
613 	void set_meta(const String &p_name, const Variant &p_value);
614 	Variant get_meta(const String &p_name) const;
615 	void get_meta_list(List<String> *p_list) const;
616 
617 #ifdef TOOLS_ENABLED
618 	void set_edited(bool p_edited);
619 	bool is_edited() const;
620 	uint32_t get_edited_version() const; //this function is used to check when something changed beyond a point, it's used mainly for generating previews
621 #endif
622 
623 	void set_script_instance(ScriptInstance *p_instance);
get_script_instance()624 	_FORCE_INLINE_ ScriptInstance *get_script_instance() const { return script_instance; }
625 
626 	void add_user_signal(const MethodInfo &p_signal);
627 	void emit_signal(const StringName &p_name, VARIANT_ARG_LIST);
628 	void emit_signal(const StringName &p_name, const Variant **p_args, int p_argcount);
629 	void get_signal_list(List<MethodInfo> *p_signals) const;
630 	void get_signal_connection_list(const StringName &p_signal, List<Connection> *p_connections) const;
631 	void get_all_signal_connections(List<Connection> *p_connections) const;
632 	bool has_persistent_signal_connections() const;
633 	void get_signals_connected_to_this(List<Connection> *p_connections) const;
634 
635 	Error connect(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method, const Vector<Variant> &p_binds = Vector<Variant>(), uint32_t p_flags = 0);
636 	void disconnect(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method);
637 	bool is_connected(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method) const;
638 
639 	void call_deferred(const StringName &p_method, VARIANT_ARG_LIST);
640 
641 	void set_block_signals(bool p_block);
642 	bool is_blocking_signals() const;
643 
644 	Variant::Type get_static_property_type(const StringName &p_property, bool *r_valid = NULL) const;
645 
646 	virtual void get_translatable_strings(List<String> *p_strings) const;
647 
648 	virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const;
649 
650 	StringName XL_MESSAGE(const StringName &p_message) const; //translate message (internationalization)
651 	StringName tr(const StringName &p_message) const; //translate message (alternative)
652 
653 	bool _is_queued_for_deletion; // set to true by SceneTree::queue_delete()
654 	bool is_queued_for_deletion() const;
655 
set_message_translation(bool p_enable)656 	_FORCE_INLINE_ void set_message_translation(bool p_enable) { _can_translate = p_enable; }
can_translate_messages()657 	_FORCE_INLINE_ bool can_translate_messages() const { return _can_translate; }
658 
659 	void clear_internal_resource_paths();
660 
661 	Object();
662 	virtual ~Object();
663 };
664 
665 bool predelete_handler(Object *p_object);
666 void postinitialize_handler(Object *p_object);
667 
668 class ObjectDB {
669 
670 	struct ObjectPtrHash {
671 
hashObjectPtrHash672 		static _FORCE_INLINE_ uint32_t hash(const Object *p_obj) {
673 
674 			union {
675 				const Object *p;
676 				unsigned long i;
677 			} u;
678 			u.p = p_obj;
679 			return HashMapHasherDefault::hash((uint64_t)u.i);
680 		}
681 	};
682 
683 	static HashMap<uint32_t, Object *> instances;
684 	static HashMap<Object *, ObjectID, ObjectPtrHash> instance_checks;
685 
686 	static uint32_t instance_counter;
687 	friend class Object;
688 	friend void unregister_core_types();
689 
690 	static void cleanup();
691 	static uint32_t add_instance(Object *p_object);
692 	static void remove_instance(Object *p_object);
693 
694 public:
695 	typedef void (*DebugFunc)(Object *p_obj);
696 
697 	static Object *get_instance(uint32_t p_instance_ID);
698 	static void debug_objects(DebugFunc p_func);
699 	static int get_object_count();
700 
701 #ifdef DEBUG_ENABLED
instance_validate(Object * p_ptr)702 	_FORCE_INLINE_ static bool instance_validate(Object *p_ptr) {
703 
704 		return instance_checks.has(p_ptr);
705 	}
706 #else
instance_validate(Object * p_ptr)707 	_FORCE_INLINE_ static bool instance_validate(Object *p_ptr) { return true; }
708 
709 #endif
710 };
711 
712 //needed by macros
713 #include "object_type_db.h"
714 
715 #endif
716