From e6ee72828f1d0a0fe8248f0a4809860098c09872 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 | 286 +++++++++------------------------ scene/resources/curve.h | 52 ++++-- 4 files changed, 135 insertions(+), 222 deletions(-) diff --git a/scene/property_list_helper.cpp b/scene/property_list_helper.cpp index 315c602e61..3ba5b0ef0e 100644 --- a/scene/property_list_helper.cpp +++ b/scene/property_list_helper.cpp @@ -111,6 +111,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; } @@ -140,6 +141,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 (!(info.usage & PROPERTY_USAGE_STORE_IF_NULL) && _call_getter(&property, i) == property.default_value) { @@ -192,6 +203,9 @@ bool PropertyListHelper::property_get_revert(const String &p_property, Variant & void PropertyListHelper::clear() { if (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 1af04b9fa1..f169088482 100644 --- a/scene/property_list_helper.h +++ b/scene/property_list_helper.h @@ -45,6 +45,7 @@ class PropertyListHelper { String prefix; MethodBind *array_length_getter = nullptr; + MethodBind *property_filter = nullptr; HashMap property_list; Object *object = nullptr; @@ -64,6 +65,10 @@ public: 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 154859f63e..4b69bd9a52 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -36,6 +36,7 @@ const char *Curve::SIGNAL_RANGE_CHANGED = "range_changed"; const char *Curve::SIGNAL_DOMAIN_CHANGED = "domain_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, bool p_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(); @@ -432,6 +438,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(); @@ -577,88 +593,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 (uint32_t 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); @@ -712,6 +646,19 @@ 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); + PropertyListHelper::register_base_helper(&base_property_helper); } int Curve2D::get_point_count() const { @@ -1309,6 +1256,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; @@ -1341,64 +1298,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 (uint32_t 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); @@ -1432,6 +1331,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); + PropertyListHelper::register_base_helper(&base_property_helper); +} + +Curve2D::Curve2D() { + property_helper.setup_for_instance(base_property_helper, this); } /***********************************************************************************/ @@ -2366,6 +2279,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; @@ -2404,74 +2327,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 (uint32_t 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 (closed || i != 0) { - pi = PropertyInfo(Variant::VECTOR3, vformat("point_%d/in", i)); - pi.usage &= ~PROPERTY_USAGE_STORAGE; - p_list->push_back(pi); - } - - if (closed || 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), PROPERTY_HINT_RANGE, "-360,360,0.1,or_less,or_greater,radians_as_degrees"); - 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); @@ -2519,4 +2374,19 @@ 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); + PropertyListHelper::register_base_helper(&base_property_helper); +} + +Curve3D::Curve3D() { + property_helper.setup_for_instance(base_property_helper, this); } diff --git a/scene/resources/curve.h b/scene/resources/curve.h index 7782135402..3a62397284 100644 --- a/scene/resources/curve.h +++ b/scene/resources/curve.h @@ -32,6 +32,7 @@ #include "core/io/resource.h" #include "core/templates/rb_map.h" +#include "scene/property_list_helper.h" // y(x) curve class Curve : public Resource { @@ -54,8 +55,7 @@ public: TangentMode left_mode = TANGENT_FREE; TangentMode right_mode = TANGENT_FREE; - Point() { - } + Point() {} Point(const Vector2 &p_position, real_t p_left = 0.0, @@ -70,6 +70,9 @@ public: } }; + static inline PropertyListHelper base_property_helper; + PropertyListHelper property_helper; + Curve(); int get_point_count() const { return _points.size(); } @@ -140,14 +143,18 @@ public: 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 p_left_tangent = 0, @@ -156,6 +163,7 @@ private: TangentMode p_right_mode = TANGENT_FREE, bool p_mark_dirty = true); void _remove_point(int p_index, bool p_mark_dirty = true); + void _set_point_position(int p_index, const Vector2 &p_position); LocalVector _points; mutable bool _baked_cache_dirty = false; @@ -178,6 +186,9 @@ class Curve2D : public Resource { Vector2 position; }; + static inline PropertyListHelper base_property_helper; + PropertyListHelper property_helper; + LocalVector points; struct BakedPoint { @@ -211,16 +222,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: @@ -252,6 +266,8 @@ public: PackedVector2Array tessellate(int p_max_stages = 5, real_t p_tolerance = 4) const; //useful for display PackedVector2Array tessellate_even_length(int p_max_stages = 5, real_t p_length = 20.0) const; // Useful for baking. + + Curve2D(); }; class Curve3D : public Resource { @@ -264,6 +280,9 @@ class Curve3D : public Resource { real_t tilt = 0.0; }; + static inline PropertyListHelper base_property_helper; + PropertyListHelper property_helper; + LocalVector points; #ifdef TOOLS_ENABLED // For Path3DGizmo. @@ -303,16 +322,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: @@ -360,4 +382,6 @@ public: PackedVector3Array tessellate(int p_max_stages = 5, real_t p_tolerance = 4) const; // Useful for display. PackedVector3Array tessellate_even_length(int p_max_stages = 5, real_t p_length = 0.2) const; // Useful for baking. + + Curve3D(); };