ue-mcp-plugin-voxel-plugin 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,21 +2,53 @@
2
2
 
3
3
  [Voxel Plugin](https://voxelplugin.com) actions for [ue-mcp](https://github.com/db-lyon/ue-mcp).
4
4
 
5
- ## Status
5
+ ## What ships
6
6
 
7
- **v0.1.1 ships no actions.** The `0.1.0` release injected three placeholder
8
- actions (`voxel_scatter_meshes`, `voxel_spawn_stamps`, `voxel_bake_heightmap`)
9
- that called ue-mcp tasks with wrong parameter names and passed PCG node-type
10
- strings that do not exist. They have been removed rather than left as broken
11
- surface.
7
+ Each action is cited to the C++ header it wraps. Full API reference under [`docs/`](docs/).
12
8
 
13
- Real tools, grounded in the actual Voxel Plugin C++ API, are tracked in
14
- [`TODO.md`](TODO.md). Every entry there cites the header file and class it
15
- wraps.
9
+ | Category | Action | Wraps |
10
+ |----------|---------------------------------|-------|
11
+ | `pcg` | `voxel_build_scatter_graph` | `UPCGVoxelSamplerSettings` (`VoxelPCG/Public/PCGVoxelSampler.h`) feeding `UPCGStaticMeshSpawnerSettings` |
12
+ | `level` | `voxel_get_voxel_world_status` | 5 zero-arg lifecycle UFUNCTIONs on `AVoxelWorld` (`Voxel/Public/VoxelWorld.h`) |
16
13
 
17
- Do not depend on this package yet it intentionally exposes nothing.
14
+ The v0.1.0 release shipped three actions that called ue-mcp tasks with wrong parameter names and passed PCG node-type strings that did not exist; v0.1.1 removed them.
18
15
 
19
- ## Requirements (for future versions)
16
+ ## Install
17
+
18
+ ```bash
19
+ ue-mcp plugin install ue-mcp-plugin-voxel-plugin
20
+ ```
21
+
22
+ The CLI adds an entry under `plugins:` in your `ue-mcp.yml`. Restart ue-mcp; the injected action shows up under `pcg`.
23
+
24
+ ## Usage
25
+
26
+ ```text
27
+ pcg(action="voxel_build_scatter_graph",
28
+ assetPath="/Game/PCG/RockScatter",
29
+ meshes=[
30
+ {mesh: "/Game/Foliage/Rock_A.Rock_A", weight: 2},
31
+ {mesh: "/Game/Foliage/Rock_B.Rock_B"}
32
+ ],
33
+ pointsPerSquaredMeter=0.05,
34
+ seed=42)
35
+ ```
36
+
37
+ The call creates a `UPCGGraph` at `assetPath`, adds a Voxel Sampler → Static Mesh Spawner pipeline, and populates the weighted mesh table. Attach the resulting graph to a PCG component on or near your `AVoxelWorld`, then:
38
+
39
+ ```text
40
+ pcg(action="execute", actorLabel="MyPCGActor")
41
+ ```
42
+
43
+ Check the voxel world is actually live before scattering / stamping into it:
44
+
45
+ ```text
46
+ level(action="voxel_get_voxel_world_status", actorLabel="MyVoxelWorld")
47
+ ```
48
+
49
+ Returns `{ isRuntimeCreated, isVoxelWorldReady, isProcessingNewState, progress, numPendingTasks }`. The runtime can be mid-regeneration even after `IsRuntimeCreated` flips true — wait for `isVoxelWorldReady && !isProcessingNewState` before pipelines that depend on stable terrain.
50
+
51
+ ## Requirements
20
52
 
21
53
  - ue-mcp `>= 1.0.15`
22
54
  - Voxel Plugin enabled in your `.uproject` (`Plugins[].Name == "Voxel"`)
@@ -0,0 +1,29 @@
1
+ import { BaseTask, type TaskResult } from "@db-lyon/flowkit";
2
+ interface MeshEntry {
3
+ mesh: string;
4
+ weight?: number;
5
+ }
6
+ interface Options {
7
+ assetPath: string;
8
+ meshes: MeshEntry[];
9
+ pointsPerSquaredMeter?: number;
10
+ seed?: number;
11
+ }
12
+ /**
13
+ * Build a PCG graph that scatters weighted static meshes on a voxel terrain.
14
+ *
15
+ * Wraps `UPCGVoxelSamplerSettings` (VoxelPCG/Public/PCGVoxelSampler.h) feeding
16
+ * `UPCGStaticMeshSpawnerSettings`. The output asset is a UPCGGraph that the
17
+ * caller attaches to a PCG component (typically on or near an AVoxelWorld)
18
+ * before calling `pcg.execute`.
19
+ *
20
+ * Layer wiring (FVoxelStackLayer struct) is intentionally not exposed in v1.
21
+ * The sampler defaults to the UE-side default stack/layer, which is what an
22
+ * out-of-the-box voxel world uses.
23
+ */
24
+ export default class BuildScatterGraph extends BaseTask<Options> {
25
+ get taskName(): string;
26
+ protected validate(): void;
27
+ execute(): Promise<TaskResult>;
28
+ }
29
+ export {};
@@ -0,0 +1,102 @@
1
+ import { BaseTask } from "@db-lyon/flowkit";
2
+ /**
3
+ * Build a PCG graph that scatters weighted static meshes on a voxel terrain.
4
+ *
5
+ * Wraps `UPCGVoxelSamplerSettings` (VoxelPCG/Public/PCGVoxelSampler.h) feeding
6
+ * `UPCGStaticMeshSpawnerSettings`. The output asset is a UPCGGraph that the
7
+ * caller attaches to a PCG component (typically on or near an AVoxelWorld)
8
+ * before calling `pcg.execute`.
9
+ *
10
+ * Layer wiring (FVoxelStackLayer struct) is intentionally not exposed in v1.
11
+ * The sampler defaults to the UE-side default stack/layer, which is what an
12
+ * out-of-the-box voxel world uses.
13
+ */
14
+ export default class BuildScatterGraph extends BaseTask {
15
+ get taskName() { return "voxel.build_scatter_graph"; }
16
+ validate() {
17
+ if (!this.options.assetPath)
18
+ throw new Error("assetPath is required");
19
+ if (!Array.isArray(this.options.meshes) || this.options.meshes.length === 0) {
20
+ throw new Error("meshes must be a non-empty array of { mesh, weight? } entries");
21
+ }
22
+ for (const m of this.options.meshes) {
23
+ if (!m?.mesh)
24
+ throw new Error("each meshes[] entry must include a `mesh` asset path");
25
+ }
26
+ }
27
+ async execute() {
28
+ const { assetPath, meshes, pointsPerSquaredMeter = 0.1, seed = 1 } = this.options;
29
+ const slash = assetPath.lastIndexOf("/");
30
+ if (slash <= 0) {
31
+ return { success: false, error: new Error(`assetPath must be a content path like /Game/Folder/Name, got: ${assetPath}`) };
32
+ }
33
+ const packagePath = assetPath.slice(0, slash);
34
+ const name = assetPath.slice(slash + 1);
35
+ const create = await this.call("pcg.create_graph", { name, packagePath });
36
+ if (!create.success) {
37
+ // Re-running over an existing graph is a supported workflow; only abort
38
+ // on hard failures, not on the "asset already exists" path.
39
+ const msg = create.error?.message ?? "";
40
+ if (!/exist|already/i.test(msg))
41
+ return create;
42
+ }
43
+ // Bridge's nodeType resolver only falls back to /Script/PCG.* — for
44
+ // VoxelPCG classes we pass the absolute object path so the first
45
+ // FindObject lookup hits.
46
+ const samplerR = await this.call("pcg.add_node", {
47
+ assetPath,
48
+ nodeType: "/Script/VoxelPCG.PCGVoxelSamplerSettings",
49
+ });
50
+ if (!samplerR.success)
51
+ return samplerR;
52
+ const samplerName = samplerR.data?.nodeName;
53
+ if (!samplerName)
54
+ return { success: false, error: new Error("pcg.add_node sampler returned no nodeName") };
55
+ const spawnerR = await this.call("pcg.add_node", {
56
+ assetPath,
57
+ nodeType: "/Script/PCG.PCGStaticMeshSpawnerSettings",
58
+ });
59
+ if (!spawnerR.success)
60
+ return spawnerR;
61
+ const spawnerName = spawnerR.data?.nodeName;
62
+ if (!spawnerName)
63
+ return { success: false, error: new Error("pcg.add_node spawner returned no nodeName") };
64
+ const settingsR = await this.call("pcg.set_node_settings", {
65
+ assetPath,
66
+ nodeName: samplerName,
67
+ settings: {
68
+ PointsPerSquaredMeter: pointsPerSquaredMeter,
69
+ Seed: seed,
70
+ },
71
+ });
72
+ if (!settingsR.success)
73
+ return settingsR;
74
+ const connectR = await this.call("pcg.connect_nodes", {
75
+ assetPath,
76
+ sourceNode: samplerName,
77
+ targetNode: spawnerName,
78
+ });
79
+ if (!connectR.success)
80
+ return connectR;
81
+ const meshesR = await this.call("pcg.set_static_mesh_spawner_meshes", {
82
+ assetPath,
83
+ nodeName: spawnerName,
84
+ entries: meshes,
85
+ replace: true,
86
+ });
87
+ if (!meshesR.success)
88
+ return meshesR;
89
+ return {
90
+ success: true,
91
+ data: {
92
+ assetPath,
93
+ samplerNode: samplerName,
94
+ spawnerNode: spawnerName,
95
+ meshCount: meshes.length,
96
+ pointsPerSquaredMeter,
97
+ seed,
98
+ },
99
+ };
100
+ }
101
+ }
102
+ //# sourceMappingURL=BuildScatterGraph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BuildScatterGraph.js","sourceRoot":"","sources":["../../src/tasks/BuildScatterGraph.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { BaseTask, type TaskResult } from "@db-lyon/flowkit";
2
+ interface Options {
3
+ actorLabel: string;
4
+ world?: "editor" | "pie";
5
+ }
6
+ /**
7
+ * One-call snapshot of an `AVoxelWorld`'s lifecycle state.
8
+ *
9
+ * Composes 5x `editor.invoke_function` against the zero-arg lifecycle
10
+ * UFUNCTIONs on `AVoxelWorld` (`Voxel/Public/VoxelWorld.h`):
11
+ *
12
+ * bool IsRuntimeCreated()
13
+ * bool IsVoxelWorldReady()
14
+ * bool IsProcessingNewState()
15
+ * float GetProgress()
16
+ * int32 GetNumPendingTasks()
17
+ *
18
+ * Use it before any operation that requires the voxel runtime to be live —
19
+ * scattering meshes / placing stamps into a half-built world produces empty
20
+ * or stale output. The five calls fan out in parallel.
21
+ */
22
+ export default class GetWorldStatus extends BaseTask<Options> {
23
+ get taskName(): string;
24
+ protected validate(): void;
25
+ execute(): Promise<TaskResult>;
26
+ }
27
+ export {};
@@ -0,0 +1,57 @@
1
+ import { BaseTask } from "@db-lyon/flowkit";
2
+ /**
3
+ * One-call snapshot of an `AVoxelWorld`'s lifecycle state.
4
+ *
5
+ * Composes 5x `editor.invoke_function` against the zero-arg lifecycle
6
+ * UFUNCTIONs on `AVoxelWorld` (`Voxel/Public/VoxelWorld.h`):
7
+ *
8
+ * bool IsRuntimeCreated()
9
+ * bool IsVoxelWorldReady()
10
+ * bool IsProcessingNewState()
11
+ * float GetProgress()
12
+ * int32 GetNumPendingTasks()
13
+ *
14
+ * Use it before any operation that requires the voxel runtime to be live —
15
+ * scattering meshes / placing stamps into a half-built world produces empty
16
+ * or stale output. The five calls fan out in parallel.
17
+ */
18
+ export default class GetWorldStatus extends BaseTask {
19
+ get taskName() { return "voxel.get_world_status"; }
20
+ validate() {
21
+ if (!this.options.actorLabel)
22
+ throw new Error("actorLabel is required");
23
+ }
24
+ async execute() {
25
+ const { actorLabel, world } = this.options;
26
+ const baseParams = { actorLabel };
27
+ if (world)
28
+ baseParams.world = world;
29
+ const fns = [
30
+ "IsRuntimeCreated",
31
+ "IsVoxelWorldReady",
32
+ "IsProcessingNewState",
33
+ "GetProgress",
34
+ "GetNumPendingTasks",
35
+ ];
36
+ const results = await Promise.all(fns.map(functionName => this.call("editor.invoke_function", { ...baseParams, functionName })));
37
+ for (let i = 0; i < results.length; i++) {
38
+ if (!results[i].success)
39
+ return results[i];
40
+ }
41
+ const ret = (r) => r.data?.returnValues?.ReturnValue;
42
+ const asBool = (s) => s === "true" || s === "True";
43
+ const asNum = (s) => (s == null ? NaN : Number(s));
44
+ return {
45
+ success: true,
46
+ data: {
47
+ actorLabel,
48
+ isRuntimeCreated: asBool(ret(results[0])),
49
+ isVoxelWorldReady: asBool(ret(results[1])),
50
+ isProcessingNewState: asBool(ret(results[2])),
51
+ progress: asNum(ret(results[3])),
52
+ numPendingTasks: asNum(ret(results[4])),
53
+ },
54
+ };
55
+ }
56
+ }
57
+ //# sourceMappingURL=GetWorldStatus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GetWorldStatus.js","sourceRoot":"","sources":["../../src/tasks/GetWorldStatus.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAmB,MAAM,kBAAkB,CAAC;AAW7D;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,QAAiB;IAC3D,IAAI,QAAQ,KAAa,OAAO,wBAAwB,CAAC,CAAC,CAAC;IAEjD,QAAQ;QAChB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU;YAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC1E,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;QAC3C,MAAM,UAAU,GAA4B,EAAE,UAAU,EAAE,CAAC;QAC3D,IAAI,KAAK;YAAE,UAAU,CAAC,KAAK,GAAG,KAAK,CAAC;QAEpC,MAAM,GAAG,GAAG;YACV,kBAAkB;YAClB,mBAAmB;YACnB,sBAAsB;YACtB,aAAa;YACb,oBAAoB;SACZ,CAAC;QAEX,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CACrB,IAAI,CAAC,IAAI,CAAC,wBAAwB,EAAE,EAAE,GAAG,UAAU,EAAE,YAAY,EAAE,CAAC,CACrE,CACF,CAAC;QAEF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO;gBAAE,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC;QAC7C,CAAC;QAED,MAAM,GAAG,GAAG,CAAC,CAAa,EAAsB,EAAE,CAC/C,CAAC,CAAC,IAA+B,EAAE,YAAY,EAAE,WAAW,CAAC;QAChE,MAAM,MAAM,GAAG,CAAC,CAAqB,EAAW,EAAE,CAAC,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,MAAM,CAAC;QAChF,MAAM,KAAK,GAAG,CAAC,CAAqB,EAAU,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAE/E,OAAO;YACL,OAAO,EAAE,IAAI;YACb,IAAI,EAAE;gBACJ,UAAU;gBACV,gBAAgB,EAAM,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC7C,iBAAiB,EAAK,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC7C,oBAAoB,EAAE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC7C,QAAQ,EAAc,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC5C,eAAe,EAAO,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;aAC7C;SACF,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,107 @@
1
+ # Voxel Plugin — Module Map
2
+
3
+ The plugin ships **twelve modules** plus a UHT (UnrealHeaderTool) extension. Every module funnels through a single `VoxelGlobalMethods.SetupVoxelModule` shim defined in `VoxelCore/VoxelCore.Build.cs`, which standardizes C++20, IWYU=None, unity builds, the shared PCH (`VoxelPCH.h` for runtime, `VoxelCoreEditorPCH.h` for editor), and `FPSemanticsMode.Precise` (so PCG point output is identical on client and server).
4
+
5
+ ## Module list
6
+
7
+ | Module | Type | Loading phase | Public headers? | Role |
8
+ |---|---|---|---|---|
9
+ | `VoxelCore` | Runtime | `PostConfigInit` | yes | Foundational containers, math, threading, messaging, ISPC bridge, dependency tracking. No voxel concepts. |
10
+ | `VoxelCoreEditor` | Editor | `Default` | yes | Slate widgets, detail customizations, asset wizards used by every other editor module. |
11
+ | `VoxelGraph` | Runtime | `Default` | yes | Visual-graph asset, compilation pipeline, typed buffers, function-library nodes. |
12
+ | `VoxelGraphEditor` | Editor | `Default` | yes | Graph editor UI, node panels, preview viewport, message log. |
13
+ | `Voxel` | Runtime | `PostConfigInit` | yes | The gameplay-facing module: `AVoxelWorld`, stamps, layers, mega-material, render/collision/navigation, sculpt/spline/shape/scatter. |
14
+ | `VoxelEditor` | Editor | `Default` | yes | World/stamp/layer detail panels, interactive sculpt tools, placement mode integration. |
15
+ | `VoxelBlueprint` | UncookedOnly | `PostConfigInit` | yes | Kismet (BP) K2 nodes that expose voxel-graph parameters and the make/break pin-value flow. Editor-time only. |
16
+ | `VoxelBlueprintEditor` | Editor | `Default` | no (private only) | Slate pieces specific to the BP K2 nodes. |
17
+ | `VoxelPCG` | Runtime | `Default` | yes | Bridge to Epic's PCG framework. PCG nodes that read/write voxel state plus voxel-graph nodes that operate on point sets. |
18
+ | `VoxelPCGEditor` | Editor | `Default` | no (private only) | PCG node UI/customizations. |
19
+ | `VoxelTests` | Runtime | `Default` | no | Automation tests; include-correctness checks when `VoxelDevWorkflow.txt` is present. |
20
+ | `VoxelUHT` | UBT plugin | n/a | n/a | Custom UnrealHeaderTool exporter (`*.generated.voxel.cpp`) that codegens function-library wrappers around `UVoxelFunctionLibrary` and `FVoxelRuntimePinValue`. |
21
+
22
+ `UncookedOnly` means `VoxelBlueprint` is built into editor/uncooked targets only — it ships nothing in packaged builds, because BP K2 node classes only exist to extend the Kismet compiler.
23
+
24
+ ## Loading phases
25
+
26
+ Two modules load at `PostConfigInit` (very early, before most engine systems):
27
+
28
+ - `VoxelCore` — needed early so `FVoxelMessageManager`, the `FVoxelDeveloperSettings` CDO, and the ISPC runtime are available before subsystems initialize.
29
+ - `Voxel` — needs early load so `AVoxelWorld` subsystems can register themselves before the world begins streaming.
30
+
31
+ `VoxelBlueprint` also loads `PostConfigInit` (but as `UncookedOnly`) so its K2 node factories are registered before the Blueprint editor opens any assets.
32
+
33
+ Everything else loads at the `Default` phase.
34
+
35
+ ## Dependency graph
36
+
37
+ ```
38
+ VoxelCore ←─────────────────────────┐
39
+ ▲ │
40
+ ┌───────────────┼───────────────┐ │
41
+ │ │ │ │
42
+ VoxelGraph Voxel VoxelPCG ───→ Voxel + VoxelGraph
43
+ ▲ ▲ ▲ │
44
+ │ │ │ │
45
+ │ │ │ │
46
+ VoxelGraphEditor VoxelEditor VoxelPCGEditor │
47
+ ▲ │
48
+ │ │
49
+ VoxelBlueprint ──→ Voxel + VoxelGraph + VoxelEditor + VoxelGraphEditor + VoxelCoreEditor
50
+
51
+
52
+ VoxelBlueprintEditor
53
+ ```
54
+
55
+ (Arrow direction: A → B means A depends on B.)
56
+
57
+ Concrete declarations from the `*.Build.cs` files:
58
+
59
+ - `VoxelCore` adds engine deps `Chaos`, `Renderer`, `Projects`, `ApplicationCore`, `TraceLog`. Private deps include `zlib`, `UElibPNG`, `Json`, `HTTP`, `Landscape`, `EventLoop`, `MoviePlayer`. Editor builds pull in `MaterialEditor`, `UATHelper`, `GraphEditor`, `DesktopPlatform`.
60
+ - `Voxel` depends on `VoxelGraph`, plus `Chaos`, `Renderer`, `PhysicsCore`, `Landscape`, `NavigationSystem`, `PCG`, `MeshDescription`, `StaticMeshDescription`.
61
+ - `VoxelGraph` depends only on the standard set plus `TraceLog`, `Chaos`, `PhysicsCore`, `Json` (and `MessageLog` in editor).
62
+ - `VoxelPCG` depends on `Voxel`, `VoxelGraph`, `PCG`.
63
+ - `VoxelBlueprint` depends on `VoxelCoreEditor`, `Voxel`, `VoxelEditor`, `VoxelGraph`, `VoxelGraphEditor`, plus `BlueprintGraph` and `KismetCompiler` for K2 node integration.
64
+ - `VoxelEditor` is the heaviest editor module — it depends on `Voxel`, `VoxelPCG`, `VoxelGraph`, `VoxelGraphEditor`, plus the full editor surface (`LevelEditor`, `AssetTools`, `PlacementMode`, `InteractiveToolsFramework`, `SceneOutliner`, `DetailCustomizations`, etc.).
65
+ - `VoxelTests` depends only on `Json` and `NavigationSystem`.
66
+
67
+ ## ISPC and the build script
68
+
69
+ `VoxelCore.Build.cs` defines `VoxelISPCCompiler`, which scans every module's `Source/<Module>/**.ispc` and `**.isph` files and generates a per-platform build script (`Intermediate/ISPC/<Platform>/<Arch>/<Editor>/<Config>/Build.ps1` or `Build.sh`). On Windows it downloads the same ISPC binary Unreal uses (`UnrealEngine-28863921/...`) if the engine copy is missing. ISPC is built into per-module static libraries (`libVoxel.a`, `libVoxelCore.a`, etc.) linked via `PublicAdditionalLibraries`.
70
+
71
+ The cross-platform target matrix is hard-coded to:
72
+
73
+ - `Win64` / `Linux` / `Mac (x64)` / `Android (x64)`: `avx512skx-i32x8`, `avx2`, `avx`, `sse4`
74
+ - `LinuxArm64` / `Mac (arm64)` / `Android (arm64)` / `iOS` / `VisionOS`: `neon`
75
+
76
+ ## Build toggles
77
+
78
+ Two opt-in flags live as marker files in the plugin's parent `Plugins/` directory:
79
+
80
+ - `VoxelDevWorkflow.txt` — disables unity builds for `Win64` and `Mac` and switches off forced code optimization so iteration with a debugger is bearable. Also installs the IDE-friendly include-path that lets ReSharper/Rider see ISPC generated headers.
81
+ - `VoxelDebug.txt` — forces the `VOXEL_DEBUG=1` define regardless of build configuration. Equivalently, building `Debug` (or `DebugGame` with dev workflow on) flips this on automatically.
82
+
83
+ There's also `CheckPackaging.txt`: if present, all optimization is disabled (build-only sanity pass).
84
+
85
+ ## UHT extension
86
+
87
+ `VoxelUHT/Program.cs` defines a single `[UhtExporter]` named `"VoxelGraph"` that:
88
+
89
+ 1. Locates `UVoxelFunctionLibrary` and `FVoxelRuntimePinValue` in the parsed metadata.
90
+ 2. Walks every header in the `VoxelGraph` module.
91
+ 3. For every class deriving from `UVoxelFunctionLibrary`, emits a `*.generated.voxel.cpp` file with the C++ glue that turns `UFUNCTION`-tagged static methods into compute-graph nodes.
92
+
93
+ This is why writing a new voxel-graph function library node only requires a `UFUNCTION` declaration — the boilerplate that wires it into the graph system is generated by this UHT plugin at build time.
94
+
95
+ ## What's in each module's `Public/`
96
+
97
+ | Module | Subfolders under `Public/` |
98
+ |---|---|
99
+ | `VoxelCore` | `VoxelMinimal/`, `VoxelMinimal/Containers/`, `VoxelMinimal/Utilities/`, root |
100
+ | `Voxel` | `Collision/`, `Graphs/`, `Heightmap/`, `MegaMaterial/`, `Nanite/`, `Navigation/`, `Render/`, `Scatter/`, `Sculpt/`, `Shape/`, `Spline/`, `StaticMesh/`, `Surface/`, `Texture/`, root |
101
+ | `VoxelGraph` | `Buffer/`, `FunctionLibrary/`, `Nodes/`, `Preview/`, `Utilities/`, root |
102
+ | `VoxelPCG` | flat (no subfolders) |
103
+ | `VoxelBlueprint` | flat (five K2 node headers) |
104
+ | `VoxelCoreEditor`, `VoxelEditor`, `VoxelGraphEditor` | each has a `Public/`, but most concrete UI lives in `Private/` |
105
+ | `VoxelBlueprintEditor`, `VoxelPCGEditor`, `VoxelTests` | private-only, no `Public/` |
106
+
107
+ For per-module API detail see [VoxelCore](VoxelCore.md), [Voxel](Voxel.md), [VoxelGraph](VoxelGraph.md), [VoxelPCG](VoxelPCG.md), [VoxelBlueprint](VoxelBlueprint.md).
package/docs/README.md ADDED
@@ -0,0 +1,47 @@
1
+ # Voxel Plugin — Reference Docs
2
+
3
+ Reference docs for the [Voxel Plugin](https://voxelplugin.com) (Phyronnaz) — module map, public C++ surface per module, how the pieces fit together. They live in this repo because this is the ue-mcp wrapper for the Voxel Plugin, and the same reference material that helps wrapper-action authors also helps anyone building against the plugin from C++ or Blueprint.
4
+
5
+ These docs are **API-level reference** — what's in each module, what the public types do, how the pieces relate. They complement, not replace, the official knowledgebase at <https://docs.voxelplugin.com/knowledgebase>, which covers task-oriented "how do I do X" workflows.
6
+
7
+ ## When to read what
8
+
9
+ | You want… | Go here |
10
+ |---|---|
11
+ | "How do I author a stamp / use the graph editor / set up PCG?" | [Official KB](https://docs.voxelplugin.com/knowledgebase) — those pages exist and are decent. |
12
+ | "What modules does this plugin actually ship, and how do they depend on each other?" | [Modules.md](Modules.md) |
13
+ | "What's in the foundation module — containers, math, threading, ISPC?" | [VoxelCore.md](VoxelCore.md) |
14
+ | "What's `AVoxelWorld`? What are stamps, layers, the runtime, sampling?" | [Voxel.md](Voxel.md) |
15
+ | "How does the graph compile pipeline work? What's a buffer? What nodes ship?" | [VoxelGraph.md](VoxelGraph.md) |
16
+ | "How do PCG and Voxel talk to each other?" | [VoxelPCG.md](VoxelPCG.md) |
17
+ | "What K2 nodes does the plugin add to Blueprint?" | [VoxelBlueprint.md](VoxelBlueprint.md) |
18
+ | "Is the test suite worth borrowing patterns from?" | [Tests.md](Tests.md) |
19
+
20
+ ## Doc scope
21
+
22
+ These docs cover the **runtime + Blueprint** public API. Editor modules (`VoxelCoreEditor`, `VoxelEditor`, `VoxelGraphEditor`, `VoxelBlueprintEditor`, `VoxelPCGEditor`) are mentioned in [Modules.md](Modules.md) but not given their own reference pages — most of their public surface is detail customizations and Slate widgets that aren't useful to call from game code.
23
+
24
+ The plugin's `Tests/` content and `VoxelTests` module are covered as a *pattern-mining* exercise in [Tests.md](Tests.md), not as exhaustive reference.
25
+
26
+ ## Conventions
27
+
28
+ - File paths are written relative to the plugin source root (`Plugins/Voxel/Source/...`) unless they're inside a code block.
29
+ - C++ type names use their actual prefixes (`F`, `U`, `A`, `T`, `S`, `I`) — `AVoxelWorld`, `UVoxelGraph`, `FVoxelBox`, `TVoxelArray<T>`.
30
+ - Where the official KB has a corresponding page, the module doc links out to it.
31
+ - Cross-doc links between these pages use relative paths so they work on disk and on a wiki host.
32
+
33
+ ## Plugin metadata
34
+
35
+ - Source: <https://voxelplugin.com>
36
+ - Docs (official, task-focused): <https://docs.voxelplugin.com/knowledgebase>
37
+ - Discord (support): <https://discord.voxelplugin.com>
38
+ - License: see `Plugins/Voxel/LICENSES.txt` in the plugin itself. Note in particular the Transvoxel attribution requirement called out in [VoxelCore.md](VoxelCore.md#transvoxel-data).
39
+ - Loaded by default (`EnabledByDefault: true` in `Voxel.uplugin`).
40
+
41
+ ## Doc maintenance
42
+
43
+ When the upstream plugin is bumped to a new version, this is what to refresh:
44
+
45
+ 1. [Modules.md](Modules.md) — re-read every `*.Build.cs`; phases and module-name changes happen at major version bumps.
46
+ 2. Per-module docs — `Glob` `Public/**/*.h` and reconcile against the listings here. New top-level types deserve a row; deleted ones should be removed.
47
+ 3. [Tests.md](Tests.md) — re-run the include-test count and check `VoxelTests.Build.cs` for new infrastructure files.