diff --git a/include/godot_cpp/classes/ref.hpp b/include/godot_cpp/classes/ref.hpp index 7027e7eff..a721e0bb0 100644 --- a/include/godot_cpp/classes/ref.hpp +++ b/include/godot_cpp/classes/ref.hpp @@ -186,6 +186,14 @@ class Ref { r.reference = nullptr; } + template + Ref(Ref &&p_other) { + // Should just be able to swap these... + T *swap = (T *)p_other.reference; + p_other.reference = (T_Other *)reference; + reference = swap; + } + Ref(T *p_reference) { if (p_reference) { ref_pointer(p_reference); diff --git a/test/demo/main.gd b/test/demo/main.gd index 16be87cb3..d0de0b89c 100644 --- a/test/demo/main.gd +++ b/test/demo/main.gd @@ -9,9 +9,12 @@ func _ready(): ($Example as Example).simple_const_func() # Force use of ptrcall prints("returned", $Example.return_something("some string")) prints("returned const", $Example.return_something_const()) - prints("returned ref", $Example.return_extended_ref()) + + prints("returned example ref object: ", $Example.return_extended_ref()) + var ref = ExampleRef.new() prints("sending ref: ", ref.get_instance_id(), "returned ref: ", $Example.extended_ref_checks(ref).get_instance_id()) + prints("vararg args", $Example.varargs_func("some", "arguments", "to", "test")) prints("test array", $Example.test_array()) diff --git a/test/demo/main.tscn b/test/demo/main.tscn index 4b6a1a4cb..93b8535ce 100644 --- a/test/demo/main.tscn +++ b/test/demo/main.tscn @@ -1,17 +1,25 @@ -[gd_scene load_steps=2 format=3 uid="uid://dmx2xuigcpvt4"] +[gd_scene load_steps=3 format=3 uid="uid://dmx2xuigcpvt4"] [ext_resource type="Script" path="res://main.gd" id="1_c326s"] +[sub_resource type="ExampleRef" id="ExampleRef_gveeo"] +value = 5 + [node name="Node" type="Node"] script = ExtResource( "1_c326s" ) [node name="Example" type="Example" parent="."] +ref_obj = SubResource( "ExampleRef_gveeo" ) +__meta__ = { +"_edit_use_anchors_": false +} [node name="Label" type="Label" parent="Example"] offset_left = 194.0 offset_top = -2.0 offset_right = 234.0 offset_bottom = 21.0 +theme_override_font_sizes/font_size = 16 __meta__ = { "_edit_use_anchors_": false } diff --git a/test/src/example.cpp b/test/src/example.cpp index ad82103a4..57334b592 100644 --- a/test/src/example.cpp +++ b/test/src/example.cpp @@ -38,22 +38,43 @@ using namespace godot; +uint64_t ExampleRef::instance_count = 0; + +void ExampleRef::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_value"), &ExampleRef::get_value); + ClassDB::bind_method(D_METHOD("set_value", "value"), &ExampleRef::set_value); + ADD_PROPERTY(PropertyInfo(Variant::INT, "value"), "set_value", "get_value"); +} + ExampleRef::ExampleRef() { - UtilityFunctions::print("ExampleRef created."); + instance_count++; + UtilityFunctions::print("ExampleRef created. Our total instance count is now: ", instance_count); + + // default this + value = 1; } ExampleRef::~ExampleRef() { - UtilityFunctions::print("ExampleRef destroyed."); + instance_count--; + UtilityFunctions::print("ExampleRef destroyed. Our total instance count is now: ", instance_count); +} + +void ExampleRef::set_value(int64_t p_value) { + value = p_value; +} + +int64_t ExampleRef::get_value() const { + return value; } void Example::_bind_methods() { // Methods. ClassDB::bind_method(D_METHOD("simple_func"), &Example::simple_func); ClassDB::bind_method(D_METHOD("simple_const_func"), &Example::simple_const_func); - ClassDB::bind_method(D_METHOD("return_something"), &Example::return_something); + ClassDB::bind_method(D_METHOD("return_something", "base"), &Example::return_something); ClassDB::bind_method(D_METHOD("return_something_const"), &Example::return_something_const); ClassDB::bind_method(D_METHOD("return_extended_ref"), &Example::return_extended_ref); - ClassDB::bind_method(D_METHOD("extended_ref_checks"), &Example::extended_ref_checks); + ClassDB::bind_method(D_METHOD("extended_ref_checks", "ref"), &Example::extended_ref_checks); ClassDB::bind_method(D_METHOD("test_array"), &Example::test_array); ClassDB::bind_method(D_METHOD("test_dictionary"), &Example::test_dictionary); @@ -73,6 +94,10 @@ void Example::_bind_methods() { ClassDB::bind_method(D_METHOD("set_custom_position", "position"), &Example::set_custom_position); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "group_subgroup_custom_position"), "set_custom_position", "get_custom_position"); + ClassDB::bind_method(D_METHOD("get_ref_obj"), &Example::get_ref_obj); + ClassDB::bind_method(D_METHOD("set_ref_obj", "ref_obj"), &Example::set_ref_obj); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "ref_obj", PROPERTY_HINT_RESOURCE_TYPE, "ExampleRef"), "set_ref_obj", "get_ref_obj"); + // Signals. ADD_SIGNAL(MethodInfo("custom_signal", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::INT, "value"))); ClassDB::bind_method(D_METHOD("emit_custom_signal", "name", "value"), &Example::emit_custom_signal); @@ -85,11 +110,11 @@ void Example::_bind_methods() { } Example::Example() { - UtilityFunctions::print("Constructor."); + UtilityFunctions::print("Example Constructor."); } Example::~Example() { - UtilityFunctions::print("Destructor."); + UtilityFunctions::print("Example Destructor."); } // Methods. @@ -115,15 +140,19 @@ Viewport *Example::return_something_const() const { return nullptr; } -ExampleRef *Example::return_extended_ref() const { - return memnew(ExampleRef()); +Ref Example::return_extended_ref() const { + // When subclassing RefCounted we should ALWAYS use Ref<..> or Godot will start doing confusing things as it will start using reference counting to manage the object. + // We should never instantiate the object directly such as this: + // return memnew(ExampleRef()); + + Ref ref; + ref.instantiate(); + return ref; } Ref Example::extended_ref_checks(Ref p_ref) const { Ref ref; ref.instantiate(); - // TODO the returned value gets dereferenced too early and return a null object otherwise. - ref->reference(); UtilityFunctions::print("Example ref checks called with value: ", p_ref->get_instance_id(), ", returning value: ", ref->get_instance_id()); return ref; } @@ -165,6 +194,14 @@ Vector2 Example::get_custom_position() const { return custom_position; } +void Example::set_ref_obj(const Ref p_ref) { + ref_obj = p_ref; +} + +Ref Example::get_ref_obj() const { + return ref_obj; +} + // Virtual function override. bool Example::_has_point(const Vector2 &point) const { Label *label = get_node