#ifndef OBJECT_H #define OBJECT_H //--STRIP #include "core/hash_map.h" #include "core/rw_lock.h" #include "core/string_name.h" #include "core/ustring.h" #include "core/vector.h" #include "object/object_id.h" #include "object/variant.h" #include "object/dictionary.h" //--STRIP /*************************************************************************/ /* object.h */ /* From https://github.com/Relintai/pandemonium_engine (MIT) */ /*************************************************************************/ class ObjectRC; #define SFW_OBJECT(m_class, m_inherits) \ private: \ void operator=(const m_class &p_rval) {} \ \ public: \ virtual String get_class() const override { \ return String(#m_class); \ } \ virtual const StringName *_get_class_namev() const { \ if (!_class_name) \ _class_name = get_class_static(); \ return &_class_name; \ } \ static void *get_class_ptr_static() { \ static int ptr; \ return &ptr; \ } \ static String get_class_static() { \ return String(#m_class); \ } \ static String get_parent_class_static() { \ return m_inherits::get_class_static(); \ } \ static void get_inheritance_list_static(Vector *p_inheritance_list) { \ m_inherits::get_inheritance_list_static(p_inheritance_list); \ p_inheritance_list->push_back(String(#m_class)); \ } \ static String inherits_static() { \ return String(#m_inherits); \ } \ virtual bool is_class(const String &p_class) const override { \ return (p_class == (#m_class)) ? true : m_inherits::is_class(p_class); \ } \ virtual bool is_class_ptr(void *p_ptr) const override { \ return (p_ptr == get_class_ptr_static()) ? true : m_inherits::is_class_ptr(p_ptr); \ } \ static void get_valid_parents_static(Vector *p_parents) { \ if (m_class::_get_valid_parents_static != m_inherits::_get_valid_parents_static) { \ m_class::_get_valid_parents_static(p_parents); \ } \ m_inherits::get_valid_parents_static(p_parents); \ } \ _FORCE_INLINE_ void (Object::*_get_notification() const)(int) { \ return (void(Object::*)(int)) & m_class::_notification; \ } \ virtual void _notificationv(int p_notification, bool p_reversed) { \ if (!p_reversed) \ m_inherits::_notificationv(p_notification, p_reversed); \ if (m_class::_get_notification() != m_inherits::_get_notification()) { \ _notification(p_notification); \ } \ if (p_reversed) \ m_inherits::_notificationv(p_notification, p_reversed); \ } \ _FORCE_INLINE_ bool (Object::*_get_get() const)(const StringName &p_name, Variant &) const { \ return (bool(Object::*)(const StringName &, Variant &) const) & m_class::_get; \ } \ virtual bool _getv(const StringName &p_name, Variant &r_ret) const { \ if (m_class::_get_get() != m_inherits::_get_get()) { \ if (_get(p_name, r_ret)) \ return true; \ } \ return m_inherits::_getv(p_name, r_ret); \ } \ _FORCE_INLINE_ bool (Object::*_get_set() const)(const StringName &p_name, const Variant &p_property) { \ return (bool(Object::*)(const StringName &, const Variant &)) & m_class::_set; \ } \ virtual bool _setv(const StringName &p_name, const Variant &p_property) { \ if (m_inherits::_setv(p_name, p_property)) \ return true; \ if (m_class::_get_set() != m_inherits::_get_set()) { \ return _set(p_name, p_property); \ } \ return false; \ } \ \ private: class Object { public: enum { NOTIFICATION_POSTINITIALIZE = 0, NOTIFICATION_PREDELETE = 1 }; void set(const StringName &p_name, const Variant &p_value, bool *r_valid = nullptr); Variant get(const StringName &p_name, bool *r_valid = nullptr) const; //less than. < "operator" used for cutrom sorting Arrays. virtual bool lt(const Variant &p_value_l, const Variant &p_value_r); virtual String get_class() const { return "Object"; } static void *get_class_ptr_static() { static int ptr; return &ptr; } static String get_class_static() { return "Object"; } static String get_parent_class_static() { return String(); } static void get_inheritance_list_static(Vector *p_inheritance_list) { p_inheritance_list->push_back("Object"); } virtual bool is_class(const String &p_class) const { return (p_class == "Object"); } virtual bool is_class_ptr(void *p_ptr) const { return get_class_ptr_static() == p_ptr; } static void get_valid_parents_static(Vector *p_parents) {} static void _get_valid_parents_static(Vector *p_parents) {} virtual const StringName *_get_class_namev() const { if (!_class_name) { _class_name = get_class_static(); } return &_class_name; } _FORCE_INLINE_ const StringName &get_class_name() const { if (!_class_ptr) { return *_get_class_namev(); } else { return *_class_ptr; } } ObjectRC *_use_rc(); _FORCE_INLINE_ ObjectID get_instance_id() const { return _instance_id; } void notification(int p_notification, bool p_reversed = false); virtual String to_string(); bool _is_queued_for_deletion; bool is_queued_for_deletion() const { return _is_queued_for_deletion; } void cancel_free(); bool has_meta(const String &p_name) const; void set_meta(const String &p_name, const Variant &p_value); void remove_meta(const String &p_name); Variant get_meta(const String &p_name, const Variant &p_default = Variant()) const; void get_meta_list(List *p_list) const; Object(); virtual ~Object(); template static T *cast_to(Object *p_object) { if (!p_object) return NULL; if (p_object->is_class_ptr(T::get_class_ptr_static())) return static_cast(p_object); else return NULL; } template static const T *cast_to(const Object *p_object) { if (!p_object) return NULL; if (p_object->is_class_ptr(T::get_class_ptr_static())) return static_cast(p_object); else return NULL; } protected: _FORCE_INLINE_ void (Object::*_get_notification() const)(int) { return &Object::_notification; } bool _set(const StringName &p_name, const Variant &p_property) { return false; }; bool _get(const StringName &p_name, Variant &r_property) const { return false; }; virtual bool _setv(const StringName &p_name, const Variant &p_property) { return false; }; virtual bool _getv(const StringName &p_name, Variant &r_property) const { return false; }; _FORCE_INLINE_ bool (Object::*_get_get() const)(const StringName &p_name, Variant &r_ret) const { return &Object::_get; } _FORCE_INLINE_ bool (Object::*_get_set() const)(const StringName &p_name, const Variant &p_property) { return &Object::_set; } virtual void _notificationv(int p_notification, bool p_reversed){}; void _notification(int p_notification){}; friend bool predelete_handler(Object *); friend void postinitialize_handler(Object *); int _predelete_ok; bool _predelete(); void _postinitialize(); mutable StringName _class_name; mutable const StringName *_class_ptr; ObjectID _instance_id; std::atomic _rc; Dictionary metadata; }; bool predelete_handler(Object *p_object); void postinitialize_handler(Object *p_object); class ObjectDB { struct ObjectPtrHash { static _FORCE_INLINE_ uint32_t hash(const Object *p_obj) { union { const Object *p; unsigned long i; } u; u.p = p_obj; return HashMapHasherDefault::hash((uint64_t)u.i); } }; static HashMap instances; static HashMap instance_checks; static ObjectID instance_counter; friend class Object; friend void unregister_core_types(); static RWLock rw_lock; static void cleanup(); static ObjectID add_instance(Object *p_object); static void remove_instance(Object *p_object); friend void register_core_types(); public: typedef void (*DebugFunc)(Object *p_obj); static Object *get_instance(ObjectID p_instance_id); static void debug_objects(DebugFunc p_func); static int get_object_count(); // This one may give false positives because a new object may be allocated at the same memory of a previously freed one _FORCE_INLINE_ static bool instance_validate(Object *p_ptr) { rw_lock.read_lock(); bool exists = instance_checks.has(p_ptr); rw_lock.read_unlock(); return exists; } }; #endif