Selaa lähdekoodia

Make `property_*_revert` methods multilevel and expose them for scripting

Yuri Sizov 3 vuotta sitten
vanhempi
commit
980f5f32f4

+ 5 - 6
core/config/project_settings.cpp

@@ -1070,7 +1070,7 @@ bool ProjectSettings::is_using_datapack() const {
 	return using_datapack;
 }
 
-bool ProjectSettings::property_can_revert(const String &p_name) {
+bool ProjectSettings::_property_can_revert(const StringName &p_name) const {
 	if (!props.has(p_name)) {
 		return false;
 	}
@@ -1078,12 +1078,13 @@ bool ProjectSettings::property_can_revert(const String &p_name) {
 	return props[p_name].initial != props[p_name].variant;
 }
 
-Variant ProjectSettings::property_get_revert(const String &p_name) {
+bool ProjectSettings::_property_get_revert(const StringName &p_name, Variant &r_property) const {
 	if (!props.has(p_name)) {
-		return Variant();
+		return false;
 	}
 
-	return props[p_name].initial;
+	r_property = props[p_name].initial;
+	return true;
 }
 
 void ProjectSettings::set_setting(const String &p_setting, const Variant &p_value) {
@@ -1134,8 +1135,6 @@ void ProjectSettings::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("globalize_path", "path"), &ProjectSettings::globalize_path);
 	ClassDB::bind_method(D_METHOD("save"), &ProjectSettings::save);
 	ClassDB::bind_method(D_METHOD("load_resource_pack", "pack", "replace_files", "offset"), &ProjectSettings::_load_resource_pack, DEFVAL(true), DEFVAL(0));
-	ClassDB::bind_method(D_METHOD("property_can_revert", "name"), &ProjectSettings::property_can_revert);
-	ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &ProjectSettings::property_get_revert);
 
 	ClassDB::bind_method(D_METHOD("save_custom", "file"), &ProjectSettings::_save_custom_bnd);
 }

+ 2 - 3
core/config/project_settings.h

@@ -102,6 +102,8 @@ protected:
 	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<PropertyInfo> *p_list) const;
+	bool _property_can_revert(const StringName &p_name) const;
+	bool _property_get_revert(const StringName &p_name, Variant &r_property) const;
 
 	static ProjectSettings *singleton;
 
@@ -147,9 +149,6 @@ public:
 	void set_ignore_value_in_docs(const String &p_name, bool p_ignore);
 	bool get_ignore_value_in_docs(const String &p_name) const;
 
-	bool property_can_revert(const String &p_name);
-	Variant property_get_revert(const String &p_name);
-
 	String get_project_data_dir_name() const;
 	String get_project_data_path() const;
 	String get_resource_path() const;

+ 10 - 0
core/extension/gdnative_interface.h

@@ -222,6 +222,8 @@ typedef struct {
 
 typedef const GDNativePropertyInfo *(*GDNativeExtensionClassGetPropertyList)(GDExtensionClassInstancePtr p_instance, uint32_t *r_count);
 typedef void (*GDNativeExtensionClassFreePropertyList)(GDExtensionClassInstancePtr p_instance, const GDNativePropertyInfo *p_list);
+typedef GDNativeBool (*GDNativeExtensionClassPropertyCanRevert)(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name);
+typedef GDNativeBool (*GDNativeExtensionClassPropertyGetRevert)(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret);
 typedef void (*GDNativeExtensionClassNotification)(GDExtensionClassInstancePtr p_instance, int32_t p_what);
 typedef void (*GDNativeExtensionClassToString)(GDExtensionClassInstancePtr p_instance, GDNativeStringPtr p_out);
 typedef void (*GDNativeExtensionClassReference)(GDExtensionClassInstancePtr p_instance);
@@ -237,6 +239,8 @@ typedef struct {
 	GDNativeExtensionClassGet get_func;
 	GDNativeExtensionClassGetPropertyList get_property_list_func;
 	GDNativeExtensionClassFreePropertyList free_property_list_func;
+	GDNativeExtensionClassPropertyCanRevert property_can_revert_func;
+	GDNativeExtensionClassPropertyGetRevert property_get_revert_func;
 	GDNativeExtensionClassNotification notification_func;
 	GDNativeExtensionClassToString to_string_func;
 	GDNativeExtensionClassReference reference_func;
@@ -309,6 +313,9 @@ typedef const GDNativePropertyInfo *(*GDNativeExtensionScriptInstanceGetProperty
 typedef void (*GDNativeExtensionScriptInstanceFreePropertyList)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativePropertyInfo *p_list);
 typedef GDNativeVariantType (*GDNativeExtensionScriptInstanceGetPropertyType)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, GDNativeBool *r_is_valid);
 
+typedef GDNativeBool (*GDNativeExtensionScriptInstancePropertyCanRevert)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name);
+typedef GDNativeBool (*GDNativeExtensionScriptInstancePropertyGetRevert)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret);
+
 typedef GDNativeObjectPtr (*GDNativeExtensionScriptInstanceGetOwner)(GDNativeExtensionScriptInstanceDataPtr p_instance);
 typedef void (*GDNativeExtensionScriptInstancePropertyStateAdd)(const GDNativeStringNamePtr p_name, const GDNativeVariantPtr p_value, void *p_userdata);
 typedef void (*GDNativeExtensionScriptInstanceGetPropertyState)(GDNativeExtensionScriptInstanceDataPtr p_instance, GDNativeExtensionScriptInstancePropertyStateAdd p_add_func, void *p_userdata);
