# 138 — Planar Capture Manager Subsystem (`SS_PlanarCaptureManager`)

## Purpose
Global budget manager for all planar capture surfaces in the world. One instance per World (World Subsystem). Scores every registered surface each frame and assigns quality tiers to stay within configurable budget limits. Owns the shared render target pool.

## Dependencies
- **Requires:** `BP_PlanarCaptureActor` (137) for surface registration, `BPC_PlanarCapture` (136) for tier assignment
- **Required By:** All capture surfaces in the world
- **Engine/Plugin Requirements:** WorldSubsystem (auto-created)

## Class Info
| Property | Value |
|----------|-------|
| **Parent Class** | `WorldSubsystem` (C++ `USS_PlanarCaptureManager`, also implements `FTickableGameObject` for per-frame evaluation) |
| **Class Type** | World Subsystem |
| **Asset Path** | N/A (auto-created by engine) |
| **C++ Header** | `Source/PG_Framework/Public/Capture/SS_PlanarCaptureManager.h` |
| **C++ Status** | ✅ Full Implementation |
| **BP Asset** | None — engine auto-creates |

## 1. Variables

### Configuration (Budget)
| Variable | Type | Default | Description |
|----------|------|---------|-------------|
| `GlobalQualityCap` | EPlanarCaptureQualityTier | High | Max quality tier for any surface |
| `MaxHeroSurfaces` | int32 | 1 | Max simultaneous Hero-tier captures |
| `MaxHighSurfaces` | int32 | 3 | Max simultaneous High-tier captures |
| `MaxMediumSurfaces` | int32 | 6 | Max simultaneous Medium-tier captures |
| `MaxTotalRenderTargetMemoryMB` | float | 128.0 | Total RT memory budget |
| `MaxCaptureDistance` | float | 10000.0 | Distance at which surface goes Off |
| `FullEvaluationInterval` | float | 0.5 | Seconds between full re-evaluation |

## 2. Functions

#### `RegisterSurface(Surface: ABP_PlanarCaptureActor*)`
- **Description:** Register a surface with the manager. Called by BP_PlanarCaptureActor.BeginPlay.
- **Flow:** Check duplicates → Add to RegisteredSurfaces → Log → Broadcast OnSurfaceRegistered → EvaluateAllSurfaces

#### `UnregisterSurface(Surface: ABP_PlanarCaptureActor*)`
- **Description:** Remove a surface. Called on EndPlay.
- **Flow:** Remove from RegisteredSurfaces → Log → Broadcast OnSurfaceUnregistered

#### `RequestRenderTarget(Size: int32)` → `UTextureRenderTarget2D*`
- **Description:** Get a render target from the pool (or allocate new). Returns nullptr if pool exhausted.
- **Flow:** Check pool for matching size + not in use → If found, mark in use → If not, CreateRenderTarget

#### `ReleaseRenderTarget(RT: UTextureRenderTarget2D*)`
- **Description:** Return a render target to the pool. Marks as free for reuse.

#### `ForceAllSurfacesToTier(Tier: EPlanarCaptureQualityTier)`
- **Description:** Override all surfaces to a specific tier (e.g., Hero during a cutscene mirror moment).

#### `ReleaseForceTier()`
- **Description:** Remove force override, resume normal scoring.

#### `GetNearestSurfaceOfMode(Mode, Location, MaxDistance)` → `ABP_PlanarCaptureActor*`
- **Description:** Find nearest surface of a given mode (e.g., find nearest portal for teleport).

## 3. Event Dispatchers
| Dispatcher | Parameters | Description |
|------------|-----------|-------------|
| `OnSurfaceRegistered` | Surface, TotalSurfaces | Surface added |
| `OnSurfaceUnregistered` | Surface, TotalSurfaces | Surface removed |
| `OnGlobalQualityCapChanged` | NewCap | Quality cap changed |

## 4. Scoring Algorithm (Internal)
```
CompositeScore = (ScreenCoverage × 0.5) + (FacingAngle × 0.3) + (DistanceFactor × 0.1) + (ScriptedPriority × 0.1)

Tier: Score ≥ 0.8 → Hero | ≥ 0.5 → High | ≥ 0.2 → Medium | > 0 → Low | 0 → Off
Budget enforcement: demote if tier count exceeds Max*Surfaces limits
Apply GlobalQualityCap: clamp tier to cap
```

## 5. Communication Matrix
| Target System | Method | What |
|---------------|--------|------|
| `BP_PlanarCaptureActor` | Direct (registry) | Surface tracking |
| `BPC_PlanarCapture` | Direct (ApplyQualityTier) | Tier assignment |
| `UTextureRenderTarget2D` | Direct (create/release) | RT pool management |
| Player Camera Manager | UGameplayStatics (indirect via Capture) | View transform for scoring |

## 6. Manual Implementation Guide

*No Blueprint implementation needed — the C++ subsystem auto-creates per world.*

### 6.1 Budget Tuning
Adjust the following in `Project Settings → Plugins → PG_Framework → Planar Capture` (or via Config in DefaultEngine.ini):
- **High-end GPU (RTX 4080+):** MaxHeroSurfaces=2, MaxHighSurfaces=5
- **Mid-range (RTX 3060):** MaxHeroSurfaces=1, MaxHighSurfaces=3
- **Console (PS5/Xbox):** MaxHeroSurfaces=1, MaxHighSurfaces=2, GlobalQualityCap=High
- **Low-end (Steam Deck):** MaxHeroSurfaces=0, MaxHighSurfaces=1, GlobalQualityCap=Medium

### 6.2 Debug Commands
```
SS_PlanarCaptureManager.GetSurfaceCount()       → Blueprint: print count
SS_PlanarCaptureManager.GetPoolMemoryUsageMB()   → Blueprint: print memory
ForceAllSurfacesToTier(Hero)                     → test all at max quality
ReleaseForceTier()                                → resume normal scoring
```

## 7. Build Checklist
- [ ] C++ subsystem compiles
- [ ] Auto-creates per world (no manual creation needed)
- [ ] Budget limits tested with multiple surfaces
- [ ] RT pool reuses targets (not leaking)
- [ ] Force tier override works for cutscenes
