Ref.hpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. #ifndef REF_H
  2. #define REF_H
  3. #include "GodotGlobal.hpp"
  4. #include "Reference.hpp"
  5. #include "Variant.hpp"
  6. namespace godot {
  7. // Replicates Godot's Ref<T> behavior
  8. // Rewritten from f5234e70be7dec4930c2d5a0e829ff480d044b1d.
  9. template <class T>
  10. class Ref {
  11. T *reference = nullptr;
  12. void ref(const Ref &p_from) {
  13. if (p_from.reference == reference)
  14. return;
  15. unref();
  16. reference = p_from.reference;
  17. if (reference)
  18. reference->reference();
  19. }
  20. void ref_pointer(T *p_ref) {
  21. ERR_FAIL_COND(!p_ref);
  22. if (p_ref->init_ref())
  23. reference = p_ref;
  24. }
  25. public:
  26. inline bool operator<(const Ref<T> &p_r) const {
  27. return reference < p_r.reference;
  28. }
  29. inline bool operator==(const Ref<T> &p_r) const {
  30. return reference == p_r.reference;
  31. }
  32. inline bool operator!=(const Ref<T> &p_r) const {
  33. return reference != p_r.reference;
  34. }
  35. inline T *operator->() {
  36. return reference;
  37. }
  38. inline T *operator*() {
  39. return reference;
  40. }
  41. inline const T *operator->() const {
  42. return reference;
  43. }
  44. inline const T *ptr() const {
  45. return reference;
  46. }
  47. inline T *ptr() {
  48. return reference;
  49. }
  50. inline const T *operator*() const {
  51. return reference;
  52. }
  53. operator Variant() const {
  54. // Note: the C API handles the cases where the object is a Reference,
  55. // so the Variant will be correctly constructed with a RefPtr engine-side
  56. return Variant((Object *)reference);
  57. }
  58. void operator=(const Ref &p_from) {
  59. ref(p_from);
  60. }
  61. template <class T_Other>
  62. void operator=(const Ref<T_Other> &p_from) {
  63. // TODO We need a safe cast
  64. Reference *refb = const_cast<Reference *>(static_cast<const Reference *>(p_from.ptr()));
  65. if (!refb) {
  66. unref();
  67. return;
  68. }
  69. Ref r;
  70. //r.reference = Object::cast_to<T>(refb);
  71. r.reference = (T *)refb;
  72. ref(r);
  73. r.reference = nullptr;
  74. }
  75. void operator=(const Variant &p_variant) {
  76. // TODO We need a safe cast
  77. Reference *refb = (Reference *)T::___get_from_variant(p_variant);
  78. if (!refb) {
  79. unref();
  80. return;
  81. }
  82. Ref r;
  83. // TODO We need a safe cast
  84. //r.reference = Object::cast_to<T>(refb);
  85. r.reference = (T *)refb;
  86. ref(r);
  87. r.reference = nullptr;
  88. }
  89. Ref(const Ref &p_from) {
  90. reference = nullptr;
  91. ref(p_from);
  92. }
  93. template <class T_Other>
  94. Ref(const Ref<T_Other> &p_from) {
  95. reference = nullptr;
  96. // TODO We need a safe cast
  97. Reference *refb = const_cast<Reference *>(static_cast<const Reference *>(p_from.ptr()));
  98. if (!refb) {
  99. unref();
  100. return;
  101. }
  102. Ref r;
  103. // TODO We need a safe cast
  104. //r.reference = Object::cast_to<T>(refb);
  105. r.reference = (T *)refb;
  106. ref(r);
  107. r.reference = nullptr;
  108. }
  109. Ref(T *p_reference) {
  110. if (p_reference)
  111. ref_pointer(p_reference);
  112. else
  113. reference = nullptr;
  114. }
  115. Ref(const Variant &p_variant) {
  116. reference = nullptr;
  117. // TODO We need a safe cast
  118. Reference *refb = (Reference *)T::___get_from_variant(p_variant);
  119. if (!refb) {
  120. unref();
  121. return;
  122. }
  123. Ref r;
  124. // TODO We need a safe cast
  125. //r.reference = Object::cast_to<T>(refb);
  126. r.reference = (T *)refb;
  127. ref(r);
  128. r.reference = nullptr;
  129. }
  130. inline bool is_valid() const { return reference != nullptr; }
  131. inline bool is_null() const { return reference == nullptr; }
  132. void unref() {
  133. //TODO this should be moved to mutexes, since this engine does not really
  134. // do a lot of referencing on references and stuff
  135. // mutexes will avoid more crashes?
  136. if (reference && reference->unreference()) {
  137. //memdelete(reference);
  138. reference->free();
  139. }
  140. reference = nullptr;
  141. }
  142. void instance() {
  143. //ref(memnew(T));
  144. ref(T::_new());
  145. }
  146. Ref() {
  147. reference = nullptr;
  148. }
  149. ~Ref() {
  150. unref();
  151. }
  152. // Used exclusively in the bindings to recreate the Ref Godot encapsulates in return values,
  153. // without adding to the refcount.
  154. inline static Ref<T> __internal_constructor(Object *obj) {
  155. Ref<T> r;
  156. r.reference = (T *)obj;
  157. return r;
  158. }
  159. };
  160. } // namespace godot
  161. #endif