# Landing Page — Testing-Channel Feature Plan Target: develop and validate on the FoundryMods **testing channel** (`0.34.51-beta.N`), then promote the accumulated work to stable in one release. Each stage below is a self-contained beta that can be installed and tested independently. Owner: Jerrod Bailey · Platform: Foundry VTT v13–v14 · Status: proposed --- ## Research answers (inform Stages 2 and 6) **TMFX filters on sprites.** A "sprite" in Token Magic FX is a *filter* (`filterType:"sprite"`), not a separate object — it lives in an ordinary tile's filter stack (that is how the backdrop works today). Every TMFX filter attaches to the same placeable and composites together, so an **Adjust** filter can be stacked on the same tile as the sprite filter and will affect the sprite's rendered output. No image redraws or masks required. Only caveat: stacking order (Adjust must process after the sprite). ACTION: 15-minute in-world spike to confirm compositing order before Stage 6 builds on it. **Sound library.** Seed from **Kenney.nl** (CC0 — no attribution, redistributable inside the module): Interface Sounds / UI Audio (hover, click), RPG Audio (fantasy), Sci-Fi Sounds. Backup CC0 sources: OpenGameArt (CC0 filter), Freesound (CC0 filter). Convert to OGG, bundle under `assets/sounds/{ui,fantasy,scifi}/`, expose via a small registry. --- ## Existing infrastructure we reuse - **Per-client hover** (`effects.mjs`): effect persisted ONCE as a *disabled* TMFX filter; each client toggles `.enabled` locally. Inverted hover (Stage 6) is the same mechanism with the default flipped (persist ENABLED, toggle OFF on hover). - **Audio playback** (`scene-sound.mjs`): already wraps `AudioHelper.play` on the environment channel. Stages 2 reuse this for one-shot hover/click sounds (interface channel, no loop). - **Interaction layer** (`interaction.mjs`): pointer hit-test → hover reconcile + click. Stage 2 hooks sound into the existing hover-enter and click paths; Stage 4 extends the hit-test to drawings. - **Runtime click resolution** (`resolve-click.mjs`) and **category system** (`content.mjs`, `category-config.mjs`) — Stage 5 (lock category) plugs into the rebuild path. --- ## Stage 1 — Lock Screen (pan / zoom lock + fit-to-width) **Goal:** make a landing page feel like a fixed intro page for players. - Per-scene flags: `lockPan`, `lockZoom`, plus a view mode: `fitWidth` (fit scene to the background's horizontal extent) or `lockView` (pin an exact position+scale). - Enforced for **players only** (GM stays free to author). Hook `canvasPan` / `canvasReady`: on a flagged scene, re-assert the target view when a non-GM tries to pan/zoom. - Designer UI: a "Lock screen" block in the Scene-base or a new section (lockPan, lockZoom, view-mode radio, "capture current view" for lockView). - Touches: `main.js` (hooks), a new `scripts/lock-view.mjs`, `builder.hbs` + `builder.mjs`, `lang/en.json`. - Risks: v13/v14 differences in `canvasPan` signature and `canvas.animatePan`; fighting other modules that also pan. Mitigation: gentle re-assert (not a hard lock loop), GM-exempt. ## Stage 2 — Sound foundation + hover & click sounds **Goal:** a hover sound and a click sound per button/tile, built-in presets + custom path. - **2a. Sound library + registry.** Bundle CC0 clips under `assets/sounds/{ui,fantasy,scifi}/`; `scripts/sounds.mjs` exports a preset list ({key,label,path,category}) + a `playOneShot(src)` helper (interface channel, volume from settings, no loop, per-client). - **2b. Hover sound.** New field in BOTH hover surfaces: the per-tile **Hover** modal (`config-apps.mjs`) and the Builder/Scene-Design hover panel. A file-path picker (audio) + a preset dropdown. Stored on the hover flag (or a sibling `hoverSound` flag). Played on hover-enter in `interaction.mjs` (debounced so a fast sweep doesn't machine-gun). - **2c. Click sound.** New field in the per-tile **Click** modal and the Builder. Played in `actions.mjs`/`resolve-click` on click, before/at action dispatch. - Model decision (confirm): scene-wide default in Builder/Scene-Design + per-button override in the HUD modals, mirroring how hover/click already work. - Touches: new `assets/sounds/*`, `scripts/sounds.mjs`, `config-apps.mjs`, `builder.hbs`/`.mjs`, `scene-design.hbs`/`.mjs`, `interaction.mjs`, `actions.mjs`, `lang/en.json`. - Risks: browser autoplay policy (sound needs a prior user gesture — clicks are fine; first hover before any gesture may be silent). Keep volume tied to the interface-volume slider. ## Stage 3 — Invisible buttons + Design-Mode outlines **Goal:** label-only buttons (transparent tile) for a clean UI, still fully functional. - New "Invisible" style: transparent tile texture, label visible, all click/hover machinery intact. (There is already an `assets/backdrops/invisible.png` precedent.) - **Design-Mode outline overlay:** when Design Mode is on, draw a dashed rectangle over each button tile (PIXI graphics on the interaction/controls layer) so invisible buttons are visible and selectable; hidden for players and when Design Mode is off. - Touches: `content.mjs` (STYLES), `builder.mjs` (build path handles no-art), a new `scripts/design-outline.mjs`, `interaction.mjs`/`main.js` (design-mode hook), `styles`. - Risks: hit-testing on a fully transparent tile (pixel-perfect must be bypassed for invisible buttons — they should use whole-rect hit like generated buttons already do). ## Stage 4 — Hover effects on text Drawings **Goal:** the exact tile hover system, but for Foundry text Drawings (pairs with Stage 3 — a transparent button whose label lights up on hover). - Extend `effects.mjs` persist/toggle to Drawing documents (TMFX supports Drawings). - **Drawing HUD button** ("Hover Effect") via `renderDrawingHUD`, mirroring the Tile HUD. - **Builder hover panel: a Drawings sub-section** to pick a hover effect for generated labels. - Extend `interaction.mjs` hit-test to consider flagged drawings (or drive label hover from the linked tile's hover, since labels are already Mass-Edit-linked to their button). - Touches: `effects.mjs`, `hud.mjs`, `interaction.mjs`, `hover-labels.mjs`, `builder.*`, `scene-design.*`, `lang/en.json`. - Risks: per-client toggle on drawings needs the same `flags.tokenmagic` persistence path; confirm TMFX drawing support on v13 AND v14. ## Stage 5 — Lock Category (protect on Rebuild) **Goal:** a per-category checkbox that stops the Designer from changing that button's click, hover, or placement when Rebuilding — protects hand-tuned buttons. - Per-category `locked` flag (in the Builder's category list and/or Category Defaults). - `buildLandingPage`: for a locked category, do NOT delete/regenerate its tile — preserve position, size, click, hover, style, label. Only unlocked categories are rebuilt. - Touches: `builder.mjs` (rebuild preservation — extends the existing menu-ownership logic), `builder.hbs`, `category-config.*`, `lang/en.json`. - Risks: interaction with the runtime click resolution (Stage-0 work) and menu-ownership flags; needs a clear rule for "locked but user changed the layout." ## Stage 6 — Inverted hover + Adjust control **Goal:** effect ON by default, OFF on hover (e.g. everything greyscale until hovered → colour). - Add an **invert** toggle to the hover picker: reuse the persist/toggle mechanism with the default flipped (persist ENABLED; hover sets `.enabled=false`). A tile/drawing can carry a normal OR an inverted hover. - **Adjust filter control:** a small tunable UI (saturation, brightness, contrast, gamma) for the TMFX Adjust filter, so "black-and-white until hover" is a one-click preset. Depends on the Research-Q1 spike. - Touches: `effects.mjs` (invert path), `config-apps.mjs` + Builder/Scene-Design hover UI, `lang/en.json`. - Risks: the compositing-order question for Adjust-over-sprite (spike first); making sure inverted and normal hovers don't collide on the same placeable. --- ## Sequencing rationale 1. **Stage 1** is standalone and high-value → good first beta. 2. **Stage 2** is foundational content (sounds) many users will want; reuses audio infra. 3. **Stages 3 + 4** are a natural pair (invisible button + text hover) — ship close together. 4. **Stage 5** is builder-rebuild protection, independent, medium risk. 5. **Stage 6** is the most research-dependent (Adjust spike) → last, after the hover system is otherwise stable. Each stage: build → preflight → publish `beta.N` to testing → you install & test → iterate. Accumulate user-facing notes under `## Unreleased`; promote to a single stable release at the end. ## Open decisions to confirm before building - Hover/click **sound model**: scene-wide default + per-button override (recommended), or per-button only? - **Sounds**: do you want me to fetch the Kenney CC0 packs into the sandbox (if network allows) and curate, or will you drop the packs in and I build the registry + OGG conversion? - **Fit-to-width** default: fit on load every time, or only set the initial view and then lock? - Stage order: is 1 → 2 → 3+4 → 5 → 6 right, or do you want sounds (2) or invisible/text (3+4) first?