wip(unreal): VoxelForgeCore UBT module + asset adapter reproduce the standalone world
Luna, integration round 1 (BuildHost only; owner's project and assets untouched): - New runtime module VoxelForgeCore: one shim per Standalone/Core/core_sources.txt row (sources stay canonical under Standalone/), NoPCH/no unity, manifest check; VoxelForge links it (no runtime routing yet). UE link-safety audit: 18 shims, 83,843 symbol lines vs 399 Unreal-style names, 0 clashes. - Adapter (editor commandlet path) turns staged copies of the owner's DA_* assets into schema-v1 JSON; with clip_radius=3/max_clip_level=8 it reproduces all four Core hashes (0xdb2991c73215af4c, 0x8236c5edd7fc8e4f, 0x4c48fa75a543d58e, 0xbea22e76b34a4dfc) and walkability 5,642/5,642 at worker limits 1, 8 and 16. - Noted: the owner's settings asset says max clip level 6 (standalone used 8); Core uses 25 cm voxels vs the plugin runtime's 12.5 cm. Not done yet: AVoxelWorld switch and Core runtime route (round 2). Docs: CODEMAP, ARCHITECTURE, SHARED_CPP_LIBRARY_PLAN, UNREAL_INTEGRATION_REPORT. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
1 parent
a1dfc0422e
commit
29ca99af7f
32 files changed
+919
-69
No files matched your search
@@ -0,0 +1,7 @@
|
||||
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
|
||||
#define VFCORE_PRIVATE_IMPLEMENTATION 1
|
||||
#include "CoreNamespacePreamble.h"
|
||||
namespace vfcore::detail
|
||||
{
|
||||
#include "Compat/StandaloneDataAssetGlue.cpp"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
|
||||
#define VFCORE_PRIVATE_IMPLEMENTATION 1
|
||||
#include "CoreNamespacePreamble.h"
|
||||
namespace vfcore::detail
|
||||
{
|
||||
#include "Compat/UnrealPerlin.cpp"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// The public API is standard-only; this UBT boundary supplies its module export token locally.
|
||||
#ifndef DLLEXPORT
|
||||
#if defined(_WIN32)
|
||||
#define DLLEXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define DLLEXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
#endif
|
||||
#include "Core/src/VoxelForgeCore.cpp"
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
|
||||
#define VFCORE_PRIVATE_IMPLEMENTATION 1
|
||||
#include "CoreNamespacePreamble.h"
|
||||
namespace vfcore::detail
|
||||
{
|
||||
#include "Source/VoxelForge/Private/VoxelBiomeDefinition.cpp"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
|
||||
#define VFCORE_PRIVATE_IMPLEMENTATION 1
|
||||
#include "CoreNamespacePreamble.h"
|
||||
namespace vfcore::detail
|
||||
{
|
||||
#include "Source/VoxelForge/Private/VoxelCaveMorphology.cpp"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
|
||||
#define VFCORE_PRIVATE_IMPLEMENTATION 1
|
||||
#include "CoreNamespacePreamble.h"
|
||||
namespace vfcore::detail
|
||||
{
|
||||
#include "Source/VoxelForge/Private/VoxelDensityAblation.cpp"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
|
||||
#define VFCORE_PRIVATE_IMPLEMENTATION 1
|
||||
#include "CoreNamespacePreamble.h"
|
||||
namespace vfcore::detail
|
||||
{
|
||||
#include "Source/VoxelForge/Private/VoxelDensityOpStack.cpp"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
|
||||
#define VFCORE_PRIVATE_IMPLEMENTATION 1
|
||||
#include "CoreNamespacePreamble.h"
|
||||
namespace vfcore::detail
|
||||
{
|
||||
#include "Source/VoxelForge/Private/VoxelDensityProfile.cpp"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
|
||||
#define VFCORE_PRIVATE_IMPLEMENTATION 1
|
||||
#include "CoreNamespacePreamble.h"
|
||||
namespace vfcore::detail
|
||||
{
|
||||
#include "Source/VoxelForge/Private/VoxelDiffLayer.cpp"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
|
||||
#define VFCORE_PRIVATE_IMPLEMENTATION 1
|
||||
#include "CoreNamespacePreamble.h"
|
||||
namespace vfcore::detail
|
||||
{
|
||||
#include "Source/VoxelForge/Private/VoxelGenerator.cpp"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
|
||||
#define VFCORE_PRIVATE_IMPLEMENTATION 1
|
||||
#include "CoreNamespacePreamble.h"
|
||||
namespace vfcore::detail
|
||||
{
|
||||
#include "Source/VoxelForge/Private/VoxelHeightOpStack.cpp"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
|
||||
#define VFCORE_PRIVATE_IMPLEMENTATION 1
|
||||
#include "CoreNamespacePreamble.h"
|
||||
namespace vfcore::detail
|
||||
{
|
||||
#include "Source/VoxelForge/Private/VoxelMarchingCubesMesher.cpp"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
|
||||
#define VFCORE_PRIVATE_IMPLEMENTATION 1
|
||||
#include "CoreNamespacePreamble.h"
|
||||
namespace vfcore::detail
|
||||
{
|
||||
#include "Source/VoxelForge/Private/VoxelSettings.cpp"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
|
||||
#define VFCORE_PRIVATE_IMPLEMENTATION 1
|
||||
#include "CoreNamespacePreamble.h"
|
||||
namespace vfcore::detail
|
||||
{
|
||||
#include "Source/VoxelForge/Private/VoxelStrateComposer.cpp"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
|
||||
#define VFCORE_PRIVATE_IMPLEMENTATION 1
|
||||
#include "CoreNamespacePreamble.h"
|
||||
namespace vfcore::detail
|
||||
{
|
||||
#include "Source/VoxelForge/Private/VoxelStrateManager.cpp"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
|
||||
#define VFCORE_PRIVATE_IMPLEMENTATION 1
|
||||
#include "CoreNamespacePreamble.h"
|
||||
namespace vfcore::detail
|
||||
{
|
||||
#include "Source/VoxelForge/Private/VoxelStrateMeasure.cpp"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
|
||||
#define VFCORE_PRIVATE_IMPLEMENTATION 1
|
||||
#include "CoreNamespacePreamble.h"
|
||||
namespace vfcore::detail
|
||||
{
|
||||
#include "Source/VoxelForge/Private/VoxelTerrainOpDefinition.cpp"
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// Private implementation symbols stay internal to the Core module. Les symboles restent internes.
|
||||
#define VFCORE_PRIVATE_IMPLEMENTATION 1
|
||||
#include "CoreNamespacePreamble.h"
|
||||
namespace vfcore::detail
|
||||
{
|
||||
#include "Source/VoxelForge/Private/VoxelWormField.cpp"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
// The module entry must see UE's real CoreMinimal; the Core shims intentionally use Compat/CoreMinimal.
|
||||
#ifndef VFCORE_ENGINE_COREMINIMAL_HEADER
|
||||
#error VoxelForgeCore must provide the engine CoreMinimal header path for its module entry.
|
||||
#endif
|
||||
#include VFCORE_ENGINE_COREMINIMAL_HEADER
|
||||
@@ -0,0 +1,6 @@
|
||||
// Core module entry point. Le module garde ses wrappers Core isolés du PCH Unreal.
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "ModuleManager.h"
|
||||
|
||||
IMPLEMENT_MODULE(FDefaultModuleImpl, VoxelForgeCore)
|
||||
@@ -0,0 +1,132 @@
|
||||
// VoxelForgeCore compiles the canonical Standalone sources in isolated, one-source shims.
|
||||
// Le module compile les sources canoniques Standalone via des wrappers isolés.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class VoxelForgeCore : ModuleRules
|
||||
{
|
||||
public VoxelForgeCore(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
string PluginRoot = Path.GetFullPath(Path.Combine(ModuleDirectory, "..", ".."));
|
||||
string StandaloneRoot = Path.Combine(PluginRoot, "Standalone");
|
||||
string ManifestPath = Path.Combine(StandaloneRoot, "Core", "core_sources.txt");
|
||||
string ShimRoot = Path.Combine(ModuleDirectory, "Private", "Manifest");
|
||||
string CoreMinimalHeader = Path.Combine(
|
||||
EngineDirectory, "Source", "Runtime", "Core", "Public", "CoreMinimal.h").Replace('\\', '/');
|
||||
|
||||
ValidateManifest(ManifestPath, ShimRoot, StandaloneRoot);
|
||||
|
||||
PublicIncludePaths.Add(Path.Combine(StandaloneRoot, "Core", "include"));
|
||||
PrivateIncludePaths.AddRange(new string[]
|
||||
{
|
||||
StandaloneRoot,
|
||||
Path.Combine(EngineDirectory, "Source", "Runtime", "Core", "Public", "Modules"),
|
||||
Path.Combine(StandaloneRoot, "Core", "src"),
|
||||
Path.Combine(StandaloneRoot, "Compat"),
|
||||
Path.Combine(StandaloneRoot, "Source"),
|
||||
Path.Combine(StandaloneRoot, "Source", "VoxelForge", "Public"),
|
||||
Path.Combine(StandaloneRoot, "Source", "VoxelForge", "Private")
|
||||
});
|
||||
PrivateDefinitions.Add("VFCORE_ENGINE_COREMINIMAL_HEADER=\"" + CoreMinimalHeader + "\"");
|
||||
PrivateDefinitions.Add("UE_BUILD_SHIPPING=" + (Target.Configuration == UnrealTargetConfiguration.Shipping ? "1" : "0"));
|
||||
// The wrapped VoxelForge sources use the standalone compatibility layer, which excludes editor-only fields.
|
||||
PrivateDefinitions.Add("WITH_EDITORONLY_DATA=0");
|
||||
|
||||
PublicDependencyModuleNames.Add("Core");
|
||||
CppStandard = CppStandardVersion.Cpp20;
|
||||
// Canonical Standalone code predates UE's stricter warning defaults; keep this narrow to legal local shadowing.
|
||||
CppCompileWarningSettings.ShadowVariableWarningLevel = WarningLevel.Off;
|
||||
FPSemantics = FPSemanticsMode.Precise;
|
||||
PCHUsage = PCHUsageMode.NoPCHs;
|
||||
bUseUnity = false;
|
||||
bEnableExceptions = true;
|
||||
bUseRTTI = true;
|
||||
}
|
||||
|
||||
private static void ValidateManifest(string ManifestPath, string ShimRoot, string StandaloneRoot)
|
||||
{
|
||||
if (!File.Exists(ManifestPath))
|
||||
{
|
||||
throw new BuildException("VoxelForgeCore source manifest is missing: {0}", ManifestPath);
|
||||
}
|
||||
|
||||
string Root = Path.GetFullPath(StandaloneRoot) + Path.DirectorySeparatorChar;
|
||||
string[] Sources = File.ReadAllLines(ManifestPath)
|
||||
.Select(Line => Line.Trim().Replace('\\', '/'))
|
||||
.Where(Line => Line.Length != 0 && !Line.StartsWith("#", StringComparison.Ordinal))
|
||||
.ToArray();
|
||||
if (Sources.Length == 0)
|
||||
{
|
||||
throw new BuildException("VoxelForgeCore source manifest is empty: {0}", ManifestPath);
|
||||
}
|
||||
|
||||
if (Sources.Distinct(StringComparer.Ordinal).Count() != Sources.Length)
|
||||
{
|
||||
throw new BuildException("VoxelForgeCore source manifest contains duplicate rows: {0}", ManifestPath);
|
||||
}
|
||||
|
||||
if (!Directory.Exists(ShimRoot))
|
||||
{
|
||||
throw new BuildException("VoxelForgeCore manifest shim directory is missing: {0}", ShimRoot);
|
||||
}
|
||||
|
||||
HashSet<string> ExpectedShimNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
foreach (string Source in Sources)
|
||||
{
|
||||
if (Path.IsPathRooted(Source) || Source.Split('/').Any(Part => Part == ".."))
|
||||
{
|
||||
throw new BuildException("VoxelForgeCore manifest path escapes Standalone: {0}", Source);
|
||||
}
|
||||
|
||||
string CanonicalPath = Path.GetFullPath(Path.Combine(StandaloneRoot, Source.Replace('/', Path.DirectorySeparatorChar)));
|
||||
if (!CanonicalPath.StartsWith(Root, StringComparison.OrdinalIgnoreCase) || !File.Exists(CanonicalPath))
|
||||
{
|
||||
throw new BuildException("VoxelForgeCore canonical source is missing or outside Standalone: {0}", Source);
|
||||
}
|
||||
|
||||
string ShimName = "VFCore_" + Regex.Replace(Source, "[^A-Za-z0-9]+", "_") + ".cpp";
|
||||
ExpectedShimNames.Add(ShimName);
|
||||
string ShimPath = Path.Combine(ShimRoot, ShimName);
|
||||
if (!File.Exists(ShimPath))
|
||||
{
|
||||
throw new BuildException("VoxelForgeCore manifest row has no shim: {0} -> {1}", Source, ShimPath);
|
||||
}
|
||||
|
||||
string Shim = File.ReadAllText(ShimPath);
|
||||
string EscapedSource = Regex.Escape(Source);
|
||||
if (Regex.Matches(Shim, "(?m)^\\s*#include\\s+\"" + EscapedSource + "\"\\s*$").Count != 1)
|
||||
{
|
||||
throw new BuildException("VoxelForgeCore shim must include its canonical manifest source exactly once: {0}", ShimPath);
|
||||
}
|
||||
|
||||
bool IsApiBoundary = String.Equals(Source, "Core/src/VoxelForgeCore.cpp", StringComparison.Ordinal);
|
||||
if (IsApiBoundary)
|
||||
{
|
||||
if (Regex.Matches(Shim, "(?m)^\\s*#include\\s+\"").Count != 1)
|
||||
{
|
||||
throw new BuildException("VoxelForgeCore API boundary shim must include only its canonical source: {0}", ShimPath);
|
||||
}
|
||||
}
|
||||
else if (!Regex.IsMatch(Shim, "(?s)#include\\s+\"CoreNamespacePreamble\\.h\".*namespace\\s+vfcore::detail\\s*\\{.*#include\\s+\"" + EscapedSource + "\""))
|
||||
{
|
||||
throw new BuildException("VoxelForgeCore implementation shim must preload headers and wrap its source in vfcore::detail: {0}", ShimPath);
|
||||
}
|
||||
}
|
||||
|
||||
string[] ActualShims = Directory.GetFiles(ShimRoot, "*.cpp", SearchOption.TopDirectoryOnly)
|
||||
.Select(Path.GetFileName)
|
||||
.ToArray();
|
||||
if (ActualShims.Length != ExpectedShimNames.Count
|
||||
|| ActualShims.Any(Name => !ExpectedShimNames.Contains(Name)))
|
||||
{
|
||||
throw new BuildException(
|
||||
"VoxelForgeCore shims and Core/core_sources.txt differ. Expected {0} shims under {1}; found {2}.",
|
||||
ExpectedShimNames.Count, ShimRoot, ActualShims.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user