diff --git a/MODULES.md b/MODULES.md index 3c527c4d..ce956897 100644 --- a/MODULES.md +++ b/MODULES.md @@ -430,8 +430,11 @@ api.onInput((kind, code) => {}); // 'down'/'up' events; returns unsubscri // pause the HOST's use of an input scope while your module drives: // 'keys' — WASD camera fly + play-mode movement // 'locomotion' — VR left-stick locomotion +// 'sticks' — (1.19) BOTH VR sticks: left-stick move, right-stick snap/smooth turn + teleport +// (a held thing reeled on Y and scaled on X, the way an Edit grab does) api.claimInput('keys'); // ALWAYS release when your mode ends api.releaseInput('keys'); +const sticksOk = api.claimInput('sticks') === true; // true = this core knows the scope (older: undefined) // reading a keydown YOURSELF (a toolbox's own handler)? resolve the key the way the // editor does — `event.key` when it is an ASCII letter/digit, the physical @@ -693,6 +696,8 @@ api.game.addSetting?.({ onChange: (v) => setBoard(v) }); setBoard(api.game.setting?.('board') ?? 'globe'); // the stored choice at load +// (1.19) a CHOICE that decides which levels you see: `onLevels: true` also draws it as tabs +// above the Levels page's grid (desktop + headset) — Untangle's Board [Globe] [2D board] api.game.setSetting?.('board', '2d'); // your in-game button writes the same row api.game.onSettingsChange?.((values) => console.log(values.board, values.sfx)); ``` diff --git a/src/components/hud/GameShellMenu.svelte b/src/components/hud/GameShellMenu.svelte index b4614ca5..609c53ac 100644 --- a/src/components/hud/GameShellMenu.svelte +++ b/src/components/hud/GameShellMenu.svelte @@ -21,6 +21,7 @@ shellMenuAvailable, shellMenuItems, shellSettingViews, + shellLevelTabs, shellPageTitle, shellGameName, shellHelpLines, @@ -43,6 +44,9 @@ const items = $derived(itemsFor($gameLevels)); const viewsFor = (/** @type {any[]} */ ..._deps) => shellSettingViews({ vr: false }); const settings = $derived(viewsFor($gameSettingValues, $gameSettingRows)); + // 33 (G3): a game's level-picking choice (Untangle's Board) as tabs above the grid + const tabsFor = (/** @type {any[]} */ ..._deps) => shellLevelTabs(); + const levelTabs = $derived(tabsFor($gameSettingValues, $gameSettingRows)); const vrViewsFor = (/** @type {any[]} */ ..._deps) => shellSettingViews({ vr: true }).filter((/** @type {any} */ r) => r.vrOnly); const vrSettings = $derived(vrViewsFor($gameSettingValues)); const helpFor = (/** @type {any[]} */ ..._deps) => shellHelpLines({ vr: false }); @@ -150,6 +154,22 @@ {/each} {:else if page === 'levels'} + {#each levelTabs as tab (tab.id)} +
+ {tab.label} + {#each tab.options as option (option.value)} + + {/each} +
+ {/each}
{#each $gameLevels?.list ?? [] as level (level.id)}