Files
UE5-Modular-Game-Framework/Source/PG_Framework/Public/Capture/BPC_PlanarCapture.h
Lefteris Notas 0a2d08b2ad Add Planar Capture System implementation checklist and developer reference
- Created a comprehensive implementation checklist for the Planar Capture System (Systems 136-147) detailing tasks across multiple phases including C++ core, material foundation, Blueprint actors, data assets, integration, and performance testing.
- Added a developer reference document outlining the architecture, data flow, state machine, budget enforcement, render target pooling, horror features, integration points, multiplayer networking, performance characteristics, debugging methods, and build order for the capture systems.
- Introduced examples of capture surface usage in the Project Void horror game, including specific implementations for mirrors, monitors, portals, and fake windows, along with a checklist for integration tasks.
2026-05-22 15:36:08 +03:00

279 lines
11 KiB
C++

// Copyright Ngonart OU. All Rights Reserved.
// UE5 Modular Game Framework — BPC_PlanarCapture (136)
// The heart of the Planar Capture System. Attached to any actor that needs
// a scene capture — mirrors, portals, monitors, horror surfaces.
//
// Manages USceneCaptureComponent2D lifetime, render target pool allocation,
// camera transform computation per mode, oblique clip plane injection,
// show/hide actor lists, quality tier application, frame ring buffer,
// and MPC parameter pushes.
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "Capture/PlanarCaptureCommon.h"
#include "BPC_PlanarCapture.generated.h"
// Forward declarations
class USceneCaptureComponent2D;
class UTextureRenderTarget2D;
class UMaterialInstanceDynamic;
class UMaterialParameterCollection;
class ASS_PlanarCaptureManager;
class ABP_PlanarCaptureActor;
// ============================================================================
// Delegates
// ============================================================================
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnCaptureQualityChanged, EPlanarCaptureQualityTier, OldTier, EPlanarCaptureQualityTier, NewTier);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnCaptureInitialized, EPlanarCaptureInitResult, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnCaptureRendered);
/**
* BPC_PlanarCapture — Core capture component for mirrors, portals, monitors, etc.
*
* Owns the USceneCaptureComponent2D lifecycle. All camera math, render target
* management, and per-frame capture decisions happen here in C++ for performance.
* Designer configuration flows through Blueprint children.
*
* Multiplayer: Capture is always local-only. Each client renders their own view.
* No replication needed. This component only exists on clients.
*/
UCLASS(Blueprintable, ClassGroup = (Framework), meta = (BlueprintSpawnableComponent))
class PG_FRAMEWORK_API UBPC_PlanarCapture : public UActorComponent
{
GENERATED_BODY()
public:
UBPC_PlanarCapture();
// ========================================================================
// Lifecycle
// ========================================================================
virtual void BeginPlay() override;
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
virtual void TickComponent(float DeltaTime, ELevelTick TickType,
FActorComponentTickFunction* ThisTickFunction) override;
// ========================================================================
// Configuration — Set in Blueprint Defaults
// ========================================================================
/** What kind of surface this capture represents. */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Capture|Config")
EPlanarCaptureMode CaptureMode = EPlanarCaptureMode::Mirror;
/** Quality profiles per tier (0=Low, 1=Medium, 2=High, 3=Hero). Index maps to EPlanarCaptureQualityTier. */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Capture|Config")
TArray<FPlanarCaptureQualityProfile> QualityProfiles;
/** FOV for the capture camera. */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Capture|Config")
float CaptureFOV = 90.0f;
/** Maximum view distance for the capture (0 = unlimited). */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Capture|Config")
float MaxViewDistance = 5000.0f;
// ========================================================================
// Portal Configuration
// ========================================================================
/** For Portal mode: the linked target surface actor. */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Portal")
TSoftObjectPtr<ABP_PlanarCaptureActor> LinkedTargetSurface;
// ========================================================================
// Monitor Configuration
// ========================================================================
/** For Monitor mode: a fixed camera actor to capture from. */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Monitor")
TSoftObjectPtr<AActor> FixedCameraActor;
// ========================================================================
// Actor Lists
// ========================================================================
/** Actors to show exclusively in the capture (empty = show all). */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|ActorLists")
TArray<FPlanarCaptureActorListEntry> ShowOnlyActors;
/** Actors to hide from the capture. */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|ActorLists")
TArray<FPlanarCaptureActorListEntry> HiddenActors;
// ========================================================================
// Horror Configuration
// ========================================================================
/** Actor to swap into the ShowOnly list during wrong-reflection events. */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Horror")
TSoftObjectPtr<AActor> WrongReflectionActor;
/** Mesh component of the surface plane (for clip plane calculation). */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Config")
TSoftObjectPtr<UStaticMeshComponent> SurfaceMeshComponent;
// ========================================================================
// Runtime State (Read-Only)
// ========================================================================
/** Current assigned quality tier (set by SS_PlanarCaptureManager). */
UPROPERTY(BlueprintReadOnly, Category = "Capture|Runtime")
EPlanarCaptureQualityTier CurrentQualityTier = EPlanarCaptureQualityTier::Off;
/** Is this capture currently active (capturing frames)? */
UPROPERTY(BlueprintReadOnly, Category = "Capture|Runtime")
bool bIsCapturing = false;
/** The render target this capture writes to. */
UPROPERTY(BlueprintReadOnly, Category = "Capture|Runtime")
TObjectPtr<UTextureRenderTarget2D> CaptureRenderTarget;
// ========================================================================
// Public API — BlueprintCallable
// ========================================================================
/**
* Initialize the capture component. Allocates render target, creates and
* configures the USceneCaptureComponent2D. Called by the owning actor on BeginPlay.
*/
UFUNCTION(BlueprintCallable, Category = "Capture")
EPlanarCaptureInitResult InitializeCapture();
/**
* Shut down the capture, release render target back to pool, destroy SceneCaptureComponent2D.
*/
UFUNCTION(BlueprintCallable, Category = "Capture")
void ShutdownCapture();
/**
* Apply a quality tier profile immediately. Called by SS_PlanarCaptureManager.
*/
UFUNCTION(BlueprintCallable, Category = "Capture")
void ApplyQualityTier(EPlanarCaptureQualityTier Tier);
/**
* Trigger a single capture frame immediately (bypasses tick interval).
*/
UFUNCTION(BlueprintCallable, Category = "Capture")
void CaptureNow();
/**
* Swap the ShowOnly actor list to the wrong-reflection actor (horror mode).
* Original list is preserved and restored on DeactivateHorrorReflection().
*/
UFUNCTION(BlueprintCallable, Category = "Capture|Horror")
void ActivateHorrorReflection();
/**
* Restore the original ShowOnly actor list after a horror event.
*/
UFUNCTION(BlueprintCallable, Category = "Capture|Horror")
void DeactivateHorrorReflection();
/**
* Push a frame from the ring buffer into the render target for delayed reflection (horror lag).
*/
UFUNCTION(BlueprintCallable, Category = "Capture|Horror")
void PushDelayedFrame();
/**
* Set a scripted priority override (0.0 to 1.0). Higher values force higher quality tier.
* Example: a scare event elevates a specific mirror to Hero tier.
*/
UFUNCTION(BlueprintCallable, Category = "Capture")
void SetScriptedPriority(float Priority);
/**
* Push all Material Parameter Collection values for this surface.
* Called every frame when capturing, or on event trigger for horror params.
*/
UFUNCTION(BlueprintCallable, Category = "Capture|Material")
void PushMPCParameters(UMaterialParameterCollection* MPC);
// ========================================================================
// Compute — BlueprintPure
// ========================================================================
/** Compute the capture camera transform for the current mode. */
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Capture")
FTransform ComputeCaptureCameraTransform(const FTransform& ViewerCameraTransform) const;
/** Get the current composite quality score. */
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Capture")
FPlanarCaptureScore GetCurrentScore() const;
// ========================================================================
// Event Dispatchers
// ========================================================================
UPROPERTY(BlueprintAssignable, Category = "Capture|Events")
FOnCaptureQualityChanged OnCaptureQualityChanged;
UPROPERTY(BlueprintAssignable, Category = "Capture|Events")
FOnCaptureInitialized OnCaptureInitialized;
UPROPERTY(BlueprintAssignable, Category = "Capture|Events")
FOnCaptureRendered OnCaptureRendered;
protected:
// ========================================================================
// Internal State
// ========================================================================
/** The actual UE5 SceneCaptureComponent2D — created at runtime. */
UPROPERTY()
TObjectPtr<USceneCaptureComponent2D> SceneCapture;
/** Cached reference to the manager subsystem. */
UPROPERTY()
TObjectPtr<ASS_PlanarCaptureManager> CachedManager;
/** Cached reference to the owning actor. */
UPROPERTY()
TObjectPtr<ABP_PlanarCaptureActor> CachedOwningActor;
/** Time accumulator for capture interval throttling. */
float TimeSinceLastCapture = 0.0f;
/** Current quality profile (cached from QualityProfiles[Tier]). */
FPlanarCaptureQualityProfile ActiveProfile;
/** Scripted priority override (0.0 to 1.0). */
float ScriptedPriorityOverride = 0.0f;
/** Ring buffer of render targets for delayed reflection (horror mode). */
UPROPERTY()
TArray<TObjectPtr<UTextureRenderTarget2D>> FrameRingBuffer;
/** Current write index into the frame ring buffer. */
int32 RingBufferWriteIndex = 0;
/** Saved ShowOnly list before horror swap. */
TArray<TSoftObjectPtr<AActor>> SavedShowOnlyActors;
// ========================================================================
// Internal Methods
// ========================================================================
/** Create and configure the USceneCaptureComponent2D. */
void CreateSceneCaptureComponent();
/** Apply show flags from the active quality profile to the SceneCapture. */
void ApplyShowFlags();
/** Update the ShowOnly and Hidden actor lists on the SceneCapture. */
void UpdateActorLists();
/** Resolve soft references on initialization. */
void ResolveSoftReferences();
/** Compute the surface plane in world space for clip plane and mirror math. */
FPlane GetSurfacePlane() const;
};