feat(puppet): v0.4.3 — inherit_scale=false flag (decouple world.scl)

New optional bone field 'inherit_scale' (default true). When set false,
world.scl = local.scl (no parent.scl multiplier). Position cascade still
uses parent.scl (so child follows parent's stretch positionally).

Use case: feet that move with leg-end as leg.scl_y cycles +1/0/-1, but
foot sprite stays at constant scale (no Y-flip when leg flips, no
collapse when leg collapses).
This commit is contained in:
Axel Meyer
2026-05-18 22:31:39 +02:00
parent 0b41e8efb7
commit 4448fc7a29
2 changed files with 19 additions and 3 deletions

View File

@@ -112,6 +112,11 @@ function M.build_rig(rig_table)
-- v0.4.0: Parse virtual flag (virtual=true skips render; bone still participates in compute_world)
local virtual = (b.virtual == true)
-- v0.4.3: Parse inherit_scale flag (default true; false → world.scl = local.scl,
-- ignoring parent.world.scl. Position cascade still uses parent.scl).
local inherit_scale = true
if b.inherit_scale == false then inherit_scale = false end
bones_by_id[b.id] = {
id = b.id,
parent = nil, -- resolved below
@@ -128,6 +133,7 @@ function M.build_rig(rig_table)
look_at_slerp = look_at_slerp, -- v0.4.0: slerp-rate (unitless float)
sprite_rot = sprite_rot,
virtual = virtual, -- v0.4.0: skip render if true
inherit_scale = inherit_scale, -- v0.4.3: false → world.scl decoupled from parent.scl
color = b.color or { 200, 200, 200 },
texture = b.texture, -- optional atlas-id (string) or nil
z_order = b.z_order or 0, -- render-sort key; default 0
@@ -728,8 +734,18 @@ local function compute_world(p, b)
bs.world.x = pw.x + (cos_r * bs.pos.x * sx - sin_r * bs.pos.y * sy)
bs.world.y = pw.y + (sin_r * bs.pos.x * sx + cos_r * bs.pos.y * sy)
bs.world.rot = pw.rot + bs.rot
bs.world.scl_x = pw.scl_x * bs.scl.x
bs.world.scl_y = pw.scl_y * bs.scl.y
if b.inherit_scale == false then
-- v0.4.3: inherit_scale=false → world.scl from local only,
-- ignoring parent.world.scl. POSITION cascade above still
-- uses parent.scl (so child follows parent's stretch
-- positionally without scaling its own sprite). Use case:
-- feet that track leg-end but don't Y-flip when leg flips.
bs.world.scl_x = bs.scl.x
bs.world.scl_y = bs.scl.y
else
bs.world.scl_x = pw.scl_x * bs.scl.x
bs.world.scl_y = pw.scl_y * bs.scl.y
end
end
end