feat(launcher): hero carousel with auto-rotate + manual nav
panels/carousel.lua holds per-module state (index, timer, manual pause, texture cache). Auto-rotate at carousel_interval_seconds (5s default, frontmatter-overrideable). Click on overlay arrows steps and pauses auto-rotate for 30s. Max 7 indicator dots, then 'X / N' overlay (L-Q4). Single-teaser hides the arrows and dots. Zero-teaser falls through to ctx.default_teaser_texture which L.10 ships.
This commit is contained in:
20
init.lua
20
init.lua
@@ -14,6 +14,7 @@ end
|
||||
|
||||
local list_panel = require_panel("list")
|
||||
local detail_panel = require_panel("detail")
|
||||
local carousel = require_panel("carousel")
|
||||
|
||||
local STATE_LIST, STATE_QUIT, EXIT = fsm.STATE_LIST, fsm.STATE_QUIT_CONFIRM, fsm.EXIT
|
||||
local state = STATE_LIST
|
||||
@@ -255,6 +256,18 @@ function init(ctx)
|
||||
end
|
||||
end
|
||||
|
||||
-- L.5: per-module carousel state. Reads teaser_images +
|
||||
-- carousel_interval_seconds from the cached manifest.launcher.md
|
||||
-- meta. Modules without teasers still get an empty-state for the
|
||||
-- detail panel to render the fallback texture.
|
||||
ctx_panels.carousel_mod = carousel
|
||||
for _, entry in ipairs(ctx_panels.module_entries) do
|
||||
local mc = ctx_panels.manifest_cache[entry.id]
|
||||
local paths = (mc and mc.meta and mc.meta.teaser_images) or {}
|
||||
local interval = (mc and mc.meta and mc.meta.carousel_interval_seconds) or 5.0
|
||||
ctx_panels.carousel_state[entry.id] = carousel.new_state(entry.id, paths, interval)
|
||||
end
|
||||
|
||||
local wy, hy = engine.render.measure_text(YES_LABEL, FONT_BUTTON)
|
||||
local wn, hn = engine.render.measure_text(NO_LABEL, FONT_BUTTON)
|
||||
local qbtn_w = math.max(wy, wn) + 2 * PAD_X
|
||||
@@ -298,6 +311,13 @@ function update(ctx, dt)
|
||||
end
|
||||
end
|
||||
|
||||
-- L.5: pump only the selected module's carousel (perf — no point
|
||||
-- advancing offscreen rotation timers).
|
||||
if ctx_panels.selected_entry and ctx_panels.selected_entry ~= "news" then
|
||||
local s = ctx_panels.carousel_state[ctx_panels.selected_entry]
|
||||
if s then ctx_panels.carousel_mod.update(s, dt) end
|
||||
end
|
||||
|
||||
local mx, my = engine.input.get_mouse_pos()
|
||||
|
||||
if state == STATE_LIST then
|
||||
|
||||
Reference in New Issue
Block a user