ソースを参照

Remove unnecessary `_validate_property()` calling

LuoZhihao 1 ヶ月 前
コミット
713ed59a77

+ 1 - 1
doc/classes/AnimationMixer.xml

@@ -317,7 +317,7 @@
 			This is used by the editor. If set to [code]true[/code], the scene will be saved with the effects of the reset animation (the animation with the key [code]"RESET"[/code]) applied as if it had been seeked to time 0, with the editor keeping the values that the scene had before saving.
 			This makes it more convenient to preview and edit animations in the editor, as changes to the scene will not be saved as long as they are set in the reset animation.
 		</member>
-		<member name="root_motion_local" type="bool" setter="set_root_motion_local" getter="is_root_motion_local">
+		<member name="root_motion_local" type="bool" setter="set_root_motion_local" getter="is_root_motion_local" default="false">
 			If [code]true[/code], [method get_root_motion_position] value is extracted as a local translation value before blending. In other words, it is treated like the translation is done after the rotation.
 		</member>
 		<member name="root_motion_track" type="NodePath" setter="set_root_motion_track" getter="get_root_motion_track" default="NodePath(&quot;&quot;)">

+ 8 - 19
scene/3d/aim_modifier_3d.cpp

@@ -29,6 +29,7 @@
 /**************************************************************************/
 
 #include "aim_modifier_3d.h"
+#include "scene/3d/look_at_modifier_3d.h"
 
 bool AimModifier3D::_set(const StringName &p_path, const Variant &p_value) {
 	String path = p_path;
@@ -76,29 +77,17 @@ bool AimModifier3D::_get(const StringName &p_path, Variant &r_ret) const {
 	return true;
 }
 
-void AimModifier3D::_validate_dynamic_prop(PropertyInfo &p_property) const {
-	PackedStringArray split = p_property.name.split("/");
-	if (split.size() == 3 && split[0] == "settings" && (split[2] == "primary_rotation_axis" || split[2] == "use_secondary_rotation")) {
-		int which = split[1].to_int();
-		if (!is_using_euler(which)) {
-			p_property.usage = PROPERTY_USAGE_NONE;
-		}
-	}
-}
-
 void AimModifier3D::_get_property_list(List<PropertyInfo> *p_list) const {
 	BoneConstraint3D::get_property_list(p_list);
-	LocalVector<PropertyInfo> props;
+
 	for (int i = 0; i < settings.size(); i++) {
 		String path = "settings/" + itos(i) + "/";
-		props.push_back(PropertyInfo(Variant::INT, path + "forward_axis", PROPERTY_HINT_ENUM, "+X,-X,+Y,-Y,+Z,-Z"));
-		props.push_back(PropertyInfo(Variant::BOOL, path + "use_euler"));
-		props.push_back(PropertyInfo(Variant::INT, path + "primary_rotation_axis", PROPERTY_HINT_ENUM, "X,Y,Z"));
-		props.push_back(PropertyInfo(Variant::BOOL, path + "use_secondary_rotation"));
-	}
-	for (PropertyInfo &p : props) {
-		_validate_dynamic_prop(p);
-		p_list->push_back(p);
+		int rotation_usage = is_using_euler(i) ? PROPERTY_USAGE_DEFAULT : PROPERTY_USAGE_NONE;
+
+		p_list->push_back(PropertyInfo(Variant::INT, path + "forward_axis", PROPERTY_HINT_ENUM, "+X,-X,+Y,-Y,+Z,-Z"));
+		p_list->push_back(PropertyInfo(Variant::BOOL, path + "use_euler"));
+		p_list->push_back(PropertyInfo(Variant::INT, path + "primary_rotation_axis", PROPERTY_HINT_ENUM, "X,Y,Z", rotation_usage));
+		p_list->push_back(PropertyInfo(Variant::BOOL, path + "use_secondary_rotation", PROPERTY_HINT_NONE, "", rotation_usage));
 	}
 }
 

+ 0 - 2
scene/3d/aim_modifier_3d.h

@@ -31,7 +31,6 @@
 #pragma once
 
 #include "scene/3d/bone_constraint_3d.h"
-#include "scene/3d/look_at_modifier_3d.h"
 
 class AimModifier3D : public BoneConstraint3D {
 	GDCLASS(AimModifier3D, BoneConstraint3D);
@@ -49,7 +48,6 @@ protected:
 	bool _set(const StringName &p_path, const Variant &p_value);
 	virtual PackedStringArray get_configuration_warnings() const override;
 	void _get_property_list(List<PropertyInfo> *p_list) const;
-	void _validate_dynamic_prop(PropertyInfo &p_property) const;
 
 	static void _bind_methods();
 

+ 0 - 2
scene/3d/camera_3d.cpp

@@ -139,8 +139,6 @@ void Camera3D::_validate_property(PropertyInfo &p_property) const {
 			}
 		}
 	}
