mirror of
https://github.com/Relintai/sfw.git
synced 2024-12-20 21:06:49 +01:00
288 lines
13 KiB
C++
288 lines
13 KiB
C++
//--STRIP
|
|
#ifndef OBJECT_H
|
|
#define OBJECT_H
|
|
//--STRIP
|
|
|
|
//--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 { \
|
|
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<String> *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 { \
|
|
return (p_class == (#m_class)) ? true : m_inherits::is_class(p_class); \
|
|
} \
|
|
virtual bool is_class_ptr(void *p_ptr) const { \
|
|
return (p_ptr == get_class_ptr_static()) ? true : m_inherits::is_class_ptr(p_ptr); \
|
|
} \
|
|
static void get_valid_parents_static(Vector<String> *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<String> *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<String> *p_parents) {}
|
|
static void _get_valid_parents_static(Vector<String> *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<String> *p_list) const;
|
|
|
|
Object();
|
|
virtual ~Object();
|
|
|
|
template <class T>
|
|
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<T *>(p_object);
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
template <class T>
|
|
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<const T *>(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<ObjectRC *> _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<ObjectID, Object *> instances;
|
|
static HashMap<Object *, ObjectID, ObjectPtrHash> 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;
|
|
}
|
|
};
|
|
|
|
//--STRIP
|
|
#endif
|
|
//--STRIP
|