ue-mcp-plugin-voxel-plugin 0.1.1 → 0.2.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,44 @@
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
+ One injected action in v0.2.0, cited to its source:
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` |
16
12
 
17
- Do not depend on this package yet — it intentionally exposes nothing.
13
+ More tools are tracked in [`TODO.md`](TODO.md)each entry cites the header and class it would wrap. 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
14
 
19
- ## Requirements (for future versions)
15
+ ## Install
16
+
17
+ ```bash
18
+ ue-mcp plugin install ue-mcp-plugin-voxel-plugin
19
+ ```
20
+
21
+ The CLI adds an entry under `plugins:` in your `ue-mcp.yml`. Restart ue-mcp; the injected action shows up under `pcg`.
22
+
23
+ ## Usage
24
+
25
+ ```text
26
+ pcg(action="voxel_build_scatter_graph",
27
+ assetPath="/Game/PCG/RockScatter",
28
+ meshes=[
29
+ {mesh: "/Game/Foliage/Rock_A.Rock_A", weight: 2},
30
+ {mesh: "/Game/Foliage/Rock_B.Rock_B"}
31
+ ],
32
+ pointsPerSquaredMeter=0.05,
33
+ seed=42)
34
+ ```
35
+
36
+ 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:
37
+
38
+ ```text
39
+ pcg(action="execute", actorLabel="MyPCGActor")
40
+ ```
41
+
42
+ ## Requirements
20
43
 
21
44
  - ue-mcp `>= 1.0.15`
22
45
  - 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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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ue-mcp-plugin-voxel-plugin",
3
- "version": "0.1.1",
4
- "description": "Voxel Plugin actions for ue-mcp. Scaffold only at this version - real tools tracked in TODO.md.",
3
+ "version": "0.2.0",
4
+ "description": "Voxel Plugin actions for ue-mcp. One real PCG action in 0.2.0 - rest tracked in TODO.md.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "files": [
package/ue-mcp.plugin.yml CHANGED
@@ -2,14 +2,22 @@ actionPrefix: voxel
2
2
  minServerVersion: 1.0.15
3
3
  uePluginDependency: Voxel
4
4
 
5
- # No actions ship in this version. The 0.1.0 release injected three
6
- # placeholder actions (voxel_scatter_meshes, voxel_spawn_stamps,
7
- # voxel_bake_heightmap) that called ue-mcp tasks with the wrong parameter
8
- # names and passed fabricated PCG node-type strings - none of them worked.
9
- # They have been removed. See TODO.md in the repo for the real API surface
10
- # and the prioritized list of tools being built against it.
11
-
12
- inject: {}
5
+ inject:
6
+ pcg:
7
+ build_scatter_graph:
8
+ task: voxel.build_scatter_graph
9
+ description: "Build a PCG graph that scatters weighted static meshes on a voxel terrain. Wraps UPCGVoxelSamplerSettings (VoxelPCG/Public/PCGVoxelSampler.h) feeding the stock PCGStaticMeshSpawner. After creation, attach the graph to a PCG component (usually near an AVoxelWorld) and call pcg.execute. Params: assetPath (e.g. /Game/PCG/MyScatter), meshes=[{mesh, weight?}], pointsPerSquaredMeter? (default 0.1), seed? (default 1)."
10
+ schema:
11
+ assetPath: { type: string, required: true }
12
+ meshes: { type: array, required: true }
13
+ pointsPerSquaredMeter: { type: number }
14
+ seed: { type: number }
15
+
13
16
  knowledge: {}
14
- tasks: {}
17
+
18
+ tasks:
19
+ voxel.build_scatter_graph:
20
+ class_path: tasks/BuildScatterGraph
21
+ description: "Build a Voxel-Sampler-driven PCG mesh scatter graph"
22
+
15
23
  flows: {}