#include <ComposableCameraShotTarget.h>
Per-Actor data within a single FComposableCameraShot. Targets are PURELY world-space objects: identity (Actor + Bone + Offset via the embedded [FComposableCameraTargetInfo](FComposableCameraTargetInfo.md#fcomposablecameratargetinfo)) plus an optional bounding box used by the FOV bounds-fit solve. Targets do NOT carry screen-space composition data — that lives on the Shot's Placement / Aim layers (see Docs/ShotBasedKeyframing.md §3 for the layered data model).
V1.x (pre-refactor): DesiredScreenPosition, ScreenPositionWeight, Method (Rotate / Translate) lived here. V2 deletes those fields — screen-position constraints come from [FShotPlacement::ScreenPosition](FShotPlacement.md#screenposition-1) (where the placement anchor lands, realized via lateral camera translation) and [FShotAim::ScreenPosition](FShotAim.md#screenposition) (where the aim anchor lands, realized via camera rotation). Method is no longer per-target: Placement is always Translate (changes Position), Aim is always Rotate (changes Rotation). This kills the old V1.x cross-layer coupling.
Properties are BlueprintReadOnly per the Shot system's "no runtime BP API for mutating Shot data" principle (spec §1.4).
Public Attributes¶
| Return | Name | Description |
|---|---|---|
FComposableCameraTargetInfo |
Target |
Identity + pivot resolution. Drives the world point this target contributes to all solver passes. |
EShotTargetBoundsShape |
BoundsShape |
|
FVector |
ManualBoundsExtent |
Half-extent in world units; used iff BoundsShape == ManualExtent. |
EBoundsCachePolicy |
BoundsCachePolicy |
Cache refresh policy when BoundsShape == AutoFromComponentBounds. See EBoundsCachePolicy and spec §3.3.1. |
int32 |
BoundsRefreshIntervalFrames |
Refresh interval in frames when BoundsCachePolicy == Periodic. |
FVector |
CachedAutoBoundsExtent |
Snapshot of Actor->GetComponentsBoundingBox().GetExtent() — populated via RefreshAutoBoundsCache(). Never read directly by user code; go through GetEffectiveBoundsExtent() which dispatches on BoundsShape. |
TWeakObjectPtr< class UPrimitiveComponent > |
CachedBoundsMeshComponent |
Cached weak ref to the actor's first SkeletalMesh / StaticMesh component used by RefreshAutoBoundsCache. Polish P.1 — without this, Live-policy refreshes call Actor->FindComponentByClass<...>() per tick per target (O(actor.Components.Num()) linear walk), which accumulates measurably on character actors with 30+ components in a 4-target Shot at 60fps. With the cache, Live reduces to a weak-ptr validity check + a Bounds.GetBox() read; only invalidation (actor swap, component destroyed) re-runs FindComponentByClass. |
float |
BoundsContributionWeight |
Importance weight of this target's bounds in the FOV bounds-fit solve. Drives the BlackEye-style "perceptual union box" sizing in spec §4.5: high-weight targets dominate the resulting box, low-weight ones contribute proportionally less. 0 = target has bounds but doesn't drive FOV. Clamped [0, 1] — only ratios matter in the perceptual-box math, the [0, 1] convention keeps Details-panel intent readable. |
Target¶
FComposableCameraTargetInfo Target
Identity + pivot resolution. Drives the world point this target contributes to all solver passes.
BoundsShape¶
EShotTargetBoundsShape BoundsShape =
ManualBoundsExtent¶
FVector ManualBoundsExtent = FVector(50.f)
Half-extent in world units; used iff BoundsShape == ManualExtent.
BoundsCachePolicy¶
EBoundsCachePolicy BoundsCachePolicy =
Cache refresh policy when BoundsShape == AutoFromComponentBounds. See EBoundsCachePolicy and spec §3.3.1.
BoundsRefreshIntervalFrames¶
int32 BoundsRefreshIntervalFrames = 30
Refresh interval in frames when BoundsCachePolicy == Periodic.
CachedAutoBoundsExtent¶
FVector CachedAutoBoundsExtent = FVector::ZeroVector
Snapshot of Actor->GetComponentsBoundingBox().GetExtent() — populated via RefreshAutoBoundsCache(). Never read directly by user code; go through GetEffectiveBoundsExtent() which dispatches on BoundsShape.
Marked Transient: the cache is rebuilt at Shot activation and is never serialized.
CachedBoundsMeshComponent¶
TWeakObjectPtr< class UPrimitiveComponent > CachedBoundsMeshComponent
Cached weak ref to the actor's first SkeletalMesh / StaticMesh component used by RefreshAutoBoundsCache. Polish P.1 — without this, Live-policy refreshes call Actor->FindComponentByClass<...>() per tick per target (O(actor.Components.Num()) linear walk), which accumulates measurably on character actors with 30+ components in a 4-target Shot at 60fps. With the cache, Live reduces to a weak-ptr validity check + a Bounds.GetBox() read; only invalidation (actor swap, component destroyed) re-runs FindComponentByClass.
Stored as TWeakObjectPtr<UPrimitiveComponent> (the common base of SkelMesh + StaticMesh) so the same field handles either class. Mutable so the const-method GetEffectiveBoundsExtent could still do a read-side validity check if needed; current callers only mutate via RefreshAutoBoundsCache (already non-const). Transient so the cache doesn't persist across save/load — actors must re-resolve on first tick after load.
BoundsContributionWeight¶
float BoundsContributionWeight = 1.f
Importance weight of this target's bounds in the FOV bounds-fit solve. Drives the BlackEye-style "perceptual union box" sizing in spec §4.5: high-weight targets dominate the resulting box, low-weight ones contribute proportionally less. 0 = target has bounds but doesn't drive FOV. Clamped [0, 1] — only ratios matter in the perceptual-box math, the [0, 1] convention keeps Details-panel intent readable.
Public Methods¶
| Return | Name | Description |
|---|---|---|
void |
RefreshAutoBoundsCache |
Refreshes CachedAutoBoundsExtent from Actor's component bounds. No-op when BoundsShape != AutoFromComponentBounds OR Target.Actor is null. Call from: (a) Shot Editor on Actor pick / BoundsShape toggle; (b) Runtime when the Shot becomes active in LS; © Periodic / Live tick if the policy demands. |
FVector |
GetEffectiveBoundsExtent const |
Returns the effective bounds half-extent based on BoundsShape: None → FVector::ZeroVector (target ignored by FOV solve) ManualExtent → ManualBoundsExtent AutoFromComponentBounds → CachedAutoBoundsExtent (zero if cache cold — degrades silently to "no bounds") |
RefreshAutoBoundsCache¶
void RefreshAutoBoundsCache()
Refreshes CachedAutoBoundsExtent from Actor's component bounds. No-op when BoundsShape != AutoFromComponentBounds OR Target.Actor is null. Call from: (a) Shot Editor on Actor pick / BoundsShape toggle; (b) Runtime when the Shot becomes active in LS; © Periodic / Live tick if the policy demands.
Walks the actor's component hierarchy via GetComponentsBoundingBox (O(component count)) — never call from per-frame code unless the cache policy is Live.
GetEffectiveBoundsExtent¶
const
FVector GetEffectiveBoundsExtent() const
Returns the effective bounds half-extent based on BoundsShape: None → FVector::ZeroVector (target ignored by FOV solve) ManualExtent → ManualBoundsExtent AutoFromComponentBounds → CachedAutoBoundsExtent (zero if cache cold — degrades silently to "no bounds")