diff options
-rw-r--r-- | core/object/object.cpp | 6 | ||||
-rw-r--r-- | core/object/script_language.h | 2 | ||||
-rw-r--r-- | core/object/script_language_extension.h | 3 | ||||
-rw-r--r-- | doc/classes/Object.xml | 53 | ||||
-rw-r--r-- | modules/gdscript/gdscript.cpp | 23 | ||||
-rw-r--r-- | modules/gdscript/gdscript.h | 2 | ||||
-rw-r--r-- | modules/mono/csharp_script.cpp | 21 | ||||
-rw-r--r-- | modules/mono/csharp_script.h | 1 | ||||
-rw-r--r-- | tests/core/object/test_object.h | 2 |
9 files changed, 111 insertions, 2 deletions
diff --git a/core/object/object.cpp b/core/object/object.cpp index 4ae0ecdefd..b803d57cd9 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -526,6 +526,10 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons void Object::validate_property(PropertyInfo &p_property) const { _validate_propertyv(p_property); + + if (script_instance) { // Call it last to allow user altering already validated properties. + script_instance->validate_property(p_property); + } } bool Object::property_can_revert(const StringName &p_name) const { @@ -1604,6 +1608,8 @@ void Object::_bind_methods() { plget.return_val.hint_string = "Dictionary"; BIND_OBJ_CORE_METHOD(plget); + BIND_OBJ_CORE_METHOD(MethodInfo(Variant::NIL, "_validate_property", PropertyInfo(Variant::DICTIONARY, "property"))); + BIND_OBJ_CORE_METHOD(MethodInfo(Variant::BOOL, "_property_can_revert", PropertyInfo(Variant::STRING_NAME, "property"))); MethodInfo mipgr("_property_get_revert", PropertyInfo(Variant::STRING_NAME, "property")); mipgr.return_val.name = "Variant"; diff --git a/core/object/script_language.h b/core/object/script_language.h index 215e5880fa..9d83a12bbd 100644 --- a/core/object/script_language.h +++ b/core/object/script_language.h @@ -180,6 +180,7 @@ public: virtual bool get(const StringName &p_name, Variant &r_ret) const = 0; virtual void get_property_list(List<PropertyInfo> *p_properties) const = 0; virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = nullptr) const = 0; + virtual void validate_property(PropertyInfo &p_property) const = 0; virtual bool property_can_revert(const StringName &p_name) const = 0; virtual bool property_get_revert(const StringName &p_name, Variant &r_ret) const = 0; @@ -463,6 +464,7 @@ public: virtual bool get(const StringName &p_name, Variant &r_ret) const override; virtual void get_property_list(List<PropertyInfo> *p_properties) const override; virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = nullptr) const override; + virtual void validate_property(PropertyInfo &p_property) const override {} virtual bool property_can_revert(const StringName &p_name) const override { return false; }; virtual bool property_get_revert(const StringName &p_name, Variant &r_ret) const override { return false; }; diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h index 7fa1fe6810..6edbcdaeee 100644 --- a/core/object/script_language_extension.h +++ b/core/object/script_language_extension.h @@ -682,6 +682,9 @@ public: } return Variant::NIL; } + virtual void validate_property(PropertyInfo &p_property) const override { + // TODO + } virtual bool property_can_revert(const StringName &p_name) const override { if (native_info->property_can_revert_func) { diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml index 5fb1d7ab8f..bb958a8189 100644 --- a/doc/classes/Object.xml +++ b/doc/classes/Object.xml @@ -269,6 +269,59 @@ [/codeblock] </description> </method> + <method name="_validate_property" qualifiers="virtual"> + <return type="void" /> + <param index="0" name="property" type="Dictionary" /> + <description> + Override this method to customize existing properties. Every property info goes through this method. The dictionary contents is the same as in [method _get_property_list]. + [codeblocks] + [gdscript] + @tool + extends Node + + @export var is_number_editable: bool: + set(value): + is_number_editable = value + notify_property_list_changed() + @export var number: int + + func _validate_property(property: Dictionary): + if property.name == "number" and not is_number_editable: + property.usage |= PROPERTY_USAGE_READ_ONLY + [/gdscript] + [csharp] + [Tool] + public partial class MyNode : Node + { + private bool _isNumberEditable; + + [Export] + public bool IsNumberEditable + { + get => _isNumberEditable; + set + { + _isNumberEditable = value; + NotifyPropertyListChanged(); + } + } + + [Export] + public int Number { get; set; } + + public override void _ValidateProperty(Godot.Collections.Dictionary property) + { + if (property["name"].AsStringName() == PropertyName.Number && IsNumberEditable) + { + var usage = property["usage"].As>PropertyUsageFlags<() | PropertyUsageFlags.ReadOnly; + property["usage"] = (int)usage; + } + } + } + [/csharp] + [/codeblocks] + </description> + </method> <method name="add_user_signal"> <return type="void" /> <param index="0" name="signal" type="String" /> diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index fe7ccc31a5..b304bc6ca7 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -1732,6 +1732,25 @@ Variant::Type GDScriptInstance::get_property_type(const StringName &p_name, bool return Variant::NIL; } +void GDScriptInstance::validate_property(PropertyInfo &p_property) const { + Variant property = (Dictionary)p_property; + const Variant *args[1] = { &property }; + + const GDScript *sptr = script.ptr(); + while (sptr) { + HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._validate_property); + if (E) { + Callable::CallError err; + Variant ret = E->value->call(const_cast<GDScriptInstance *>(this), args, 1, err); + if (err.error == Callable::CallError::CALL_OK) { + p_property = PropertyInfo::from_dict(property); + return; + } + } + sptr = sptr->_base; + } +} + void GDScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const { // exported members, not done yet! @@ -1797,7 +1816,8 @@ void GDScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const p_properties->push_back(sptr->get_class_category()); #endif // TOOLS_ENABLED - for (const PropertyInfo &prop : props) { + for (PropertyInfo &prop : props) { + validate_property(prop); p_properties->push_back(prop); } @@ -2616,6 +2636,7 @@ GDScriptLanguage::GDScriptLanguage() { strings._set = StaticCString::create("_set"); strings._get = StaticCString::create("_get"); strings._get_property_list = StaticCString::create("_get_property_list"); + strings._validate_property = StaticCString::create("_validate_property"); strings._property_can_revert = StaticCString::create("_property_can_revert"); strings._property_get_revert = StaticCString::create("_property_get_revert"); strings._script_source = StaticCString::create("script/source"); diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index 1fb0f01c1d..ba21a90ce5 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -321,6 +321,7 @@ public: virtual bool get(const StringName &p_name, Variant &r_ret) const; virtual void get_property_list(List<PropertyInfo> *p_properties) const; virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = nullptr) const; + virtual void validate_property(PropertyInfo &p_property) const; virtual bool property_can_revert(const StringName &p_name) const; virtual bool property_get_revert(const StringName &p_name, Variant &r_ret) const; @@ -468,6 +469,7 @@ public: StringName _set; StringName _get; StringName _get_property_list; + StringName _validate_property; StringName _property_can_revert; StringName _property_get_revert; StringName _script_source; diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 2971706c75..1fcb2791d9 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -1656,7 +1656,8 @@ void CSharpInstance::get_property_list(List<PropertyInfo> *p_properties) const { } } - for (const PropertyInfo &prop : props) { + for (PropertyInfo &prop : props) { + validate_property(prop); p_properties->push_back(prop); } } @@ -1694,6 +1695,24 @@ bool CSharpInstance::property_can_revert(const StringName &p_name) const { return (bool)ret; } +void CSharpInstance::validate_property(PropertyInfo &p_property) const { + ERR_FAIL_COND(!script.is_valid()); + + Variant property_arg = (Dictionary)p_property; + const Variant *args[1] = { &property_arg }; + + Variant ret; + Callable::CallError call_error; + GDMonoCache::managed_callbacks.CSharpInstanceBridge_Call( + gchandle.get_intptr(), &SNAME("_validate_property"), args, 1, &call_error, &ret); + + if (call_error.error != Callable::CallError::CALL_OK) { + return; + } + + p_property = PropertyInfo::from_dict(property_arg); +} + bool CSharpInstance::property_get_revert(const StringName &p_name, Variant &r_ret) const { ERR_FAIL_COND_V(!script.is_valid(), false); diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index 22115667a7..e28c91da2c 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -258,6 +258,7 @@ public: bool get(const StringName &p_name, Variant &r_ret) const override; void get_property_list(List<PropertyInfo> *p_properties) const override; Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid) const override; + virtual void validate_property(PropertyInfo &p_property) const override; bool property_can_revert(const StringName &p_name) const override; bool property_get_revert(const StringName &p_name, Variant &r_ret) const override; diff --git a/tests/core/object/test_object.h b/tests/core/object/test_object.h index 8ab6221a1c..a3d6b38ca4 100644 --- a/tests/core/object/test_object.h +++ b/tests/core/object/test_object.h @@ -82,6 +82,8 @@ public: Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid) const override { return Variant::PACKED_FLOAT32_ARRAY; } + virtual void validate_property(PropertyInfo &p_property) const override { + } bool property_can_revert(const StringName &p_name) const override { return false; }; |