From 3197c3dce3d634cf3c5c74b2c42a23fe3627763f Mon Sep 17 00:00:00 2001 From: Marc Gilleron Date: Mon, 22 Jan 2018 22:27:10 +0100 Subject: [PATCH] Rewrite Ref to behave like Godot again --- binding_generator.py | 7 +- include/core/Ref.hpp | 318 ++++++++++++++++++++++++------------------- 2 files changed, 187 insertions(+), 138 deletions(-) diff --git a/binding_generator.py b/binding_generator.py index bdea3545..cff0d54e 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -72,10 +72,15 @@ def generate_class_header(used_classes, c): source.append("#include ") - source.append("#include ") class_name = strip_name(c["name"]) + # Ref is not included in object.h in Godot either, + # so don't include it here because it's not needed + if class_name != "Object": + source.append("#include ") + + included = [] for used_class in used_classes: diff --git a/include/core/Ref.hpp b/include/core/Ref.hpp index 043db576..3d06e758 100644 --- a/include/core/Ref.hpp +++ b/include/core/Ref.hpp @@ -3,156 +3,200 @@ #include "Variant.hpp" #include "GodotGlobal.hpp" +#include "../Reference.hpp" namespace godot { -template +// Replicates Godot's Ref behavior +// Rewritten from f5234e70be7dec4930c2d5a0e829ff480d044b1d. +template class Ref { - T *reference; -public: - inline bool operator==(const Ref &r) const - { - return reference == r.reference; - } - - inline bool operator!=(const Ref &r) const - { - return reference != r.reference; - } - - inline T *operator->() - { - return reference; - } - - inline T *operator*() - { - return reference; - } - - inline T *ptr() - { - return reference; - } - - inline const T *operator->() const - { - return reference; - } - - inline const T *operator*() const - { - return reference; - } - - inline const T *ptr() const - { - return reference; - } - - - - void operator=(const Ref &from) - { - if (reference) - unref(); + T *reference = NULL; - if (from.reference) { - reference = from.reference; - reference->reference(); - } else { - reference = nullptr; - } - } + void ref(const Ref &p_from) { - template - void operator=(const Ref &from) - { - if (reference) - unref(); + if (p_from.reference == reference) + return; - if (from.reference) { - reference = (T *) from.reference; - reference->reference(); - } else { - reference = nullptr; - } - } - - void operator=(const Variant &variant) - { - if (reference) - unref(); - - reference = (T *) (Object *) variant; - } - - operator Variant() const - { - return Variant((Object *) reference); - } - - template - Ref(const Ref &from) - { - if (from.reference) { - reference = (T *) from.reference; - reference->reference(); - } else { - reference = nullptr; - } - } - - Ref(const Ref &from) - { - if (from.reference) { - reference = from.reference; - reference->reference(); - } else { - reference = nullptr; - } - } - - - Ref(T *r) - { - reference = r; - } - - template - Ref(T_Other *r) : Ref((T *) r) {} - - Ref(const Variant &variant) - { - reference = (T *) (Object *) variant; - } - - inline bool is_valid() const { return reference != nullptr; } - inline bool is_null() const { return reference == nullptr; } - - void unref() - { - if (reference && reference->unreference()) { - godot::api->godot_object_destroy((godot_object *) reference); - } - reference = nullptr; - } - - void instance() - { unref(); - reference = new T; + reference = p_from.reference; + if (reference) + reference->reference(); } - Ref() - { - reference = nullptr; + void ref_pointer(T *p_ref) { + + ERR_FAIL_COND(!p_ref); + + if (p_ref->init_ref()) + reference = p_ref; } - - ~Ref() - { + +public: + inline bool operator<(const Ref &p_r) const { + + return reference < p_r.reference; + } + inline bool operator==(const Ref &p_r) const { + + return reference == p_r.reference; + } + inline bool operator!=(const Ref &p_r) const { + + return reference != p_r.reference; + } + + inline T *operator->() { + + return reference; + } + + inline T *operator*() { + + return reference; + } + + inline const T *operator->() const { + + return reference; + } + + inline const T *ptr() const { + + return reference; + } + inline T *ptr() { + + return reference; + } + + inline const T *operator*() const { + + return reference; + } + + operator Variant() const { + // Note: the C API handles the cases where the object is a Reference, + // so the Variant will be correctly constructed with a RefPtr engine-side + return Variant((Object*)reference); + } + + void operator=(const Ref &p_from) { + + ref(p_from); + } + + template + void operator=(const Ref &p_from) { + + // TODO We need a safe cast + Reference *refb = const_cast(static_cast(p_from.ptr())); + if (!refb) { + unref(); + return; + } + Ref r; + //r.reference = Object::cast_to(refb); + r.reference = (T*)refb; + ref(r); + r.reference = NULL; + } + + void operator=(const Variant &p_variant) { + + // TODO We need a safe cast + Reference *refb = (Reference *) (Object *) p_variant; + if (!refb) { + unref(); + return; + } + Ref r; + // TODO We need a safe cast + //r.reference = Object::cast_to(refb); + r.reference = (T *)refb; + ref(r); + r.reference = NULL; + } + + Ref(const Ref &p_from) { + + reference = NULL; + ref(p_from); + } + + template + Ref(const Ref &p_from) { + + reference = NULL; + // TODO We need a safe cast + Reference *refb = const_cast(static_cast(p_from.ptr())); + if (!refb) { + unref(); + return; + } + Ref r; + // TODO We need a safe cast + //r.reference = Object::cast_to(refb); + r.reference = (T *)refb; + ref(r); + r.reference = NULL; + } + + Ref(T *p_reference) { + + if (p_reference) + ref_pointer(p_reference); + else + reference = NULL; + } + + Ref(const Variant &p_variant) { + + reference = NULL; + // TODO We need a safe cast + Reference *refb = (Reference *) (Object *) p_variant; + if (!refb) { + unref(); + return; + } + Ref r; + // TODO We need a safe cast + //r.reference = Object::cast_to(refb); + r.reference = (T *)refb; + ref(r); + r.reference = NULL; + } + + inline bool is_valid() const { return reference != NULL; } + inline bool is_null() const { return reference == NULL; } + + void unref() { + //TODO this should be moved to mutexes, since this engine does not really + // do a lot of referencing on references and stuff + // mutexes will avoid more crashes? + + if (reference && reference->unreference()) { + + //memdelete(reference); + delete reference; + } + reference = NULL; + } + + void instance() { + //ref(memnew(T)); + ref(new T); + } + + Ref() { + + reference = NULL; + } + + ~Ref() { + unref(); } };