Refactor stickman rig and ragdoll mechanics; enhance pose restoration and stability

- Disabled constraints for the stickman rig's head bone to allow for smoother animations.
- Improved mode transitions in the sandbox stage to preserve stickman poses between EDIT and DIRECT modes.
- Added side profile stabilization for knee bends in the ragdoll component to prevent unnatural poses during physics interactions.
- Enhanced the snap-to-standing functionality to restore the stickman's original pose accurately.
- Introduced new tests for validating pose preservation during mode transitions and ragdoll behavior during walking animations.
- Created a new scene for testing stickman bending and ragdoll transitions.
This commit is contained in:
2026-09-18 22:44:48 -04:00
parent db4ff8d939
commit fbce638bc5
12 changed files with 692 additions and 39 deletions
+5 -3
View File
@@ -183,6 +183,8 @@ func _test_reactions(rig: StickmanRig) -> void:
func _test_direct_restores_animated_pose(stage: Node2D, rig: StickmanRig) -> void:
var authored: Dictionary = stage._authored[rig.get_instance_id()]
var ragdoll := rig.get_node("RigComponents/Ragdoll") as StickmanRagdoll
var authored_markers := ragdoll.get_spawn_pose()
stage.set_mode(stage.StageMode.PLAY)
rig.set_facing_profile(StickmanRig.FacingProfile.LEFT)
rig.global_position += Vector2(220.0, -90.0)
@@ -201,9 +203,9 @@ func _test_direct_restores_animated_pose(stage: Node2D, rig: StickmanRig) -> voi
_check(rig.get_facing_profile() == int(authored["facing_profile"]), "PLAY to DIRECT restores the authored facing profile")
for marker_name: String in StickmanRagdoll.STAND_POSE:
var marker := rig.get_node("IK_Targets/" + marker_name) as Node2D
var expected: Dictionary = StickmanRagdoll.STAND_POSE[marker_name]
_check(marker.position.distance_to(expected["pos"] as Vector2) < 0.01, "%s marker returns to standing after PLAY" % marker_name)
_check(absf(angle_difference(torso_marker.rotation, float(StickmanRagdoll.STAND_POSE["Torso"]["rot"]))) < 0.001, "torso marker cannot retain an upside-down PLAY frame")
var expected: Dictionary = authored_markers[marker_name]
_check(marker.position.distance_to(expected["pos"] as Vector2) < 0.01, "%s marker returns to its authored spawn pose after PLAY" % marker_name)
_check(absf(angle_difference(torso_marker.rotation, float((authored_markers["Torso"] as Dictionary)["rot"]))) < 0.001, "torso marker restores its authored rotation after PLAY")
func _test_ghost_collision(stage: Node2D) -> void: