Merge pull request #75778 from KoBeWi/_vp
Expose `_validate_property()` for scripting
This commit is contained in:
commit
76d318dbd1
|
@ -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";
|
||||
|
|
|
@ -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; };
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue