2023-01-10 16:14:30 +01:00
|
|
|
/**************************************************************************/
|
|
|
|
|
/* ref.hpp */
|
|
|
|
|
/**************************************************************************/
|
|
|
|
|
/* This file is part of: */
|
|
|
|
|
/* GODOT ENGINE */
|
|
|
|
|
/* https://godotengine.org */
|
|
|
|
|
/**************************************************************************/
|
|
|
|
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
|
|
|
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
|
|
|
|
/* */
|
|
|
|
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
|
|
|
/* a copy of this software and associated documentation files (the */
|
|
|
|
|
/* "Software"), to deal in the Software without restriction, including */
|
|
|
|
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
|
|
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
|
|
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
|
|
|
/* the following conditions: */
|
|
|
|
|
/* */
|
|
|
|
|
/* The above copyright notice and this permission notice shall be */
|
|
|
|
|
/* included in all copies or substantial portions of the Software. */
|
|
|
|
|
/* */
|
|
|
|
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
|
|
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
|
|
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
|
|
|
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
|
|
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
|
|
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
|
|
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
|
|
|
/**************************************************************************/
|
2021-08-02 18:34:47 +02:00
|
|
|
|
2022-10-09 01:47:07 -05:00
|
|
|
#pragma once
|
2017-06-19 02:03:59 +02:00
|
|
|
|
2021-08-18 11:03:52 -03:00
|
|
|
#include <godot_cpp/core/defs.hpp>
|
|
|
|
|
|
|
|
|
|
#include <godot_cpp/classes/object.hpp>
|
|
|
|
|
#include <godot_cpp/classes/ref_counted.hpp>
|
2021-09-28 15:49:08 +02:00
|
|
|
#include <godot_cpp/core/binder_common.hpp>
|
2021-08-18 11:03:52 -03:00
|
|
|
#include <godot_cpp/core/memory.hpp>
|
|
|
|
|
#include <godot_cpp/variant/variant.hpp>
|
2017-06-19 02:03:59 +02:00
|
|
|
|
|
|
|
|
namespace godot {
|
|
|
|
|
|
2021-08-18 11:03:52 -03:00
|
|
|
// Helper class for RefCounted objects, same as Godot one.
|
|
|
|
|
|
2024-03-10 16:02:43 -05:00
|
|
|
template <typename T>
|
2017-06-19 02:03:59 +02:00
|
|
|
class Ref {
|
2018-02-23 16:08:36 +03:00
|
|
|
T *reference = nullptr;
|
2018-01-22 22:27:10 +01:00
|
|
|
|
2026-02-28 17:24:04 +01:00
|
|
|
_FORCE_INLINE_ void ref(const Ref &p_from) {
|
|
|
|
|
ref_pointer<false>(p_from.reference);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <bool Init>
|
|
|
|
|
_FORCE_INLINE_ void ref_pointer(T *p_refcounted) {
|
|
|
|
|
if (p_refcounted == reference) {
|
2018-01-22 22:27:10 +01:00
|
|
|
return;
|
2021-08-18 11:03:52 -03:00
|
|
|
}
|
2018-01-22 22:27:10 +01:00
|
|
|
|
2026-02-28 17:24:04 +01:00
|
|
|
// This will go out of scope and get unref'd.
|
|
|
|
|
Ref cleanup_ref;
|
|
|
|
|
cleanup_ref.reference = reference;
|
|
|
|
|
reference = p_refcounted;
|
2021-08-18 11:03:52 -03:00
|
|
|
if (reference) {
|
2026-02-28 17:24:04 +01:00
|
|
|
if constexpr (Init) {
|
|
|
|
|
if (!reference->init_ref()) {
|
|
|
|
|
reference = nullptr;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (!reference->reference()) {
|
|
|
|
|
reference = nullptr;
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-08-18 11:03:52 -03:00
|
|
|
}
|
2018-01-22 22:27:10 +01:00
|
|
|
}
|
2017-06-19 02:03:59 +02:00
|
|
|
|
|
|
|
|
public:
|
2025-03-24 19:42:04 +00:00
|
|
|
static _FORCE_INLINE_ String get_class_static() {
|
|
|
|
|
return T::get_class_static();
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-18 11:03:52 -03:00
|
|
|
_FORCE_INLINE_ bool operator==(const T *p_ptr) const {
|
|
|
|
|
return reference == p_ptr;
|
|
|
|
|
}
|
|
|
|
|
_FORCE_INLINE_ bool operator!=(const T *p_ptr) const {
|
|
|
|
|
return reference != p_ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_FORCE_INLINE_ bool operator<(const Ref<T> &p_r) const {
|
2018-01-22 22:27:10 +01:00
|
|
|
return reference < p_r.reference;
|
|
|
|
|
}
|
2021-08-18 11:03:52 -03:00
|
|
|
_FORCE_INLINE_ bool operator==(const Ref<T> &p_r) const {
|
2018-01-22 22:27:10 +01:00
|
|
|
return reference == p_r.reference;
|
|
|
|
|
}
|
2021-08-18 11:03:52 -03:00
|
|
|
_FORCE_INLINE_ bool operator!=(const Ref<T> &p_r) const {
|
2018-01-22 22:27:10 +01:00
|
|
|
return reference != p_r.reference;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-17 19:24:09 +09:00
|
|
|
_FORCE_INLINE_ T *operator*() const {
|
2017-06-19 02:03:59 +02:00
|
|
|
return reference;
|
|
|
|
|
}
|
2018-01-22 22:27:10 +01:00
|
|
|
|
2023-05-17 19:24:09 +09:00
|
|
|
_FORCE_INLINE_ T *operator->() const {
|
2017-06-19 02:03:59 +02:00
|
|
|
return reference;
|
|
|
|
|
}
|
2018-01-22 22:27:10 +01:00
|
|
|
|
2023-05-17 19:24:09 +09:00
|
|
|
_FORCE_INLINE_ T *ptr() const {
|
2017-06-19 02:03:59 +02:00
|
|
|
return reference;
|
|
|
|
|
}
|
2018-01-19 11:40:50 +01:00
|
|
|
|
2018-01-22 22:27:10 +01:00
|
|
|
operator Variant() const {
|
2021-08-18 11:03:52 -03:00
|
|
|
return Variant(reference);
|
2017-06-19 02:03:59 +02:00
|
|
|
}
|
2017-06-21 00:42:29 +02:00
|
|
|
|
2018-01-22 22:27:10 +01:00
|
|
|
void operator=(const Ref &p_from) {
|
|
|
|
|
ref(p_from);
|
2017-06-21 00:42:29 +02:00
|
|
|
}
|
2018-01-19 11:40:50 +01:00
|
|
|
|
2026-02-28 17:24:04 +01:00
|
|
|
void operator=(Ref &&p_from) {
|
|
|
|
|
if (reference == p_from.reference) {
|
2018-01-22 22:27:10 +01:00
|
|
|
return;
|
|
|
|
|
}
|
2026-02-28 17:24:04 +01:00
|
|
|
unref();
|
|
|
|
|
reference = p_from.reference;
|
|
|
|
|
p_from.reference = nullptr;
|
|
|
|
|
}
|
2021-09-14 14:43:08 +10:00
|
|
|
|
2026-02-28 17:24:04 +01:00
|
|
|
template <typename T_Other>
|
|
|
|
|
void operator=(const Ref<T_Other> &p_from) {
|
|
|
|
|
ref_pointer<false>(Object::cast_to<T>(p_from.ptr()));
|
2017-06-19 02:03:59 +02:00
|
|
|
}
|
2018-01-22 22:27:10 +01:00
|
|
|
|
2026-02-28 17:24:04 +01:00
|
|
|
void operator=(T *p_from) {
|
|
|
|
|
ref_pointer<true>(p_from);
|
|
|
|
|
}
|
2021-09-14 14:43:08 +10:00
|
|
|
|
2026-02-28 17:24:04 +01:00
|
|
|
void operator=(const Variant &p_variant) {
|
|
|
|
|
Object *object = p_variant.get_validated_object();
|
2018-01-22 22:27:10 +01:00
|
|
|
|
2021-09-14 14:43:08 +10:00
|
|
|
if (object == reference) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-08-18 11:03:52 -03:00
|
|
|
|
2026-02-28 17:24:04 +01:00
|
|
|
ref_pointer<false>(Object::cast_to<T>(object));
|
2018-01-22 22:27:10 +01:00
|
|
|
}
|
|
|
|
|
|
2024-03-10 16:02:43 -05:00
|
|
|
template <typename T_Other>
|
2021-08-18 11:03:52 -03:00
|
|
|
void reference_ptr(T_Other *p_ptr) {
|
|
|
|
|
if (reference == p_ptr) {
|
2018-01-22 22:27:10 +01:00
|
|
|
return;
|
2018-01-19 11:40:50 +01:00
|
|
|
}
|
2021-08-18 11:03:52 -03:00
|
|
|
|
2026-02-28 17:24:04 +01:00
|
|
|
ref_pointer<true>(Object::cast_to<T>(p_ptr));
|
2021-08-18 11:03:52 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ref(const Ref &p_from) {
|
2026-02-28 17:24:04 +01:00
|
|
|
this->operator=(p_from);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ref(Ref &&p_from) {
|
|
|
|
|
reference = p_from.reference;
|
|
|
|
|
p_from.reference = nullptr;
|
2017-06-19 02:03:59 +02:00
|
|
|
}
|
2017-06-21 00:42:29 +02:00
|
|
|
|
2024-03-10 16:02:43 -05:00
|
|
|
template <typename T_Other>
|
2021-09-14 14:43:08 +10:00
|
|
|
Ref(const Ref<T_Other> &p_from) {
|
2026-02-28 17:24:04 +01:00
|
|
|
this->operator=(p_from);
|
2021-09-14 14:43:08 +10:00
|
|
|
}
|
|
|
|
|
|
2026-02-28 17:24:04 +01:00
|
|
|
Ref(T *p_from) {
|
|
|
|
|
this->operator=(p_from);
|
2017-06-19 02:03:59 +02:00
|
|
|
}
|
2017-06-21 00:42:29 +02:00
|
|
|
|
2026-02-28 17:24:04 +01:00
|
|
|
Ref(const Variant &p_from) {
|
|
|
|
|
this->operator=(p_from);
|
2017-06-19 02:03:59 +02:00
|
|
|
}
|
2017-06-21 02:14:54 +02:00
|
|
|
|
2018-02-23 16:08:36 +03:00
|
|
|
inline bool is_valid() const { return reference != nullptr; }
|
|
|
|
|
inline bool is_null() const { return reference == nullptr; }
|
2018-01-22 22:27:10 +01:00
|
|
|
|
|
|
|
|
void unref() {
|
2026-02-28 17:24:04 +01:00
|
|
|
if (reference) {
|
|
|
|
|
// NOTE: `reinterpret_cast` is "safe" here because we know `T` has simple linear
|
|
|
|
|
// inheritance to `RefCounted`. This guarantees that `T * == `RefCounted *`, which
|
|
|
|
|
// allows us to declare `Ref<T>` with forward declared `T` types.
|
|
|
|
|
if (reinterpret_cast<RefCounted *>(reference)->unreference()) {
|
|
|
|
|
memdelete(reinterpret_cast<RefCounted *>(reference));
|
|
|
|
|
}
|
|
|
|
|
reference = nullptr;
|
2017-06-19 02:03:59 +02:00
|
|
|
}
|
|
|
|
|
}
|
2018-01-19 11:40:50 +01:00
|
|
|
|
2026-02-28 17:24:04 +01:00
|
|
|
template <typename... VarArgs>
|
|
|
|
|
void instantiate(VarArgs... p_params) {
|
|
|
|
|
ref(memnew(T(p_params...)));
|
2018-01-17 01:54:02 +01:00
|
|
|
}
|
|
|
|
|
|
2026-02-28 17:24:04 +01:00
|
|
|
uint32_t hash() const { return HashMapHasherDefault::hash(reference); }
|
|
|
|
|
|
|
|
|
|
Ref() = default;
|
2018-01-22 22:27:10 +01:00
|
|
|
|
|
|
|
|
~Ref() {
|
2017-06-19 02:03:59 +02:00
|
|
|
unref();
|
|
|
|
|
}
|
2018-01-24 23:16:00 +01:00
|
|
|
|
|
|
|
|
// Used exclusively in the bindings to recreate the Ref Godot encapsulates in return values,
|
|
|
|
|
// without adding to the refcount.
|
2023-02-16 10:38:38 -05:00
|
|
|
inline static Ref<T> _gde_internal_constructor(Object *obj) {
|
2018-01-24 23:16:00 +01:00
|
|
|
Ref<T> r;
|
2026-02-28 17:24:04 +01:00
|
|
|
r.reference = reinterpret_cast<T *>(obj);
|
2018-01-24 23:16:00 +01:00
|
|
|
return r;
|
|
|
|
|
}
|
2017-06-19 02:03:59 +02:00
|
|
|
};
|
|
|
|
|
|
2024-03-10 16:02:43 -05:00
|
|
|
template <typename T>
|
2021-09-28 15:49:08 +02:00
|
|
|
struct PtrToArg<Ref<T>> {
|
|
|
|
|
_FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) {
|
2023-05-23 15:17:06 -05:00
|
|
|
GDExtensionRefPtr ref = (GDExtensionRefPtr)p_ptr;
|
2024-10-07 11:22:52 -05:00
|
|
|
if (unlikely(!p_ptr)) {
|
|
|
|
|
return Ref<T>();
|
|
|
|
|
}
|
2025-12-06 09:44:43 -06:00
|
|
|
return Ref<T>(reinterpret_cast<T *>(::godot::internal::get_object_instance_binding(::godot::gdextension_interface::ref_get_object(ref))));
|
2021-09-28 15:49:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef Ref<T> EncodeT;
|
|
|
|
|
|
2022-11-13 00:37:55 +01:00
|
|
|
_FORCE_INLINE_ static void encode(Ref<T> p_val, void *p_ptr) {
|
2022-12-11 23:20:14 +11:00
|
|
|
GDExtensionRefPtr ref = (GDExtensionRefPtr)p_ptr;
|
|
|
|
|
ERR_FAIL_NULL(ref);
|
|
|
|
|
|
|
|
|
|
// This code assumes that p_ptr points to an unset Ref<T> variable on the Godot side
|
|
|
|
|
// so we only set it if we have an object to set.
|
|
|
|
|
if (p_val.is_valid()) {
|
2025-12-06 09:44:43 -06:00
|
|
|
::godot::gdextension_interface::ref_set_object(ref, p_val->_owner);
|
2022-12-11 23:20:14 +11:00
|
|
|
}
|
2021-09-28 15:49:08 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2024-03-10 16:02:43 -05:00
|
|
|
template <typename T>
|
2021-09-28 15:49:08 +02:00
|
|
|
struct PtrToArg<const Ref<T> &> {
|
|
|
|
|
typedef Ref<T> EncodeT;
|
|
|
|
|
|
|
|
|
|
_FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) {
|
2023-05-23 15:17:06 -05:00
|
|
|
GDExtensionRefPtr ref = const_cast<GDExtensionRefPtr>(p_ptr);
|
2024-10-07 11:22:52 -05:00
|
|
|
if (unlikely(!p_ptr)) {
|
|
|
|
|
return Ref<T>();
|
|
|
|
|
}
|
2025-12-06 09:44:43 -06:00
|
|
|
return Ref<T>(reinterpret_cast<T *>(::godot::internal::get_object_instance_binding(::godot::gdextension_interface::ref_get_object(ref))));
|
2021-09-28 15:49:08 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2024-03-10 16:02:43 -05:00
|
|
|
template <typename T>
|
2021-09-28 15:49:08 +02:00
|
|
|
struct GetTypeInfo<Ref<T>, typename EnableIf<TypeInherits<RefCounted, T>::value>::type> {
|
2024-06-10 10:51:52 -05:00
|
|
|
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
|
|
|
|
|
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
|
2021-09-28 15:49:08 +02:00
|
|
|
|
2022-10-22 19:42:48 +02:00
|
|
|
static inline PropertyInfo get_class_info() {
|
2022-12-06 08:33:13 +03:00
|
|
|
return make_property_info(Variant::Type::OBJECT, "", PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static());
|
2021-09-28 15:49:08 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2024-03-10 16:02:43 -05:00
|
|
|
template <typename T>
|
2021-09-28 15:49:08 +02:00
|
|
|
struct GetTypeInfo<const Ref<T> &, typename EnableIf<TypeInherits<RefCounted, T>::value>::type> {
|
2024-06-10 10:51:52 -05:00
|
|
|
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_OBJECT;
|
|
|
|
|
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
|
2021-09-28 15:49:08 +02:00
|
|
|
|
2022-10-22 19:42:48 +02:00
|
|
|
static inline PropertyInfo get_class_info() {
|
2022-12-06 08:33:13 +03:00
|
|
|
return make_property_info(Variant::Type::OBJECT, "", PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static());
|
2021-09-28 15:49:08 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2018-11-24 09:09:41 +11:00
|
|
|
} // namespace godot
|