summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/object/object.cpp6
-rw-r--r--core/object/script_language.h2
-rw-r--r--core/object/script_language_extension.h3
-rw-r--r--doc/classes/Object.xml53
-rw-r--r--modules/gdscript/gdscript.cpp23
-rw-r--r--modules/gdscript/gdscript.h2
-rw-r--r--modules/mono/csharp_script.cpp21
-rw-r--r--modules/mono/csharp_script.h1
-rw-r--r--tests/core/object/test_object.h2
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 =&gt; _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 &amp;&amp; IsNumberEditable)
+ {
+ var usage = property["usage"].As&gt;PropertyUsageFlags&lt;() | 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;
};