233 lines
8.4 KiB
C++
233 lines
8.4 KiB
C++
// Copyright Ngonart OU. All Rights Reserved.
|
|
// UE5 Modular Game Framework — SS_PlanarCaptureManager (138)
|
|
// Global budget manager for all planar capture surfaces in the world.
|
|
//
|
|
// One instance per World (World Subsystem). Each frame, scores every registered
|
|
// capture surface by distance, screen coverage, facing angle, and scripted priority.
|
|
// Assigns quality tiers across all surfaces respecting a global budget
|
|
// (max simultaneous high-quality captures, max total render target memory).
|
|
// Forces idle/disabled state on surfaces outside active rooms/sublevels.
|
|
//
|
|
// Also manages the render target pool — allocates, reuses, and resizes RTs
|
|
// to minimize memory churn.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "Subsystems/WorldSubsystem.h"
|
|
#include "Capture/PlanarCaptureCommon.h"
|
|
#include "SS_PlanarCaptureManager.generated.h"
|
|
|
|
class ABP_PlanarCaptureActor;
|
|
class UBPC_PlanarCapture;
|
|
|
|
// Delegates
|
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSurfaceRegistered, ABP_PlanarCaptureActor*, Surface, int32, TotalSurfaces);
|
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSurfaceUnregistered, ABP_PlanarCaptureActor*, Surface, int32, TotalSurfaces);
|
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnGlobalQualityCapChanged, EPlanarCaptureQualityTier, NewCap);
|
|
|
|
/**
|
|
* SS_PlanarCaptureManager — Global Planar Capture Budget Manager.
|
|
*
|
|
* Manages all ABP_PlanarCaptureActor instances per world. Evaluates priority
|
|
* and assigns quality tiers to stay within a configurable budget.
|
|
* Also owns the render target pool to reduce memory allocation overhead.
|
|
*
|
|
* Multiplayer: This subsystem exists on both server and clients.
|
|
* On the server, it tracks surfaces for replication state.
|
|
* On clients, it drives actual capture rendering.
|
|
*/
|
|
UCLASS()
|
|
class PG_FRAMEWORK_API USS_PlanarCaptureManager : public UWorldSubsystem
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
USS_PlanarCaptureManager();
|
|
|
|
// ========================================================================
|
|
// Lifecycle
|
|
// ========================================================================
|
|
|
|
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
|
|
virtual void Deinitialize() override;
|
|
virtual void Tick(float DeltaTime) override;
|
|
virtual TStatId GetStatId() const override;
|
|
|
|
// ========================================================================
|
|
// Surface Registry
|
|
// ========================================================================
|
|
|
|
/**
|
|
* Register a capture surface actor with the global manager.
|
|
* Called by ABP_PlanarCaptureActor::BeginPlay.
|
|
*/
|
|
UFUNCTION(BlueprintCallable, Category = "Capture|Manager")
|
|
void RegisterSurface(ABP_PlanarCaptureActor* Surface);
|
|
|
|
/**
|
|
* Unregister a capture surface actor. Called on EndPlay.
|
|
*/
|
|
UFUNCTION(BlueprintCallable, Category = "Capture|Manager")
|
|
void UnregisterSurface(ABP_PlanarCaptureActor* Surface);
|
|
|
|
/**
|
|
* Get all currently registered surfaces.
|
|
*/
|
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Capture|Manager")
|
|
TArray<ABP_PlanarCaptureActor*> GetRegisteredSurfaces() const;
|
|
|
|
/**
|
|
* Get the number of registered surfaces.
|
|
*/
|
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Capture|Manager")
|
|
int32 GetSurfaceCount() const { return RegisteredSurfaces.Num(); }
|
|
|
|
// ========================================================================
|
|
// Quality Budget Management
|
|
// ========================================================================
|
|
|
|
/**
|
|
* Global quality ceiling — caps all surfaces at this tier regardless of score.
|
|
* Use this for lower-end hardware targets.
|
|
*/
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Manager|Budget")
|
|
EPlanarCaptureQualityTier GlobalQualityCap = EPlanarCaptureQualityTier::High;
|
|
|
|
/**
|
|
* Maximum number of simultaneous Hero-tier captures.
|
|
*/
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Manager|Budget")
|
|
int32 MaxHeroSurfaces = 1;
|
|
|
|
/**
|
|
* Maximum number of simultaneous High-tier captures.
|
|
*/
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Manager|Budget")
|
|
int32 MaxHighSurfaces = 3;
|
|
|
|
/**
|
|
* Maximum number of simultaneous Medium-tier captures.
|
|
*/
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Manager|Budget")
|
|
int32 MaxMediumSurfaces = 6;
|
|
|
|
/**
|
|
* Maximum total render target memory in megabytes across all surfaces.
|
|
*/
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Manager|Budget")
|
|
float MaxTotalRenderTargetMemoryMB = 128.0f;
|
|
|
|
/**
|
|
* Distance at which capture quality drops to Off (world units).
|
|
*/
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Manager|Budget")
|
|
float MaxCaptureDistance = 10000.0f;
|
|
|
|
/**
|
|
* Interval between full re-evaluation of all surfaces (seconds).
|
|
* Individual surfaces check their own interval every frame via their component.
|
|
*/
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Manager|Budget")
|
|
float FullEvaluationInterval = 0.5f;
|
|
|
|
// ========================================================================
|
|
// Render Target Pool
|
|
// ========================================================================
|
|
|
|
/**
|
|
* Request a render target from the pool. Returns nullptr if none available.
|
|
*/
|
|
UTextureRenderTarget2D* RequestRenderTarget(int32 Size);
|
|
|
|
/**
|
|
* Release a render target back to the pool.
|
|
*/
|
|
void ReleaseRenderTarget(UTextureRenderTarget2D* RenderTarget);
|
|
|
|
/**
|
|
* Get the total memory used by the render target pool (in MB).
|
|
*/
|
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Capture|Manager")
|
|
float GetPoolMemoryUsageMB() const;
|
|
|
|
// ========================================================================
|
|
// Query
|
|
// ========================================================================
|
|
|
|
/**
|
|
* Get the nearest capture surface of a given mode to a world location.
|
|
*/
|
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Capture|Manager")
|
|
ABP_PlanarCaptureActor* GetNearestSurfaceOfMode(
|
|
EPlanarCaptureMode Mode, FVector WorldLocation, float MaxDistance = 0.0f) const;
|
|
|
|
/**
|
|
* Force all surfaces to a specific quality tier (e.g., for cutscenes).
|
|
*/
|
|
UFUNCTION(BlueprintCallable, Category = "Capture|Manager")
|
|
void ForceAllSurfacesToTier(EPlanarCaptureQualityTier Tier);
|
|
|
|
/**
|
|
* Release the force-tier override and resume normal scoring.
|
|
*/
|
|
UFUNCTION(BlueprintCallable, Category = "Capture|Manager")
|
|
void ReleaseForceTier();
|
|
|
|
// ========================================================================
|
|
// Event Dispatchers
|
|
// ========================================================================
|
|
|
|
UPROPERTY(BlueprintAssignable, Category = "Capture|Manager|Events")
|
|
FOnSurfaceRegistered OnSurfaceRegistered;
|
|
|
|
UPROPERTY(BlueprintAssignable, Category = "Capture|Manager|Events")
|
|
FOnSurfaceUnregistered OnSurfaceUnregistered;
|
|
|
|
UPROPERTY(BlueprintAssignable, Category = "Capture|Manager|Events")
|
|
FOnGlobalQualityCapChanged OnGlobalQualityCapChanged;
|
|
|
|
protected:
|
|
// ========================================================================
|
|
// Internal State
|
|
// ========================================================================
|
|
|
|
/** All registered capture surface actors. */
|
|
UPROPERTY()
|
|
TArray<TWeakObjectPtr<ABP_PlanarCaptureActor>> RegisteredSurfaces;
|
|
|
|
/** Render target pool. */
|
|
TArray<FPlanarCaptureRenderTargetEntry> RenderTargetPool;
|
|
|
|
/** Time accumulator for full re-evaluation interval. */
|
|
float TimeSinceLastEvaluation = 0.0f;
|
|
|
|
/** Force-tier override — if set, all surfaces use this tier. */
|
|
TOptional<EPlanarCaptureQualityTier> ForceTierOverride;
|
|
|
|
/** Count of surfaces at each tier (tracked for budget enforcement). */
|
|
TMap<EPlanarCaptureQualityTier, int32> TierAssignmentCounts;
|
|
|
|
// ========================================================================
|
|
// Internal Methods
|
|
// ========================================================================
|
|
|
|
/** Evaluate all registered surfaces and assign quality tiers. */
|
|
void EvaluateAllSurfaces();
|
|
|
|
/**
|
|
* Score a single surface and determine its quality tier within budget constraints.
|
|
* @return The assigned tier.
|
|
*/
|
|
EPlanarCaptureQualityTier ScoreAndAssignTier(UBPC_PlanarCapture* Capture);
|
|
|
|
/** Enforce budget limits — demote lower-priority surfaces if budget exceeded. */
|
|
void EnforceBudgetLimits();
|
|
|
|
/** Create a new render target of the given size. */
|
|
UTextureRenderTarget2D* CreateRenderTarget(int32 Size);
|
|
|
|
/** Get or create a render target for a given size (first checks pool). */
|
|
UTextureRenderTarget2D* GetOrCreateRenderTarget(int32 Size);
|
|
};
|