Files
stickman/tests/test_phase8_rig_modularization.gd
T
ryan db4ff8d939 Implement Phase 8: Rig Relocation and Component Modularization
- Moved the rig scene from `res://master_rig.tscn` to `res://scenes/stickman_rig.tscn`, preserving its UID.
- Split the `StickmanRig` controller into three components: `StickmanLocomotion`, `StickmanRagdoll`, and `StickmanActionRunner`.
- Updated the architecture to ensure `StickmanRig` acts as the public facade for the new components.
- Created a new test suite `test_phase8_rig_modularization.gd` to verify the integrity of the relocated rig and its components.
- Added checks for scene loading, component resolution, action queue delegation, and state authority.
2026-09-18 14:11:53 -04:00

75 lines
2.6 KiB
GDScript

extends SceneTree
const RIG_SCENE_PATH := "res://scenes/stickman_rig.tscn"
const EXPECTED_UID := "uid://dr5ef3l2var2s"
var _checks := 0
var _failures := 0
func _initialize() -> void:
call_deferred("_run")
func _run() -> void:
var scene_source := FileAccess.get_file_as_string(RIG_SCENE_PATH)
_check(scene_source.contains('uid="%s"' % EXPECTED_UID), "relocated scene retains its UID")
var packed := load(RIG_SCENE_PATH) as PackedScene
_check(packed != null, "relocated rig scene loads")
if packed == null:
_finish()
return
var rig := packed.instantiate() as StickmanRig
_check(rig != null, "scene root remains StickmanRig")
root.add_child(rig)
await process_frame
await physics_frame
var locomotion := rig.get_node_or_null("RigComponents/Locomotion") as StickmanLocomotion
var ragdoll := rig.get_node_or_null("RigComponents/Ragdoll") as StickmanRagdoll
var runner := rig.get_node_or_null("RigComponents/ActionRunner") as StickmanActionRunner
_check(locomotion != null, "typed Locomotion component resolves")
_check(ragdoll != null, "typed Ragdoll component resolves")
_check(runner != null, "typed ActionRunner component resolves")
_check(rig.get_locomotion() == locomotion, "root locomotion facade exposes authored component")
var assigned: Array[Dictionary] = [{"type": "wait", "duration": 0.25}]
rig.action_queue = assigned
_check(runner.action_queue.size() == 1, "direct root action_queue assignment delegates")
_check(rig.get_queue() == assigned, "root queue query preserves compatibility")
rig.queue_action({"type": "speak", "text": "modular", "duration": 0.1})
_check(runner.action_queue.size() == 2, "root queue mutation delegates")
rig.set_ragdoll(true)
await physics_frame
_check(rig.state == StickmanRig.RigState.RAGDOLL, "root remains ragdoll state authority")
_check(ragdoll.get_bodies().size() == 10, "ragdoll component owns ten physics bodies")
rig.snap_to_standing()
await physics_frame
_check(rig.state == StickmanRig.RigState.ANIMATED, "snap facade returns to ANIMATED")
_check(ragdoll.get_bodies().is_empty(), "snap destroys component-owned ragdoll bodies")
rig.queue_free()
await process_frame
await process_frame
var orphan := root.find_child("RagdollBodyContainer", true, false)
_check(orphan == null, "freeing rig leaves no ragdoll container orphan")
_finish()
func _check(condition: bool, label: String) -> void:
_checks += 1
if condition:
print("PASS: %s" % label)
else:
_failures += 1
push_error("FAIL: %s" % label)
func _finish() -> void:
if _failures == 0:
print("RESULT: ALL PASSED (%d assertions)" % _checks)
quit(0)
else:
print("RESULT: %d FAILURE(S) out of %d assertions" % [_failures, _checks])
quit(1)