Files
vertical-partition-system-p…/Source/VerticalPartition/Private/VerticalPartitionDebugComponent.cpp
Bonchellon 04ad6d3f25 Initial commit: Vertical Partition Streaming plugin (UE 5.7)
Bounded vertical route partition / streaming for handcrafted spiral climb maps
(Only Up / Only Climb). Not World Partition, not Level Instances as core arch.

- Z-cell segmentation + optional XY subcells, editor builder + commandlet
- NonDestructive visibility backend + streaming-level backend
- Offline HLOD proxies: MergedMesh / SimplifiedProxy (ProxyLOD)
- Universal Level Instance + Packed Level Actor + HISM support (flatten+merge)
- Vertical-aware runtime streamer (full/preload/HLOD/unload, hysteresis,
  velocity prediction, fall-risk), WP-style debug viz + vp.* console
- Safe-by-default: only static decor streams; sky/lights/gameplay stay persistent

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 17:42:41 +03:00

115 lines
3.8 KiB
C++

// Copyright IHY. Vertical Partition Streaming plugin.
#include "VerticalPartitionDebugComponent.h"
#include "VerticalPartitionRuntimeSubsystem.h"
#include "VerticalPartitionStatics.h"
#include "Engine/Engine.h"
#include "DrawDebugHelpers.h"
static TAutoConsoleVariable<int32> CVarVPDebug(
TEXT("vp.Debug"), 0,
TEXT("Master Vertical Partition debug toggle (gates DebugDraw + DebugOverlay)."), ECVF_Default);
static TAutoConsoleVariable<int32> CVarVPDebugDraw(
TEXT("vp.DebugDraw"), 1,
TEXT("Draw 3D coloured cell boxes / ids / counts (requires vp.Debug 1)."), ECVF_Default);
static TAutoConsoleVariable<int32> CVarVPDebugOverlay(
TEXT("vp.DebugOverlay"), 1,
TEXT("Draw the on-screen runtime stats overlay (requires vp.Debug 1)."), ECVF_Default);
UVerticalPartitionDebugComponent::UVerticalPartitionDebugComponent()
{
PrimaryComponentTick.bCanEverTick = true;
PrimaryComponentTick.bStartWithTickEnabled = true;
}
UVerticalPartitionRuntimeSubsystem* UVerticalPartitionDebugComponent::GetSub() const
{
return UVerticalPartitionRuntimeSubsystem::Get(this);
}
void UVerticalPartitionDebugComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
if (CVarVPDebug.GetValueOnGameThread() == 0)
{
return;
}
UVerticalPartitionRuntimeSubsystem* Sub = GetSub();
if (!Sub || !Sub->IsReady())
{
return;
}
if (CVarVPDebugDraw.GetValueOnGameThread() != 0)
{
DrawDebugCells(Sub);
}
if (CVarVPDebugOverlay.GetValueOnGameThread() != 0)
{
DrawOverlay(Sub);
}
}
void UVerticalPartitionDebugComponent::DrawDebugCells(UVerticalPartitionRuntimeSubsystem* Sub) const
{
#if ENABLE_DRAW_DEBUG
UWorld* World = GetWorld();
if (!World || !Sub)
{
return;
}
for (const TPair<FVerticalCellId, FVerticalCellRuntime>& Pair : Sub->GetCellRuntimes())
{
const FVerticalCellRuntime& C = Pair.Value;
if (!C.Bounds.IsValid)
{
continue;
}
// Purple overrides the state colour when a cell is force-locked.
FColor Color = C.bForced
? FColor(180, 60, 220)
: UVerticalPartitionStatics::GetStateColor(C.State).ToFColor(true);
const FVector Center = C.Bounds.GetCenter();
const FVector Extent = C.Bounds.GetExtent();
DrawDebugBox(World, Center, Extent, Color, false, -1.f, 0, 4.f);
const FString Label = FString::Printf(TEXT("%s [%s] actors:%d"),
*C.Id.ToString(),
C.bForced ? TEXT("LOCK") : *UEnum::GetDisplayValueAsText(C.State).ToString(),
C.ResolvedActors.Num());
DrawDebugString(World, Center + FVector(0, 0, Extent.Z * 0.5f), Label, nullptr, Color, 0.f, true);
}
#endif // ENABLE_DRAW_DEBUG
}
void UVerticalPartitionDebugComponent::DrawOverlay(UVerticalPartitionRuntimeSubsystem* Sub) const
{
if (!GEngine || !Sub)
{
return;
}
const FVerticalRuntimeStats& S = Sub->GetStats();
const int32 Key = 0x5650; // 'VP'
auto Line = [&](int32 Slot, const FColor& Col, const FString& Text)
{
GEngine->AddOnScreenDebugMessage(Key + Slot, 0.f, Col, Text);
};
Line(0, FColor::Cyan, TEXT("==== Vertical Partition ===="));
Line(1, FColor::White, FString::Printf(TEXT("Player Z cell: %d"), S.PlayerCellZ));
Line(2, FColor::Green, FString::Printf(TEXT("Full cells: %d"), S.FullCellsLoaded));
Line(3, FColor::Blue, FString::Printf(TEXT("HLOD cells: %d"), S.HLODCellsVisible));
Line(4, FColor::Silver, FString::Printf(TEXT("Unloaded: %d"), S.CellsUnloaded));
Line(5, FColor::Yellow, FString::Printf(TEXT("Loading/async: %d / %d"), S.CellsLoading, S.ActiveAsyncLoads));
Line(6, FColor::White, FString::Printf(TEXT("Est. memory: %.1f MB"), S.EstimatedMemoryMB));
Line(7, FColor::White, FString::Printf(TEXT("Update time: %.2f ms"), S.LastUpdateTimeMS));
Line(8, S.HitchesOverThreshold > 0 ? FColor::Red : FColor::White,
FString::Printf(TEXT("Hitches: %d"), S.HitchesOverThreshold));
}