#include <ComposableCameraCameraBase.h>

Inherits: ACameraActor Subclassed by: AComposableCameraGeneralThirdPersonCamera

Base camera class.

Public Attributes

Return Name Description
FGameplayTag CameraTag Tag for this camera. Used by modifiers to distinguish different cameras.
FString CameraTagTraceName Cached CameraTag.ToString() populated once at Initialize and reused by per-tick TRACE_CPUPROFILER_EVENT_SCOPE_STR so the dynamic Insights scope name doesn't allocate an FString per tick. CameraTag is EditDefaultsOnly so the cache is stable across the camera's lifetime — repopulated only on Initialize (in case the runtime mutates the tag before construction completes).
UComposableCameraTransitionBase * EnterTransition Enter transition. Usually used for returning back to this camera from a transient camera.
bool bDefaultPreserveCameraPose Whether to preserve last camera's pose when resuming this camera.
TArray< UComposableCameraCameraNodeBase * > CameraNodes Nodes for this camera. They're executed in the order they are placed in this array. Each node reads input pin values, applies its logic, and writes output pin values. Inter-node data flow is handled entirely through the pin-based RuntimeDataBlock system.
TArray< TObjectPtr< UComposableCameraComputeNodeBase > > ComputeNodes One-shot compute nodes that run during BeginPlayCamera, after every node (both camera nodes and compute nodes) has had Initialize() run. They are walked in array order and each has ExecuteBeginPlay() called exactly once.
FOnPreTick OnPreTick
FOnPostTick OnPostTick
FOnActionPreTick OnActionPreTick
FOnActionPostTick OnActionPostTick
TArray< UComposableCameraActionBase * > PreNodeTickActions Node-scoped actions fired around each node's TickNode. The PCM registers actions here when their ExecutionType is PreNodeTick / PostNodeTick (see AComposableCameraPlayerCameraManager::AddCameraAction / BindCameraActionsForNewCamera). Matching is by exact class (Node->GetClass() == Action->TargetNodeClass), same rule as the Modifier system.
TArray< UComposableCameraActionBase * > PostNodeTickActions
FComposableCameraPose CameraPose
FComposableCameraPose LastFrameCameraPose
bool bIsTransient
float LifeTime
float RemainingLifeTime
uint64 LastTickedFrameCounter Per-frame tick memoization.
bool bLastTickFramingFailed Set by [UComposableCameraCompositionFramingNode::OnTickNode](../uobjects-other/UComposableCameraCameraNodeBase.md#onticknode) each tick — true when the primary SolveShot returned bValid=false (anchor unresolvable, all weights zero, target index out of range, etc.).
TArray< FComposableCameraExecEntry > FullExecChain Full execution chain for the per-frame camera tick, including both camera-node steps and internal-variable Set operations. Copied from UComposableCameraTypeAsset::FullExecChain during OnTypeAssetCameraConstructed.
TArray< FComposableCameraExecEntry > ComputeFullExecChain Full execution chain for the BeginPlay compute pass, including both compute-node steps and internal-variable Set operations. Copied from UComposableCameraTypeAsset::ComputeFullExecChain during OnTypeAssetCameraConstructed.
int32 TypeAssetNodeTemplateCount The number of entries in TypeAsset::NodeTemplates at construction time. Used as the base offset for compute-node pin keys in the RuntimeDataBlock (compute node i has pin key NodeIndex = TypeAssetNodeTemplateCount + i).
TUniquePtr< FComposableCameraRuntimeDataBlock > OwnedRuntimeDataBlock Owned RuntimeDataBlock for type-asset-based cameras. Allocated during activation from a UComposableCameraTypeAsset. Nodes hold raw pointers into this block — they never outlive the camera.
TObjectPtr< UComposableCameraTypeAsset > SourceTypeAsset The type asset that was used to construct this camera. Stored so that ReactivateCurrentCamera (triggered by modifier changes) can fully reconstruct the camera from the same source asset instead of producing an empty shell.
FComposableCameraParameterBlock SourceParameterBlock The parameter block that was applied when this camera was activated from a type asset. Stored alongside SourceTypeAsset so reactivation preserves the original caller-provided parameter values.

CameraTag

FGameplayTag CameraTag {}

Tag for this camera. Used by modifiers to distinguish different cameras.


CameraTagTraceName

FString CameraTagTraceName

Cached CameraTag.ToString() populated once at Initialize and reused by per-tick TRACE_CPUPROFILER_EVENT_SCOPE_STR so the dynamic Insights scope name doesn't allocate an FString per tick. CameraTag is EditDefaultsOnly so the cache is stable across the camera's lifetime — repopulated only on Initialize (in case the runtime mutates the tag before construction completes).


EnterTransition

UComposableCameraTransitionBase * EnterTransition

Enter transition. Usually used for returning back to this camera from a transient camera.


bDefaultPreserveCameraPose

bool bDefaultPreserveCameraPose { true }

Whether to preserve last camera's pose when resuming this camera.


CameraNodes

TArray< UComposableCameraCameraNodeBase * > CameraNodes

Nodes for this camera. They're executed in the order they are placed in this array. Each node reads input pin values, applies its logic, and writes output pin values. Inter-node data flow is handled entirely through the pin-based RuntimeDataBlock system.

@NOTE: This property is exposed as EditAnywhere, only for debug purposes at runtime. You should NEVER modify this for instances.


ComputeNodes

TArray< TObjectPtr< UComposableCameraComputeNodeBase > > ComputeNodes

One-shot compute nodes that run during BeginPlayCamera, after every node (both camera nodes and compute nodes) has had Initialize() run. They are walked in array order and each has ExecuteBeginPlay() called exactly once.

Compute nodes are NOT per-frame-ticked. They exist to perform C++ math / data shaping at activation time and publish the result via internal variables or output pins. Downstream camera nodes then read those values in their own Initialize or TickNode bodies.

Populated during type-asset activation: AComposableCameraPlayerCameraManager::OnTypeAssetCameraConstructed duplicates every non-null entry of UComposableCameraTypeAsset::ComputeNodeTemplates into this array, then reorders by the type asset's ComputeExecutionOrder (built from the editor's BeginPlay compute chain rooted at UComposableCameraBeginPlayStartGraphNode — see EditorDesignDoc §8 "Dual exec chains: camera chain vs BeginPlay compute chain").

