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