Files
vertical-partition-system-p…/Source/VerticalPartitionEditor/Public/VerticalPartitionBuilder.h
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

90 lines
3.9 KiB
C++

// Copyright IHY. Vertical Partition Streaming plugin (editor module).
//
// Editor-only conversion pipeline: scan -> validate -> assign -> generate
// descriptor -> generate HLOD proxies -> (optionally) bake streaming sub-levels.
#pragma once
#include "CoreMinimal.h"
#include "UObject/Object.h"
#include "VerticalPartitionTypes.h"
#include "VerticalPartitionBuilder.generated.h"
class AVerticalPartitionVolume;
class UVerticalPartitionDescriptor;
class UWorld;
class AActor;
/** One actor's analysed placement, shared between Analyze and Build. */
struct FVerticalActorAssignment
{
TWeakObjectPtr<AActor> Actor;
/** The renderable static-decor leaf actors this unit streams. For a normal actor this
* is just [Actor]; for a Level Instance it is its (recursively flattened) static child
* actors; for a Packed Level Actor it is [Actor] (its baked HISM live on it). */
TArray<TWeakObjectPtr<AActor>> LeafActors;
FVerticalCellId Cell;
FBox Bounds = FBox(ForceInit);
bool bCrossesMultiple = false;
bool bExcluded = false;
bool bLargeKeepPersistent = false;
};
UCLASS()
class UVerticalPartitionBuilder : public UObject
{
GENERATED_BODY()
public:
/** Scan the level, classify every actor, return a report without writing anything. */
static FVerticalPartitionBuildReport AnalyzeCurrentLevel(AVerticalPartitionVolume* Volume);
/** Full build: analyze -> create/refresh descriptor -> generate HLOD proxies ->
* (DestructiveCommit only) bake streaming sub-levels + remove source actors.
* Returns the report; writes the descriptor asset. */
static bool Build(AVerticalPartitionVolume* Volume, FVerticalPartitionBuildReport& OutReport);
/** Re-run only cells whose source content hash changed since the last build. */
static bool RebuildChangedCells(AVerticalPartitionVolume* Volume, FVerticalPartitionBuildReport& OutReport);
/** (Re)generate HLOD proxy meshes for all cells. */
static bool RebuildHLOD(AVerticalPartitionVolume* Volume, FVerticalPartitionBuildReport& OutReport);
/** Re-run analysis against the existing descriptor and flag drift / problems. */
static FVerticalPartitionBuildReport ValidateCells(AVerticalPartitionVolume* Volume);
/** Promote a NonDestructive descriptor to baked streaming sub-levels. */
static bool CommitConversion(AVerticalPartitionVolume* Volume, FVerticalPartitionBuildReport& OutReport);
static bool CreateBackup(UWorld* World, FString& OutBackupPath);
static bool RestoreFromBackup(UWorld* World);
/** Delete generated descriptor / cell maps / proxies under the output root. */
static void ClearGenerated(AVerticalPartitionVolume* Volume);
/** Write the report to Saved/VerticalPartition/<Map>_Report.txt and log it. */
static FString DumpReport(const FVerticalPartitionBuildReport& Report, const FString& MapName);
private:
// ---- pipeline steps ----
static void GatherActors(AVerticalPartitionVolume* Volume, const FBox& VolumeBounds,
TArray<FVerticalActorAssignment>& OutAssignments, FVerticalPartitionBuildReport& Report);
static void ClassifyActorWarnings(const FVerticalActorAssignment& A, const FVerticalPartitionSettings& S,
FVerticalPartitionBuildReport& Report);
static UVerticalPartitionDescriptor* CreateOrLoadDescriptor(AVerticalPartitionVolume* Volume);
static void BuildCells(AVerticalPartitionVolume* Volume, const FBox& VolumeBounds,
const TArray<FVerticalActorAssignment>& Assignments,
UVerticalPartitionDescriptor* Descriptor, FVerticalPartitionBuildReport& Report);
/** Generate one proxy mesh for a cell from its static-mesh actors. Returns the
* asset path or an empty path (with a warning) on failure / unavailable API. */
static FSoftObjectPath GenerateHLODProxyForCell(const FVerticalCellId& Cell,
const TArray<AActor*>& CellActors, const FVerticalPartitionSettings& S,
const FString& PackageRoot, FVerticalPartitionBuildReport& Report);
static int64 ComputeContentHash(const TArray<FVerticalActorAssignment>& Assignments);
static bool SaveAsset(UObject* Asset);
};