Browse Source

Merge pull request #101633 from TokageItLab/external-force-spring

Add external force property to `SpringBoneSimulator3D`
Thaddeus Crews 6 months ago
parent
commit
e4628a249f

+ 4 - 0
doc/classes/SpringBoneSimulator3D.xml

@@ -594,6 +594,10 @@
 		</method>
 		</method>
 	</methods>
 	</methods>
 	<members>
 	<members>
+		<member name="external_force" type="Vector3" setter="set_external_force" getter="get_external_force" default="Vector3(0, 0, 0)">
+			The constant force that always affected bones. It is equal to the result when the parent [Skeleton3D] moves at this speed in the opposite direction.
+			This is useful for effects such as wind and anti-gravity.
+		</member>
 		<member name="setting_count" type="int" setter="set_setting_count" getter="get_setting_count" default="0">
 		<member name="setting_count" type="int" setter="set_setting_count" getter="get_setting_count" default="0">
 			The number of settings.
 			The number of settings.
 		</member>
 		</member>

+ 13 - 1
scene/3d/spring_bone_simulator_3d.cpp

@@ -1098,6 +1098,14 @@ LocalVector<ObjectID> SpringBoneSimulator3D::get_valid_collision_instance_ids(in
 	return settings[p_index]->cached_collisions;
 	return settings[p_index]->cached_collisions;
 }
 }
 
 
+void SpringBoneSimulator3D::set_external_force(const Vector3 &p_force) {
+	external_force = p_force;
+}
+
+Vector3 SpringBoneSimulator3D::get_external_force() const {
+	return external_force;
+}
+
 void SpringBoneSimulator3D::_bind_methods() {
 void SpringBoneSimulator3D::_bind_methods() {
 	// Setting.
 	// Setting.
 	ClassDB::bind_method(D_METHOD("set_root_bone_name", "index", "bone_name"), &SpringBoneSimulator3D::set_root_bone_name);
 	ClassDB::bind_method(D_METHOD("set_root_bone_name", "index", "bone_name"), &SpringBoneSimulator3D::set_root_bone_name);
@@ -1190,9 +1198,13 @@ void SpringBoneSimulator3D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_collision_count", "index"), &SpringBoneSimulator3D::get_collision_count);
 	ClassDB::bind_method(D_METHOD("get_collision_count", "index"), &SpringBoneSimulator3D::get_collision_count);
 	ClassDB::bind_method(D_METHOD("clear_collisions", "index"), &SpringBoneSimulator3D::clear_collisions);
 	ClassDB::bind_method(D_METHOD("clear_collisions", "index"), &SpringBoneSimulator3D::clear_collisions);
 
 
+	ClassDB::bind_method(D_METHOD("set_external_force", "force"), &SpringBoneSimulator3D::set_external_force);
+	ClassDB::bind_method(D_METHOD("get_external_force"), &SpringBoneSimulator3D::get_external_force);
+
 	// To process manually.
 	// To process manually.
 	ClassDB::bind_method(D_METHOD("reset"), &SpringBoneSimulator3D::reset);
 	ClassDB::bind_method(D_METHOD("reset"), &SpringBoneSimulator3D::reset);
 
 
+	ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "external_force", PROPERTY_HINT_RANGE, "-99999,99999,or_greater,or_less,hide_slider,suffix:m/s"), "set_external_force", "get_external_force");
 	ADD_ARRAY_COUNT("Settings", "setting_count", "set_setting_count", "get_setting_count", "settings/");
 	ADD_ARRAY_COUNT("Settings", "setting_count", "set_setting_count", "get_setting_count", "settings/");
 
 
 	BIND_ENUM_CONSTANT(BONE_DIRECTION_PLUS_X);
 	BIND_ENUM_CONSTANT(BONE_DIRECTION_PLUS_X);
@@ -1580,7 +1592,7 @@ void SpringBoneSimulator3D::_process_joints(double p_delta, Skeleton3D *p_skelet
 		Transform3D current_world_pose = p_center_transform * current_global_pose;
 		Transform3D current_world_pose = p_center_transform * current_global_pose;
 		Quaternion current_rot = current_global_pose.basis.get_rotation_quaternion();
 		Quaternion current_rot = current_global_pose.basis.get_rotation_quaternion();
 		Vector3 current_origin = p_center_transform.xform(current_global_pose.origin);
 		Vector3 current_origin = p_center_transform.xform(current_global_pose.origin);
-		Vector3 external = p_inverted_center_rotation.xform(p_joints[i]->gravity_direction * p_joints[i]->gravity * p_delta);
+		Vector3 external = p_inverted_center_rotation.xform((external_force + p_joints[i]->gravity_direction * p_joints[i]->gravity) * p_delta);
 
 
 		// Integration of velocity by verlet.
 		// Integration of velocity by verlet.
 		Vector3 next_tail = verlet->current_tail +
 		Vector3 next_tail = verlet->current_tail +

+ 4 - 0
scene/3d/spring_bone_simulator_3d.h

@@ -141,6 +141,7 @@ public:
 
 
 protected:
 protected:
 	Vector<SpringBone3DSetting *> settings;
 	Vector<SpringBone3DSetting *> settings;
+	Vector3 external_force;
 
 
 	bool _get(const StringName &p_path, Variant &r_ret) const;
 	bool _get(const StringName &p_path, Variant &r_ret) const;
 	bool _set(const StringName &p_path, const Variant &p_value);
 	bool _set(const StringName &p_path, const Variant &p_value);
@@ -268,6 +269,9 @@ public:
 
 
 	LocalVector<ObjectID> get_valid_collision_instance_ids(int p_index);
 	LocalVector<ObjectID> get_valid_collision_instance_ids(int p_index);
 
 
+	void set_external_force(const Vector3 &p_force);
+	Vector3 get_external_force() const;
+
 	// Helper.
 	// Helper.
 	static Quaternion get_local_pose_rotation(Skeleton3D *p_skeleton, int p_bone, const Quaternion &p_global_pose_rotation);
 	static Quaternion get_local_pose_rotation(Skeleton3D *p_skeleton, int p_bone, const Quaternion &p_global_pose_rotation);
 	static Quaternion get_from_to_rotation(const Vector3 &p_from, const Vector3 &p_to, const Quaternion &p_prev_rot);
 	static Quaternion get_from_to_rotation(const Vector3 &p_from, const Vector3 &p_to, const Quaternion &p_prev_rot);