-
-	Node3D::_validate_property(p_property);
 }
 
 void Camera3D::_update_camera() {

+ 28 - 48
scene/3d/convert_transform_modifier_3d.cpp

@@ -122,60 +122,40 @@ bool ConvertTransformModifier3D::_get(const StringName &p_path, Variant &r_ret)
 	return true;
 }
 
-void ConvertTransformModifier3D::_validate_dynamic_prop(PropertyInfo &p_property) const {
-	PackedStringArray split = p_property.name.split("/");
-	if (split.size() == 4 && split[0] == "settings") {
-		int which = split[1].to_int();
-		bool hide = false;
-		if (split[2] == "apply") {
-			if (split[3] == "range_min" || split[3] == "range_max") {
-				if (get_apply_transform_mode(which) == TRANSFORM_MODE_POSITION) {
-					p_property.hint_string = HINT_POSITION;
-				} else if (get_apply_transform_mode(which) == TRANSFORM_MODE_ROTATION) {
-					p_property.hint_string = HINT_ROTATION;
-				} else {
-					p_property.hint_string = HINT_SCALE;
-				}
-			}
-		} else if (split[2] == "reference") {
-			if (split[3] == "range_min" || split[3] == "range_max") {
-				if (get_reference_transform_mode(which) == TRANSFORM_MODE_POSITION) {
-					p_property.hint_string = HINT_POSITION;
-				} else if (get_reference_transform_mode(which) == TRANSFORM_MODE_ROTATION) {
-					p_property.hint_string = HINT_ROTATION;
-				} else {
-					p_property.hint_string = HINT_SCALE;
-				}
-			}
-		}
-		if (hide) {
-			p_property.usage = PROPERTY_USAGE_NONE;
-		}
-	}
-}
-
 void ConvertTransformModifier3D::_get_property_list(List<PropertyInfo> *p_list) const {
 	BoneConstraint3D::get_property_list(p_list);
-	LocalVector<PropertyInfo> props;
+
 	for (int i = 0; i < settings.size(); i++) {
 		String path = "settings/" + itos(i) + "/";
 
-		props.push_back(PropertyInfo(Variant::INT, path + "apply/transform_mode", PROPERTY_HINT_ENUM, "Position,Rotation,Scale"));
-		props.push_back(PropertyInfo(Variant::INT, path + "apply/axis", PROPERTY_HINT_ENUM, "X,Y,Z"));
-		props.push_back(PropertyInfo(Variant::FLOAT, path + "apply/range_min", PROPERTY_HINT_RANGE, HINT_POSITION));
-		props.push_back(PropertyInfo(Variant::FLOAT, path + "apply/range_max", PROPERTY_HINT_RANGE, HINT_POSITION));
-
-		props.push_back(PropertyInfo(Variant::INT, path + "reference/transform_mode", PROPERTY_HINT_ENUM, "Position,Rotation,Scale"));
-		props.push_back(PropertyInfo(Variant::INT, path + "reference/axis", PROPERTY_HINT_ENUM, "X,Y,Z"));
-		props.push_back(PropertyInfo(Variant::FLOAT, path + "reference/range_min", PROPERTY_HINT_RANGE, HINT_POSITION));
-		props.push_back(PropertyInfo(Variant::FLOAT, path + "reference/range_max", PROPERTY_HINT_RANGE, HINT_POSITION));
+		String hint_apply_range;
+		if (get_apply_transform_mode(i) == TRANSFORM_MODE_POSITION) {
+			hint_apply_range = HINT_POSITION;
+		} else if (get_apply_transform_mode(i) == TRANSFORM_MODE_ROTATION) {
+			hint_apply_range = HINT_ROTATION;
+		} else {
+			hint_apply_range = HINT_SCALE;
+		}
+		p_list->push_back(PropertyInfo(Variant::INT, path + "apply/transform_mode", PROPERTY_HINT_ENUM, "Position,Rotation,Scale"));
+		p_list->push_back(PropertyInfo(Variant::INT, path + "apply/axis", PROPERTY_HINT_ENUM, "X,Y,Z"));
+		p_list->push_back(PropertyInfo(Variant::FLOAT, path + "apply/range_min", PROPERTY_HINT_RANGE, hint_apply_range));
+		p_list->push_back(PropertyInfo(Variant::FLOAT, path + "apply/range_max", PROPERTY_HINT_RANGE, hint_apply_range));
+
+		String hint_reference_range;
+		if (get_reference_transform_mode(i) == TRANSFORM_MODE_POSITION) {
+			hint_reference_range = HINT_POSITION;
+		} else if (get_reference_transform_mode(i) == TRANSFORM_MODE_ROTATION) {
+			hint_reference_range = HINT_ROTATION;
+		} else {
+			hint_reference_range = HINT_SCALE;
+		}
+		p_list->push_back(PropertyInfo(Variant::INT, path + "reference/transform_mode", PROPERTY_HINT_ENUM, "Position,Rotation,Scale"));
+		p_list->push_back(PropertyInfo(Variant::INT, path + "reference/axis", PROPERTY_HINT_ENUM, "X,Y,Z"));
+		p_list->push_back(PropertyInfo(Variant::FLOAT, path + "reference/range_min", PROPERTY_HINT_RANGE, hint_reference_range));
+		p_list->push_back(PropertyInfo(Variant::FLOAT, path + "reference/range_max", PROPERTY_HINT_RANGE, hint_reference_range));
 
-		props.push_back(PropertyInfo(Variant::BOOL, path + "relative"));
-		props.push_back(PropertyInfo(Variant::BOOL, path + "additive"));
-	}
-	for (PropertyInfo &p : props) {
-		_validate_dynamic_prop(p);
-		p_list->push_back(p);
+		p_list->push_back(PropertyInfo(Variant::BOOL, path + "relative"));
+		p_list->push_back(PropertyInfo(Variant::BOOL, path + "additive"));
 	}
 }
 

