HSDollyCam/AGENTS.md
mita 31443b091f Add user manual for HS DollyCam and FOV extension; introduce project context for AI agents
- Created HS DollyCam HUD user manual (v1.3.0) detailing features, setup, commands, and troubleshooting.
- Added FOV extension manual outlining FOV commands, usage in playlists, and dollyzoom functionality.
- Introduced project context file for AI agents, specifying technology stack, critical implementation rules, and existing patterns.
2026-05-07 06:10:45 +02:00

250 lines
9.9 KiB
Markdown

# HS_DollyCam Project Information
This repository contains LSL (Linden Scripting Language) scripts for **HS_DollyCam**, a professional camera control system for Second Life.
The project is highly memory-sensitive. LSL script memory is limited, and large lists, mixed-type lists, and repeated string splitting can create avoidable memory pressure. Prefer targeted parsing and short-lived data where practical.
## Core Components
The system is split across specialized scripts that communicate mostly via `llMessageLinked`.
### 1. `HS_CamController.lsl` (Main Controller)
The central command and state coordinator.
- Handles chat commands and menu commands.
- Coordinates playlist, menu, marker, FOV, and engine scripts.
- Saves presets into Linkset Data.
- Handles marker click events and forwards camera movement requests.
- Maintains FOLLOW and LOCK state in Linkset Data.
Important note: movement math and continuous tour playback are not owned entirely by the Controller anymore. Controller dispatches movement/tour commands to helper scripts and engine scripts.
### 2. `HS_CamPlaylist.lsl` (Playlist Manager)
Primary script for notecard-driven workflows.
- Reads playlist notecards line by line.
- Uses `llGetNotecardLineSync` when the simulator has the notecard cached, with fallback to `llGetNotecardLine` on `NAK`.
- Handles `moveto`, `goto`, `load`, `wait`, `tour ... endtour`, `dollyzoom`, `fov`, `lock`, `follow`, and marker show/hide commands.
- Builds tour payloads and sends them to `HS_CamEngineTour.lsl` via `CE_CMD_TOUR`.
- For notecard tour blocks, the builder stores preset indices, holds, and weights, then loads position/focus only at `endtour`.
- Also supports compact notecard tours (`tour <ms> [mode] <idx...>`) to avoid slow multi-line notecard reads when no holds/weights are needed.
- Compact notecard tours add an internal `startfirst` mode flag so `HS_CamEngineTour.lsl` starts from the first preset without a current-camera-state roundtrip.
- `loadPreset()` intentionally uses targeted field parsing instead of splitting the full preset string into a list.
- Standard notecard command parsing uses token helpers rather than full `llParseString2List(line, [" "], [])`.
The user's primary workflow is Notecard Tours, so optimize this file carefully and prioritize notecard-tour memory use over chat/menu one-liner convenience.
### 3. `HS_CamTourCommands.lsl` (Secondary Tour Command Helper)
Dedicated helper for chat/menu one-shot tour builders.
- Handles `/88 tour ...`, `/88 dollyzoom ...`, and menu-built `TOURRUN` payloads.
- Builds `CE_CMD_TOUR` payloads for secondary workflows without adding memory pressure to `HS_CamPlaylist.lsl`.
- Uses targeted preset parsing for position/focus/FOV fields.
- Keep notecard playlist logic in `HS_CamPlaylist.lsl`; keep chat/menu convenience parsing here.
### 4. `HS_CamEngineTour.lsl` (Continuous Tour Runtime)
Dedicated runtime for continuous multi-waypoint camera tours.
- Receives `CE_CMD_TOUR` payloads from Playlist and TourCommands paths.
- Requests current camera state from Core via `CE_CMD_GET_STATE`.
- Builds runtime lists for active tour playback: position, focus, holds, segment lengths, cumulative lengths, point times, and optional weights.
- Drives the camera by sending `CE_INT_SET_CAM` to `HS_CamEngineCore.lsl`.
- Supports spline/linear movement, easing profiles, FOV ramps, and keep-frame mode.
- Uses throttled camera-frame sending via `tourSendCam()` to reduce repeated `CE_INT_SET_CAM` messages.
- Uses segment caching during timer playback to reduce repeated `llList2Vector` access.
- Parses large `CE_CMD_TOUR` payloads using targeted pipe-field helpers rather than splitting the whole payload list.
Do not move active tour runtime lists into Linkset Data. They are read every timer tick; Linkset Data would reduce script memory but likely hurt runtime performance due to repeated string reads and conversions.
### 5. `HS_CamEngineCore.lsl` (Camera Engine Core)
Low-level camera engine.
- Handles camera permissions, base camera params, MoveTo, Follow, Lock, config, and state queries.
- Receives internal tour camera frames with `CE_INT_SET_CAM`.
- `CE_INT_SET_CAM` is parsed without `llParseString2List` because it is part of the active tour hot path.
- Applies `llSetCameraParams` for active camera movement.
- Holds engine configuration and emits config dumps consumed by Playlist and TourEngine.
Tour-related config keys include:
- `tour_max_points`
- `tour_cam_min_interval`
- `tour_pos_epsilon`
- `tour_focus_epsilon`
### 6. `HS_CamMenu.lsl` (Menu/UI)
Handles dialog menus, page state, menu-driven tour building, nearby target lists, and UI command dispatch.
- Sends menu commands with `MN_CMD`.
- Keeps short UI lists such as nearby avatars/objects and selected tour indices.
- Menu paths are secondary compared with notecard tours.
### 7. `HS_CamMarkers.lsl` (Marker Helper)
Marker support is a comparatively rare workflow.
- Rezzes `HS_CamMarker` objects at preset positions.
- Uses `MARKER_CH = -880088`.
- Uses `llRegionSayTo` for marker setup/cleanup when marker keys are known.
- Keeps a mixed marker list internally. This is known to be less memory-efficient, but marker usage is rare and should not be prioritized unless marker workflows become important.
### 8. `HS_CamFov.lsl`
Handles Field of View adjustments and FOV-related state synchronization.
## Communication Protocol
Primary communication uses `llMessageLinked`.
Important constants:
- `MC_CMD = 5100`: Marker helper command channel, e.g. `SHOW|N`, `HIDE`.
- `MC_EVT_CLICK = 5101`: Marker click event from Markers to Controller.
- `MN_CMD = 7000`: Menu command channel.
- `PH_CMD_PLAY = 6100`: Controller/Menu to Playlist play command.
- `PH_CMD_STOP = 6101`: Stop playlist command.
- `PH_CMD_CHAT_TOUR = 6102`: Chat one-liner tour forwarded to TourCommands.
- `PH_CMD_TOURRUN = 6103`: Menu-built tour forwarded to TourCommands.
- `PH_CMD_CHAT_DZ = 6104`: Chat DollyZoom forwarded to TourCommands.
- `CE_CMD_MOVE = 1010`: Engine move command.
- `CE_CMD_TOUR = 1011`: Continuous tour command handled by TourEngine.
- `CE_CMD_STOP = 1012`: Stop engine movement.
- `CE_CMD_LOCK = 1020`: Lock command.
- `CE_CMD_FOLLOW = 1030`: Follow command.
- `CE_CMD_FOV = 1040`: FOV command.
- `CE_CMD_GET_STATE = 1060`: Request current camera state.
- `CE_INT_SET_CAM = 3000`: TourEngine to Core camera frame, payload `<pos>|<focus>`.
- `CE_INT_TOUR_BEGIN = 3001`: TourEngine begins external drive.
- `CE_INT_TOUR_END = 3002`: TourEngine ends external drive.
- `CE_INT_TOUR_STOP = 3003`: Stop external tour drive.
- `MARKER_CH = -880088`: Region channel for marker communication.
## Preset Storage
Presets are stored in Linkset Data using keys like `P1`, `P2`, etc.
Preset format:
```text
px|py|pz|fx|fy|fz|rx|ry|rz|rs|fovRad
```
Many consumers only need the first six fields:
- position: fields `0..2`
- focus: fields `3..5`
- optional FOV: field `10`
When reading presets in memory-sensitive code, avoid full `llParseString2List(data, ["|"], [])` if only these fields are needed.
## Performance And Memory Guidelines
### Prefer targeted parsing in hot paths
Avoid full `llParseString2List` when:
- parsing `CE_INT_SET_CAM`
- parsing preset data
- parsing large `CE_CMD_TOUR` payloads
- parsing normal notecard playlist lines
Use targeted helpers such as:
- `lineToken()` in `HS_CamPlaylist.lsl`
- pipe-field helpers in `HS_CamEngineTour.lsl`
- direct separator lookup for two-field payloads in `HS_CamEngineCore.lsl`
### Keep active runtime data in script memory
Active tour playback reads position/focus/segment lists every timer tick. Keep those lists in `HS_CamEngineTour.lsl`; do not replace them with Linkset Data reads.
Linkset Data is appropriate for persistent presets and shared state, not per-frame runtime data.
### Minimize mixed-type and large temporary lists
Avoid mixed-type list builders for large payloads where a direct string build is clear and safe.
For notecard tour blocks:
- Store preset indices while parsing.
- Load preset position/focus at `endtour`.
- Build the final `CE_CMD_TOUR` payload directly.
### Be careful with timer hot paths
Timer-driven code should avoid:
- full string splitting
- repeated Linkset Data reads
- repeated object detail calls unless needed
- unnecessary `llMessageLinked` calls
Tour playback currently reduces load with:
- `tour_cam_min_interval`
- `tour_pos_epsilon`
- `tour_focus_epsilon`
- segment caching in TourEngine
### Use `llRegionSayTo` when target keys are known
For marker communication, prefer `llRegionSayTo` over `llRegionSay` when the marker key is known. This reduces unnecessary listener wakeups in the region.
## Configuration
Engine configuration lives in `HS_CamEngine.properties`.
Useful current keys:
```text
move_step=0.025
follow_step=0.05
default_move_ms=3000
default_focus_dist=10.0
move_pos_lag=0.5
move_focus_lag=0.5
follow_pos_lag=0.5
follow_focus_lag=0.5
pos_threshold=0.02
focus_threshold=0.02
tour_cam_min_interval=0.033
tour_pos_epsilon=0.005
tour_focus_epsilon=0.005
follow_predict=0.10
tour_max_points=20
```
`tour_cam_min_interval=0.033` caps internal tour camera updates around 30 Hz while still allowing path computation at `move_step`.
## Validation Notes
There is no official local Second Life LSL compiler in this repository. The authoritative compile check is still in-world via the Second Life Viewer or Firestorm.
Local checks that are useful before in-world compile:
- brace-balance checks
- conflict marker search
- targeted `rg` scans for unwanted `llParseString2List` reintroductions in hot paths
- optional `lslint` if installed, with the understanding that it is not the official Linden compiler
## Current Optimization Priorities
Highest priority:
- Notecard tour memory behavior.
- TourEngine timer hot path.
- Core `CE_INT_SET_CAM` hot path.
- Large `CE_CMD_TOUR` startup parsing.
Lower priority:
- Marker memory layout, because marker use is rare.
- Chat one-liner tour convenience paths.
- Menu-only tour building paths, unless they become a primary workflow.