- 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.
250 lines
9.9 KiB
Markdown
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.
|