@NOTE: Like CameraNodes, this is EditAnywhere only for debug inspection. Do not mutate at runtime.


OnPreTick

FOnPreTick OnPreTick

OnPostTick

FOnPostTick OnPostTick

OnActionPreTick

FOnActionPreTick OnActionPreTick

OnActionPostTick

FOnActionPostTick OnActionPostTick

PreNodeTickActions

TArray< UComposableCameraActionBase * > PreNodeTickActions

Node-scoped actions fired around each node's TickNode. The PCM registers actions here when their ExecutionType is PreNodeTick / PostNodeTick (see AComposableCameraPlayerCameraManager::AddCameraAction / BindCameraActionsForNewCamera). Matching is by exact class (Node->GetClass() == Action->TargetNodeClass), same rule as the Modifier system.

These are NOT UPROPERTY — ownership lives on the PCM's CameraActions UPROPERTY TSet, which is the GC root. This camera-local view is just a hot-path iteration cache; the PCM clears it via UnregisterNodeAction when an action expires, and EndPlay clears it defensively.


PostNodeTickActions

TArray< UComposableCameraActionBase * > PostNodeTickActions

CameraPose

FComposableCameraPose CameraPose

LastFrameCameraPose

FComposableCameraPose LastFrameCameraPose

bIsTransient

bool bIsTransient { false }

LifeTime

float LifeTime { 0.f }

RemainingLifeTime

float RemainingLifeTime { 0.f }

LastTickedFrameCounter

uint64 LastTickedFrameCounter { 0 }

Per-frame tick memoization.

When the evaluation DAG (produced by snapshot-based RefLeaves) reaches the same camera via multiple paths in a single frame — e.g. the pop transition's target subtree AND the RefLeaf→B → push-source RefLeaf both bottom out at the same original A leaf — a second TickCamera would double-advance the camera's per-node state (damping, interpolator bStartFrame, spline progress, noise seeds, etc.). TickCamera compares GFrameCounter against this value: if it matches, the cached CameraPose is returned verbatim and the node chain is NOT walked again.