+ 0 - 1
scene/3d/convert_transform_modifier_3d.h

@@ -61,7 +61,6 @@ protected:
 	bool _get(const StringName &p_path, Variant &r_ret) const;
 	bool _set(const StringName &p_path, const Variant &p_value);
 	void _get_property_list(List<PropertyInfo> *p_list) const;
-	void _validate_dynamic_prop(PropertyInfo &p_property) const;
 
 	static void _bind_methods();
 

+ 0 - 4
scene/3d/copy_transform_modifier_3d.cpp

@@ -91,10 +91,6 @@ void CopyTransformModifier3D::_get_property_list(List<PropertyInfo> *p_list) con
 		p_list->push_back(PropertyInfo(Variant::BOOL, path + "relative"));
 		p_list->push_back(PropertyInfo(Variant::BOOL, path + "additive"));
 	}
-
-	for (PropertyInfo &E : *p_list) {
-		_validate_property(E);
-	}
 }
 
 void CopyTransformModifier3D::_validate_setting(int p_index) {

+ 0 - 2
scene/3d/look_at_modifier_3d.cpp

@@ -31,8 +31,6 @@
 #include "look_at_modifier_3d.h"
 
 void LookAtModifier3D::_validate_property(PropertyInfo &p_property) const {
-	SkeletonModifier3D::_validate_property(p_property);
-
 	if (p_property.name == "bone_name" || p_property.name == "origin_bone_name") {
 		Skeleton3D *skeleton = get_skeleton();
 		if (skeleton) {

+ 15 - 42
scene/3d/skeleton_3d.cpp

@@ -182,56 +182,29 @@ bool Skeleton3D::_get(const StringName &p_path, Variant &r_ret) const {
 void Skeleton3D::_get_property_list(List<PropertyInfo> *p_list) const {
 	for (uint32_t i = 0; i < bones.size(); i++) {
 		const String prep = vformat("%s/%d/", "bones", i);
+
+		int enabled_usage = PROPERTY_USAGE_NO_EDITOR;
+		int xform_usage = PROPERTY_USAGE_NO_EDITOR;
+		if (is_show_rest_only()) {
+			enabled_usage |= PROPERTY_USAGE_READ_ONLY;
+			xform_usage |= PROPERTY_USAGE_READ_ONLY;
+		} else if (!is_bone_enabled(i)) {
+			xform_usage |= PROPERTY_USAGE_READ_ONLY;
+		}
+
 		p_list->push_back(PropertyInfo(Variant::STRING, prep + "name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
 		p_list->push_back(PropertyInfo(Variant::INT, prep + "parent", PROPERTY_HINT_RANGE, "-1," + itos(bones.size() - 1) + ",1", PROPERTY_USAGE_NO_EDITOR));
-		p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, prep + "rest", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
-		p_list->push_back(PropertyInfo(Variant::BOOL, prep + "enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
-		p_list->push_back(PropertyInfo(Variant::VECTOR3, prep + "position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
-		p_list->push_back(PropertyInfo(Variant::QUATERNION, prep + "rotation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
-		p_list->push_back(PropertyInfo(Variant::VECTOR3, prep + "scale", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
+		p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, prep + "rest", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_READ_ONLY));
+		p_list->push_back(PropertyInfo(Variant::BOOL, prep + "enabled", PROPERTY_HINT_NONE, "", enabled_usage));
+		p_list->push_back(PropertyInfo(Variant::VECTOR3, prep + "position", PROPERTY_HINT_NONE, "", xform_usage));
+		p_list->push_back(PropertyInfo(Variant::QUATERNION, prep + "rotation", PROPERTY_HINT_NONE, "", xform_usage));
+		p_list->push_back(PropertyInfo(Variant::VECTOR3, prep + "scale", PROPERTY_HINT_NONE, "", xform_usage));
 
 		for (const KeyValue<StringName, Variant> &K : bones[i].metadata) {
 			PropertyInfo pi = PropertyInfo(bones[i].metadata[K.key].get_type(), prep + "bone_meta/" + K.key, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR);
 			p_list->push_back(pi);
 		}
 	}
-
-	for (PropertyInfo &E : *p_list) {
-		_validate_property(E);
-	}
-}
-
-void Skeleton3D::_validate_property(PropertyInfo &p_property) const {
-	PackedStringArray split = p_property.name.split("/");
-	if (split.size() == 3 && split[0] == "bones") {
-		if (split[2] == "rest") {
-			p_property.usage |= PROPERTY_USAGE_READ_ONLY;
-		}
-		if (is_show_rest_only()) {
-			if (split[2] == "enabled") {
-				p_property.usage |= PROPERTY_USAGE_READ_ONLY;
-			}
-			if (split[2] == "position") {
-				p_property.usage |= PROPERTY_USAGE_READ_ONLY;
-			}
-			if (split[2] == "rotation") {
-				p_property.usage |= PROPERTY_USAGE_READ_ONLY;
-			}
-			if (split[2] == "scale") {
-				p_property.usage |= PROPERTY_USAGE_READ_ONLY;
-			}
-		} else if (!is_bone_enabled(split[1].to_int())) {
-			if (split[2] == "position") {
-				p_property.usage |= PROPERTY_USAGE_READ_ONLY;
-			}
-			if (split[2] == "rotation") {
-				p_property.usage |= PROPERTY_USAGE_READ_ONLY;
-			}
-			if (split[2] == "scale") {
-				p_property.usage |= PROPERTY_USAGE_READ_ONLY;
-			}
-		}
-	}
 }
 
 void Skeleton3D::_update_process_order() const {

+ 0 - 1
scene/3d/skeleton_3d.h

@@ -208,7 +208,6 @@ protected:
 	bool _get(const StringName &p_path, Variant &r_ret) const;
 	bool _set(const StringName &p_path, const Variant &p_value);
 	void _get_property_list(List<PropertyInfo> *p_list) const;
-	void _validate_property(PropertyInfo &p_property) const;
 	void _notification(int p_what);
 	TypedArray<StringName> _get_bone_meta_list_bind(int p_bone) const;
 	static void _bind_methods();

+ 0 - 2
scene/3d/skeleton_ik_3d.cpp

@@ -301,8 +301,6 @@ void FabrikInverseKinematic::_update_chain(const Skeleton3D *p_sk, ChainItem *p_
 }
 
 void SkeletonIK3D::_validate_property(PropertyInfo &p_property) const {
-	SkeletonModifier3D::_validate_property(p_property);
-
 	if (p_property.name == "root_bone" || p_property.name == "tip_bone") {
 		Skeleton3D *skeleton = get_skeleton();
 		if (skeleton) {

+ 42 - 39
scene/3d/spring_bone_simulator_3d.cpp

@@ -281,61 +281,64 @@ void SpringBoneSimulator3D::_get_property_list(List<PropertyInfo> *p_list) const
 		enum_hint = skeleton->get_concatenated_bone_names();
 	}
 
+	LocalVector<PropertyInfo> props;
+
 	for (int i = 0; i < settings.size(); i++) {
 		String path = "settings/" + itos(i) + "/";
-		p_list->push_back(PropertyInfo(Variant::STRING, path + "root_bone_name", PROPERTY_HINT_ENUM_SUGGESTION, enum_hint));
-		p_list->push_back(PropertyInfo(Variant::INT, path + "root_bone", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
-		p_list->push_back(PropertyInfo(Variant::STRING, path + "end_bone_name", PROPERTY_HINT_ENUM_SUGGESTION, enum_hint));
-		p_list->push_back(PropertyInfo(Variant::INT, path + "end_bone", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
-		p_list->push_back(PropertyInfo(Variant::BOOL, path + "extend_end_bone"));
-		p_list->push_back(PropertyInfo(Variant::INT, path + "end_bone/direction", PROPERTY_HINT_ENUM, "+X,-X,+Y,-Y,+Z,-Z,FromParent"));
-		p_list->push_back(PropertyInfo(Variant::FLOAT, path + "end_bone/length", PROPERTY_HINT_RANGE, "0,1,0.001,or_greater,suffix:m"));
-		p_list->push_back(PropertyInfo(Variant::INT, path + "center_from", PROPERTY_HINT_ENUM, "WorldOrigin,Node,Bone"));
-		p_list->push_back(PropertyInfo(Variant::NODE_PATH, path + "center_node"));
-		p_list->push_back(PropertyInfo(Variant::STRING, path + "center_bone_name", PROPERTY_HINT_ENUM_SUGGESTION, enum_hint));
-		p_list->push_back(PropertyInfo(Variant::INT, path + "center_bone", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
-		p_list->push_back(PropertyInfo(Variant::BOOL, path + "individual_config"));
-		p_list->push_back(PropertyInfo(Variant::INT, path + "rotation_axis", PROPERTY_HINT_ENUM, "X,Y,Z,All"));
-		p_list->push_back(PropertyInfo(Variant::FLOAT, path + "radius/value", PROPERTY_HINT_RANGE, "0,1,0.001,or_greater,suffix:m"));
-		p_list->push_back(PropertyInfo(Variant::OBJECT, path + "radius/damping_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"));
-		p_list->push_back(PropertyInfo(Variant::FLOAT, path + "stiffness/value", PROPERTY_HINT_RANGE, "0,4,0.01,or_greater"));
-		p_list->push_back(PropertyInfo(Variant::OBJECT, path + "stiffness/damping_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"));
-		p_list->push_back(PropertyInfo(Variant::FLOAT, path + "drag/value", PROPERTY_HINT_RANGE, "0,1,0.01,or_greater"));
-		p_list->push_back(PropertyInfo(Variant::OBJECT, path + "drag/damping_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"));
-		p_list->push_back(PropertyInfo(Variant::FLOAT, path + "gravity/value", PROPERTY_HINT_RANGE, "0,1,0.01,or_greater,or_less,suffix:m/s"));
-		p_list->push_back(PropertyInfo(Variant::OBJECT, path + "gravity/damping_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"));
-		p_list->push_back(PropertyInfo(Variant::VECTOR3, path + "gravity/direction"));
-		p_list->push_back(PropertyInfo(Variant::INT, path + "joint_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_ARRAY, "Joints," + path + "joints/,static,const"));
+		props.push_back(PropertyInfo(Variant::STRING, path + "root_bone_name", PROPERTY_HINT_ENUM_SUGGESTION, enum_hint));
+		props.push_back(PropertyInfo(Variant::INT, path + "root_bone", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
+		props.push_back(PropertyInfo(Variant::STRING, path + "end_bone_name", PROPERTY_HINT_ENUM_SUGGESTION, enum_hint));
+		props.push_back(PropertyInfo(Variant::INT, path + "end_bone", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
+		props.push_back(PropertyInfo(Variant::BOOL, path + "extend_end_bone"));
+		props.push_back(PropertyInfo(Variant::INT, path + "end_bone/direction", PROPERTY_HINT_ENUM, "+X,-X,+Y,-Y,+Z,-Z,FromParent"));
+		props.push_back(PropertyInfo(Variant::FLOAT, path + "end_bone/length", PROPERTY_HINT_RANGE, "0,1,0.001,or_greater,suffix:m"));
+		props.push_back(PropertyInfo(Variant::INT, path + "center_from", PROPERTY_HINT_ENUM, "WorldOrigin,Node,Bone"));
+		props.push_back(PropertyInfo(Variant::NODE_PATH, path + "center_node"));
+		props.push_back(PropertyInfo(Variant::STRING, path + "center_bone_name", PROPERTY_HINT_ENUM_SUGGESTION, enum_hint));
+		props.push_back(PropertyInfo(Variant::INT, path + "center_bone", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
+		props.push_back(PropertyInfo(Variant::BOOL, path + "individual_config"));
+		props.push_back(PropertyInfo(Variant::INT, path + "rotation_axis", PROPERTY_HINT_ENUM, "X,Y,Z,All"));
+		props.push_back(PropertyInfo(Variant::FLOAT, path + "radius/value", PROPERTY_HINT_RANGE, "0,1,0.001,or_greater,suffix:m"));
+		props.push_back(PropertyInfo(Variant::OBJECT, path + "radius/damping_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"));
+		props.push_back(PropertyInfo(Variant::FLOAT, path + "stiffness/value", PROPERTY_HINT_RANGE, "0,4,0.01,or_greater"));
+		props.push_back(PropertyInfo(Variant::OBJECT, path + "stiffness/damping_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"));
+		props.push_back(PropertyInfo(Variant::FLOAT, path + "drag/value", PROPERTY_HINT_RANGE, "0,1,0.01,or_greater"));
+		props.push_back(PropertyInfo(Variant::OBJECT, path + "drag/damping_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"));
+		props.push_back(PropertyInfo(Variant::FLOAT, path + "gravity/value", PROPERTY_HINT_RANGE, "0,1,0.01,or_greater,or_less,suffix:m/s"));
+		props.push_back(PropertyInfo(Variant::OBJECT, path + "gravity/damping_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"));
+		props.push_back(PropertyInfo(Variant::VECTOR3, path + "gravity/direction"));
+		props.push_back(PropertyInfo(Variant::INT, path + "joint_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_ARRAY, "Joints," + path + "joints/,static,const"));
 		for (int j = 0; j < settings[i]->joints.size(); j++) {
 			String joint_path = path + "joints/" + itos(j) + "/";
-			p_list->push_back(PropertyInfo(Variant::STRING, joint_path + "bone_name", PROPERTY_HINT_ENUM_SUGGESTION, enum_hint, PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_READ_ONLY | PROPERTY_USAGE_STORAGE));
-			p_list->push_back(PropertyInfo(Variant::INT, joint_path + "bone", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_READ_ONLY));
-			p_list->push_back(PropertyInfo(Variant::INT, joint_path + "rotation_axis", PROPERTY_HINT_ENUM, "X,Y,Z,All"));
-			p_list->push_back(PropertyInfo(Variant::FLOAT, joint_path + "radius", PROPERTY_HINT_RANGE, "0,1,0.001,or_greater,suffix:m"));
-			p_list->push_back(PropertyInfo(Variant::FLOAT, joint_path + "stiffness", PROPERTY_HINT_RANGE, "0,4,0.01,or_greater"));
-			p_list->push_back(PropertyInfo(Variant::FLOAT, joint_path + "drag", PROPERTY_HINT_RANGE, "0,1,0.01,or_greater"));
-			p_list->push_back(PropertyInfo(Variant::FLOAT, joint_path + "gravity", PROPERTY_HINT_RANGE, "0,1,0.01,or_greater,or_less,suffix:m/s"));
-			p_list->push_back(PropertyInfo(Variant::VECTOR3, joint_path + "gravity_direction"));
+			props.push_back(PropertyInfo(Variant::STRING, joint_path + "bone_name", PROPERTY_HINT_ENUM_SUGGESTION, enum_hint, PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_READ_ONLY | PROPERTY_USAGE_STORAGE));
+			props.push_back(PropertyInfo(Variant::INT, joint_path + "bone", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_READ_ONLY));
+			props.push_back(PropertyInfo(Variant::INT, joint_path + "rotation_axis", PROPERTY_HINT_ENUM, "X,Y,Z,All"));
+			props.push_back(PropertyInfo(Variant::FLOAT, joint_path + "radius", PROPERTY_HINT_RANGE, "0,1,0.001,or_greater,suffix:m"));
+			props.push_back(PropertyInfo(Variant::FLOAT, joint_path + "stiffness", PROPERTY_HINT_RANGE, "0,4,0.01,or_greater"));
+			props.push_back(PropertyInfo(Variant::FLOAT, joint_path + "drag", PROPERTY_HINT_RANGE, "0,1,0.01,or_greater"));
+			props.push_back(PropertyInfo(Variant::FLOAT, joint_path + "gravity", PROPERTY_HINT_RANGE, "0,1,0.01,or_greater,or_less,suffix:m/s"));
+			props.push_back(PropertyInfo(Variant::VECTOR3, joint_path + "gravity_direction"));
 		}
-		p_list->push_back(PropertyInfo(Variant::BOOL, path + "enable_all_child_collisions"));
-		p_list->push_back(PropertyInfo(Variant::INT, path + "exclude_collision_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_ARRAY, "Exclude Collisions," + path + "exclude_collisions/"));
+		props.push_back(PropertyInfo(Variant::BOOL, path + "enable_all_child_collisions"));
+		props.push_back(PropertyInfo(Variant::INT, path + "exclude_collision_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_ARRAY, "Exclude Collisions," + path + "exclude_collisions/"));
 		for (int j = 0; j < settings[i]->exclude_collisions.size(); j++) {
 			String collision_path = path + "exclude_collisions/" + itos(j);
-			p_list->push_back(PropertyInfo(Variant::NODE_PATH, collision_path, PROPERTY_HINT_NODE_PATH_VALID_TYPES, "SpringBoneCollision3D"));
+			props.push_back(PropertyInfo(Variant::NODE_PATH, collision_path, PROPERTY_HINT_NODE_PATH_VALID_TYPES, "SpringBoneCollision3D"));
 		}
-		p_list->push_back(PropertyInfo(Variant::INT, path + "collision_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_ARRAY, "Collisions," + path + "collisions/"));
+		props.push_back(PropertyInfo(Variant::INT, path + "collision_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_ARRAY, "Collisions," + path + "collisions/"));
 		for (int j = 0; j < settings[i]->collisions.size(); j++) {
 			String collision_path = path + "collisions/" + itos(j);
-			p_list->push_back(PropertyInfo(Variant::NODE_PATH, collision_path, PROPERTY_HINT_NODE_PATH_VALID_TYPES, "SpringBoneCollision3D"));
+			props.push_back(PropertyInfo(Variant::NODE_PATH, collision_path, PROPERTY_HINT_NODE_PATH_VALID_TYPES, "SpringBoneCollision3D"));
 		}
 	}
 
-	for (PropertyInfo &E : *p_list) {
-		_validate_property(E);
+	for (PropertyInfo &p : props) {
+		_validate_dynamic_prop(p);
+		p_list->push_back(p);
 	}
 }
 
-void SpringBoneSimulator3D::_validate_property(PropertyInfo &p_property) const {
+void SpringBoneSimulator3D::_validate_dynamic_prop(PropertyInfo &p_property) const {
 	PackedStringArray split = p_property.name.split("/");
 	if (split.size() > 2 && split[0] == "settings") {
 		int which = split[1].to_int();

+ 1 - 1
scene/3d/spring_bone_simulator_3d.h

@@ -146,7 +146,7 @@ protected:
 	bool _get(const StringName &p_path, Variant &r_ret) const;
 	bool _set(const StringName &p_path, const Variant &p_value);
 	void _get_property_list(List<PropertyInfo> *p_list) const;
-	void _validate_property(PropertyInfo &p_property) const;
+	void _validate_dynamic_prop(PropertyInfo &p_property) const;
 
 	void _notification(int p_what);
 

+ 1 - 9
scene/animation/animation_mixer.cpp

@@ -107,15 +107,7 @@ bool AnimationMixer::_get(const StringName &p_name, Variant &r_ret) const {
 }
 
 void AnimationMixer::_get_property_list(List<PropertyInfo> *p_list) const {
-	List<PropertyInfo> anim_names;
-	anim_names.push_back(PropertyInfo(Variant::DICTIONARY, PNAME("libraries"), PROPERTY_HINT_DICTIONARY_TYPE, "StringName;AnimationLibrary"));
-	for (const PropertyInfo &E : anim_names) {
-		p_list->push_back(E);
-	}
-
-	for (PropertyInfo &E : *p_list) {
-		_validate_property(E);
-	}
+	p_list->push_back(PropertyInfo(Variant::DICTIONARY, PNAME("libraries"), PROPERTY_HINT_DICTIONARY_TYPE, "StringName;AnimationLibrary"));
 }
 
 void AnimationMixer::_validate_property(PropertyInfo &p_property) const {

+ 2 - 5
scene/animation/animation_node_state_machine.cpp

@@ -1704,7 +1704,8 @@ bool AnimationNodeStateMachine::_get(const StringName &p_name, Variant &r_ret) c
 }
 
 void AnimationNodeStateMachine::_get_property_list(List<PropertyInfo> *p_list) const {
-	List<StringName> names;
+	LocalVector<StringName> names;
+	names.reserve(states.size());
 	for (const KeyValue<StringName, State> &E : states) {
 		names.push_back(E.key);
 	}
@@ -1717,10 +1718,6 @@ void AnimationNodeStateMachine::_get_property_list(List<PropertyInfo> *p_list) c
 
 	p_list->push_back(PropertyInfo(Variant::ARRAY, "transitions", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
 	p_list->push_back(PropertyInfo(Variant::VECTOR2, "graph_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
-
-	for (PropertyInfo &E : *p_list) {
-		_validate_property(E);
-	}
 }
 
 void AnimationNodeStateMachine::_validate_property(PropertyInfo &p_property) const {

+ 0 - 2
scene/animation/animation_player.cpp

@@ -106,8 +106,6 @@ bool AnimationPlayer::_get(const StringName &p_name, Variant &r_ret) const {
 }
 
 void AnimationPlayer::_validate_property(PropertyInfo &p_property) const {
-	AnimationMixer::_validate_property(p_property);
-
 	if (p_property.name == "current_animation") {
 		List<String> names;
 

+ 0 - 2
scene/animation/animation_tree.cpp

@@ -893,8 +893,6 @@ void AnimationTree::_setup_animation_player() {
 }
 
 void AnimationTree::_validate_property(PropertyInfo &p_property) const {
-	AnimationMixer::_validate_property(p_property);
-
 	if (!animation_player.is_empty()) {
 		if (p_property.name == "root_node" || p_property.name.begins_with("libraries")) {
 			p_property.usage |= PROPERTY_USAGE_READ_ONLY;

+ 0 - 1
scene/gui/graph_element.cpp

@@ -88,7 +88,6 @@ void GraphElement::_notification(int p_what) {
 }
 
 void GraphElement::_validate_property(PropertyInfo &p_property) const {
-	Control::_validate_property(p_property);
 	GraphEdit *graph = Object::cast_to<GraphEdit>(get_parent());
 	if (graph) {
 		if (p_property.name == "position") {

+ 3 - 12
scene/resources/skeleton_profile.cpp

@@ -150,13 +150,6 @@ void SkeletonProfile::_validate_property(PropertyInfo &p_property) const {
 		}
 		p_property.hint_string = hint;
 	}
-
-	PackedStringArray split = p_property.name.split("/");
-	if (split.size() == 3 && split[0] == "bones") {
-		if (split[2] == "bone_tail" && get_tail_direction(split[1].to_int()) != TAIL_DIRECTION_SPECIFIC_CHILD) {
-			p_property.usage = PROPERTY_USAGE_NONE;
-		}
-	}
 }
 
 void SkeletonProfile::_get_property_list(List<PropertyInfo> *p_list) const {
@@ -175,19 +168,17 @@ void SkeletonProfile::_get_property_list(List<PropertyInfo> *p_list) const {
 	}
 	for (int i = 0; i < bones.size(); i++) {
 		String path = "bones/" + itos(i) + "/";
+		int bone_tail_usage = (get_tail_direction(i) != TAIL_DIRECTION_SPECIFIC_CHILD) ? PROPERTY_USAGE_NONE : PROPERTY_USAGE_DEFAULT;
+
 		p_list->push_back(PropertyInfo(Variant::STRING_NAME, path + "bone_name"));
 		p_list->push_back(PropertyInfo(Variant::STRING_NAME, path + "bone_parent"));
 		p_list->push_back(PropertyInfo(Variant::INT, path + "tail_direction", PROPERTY_HINT_ENUM, "AverageChildren,SpecificChild,End"));
-		p_list->push_back(PropertyInfo(Variant::STRING_NAME, path + "bone_tail"));
+		p_list->push_back(PropertyInfo(Variant::STRING_NAME, path + "bone_tail", PROPERTY_HINT_NONE, "", bone_tail_usage));
 		p_list->push_back(PropertyInfo(Variant::TRANSFORM3D, path + "reference_pose"));
 		p_list->push_back(PropertyInfo(Variant::VECTOR2, path + "handle_offset"));
 		p_list->push_back(PropertyInfo(Variant::STRING_NAME, path + "group", PROPERTY_HINT_ENUM, group_names));
 		p_list->push_back(PropertyInfo(Variant::BOOL, path + "require"));
 	}
-
-	for (PropertyInfo &E : *p_list) {
-		_validate_property(E);
-	}
 }
 
 StringName SkeletonProfile::get_root_bone() {