#include <ComposableCameraLevelSequenceComponent.h>
Inherits:
UActorComponent
Actor component that drives a composable camera in the Level Sequence path.
Holds a FComposableCameraTypeAssetReference (TypeAsset + editable Parameters / Variables bags) and references an OutputCineCameraComponent on the same Actor. On activation, the component spawns a transient AComposableCameraCameraBase, runs its nodes each tick (without a PlayerCameraManager), and projects the resulting pose onto the CineCamera so Sequencer's Camera Cut Track and viewport Pilot both see the CCS camera natively via the standard UCameraComponent path.
Pure UActorComponent — NOT a USceneComponent. The component holds no transform of its own; it is a logic-and-data driver. The owning Actor is expected to provide a UCineCameraComponent as its RootComponent (that's what AComposableCameraLevelSequenceActor does), and to hand us the reference via OutputCineCameraComponent during construction. If a designer adds this component to an arbitrary Actor (BlueprintSpawnableComponent), OnRegister falls back to FindComponentByClass
Why ActorComponent not SceneComponent
Previously this was a USceneComponent whose RootComponent role doubled as a parent for the CineCamera child. That arrangement collided with UE's DefaultSubobject semantics (a component creating its own CreateDefaultSubobject
With the CineCamera as the Actor's RootComponent and this component as a plain sibling UActorComponent, the engine's standard "find a CameraComponent on the actor" path trivially finds the root, PCM::SetViewTarget creates the proxy, and we go down the same fast path ACineCameraActor uses. No special-case walks needed.
Compatibility & responsibilities remain unchanged:
-
PCM-independent evaluation (via UE::ComposableCameras::ConstructCameraFromTypeAsset).
-
Per-tick bag → RuntimeDataBlock re-sync before TickCamera.
-
Pose projection to OutputCineCameraComponent (position + rotation only).
-
Component evaluation while the owning Level Sequence Spawnable exists, with SetEvaluationEnabled available as a local teardown switch.
Public Attributes¶
| Return | Name | Description |
|---|---|---|
FComposableCameraTypeAssetReference |
TypeAssetReference |
The TypeAsset reference + its per-instance parameter and variable bags. Editing TypeAsset from the Details panel rebuilds the bags on PostEditChangeProperty; editing individual parameter values rebuilds the internal camera so the new values are reflected in the pose. Not BlueprintReadWrite: the nested FInstancedPropertyBag fields are not Blueprint-supported (see the struct comment). |
TObjectPtr< UCineCameraComponent > |
OutputCineCameraComponent |
Reference to the Actor's UCineCameraComponent used as the viewport terminal. Assigned by the owning Actor's constructor (primary path) or resolved in OnRegister via FindComponentByClass (fallback for arbitrary Actor hosts). The component does not own lifetime of the CineCamera — the Actor does. |
TypeAssetReference¶
FComposableCameraTypeAssetReference TypeAssetReference
The TypeAsset reference + its per-instance parameter and variable bags. Editing TypeAsset from the Details panel rebuilds the bags on PostEditChangeProperty; editing individual parameter values rebuilds the internal camera so the new values are reflected in the pose. Not BlueprintReadWrite: the nested FInstancedPropertyBag fields are not Blueprint-supported (see the struct comment).
OutputCineCameraComponent¶
TObjectPtr< UCineCameraComponent > OutputCineCameraComponent
Reference to the Actor's UCineCameraComponent used as the viewport terminal. Assigned by the owning Actor's constructor (primary path) or resolved in OnRegister via FindComponentByClass (fallback for arbitrary Actor hosts). The component does not own lifetime of the CineCamera — the Actor does.
No edit/visible specifier on purpose: [AComposableCameraLevelSequenceActor](../actors/AComposableCameraLevelSequenceActor.md#acomposablecameralevelsequenceactor) exposes the same UCineCameraComponent via its own OutputCineCameraComponent UPROPERTY (the surface designers actually use to author optics). Adding Visible/EditAnywhere here would create TWO UPROPERTY paths reaching the same component instance — when the Details panel walks the actor's property map, UpdateSinglePropertyMapRecursive follows both paths, hits the component on the second path, and recurses without cycle detection (StackOverflow inside SDetailsView::SetObjects on Track / actor selection). Plain UPROPERTY() keeps GC tracking + retains the value through serialization but skips Details panel walking.
Public Methods¶
| Return | Name | Description |
|---|---|---|
UComposableCameraLevelSequenceComponent |
||
void |
OnRegister virtual |
|
void |
OnUnregister virtual |
|
void |
BeginPlay virtual |
|
void |
EndPlay virtual |
|
void |
TickComponent virtual |
|
void |
SetEvaluationEnabled |
Enable or disable component-driven evaluation. |
bool |
IsEvaluationEnabled const inline |
|
AComposableCameraCameraBase * |
GetInternalCamera const inline |
Access the internal camera for editor-side inspection / debugging. |
void |
NotifyTypeAssetExternallyChanged |
External "TypeAsset was just swapped" entry for non-Details-panel paths (e.g. the Sequencer track editor's "Camera Type Asset" picker). Performs the same chain PostEditChangeProperty does on a TypeAsset edit: rebuild parameter / variable bag layouts from the new asset, then destroy + respawn the InternalCamera so the next tick reflects the new TypeAsset. Caller is responsible for setting TypeAssetReference.TypeAsset before calling this. Marks the component dirty for transaction tracking. |
void |
SetSequencerPatchOverlay |
Push (or refresh) an overlay registration for Section. Called every frame the section is in-range. The pre-computed EnvelopeAlpha (from the section's playhead position via PatchEnvelope::ComputeStatelessAlpha) drives the BlendBy. The component caches a transient evaluator actor per section (lazy-spawned on first use, destroyed on Remove or component teardown). Intentionally accepts the parameter block by value — caller builds it per-frame from the section's channel curves. |
void |
RemoveSequencerPatchOverlay |
Remove an overlay registration when the section leaves its range or when the TrackInstance shuts down. Destroys the cached evaluator actor. Idempotent — safe to call on a section that wasn't registered. |
void |
BuildSequencerPatchSnapshot const |
Capture this LS Component's currently-registered Sequencer patch overlays as Debug Panel snapshot rows. Called by the panel's BuildPatchesLines (it walks every LS Component in the world and merges results with the PatchManager-side snapshot). One snapshot row per overlay, sorted by the section's resolved LayerIndex (matches the per-tick apply order so the panel rows reflect actual composition order). Each entry has Source = [EComposableCameraPatchSource::Sequencer](#ComposableCameraDebugPanelData_8h_1aa9c73c4b40ce69b42a63367e19e90b86a0aa30ee67105bbe58a0c35001b9efe88) and HostActorName populated so the renderer can prefix "[Seq]" / suffix "on Actor". |
void |
SetSequencerShotOverride |
Push (or refresh) a Shot override for Section. Called every frame the section is in-range. The InEntry carries the resolved Shot, RowIndex, EnterTransition, and pre-computed BlendAlpha — the TrackInstance does the cross-section overlap analysis once per frame and the LSComponent blender just consumes the result. |
void |
RemoveSequencerShotOverride |
Remove a Shot override when the section leaves its range or the TrackInstance shuts down. Idempotent. |
UComposableCameraLevelSequenceComponent¶
UComposableCameraLevelSequenceComponent()
OnRegister¶
virtual
virtual void OnRegister()
OnUnregister¶
virtual
virtual void OnUnregister()
BeginPlay¶
virtual
virtual void BeginPlay()
EndPlay¶
virtual
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason)
TickComponent¶
virtual
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction * ThisTickFunction)
SetEvaluationEnabled¶
void SetEvaluationEnabled(bool bEnabled)
Enable or disable component-driven evaluation.
Level Sequence Spawn Tracks own actor lifetime. This flag is a local component switch used by teardown and external hosts; disabling destroys the transient internal camera, and enabling evaluates lazily on the next tick.
IsEvaluationEnabled¶
const inline
inline bool IsEvaluationEnabled() const
GetInternalCamera¶
const inline
inline AComposableCameraCameraBase * GetInternalCamera() const
Access the internal camera for editor-side inspection / debugging.
NotifyTypeAssetExternallyChanged¶
void NotifyTypeAssetExternallyChanged()
External "TypeAsset was just swapped" entry for non-Details-panel paths (e.g. the Sequencer track editor's "Camera Type Asset" picker). Performs the same chain PostEditChangeProperty does on a TypeAsset edit: rebuild parameter / variable bag layouts from the new asset, then destroy + respawn the InternalCamera so the next tick reflects the new TypeAsset. Caller is responsible for setting TypeAssetReference.TypeAsset before calling this. Marks the component dirty for transaction tracking.
SetSequencerPatchOverlay¶
void SetSequencerPatchOverlay(UMovieSceneComposableCameraPatchSection * Section, const FComposableCameraParameterBlock & Parameters, float EnvelopeAlpha)
Push (or refresh) an overlay registration for Section. Called every frame the section is in-range. The pre-computed EnvelopeAlpha (from the section's playhead position via PatchEnvelope::ComputeStatelessAlpha) drives the BlendBy. The component caches a transient evaluator actor per section (lazy-spawned on first use, destroyed on Remove or component teardown). Intentionally accepts the parameter block by value — caller builds it per-frame from the section's channel curves.
RemoveSequencerPatchOverlay¶
void RemoveSequencerPatchOverlay(UMovieSceneComposableCameraPatchSection * Section)
Remove an overlay registration when the section leaves its range or when the TrackInstance shuts down. Destroys the cached evaluator actor. Idempotent — safe to call on a section that wasn't registered.
BuildSequencerPatchSnapshot¶
const
void BuildSequencerPatchSnapshot(TArray< struct FComposableCameraPatchSnapshot > & OutPatches) const
Capture this LS Component's currently-registered Sequencer patch overlays as Debug Panel snapshot rows. Called by the panel's BuildPatchesLines (it walks every LS Component in the world and merges results with the PatchManager-side snapshot). One snapshot row per overlay, sorted by the section's resolved LayerIndex (matches the per-tick apply order so the panel rows reflect actual composition order). Each entry has Source = [EComposableCameraPatchSource::Sequencer](#ComposableCameraDebugPanelData_8h_1aa9c73c4b40ce69b42a63367e19e90b86a0aa30ee67105bbe58a0c35001b9efe88) and HostActorName populated so the renderer can prefix "[Seq]" / suffix "on Actor".
SetSequencerShotOverride¶
void SetSequencerShotOverride(UMovieSceneComposableCameraShotSection * Section, const FComposableCameraSequencerShotEntry & InEntry)
Push (or refresh) a Shot override for Section. Called every frame the section is in-range. The InEntry carries the resolved Shot, RowIndex, EnterTransition, and pre-computed BlendAlpha — the TrackInstance does the cross-section overlap analysis once per frame and the LSComponent blender just consumes the result.
RemoveSequencerShotOverride¶
void RemoveSequencerShotOverride(UMovieSceneComposableCameraShotSection * Section)
Remove a Shot override when the section leaves its range or the TrackInstance shuts down. Idempotent.
Public Static Methods¶
| Return | Name | Description |
|---|---|---|
void |
AddReferencedObjects static |
Walk UObject references inside the non-UPROPERTY-reflected SequencerPatchOverlays map. The map keys are weak (intentional — see field doc above), so the TMap itself can't be UPROPERTY-tagged; this override surfaces each overlay's Evaluator actor and the UObject contents of its LatestParameters parameter block to GC. (Same override also walks SequencerShotOverrides — see LSComponent.cpp::AddReferencedObjects for the implementation.) |
AddReferencedObjects¶
static
static void AddReferencedObjects(UObject * InThis, FReferenceCollector & Collector)
Walk UObject references inside the non-UPROPERTY-reflected SequencerPatchOverlays map. The map keys are weak (intentional — see field doc above), so the TMap itself can't be UPROPERTY-tagged; this override surfaces each overlay's Evaluator actor and the UObject contents of its LatestParameters parameter block to GC. (Same override also walks SequencerShotOverrides — see LSComponent.cpp::AddReferencedObjects for the implementation.)
Private Attributes¶
| Return | Name | Description |
|---|---|---|
TObjectPtr< AComposableCameraCameraBase > |
InternalCamera |
Transient internal camera — spawned lazily on first evaluation. Not added to any context stack or director; driven entirely by this component's TickComponent. |
bool |
bEvaluationEnabled |
Local evaluation switch; see SetEvaluationEnabled. |
bool |
bEvaluateNextTickWithZeroDelta |
One-shot zero-delta evaluation consumed by TickComponent after enabling. |
TMap< TWeakObjectPtr< UMovieSceneComposableCameraPatchSection >, FComposableCameraSequencerPatchOverlay > |
SequencerPatchOverlays |
Active overlays keyed by section. Key is TWeakObjectPtr (NOT TObjectPtr) so a stale section that's been GC'd can actually go stale — a strong-ref key would keep every Sequencer-side patch section alive forever, defeating the prune-on-tick path in ApplySequencerPatchOverlays that exists precisely to clean up overlays whose source section has been destroyed (Sequencer rebuild, asset reimport, undo across the section creation, etc.). TMap with TWeakObjectPtr keys cannot be UPROPERTY-reflected, so the inner Evaluator / LatestParameters UObject references are walked manually in AddReferencedObjects below — without that override, the inner Evaluator actor would be GC-blind. The section pointer itself stays alive via Sequencer's own TrackInstance / SectionInterface ownership while it's a live edit target. |
TMap< TWeakObjectPtr< UMovieSceneComposableCameraShotSection >, FComposableCameraSequencerShotEntry > |
SequencerShotOverrides |
Active Shot overrides keyed by Section. Held by TWeakObjectPtr to tolerate GC of the section between frames (a common case during Sequencer hot-reload / asset reimport). |
TWeakObjectPtr< UMovieSceneSequencePlayer > |
CachedOwningSequencePlayer |
Runtime player cache used for Sequencer-aware DeltaTime scaling. |
TWeakObjectPtr< UMovieSceneComposableCameraShotSection > |
LastActivePrimarySection |
Last frame's resolved primary Section (lowest RowIndex among the active overrides). ApplyActiveSequencerShotOverride compares this to the current frame's primary; mismatch = section transition. The framing node either reseeds its primary prior state for a true hard cut, or promotes the previous secondary prior when the incoming Section becomes the new primary after an authored overlap. |
TWeakObjectPtr< UMovieSceneComposableCameraShotSection > |
LastActiveSecondarySection |
Last frame's resolved secondary Section (next-lowest RowIndex). Used to recognize the normal overlap exit A+B → B, where B should inherit the secondary prior cache instead of hard-seeding as a fresh primary. Also detects secondary swaps like A+B → A+C so C starts from its own authored pose. |
InternalCamera¶
TObjectPtr< AComposableCameraCameraBase > InternalCamera
Transient internal camera — spawned lazily on first evaluation. Not added to any context stack or director; driven entirely by this component's TickComponent.
bEvaluationEnabled¶
bool bEvaluationEnabled = false
Local evaluation switch; see SetEvaluationEnabled.
bEvaluateNextTickWithZeroDelta¶
bool bEvaluateNextTickWithZeroDelta = false
One-shot zero-delta evaluation consumed by TickComponent after enabling, after Sequencer property tracks have written the current bag values.
SequencerPatchOverlays¶
TMap< TWeakObjectPtr< UMovieSceneComposableCameraPatchSection >, FComposableCameraSequencerPatchOverlay > SequencerPatchOverlays
Active overlays keyed by section. Key is TWeakObjectPtr (NOT TObjectPtr) so a stale section that's been GC'd can actually go stale — a strong-ref key would keep every Sequencer-side patch section alive forever, defeating the prune-on-tick path in ApplySequencerPatchOverlays that exists precisely to clean up overlays whose source section has been destroyed (Sequencer rebuild, asset reimport, undo across the section creation, etc.). TMap with TWeakObjectPtr keys cannot be UPROPERTY-reflected, so the inner Evaluator / LatestParameters UObject references are walked manually in AddReferencedObjects below — without that override, the inner Evaluator actor would be GC-blind. The section pointer itself stays alive via Sequencer's own TrackInstance / SectionInterface ownership while it's a live edit target.
SequencerShotOverrides¶
TMap< TWeakObjectPtr< UMovieSceneComposableCameraShotSection >, FComposableCameraSequencerShotEntry > SequencerShotOverrides
Active Shot overrides keyed by Section. Held by TWeakObjectPtr to tolerate GC of the section between frames (a common case during Sequencer hot-reload / asset reimport).
Not UPROPERTY — same constraint as SequencerPatchOverlays above: TMap with TWeakObjectPtr keys cannot be UHT-reflected. The inner [FComposableCameraSequencerShotEntry](../structs/FComposableCameraSequencerShotEntry.md#fcomposablecamerasequencershotentry)'s UObject references (EnterTransition TObjectPtr; Shot containing FShotTarget TSoftObjectPtr / TObjectPtr resolved to actors) are walked manually in AddReferencedObjects via AddPropertyReferencesWithStructARO per entry, so reflection's blindness to the outer TMap doesn't leave the resolved transition / target actors GC-blind.
LastActivePrimarySection¶
TWeakObjectPtr< UMovieSceneComposableCameraShotSection > LastActivePrimarySection
Last frame's resolved primary Section (lowest RowIndex among the active overrides). ApplyActiveSequencerShotOverride compares this to the current frame's primary; mismatch = section transition. The framing node either reseeds its primary prior state for a true hard cut, or promotes the previous secondary prior when the incoming Section becomes the new primary after an authored overlap (A+B → B).
LastActiveSecondarySection¶
TWeakObjectPtr< UMovieSceneComposableCameraShotSection > LastActiveSecondarySection
Last frame's resolved secondary Section (next-lowest RowIndex among the active overrides). Used to recognize the normal overlap exit A+B → B, where B should inherit the secondary prior cache instead of hard-seeding as a fresh primary on the first post-blend frame. Also detects secondary swaps like A+B → A+C so C starts from its own authored pose rather than B's cached state.
CachedOwningSequencePlayer¶
TWeakObjectPtr< UMovieSceneSequencePlayer > CachedOwningSequencePlayer
Runtime player cache used for Sequencer-aware DeltaTime scaling. Weak because players can disappear during Sequencer rebuild or PIE teardown.
Private Methods¶
| Return | Name | Description |
|---|---|---|
void |
EnsureInternalCamera |
Spawn InternalCamera if it doesn't exist yet, then call ConstructCameraFromTypeAsset with the current bag values. Safe to call repeatedly; reuses an existing camera when the TypeAsset hasn't changed. |
void |
RebuildInternalCamera |
Destroy InternalCamera and spawn a fresh one. Called from PostEditChangeProperty when TypeAsset changes. |
void |
ProjectPoseToCineCamera |
Project a pose into OutputCineCameraComponent. Position and rotation are the only fields written; physical optics stay on the CineCamera (designer or Sequencer property tracks drive them). |
void |
DestroyInternalCamera |
Destroy the internal camera actor if one exists. |
void |
ApplySequencerPatchOverlays |
Apply every active editor-preview patch overlay (sorted by the section's resolved LayerIndex) onto InOutPose. Called from TickComponent in editor world only, between InternalCamera->TickCamera and ProjectPoseToCineCamera. Lazy-spawns evaluator actors as needed and prunes stale entries (section GC'd) from the overlay map. |
float |
ResolveSequencerAwareDeltaTime |
Resolve a DeltaTime that follows the owning Level Sequence playback speed. |
UMovieSceneSequencePlayer * |
ResolveOwningSequencePlayer |
Find the runtime sequence player whose spawn register owns this component's Actor. |
void |
ApplyActiveSequencerShotOverride |
Pick the top-row override (lowest RowIndex) and write its Shot into the first found [UComposableCameraCompositionFramingNode](../nodes/UComposableCameraCompositionFramingNode.md#ucomposablecameracompositionframingnode) on the InternalCamera's CameraNodes array. No-op when the map is empty (gap between sections — CompositionFramingNode keeps last-written Shot). |
void |
EvaluateOnce |
Run one full evaluation pass (parameter block sync -> Shot override apply -> InternalCamera TickCamera -> patch overlays -> CineCamera projection). Used by TickComponent and by the Shot override first-entry path. |
EnsureInternalCamera¶
void EnsureInternalCamera()
Spawn InternalCamera if it doesn't exist yet, then call ConstructCameraFromTypeAsset with the current bag values. Safe to call repeatedly; reuses an existing camera when the TypeAsset hasn't changed.
RebuildInternalCamera¶
void RebuildInternalCamera()
Destroy InternalCamera and spawn a fresh one. Called from PostEditChangeProperty when TypeAsset changes.
ProjectPoseToCineCamera¶
void ProjectPoseToCineCamera(const FComposableCameraPose & Pose)
Project a pose into OutputCineCameraComponent. Position and rotation are the only fields written; physical optics stay on the CineCamera (designer or Sequencer property tracks drive them).
DestroyInternalCamera¶
void DestroyInternalCamera()
Destroy the internal camera actor if one exists.
ApplySequencerPatchOverlays¶
void ApplySequencerPatchOverlays(FComposableCameraPose & InOutPose, float DeltaTime)
Apply every active editor-preview patch overlay (sorted by the section's resolved LayerIndex) onto InOutPose. Called from TickComponent in editor world only, between InternalCamera->TickCamera and ProjectPoseToCineCamera. Lazy-spawns evaluator actors as needed and prunes stale entries (section GC'd) from the overlay map.
ResolveSequencerAwareDeltaTime¶
float ResolveSequencerAwareDeltaTime(float WorldDeltaTime)
Resolve a DeltaTime that follows the owning Level Sequence playback speed. Editor preview resolves through the editor hook; runtime playback resolves through the owning UMovieSceneSequencePlayer. Paused Sequencer preview returns zero so history-dependent nodes do not advance while scrubbing or stopped.
ResolveOwningSequencePlayer¶
UMovieSceneSequencePlayer * ResolveOwningSequencePlayer()
Find the runtime sequence player whose spawn register owns this component's Actor. Used for runtime Sequencer-aware DeltaTime scaling.
ApplyActiveSequencerShotOverride¶
void ApplyActiveSequencerShotOverride()
Pick the top-row override (lowest RowIndex) and write its Shot into the first found [UComposableCameraCompositionFramingNode](../nodes/UComposableCameraCompositionFramingNode.md#ucomposablecameracompositionframingnode) on the InternalCamera's CameraNodes array. No-op when the map is empty (gap between sections — CompositionFramingNode keeps last-written Shot).
Called from TickComponent BEFORE InternalCamera->TickCamera so the solver evaluates with the new Shot data on the same frame.
EvaluateOnce¶
void EvaluateOnce(float DeltaTime)
Run one full evaluation pass (parameter block sync -> Shot override apply -> InternalCamera TickCamera -> patch overlays -> CineCamera projection). Identical to a TickComponent body sans the Super::TickComponent / evaluation guard. Used by TickComponent and by the Shot override first-entry path, where Sequencer has already pushed the current section data and the CineCamera must be re-projected before the cut renders.
DeltaTime <= 0 is the standard "first-frame snap" signal — downstream solvers (V2.2 IIR damping, scrub-aware nodes) treat it as "use authored values, don't damp", which matches the cut-as-cut design intent.