-
-
Notifications
You must be signed in to change notification settings - Fork 0
Description
iHog Board Feature Spec
Feature: Infinite Board for Show Objects
1. Overview
This feature adds a freeform, zoomable, and scrollable board to iHog on iPad and iPhone. Users can visually organize and trigger show objects (groups, palettes, lists, scenes) by placing them as square blocks on the board. The board supports both edit and play modes, enabling layout customization and live triggering.
2. Supported Show Objects
All Show Objects and show object types will be supported. Here's the data structure and object types:
@Model final class ShowObjectEntity {
var id: UUID?
var isOutlined: Bool?
var name: String?
var number: Double? = 0.0
var objColor: String?
var objType: String?
var showID: String?
var show: ShowEntity?
init(
id: UUID = UUID(),
isOutlined: Bool? = nil,
name: String? = nil,
number: Double? = nil,
objColor: String? = nil,
objType: String? = nil,
showID: String? = nil,
show: ShowEntity? = nil
) {
self.id = id
self.isOutlined = isOutlined
self.name = name
self.number = number
self.objColor = objColor
self.objType = objType
self.showID = showID
self.show = show
}
}Available object types are as follows:
public enum ShowObjectType: String {
case group
case intensity
case position
case color = "colour"
case beam
case effect
case list
case scene
case batch
// others
case macro
case plot
}3. Board Behavior
- Infinite scrollable area in all directions
- No zoom or pan limits
- Board supports:
- Drag to pan
- Pinch to zoom
- No default board is loaded automatically; users explicitly select one
- Boards are tied to a specific show
- Multiple boards can exist per show
- Board names are:
- User-defined (renameable)
- Displayed on-screen
4. Object Placement
- Users press and drag to define a rectangular region
- In Edit Mode, users can move placed objects by dragging them across the board
- On release, a menu appears to select a show object
- Placement is rejected if:
- It overlaps with an existing object
- The drawn area is smaller than 44×44 points
- Minimum size is 44×44 pts (1×1 grid unit), ensuring accessible tap targets
- All object movement and resizing snaps to grid
- Objects can be any rectangular size (width × height) as long as each dimension is at least 1 grid unit
5. Interaction Modes
Tapping an object in Play Mode provides standard iOS visual feedback (e.g., highlight or pressed animation) to indicate the interaction occurred.
If a move or resize action would result in overlap with another object, the action is rejected. The object snaps back to its last valid state, and a message appears saying "You cannot overlap items."
In Play Mode, only tap-to-trigger, zooming, and panning are allowed. All other interactions — including dragging, resizing, or long-press — are disabled.
Edit Mode
- Board is editable
- Tapping on an object opens an edit menu with options to:
- Reassign object
- Remove object
- Resize object (via drag handles)
- Objects are draggable and resizable
- Grid snap is enforced
Play Mode
- Board is live
- Tapping a square sends the assigned command to the connected device
- No edit options are available
For existing objects:
- Cannot be resized below 1×1 grid unit (44×44 pts)
- Attempts to resize below minimum will be blocked (object keeps current size)
- No deletion occurs from attempting to resize too small
6. Persistence
- Board layout is saved per show
- Multiple boards are supported per show
- All board data is saved via SwiftData
- Sync enabled via CloudKit
7. Undo / Redo
- The following actions are undoable/redone within the current Edit Mode session only:
- Object added
- Object moved
- Object resized
- Object reassigned
- Object removed
- Leaving Edit Mode clears the undo/redo history
- Board zoom/pan is not included in undo history
8. Grid System
Grid Units
- 1 grid unit = 44×44 points
- All object placement, movement, and resizing snaps to these units
- Minimum object size = 2×2 grid units (88×88 pts)
Grid Visibility
- Grid is always visible in Edit Mode
- A toggle button allows the user to show/hide the grid
- Grid is hidden in Play Mode
Grid Style
- Grid appears as dots at the corners of each 44×44 square
- Dots are lightly colored (e.g. translucent gray), non-distracting
Grid Origin
- Grid origin is at the center of the board ((0, 0) in the middle)
- Supports infinite panning in all directions
Zoom Behavior
- Grid scales with zoom so grid units appear larger or smaller depending on zoom level
9. Board Switching
Board thumbnails are shown in the board list. These are rendered snapshots of each board area with the object squares. No need for names inside the preview thumbnails as they may be too small to read.
Board names must be non-empty and unique within the same show.
Access
- A dedicated tab bar icon is added for boards within an open show
- Tapping the board icon opens the board system for the current show
Board List UI
- Displays a full-screen selector with a list of all boards for the show
- Each entry includes the board name (thumbnail previews optional in future)
- A "+ New Board" button is available
Board Creation
- Tapping "New Board" prompts the user to name the board (default name pre-filled and editable)
- New boards open in Edit Mode by default
Board Switching Behavior
- Selecting a board opens it in full screen
- If the board already exists:
- Opens in Play Mode
- Restores last used pan and zoom
- If the board is new:
- Opens in Edit Mode
- Starts centered at origin
Deletion and Renaming
- Users can rename or delete boards via swipe or long-press actions
- Deletion is confirmed via a modal dialog
10. Menus and Object Interaction
Post-Placement Object Selection Menu
- After drawing a new square, a popover menu appears near the drawn region
- Menu includes:
- Search bar
- Filters for all object types
- User can cancel the menu to avoid placing anything
- (Note: remembering the last-used object type is not supported in the first version)
Edit Menu (Edit Mode Only)
- Tapping an existing object opens a context menu
- Menu options:
- Reassign — opens the same object selection menu as above
- Remove — deletes the object from the board
- Resizing is handled directly via drag handles, not through the menu
11. Data Modeling
If the linked ShowObjectEntity is deleted, the corresponding BoardItemEntity should also be deleted automatically.
All models below are SwiftData models and must support CloudKit syncing.
BoardEntity
Represents a saved board tied to a specific show.
id: UUID?— unique identifier for the boardname: String?— user-defined board nameshowID: UUID?— ID of associated ShowEntitylastPanOffsetX: Double?— x component of last visible offset when board was viewedlastPanOffsetY: Double?— y component of last visible offset when board was viewedlastZoomScale: Double?— last zoom scale usedobjects: [BoardItemEntity]?— placed objects on this boardshow: ShowEntity?— relationship to owning ShowEntity
BoardItemEntity
Represents a placed show object on a board. Multiple BoardItemEntities can reference the same ShowObjectEntity. Position and size are stored in grid units relative to the board origin. All objects are snapped to the nearest grid corner during placement, movement, or resizing.
id: UUID?— unique identifier for the board itemboardID: UUID?— ID of associated BoardEntityobjectID: UUID?— ID of the ShowObjectEntity this refers topositionX: Double?— x coordinate of the square relative to board centerpositionY: Double?— y coordinate of the square relative to board centerwidth: Double?— width of the square in grid units (minimum 2)height: Double?— height of the square in grid units (minimum 2)board: BoardEntity?— relationship to owning BoardEntity
ShowEntity Updates
The ShowEntity has been updated to include a relationship to boards:
boards: [BoardEntity]?— relationship to boards owned by this show