--- title: 'Preset Transfer Utility' type: 'feature' created: '2026-05-13' status: 'done' baseline_commit: 'd979c9ee73947175fd246f1048759c74a833133e' context: - '{project-root}/project-context.md' - '{project-root}/AGENTS.md' --- ## Intent **Problem:** HS_DollyCam users need a practical way to move saved camera positions between camera objects, including older versions, without permanently adding memory pressure or dependencies to the main camera scripts. **Approach:** Add one isolated drop-in LSL utility script that can be inserted when needed, exports existing `P` Linkset Data presets as copyable text, imports the same text back from a notecard, and can remove itself afterward. ## Boundaries & Constraints **Always:** Preserve the existing preset payload exactly after the `P` key; use the current Linkset Data keys `P1`, `P2`, etc.; keep the script independent from controller, menu, playlist, engine, marker, and FOV scripts; restrict commands to the object owner or owner-owned attachments; use owner-visible feedback for all import/export operations. **Ask First:** Changing the persisted preset format; adding controller/menu integration; deleting or overwriting unrelated Linkset Data keys; adding a dependency on current-version-only linked-message protocols. **Never:** Do not move this into hot-path scripts; do not require edits to old camera versions; do not claim runtime notecard creation is possible in LSL; do not import malformed preset lines silently. ## I/O & Edge-Case Matrix | Scenario | Input / State | Expected Output / Behavior | Error Handling | |----------|--------------|---------------------------|----------------| | Export saved presets | `/88 xfer export 1 20` with `P1` and `P5` populated | Owner receives header, one `P=` line per populated preset, and end marker | If range has no presets, report that none were found | | Import presets | `/88 xfer import My Presets` with notecard lines `P1=` | Script writes each valid line to matching Linkset Data key | Blank, comment, header, and end-marker lines are skipped | | Replace import | `/88 xfer importreplace My Presets` with existing presets | Script clears existing `P1..P999`, then imports valid notecard lines | Missing notecard aborts before clearing | | Malformed import line | Notecard contains `foo` or `P0=` | Line is rejected and counted as skipped | Owner sees skipped count at completion | | Cleanup | `/88 xfer poof` | Script announces removal and removes its own inventory item | No other inventory or Linkset Data is touched | ## Code Map - `HS_CamController.lsl` -- Existing owner chat and `P` Linkset Data storage behavior used for compatibility reference. - `project-context.md` -- Project memory and parsing constraints. - `HS_CamPresetTransfer.lsl` -- New isolated drop-in utility script for preset export, import, replace import, status, help, and self-removal. ## Tasks & Acceptance **Execution:** - [x] `HS_CamPresetTransfer.lsl` -- Add standalone transfer script -- Enables import/export without touching core camera scripts or increasing normal runtime memory. - [x] `_bmad-output/implementation-artifacts/spec-preset-transfer-utility.md` -- Track Quick Dev specification and review order -- Keeps the feature reviewable. **Acceptance Criteria:** - Given an object with populated `P` Linkset Data presets, when the owner runs `/88 xfer export [from] [count]`, then the script emits copyable `P=` lines that preserve the stored preset payload exactly. - Given an object containing a transfer notecard, when the owner runs `/88 xfer import `, then valid `P=` lines are written to matching Linkset Data keys without requiring any other HS_DollyCam script. - Given existing presets and a valid notecard, when the owner runs `/88 xfer importreplace `, then existing `P1..P999` keys are cleared before import and unrelated Linkset Data keys remain untouched. - Given any command from a non-owner object or avatar, when it is heard on channel 88, then it is ignored. - Given the owner runs `/88 xfer poof`, when the command is accepted, then only the transfer script removes itself. ## Spec Change Log ## Design Notes The export format intentionally mirrors the Linkset Data key/value pair instead of inventing a richer schema: ```text HS_DOLLYCAM_PRESETS_V1 P1=px|py|pz|fx|fy|fz|rx|ry|rz|rs|fovRad P2=px|py|pz|fx|fy|fz|rx|ry|rz|rs|fovRad HS_DOLLYCAM_PRESETS_END ``` This keeps import compatible with older camera builds because the utility writes the same `P` keys and unchanged preset value strings those builds already read. ## Verification **Commands:** - `rg -n "llParseString2List" HS_CamPresetTransfer.lsl` -- expected: no output. - Conflict marker scan on `HS_CamPresetTransfer.lsl` and this spec -- expected: no conflict marker output. **Manual checks:** - In-world compile in Second Life Viewer or Firestorm; local repository has no official LSL compiler. ## Suggested Review Order **Command Surface** - Entry point keeps transfer commands isolated under `/88 xfer`. [`HS_CamPresetTransfer.lsl:240`](../../HS_CamPresetTransfer.lsl#L240) - Owner gate matches the existing controller trust model. [`HS_CamPresetTransfer.lsl:304`](../../HS_CamPresetTransfer.lsl#L304) **Import And Export** - Export emits stable copyable `P=` lines. [`HS_CamPresetTransfer.lsl:165`](../../HS_CamPresetTransfer.lsl#L165) - Import validates key shape and minimum preset fields before writing. [`HS_CamPresetTransfer.lsl:103`](../../HS_CamPresetTransfer.lsl#L103) - Replace mode clears only preset keys before notecard import. [`HS_CamPresetTransfer.lsl:122`](../../HS_CamPresetTransfer.lsl#L122) **Lifecycle** - Self-removal is explicit and limited to this script. [`HS_CamPresetTransfer.lsl:274`](../../HS_CamPresetTransfer.lsl#L274)