Story 3.3 done
This commit is contained in:
+130
-25
@@ -3,6 +3,7 @@
|
||||
**Workspace:** `_bmad-output/planning-artifacts/prds/prd-video-view-manager-2026-05-19/`
|
||||
**Created:** 2026-05-19
|
||||
**Author:** Morr
|
||||
**Last Updated:** 2026-05-25
|
||||
|
||||
---
|
||||
|
||||
@@ -12,7 +13,7 @@
|
||||
**Date:** 2026-05-19
|
||||
**Decision:** PRD covers full product vision across all 3 priority tiers. v1.0 = Day 1 + Week 1–2 features (FR-1 through FR-26). Later-tier features are documented in §10 as a roadmap, not as FRs.
|
||||
**Rationale:** User selected "Full vision PRD" during working mode selection.
|
||||
**Status:** Captured in §10 Product Roadmap.
|
||||
**Status:** Captured in §10 Product Roadmap. **UPDATED:** Expanded to include FR-27 through FR-32 from live testing.
|
||||
|
||||
### D-2 — WebRTC track disabling preferred
|
||||
**Date:** 2026-05-19
|
||||
@@ -56,18 +57,6 @@
|
||||
**Rationale:** Standard FoundryVTT module convention. Community translation is a common contribution pattern in the ecosystem.
|
||||
**Status:** Captured in §6.1 MVP Scope.
|
||||
|
||||
### D-11 — GM sees all activated feeds; own self-view is configurable
|
||||
**Date:** 2026-05-19
|
||||
**Decision:** The GM always sees all activated player webcams. The GM's own feed visibility in their own view is a configurable module setting ("Show my own feed to myself", default ON).
|
||||
**Rationale:** User answer to OQ-3: "All activated webcam of players + himself as an option."
|
||||
**Status:** Captured in FR-6. OQ-3 closed.
|
||||
|
||||
### D-12 — Native WebRTC only for v1.0; non-native AV backends deferred
|
||||
**Date:** 2026-05-19
|
||||
**Decision:** Only FoundryVTT's native WebRTC AV backend is supported in v1.0. Jitsi Meeting Server and other backends are not in scope.
|
||||
**Rationale:** User answer to OQ-4: "Not planned in first steps, maybe later."
|
||||
**Status:** Captured in §5 Non-Goals. OQ-4 closed; deferred to Later roadmap.
|
||||
|
||||
### D-9 — Native FoundryVTT socket API for state broadcast
|
||||
**Date:** 2026-05-19
|
||||
**Decision:** Visibility Matrix changes are broadcast via the native FoundryVTT socket API using a registered module event name. `socketlib` will not be added as a dependency.
|
||||
@@ -80,14 +69,17 @@
|
||||
**Rationale:** User confirmed: "Not sure, to be checked with the API itself." OQ-1 remains open but is unblocking — CSS fallback ships regardless.
|
||||
**Status:** OQ-1 downgraded from hard phase blocker to development-time research item. FR-7 unchanged.
|
||||
|
||||
| OQ | Phase Blocker? | Status |
|
||||
|---|---|---|
|
||||
| OQ-1: WebRTC track disable API access | Yes | Open — to be checked against v14 API during development; CSS fallback is safe default |
|
||||
| OQ-2: socketlib vs native socket API | Yes | **RESOLVED** — native FoundryVTT socket API |
|
||||
| OQ-3: GM own-feed hidden behavior | No | **RESOLVED** — GM always sees all activated feeds; own self-view is a configurable option |
|
||||
| OQ-4: Non-native AV backend support | No | **RESOLVED** — native WebRTC only for v1.0; others deferred to Later roadmap |
|
||||
| OQ-5: Scene hook timing | No | Deferred — not a concern for first implementation stage |
|
||||
| OQ-6: Partial vs full preset application | No | Open — to be resolved during FR-15/FR-16 implementation |
|
||||
### D-11 — GM sees all activated feeds; own self-view is configurable
|
||||
**Date:** 2026-05-19
|
||||
**Decision:** The GM always sees all activated player webcams. The GM's own feed visibility in their own view is a configurable module setting ("Show my own feed to myself", default ON).
|
||||
**Rationale:** User answer to OQ-3: "All activated webcam of players + himself as an option."
|
||||
**Status:** Captured in FR-6. OQ-3 closed.
|
||||
|
||||
### D-12 — Native WebRTC only for v1.0; non-native AV backends deferred
|
||||
**Date:** 2026-05-19
|
||||
**Decision:** Only FoundryVTT's native WebRTC AV backend is supported in v1.0. Jitsi Meeting Server and other backends are not in scope.
|
||||
**Rationale:** User answer to OQ-4: "Not planned in first steps, maybe later."
|
||||
**Status:** Captured in §5 Non-Goals. OQ-4 closed; deferred to Later roadmap.
|
||||
|
||||
### D-13 — Reaction Cam / automation effects are opt-in (not opt-out)
|
||||
**Date:** 2026-05-19
|
||||
@@ -107,7 +99,120 @@
|
||||
**Rationale:** From brainstorming "panic button" + Marcus persona. Elevated to cross-cutting design rule.
|
||||
**Status:** Added to Cross-Cutting NFRs.
|
||||
|
||||
### D-16 — PRD finalized
|
||||
**Date:** 2026-05-19
|
||||
**Decision:** PRD marked `status: final`. All decisions captured, all reconciliation gaps resolved, all [ASSUMPTION] tags indexed, polish complete.
|
||||
**Status:** Closed.
|
||||
---
|
||||
|
||||
## Live Testing Decisions (May 20-25, 2026)
|
||||
|
||||
### D-16 — Full AV Dock Replacement
|
||||
**Date:** 2026-05-20
|
||||
**Decision:** Replace FoundryVTT's native AV dock completely with custom ScryingPoolStrip and RoleRenderer components rather than hooking into the native dock.
|
||||
**Rationale:** Live testing revealed limitations in hooking approach; full replacement provides better control over rendering, layout, and participant management. Enables consistent behavior across all AV states.
|
||||
**Status:** Implemented in FR-27, FR-28. Captured in §4.6 Full AV Dock Replacement.
|
||||
**Trade-offs:**
|
||||
- PRO: Full control over UI/UX, consistent behavior, easier to extend
|
||||
- PRO: Enables dock layout system and position persistence
|
||||
- CON: Must handle all edge cases that native dock handles
|
||||
- CON: Potential compatibility issues with other AV-related modules
|
||||
|
||||
### D-17 — Dock Layout System
|
||||
**Date:** 2026-05-22
|
||||
**Decision:** Implement configurable dock layouts with 6 options: vertical-sm, vertical-md, horizontal-sm, horizontal-md, mosaic-sm, mosaic-md.
|
||||
**Rationale:** User feedback from live testing requested flexibility in how participant tiles are arranged to match different table setups and screen configurations. GM controls direction/size at world level; individual users can override size preference.
|
||||
**Status:** Implemented in FR-29, FR-30. Captured in §4.7 Dock Layout System.
|
||||
**Implementation Notes:**
|
||||
- World-scoped `dockLayout` setting controls direction and canonical size
|
||||
- Client-scoped `dockLayoutExpanded` setting allows per-user override ('' = inherit, 'sm' = small, 'md' = large)
|
||||
- Director's Board includes visual selector for layout configuration
|
||||
- Legacy boolean values automatically migrated to string format
|
||||
|
||||
### D-18 — Position Persistence
|
||||
**Date:** 2026-05-24
|
||||
**Decision:** ScryingPoolStrip window position persists across sessions using GM user flags.
|
||||
**Rationale:** User feedback indicated frustration with repositioning the dock every session. Position persistence improves UX consistency.
|
||||
**Status:** Implemented in FR-31. Captured in §4.8 Position Persistence.
|
||||
**Implementation Notes:**
|
||||
- Position (left, top) saved to GM user flags on move
|
||||
- Loaded on module initialization via `_loadPosition()` method
|
||||
- First-time users get default position
|
||||
|
||||
### D-19 — ApplicationV2 API Migration
|
||||
**Date:** 2026-05-20
|
||||
**Decision:** Migrate all UI components to use FoundryVTT v14 ApplicationV2 API with HandlebarsApplicationMixin.
|
||||
**Rationale:** FoundryVTT v14 requires ApplicationV2 for proper window management, resizing, and lifecycle. Previous implementation had compatibility issues.
|
||||
**Status:** Implemented in FR-32. Captured in §4.9 Implementation Quality.
|
||||
**Implementation Notes:**
|
||||
- ScryingPoolStrip extends HandlebarsApplicationMixin(ApplicationV2)
|
||||
- DirectorsBoard extends HandlebarsApplicationMixin(ApplicationV2)
|
||||
- Fixed jQuery parameter handling in _onRender methods
|
||||
- Added proper PARTS and DEFAULT_OPTIONS static properties
|
||||
|
||||
### D-20 — PortraitFallbackHandler Integration
|
||||
**Date:** 2026-05-23
|
||||
**Decision:** Enhance portrait fallback system with dedicated PortraitFallbackHandler component for consistent image resolution.
|
||||
**Rationale:** Live testing revealed inconsistent fallback behavior. Dedicated handler provides clear priority chain and better integration with custom portraits.
|
||||
**Status:** Implemented in FR-8 enhancement, FR-26. Captured in Glossary and §4.1.
|
||||
**Implementation Notes:**
|
||||
- Priority chain: custom fallback portrait -> user.avatar -> user.character?.img -> mystery-man
|
||||
- Integrated with RoleRenderer for participant list building
|
||||
- Handled in buildParticipantList function
|
||||
|
||||
### D-21 — CSS Build Pipeline
|
||||
**Date:** 2026-05-24
|
||||
**Decision:** Add postinstall script to automatically build CSS from LESS source files.
|
||||
**Rationale:** Streamlines development and distribution; ensures styles are always up-to-date.
|
||||
**Status:** Implementation note in §6.1 MVP Scope.
|
||||
**Implementation Notes:**
|
||||
- Added postinstall script to package.json
|
||||
- Moved styles to root styles/ folder for FoundryVTT compatibility
|
||||
- Updated .gitignore to allow dist/styles/ for CSS distribution
|
||||
|
||||
---
|
||||
|
||||
## Decision Summary Table
|
||||
|
||||
| Decision | Date | Status | Related FRs | Section |
|
||||
|----------|------|--------|-------------|---------|
|
||||
| D-1 | 2026-05-19 | Active | FR-1-32 | §1, §6, §10 |
|
||||
| D-2 | 2026-05-19 | Active | FR-7 | §4.1, §9 |
|
||||
| D-3 | 2026-05-19 | Active | All | §5, §6 |
|
||||
| D-4 | 2026-05-19 | Active | All | §7, Cross-cutting |
|
||||
| D-5 | 2026-05-19 | Active | FR-1-26 | §4 |
|
||||
| D-6 | 2026-05-19 | Active | FR-10 | §4.2 |
|
||||
| D-7 | 2026-05-19 | Active | FR-24 | §4.5 |
|
||||
| D-8 | 2026-05-19 | Active | All | §6.1 |
|
||||
| D-9 | 2026-05-19 | Active | FR-2 | §4.1, §9 |
|
||||
| D-10 | 2026-05-19 | Active | FR-7 | §4.1, §8 |
|
||||
| D-11 | 2026-05-19 | Active | FR-6 | §4.1, §9 |
|
||||
| D-12 | 2026-05-19 | Active | All | §5 |
|
||||
| D-13 | 2026-05-19 | Active | FR-24, FR-25 | §4.5 |
|
||||
| D-14 | 2026-05-19 | Active | FR-9 | §4.2 |
|
||||
| D-15 | 2026-05-19 | Active | All automation | Cross-cutting |
|
||||
| **D-16** | **2026-05-20** | **Active** | **FR-27, FR-28** | **§4.6** |
|
||||
| **D-17** | **2026-05-22** | **Active** | **FR-29, FR-30** | **§4.7** |
|
||||
| **D-18** | **2026-05-24** | **Active** | **FR-31** | **§4.8** |
|
||||
| **D-19** | **2026-05-20** | **Active** | **FR-32** | **§4.9** |
|
||||
| **D-20** | **2026-05-23** | **Active** | **FR-8, FR-26** | **§4.1, §4.5** |
|
||||
| **D-21** | **2026-05-24** | **Active** | **N/A** | **§6.1** |
|
||||
|
||||
---
|
||||
|
||||
## Open Questions Status
|
||||
|
||||
| OQ | Phase Blocker? | Status | Related Decisions |
|
||||
|---|---|---|---|
|
||||
| OQ-1: WebRTC track disable API access | No | Open — to be checked against v14 API during development; CSS fallback is safe default | D-2, D-10 |
|
||||
| OQ-2: socketlib vs native socket API | No | **RESOLVED** — native FoundryVTT socket API | D-9 |
|
||||
| OQ-3: GM own-feed hidden behavior | No | **RESOLVED** — GM always sees all activated feeds; own self-view is configurable | D-11 |
|
||||
| OQ-4: Non-native AV backend support | No | **RESOLVED** — native WebRTC only for v1.0 | D-12 |
|
||||
| OQ-5: Scene hook timing | No | Open — not a concern for first implementation stage | |
|
||||
| OQ-6: Partial vs full preset application | No | Open — to be resolved during FR-15/FR-16 implementation | |
|
||||
| **OQ-7: Full AV replacement edge cases** | **No** | **Open** — Does full AV dock replacement handle all edge cases? | **D-16** |
|
||||
|
||||
---
|
||||
|
||||
## PRD Version History
|
||||
|
||||
| Version | Date | Status | Author | Changes |
|
||||
|---------|------|--------|--------|---------|
|
||||
| 1.0 | 2026-05-19 | final | Morr | Initial PRD with FR-1 through FR-26 |
|
||||
| **1.1** | **2026-05-25** | **draft** | **Morr** | **Added FR-27 through FR-32 from live testing; updated D-1, added D-16 through D-21** |
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
---
|
||||
title: "Video View Manager — FoundryVTT Webcam Visibility Control Module"
|
||||
status: final
|
||||
status: draft
|
||||
created: 2026-05-19
|
||||
updated: 2026-05-19
|
||||
updated: 2026-05-25
|
||||
version: 0.1.0
|
||||
---
|
||||
|
||||
# PRD: Video View Manager
|
||||
|
||||
## 0. Document Purpose
|
||||
|
||||
This PRD is the authoritative specification for **Video View Manager**, a FoundryVTT v14 module. It is written for the module author (Morr) and future contributors, and it is the source of record for scope decisions during development.
|
||||
This PRD is the authoritative specification for **Video View Manager** (module ID: `scrying-pool`), a FoundryVTT v14 module. It is written for the module author (Morr) and future contributors, and it is the source of record for scope decisions during development.
|
||||
|
||||
This document uses Glossary terms from §3 throughout §4+ and keeps functional requirements globally numbered FR-1 through FR-26 for stable reference. Inline `[ASSUMPTION]` tags in §4 mark unconfirmed inferences and are indexed in §9. The primary upstream input is `_bmad-output/brainstorming/brainstorming-session-2026-05-19-221747.md`.
|
||||
This document uses Glossary terms from §3 throughout §4+ and keeps functional requirements globally numbered FR-1 through FR-32 for stable reference. Inline `[ASSUMPTION]` tags in §4 mark unconfirmed inferences and are indexed in §9. The primary upstream input is `_bmad-output/brainstorming/brainstorming-session-2026-05-19-221747.md`.
|
||||
|
||||
**Implementation Updates:** This version incorporates enhancements from live testing completed May 25, 2026, including full AV dock replacement, configurable dock layouts, and position persistence.
|
||||
|
||||
---
|
||||
|
||||
@@ -23,6 +26,12 @@ From that core, the module extends into session cinematography. Scene Presets le
|
||||
|
||||
The module follows the **Progressive Enhancement Architecture**. Level 1 adds a right-click action to existing AV Tiles. Level 2 adds the Director's Board. Level 3 adds Scene Presets and automation. Participants stay informed, automation that changes an individual's on-screen presence requires explicit opt-in, and the GM always has an immediate override.
|
||||
|
||||
**Live Test Enhancements (May 2026):**
|
||||
- Full replacement of Foundry's native AV dock with custom ScryingPoolStrip
|
||||
- Configurable dock layouts (vertical, horizontal, mosaic) with size variants
|
||||
- Position persistence across sessions
|
||||
- Enhanced portrait fallback handling
|
||||
|
||||
---
|
||||
|
||||
## 2. Target Users
|
||||
@@ -48,6 +57,8 @@ Alex has just joined their first online TTRPG. They are comfortable with Zoom bu
|
||||
- Spotlight one Participant for a dramatic reveal or emotional scene climax
|
||||
- Apply a Scene Preset when transitioning between scenes without manual intervention
|
||||
- Know at a glance which of 6+ Participants are hidden, visible, or offline
|
||||
- Configure dock layout to match table preferences (vertical, horizontal, mosaic)
|
||||
- Maintain dock position and size preferences across sessions
|
||||
|
||||
**Social / Emotional**
|
||||
- Feel in control of the table atmosphere as a GM — the visual equivalent of adjusting the lights
|
||||
@@ -60,37 +71,6 @@ Alex has just joined their first online TTRPG. They are comfortable with Zoom bu
|
||||
- Groups using FoundryVTT v13 or earlier
|
||||
- Streamers requiring independent audience layouts (served in the later roadmap — §10)
|
||||
|
||||
### 2.4 Key User Journeys
|
||||
|
||||
**UJ-1. Marcus transitions into a boss fight and spotlights the villain's lair.**
|
||||
- **Persona + context:** Marcus, mid-session, activating a Scene named "Throne Room" where he wants only two Participants visible.
|
||||
- **Entry state:** A Scene Preset is configured at prep time; the Director's Board is closed.
|
||||
- **Path:** (1) Marcus activates the "Throne Room" scene. (2) The module auto-applies the saved preset — two Participants are visible and four are hidden. (3) A toast appears for all Participants: "Scene changed: camera layout updated." (4) Marcus glances at the AV Tile strip — hidden tiles show a grey overlay with a lock icon.
|
||||
- **Climax:** The table's visual focus narrows to the two Participants in the scene without Marcus touching a control.
|
||||
- **Resolution:** Marcus keeps narrating; he can override the preset with one right-click if needed.
|
||||
- **Edge case:** If a Participant whose feed should be visible is offline, the hidden overlay still appears and the preset is marked partially applied.
|
||||
|
||||
**UJ-2. Sofia opts out of HP-Reactive Cam Styling before the session.**
|
||||
- **Persona + context:** Sofia, before the session starts, opening her FoundryVTT user settings.
|
||||
- **Entry state:** Authenticated as a Participant; the Player Privacy Panel is available in module settings; HP-Reactive Cam Styling is currently ON from an earlier opt-in.
|
||||
- **Path:** (1) Sofia opens the Player Privacy Panel. (2) She sees HP-Reactive Cam Styling: ON. (3) She toggles it OFF. (4) The setting saves instantly; no page reload is required.
|
||||
- **Climax:** Sofia knows her camera will not change appearance based on her HP.
|
||||
- **Resolution:** Her opt-out flag persists for future sessions in this world until she changes it.
|
||||
|
||||
**UJ-3. Jake opens the Director's Board at session start to configure the layout.**
|
||||
- **Persona + context:** Jake, 5 minutes before going live, with 5 Participants connected.
|
||||
- **Entry state:** Authenticated as GM; the Director's Board has not been opened this session.
|
||||
- **Path:** (1) Jake presses the keyboard shortcut (⌘/Ctrl+Shift+V). (2) The Director's Board opens as a floating window. (3) Jake sees all 5 Participants in a seating-chart layout with their current states. (4) He sets Participant 4 to "Hidden" (late joiner, not on yet). (5) He uses Spotlight on his own card to confirm his feed remains visible.
|
||||
- **Climax:** Jake's table is visually configured for broadcast before he goes live.
|
||||
- **Resolution:** The Director's Board stays open in a corner, and Jake uses it as a live monitor during the session.
|
||||
|
||||
**UJ-4. Alex sees a toast notification when their feed is hidden.**
|
||||
- **Persona + context:** Alex, playing for the first time; Marcus has just hidden Alex's camera to manage a technical glitch.
|
||||
- **Entry state:** Alex's AV Tile is live; Marcus triggers hide from the context menu.
|
||||
- **Path:** (1) Alex's tile changes to Portrait Fallback mode with a grey overlay. (2) Alex receives a toast: "GM has hidden your camera. Your portrait is shown to other Participants." (3) Alex sees a small "Camera hidden" badge on their own tile.
|
||||
- **Climax:** Alex understands exactly what happened and why — no confusion or anxiety.
|
||||
- **Resolution:** Alex can keep playing; their audio is unaffected.
|
||||
|
||||
---
|
||||
|
||||
## 3. Glossary
|
||||
@@ -100,26 +80,31 @@ Alex has just joined their first online TTRPG. They are comfortable with Zoom bu
|
||||
- **Combat Cinematics Mode** — An automation mode that manages the Visibility Matrix during active FoundryVTT combat, spotlighting the active combatant's feed. Part of the Later roadmap.
|
||||
- **Director's Board** — The floating window for bulk Visibility Matrix management. Primary UI surface for Level 2/3 interactions. Synonyms are not permitted — this is not "the settings panel" or "the popout."
|
||||
- **Director's Board Stage Lighting States** — A Later-roadmap preset vocabulary tier for cinematic bulk actions such as Wash, Focus, and Blackout.
|
||||
- **Dock Layout** — Configurable layout options for the AV dock strip: `vertical-sm`, `vertical-md`, `horizontal-sm`, `horizontal-md`, `mosaic-sm`, `mosaic-md`. Controlled via world setting `dockLayout` with client-scoped override via `dockLayoutExpanded`.
|
||||
- **Dual Layout System** — A Later-roadmap architecture that separates the Participant-facing layout from the Spectator View.
|
||||
- **Full AV Replacement** — Complete replacement of FoundryVTT's native AV dock with custom ScryingPoolStrip and RoleRenderer components, providing full control over participant feed display.
|
||||
- **GM** — Game Master. The FoundryVTT user with the `GAMEMASTER` role. Has exclusive authority over the Visibility Matrix unless Player Permissions are extended (future roadmap).
|
||||
- **HP-Reactive Cam Styling** — An opt-in automation effect that changes the presentation of a Participant's feed based on HP-related game events. Part of the Later roadmap.
|
||||
- **NPC Presence Tiles** — A Later-roadmap feature that displays static image tiles for NPC voice actors or other non-camera presences.
|
||||
- **Participant** — Any connected FoundryVTT user with an AV presence (camera, microphone, or both), including the GM.
|
||||
- **Participant State** — One of eight enumerated states describing a Participant's AV presence: `active`, `hidden`, `self-muted`, `offline`, `cam-lost`, `reconnecting`, `never-connected`, `ghost`. Defined in §4.1.
|
||||
- **Player Privacy Panel** — The per-user settings interface for opting in or out of cinematic automation effects. Scoped to the current user; accessible from module settings.
|
||||
- **Portrait Fallback** — A static image (user avatar or actor portrait) displayed in place of a live camera feed when a Participant has no camera, or when their feed is `cam-lost`.
|
||||
- **Portrait Fallback** — A static image (user avatar or actor portrait) displayed in place of a live camera feed when a Participant has no camera, or when their feed is `cam-lost`. Enhanced with custom portrait handler integration via `PortraitFallbackHandler`.
|
||||
- **PortraitFallbackHandler** — Component that manages custom portrait fallback images for participants, with priority: custom fallback → user avatar → character portrait → mystery-man placeholder.
|
||||
- **Progressive Enhancement Architecture** — The three-level UI model: Level 1 (right-click on existing AV Tiles — zero new UI), Level 2 (Director's Board), Level 3 (Scene Presets + full automation). Each level is independently useful.
|
||||
- **Pull Visibility Model** — A Later-roadmap visibility model in which feeds remain hidden until a Viewer explicitly requests them.
|
||||
- **Reaction Cam** — An opt-in feature that automatically spotlights a Participant's feed during key game moments (for example, taking damage in combat). Part of the Later roadmap.
|
||||
- **Reaction Clip System** — A Later-roadmap fallback that shows a short video snippet when a Participant has no live camera feed.
|
||||
- **RoleRenderer** — Custom component that replaces Foundry's native AV tile rendering, integrating with ScryingPoolStrip and PortraitFallbackHandler for consistent participant display.
|
||||
- **Scene Preset** — A saved snapshot of the Visibility Matrix, optionally linked to a FoundryVTT Scene for automatic application on scene activation.
|
||||
- **ScryingPoolStrip** — The custom AV dock strip component that replaces Foundry's native AV dock, implementing configurable layouts, position persistence, and integrated participant feed management.
|
||||
- **Spectator View** — A read-only camera layout independent from the Participant layout, intended for streaming audiences. Part of the Later roadmap.
|
||||
- **The Living Table** — A Later-roadmap concept that exposes the full seating-chart UI for `Map<participantId, Map<viewerId, VisibilityState>>` relationships.
|
||||
- **Token-Anchored Floating Cams** — A Later-roadmap feature that links camera surfaces to canvas tokens.
|
||||
- **Visibility Matrix** — The authoritative data structure representing all camera visibility relationships: `Map<participantId, Map<viewerId, VisibilityState>>`. Stored in world-level settings and broadcast to all clients on change.
|
||||
- **Zero-UI Full Automation Mode** — A Later-roadmap mode that minimizes manual camera control after initial configuration.
|
||||
- **Visibility State** — The visibility setting for one Participant's camera as seen by one Viewer. Distinct from Participant State: a feed can be `active` but have a `hidden` Visibility State for specific viewers.
|
||||
- **Viewer** — A Participant who is receiving (watching) another Participant's camera feed.
|
||||
- **Zero-UI Full Automation Mode** — A Later-roadmap mode that minimizes manual camera control after initial configuration.
|
||||
|
||||
---
|
||||
|
||||
@@ -189,7 +174,7 @@ All Participant States produce appropriate visual feedback and do not cause AV T
|
||||
|
||||
**Consequences (testable):**
|
||||
- Hiding or revealing a Participant's feed does not change the position of other AV Tiles.
|
||||
- Mid-combat state transitions (`active` → `offline` → `reconnecting`) do not shift the combat tracker or map canvas layout.
|
||||
- Mid-combat state transitions (`active` -> `offline` -> `reconnecting`) do not shift the combat tracker or map canvas layout.
|
||||
- A Participant in `ghost` state has no AV Tile rendered for other Participants.
|
||||
|
||||
#### FR-6: GM sees all activated Participant feeds; GM self-view is configurable
|
||||
@@ -218,6 +203,7 @@ When a Participant has no camera device (`never-connected`) or enters `cam-lost`
|
||||
- The default Portrait Fallback uses the FoundryVTT user avatar and falls back to a system placeholder if no avatar is set.
|
||||
- Participants can set a custom Portrait Fallback through the Player Privacy Panel (FR-26).
|
||||
- Portrait Fallback renders at the same dimensions as a live camera-feed tile.
|
||||
- Custom PortraitFallbackHandler integrates with priority: custom fallback portrait -> user.avatar -> user.character?.img -> mystery-man placeholder.
|
||||
|
||||
**Feature-specific NFRs:**
|
||||
- Visibility Matrix updates must not block the FoundryVTT rendering loop; state changes apply asynchronously.
|
||||
@@ -235,7 +221,7 @@ When a Participant has no camera device (`never-connected`) or enters `cam-lost`
|
||||
A dedicated button in the FoundryVTT controls sidebar opens the Director's Board. A keyboard shortcut (default: `Ctrl+Shift+V`) also opens it. Realizes UJ-3.
|
||||
|
||||
**Consequences (testable):**
|
||||
- The Director's Board opens as a resizable, draggable `ApplicationV2` window [ASSUMPTION].
|
||||
- The Director's Board opens as a resizable, draggable ApplicationV2 window [ASSUMPTION].
|
||||
- Opening the Director's Board does not change the existing AV Tile strip.
|
||||
- The keyboard shortcut is configurable in module settings.
|
||||
- The window closes and reopens instantly, supporting both a pre-session setup workflow and a live-monitor workflow.
|
||||
@@ -247,6 +233,7 @@ All connected Participants are shown with their current Visibility State, name,
|
||||
- Every Participant card displays the name, portrait, current Participant State, and current Visibility State.
|
||||
- The layout reads as a seating chart, not a list.
|
||||
- Updates to Visibility State appear in the Director's Board within 500 ms, matching FR-2.
|
||||
- Dock layout selector is available in Director's Board for GM to configure world-level layout preference.
|
||||
|
||||
#### FR-11: Per-Participant visibility toggle from Director's Board
|
||||
The GM can toggle any single Participant's Visibility State from that Participant's card in the Director's Board.
|
||||
@@ -311,7 +298,7 @@ A preset can be linked to a Scene; it applies automatically when that Scene is a
|
||||
|
||||
**Consequences (testable):**
|
||||
- The Scene-to-Preset association is configured in Scene settings or module settings.
|
||||
- Auto-apply fires on the `updateScene` hook, and a configurable 0–5000 ms pre-delay supports dramatic transitions [ASSUMPTION: sufficient hook timing — to be verified during FR-17 development].
|
||||
- Auto-apply fires on the `updateScene` hook, and a configurable 0-5000 ms pre-delay supports dramatic transitions [ASSUMPTION: sufficient hook timing — to be verified during FR-17 development].
|
||||
- All clients receive the notification "Scene changed: camera layout updated." matching UJ-1.
|
||||
|
||||
#### FR-18: Scene Preset auto-apply can be disabled per scene or globally
|
||||
@@ -401,6 +388,92 @@ A Participant can set a custom image as their Portrait Fallback (used in FR-8 wh
|
||||
- A file picker in the Player Privacy Panel sets the custom portrait.
|
||||
- Accepted formats are PNG, JPG, WEBP, and static GIF.
|
||||
- The image falls back to the FoundryVTT user avatar if no custom portrait is set, then to the system placeholder if no avatar exists.
|
||||
- Custom portraits are handled by PortraitFallbackHandler with proper priority chain.
|
||||
|
||||
---
|
||||
|
||||
### 4.6 Full AV Dock Replacement
|
||||
|
||||
**Description:** Complete replacement of FoundryVTT's native AV dock with custom implementation via ScryingPoolStrip and RoleRenderer. This provides full control over participant feed rendering, layout, and display.
|
||||
|
||||
**Functional Requirements:**
|
||||
|
||||
#### FR-27: Custom AV dock strip (ScryingPoolStrip)
|
||||
The module replaces Foundry's native AV dock with ScryingPoolStrip, a custom ApplicationV2-based component.
|
||||
|
||||
**Consequences (testable):**
|
||||
- ScryingPoolStrip opens automatically for all users (GM and players) when AV is active.
|
||||
- The strip is implemented using FoundryVTT v14 ApplicationV2 API with HandlebarsApplicationMixin.
|
||||
- Custom templates (roster-strip.hbs) render participant tiles with configurable layout.
|
||||
- Strip integrates with PortraitFallbackHandler for consistent portrait display.
|
||||
|
||||
#### FR-28: Custom role rendering (RoleRenderer)
|
||||
RoleRenderer component handles individual participant feed rendering and management.
|
||||
|
||||
**Consequences (testable):**
|
||||
- RoleRenderer coordinates between StateStore, ScryingPoolController, AVTileAdapter, and PortraitFallbackHandler.
|
||||
- Participant list is built with proper priority for fallback portraits (custom -> user avatar -> character portrait -> mystery-man).
|
||||
- RoleRenderer manages strip lifecycle (open, close, rerender).
|
||||
|
||||
---
|
||||
|
||||
### 4.7 Dock Layout System
|
||||
|
||||
**Description:** Configurable dock layout options for the AV dock strip, allowing GMs and users to customize how participant tiles are arranged.
|
||||
|
||||
**Functional Requirements:**
|
||||
|
||||
#### FR-29: Dock layout configuration
|
||||
The module provides 6 layout options via world-scoped `dockLayout` setting.
|
||||
|
||||
**Consequences (testable):**
|
||||
- Available layouts: `vertical-sm`, `vertical-md`, `horizontal-sm`, `horizontal-md`, `mosaic-sm`, `mosaic-md`.
|
||||
- Layout is configured via Director's Board UI with visual selector.
|
||||
- Changing layout re-renders the strip for all users via onChange callback.
|
||||
- Default layout is `vertical-sm`.
|
||||
|
||||
#### FR-30: Per-user layout size override
|
||||
Users can override the GM's layout size preference via client-scoped `dockLayoutExpanded` setting.
|
||||
|
||||
**Consequences (testable):**
|
||||
- Setting values: `''` (inherit from world), `'sm'` (force small), `'md'` (force large).
|
||||
- Client setting only affects size, not layout direction (vertical/horizontal/mosaic).
|
||||
- Changing client override re-renders the strip for that user only.
|
||||
- Legacy boolean values are migrated to string format automatically.
|
||||
|
||||
---
|
||||
|
||||
### 4.8 Position Persistence
|
||||
|
||||
**Description:** The ScryingPoolStrip remembers its window position across sessions for consistent user experience.
|
||||
|
||||
**Functional Requirements:**
|
||||
|
||||
#### FR-31: Window position persistence
|
||||
ScryingPoolStrip position is saved and restored from GM user flags.
|
||||
|
||||
**Consequences (testable):**
|
||||
- Position (left, top coordinates) is saved when strip is moved.
|
||||
- Position is loaded on module initialization via `_loadPosition()` method.
|
||||
- Saved position applies only to the GM user; player strip positions follow GM configuration.
|
||||
- First-time users get default position (left: 0, top: 0) or system default.
|
||||
|
||||
---
|
||||
|
||||
### 4.9 Implementation Quality
|
||||
|
||||
**Description:** Code quality improvements and FoundryVTT v14 compatibility.
|
||||
|
||||
**Functional Requirements:**
|
||||
|
||||
#### FR-32: ApplicationV2 API compatibility
|
||||
All UI components properly extend and use FoundryVTT v14 ApplicationV2 API.
|
||||
|
||||
**Consequences (testable):**
|
||||
- ScryingPoolStrip extends HandlebarsApplicationMixin(ApplicationV2).
|
||||
- DirectorsBoard extends HandlebarsApplicationMixin(ApplicationV2).
|
||||
- All _onRender, _prepareContext, and _onClose methods properly implemented.
|
||||
- jQuery parameter handling is compatible with ApplicationV2 expectations.
|
||||
|
||||
---
|
||||
|
||||
@@ -422,13 +495,18 @@ A Participant can set a custom image as their Portrait Fallback (used in FR-8 wh
|
||||
|
||||
### 6.1 In Scope (v1.0)
|
||||
|
||||
- Core Visibility Toggle (FR-1 – FR-8): right-click toggle, broadcast, persistence, visual indicators, 8 Participant States, WebRTC track disabling with CSS fallback, Portrait Fallback
|
||||
- Director's Board (FR-9 – FR-14): seating-chart window, bulk actions, Spotlight, keyboard shortcuts
|
||||
- Scene-Aware Visibility Presets (FR-15 – FR-19): save, load, auto-apply, and JSON import/export
|
||||
- Contextual Notifications (FR-20 – FR-22): toast system, verbosity configuration, persistent self-status badge
|
||||
- Player Privacy Panel (FR-23 – FR-26): opt-in controls for future automation effects, custom portrait
|
||||
- Core Visibility Toggle (FR-1 - FR-8): right-click toggle, broadcast, persistence, visual indicators, 8 Participant States, WebRTC track disabling with CSS fallback, Portrait Fallback
|
||||
- Director's Board (FR-9 - FR-14): seating-chart window, bulk actions, Spotlight, keyboard shortcuts
|
||||
- Scene-Aware Visibility Presets (FR-15 - FR-19): save, load, auto-apply, and JSON import/export
|
||||
- Contextual Notifications (FR-20 - FR-22): toast system, verbosity configuration, persistent self-status badge
|
||||
- Player Privacy Panel (FR-23 - FR-26): opt-in controls for future automation effects, custom portrait
|
||||
- **Full AV Dock Replacement (FR-27 - FR-28)**: ScryingPoolStrip and RoleRenderer components
|
||||
- **Dock Layout System (FR-29 - FR-30)**: 6 layout options with per-user override
|
||||
- **Position Persistence (FR-31)**: Window position saved and restored
|
||||
- **ApplicationV2 Compatibility (FR-32)**: Full v14 API compliance
|
||||
- FoundryVTT v14+ compatibility; `module.json` per v14 manifest schema
|
||||
- English UI strings; i18n-ready string keys for community translation
|
||||
- CSS build pipeline with postinstall script for automatic CSS compilation
|
||||
|
||||
### 6.2 Out of Scope for MVP
|
||||
|
||||
@@ -473,6 +551,7 @@ A Participant can set a custom image as their Portrait Fallback (used in FR-8 wh
|
||||
4. ~~**OQ-4:** Should the module operate with Jitsi Meeting Server and other non-native AV backends (beyond native WebRTC), or is native WebRTC the only supported backend for v1.0?~~ **RESOLVED:** Native WebRTC only for v1.0. Non-native backends (Jitsi, etc.) are deferred to the Later roadmap.
|
||||
5. **OQ-5:** Do FoundryVTT v14 scene activation hooks fire early enough for Scene Preset auto-apply (FR-17) to avoid a visible flash of the wrong camera layout before the preset applies? Not a concern for the first implementation stage — defer to testing.
|
||||
6. **OQ-6:** Should Scene Presets support partial application — applying only to currently connected Participants and deferring state for offline ones — or should they always apply to all participant slots unconditionally? This cannot be decided yet and will be resolved during FR-15/FR-16 implementation.
|
||||
7. **OQ-7 (NEW):** Does the full AV dock replacement (FR-27-28) properly handle all edge cases of Foundry's native AV system, including dynamic participant join/leave, device changes, and AV mode toggles?
|
||||
|
||||
---
|
||||
|
||||
@@ -483,6 +562,9 @@ A Participant can set a custom image as their Portrait Fallback (used in FR-8 wh
|
||||
- **§4.2 / FR-9:** FoundryVTT v14's `ApplicationV2` API is the correct pattern for a resizable floating window with persistent state.
|
||||
- **§4.3 / FR-15:** 50 presets per world is an adequate upper bound for any campaign use case. If communities surface larger preset libraries, this can increase.
|
||||
- **§4.3 / FR-17:** The `updateScene` hook (or its v14 equivalent) fires early enough in the scene-transition lifecycle to apply the preset before the AV Tile strip re-renders.
|
||||
- **§4.6 / FR-27:** ScryingPoolStrip as ApplicationV2-based component can fully replace Foundry's native AV dock without breaking core functionality.
|
||||
- **§4.7 / FR-29:** 6 dock layout options (vertical-sm/md, horizontal-sm/md, mosaic-sm/md) cover the majority of table configuration needs.
|
||||
- **§4.8 / FR-31:** GM user flags are the appropriate storage mechanism for strip position persistence.
|
||||
|
||||
---
|
||||
|
||||
@@ -512,23 +594,28 @@ The following concepts from the brainstorming session are architecturally consis
|
||||
**Compatibility**
|
||||
- The module must not conflict with other popular FoundryVTT modules (Monk's Hotbar, Token Action HUD, etc.) by patching shared DOM selectors or overriding core FoundryVTT hooks without proper chaining.
|
||||
- All hooks must use FoundryVTT's `Hooks.on()` registration pattern, never `Hooks.once()` for persistent behavior.
|
||||
- **NEW:** Full AV replacement must coexist with other modules that patch AV-related hooks; proper hook chaining is required.
|
||||
|
||||
**Performance**
|
||||
- No Visibility Matrix operation should block the FoundryVTT main render loop.
|
||||
- The Director's Board must render and become interactive within 1 second even with 12 Participants.
|
||||
- Socket message payload for a Visibility Matrix update must be ≤ 4 KB.
|
||||
- **NEW:** Strip rendering with 6+ participants must maintain 60fps in all layout modes.
|
||||
|
||||
**Reliability**
|
||||
- If the socket broadcast fails because of a network interruption, the GM client retries up to 3 times before surfacing an error notification.
|
||||
- The module must fail gracefully if `game.webrtc` is unavailable (for example, when AV is disabled); all UI elements are hidden or disabled rather than erroring.
|
||||
- **NEW:** Position persistence must handle corrupted or invalid saved positions gracefully.
|
||||
|
||||
**Privacy**
|
||||
- The module does not transmit any data outside the FoundryVTT world. No analytics, telemetry, or third-party calls.
|
||||
- Participant names and portraits are used only within the FoundryVTT session; no external storage is allowed.
|
||||
- **NEW:** Custom portrait images are stored in FoundryVTT's standard file storage; no external uploads.
|
||||
|
||||
**Accessibility**
|
||||
- All interactive elements in the Director's Board have ARIA labels and are keyboard navigable (FR-14).
|
||||
- State-indicator icons (FR-4) include tooltip text for screen-reader compatibility.
|
||||
- **NEW:** All dock layout options are keyboard-navigable and have proper ARIA labels.
|
||||
|
||||
**Language and Voice**
|
||||
- Default UI labels use plain language: "Show," "Hide," "Spotlight," "Hidden by GM," "No Camera." Technical or cinematic vocabulary (for example, "Visibility Matrix" or "Wash / Focus / Blackout") is reserved for documentation, tooltips in advanced mode, and developer-facing strings — never as primary interface labels.
|
||||
@@ -540,4 +627,6 @@ The following concepts from the brainstorming session are architecturally consis
|
||||
- This is a non-negotiable cross-cutting rule: no automation may be implemented if it cannot be interrupted or overridden immediately by the GM.
|
||||
|
||||
**Delivery Risk Note (v1.0 scope)**
|
||||
- v1.0 intentionally combines the Day 1 core toggle (FR-1–FR-8) with Week 1–2 enhancements (FR-9–FR-26) into a single release. The brainstorming established Day 1 as a shippable standalone product; if delivery constraints arise, the Level 1 core toggle (FR-1–FR-8) is the minimum shippable increment, and all higher-level features can shift to v1.1 without breaking the architecture.
|
||||
- v1.0 intentionally combines the Day 1 core toggle (FR-1-8) with Week 1-2 enhancements (FR-9-26) and live-test enhancements (FR-27-32) into a single release. The brainstorming established Day 1 as a shippable standalone product; if delivery constraints arise, the Level 1 core toggle (FR-1-8) is the minimum shippable increment, and all higher-level features can shift to v1.1 without breaking the architecture.
|
||||
|
||||
---
|
||||
Reference in New Issue
Block a user