@@ -343,6 +350,9 @@ typedef struct {
 	GDNativeExtensionScriptInstanceFreePropertyList free_property_list_func;
 	GDNativeExtensionScriptInstanceGetPropertyType get_property_type_func;
 
+	GDNativeExtensionScriptInstancePropertyCanRevert property_can_revert_func;
+	GDNativeExtensionScriptInstancePropertyGetRevert property_get_revert_func;
+
 	GDNativeExtensionScriptInstanceGetOwner get_owner_func;
 	GDNativeExtensionScriptInstanceGetPropertyState get_property_state_func;
 

+ 2 - 0
core/extension/native_extension.cpp

@@ -156,6 +156,8 @@ void NativeExtension::_register_extension_class(const GDNativeExtensionClassLibr
 	extension->native_extension.get = p_extension_funcs->get_func;
 	extension->native_extension.get_property_list = p_extension_funcs->get_property_list_func;
 	extension->native_extension.free_property_list = p_extension_funcs->free_property_list_func;
+	extension->native_extension.property_can_revert = p_extension_funcs->property_can_revert_func;
+	extension->native_extension.property_get_revert = p_extension_funcs->property_get_revert_func;
 	extension->native_extension.notification = p_extension_funcs->notification_func;
 	extension->native_extension.to_string = p_extension_funcs->to_string_func;
 	extension->native_extension.reference = p_extension_funcs->reference_func;

+ 59 - 4
core/object/object.cpp

@@ -518,6 +518,59 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons
 void Object::_validate_property(PropertyInfo &property) const {
 }
 
+bool Object::property_can_revert(const String &p_name) const {
+	if (script_instance) {
+		if (script_instance->property_can_revert(p_name)) {
+			return true;
+		}
+	}
+
+// C style pointer casts should never trigger a compiler warning because the risk is assumed by the user, so GCC should keep quiet about it.
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wignored-qualifiers"
+#endif
+	if (_extension && _extension->property_can_revert) {
+		if (_extension->property_can_revert(_extension_instance, (const GDNativeStringNamePtr)&p_name)) {
+			return true;
+		}
+	}
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+	return _property_can_revertv(p_name);
+}
+
+Variant Object::property_get_revert(const String &p_name) const {
+	Variant ret;
+
+	if (script_instance) {
+		if (script_instance->property_get_revert(p_name, ret)) {
+			return ret;
+		}
+	}
+
+// C style pointer casts should never trigger a compiler warning because the risk is assumed by the user, so GCC should keep quiet about it.
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wignored-qualifiers"
+#endif
+	if (_extension && _extension->property_get_revert) {
+		if (_extension->property_get_revert(_extension_instance, (const GDNativeStringNamePtr)&p_name, (GDNativeVariantPtr)&ret)) {
+			return ret;
+		}
+	}
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+	if (_property_get_revertv(p_name, ret)) {
+		return ret;
+	}
+	return Variant();
+}
+
 void Object::get_method_list(List<MethodInfo> *p_list) const {
 	ClassDB::get_method_list(get_class_name(), p_list);
 	if (script_instance) {
@@ -1499,10 +1552,12 @@ void Object::_bind_methods() {
 	miget.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
 	BIND_OBJ_CORE_METHOD(miget);
 
-	MethodInfo plget("_get_property_list");
-
-	plget.return_val.type = Variant::ARRAY;
-	BIND_OBJ_CORE_METHOD(plget);
+	BIND_OBJ_CORE_METHOD(MethodInfo(Variant::ARRAY, "_get_property_list"));
+	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";
+	mipgr.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
+	BIND_OBJ_CORE_METHOD(mipgr);
 
 #endif
 	BIND_OBJ_CORE_METHOD(MethodInfo("_init"));

+ 36 - 0
core/object/object.h

@@ -294,6 +294,8 @@ struct ObjectNativeExtension {
 	GDNativeExtensionClassGet get;
 	GDNativeExtensionClassGetPropertyList get_property_list;
 	GDNativeExtensionClassFreePropertyList free_property_list;
+	GDNativeExtensionClassPropertyCanRevert property_can_revert;
+	GDNativeExtensionClassPropertyGetRevert property_get_revert;
 	GDNativeExtensionClassNotification notification;
 	GDNativeExtensionClassToString to_string;
 	GDNativeExtensionClassReference reference;
@@ -469,6 +471,28 @@ protected:
 			m_inherits::_get_property_listv(p_list, p_reversed);                                                                                 \
 		}                                                                                                                                        \
 	}                                                                                                                                            \
+	_FORCE_INLINE_ bool (Object::*_get_property_can_revert() const)(const StringName &p_name) const {                                            \
+		return (bool(Object::*)(const StringName &) const) & m_class::_property_can_revert;                                                      \
+	}                                                                                                                                            \
+	virtual bool _property_can_revertv(const StringName &p_name) const override {                                                                \
+		if (m_class::_get_property_can_revert() != m_inherits::_get_property_can_revert()) {                                                     \
+			if (_property_can_revert(p_name)) {                                                                                                  \
+				return true;                                                                                                                     \
+			}                                                                                                                                    \
+		}                                                                                                                                        \
+		return m_inherits::_property_can_revertv(p_name);                                                                                        \
+	}                                                                                                                                            \
+	_FORCE_INLINE_ bool (Object::*_get_property_get_revert() const)(const StringName &p_name, Variant &) const {                                 \
+		return (bool(Object::*)(const StringName &, Variant &) const) & m_class::_property_get_revert;                                           \
+	}                                                                                                                                            \
+	virtual bool _property_get_revertv(const StringName &p_name, Variant &r_ret) const override {                                                \
+		if (m_class::_get_property_get_revert() != m_inherits::_get_property_get_revert()) {                                                     \
+			if (_property_get_revert(p_name, r_ret)) {                                                                                           \
+				return true;                                                                                                                     \
+			}                                                                                                                                    \
+		}                                                                                                                                        \
+		return m_inherits::_property_get_revertv(p_name, r_ret);                                                                                 \
+	}                                                                                                                                            \
 	_FORCE_INLINE_ void (Object::*_get_notification() const)(int) {                                                                              \
 		return (void(Object::*)(int)) & m_class::_notification;                                                                                  \
 	}                                                                                                                                            \
@@ -613,12 +637,16 @@ protected:
 	virtual bool _setv(const StringName &p_name, const Variant &p_property) { return false; };
 	virtual bool _getv(const StringName &p_name, Variant &r_property) const { return false; };
 	virtual void _get_property_listv(List<PropertyInfo> *p_list, bool p_reversed) const {};
+	virtual bool _property_can_revertv(const StringName &p_name) const { return false; };
+	virtual bool _property_get_revertv(const StringName &p_name, Variant &r_property) const { return false; };
 	virtual void _notificationv(int p_notification, bool p_reversed) {}
 
 	static void _bind_methods();
 	bool _set(const StringName &p_name, const Variant &p_property) { return false; };
 	bool _get(const StringName &p_name, Variant &r_property) const { return false; };
 	void _get_property_list(List<PropertyInfo> *p_list) const {};
+	bool _property_can_revert(const StringName &p_name) const { return false; };
+	bool _property_get_revert(const StringName &p_name, Variant &r_property) const { return false; };
 	void _notification(int p_notification) {}
 
 	_FORCE_INLINE_ static void (*_get_bind_methods())() {
@@ -633,6 +661,12 @@ protected:
 	_FORCE_INLINE_ void (Object::*_get_get_property_list() const)(List<PropertyInfo> *p_list) const {
 		return &Object::_get_property_list;
 	}
+	_FORCE_INLINE_ bool (Object::*_get_property_can_revert() const)(const StringName &p_name) const {
+		return &Object::_property_can_revert;
+	}
+	_FORCE_INLINE_ bool (Object::*_get_property_get_revert() const)(const StringName &p_name, Variant &) const {
+		return &Object::_property_get_revert;
+	}
 	_FORCE_INLINE_ void (Object::*_get_notification() const)(int) {
 		return &Object::_notification;
 	}
@@ -757,6 +791,8 @@ public:
 	Variant get_indexed(const Vector<StringName> &p_names, bool *r_valid = nullptr) const;
 
 	void get_property_list(List<PropertyInfo> *p_list, bool p_reversed = false) const;
+	bool property_can_revert(const String &p_name) const;
+	Variant property_get_revert(const String &p_name) const;
 
 	bool has_method(const StringName &p_method) const;
 	void get_method_list(List<MethodInfo> *p_list) const;

+ 6 - 0
core/object/script_language.h

@@ -171,6 +171,9 @@ public:
 	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 bool property_can_revert(const StringName &p_name) const = 0;
+	virtual bool property_get_revert(const StringName &p_name, Variant &r_ret) const = 0;
+
 	virtual Object *get_owner() { return nullptr; }
 	virtual void get_property_state(List<Pair<StringName, Variant>> &state);
 
@@ -447,6 +450,9 @@ public:
 	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 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; };
+
 	virtual void get_method_list(List<MethodInfo> *p_list) const override;
 	virtual bool has_method(const StringName &p_method) const override;
 

+ 13 - 0
core/object/script_language_extension.h

@@ -692,6 +692,19 @@ public:
 		return Variant::NIL;
 	}
 
+	virtual bool property_can_revert(const StringName &p_name) const override {
+		if (native_info->property_can_revert_func) {
+			return native_info->property_can_revert_func(instance, (const GDNativeStringNamePtr)&p_name);
+		}
+		return false;
+	}
+	virtual bool property_get_revert(const StringName &p_name, Variant &r_ret) const override {
+		if (native_info->property_get_revert_func) {
+			return native_info->property_get_revert_func(instance, (const GDNativeStringNamePtr)&p_name, (GDNativeVariantPtr)&r_ret);
+		}
+		return false;
+	}
+
 	virtual Object *get_owner() override {
 		if (native_info->get_owner_func) {
 			return (Object *)native_info->get_owner_func(instance);

+ 0 - 14
doc/classes/EditorSettings.xml

@@ -132,20 +132,6 @@
 				Marks the passed editor setting as being changed, see [method get_changed_settings]. Only settings which exist (see [method has_setting]) will be accepted.
 			</description>
 		</method>
-		<method name="property_can_revert">
-			<return type="bool" />
-			<param index="0" name="name" type="String" />
-			<description>
-				Returns [code]true[/code] if the setting specified by [param name] can have its value reverted to the default value, [code]false[/code] otherwise. When this method returns [code]true[/code], a Revert button will display next to the setting in the Editor Settings.
-			</description>
-		</method>
-		<method name="property_get_revert">
-			<return type="Variant" />
-			<param index="0" name="name" type="String" />
-			<description>
-				Returns the default value of the setting specified by [param name]. This is the value that would be applied when clicking the Revert button in the Editor Settings.
-			</description>
-		</method>
 		<method name="set_builtin_action_override">
 			<return type="void" />
 			<param index="0" name="name" type="String" />

+ 0 - 14
doc/classes/Node3D.xml

@@ -134,20 +134,6 @@
 				Resets this node's transformations (like scale, skew and taper) preserving its rotation and translation by performing Gram-Schmidt orthonormalization on this node's [Transform3D].
 			</description>
 		</method>
-		<method name="property_can_revert">
-			<return type="bool" />
-			<param index="0" name="name" type="String" />
-			<description>
-				Returns [code]true[/code] if the property identified by [param name] can be reverted to a default value.
-			</description>
-		</method>
-		<method name="property_get_revert">
-			<return type="Variant" />
-			<param index="0" name="name" type="String" />
-			<description>
-				Returns the default value of the Node3D property with given [param name].
-			</description>
-		</method>
 		<method name="rotate">
 			<return type="void" />
 			<param index="0" name="axis" type="Vector3" />

+ 16 - 0
doc/classes/Object.xml

@@ -64,6 +64,22 @@
 				Called whenever the object receives a notification, which is identified in [param what] by a constant. The base [Object] has two constants [constant NOTIFICATION_POSTINITIALIZE] and [constant NOTIFICATION_PREDELETE], but subclasses such as [Node] define a lot more notifications which are also received by this method.
 			</description>
 		</method>
+		<method name="_property_can_revert" qualifiers="virtual">
+			<return type="bool" />
+			<param index="0" name="property" type="StringName" />
+			<description>
+				Virtual methods that can be overridden to customize the property revert behavior in the editor.
+				Returns [code]true[/code] if the property identified by [code]name[/code] can be reverted to a default value. Override [method _property_get_revert] to return the actual value.
+			</description>
+		</method>
+		<method name="_property_get_revert" qualifiers="virtual">
+			<return type="Variant" />
+			<param index="0" name="property" type="StringName" />
+			<description>
+				Virtual methods that can be overridden to customize the property revert behavior in the editor.
+				Returns the default value of the property identified by [code]name[/code]. [method _property_can_revert] must be overridden as well for this method to be called.
+			</description>
+		</method>
 		<method name="_set" qualifiers="virtual">
 			<return type="bool" />
 			<param index="0" name="property" type="StringName" />

+ 0 - 14
doc/classes/ProjectSettings.xml

@@ -129,20 +129,6 @@
 				Returns the localized path (starting with [code]res://[/code]) corresponding to the absolute, native OS [param path]. See also [method globalize_path].
 			</description>
 		</method>
-		<method name="property_can_revert">
-			<return type="bool" />
-			<param index="0" name="name" type="String" />
-			<description>
-				Returns [code]true[/code] if the specified property exists and its initial value differs from the current value.
-			</description>
-		</method>
-		<method name="property_get_revert">
-			<return type="Variant" />
-			<param index="0" name="name" type="String" />
-			<description>
-				Returns the specified property's initial value. Returns [code]null[/code] if the property does not exist.
-			</description>
-		</method>
 		<method name="save">
 			<return type="int" enum="Error" />
 			<description>

+ 0 - 14
doc/classes/ShaderMaterial.xml

@@ -17,20 +17,6 @@
 				Returns the current value set for this material of a uniform in the shader.
 			</description>
 		</method>
-		<method name="property_can_revert">
-			<return type="bool" />
-			<param index="0" name="name" type="String" />
-			<description>
-				Returns [code]true[/code] if the property identified by [param name] can be reverted to a default value.
-			</description>
-		</method>
-		<method name="property_get_revert">
-			<return type="Variant" />
-			<param index="0" name="name" type="String" />
-			<description>
-				Returns the default value of the material property with given [param name].
-			</description>
-		</method>
 		<method name="set_shader_uniform">
 			<return type="void" />
 			<param index="0" name="param" type="StringName" />

+ 2 - 2
editor/editor_inspector.cpp

@@ -432,11 +432,11 @@ bool EditorProperty::is_read_only() const {
 }
 
 Variant EditorPropertyRevert::get_property_revert_value(Object *p_object, const StringName &p_property, bool *r_is_valid) {
-	if (p_object->has_method("property_can_revert") && p_object->call("property_can_revert", p_property)) {
+	if (p_object->property_can_revert(p_property)) {
 		if (r_is_valid) {
 			*r_is_valid = true;
 		}
-		return p_object->call("property_get_revert", p_property);
+		return p_object->property_get_revert(p_property);
 	}
 
 	return PropertyUtils::get_property_default_value(p_object, p_property, r_is_valid);

+ 2 - 2
editor/editor_sectioned_inspector.cpp

@@ -114,11 +114,11 @@ class SectionedInspectorFilter : public Object {
 	}
 
 	bool property_can_revert(const String &p_name) {
-		return edited->call("property_can_revert", section + "/" + p_name);
+		return edited->property_can_revert(section + "/" + p_name);
 	}
 
 	Variant property_get_revert(const String &p_name) {
-		return edited->call("property_get_revert", section + "/" + p_name);
+		return edited->property_get_revert(section + "/" + p_name);
 	}
 
 protected:

+ 9 - 10
editor/editor_settings.cpp

@@ -1073,24 +1073,25 @@ Variant _EDITOR_GET(const String &p_setting) {
 	return EditorSettings::get_singleton()->get(p_setting);
 }
 
-bool EditorSettings::property_can_revert(const String &p_setting) {
-	if (!props.has(p_setting)) {
+bool EditorSettings::_property_can_revert(const StringName &p_name) const {
+	if (!props.has(p_name)) {
 		return false;
 	}
 
-	if (!props[p_setting].has_default_value) {
+	if (!props[p_name].has_default_value) {
 		return false;
 	}
 
-	return props[p_setting].initial != props[p_setting].variant;
+	return props[p_name].initial != props[p_name].variant;
 }
 
-Variant EditorSettings::property_get_revert(const String &p_setting) {
-	if (!props.has(p_setting) || !props[p_setting].has_default_value) {
-		return Variant();
+bool EditorSettings::_property_get_revert(const StringName &p_name, Variant &r_property) const {
+	if (!props.has(p_name) || !props[p_name].has_default_value) {
+		return false;
 	}
 
-	return props[p_setting].initial;
+	r_property = props[p_name].initial;
+	return true;
 }
 
 void EditorSettings::add_property_hint(const PropertyInfo &p_hint) {
@@ -1621,8 +1622,6 @@ void EditorSettings::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_setting", "name"), &EditorSettings::get_setting);
 	ClassDB::bind_method(D_METHOD("erase", "property"), &EditorSettings::erase);
 	ClassDB::bind_method(D_METHOD("set_initial_value", "name", "value", "update_current"), &EditorSettings::set_initial_value);
-	ClassDB::bind_method(D_METHOD("property_can_revert", "name"), &EditorSettings::property_can_revert);
-	ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &EditorSettings::property_get_revert);
 	ClassDB::bind_method(D_METHOD("add_property_info", "info"), &EditorSettings::_add_property_info_bind);
 
 	ClassDB::bind_method(D_METHOD("set_project_metadata", "section", "key", "data"), &EditorSettings::set_project_metadata);

+ 2 - 2
editor/editor_settings.h

@@ -100,6 +100,8 @@ private:
 	void _initial_set(const StringName &p_name, const Variant &p_value);
 	void _get_property_list(List<PropertyInfo> *p_list) const;
 	void _add_property_info_bind(const Dictionary &p_info);
+	bool _property_can_revert(const StringName &p_name) const;
+	bool _property_get_revert(const StringName &p_name, Variant &r_property) const;
 
 	void _load_defaults(Ref<ConfigFile> p_extra_config = Ref<ConfigFile>());
 	void _load_godot2_text_editor_theme();
@@ -138,8 +140,6 @@ public:
 			_set_only(p_setting, p_value);
 		}
 	}
-	bool property_can_revert(const String &p_setting);
-	Variant property_get_revert(const String &p_setting);
 	void add_property_hint(const PropertyInfo &p_hint);
 	Array get_changed_settings() const;
 	bool check_changed_settings_in_group(const String &p_setting_prefix) const;

+ 5 - 9
editor/plugins/font_config_plugin.cpp

@@ -100,11 +100,6 @@ bool EditorPropertyFontOTObject::_get(const StringName &p_name, Variant &r_ret)
 	return false;
 }
 
-void EditorPropertyFontOTObject::_bind_methods() {
-	ClassDB::bind_method(D_METHOD("property_can_revert", "name"), &EditorPropertyFontOTObject::property_can_revert);
-	ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &EditorPropertyFontOTObject::property_get_revert);
-}
-
 void EditorPropertyFontOTObject::set_dict(const Dictionary &p_dict) {
 	dict = p_dict;
 }
@@ -121,7 +116,7 @@ Dictionary EditorPropertyFontOTObject::get_defaults() {
 	return defaults_dict;
 }
 
-bool EditorPropertyFontOTObject::property_can_revert(const String &p_name) {
+bool EditorPropertyFontOTObject::_property_can_revert(const StringName &p_name) const {
 	String name = p_name;
 
 	if (name.begins_with("keys")) {
@@ -136,18 +131,19 @@ bool EditorPropertyFontOTObject::property_can_revert(const String &p_name) {
 	return false;
 }
 
-Variant EditorPropertyFontOTObject::property_get_revert(const String &p_name) {
+bool EditorPropertyFontOTObject::_property_get_revert(const StringName &p_name, Variant &r_property) const {
 	String name = p_name;
 
 	if (name.begins_with("keys")) {
 		int key = name.get_slicec('/', 1).to_int();
 		if (defaults_dict.has(key)) {
 			Vector3i range = defaults_dict[key];
-			return range.z;
+			r_property = range.z;
+			return true;
 		}
 	}
 
-	return Variant();
+	return false;
 }
 
 /*************************************************************************/

+ 2 - 4
editor/plugins/font_config_plugin.h

@@ -66,7 +66,8 @@ class EditorPropertyFontOTObject : public RefCounted {
 protected:
 	bool _set(const StringName &p_name, const Variant &p_value);
 	bool _get(const StringName &p_name, Variant &r_ret) const;
-	static void _bind_methods();
+	bool _property_can_revert(const StringName &p_name) const;
+	bool _property_get_revert(const StringName &p_name, Variant &r_property) const;
 
 public:
 	void set_dict(const Dictionary &p_dict);
@@ -75,9 +76,6 @@ public:
 	void set_defaults(const Dictionary &p_dict);
 	Dictionary get_defaults();
 
-	bool property_can_revert(const String &p_name);
-	Variant property_get_revert(const String &p_name);
-
 	EditorPropertyFontOTObject(){};
 };
 

+ 43 - 0
modules/gdscript/gdscript.cpp

@@ -1538,6 +1538,47 @@ void GDScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const
 	}
 }
 
+bool GDScriptInstance::property_can_revert(const StringName &p_name) const {
+	Variant name = p_name;
+	const Variant *args[1] = { &name };
+
+	const GDScript *sptr = script.ptr();
+	while (sptr) {
+		HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._property_can_revert);
+		if (E) {
+			Callable::CallError err;
+			Variant ret = E->value->call(const_cast<GDScriptInstance *>(this), args, 1, err);
+			if (err.error == Callable::CallError::CALL_OK && ret.get_type() == Variant::BOOL && ret.operator bool()) {
+				return true;
+			}
+		}
+		sptr = sptr->_base;
+	}
+
+	return false;
+}
+
+bool GDScriptInstance::property_get_revert(const StringName &p_name, Variant &r_ret) const {
+	Variant name = p_name;
+	const Variant *args[1] = { &name };
+
+	const GDScript *sptr = script.ptr();
+	while (sptr) {
+		HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._property_get_revert);
+		if (E) {
+			Callable::CallError err;
+			Variant ret = E->value->call(const_cast<GDScriptInstance *>(this), args, 1, err);
+			if (err.error == Callable::CallError::CALL_OK && ret.get_type() != Variant::NIL) {
+				r_ret = ret;
+				return true;
+			}
+		}
+		sptr = sptr->_base;
+	}
+
+	return false;
+}
+
 void GDScriptInstance::get_method_list(List<MethodInfo> *p_list) const {
 	const GDScript *sptr = script.ptr();
 	while (sptr) {
@@ -2248,6 +2289,8 @@ GDScriptLanguage::GDScriptLanguage() {
 	strings._set = StaticCString::create("_set");
 	strings._get = StaticCString::create("_get");
 	strings._get_property_list = StaticCString::create("_get_property_list");
+	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");
 	_debug_parse_err_line = -1;
 	_debug_parse_err_file = "";

+ 5 - 0
modules/gdscript/gdscript.h

@@ -287,6 +287,9 @@ public:
 	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 bool property_can_revert(const StringName &p_name) const;
+	virtual bool property_get_revert(const StringName &p_name, Variant &r_ret) const;
+
 	virtual void get_method_list(List<MethodInfo> *p_list) const;
 	virtual bool has_method(const StringName &p_method) const;
 	virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
@@ -423,6 +426,8 @@ public:
 		StringName _set;
 		StringName _get;
 		StringName _get_property_list;
+		StringName _property_can_revert;
+		StringName _property_get_revert;
 		StringName _script_source;
 
 	} strings;

+ 70 - 0
modules/mono/csharp_script.cpp

@@ -1853,6 +1853,74 @@ Variant::Type CSharpInstance::get_property_type(const StringName &p_name, bool *
 	return Variant::NIL;
 }
 
+bool CSharpInstance::property_can_revert(const StringName &p_name) const {
+	ERR_FAIL_COND_V(!script.is_valid(), false);
+
+	GD_MONO_SCOPE_THREAD_ATTACH;
+
+	MonoObject *mono_object = get_mono_object();
+	ERR_FAIL_NULL_V(mono_object, false);
+
+	GDMonoClass *top = script->script_class;
+
+	while (top && top != script->native) {
+		GDMonoMethod *method = top->get_method(CACHED_STRING_NAME(_property_can_revert), 1);
+
+		if (method) {
+			Variant name = p_name;
+			const Variant *args[1] = { &name };
+
+			MonoObject *ret = method->invoke(mono_object, args);
+
+			if (ret) {
+				bool can_revert = GDMonoMarshal::mono_object_to_variant(ret);
+				if (can_revert) {
+					return true;
+				}
+			}
+
+			break;
+		}
+
+		top = top->get_parent_class();
+	}
+
+	return false;
+}
+
+bool CSharpInstance::property_get_revert(const StringName &p_name, Variant &r_ret) const {
+	ERR_FAIL_COND_V(!script.is_valid(), false);
+
+	GD_MONO_SCOPE_THREAD_ATTACH;
+
+	MonoObject *mono_object = get_mono_object();
+	ERR_FAIL_NULL_V(mono_object, false);
+
+	GDMonoClass *top = script->script_class;
+
+	while (top && top != script->native) {
+		GDMonoMethod *method = top->get_method(CACHED_STRING_NAME(_property_get_revert), 1);
+
+		if (method) {
+			Variant name = p_name;
+			const Variant *args[1] = { &name };
+
+			MonoObject *ret = method->invoke(mono_object, args);
+
+			if (ret) {
+				r_ret = GDMonoMarshal::mono_object_to_variant(ret);
+				return true;
+			}
+
+			break;
+		}
+
+		top = top->get_parent_class();
+	}
+
+	return false;
+}
+
 void CSharpInstance::get_method_list(List<MethodInfo> *p_list) const {
 	if (!script->is_valid() || !script->script_class) {
 		return;
@@ -3705,6 +3773,8 @@ CSharpLanguage::StringNameCache::StringNameCache() {
 	_set = StaticCString::create("_set");
 	_get = StaticCString::create("_get");
 	_get_property_list = StaticCString::create("_get_property_list");
+	_property_can_revert = StaticCString::create("_property_can_revert");
+	_property_get_revert = StaticCString::create("_property_get_revert");
 	_notification = StaticCString::create("_notification");
 	_script_source = StaticCString::create("script/source");
 	on_before_serialize = StaticCString::create("OnBeforeSerialize");

+ 5 - 0
modules/mono/csharp_script.h

@@ -293,6 +293,9 @@ public:
 	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;
 
+	bool property_can_revert(const StringName &p_name) const override;
+	bool property_get_revert(const StringName &p_name, Variant &r_ret) const override;
+
 	void get_method_list(List<MethodInfo> *p_list) const override;
 	bool has_method(const StringName &p_method) const override;
 	Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override;
@@ -371,6 +374,8 @@ class CSharpLanguage : public ScriptLanguage {
 		StringName _set;
 		StringName _get;
 		StringName _get_property_list;
+		StringName _property_can_revert;
+		StringName _property_get_revert;
 		StringName _notification;
 		StringName _script_source;
 		StringName dotctor; // .ctor

+ 3 - 0
modules/visual_script/visual_script.h

@@ -409,6 +409,9 @@ public:
 	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 bool property_can_revert(const StringName &p_name) const { return false; };
+	virtual bool property_get_revert(const StringName &p_name, Variant &r_ret) const { return false; };
+
 	virtual void get_method_list(List<MethodInfo> *p_list) const;
 	virtual bool has_method(const StringName &p_method) const;
 	virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error);

+ 15 - 17
scene/3d/node_3d.cpp

@@ -897,7 +897,7 @@ void Node3D::_validate_property(PropertyInfo &property) const {
 	}
 }
 
-bool Node3D::property_can_revert(const String &p_name) {
+bool Node3D::_property_can_revert(const StringName &p_name) const {
 	if (p_name == "basis") {
 		return true;
 	} else if (p_name == "scale") {
@@ -912,47 +912,48 @@ bool Node3D::property_can_revert(const String &p_name) {
 	return false;
 }
 
-Variant Node3D::property_get_revert(const String &p_name) {
-	Variant r_ret;
+bool Node3D::_property_get_revert(const StringName &p_name, Variant &r_property) const {
 	bool valid = false;
 
 	if (p_name == "basis") {
 		Variant variant = PropertyUtils::get_property_default_value(this, "transform", &valid);
 		if (valid && variant.get_type() == Variant::Type::TRANSFORM3D) {
-			r_ret = Transform3D(variant).get_basis();
+			r_property = Transform3D(variant).get_basis();
 		} else {
-			r_ret = Basis();
+			r_property = Basis();
 		}
 	} else if (p_name == "scale") {
 		Variant variant = PropertyUtils::get_property_default_value(this, "transform", &valid);
 		if (valid && variant.get_type() == Variant::Type::TRANSFORM3D) {
-			r_ret = Transform3D(variant).get_basis().get_scale();
+			r_property = Transform3D(variant).get_basis().get_scale();
 		} else {
-			return Vector3(1.0, 1.0, 1.0);
+			r_property = Vector3(1.0, 1.0, 1.0);
 		}
 	} else if (p_name == "quaternion") {
 		Variant variant = PropertyUtils::get_property_default_value(this, "transform", &valid);
 		if (valid && variant.get_type() == Variant::Type::TRANSFORM3D) {
-			r_ret = Quaternion(Transform3D(variant).get_basis().get_rotation_quaternion());
+			r_property = Quaternion(Transform3D(variant).get_basis().get_rotation_quaternion());
 		} else {
-			return Quaternion();
+			r_property = Quaternion();
 		}
 	} else if (p_name == "rotation") {
 		Variant variant = PropertyUtils::get_property_default_value(this, "transform", &valid);
 		if (valid && variant.get_type() == Variant::Type::TRANSFORM3D) {
-			r_ret = Transform3D(variant).get_basis().get_euler_normalized(data.euler_rotation_order);
+			r_property = Transform3D(variant).get_basis().get_euler_normalized(data.euler_rotation_order);
 		} else {
-			return Vector3();
+			r_property = Vector3();
 		}
 	} else if (p_name == "position") {
 		Variant variant = PropertyUtils::get_property_default_value(this, "transform", &valid);
 		if (valid) {
-			r_ret = Transform3D(variant).get_origin();
+			r_property = Transform3D(variant).get_origin();
 		} else {
-			return Vector3();
+			r_property = Vector3();
 		}
+	} else {
+		return false;
 	}
-	return r_ret;
+	return true;
 }
 
 void Node3D::_bind_methods() {
@@ -1032,9 +1033,6 @@ void Node3D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("to_local", "global_point"), &Node3D::to_local);
 	ClassDB::bind_method(D_METHOD("to_global", "local_point"), &Node3D::to_global);
 
-	ClassDB::bind_method(D_METHOD("property_can_revert", "name"), &Node3D::property_can_revert);
-	ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &Node3D::property_get_revert);
-
 	BIND_CONSTANT(NOTIFICATION_TRANSFORM_CHANGED);
 	BIND_CONSTANT(NOTIFICATION_ENTER_WORLD);
 	BIND_CONSTANT(NOTIFICATION_EXIT_WORLD);

+ 2 - 2
scene/3d/node_3d.h

@@ -157,8 +157,8 @@ protected:
 
 	virtual void _validate_property(PropertyInfo &property) const override;
 
-	bool property_can_revert(const String &p_name);
-	Variant property_get_revert(const String &p_name);
+	bool _property_can_revert(const StringName &p_name) const;
+	bool _property_get_revert(const StringName &p_name, Variant &r_property) const;
 
 public:
 	enum {

+ 5 - 7
scene/resources/material.cpp

@@ -297,7 +297,7 @@ void ShaderMaterial::_get_property_list(List<PropertyInfo> *p_list) const {
 	}
 }
 
-bool ShaderMaterial::property_can_revert(const String &p_name) {
+bool ShaderMaterial::_property_can_revert(const StringName &p_name) const {
 	if (shader.is_valid()) {
 		StringName pr = shader->remap_uniform(p_name);
 		if (pr) {
@@ -310,15 +310,15 @@ bool ShaderMaterial::property_can_revert(const String &p_name) {
 	return false;
 }
 
-Variant ShaderMaterial::property_get_revert(const String &p_name) {
-	Variant r_ret;
+bool ShaderMaterial::_property_get_revert(const StringName &p_name, Variant &r_property) const {
 	if (shader.is_valid()) {
 		StringName pr = shader->remap_uniform(p_name);
 		if (pr) {
-			r_ret = RenderingServer::get_singleton()->shader_get_param_default(shader->get_rid(), pr);
+			r_property = RenderingServer::get_singleton()->shader_get_param_default(shader->get_rid(), pr);
+			return true;
 		}
 	}
-	return r_ret;
+	return false;
 }
 
 void ShaderMaterial::set_shader(const Ref<Shader> &p_shader) {
@@ -386,8 +386,6 @@ void ShaderMaterial::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_shader"), &ShaderMaterial::get_shader);
 	ClassDB::bind_method(D_METHOD("set_shader_uniform", "param", "value"), &ShaderMaterial::set_shader_uniform);
 	ClassDB::bind_method(D_METHOD("get_shader_uniform", "param"), &ShaderMaterial::get_shader_uniform);
-	ClassDB::bind_method(D_METHOD("property_can_revert", "name"), &ShaderMaterial::property_can_revert);
-	ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &ShaderMaterial::property_get_revert);
 
 	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shader", PROPERTY_HINT_RESOURCE_TYPE, "Shader"), "set_shader", "get_shader");
 }

+ 2 - 2
scene/resources/material.h

@@ -99,8 +99,8 @@ protected:
 	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<PropertyInfo> *p_list) const;
-	bool property_can_revert(const String &p_name);
-	Variant property_get_revert(const String &p_name);
+	bool _property_can_revert(const StringName &p_name) const;
+	bool _property_get_revert(const StringName &p_name, Variant &r_property) const;
 
 	static void _bind_methods();
 

+ 6 - 0
tests/core/object/test_object.h

@@ -82,6 +82,12 @@ public:
 	Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid) const override {
 		return Variant::PACKED_FLOAT32_ARRAY;
 	}
+	bool property_can_revert(const StringName &p_name) const override {
+		return false;
+	};
+	bool property_get_revert(const StringName &p_name, Variant &r_ret) const override {
+		return false;
+	};
 	void get_method_list(List<MethodInfo> *p_list) const override {
 	}
 	bool has_method(const StringName &p_method) const override {