---
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)