feat(client): 3D locomotion sandbox — character walks the live Gauntlet (T-1088)
New SR_LIVE sandbox scene: CharacterVisual composited in a 3D greybox world derived from server snapshots. Per-leg constant-velocity interpolation keyed to the stance throttle, 'server feet / client eyes' facing (wire octant while moving, client aim octant idle), cadence-synced gait state machine on AnimationPlayer custom blends, D-148 orthographic follow camera (-30deg default, T-cycle presets), sim-space grid shader, camera-side wall cutaway, accumulating never-evict tile store with four-state visibility tint. Additive seams only: InputMapper.facing_angle_provider (2D path unchanged), CharacterVisual.play_animation blend_time param + get_animation_player(). Visual harness gains per-scenario scene field + SR_AUTOPILOT input scripting. 210 new gdUnit assertions across five suites; verified live (230/230 total, clean smoke, screenshot at .cache/screenshots/locomotion_idle_live.png). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -24,6 +24,7 @@ extends Node3D
|
||||
## get_accessory_node_count() — number of accessory BoneAttachment3D nodes
|
||||
## get_skin_tone_texture_name(index) — skin tone texture filename key for index
|
||||
## get_overhead_anchor() — Marker3D above Head bone for floating UI (#712)
|
||||
## get_animation_player() — AnimationPlayer for external anim drivers (T-1088)
|
||||
##
|
||||
## D-159 (11 body types), D-160 (18 segments), D-161 (head separate),
|
||||
## D-162 (clothing pre-fitted), D-163 (heads via BoneAttachment3D), D-164 (skeleton fork)
|
||||
@@ -771,7 +772,10 @@ func _load_animations() -> void:
|
||||
|
||||
|
||||
## Play a named animation. Searches all libraries for a matching name.
|
||||
func play_animation(anim_name: String) -> void:
|
||||
## blend_time >= 0.0 is passed to AnimationPlayer.play() as custom_blend (crossfade
|
||||
## seconds); the -1.0 default preserves the original hard-cut behavior for existing
|
||||
## callers (T-1088 design §6.3 — the locomotion gait machine is the first blend user).
|
||||
func play_animation(anim_name: String, blend_time: float = -1.0) -> void:
|
||||
if _anim_player == null:
|
||||
return
|
||||
# Search across all libraries for the animation
|
||||
@@ -779,12 +783,15 @@ func play_animation(anim_name: String) -> void:
|
||||
var lib: AnimationLibrary = _anim_player.get_animation_library(lib_name)
|
||||
if lib.has_animation(anim_name):
|
||||
var full_name: String = lib_name + "/" + anim_name if lib_name != "" else anim_name
|
||||
_anim_player.play(full_name)
|
||||
if blend_time >= 0.0:
|
||||
_anim_player.play(full_name, blend_time)
|
||||
else:
|
||||
_anim_player.play(full_name)
|
||||
return
|
||||
# Try common idle variants
|
||||
for variant in ["Idle", "idle_01", "Idle_01", "breathing_idle", "Breathing_Idle"]:
|
||||
if anim_name == "idle" and variant != anim_name:
|
||||
play_animation(variant)
|
||||
play_animation(variant, blend_time)
|
||||
return
|
||||
push_warning("CharacterVisual: animation '%s' not found in any library" % anim_name)
|
||||
|
||||
@@ -795,6 +802,14 @@ func stop_animation() -> void:
|
||||
_anim_player.stop()
|
||||
|
||||
|
||||
## Return the internal AnimationPlayer ("AnimPlayer") — speed_scale and clip-phase
|
||||
## access for external animation drivers (T-1088 gait machine; Q-063 footstep seam).
|
||||
## Null until load_descriptor() has run; every load_descriptor() destroys and
|
||||
## recreates the player, so callers must re-fetch — never cache across reloads.
|
||||
func get_animation_player() -> AnimationPlayer:
|
||||
return _anim_player
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Static helpers
|
||||
# =============================================================================
|
||||
|
||||
Reference in New Issue
Block a user