Concept: Shared Camera State (Shoulder & Zoom)
Shoulder side and zoom distance are player framing preferences, not per-mode settings. So they live on UCrimsonCameraComponent as a single source of truth, and every third-person-derived mode reads the same value. Switch from third-person to aim to lock-on and your shoulder and zoom follow - with no carry-over code.
Why component-wide
The stack keeps one instance per mode class (see Concept: The Mode Stack). If shoulder/zoom were stored per instance, each mode would have its own - and switching modes would reset your framing. Hoisting them to the component means there is exactly one shoulder and one zoom, shared by all modes; the component advances their interpolation each frame before the modes evaluate.
Shoulder is a mirror, not an offset
The lateral (Y) framing magnitude comes from the active mode's offset curve. The shoulder applies a sign to it, interpolated smoothly through zero on a swap:
| Shoulder | Lateral Y (curve Y = 45) | Meaning |
|---|---|---|
Right | +45 (curve Y as authored) | Default side |
Left | -45 (curve Y negated) | Mirror of Right |
Center | 0 | No lateral offset - camera directly behind |
Right/Left are always a clean mirror. ToggleShoulder flips Left/Right; from Center it moves to the default side (Right) rather than doing nothing.Zoom is shared and clamped on the component
AddZoomDistance / SetZoomDistance change one shared target, clamped to the component's [MinZoomDistance, MaxZoomDistance] and interpolated by ZoomInterpSpeed. Every mode dollies its boom by the same GetCurrentZoomDistance(). The range is a single camera-wide setting - there is no per-mode zoom range; a mode either uses the shared zoom or opts out.
Per-mode opt-out
A specific mode can ignore the shared state and keep a fixed framing - useful for a cinematic or fixed-aim view.
| Property (on the mode) | Default | When false |
|---|---|---|
bUseShoulderOffset | true | The mode ignores the shoulder sign and uses its offset-curve Y exactly as authored. |
bUseZoom | true | The mode ignores the shared zoom and keeps its fixed boom distance. |
bUseShoulderOffset / bUseZoom are all-or-nothing per mode: a mode either uses the shared shoulder/zoom value or ignores it. There is no per-mode shoulder/zoom scale or range override.