0 is a valid sentinel: GFrameCounter starts above 0 in any real engine session, so a freshly-constructed camera (counter = 0) will always take the full-tick path on its first evaluation. Not a UPROPERTY — purely transient evaluation-time scratch.


bLastTickFramingFailed

bool bLastTickFramingFailed { false }

Set by [UComposableCameraCompositionFramingNode::OnTickNode](../uobjects-other/UComposableCameraCameraNodeBase.md#onticknode) each tick — true when the primary SolveShot returned bValid=false (anchor unresolvable, all weights zero, target index out of range, etc.).

Consumed by UComposableCameraLevelSequenceComponent::ProjectPoseToCineCamera to skip the CineCamera transform write on solver failure, so the CineCamera holds its last-valid transform instead of having a default-identity (or upstream-default) pose burned in. Critical for the early Sequencer evaluation path: if evaluation runs before the Shot TrackInstance has pushed its first override, the solver runs against the framing node's default empty Shot, fails, and would otherwise project an origin pose onto the CineCam just before the PCM ViewTarget switch reads it.

Cameras without a CompositionFramingNode keep this at the default false and project normally — the flag is only ever written by the framing node, so non-framing pipelines aren't affected.

Transient — not a UPROPERTY. Reset by spawn (default ctor → false) and by every framing node tick.


FullExecChain

TArray< FComposableCameraExecEntry > FullExecChain

Full execution chain for the per-frame camera tick, including both camera-node steps and internal-variable Set operations. Copied from UComposableCameraTypeAsset::FullExecChain during OnTypeAssetCameraConstructed.

CameraNodeIndex in each entry references the author-order index in CameraNodes (which is parallel to TypeAsset::NodeTemplates).


ComputeFullExecChain

TArray< FComposableCameraExecEntry > ComputeFullExecChain

Full execution chain for the BeginPlay compute pass, including both compute-node steps and internal-variable Set operations. Copied from UComposableCameraTypeAsset::ComputeFullExecChain during OnTypeAssetCameraConstructed.

CameraNodeIndex in each entry references the author-order index in ComputeNodes (which is parallel to TypeAsset::ComputeNodeTemplates when ComputeFullExecChain is non-empty — in that case OnTypeAssetCameraConstructed skips the legacy reorder to preserve index correspondence).


TypeAssetNodeTemplateCount

int32 TypeAssetNodeTemplateCount = 0

The number of entries in TypeAsset::NodeTemplates at construction time. Used as the base offset for compute-node pin keys in the RuntimeDataBlock (compute node i has pin key NodeIndex = TypeAssetNodeTemplateCount + i).

Stored explicitly because CameraNodes.Num() can differ from NodeTemplates.Num() if OnTypeAssetCameraConstructed skips null templates during duplication.


OwnedRuntimeDataBlock

TUniquePtr< FComposableCameraRuntimeDataBlock > OwnedRuntimeDataBlock

Owned RuntimeDataBlock for type-asset-based cameras. Allocated during activation from a UComposableCameraTypeAsset. Nodes hold raw pointers into this block — they never outlive the camera.


SourceTypeAsset

TObjectPtr< UComposableCameraTypeAsset > SourceTypeAsset

The type asset that was used to construct this camera. Stored so that ReactivateCurrentCamera (triggered by modifier changes) can fully reconstruct the camera from the same source asset instead of producing an empty shell.

STRONG ref by design (not weak). Reactivation routes through OnTypeAssetCameraConstructed, which dereferences this to walk the type asset's NodeTemplates / ExposedParameters / FullExecChain. If the asset was originally loaded transiently — soft path resolved mid-frame, DataTable row asset, BP local that already went out of scope — the only remaining reference at activation time may be this one. A weak ref would let GC reclaim the asset between activation and a later modifier-triggered Reactivate, the .Get() would return null, and the new camera would be built as an empty shell with no nodes / no data block (silent regression, no crash). The strong ref's only cost is keeping the type asset alive for the camera's lifetime — acceptable because (a) type assets are small metadata, (b) the camera owns this anyway in spirit (it can't function without it), and © the field is Transient so save / load is unaffected.


SourceParameterBlock

FComposableCameraParameterBlock SourceParameterBlock

