From 60eac65bcefb9dac34be5400de2b218cbfd292e0 Mon Sep 17 00:00:00 2001 From: Axel Meyer Date: Sat, 13 Jun 2026 23:38:03 +0200 Subject: [PATCH] feat(vagrant): Tab-Toggle inventory panel + right-click context menu - lib-core.panel and lib-core.inventory-list-display added to deps (v0.1.0 each) - backpack-widget created in M.init with label-resolver returning "Rock" - Drop action registered: removes from backpack, relocates to player position, re-registers pickup trigger - Inspect action registered: prints reg_id via engine.print - M.update: panel.update(dt) + is_pausing() early-return added after quit_to_launcher check - interaction.update wrapped in panel.is_open() guard to block world triggers while panel is visible - M.draw: panel.render() added at z-top after CI traces - Q-drop (LIFO quick-drop via Q key) unchanged and parallel to panel Drop action --- README.md | 19 +++++++++++++--- init.lua | 60 +++++++++++++++++++++++++++++++++++++++++++++---- manifest.module | 4 +++- 3 files changed, 75 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index da2289c..b63983b 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ callback, foot-body-orientation ("tactical twist"), scale-deformation walk cycle, and inheritance-decoupled foot sprites. End-to-end inventory pickup/drop demo: pick up a rock into a backpack container, drop it back into the world. -**Version:** 0.8.0 +**Version:** 0.9.0 **Module-ID:** vagrant-skeleton -**Requires:** lib-core.input >=0.4.0, lib-core.camera >=0.3.0, lib-core.render >=0.1.0, lib-core.maps >=0.1.2, lib-core.puppet >=0.4.4, lib-core.interaction >=0.1.0, lib-core.composition >=0.2.0, lib-core.inventory-list >=0.1.0, lib-asset.prototype-subterrain >=0.1.0 +**Requires:** lib-core.input >=0.4.0, lib-core.camera >=0.3.0, lib-core.render >=0.1.0, lib-core.maps >=0.1.2, lib-core.puppet >=0.4.4, lib-core.interaction >=0.1.0, lib-core.composition >=0.2.0, lib-core.actor >=0.1.0, lib-core.inventory-list >=0.1.0, lib-core.panel >=0.1.0, lib-core.inventory-list-display >=0.1.0, lib-asset.prototype-subterrain >=0.1.0 **Tags:** test-chamber, puppet, walking-sim, interaction ## Topology @@ -24,7 +24,9 @@ demo: pick up a rock into a backpack container, drop it back into the world. - **Shift + WASD** — sprint (2x player speed + 2x walk-anim cadence) - **Mouse** — body + head look-at targets (same position, different smoothing) - **E** — interact: if within range of the rock, picks it up into the backpack -- **Q** — drop: places the most-recently-added backpack item at player position (+30px right) +- **Q** — quick-drop (LIFO): places the most-recently-added backpack item at player position (+30px right) +- **Tab** — toggle inventory panel (Backpack contents) +- **Right-Click on item row** (while panel open): context menu with **Drop** / **Inspect** options - **ESC** — return to launcher ## Demo Walkthrough @@ -109,6 +111,17 @@ Only one rock is spawned per session. ## CHANGELOG +### v0.9.0 — inventory panel UI +- **Panel overlay**: `lib-core.panel` + `lib-core.inventory-list-display` wired in. + Tab key toggles a panel overlay showing backpack contents. +- **Context menu actions**: right-clicking an item row opens a context menu with + **Drop** (re-parents item to world at player position, re-registers pickup trigger) + and **Inspect** (prints `reg_id` to console). +- **Q-drop unchanged**: LIFO quick-drop via Q remains available in parallel to the + panel-based drop action. +- **Interaction guard**: `interaction.update` is suppressed while the panel is open + so world triggers don't fire during menu navigation. + ### v0.8.0 — end-to-end inventory demo functional - **Backpack container**: `composition.define_template{id="backpack"}` now includes `container={kind="list"}`. The composition v0.2 validator accepts this; the backpack diff --git a/init.lua b/init.lua index e9d1b93..fd6f9f6 100644 --- a/init.lua +++ b/init.lua @@ -1,4 +1,4 @@ --- sporel-module-vagrant-skeleton v0.8.0 +-- sporel-module-vagrant-skeleton v0.9.0 -- Sprite-mode test-chamber: 13-bone humanoid puppet + sprite-tilemap + -- hardcoded furniture. Subterrain-style puppet control model: -- multi-look-target (aim/soft), slerp body rotation, hip-static legs, @@ -22,6 +22,11 @@ -- position. engine.print shows inventory count + item-IDs after each -- add/remove. Tree-check (CI-gated) verifies child placement in -- composition tree. +-- +-- v0.9.0: Inventory panel UI wired in. Tab toggles a panel overlay +-- showing backpack contents. Right-click on an item row opens a context +-- menu with Drop and Inspect actions. Q-drop (LIFO quick-drop) remains +-- available in parallel. local input = require("lib-core.input") local camera = require("lib-core.camera") @@ -32,6 +37,8 @@ local interaction = require("lib-core.interaction") local composition = require("lib-core.composition") local actor = require("lib-core.actor") local inventory = require("lib-core.inventory-list") +local panel = require("lib-core.panel") +local inv_display = require("lib-core.inventory-list-display") local M = {} @@ -389,6 +396,43 @@ function M.init(ctx) register_pickup(state.rock) if CI_FRAME_PERF then engine.print("vagrant: rock_spawned") end + -- Inventory-UI Setup + panel.set_theme{ panel_width_frac = 0.4, font_size_title = 20 } + + local backpack_widget = inv_display.create(state.backpack, { + title = "Backpack", + widget_id = "backpack", + pause_on_open = false, + }) + + -- Module-side label-resolver (display lib's default returns "Item"). + -- Vagrant currently has one item template (rock); hardcoded for v0.9. + inv_display.set_label_resolver(backpack_widget, function(item) + return "Rock" + end) + + -- Drop action: knows world-reparenting + player position + inv_display.register_action(backpack_widget, "Drop", function(item, c) + inventory.remove(state.backpack, item) + local px = state.actor:get_property("position.x") + local py = state.actor:get_property("position.y") + item:set_property("position.x", px + 30) + item:set_property("position.y", py) + register_pickup(item) + c.close_menu() + if CI_FRAME_PERF then engine.print("vagrant: event=drop_via_menu") end + end) + + -- Inspect action: dumps reg_id to console + inv_display.register_action(backpack_widget, "Inspect", function(item, c) + engine.print(string.format("vagrant: inspect: reg_id=%s", + tostring(item:get_property("composition.reg_id")))) + c.close_menu() + end) + + panel.register("backpack", backpack_widget) + panel.bind_default_trigger("tab", "backpack") + -- Input bindings. input.bind("walk_left", { "a" }) input.bind("walk_right", { "d" }) @@ -420,6 +464,10 @@ function M.update(ctx, dt) return end + -- Inventory panel input handling + panel.update(dt) + if panel.is_pausing() then return end + -- Drop: Q pops the most-recently-added item from backpack, relocates -- it to world at player position + 30px right offset, and re-registers -- a pickup-trigger. inventory.remove restores the renderable tag. @@ -436,9 +484,9 @@ function M.update(ctx, dt) -- Inventory inspection trace (unconditional — user-facing demo output). local count = inventory.count(state.backpack) - local items = inventory.contents(state.backpack) + local remaining_items = inventory.contents(state.backpack) -- re-read post-remove local ids = {} - for _, it in ipairs(items) do + for _, it in ipairs(remaining_items) do table.insert(ids, tostring(it:get_property("composition.reg_id"))) end engine.print(string.format("vagrant: backpack count=%d items=[%s]", @@ -525,7 +573,9 @@ function M.update(ctx, dt) -- Interaction: dispatches the nearest matching proximity-trigger when -- 'interact' was pressed this frame. Uses actor.position as anchor. - interaction.update(actor.position(state.actor)) + if not panel.is_open() then + interaction.update(actor.position(state.actor)) + end -- Camera follows actor position each frame. camera.set_target(actor.position(state.actor)) @@ -572,6 +622,8 @@ function M.draw(ctx) ci_sprite_traced = true end end + -- Inventory panel overlay (z-top: drawn after all world content). + panel.render() end -- Engine lifecycle globals (engine looks up by name; module-table is bridged). diff --git a/manifest.module b/manifest.module index a1b3620..87c21a7 100644 --- a/manifest.module +++ b/manifest.module @@ -1,6 +1,6 @@ { "id": "vagrant-skeleton", - "version": "0.8.0", + "version": "0.9.0", "kind": "module", "api": "^0.1", "ci_frames": 60, @@ -17,6 +17,8 @@ {"id": "lib-core.render", "version": "0.2.0"}, {"id": "lib-core.composition", "version": "0.2.0"}, {"id": "lib-core.actor", "version": "0.1.0"}, + {"id": "lib-core.panel", "version": "0.1.0"}, + {"id": "lib-core.inventory-list-display", "version": "0.1.0"}, {"id": "lib-core.maps","version":"0.5.7"}, {"id": "lib-core.puppet", "version": "0.5.0"}, {"id": "lib-core.interaction", "version": "0.1.0"},