diff --git a/core/extension/gdextension.cpp b/core/extension/gdextension.cpp index 054e51a12031..bd3f14c43093 100644 --- a/core/extension/gdextension.cpp +++ b/core/extension/gdextension.cpp @@ -293,6 +293,7 @@ void GDExtension::_register_extension_class(GDExtensionClassLibraryPtr p_library p_extension_funcs->free_property_list_func, // GDExtensionClassFreePropertyList free_property_list_func; p_extension_funcs->property_can_revert_func, // GDExtensionClassPropertyCanRevert property_can_revert_func; p_extension_funcs->property_get_revert_func, // GDExtensionClassPropertyGetRevert property_get_revert_func; + nullptr, // GDExtensionClassValidateProperty validate_property_func; nullptr, // GDExtensionClassNotification2 notification_func; p_extension_funcs->to_string_func, // GDExtensionClassToString to_string_func; p_extension_funcs->reference_func, // GDExtensionClassReference reference_func; @@ -360,6 +361,7 @@ void GDExtension::_register_extension_class_internal(GDExtensionClassLibraryPtr extension->gdextension.free_property_list = p_extension_funcs->free_property_list_func; extension->gdextension.property_can_revert = p_extension_funcs->property_can_revert_func; extension->gdextension.property_get_revert = p_extension_funcs->property_get_revert_func; + extension->gdextension.validate_property = p_extension_funcs->validate_property_func; #ifndef DISABLE_DEPRECATED if (p_deprecated_funcs) { extension->gdextension.notification = p_deprecated_funcs->notification_func; diff --git a/core/extension/gdextension_interface.h b/core/extension/gdextension_interface.h index 220bb2077a4e..9d9ae20c514b 100644 --- a/core/extension/gdextension_interface.h +++ b/core/extension/gdextension_interface.h @@ -258,6 +258,7 @@ typedef const GDExtensionPropertyInfo *(*GDExtensionClassGetPropertyList)(GDExte typedef void (*GDExtensionClassFreePropertyList)(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list); typedef GDExtensionBool (*GDExtensionClassPropertyCanRevert)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name); typedef GDExtensionBool (*GDExtensionClassPropertyGetRevert)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret); +typedef GDExtensionBool (*GDExtensionClassValidateProperty)(GDExtensionClassInstancePtr p_instance, GDExtensionPropertyInfo *p_property); typedef void (*GDExtensionClassNotification)(GDExtensionClassInstancePtr p_instance, int32_t p_what); // Deprecated. Use GDExtensionClassNotification2 instead. typedef void (*GDExtensionClassNotification2)(GDExtensionClassInstancePtr p_instance, int32_t p_what, GDExtensionBool p_reversed); typedef void (*GDExtensionClassToString)(GDExtensionClassInstancePtr p_instance, GDExtensionBool *r_is_valid, GDExtensionStringPtr p_out); @@ -298,6 +299,7 @@ typedef struct { GDExtensionClassFreePropertyList free_property_list_func; GDExtensionClassPropertyCanRevert property_can_revert_func; GDExtensionClassPropertyGetRevert property_get_revert_func; + GDExtensionClassValidateProperty validate_property_func; GDExtensionClassNotification2 notification_func; GDExtensionClassToString to_string_func; GDExtensionClassReference reference_func; diff --git a/core/object/object.cpp b/core/object/object.cpp index 0a0953f7dc26..50026fc266f7 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -527,6 +527,27 @@ void Object::get_property_list(List *p_list, bool p_reversed) cons void Object::validate_property(PropertyInfo &p_property) const { _validate_propertyv(p_property); + if (_extension && _extension->validate_property) { + // GDExtension uses a StringName rather than a String for property name. + StringName prop_name = p_property.name; + GDExtensionPropertyInfo gdext_prop = { + (GDExtensionVariantType)p_property.type, + &prop_name, + &p_property.class_name, + (uint32_t)p_property.hint, + &p_property.hint_string, + p_property.usage, + }; + if (_extension->validate_property(_extension_instance, &gdext_prop)) { + p_property.type = (Variant::Type)gdext_prop.type; + p_property.name = *reinterpret_cast(gdext_prop.name); + p_property.class_name = *reinterpret_cast(gdext_prop.class_name); + p_property.hint = (PropertyHint)gdext_prop.hint; + p_property.hint_string = *reinterpret_cast(gdext_prop.hint_string); + p_property.usage = gdext_prop.usage; + }; + } + if (script_instance) { // Call it last to allow user altering already validated properties. script_instance->validate_property(p_property); } diff --git a/core/object/object.h b/core/object/object.h index b74aa7c4bcd2..3a698f7526e2 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -322,6 +322,7 @@ struct ObjectGDExtension { GDExtensionClassFreePropertyList free_property_list; GDExtensionClassPropertyCanRevert property_can_revert; GDExtensionClassPropertyGetRevert property_get_revert; + GDExtensionClassValidateProperty validate_property; #ifndef DISABLE_DEPRECATED GDExtensionClassNotification notification; #endif // DISABLE_DEPRECATED diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h index c7218d99a62a..e06f005320ab 100644 --- a/core/object/script_language_extension.h +++ b/core/object/script_language_extension.h @@ -689,9 +689,11 @@ class ScriptInstanceExtension : public ScriptInstance { } virtual void validate_property(PropertyInfo &p_property) const override { if (native_info->validate_property_func) { + // GDExtension uses a StringName rather than a String for property name. + StringName prop_name = p_property.name; GDExtensionPropertyInfo gdext_prop = { (GDExtensionVariantType)p_property.type, - &p_property.name, + &prop_name, &p_property.class_name, (uint32_t)p_property.hint, &p_property.hint_string,