The parameter block that was applied when this camera was activated from a type asset. Stored alongside SourceTypeAsset so reactivation preserves the original caller-provided parameter values.

Empty for type-asset cameras activated without any parameter overrides.

Public Methods

Return Name Description
AComposableCameraCameraBase
void BeginPlay virtual
void EndPlay virtual
void Initialize
void InitializeNodes Per-node initialization loop. Walks CameraNodes and ComputeNodes, calls Node->Initialize on each, and wires OnPreTick/OnPostTick delegates for CameraNodes only. Compute nodes are initialized but NOT wired to the per-frame tick multicasts — they only run once, from BeginPlayCamera.
void ApplyModifiers
void BeginPlayCamera Runs the BeginPlay compute chain: walks ComputeNodes in order and calls ExecuteBeginPlay on each. Called exactly once per activation from AActor::BeginPlay, after per-node Initialize has run for every node.
FComposableCameraPose TickCamera
void InvalidateTickCache inline Force the next TickCamera (or TickWithInputPose) on this camera to walk the node chain even if it has already ticked this frame.
FComposableCameraPose TickWithInputPose Per-frame entry point for evaluators driven by an upstream pose, used by the Camera Patch system. Sets CameraPose = InputPose so the first node in the chain reads the upstream pose as its starting state, then delegates to TickCamera. Returns the post-chain pose (TickCamera's normal return).
void RegisterNodeAction
void UnregisterNodeAction
UComposableCameraCameraNodeBase * GetNodeByClass
AComposableCameraPlayerCameraManager * GetOwningPlayerCameraManager inline
FComposableCameraPose GetCameraPose const inline
FComposableCameraPose GetLastFrameCameraPose const inline
bool IsTransient const inline
void DrawCameraDebug const Draw world-space debug primitives for this camera.
void DrawCameraDebug2D const 2D counterpart to DrawCameraDebug. Walks CameraNodes and invokes each node's DrawNodeDebug2D override. Called by the viewport debug service's "Game"-channel hook (HUD pass) — fires during PIE possessed play, not during F8 eject. Each node gates its own output on its per-node CVar, same pattern as the 3D path.
float GetLifeTime const inline
float GetRemainingLifeTime const inline
bool IsFinished const inline

AComposableCameraCameraBase

AComposableCameraCameraBase(const FObjectInitializer & ObjectInitializer)

BeginPlay

virtual

virtual void BeginPlay()

EndPlay

virtual

virtual void EndPlay(const EEndPlayReason::Type EndPlayReason)

Initialize

void Initialize(AComposableCameraPlayerCameraManager * Manager)

InitializeNodes

void InitializeNodes()

Per-node initialization loop. Walks CameraNodes and ComputeNodes, calls Node->Initialize on each, and wires OnPreTick/OnPostTick delegates for CameraNodes only. Compute nodes are initialized but NOT wired to the per-frame tick multicasts — they only run once, from BeginPlayCamera.

Called twice during type-asset activation: first from Initialize() (where CameraNodes is still empty — a no-op), then again from OnTypeAssetCameraConstructed once templates have been duplicated and the RuntimeDataBlock wired, so every node's Initialize() runs exactly once.


ApplyModifiers

void ApplyModifiers(const T_NodeModifier & Modifiers)

BeginPlayCamera

void BeginPlayCamera()

Runs the BeginPlay compute chain: walks ComputeNodes in order and calls ExecuteBeginPlay on each. Called exactly once per activation from AActor::BeginPlay, after per-node Initialize has run for every node.

Compute nodes that need the outgoing camera pose read it from OwningPlayerCameraManager->GetCurrentCameraPose() — which is why this function no longer takes a pose parameter.


TickCamera

FComposableCameraPose TickCamera(float DeltaTime)

InvalidateTickCache

inline

inline void InvalidateTickCache()

Force the next TickCamera (or TickWithInputPose) on this camera to walk the node chain even if it has already ticked this frame.

The default per-frame memoization (see LastTickedFrameCounter) is a correctness requirement for cameras inside the snapshot DAG (a single underlying leaf reachable via multiple RefLeaf paths must tick exactly once). Callers that own a camera OUTSIDE the DAG — most notably [UComposableCameraLevelSequenceComponent](../uobjects-other/UComposableCameraLevelSequenceComponent.md#ucomposablecameralevelsequencecomponent)'s InternalCamera and the Patch-overlay evaluators — can use this hook to rerun the chain after pushing fresh inputs in the same frame (e.g. a Sequencer Shot / Patch override applied after an earlier same-frame tick has already cached a stale pose). Inside the DAG, calling this would re-introduce the double-advance bug the cache exists to prevent — DAG callers must not use it.


TickWithInputPose

FComposableCameraPose TickWithInputPose(float DeltaTime, const FComposableCameraPose & InputPose)

Per-frame entry point for evaluators driven by an upstream pose, used by the Camera Patch system. Sets CameraPose = InputPose so the first node in the chain reads the upstream pose as its starting state, then delegates to TickCamera. Returns the post-chain pose (TickCamera's normal return).

Side effects on the per-frame state are deliberate and identical to a normal tick afterward: LastFrameCameraPose will reflect this frame's upstream input on next tick (per PatchSystemProposal §16.7 — damping / spring nodes inside a Patch see "how much did upstream change between frames", which is the right input for smoothing the upstream's motion).

Memoization caveat (carried from TickCamera): if this is called twice in the same GFrameCounter on the same evaluator, the second call returns the cached CameraPose from the first call — node chain does NOT re-tick. Patches do not currently exercise this case (each evaluator is referenced by exactly one PatchInstance in exactly one Director's ActivePatches list).


RegisterNodeAction

void RegisterNodeAction(UComposableCameraActionBase * Action)

UnregisterNodeAction

void UnregisterNodeAction(UComposableCameraActionBase * Action)

GetNodeByClass

UComposableCameraCameraNodeBase * GetNodeByClass(TSubclassOf< UComposableCameraCameraNodeBase > NodeClass)

GetOwningPlayerCameraManager

inline

inline AComposableCameraPlayerCameraManager * GetOwningPlayerCameraManager()

GetCameraPose

const inline

inline FComposableCameraPose GetCameraPose() const

GetLastFrameCameraPose

const inline

inline FComposableCameraPose GetLastFrameCameraPose() const

IsTransient

const inline

inline bool IsTransient() const

DrawCameraDebug

const

void DrawCameraDebug(class UWorld * World, bool bDrawFrustum) const

Draw world-space debug primitives for this camera.

Invoked from the viewport debug ticker when CCS.Debug.Viewport is enabled. Two independently gated pieces:

  • Frustum pyramid at the camera's current pose — drawn only when bDrawFrustum is true. The ticker passes true only while the player is NOT viewing through the camera (F8 eject / SIE / CCS.Debug.Viewport.AlwaysShow), because otherwise the pyramid just occludes the near plane.

  • A walk over CameraNodes calling each node's DrawNodeDebug. Always invoked — each node's override checks its own per-node CVar (CCS.Debug.Viewport.<NodeName>) and early-outs when zero. Per-node gizmos are therefore visible in BOTH possessed play and ejected state, because they rarely occlude the viewpoint.

Reads CameraPose (the leaf-local evaluated pose), not the PCM's blended pose — for the running camera in a steady state these are the same; during a transition, this shows the pose this camera is contributing, not the blended result.

Compiled out in shipping builds.


DrawCameraDebug2D

const

void DrawCameraDebug2D(class UCanvas * Canvas, class APlayerController * PC) const

2D counterpart to DrawCameraDebug. Walks CameraNodes and invokes each node's DrawNodeDebug2D override. Called by the viewport debug service's "Game"-channel hook (HUD pass) — fires during PIE possessed play, not during F8 eject. Each node gates its own output on its per-node CVar, same pattern as the 3D path.


GetLifeTime

const inline

inline float GetLifeTime() const

GetRemainingLifeTime

const inline

inline float GetRemainingLifeTime() const

IsFinished

const inline

inline bool IsFinished() const

Public Static Methods

Return Name Description
void AddReferencedObjects static

AddReferencedObjects

static

static void AddReferencedObjects(UObject * InThis, FReferenceCollector & Collector)

Protected Attributes

Return Name Description
TObjectPtr< AComposableCameraPlayerCameraManager > CameraManager

CameraManager

TObjectPtr< AComposableCameraPlayerCameraManager > CameraManager