puppet.load_textures(rig, asset_aliases): - Resolves bone.texture atlas-ids to texture-handles via the asset- lib indirection. Reads asset_aliases[rig.asset_pack] to get the asset-lib id, loads the lib's atlas.json, looks up the atlas-entry by id, then calls engine.asset.load_texture on the resolved file path. - Resolves bone.anchor from the atlas entry unless the bone has an explicit anchor override. - Raises clear errors when alias/atlas-pack/atlas-id is missing. puppet.load_rig(path, asset_aliases?) now optionally calls load_textures after build_rig if asset_aliases is supplied. README updated with new API entries (load_rig signature, load_textures, bone_world_transform, write_bone_test_only) and CHANGELOG v0.2.0 entry.
146 lines
5.2 KiB
Markdown
146 lines
5.2 KiB
Markdown
# lib-core.puppet
|
|
|
|
Skeletal animation primitive for top-down 2D characters: bones,
|
|
tracks, rest pose, keyframe animations, procedural animations
|
|
(Lua-side), and look-at constraint. No footplant IK in v0.1
|
|
(deferred).
|
|
|
|
**Version:** 0.2.0
|
|
**Lib-ID:** lib-core.puppet
|
|
**Requires:** (none — pure Lua + engine.render.*)
|
|
**Tags:** animation, skeleton, puppet, character
|
|
|
|
## Topology
|
|
|
|
<!-- topology:start (auto-generated; do not edit) -->
|
|
<!-- topology:end -->
|
|
|
|
## API
|
|
|
|
### `puppet.build_rig(rig_table)`
|
|
|
|
Validates a rig table (parsed from `*.rig.json`) and returns an
|
|
internal representation with `bones_by_id`, parent-resolved object
|
|
references, and track-membership maps. Raises on invalid data
|
|
(missing parents, bones in 2 tracks, etc.).
|
|
|
|
### `puppet.build_animation(anim_table, rig)`
|
|
|
|
Validates an animation table against a built rig (bones referenced
|
|
in keyframes must exist and be in the animation's declared track).
|
|
|
|
### `puppet.sample_animation(animation, t)`
|
|
|
|
Returns a frame `{ <bone_id> = { angle = <number>, ... }, ... }`
|
|
sampling the animation at time `t` with linear interpolation. Wraps
|
|
on `t > duration` if `animation.loop` is true.
|
|
|
|
### `puppet.spawn(rig, { x, y })`, `puppet.despawn(handle)`
|
|
|
|
Spawn a new puppet instance at world position (x, y). Returns an
|
|
opaque handle. `despawn` removes the instance.
|
|
|
|
### `puppet.update(dt)`, `puppet.render(handle)`
|
|
|
|
`update(dt)` runs the pipeline for ALL spawned puppets (rest →
|
|
look-at → keyframes → procedural). `render(handle)` draws ONE
|
|
puppet via `engine.render.draw_rect_rotated` per bone.
|
|
|
|
### `puppet.set_look_target(p, world_x, world_y)`, `puppet.clear_look_target(p)`
|
|
|
|
Set or clear the look-at target. Bones marked `look_at: true` in the
|
|
rig rotate to face the target.
|
|
|
|
### `puppet.bone_angle(p, bone_id)`
|
|
|
|
Returns the current world-space angle of `bone_id` (after the
|
|
full pipeline tick). Used by tests + by callers needing bone-state.
|
|
|
|
### `puppet.set_procedural(p, name, callback)`, `puppet.clear_procedural(p, name)`
|
|
|
|
Register or unregister a per-frame procedural callback. Callback
|
|
signature: `function(handle, dt)`. Inside the callback, mutate
|
|
bones via `puppet.write_bone(handle, bone_id, { angle = <number> })`.
|
|
|
|
### `puppet.play(p, animation_name, { loop, speed })`, `puppet.stop(p, animation_name)`, `puppet.stop_all(p)`, `puppet.is_playing(p, animation_name)`
|
|
|
|
Keyframe-layer controls. Animation must be registered via
|
|
`puppet.register_animation(p, anim)` first.
|
|
|
|
### `puppet.register_animation(p, animation)`
|
|
|
|
Binds a built animation (from `build_animation`) to a puppet
|
|
instance, making it available to `play`.
|
|
|
|
### `puppet.load_rig(path, asset_aliases?)`
|
|
|
|
Loads a rig from a JSON file and optionally resolves its bone textures
|
|
via `puppet.load_textures`. Pass the module's `asset_aliases` table
|
|
(from `engine.module.asset_aliases()`) to enable sprite-mode rendering;
|
|
omit for colored-rect-only rigs.
|
|
|
|
### `puppet.load_textures(rig, asset_aliases)`
|
|
|
|
For each bone with a `texture` field, resolves the atlas-id to a
|
|
texture-handle via the asset-lib indirection: read `asset_aliases[rig.asset_pack]`
|
|
to get the lib-id, load `<lib-id>/assets/atlas.json`, look up the
|
|
atlas-entry by id, and call `engine.asset.load_texture` on the file
|
|
path. Also resolves bone anchors from the atlas (unless bone has an
|
|
explicit `anchor` field).
|
|
|
|
### `puppet.bone_world_transform(handle, bone_id)`
|
|
|
|
Returns the bone's cached world-transform `(x, y, angle)` from the
|
|
last `puppet.update` tick. Used by tests and by modules needing world-
|
|
space queries (e.g., for spawning effects at a bone position).
|
|
|
|
### `puppet.write_bone_test_only(handle, bone_id, angle_rad)`
|
|
|
|
Test-setup helper: directly write a bone angle bypassing the track-
|
|
conflict-guard. Not for production use; modules should write via
|
|
procedural callbacks.
|
|
|
|
### `puppet.load_animation(path, rig)`
|
|
|
|
Convenience wrapper: reads a JSON file and calls `build_animation`.
|
|
|
|
### `puppet.position(p)`, `puppet.facing(p)`, `puppet.move_to(p, x, y)`
|
|
|
|
Puppet owns its world position. `move_to` sets it instantly (caller
|
|
applies speed). `facing` returns the last-movement-direction angle.
|
|
|
|
### `puppet.write_bone(handle, bone_id, { angle })`
|
|
|
|
Procedural-callback-only API to mutate a bone. Validates track
|
|
ownership at write time.
|
|
|
|
## Conventions
|
|
|
|
- World-coords + pixel-units throughout (per ADR-0031).
|
|
- Bone angles in radians (internal). JSON rest-angles and animation
|
|
keyframe angles are in degrees, converted on load.
|
|
- Update pipeline runs once per frame (`puppet.update(dt)`) for ALL
|
|
spawned puppets. `render` is per-puppet so callers can interleave
|
|
with other rendering.
|
|
|
|
## CHANGELOG
|
|
|
|
### v0.2.0
|
|
- Rig-format extension (texture, z_order, scale, anchor, asset_pack
|
|
fields on bones; rig.bones_z_sorted for render-order)
|
|
- Multi-level parent-chain transform with depth-first update pipeline
|
|
- Sprite-mode render via engine.render.draw_sprite_transform
|
|
- New API: load_textures, bone_world_transform, write_bone_test_only
|
|
- All v0.1.0 rigs continue to work (texture-less bones fall back to
|
|
colored-rect render)
|
|
|
|
### v0.1.0
|
|
- Initial release: skeleton + bones + tracks + rest + keyframe +
|
|
procedural + look-at constraint. Footplant IK deferred.
|
|
|
|
## References
|
|
|
|
- `architecture/puppet.md` (Reference)
|
|
- ADR-0037 (Tests-as-Libs)
|
|
- ADR-0038 (API-Doc-Convention)
|