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:
+10
-10
@@ -479,9 +479,9 @@ func request_recovery() -> void:
|
||||
_ragdoll_component.request_recovery()
|
||||
|
||||
|
||||
## Instantly snaps the rig back to its authored standing pose — no stand-up
|
||||
## tween. Used by the sandbox stage so a stickman "reappears" at its starting
|
||||
## position/state on return to EDIT (instead of animating the recovery glide).
|
||||
## Instantly restores the rig's factory-captured spawn/ghost pose — no stand-up
|
||||
## tween. Used by the sandbox stage so a stickman reappears in its authored
|
||||
## starting pose when leaving PLAY (instead of using the generic fallback pose).
|
||||
func snap_to_standing() -> void:
|
||||
if _ragdoll_component != null:
|
||||
_ragdoll_component.snap_to_standing(int(state))
|
||||
@@ -620,7 +620,10 @@ func _apply_idle_limb_solver_mode(rotations: Dictionary = {}) -> void:
|
||||
and state == RigState.ANIMATED and not is_walking()
|
||||
var source: Dictionary = rotations.duplicate(true) if not rotations.is_empty() else _capture_limb_rotations()
|
||||
_set_limb_mods_enabled(not pin_mirrored_idle)
|
||||
if not pin_mirrored_idle:
|
||||
# Recovery supplies the exact pre-ragdoll rotations. Write them immediately
|
||||
# even for profiles that keep IK enabled so the completion frame cannot show
|
||||
# the recovery-side knee solution while the solver waits for its next tick.
|
||||
if not pin_mirrored_idle and rotations.is_empty():
|
||||
return
|
||||
for joint: String in source:
|
||||
var bones: Dictionary = _limb_bones.get(joint, {})
|
||||
@@ -658,18 +661,15 @@ func _capture_limb_rotations() -> Dictionary:
|
||||
## Fix: when facing LEFT, disable the LookAt and pin the head bone to the
|
||||
## authored canonical local rotation (0), so the head is a rigid mirror of the
|
||||
## FORWARD pose; RIGHT/FORWARD re-enable the LookAt. The pin is re-asserted
|
||||
## every physics frame while the kinematic puppet is live (ANIMATED/RECOVERING)
|
||||
## because re-enabling the IK stack during recovery would otherwise let the
|
||||
## LookAt flip the bone again.
|
||||
## every physics frame while the kinematic puppet is ANIMATED; recovery disables
|
||||
## LookAt separately while its stand-up tween drives the head bone.
|
||||
func _apply_head_lookat_mirror_mode() -> void:
|
||||
if _head_look_at == null or not is_instance_valid(_head_look_at):
|
||||
return
|
||||
var mirrored := facing_profile == FacingProfile.LEFT
|
||||
_head_look_at.enabled = false#not mirrored
|
||||
_head_look_at.enabled = not mirrored
|
||||
if mirrored and _head_bone != null and is_instance_valid(_head_bone):
|
||||
_head_bone.rotation = 0.0
|
||||
elif not mirrored:
|
||||
_head_bone.rotation = 0
|
||||
|
||||
## Per-joint setter notify: updates the resolved TwoBoneIK mod's
|
||||
## flip_bend_direction and emits bend_flag_changed. No-op before _ready (the
|
||||
|
||||
Reference in New Issue
Block a user