From 703a91eb2246a5616a2f4c946970f8f81b158707 Mon Sep 17 00:00:00 2001 From: kobewi Date: Thu, 23 May 2024 16:48:48 +0200 Subject: [PATCH] Add PropertyListHelper to Curves --- scene/property_list_helper.cpp | 14 ++ scene/property_list_helper.h | 5 + scene/resources/curve.cpp | 283 +++++++++------------------------ scene/resources/curve.h | 48 ++++-- 4 files changed, 126 insertions(+), 224 deletions(-) diff --git a/scene/property_list_helper.cpp b/scene/property_list_helper.cpp index ce258ee8c3e6..71dfbd341077 100644 --- a/scene/property_list_helper.cpp +++ b/scene/property_list_helper.cpp @@ -98,6 +98,7 @@ void PropertyListHelper::setup_for_instance(const PropertyListHelper &p_base, Ob prefix = p_base.prefix; array_length_getter = p_base.array_length_getter; + property_filter = p_base.property_filter; property_list = p_base.property_list; object = p_object; } @@ -127,6 +128,16 @@ void PropertyListHelper::get_property_list(List *p_list) const { for (int i = 0; i < property_count; i++) { for (const KeyValue &E : property_list) { const Property &property = E.value; + if (property_filter) { + Callable::CallError ce; + Variant args[] = { property.info.name, i }; + const Variant *argptrs[] = { &args[0], &args[1] }; + + bool property_valid = property_filter->call(object, argptrs, 2, ce); + if (!property_valid) { + continue; + } + } PropertyInfo info = property.info; if (_call_getter(&property, i) == property.default_value) { @@ -180,6 +191,9 @@ PropertyListHelper::~PropertyListHelper() { // No object = it's the main helper. Do a cleanup. if (!object && is_initialized()) { memdelete(array_length_getter); + if (property_filter) { + memdelete(property_filter); + } for (const KeyValue &E : property_list) { if (E.value.setter) { diff --git a/scene/property_list_helper.h b/scene/property_list_helper.h index 6bc65f6e3eee..304be9352a06 100644 --- a/scene/property_list_helper.h +++ b/scene/property_list_helper.h @@ -44,6 +44,7 @@ class PropertyListHelper { String prefix; MethodBind *array_length_getter = nullptr; + MethodBind *property_filter = nullptr; HashMap property_list; Object *object = nullptr; @@ -58,6 +59,10 @@ class PropertyListHelper { void set_array_length_getter(G p_array_length_getter) { array_length_getter = create_method_bind(p_array_length_getter); } + template + void set_property_filter(F p_property_filter) { + property_filter = create_method_bind(p_property_filter); + } // Register property without setter/getter. Only use when you don't need PropertyListHelper for _set/_get logic. void register_property(const PropertyInfo &p_info, const Variant &p_default); diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp index 8926eb1d511a..157263f6d927 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -35,6 +35,7 @@ const char *Curve::SIGNAL_RANGE_CHANGED = "range_changed"; Curve::Curve() { + property_helper.setup_for_instance(base_property_helper, this); } void Curve::set_point_count(int p_count) { @@ -231,6 +232,11 @@ void Curve::_remove_point(int p_index) { mark_dirty(); } +void Curve::_set_point_position(int p_index, const Vector2 &p_position) { + set_point_value(p_index, p_position.x); + set_point_offset(p_index, p_position.y); +} + void Curve::remove_point(int p_index) { _remove_point(p_index); notify_property_list_changed(); @@ -385,6 +391,16 @@ real_t Curve::sample_local_nocheck(int p_index, real_t p_local_offset) const { return y; } +bool Curve::_filter_property(const String &p_name, int p_index) const { + if (p_index == 0) { + return p_name != "left_tangent" && p_name != "left_mode"; + } + if (p_index == get_point_count() - 1) { + return p_name != "right_tangent" && p_name != "right_mode"; + } + return true; +} + void Curve::mark_dirty() { _baked_cache_dirty = true; emit_changed(); @@ -523,88 +539,6 @@ void Curve::ensure_default_setup(real_t p_min, real_t p_max) { } } -bool Curve::_set(const StringName &p_name, const Variant &p_value) { - Vector components = String(p_name).split("/", true, 2); - if (components.size() >= 2 && components[0].begins_with("point_") && components[0].trim_prefix("point_").is_valid_int()) { - int point_index = components[0].trim_prefix("point_").to_int(); - const String &property = components[1]; - if (property == "position") { - Vector2 position = p_value.operator Vector2(); - set_point_offset(point_index, position.x); - set_point_value(point_index, position.y); - return true; - } else if (property == "left_tangent") { - set_point_left_tangent(point_index, p_value); - return true; - } else if (property == "left_mode") { - int mode = p_value; - set_point_left_mode(point_index, (TangentMode)mode); - return true; - } else if (property == "right_tangent") { - set_point_right_tangent(point_index, p_value); - return true; - } else if (property == "right_mode") { - int mode = p_value; - set_point_right_mode(point_index, (TangentMode)mode); - return true; - } - } - return false; -} - -bool Curve::_get(const StringName &p_name, Variant &r_ret) const { - Vector components = String(p_name).split("/", true, 2); - if (components.size() >= 2 && components[0].begins_with("point_") && components[0].trim_prefix("point_").is_valid_int()) { - int point_index = components[0].trim_prefix("point_").to_int(); - const String &property = components[1]; - if (property == "position") { - r_ret = get_point_position(point_index); - return true; - } else if (property == "left_tangent") { - r_ret = get_point_left_tangent(point_index); - return true; - } else if (property == "left_mode") { - r_ret = get_point_left_mode(point_index); - return true; - } else if (property == "right_tangent") { - r_ret = get_point_right_tangent(point_index); - return true; - } else if (property == "right_mode") { - r_ret = get_point_right_mode(point_index); - return true; - } - } - return false; -} - -void Curve::_get_property_list(List *p_list) const { - for (int i = 0; i < _points.size(); i++) { - PropertyInfo pi = PropertyInfo(Variant::VECTOR2, vformat("point_%d/position", i)); - pi.usage &= ~PROPERTY_USAGE_STORAGE; - p_list->push_back(pi); - - if (i != 0) { - pi = PropertyInfo(Variant::FLOAT, vformat("point_%d/left_tangent", i)); - pi.usage &= ~PROPERTY_USAGE_STORAGE; - p_list->push_back(pi); - - pi = PropertyInfo(Variant::INT, vformat("point_%d/left_mode", i), PROPERTY_HINT_ENUM, "Free,Linear"); - pi.usage &= ~PROPERTY_USAGE_STORAGE; - p_list->push_back(pi); - } - - if (i != _points.size() - 1) { - pi = PropertyInfo(Variant::FLOAT, vformat("point_%d/right_tangent", i)); - pi.usage &= ~PROPERTY_USAGE_STORAGE; - p_list->push_back(pi); - - pi = PropertyInfo(Variant::INT, vformat("point_%d/right_mode", i), PROPERTY_HINT_ENUM, "Free,Linear"); - pi.usage &= ~PROPERTY_USAGE_STORAGE; - p_list->push_back(pi); - } - } -} - void Curve::_bind_methods() { ClassDB::bind_method(D_METHOD("get_point_count"), &Curve::get_point_count); ClassDB::bind_method(D_METHOD("set_point_count", "count"), &Curve::set_point_count); @@ -646,6 +580,18 @@ void Curve::_bind_methods() { BIND_ENUM_CONSTANT(TANGENT_FREE); BIND_ENUM_CONSTANT(TANGENT_LINEAR); BIND_ENUM_CONSTANT(TANGENT_MODE_COUNT); + + Point defaults; + const String mode_hint = "Free,Linear"; + + base_property_helper.set_prefix("point_"); + base_property_helper.set_array_length_getter(&Curve::get_point_count); + base_property_helper.set_property_filter(&Curve::_filter_property); + base_property_helper.register_property(PropertyInfo(Variant::VECTOR2, "position"), defaults.position, &Curve::_set_point_position, &Curve::get_point_position); + base_property_helper.register_property(PropertyInfo(Variant::FLOAT, "left_tangent"), defaults.left_tangent, &Curve::set_point_left_tangent, &Curve::get_point_left_tangent); + base_property_helper.register_property(PropertyInfo(Variant::INT, "left_mode", PROPERTY_HINT_ENUM, mode_hint), defaults.left_mode, &Curve::set_point_left_mode, &Curve::get_point_left_mode); + base_property_helper.register_property(PropertyInfo(Variant::FLOAT, "right_tangent"), defaults.right_tangent, &Curve::set_point_right_tangent, &Curve::get_point_right_tangent); + base_property_helper.register_property(PropertyInfo(Variant::INT, "right_mode", PROPERTY_HINT_ENUM, mode_hint), defaults.right_mode, &Curve::set_point_right_mode, &Curve::get_point_right_mode); } int Curve2D::get_point_count() const { @@ -1223,6 +1169,16 @@ Vector> Curve2D::_tessellate_even_length(int p_max_stages return midpoints; } +bool Curve2D::_filter_property(const String &p_name, int p_index) const { + if (p_index == 0) { + return p_name != "in"; + } + if (p_index == get_point_count() - 1) { + return p_name != "out"; + } + return true; +} + PackedVector2Array Curve2D::tessellate_even_length(int p_max_stages, real_t p_length) const { PackedVector2Array tess; @@ -1255,64 +1211,6 @@ PackedVector2Array Curve2D::tessellate_even_length(int p_max_stages, real_t p_le return tess; } -bool Curve2D::_set(const StringName &p_name, const Variant &p_value) { - Vector components = String(p_name).split("/", true, 2); - if (components.size() >= 2 && components[0].begins_with("point_") && components[0].trim_prefix("point_").is_valid_int()) { - int point_index = components[0].trim_prefix("point_").to_int(); - const String &property = components[1]; - if (property == "position") { - set_point_position(point_index, p_value); - return true; - } else if (property == "in") { - set_point_in(point_index, p_value); - return true; - } else if (property == "out") { - set_point_out(point_index, p_value); - return true; - } - } - return false; -} - -bool Curve2D::_get(const StringName &p_name, Variant &r_ret) const { - Vector components = String(p_name).split("/", true, 2); - if (components.size() >= 2 && components[0].begins_with("point_") && components[0].trim_prefix("point_").is_valid_int()) { - int point_index = components[0].trim_prefix("point_").to_int(); - const String &property = components[1]; - if (property == "position") { - r_ret = get_point_position(point_index); - return true; - } else if (property == "in") { - r_ret = get_point_in(point_index); - return true; - } else if (property == "out") { - r_ret = get_point_out(point_index); - return true; - } - } - return false; -} - -void Curve2D::_get_property_list(List *p_list) const { - for (int i = 0; i < points.size(); i++) { - PropertyInfo pi = PropertyInfo(Variant::VECTOR2, vformat("point_%d/position", i)); - pi.usage &= ~PROPERTY_USAGE_STORAGE; - p_list->push_back(pi); - - if (i != 0) { - pi = PropertyInfo(Variant::VECTOR2, vformat("point_%d/in", i)); - pi.usage &= ~PROPERTY_USAGE_STORAGE; - p_list->push_back(pi); - } - - if (i != points.size() - 1) { - pi = PropertyInfo(Variant::VECTOR2, vformat("point_%d/out", i)); - pi.usage &= ~PROPERTY_USAGE_STORAGE; - p_list->push_back(pi); - } - } -} - void Curve2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_point_count"), &Curve2D::get_point_count); ClassDB::bind_method(D_METHOD("set_point_count", "count"), &Curve2D::set_point_count); @@ -1346,9 +1244,20 @@ void Curve2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bake_interval", PROPERTY_HINT_RANGE, "0.01,512,0.01"), "set_bake_interval", "get_bake_interval"); ADD_PROPERTY(PropertyInfo(Variant::INT, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); ADD_ARRAY_COUNT("Points", "point_count", "set_point_count", "get_point_count", "point_"); + + Point defaults; + + base_property_helper.set_prefix("point_"); + base_property_helper.set_array_length_getter(&Curve2D::get_point_count); + base_property_helper.set_property_filter(&Curve2D::_filter_property); + base_property_helper.register_property(PropertyInfo(Variant::VECTOR2, "position"), defaults.position, &Curve2D::set_point_position, &Curve2D::get_point_position); + base_property_helper.register_property(PropertyInfo(Variant::VECTOR2, "in"), defaults.in, &Curve2D::set_point_in, &Curve2D::get_point_in); + base_property_helper.register_property(PropertyInfo(Variant::VECTOR2, "out"), defaults.out, &Curve2D::set_point_out, &Curve2D::get_point_out); } -Curve2D::Curve2D() {} +Curve2D::Curve2D() { + property_helper.setup_for_instance(base_property_helper, this); +} /***********************************************************************************/ /***********************************************************************************/ @@ -2192,6 +2101,16 @@ Vector> Curve3D::_tessellate_even_length(int p_max_stages return midpoints; } +bool Curve3D::_filter_property(const String &p_name, int p_index) const { + if (p_index == 0) { + return p_name != "in"; + } + if (p_index == get_point_count() - 1) { + return p_name != "out"; + } + return true; +} + PackedVector3Array Curve3D::tessellate_even_length(int p_max_stages, real_t p_length) const { PackedVector3Array tess; @@ -2224,74 +2143,6 @@ PackedVector3Array Curve3D::tessellate_even_length(int p_max_stages, real_t p_le return tess; } -bool Curve3D::_set(const StringName &p_name, const Variant &p_value) { - Vector components = String(p_name).split("/", true, 2); - if (components.size() >= 2 && components[0].begins_with("point_") && components[0].trim_prefix("point_").is_valid_int()) { - int point_index = components[0].trim_prefix("point_").to_int(); - const String &property = components[1]; - if (property == "position") { - set_point_position(point_index, p_value); - return true; - } else if (property == "in") { - set_point_in(point_index, p_value); - return true; - } else if (property == "out") { - set_point_out(point_index, p_value); - return true; - } else if (property == "tilt") { - set_point_tilt(point_index, p_value); - return true; - } - } - return false; -} - -bool Curve3D::_get(const StringName &p_name, Variant &r_ret) const { - Vector components = String(p_name).split("/", true, 2); - if (components.size() >= 2 && components[0].begins_with("point_") && components[0].trim_prefix("point_").is_valid_int()) { - int point_index = components[0].trim_prefix("point_").to_int(); - const String &property = components[1]; - if (property == "position") { - r_ret = get_point_position(point_index); - return true; - } else if (property == "in") { - r_ret = get_point_in(point_index); - return true; - } else if (property == "out") { - r_ret = get_point_out(point_index); - return true; - } else if (property == "tilt") { - r_ret = get_point_tilt(point_index); - return true; - } - } - return false; -} - -void Curve3D::_get_property_list(List *p_list) const { - for (int i = 0; i < points.size(); i++) { - PropertyInfo pi = PropertyInfo(Variant::VECTOR3, vformat("point_%d/position", i)); - pi.usage &= ~PROPERTY_USAGE_STORAGE; - p_list->push_back(pi); - - if (i != 0) { - pi = PropertyInfo(Variant::VECTOR3, vformat("point_%d/in", i)); - pi.usage &= ~PROPERTY_USAGE_STORAGE; - p_list->push_back(pi); - } - - if (i != points.size() - 1) { - pi = PropertyInfo(Variant::VECTOR3, vformat("point_%d/out", i)); - pi.usage &= ~PROPERTY_USAGE_STORAGE; - p_list->push_back(pi); - } - - pi = PropertyInfo(Variant::FLOAT, vformat("point_%d/tilt", i)); - pi.usage &= ~PROPERTY_USAGE_STORAGE; - p_list->push_back(pi); - } -} - void Curve3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_point_count"), &Curve3D::get_point_count); ClassDB::bind_method(D_METHOD("set_point_count", "count"), &Curve3D::set_point_count); @@ -2335,6 +2186,18 @@ void Curve3D::_bind_methods() { ADD_GROUP("Up Vector", "up_vector_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "up_vector_enabled"), "set_up_vector_enabled", "is_up_vector_enabled"); + + Point defaults; + + base_property_helper.set_prefix("point_"); + base_property_helper.set_array_length_getter(&Curve3D::get_point_count); + base_property_helper.set_property_filter(&Curve3D::_filter_property); + base_property_helper.register_property(PropertyInfo(Variant::VECTOR3, "position"), defaults.position, &Curve3D::set_point_position, &Curve3D::get_point_position); + base_property_helper.register_property(PropertyInfo(Variant::VECTOR3, "in"), defaults.in, &Curve3D::set_point_in, &Curve3D::get_point_in); + base_property_helper.register_property(PropertyInfo(Variant::VECTOR3, "out"), defaults.out, &Curve3D::set_point_out, &Curve3D::get_point_out); + base_property_helper.register_property(PropertyInfo(Variant::FLOAT, "tilt"), defaults.tilt, &Curve3D::set_point_tilt, &Curve3D::get_point_tilt); } -Curve3D::Curve3D() {} +Curve3D::Curve3D() { + property_helper.setup_for_instance(base_property_helper, this); +} diff --git a/scene/resources/curve.h b/scene/resources/curve.h index 6da337a93f8c..5ca91eeff308 100644 --- a/scene/resources/curve.h +++ b/scene/resources/curve.h @@ -32,6 +32,7 @@ #define CURVE_H #include "core/io/resource.h" +#include "scene/property_list_helper.h" // y(x) curve class Curve : public Resource { @@ -56,8 +57,7 @@ class Curve : public Resource { TangentMode left_mode = TANGENT_FREE; TangentMode right_mode = TANGENT_FREE; - Point() { - } + Point() {} Point(const Vector2 &p_position, real_t p_left = 0.0, @@ -72,6 +72,9 @@ class Curve : public Resource { } }; + static inline PropertyListHelper base_property_helper; + PropertyListHelper property_helper; + Curve(); int get_point_count() const { return _points.size(); } @@ -134,14 +137,18 @@ class Curve : public Resource { void ensure_default_setup(real_t p_min, real_t p_max); - bool _set(const StringName &p_name, const Variant &p_value); - bool _get(const StringName &p_name, Variant &r_ret) const; - void _get_property_list(List *p_list) const; - protected: + bool _set(const StringName &p_name, const Variant &p_value) { return property_helper.property_set_value(p_name, p_value); } + bool _get(const StringName &p_name, Variant &r_ret) const { return property_helper.property_get_value(p_name, r_ret); } + void _get_property_list(List *p_list) const { property_helper.get_property_list(p_list); } + bool _property_can_revert(const StringName &p_name) const { return property_helper.property_can_revert(p_name); } + bool _property_get_revert(const StringName &p_name, Variant &r_property) const { return property_helper.property_get_revert(p_name, r_property); } + static void _bind_methods(); private: + bool _filter_property(const String &p_name, int p_index) const; + void mark_dirty(); int _add_point(Vector2 p_position, real_t left_tangent = 0, @@ -149,6 +156,7 @@ class Curve : public Resource { TangentMode left_mode = TANGENT_FREE, TangentMode right_mode = TANGENT_FREE); void _remove_point(int p_index); + void _set_point_position(int p_index, const Vector2 &p_position); Vector _points; bool _baked_cache_dirty = false; @@ -170,6 +178,9 @@ class Curve2D : public Resource { Vector2 position; }; + static inline PropertyListHelper base_property_helper; + PropertyListHelper property_helper; + Vector points; struct BakedPoint { @@ -203,16 +214,19 @@ class Curve2D : public Resource { Dictionary _get_data() const; void _set_data(const Dictionary &p_data); - bool _set(const StringName &p_name, const Variant &p_value); - bool _get(const StringName &p_name, Variant &r_ret) const; - void _get_property_list(List *p_list) const; - void _add_point(const Vector2 &p_position, const Vector2 &p_in = Vector2(), const Vector2 &p_out = Vector2(), int p_atpos = -1); void _remove_point(int p_index); Vector> _tessellate_even_length(int p_max_stages = 5, real_t p_length = 0.2) const; + bool _filter_property(const String &p_name, int p_index) const; protected: + bool _set(const StringName &p_name, const Variant &p_value) { return property_helper.property_set_value(p_name, p_value); } + bool _get(const StringName &p_name, Variant &r_ret) const { return property_helper.property_get_value(p_name, r_ret); } + void _get_property_list(List *p_list) const { property_helper.get_property_list(p_list); } + bool _property_can_revert(const StringName &p_name) const { return property_helper.property_can_revert(p_name); } + bool _property_get_revert(const StringName &p_name, Variant &r_property) const { return property_helper.property_get_revert(p_name, r_property); } + static void _bind_methods(); public: @@ -258,6 +272,9 @@ class Curve3D : public Resource { real_t tilt = 0.0; }; + static inline PropertyListHelper base_property_helper; + PropertyListHelper property_helper; + Vector points; #ifdef TOOLS_ENABLED // For Path3DGizmo. @@ -295,16 +312,19 @@ class Curve3D : public Resource { Dictionary _get_data() const; void _set_data(const Dictionary &p_data); - bool _set(const StringName &p_name, const Variant &p_value); - bool _get(const StringName &p_name, Variant &r_ret) const; - void _get_property_list(List *p_list) const; - void _add_point(const Vector3 &p_position, const Vector3 &p_in = Vector3(), const Vector3 &p_out = Vector3(), int p_atpos = -1); void _remove_point(int p_index); Vector> _tessellate_even_length(int p_max_stages = 5, real_t p_length = 0.2) const; + bool _filter_property(const String &p_name, int p_index) const; protected: + bool _set(const StringName &p_name, const Variant &p_value) { return property_helper.property_set_value(p_name, p_value); } + bool _get(const StringName &p_name, Variant &r_ret) const { return property_helper.property_get_value(p_name, r_ret); } + void _get_property_list(List *p_list) const { property_helper.get_property_list(p_list); } + bool _property_can_revert(const StringName &p_name) const { return property_helper.property_can_revert(p_name); } + bool _property_get_revert(const StringName &p_name, Variant &r_property) const { return property_helper.property_get_revert(p_name, r_property); } + static void _bind_methods(); public: