From 7061ea079ee0bf71212fdfa15e73d7275fdc6c5a Mon Sep 17 00:00:00 2001 From: Axel Meyer Date: Mon, 18 May 2026 03:07:00 +0200 Subject: [PATCH] feat: sprite-mode render with z_order sort and color-rect fallback Walks bones in z-sorted order (rig.bones_z_sorted, lowest first = back). For each bone: - If texture_handle present: draw via engine.render.draw_sprite_transform using bone.scale and bone.anchor (negative scale mirrors the sprite, anchor is the in-texture pivot). - Else: fall back to colored rotated 16x4 rect via draw_rect_rotated (Phase 1 behavior preserved). bone_state[bid].world (cached by M.update's depth-first pipeline) is the source of (x, y, angle). --- init.lua | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/init.lua b/init.lua index 5707329..697d7be 100644 --- a/init.lua +++ b/init.lua @@ -542,27 +542,32 @@ update_bone_recursive = function(p, b, dt) end -- ==================================================================== --- Rendering (engine.render.* -- only callable in render-phase) +-- Rendering (engine.render.*; only callable in render-phase). +-- Walks bones in z-sorted order (back-to-front). For each bone: +-- - If bone has texture_handle: draw via engine.render.draw_sprite_transform +-- - Else: fall back to engine.render.draw_rect_rotated with bone.color -- ==================================================================== function M.render(handle) local p = all_puppets[handle] if p == nil then return end - -- Draw each bone as a rotated rect centered at the bone's world-pos. - -- v0.1 simplification: bone's world-pos = puppet origin + bone.rest offset. - -- Bone "length" is approximated by a small constant; later versions will - -- derive from rig data. - local BONE_LENGTH = 16 - local BONE_THICKNESS = 4 - - for _, b_src in ipairs(p.rig.bones) do - local b = p.rig.bones_by_id[b_src.id] - local x = p.x + b.rest.x - local y = p.y + b.rest.y - local angle = p.bone_state[b.id].angle - local c = b.color - local color = engine.render.rgb(c[1], c[2], c[3]) - engine.render.draw_rect_rotated(x, y, BONE_LENGTH, BONE_THICKNESS, angle, color) + for _, b in ipairs(p.rig.bones_z_sorted) do + local ws = p.bone_state[b.id].world + if b.texture_handle then + local sx, sy = b.scale[1], b.scale[2] + local ax, ay = b.anchor and b.anchor[1] or 0, + b.anchor and b.anchor[2] or 0 + engine.render.draw_sprite_transform( + b.texture_handle, + ws.x, ws.y, ws.angle, + sx, sy, ax, ay, + 0xFFFFFFFF + ) + else + -- Phase-1 fallback: colored rotated rect (16x4 px). + local color = engine.render.rgb(b.color[1], b.color[2], b.color[3]) + engine.render.draw_rect_rotated(ws.x, ws.y, 16, 4, ws.angle, color) + end end end