ue-mcp-plugin-voxel-plugin 0.2.0 → 0.3.1
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 +34 -8
- package/dist/tasks/EnsureWaitForWorld.d.ts +32 -0
- package/dist/tasks/EnsureWaitForWorld.js +91 -0
- package/dist/tasks/EnsureWaitForWorld.js.map +1 -0
- package/dist/tasks/GetWorldStatus.d.ts +27 -0
- package/dist/tasks/GetWorldStatus.js +57 -0
- package/dist/tasks/GetWorldStatus.js.map +1 -0
- package/dist/tasks/SpawnWorld.d.ts +37 -0
- package/dist/tasks/SpawnWorld.js +72 -0
- package/dist/tasks/SpawnWorld.js.map +1 -0
- package/docs/Modules.md +107 -0
- package/docs/README.md +47 -0
- package/docs/Tests.md +280 -0
- package/docs/Voxel.md +450 -0
- package/docs/VoxelBlueprint.md +167 -0
- package/docs/VoxelCore.md +128 -0
- package/docs/VoxelGraph.md +386 -0
- package/docs/VoxelPCG.md +288 -0
- package/package.json +3 -2
- package/ue-mcp.plugin.yml +34 -0
package/docs/Tests.md
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
# VoxelTests — What's in It, What It's Worth Borrowing
|
|
2
|
+
|
|
3
|
+
> Audience: a senior UE5 engineer evaluating whether the plugin's testing approach is worth borrowing for their own project.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Phyronnaz's `VoxelTests` module is split into two surfaces:
|
|
8
|
+
|
|
9
|
+
- a **content-driven integration layer** — 23 test maps and 127 supporting assets under `Plugins/Voxel/Tests/`
|
|
10
|
+
- a **header include-safety harness** — 96 source files under `Plugins/Voxel/Source/VoxelTests/Private/`
|
|
11
|
+
|
|
12
|
+
The framework is lightweight and **eschews UE Automation** (`IMPLEMENT_SIMPLE_AUTOMATION_TEST`) entirely. Instead, it implements a custom **Blueprint-callable test harness** that loads maps in sequence, tracks pass/fail state, captures screenshots, and emits a JSON report suitable for CI. A separate startup hook auto-generates one `.cpp` per public header to verify every header compiles in isolation.
|
|
13
|
+
|
|
14
|
+
## Layout
|
|
15
|
+
|
|
16
|
+
### `Plugins/Voxel/Tests/` — content integration tests
|
|
17
|
+
|
|
18
|
+
- 23 `.umap` test maps covering gameplay, rendering, stamping, navigation
|
|
19
|
+
- 127 supporting assets (materials, graphs, meshes)
|
|
20
|
+
- Total: 150 files
|
|
21
|
+
- Folders: `Assets/`, `BasicGameplay/`, `BasicSplines/`, `CurveNode/`, `DistanceFields/`, `GradientTest/`, `Lumen/`, `MaterialRendering/{CurveMaterial,Gravel,MuddyLeaves}/`, `Metadata/`, `MetadataQueries/`, `Navigation/`, `OverrideGraphs/`, `PCGWorld/`, `Queries/`, `RVT/`, `Sculpting/`, `SmoothBlendsAndSmartSurfaces/`, `TangentNormals/`, `Velocity/`, `WPO/`
|
|
22
|
+
|
|
23
|
+
### `Plugins/Voxel/Source/VoxelTests/` — native infrastructure
|
|
24
|
+
|
|
25
|
+
- 96 source files (90 `.cpp` + 6 headers)
|
|
26
|
+
- 85 auto-generated include-test stubs in `VoxelCoreIncludeTest/` — one `.cpp` per `VoxelMinimal/` header
|
|
27
|
+
- 6 manual infrastructure files:
|
|
28
|
+
- `VoxelTestsModule.cpp` — module entry, CLI flag handling (`-VoxelTests`, `-RunVoxelTests`)
|
|
29
|
+
- `VoxelTestManager.h/.cpp` — singleton: map sequencing, JSON serialization
|
|
30
|
+
- `VoxelTestLibrary.h/.cpp` — Blueprint-exposed test API
|
|
31
|
+
- `VoxelTestPCH.h` — lightweight include guard for `VoxelCoreMinimal.h`
|
|
32
|
+
- `VoxelCoreIncludeTestGenerator.cpp` — startup hook that creates the stubs
|
|
33
|
+
|
|
34
|
+
The `Build.cs` is intentionally tiny:
|
|
35
|
+
|
|
36
|
+
```csharp
|
|
37
|
+
public VoxelTests(ReadOnlyTargetRules Target) : base(Target)
|
|
38
|
+
{
|
|
39
|
+
if (new VoxelConfig(this).DevWorkflow)
|
|
40
|
+
{
|
|
41
|
+
// Needed by include testing
|
|
42
|
+
PrivatePCHHeaderFile = "Private/VoxelTestPCH.h";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
PublicDependencyModuleNames.AddRange(new string[] { "Json" });
|
|
46
|
+
PrivateDependencyModuleNames.AddRange(new string[] { "NavigationSystem" });
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Framework
|
|
51
|
+
|
|
52
|
+
### Custom Blueprint-driven, not UE Automation
|
|
53
|
+
|
|
54
|
+
There are **no `IMPLEMENT_SIMPLE_AUTOMATION_TEST` macros**. Instead:
|
|
55
|
+
|
|
56
|
+
1. **Blueprint layer:** call `UVoxelTestLibrary::StartTest(Name)` → returns `FVoxelTestHandle`.
|
|
57
|
+
2. **State machine:** each test transitions `Started → Succeeded | Failed`.
|
|
58
|
+
3. **Manager orchestration** (`FVoxelTestManager` singleton):
|
|
59
|
+
- Sequentially loads test maps from `/Game/VoxelTests/`.
|
|
60
|
+
- Collects pass/fail results, warnings, errors, screenshot GUIDs.
|
|
61
|
+
- Writes JSON to `Saved/VoxelTests/VoxelTests.json`.
|
|
62
|
+
- Captures high-res screenshots on demand.
|
|
63
|
+
|
|
64
|
+
Activation: console command `voxel.tests.Start` or CLI flag `-RunVoxelTests` (non-editor mode only).
|
|
65
|
+
|
|
66
|
+
### Naming
|
|
67
|
+
|
|
68
|
+
| Surface | Convention |
|
|
69
|
+
|---|---|
|
|
70
|
+
| Test maps | `TEST_<Feature>.umap` (`TEST_BasicGameplay.umap`, `TEST_Gradient.umap`) |
|
|
71
|
+
| Assets | `TEST_<Type>_<Name>.uasset` (`TEST_VHG_Gradient.uasset`, `TEST_MI_Gravel_Red.uasset`) |
|
|
72
|
+
| Include-test stubs | `VoxelCoreIncludeTest_<Category>_<HeaderName>.cpp` |
|
|
73
|
+
|
|
74
|
+
### Custom assertion macros: none
|
|
75
|
+
|
|
76
|
+
No `VOXEL_TEST_*` macros. The Blueprint-callable surface is the API:
|
|
77
|
+
|
|
78
|
+
```cpp
|
|
79
|
+
UFUNCTION(BlueprintCallable, Category = "Voxel|Tests")
|
|
80
|
+
static FVoxelTestHandle StartTest(const FString& Name);
|
|
81
|
+
|
|
82
|
+
UFUNCTION(BlueprintCallable, Category = "Voxel|Tests")
|
|
83
|
+
static void PassTest(const FVoxelTestHandle& Handle);
|
|
84
|
+
|
|
85
|
+
UFUNCTION(BlueprintCallable, Category = "Voxel|Tests")
|
|
86
|
+
static void FailTest(const FVoxelTestHandle& Handle, const FString& Reason);
|
|
87
|
+
|
|
88
|
+
UFUNCTION(BlueprintCallable, Category = "Voxel|Tests")
|
|
89
|
+
static void TakeScreenshot(const FGuid& Guid);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Tests call these from Blueprint event graphs (typically on a timer or completion callback). Standard `check()` / `ensure()` are intercepted by `FVoxelTestsOutputDevice` for logging.
|
|
93
|
+
|
|
94
|
+
### No BDD / spec layer
|
|
95
|
+
|
|
96
|
+
Purely imperative, map-and-actor-driven: an actor in the map handles setup/teardown on `BeginPlay`, the BP graph waits for a completion condition, then calls `FailTest` or `PassTest`.
|
|
97
|
+
|
|
98
|
+
## Fixture and runtime setup
|
|
99
|
+
|
|
100
|
+
### Minimal `VoxelRuntime` bootstrapping
|
|
101
|
+
|
|
102
|
+
Tests do **not** spawn an in-memory `AVoxelWorld` CDO. Instead:
|
|
103
|
+
|
|
104
|
+
1. **Editor-mounted content:** the module registers `Plugins/Voxel/Tests/` as a game path at startup:
|
|
105
|
+
```cpp
|
|
106
|
+
FPackageName::RegisterMountPoint("/Game/VoxelTests/", DiskPath);
|
|
107
|
+
```
|
|
108
|
+
2. **Per-map setup:** each test map ships a custom test actor (e.g. `TEST_BasicGameplayActor.uasset`) that:
|
|
109
|
+
- executes on `BeginPlay`,
|
|
110
|
+
- configures nav generation (`SetNavMeshGeneration(bRuntime)`),
|
|
111
|
+
- spawns the runtime objects under test (VoxelWorld refs, stamps, AI pawns),
|
|
112
|
+
- calls `StartTest` and monitors for completion.
|
|
113
|
+
3. **World lifespan:** entire map persists for the test; teardown destroys all actors after reporting.
|
|
114
|
+
|
|
115
|
+
### Asset loading
|
|
116
|
+
|
|
117
|
+
- No transient CDOs — all test assets are pre-authored, disk-resident under `Plugins/Voxel/Tests/Assets/`.
|
|
118
|
+
- Graphs are pre-built `UVoxelHeightGraph` / `UVoxelVolumeGraph` `.uasset`s.
|
|
119
|
+
- Meshes & materials are standard UE5 content.
|
|
120
|
+
|
|
121
|
+
### No explicit mocking
|
|
122
|
+
|
|
123
|
+
- GPU / render targets: used as-is.
|
|
124
|
+
- Navigation: gated via `SetNavMeshGeneration(bool bRuntime)` which flips `ERuntimeGenerationType` and triggers a rebuild.
|
|
125
|
+
- Threading / task graph: no abstraction; tests run synchronously or wait on async callbacks.
|
|
126
|
+
|
|
127
|
+
## Coverage map
|
|
128
|
+
|
|
129
|
+
### What's tested
|
|
130
|
+
|
|
131
|
+
| Area | Maps | Notes |
|
|
132
|
+
|---|---|---|
|
|
133
|
+
| Graph evaluation | `GradientTest`, `CurveNode` | Height/volume graph outputs, curve sampling. |
|
|
134
|
+
| Stamping & blending | `PCGWorld`, `OverrideGraphs`, `SmoothBlendsAndSmartSurfaces` | Procedural stamp application, blend-mode overrides. |
|
|
135
|
+
| Voxel rendering | `MaterialRendering/*`, `Lumen`, `Metadata` | Material slots, translucency, emissive, per-voxel metadata. |
|
|
136
|
+
| Serialization & I/O | `DistanceFields` | Distance-field bake + round-trip. |
|
|
137
|
+
| Gameplay integration | `BasicGameplay`, `Navigation` | Voxel-aware AI, character movement, navmesh. |
|
|
138
|
+
| Advanced rendering | `TangentNormals`, `WPO`, `RVT`, `Velocity` | Tangent normals, world-position offset, runtime VT, motion vectors. |
|
|
139
|
+
| Splines | `BasicSplines` | Spline-driven voxel deformation. |
|
|
140
|
+
|
|
141
|
+
### What's NOT tested
|
|
142
|
+
|
|
143
|
+
- Editor UI (menus, property panels).
|
|
144
|
+
- Networking / replication / multiplayer integration.
|
|
145
|
+
- Cross-module plugin build sanity beyond compile.
|
|
146
|
+
- Performance — maps exist but no automated perf gates; manual profiling only.
|
|
147
|
+
|
|
148
|
+
Maps are **functional full-stack integration tests**: spawn a VoxelWorld (or load a pre-baked one), run a gameplay loop, assert the final state from Blueprint. No unit tests for individual containers or utilities — those are guarded by the include-testing layer below.
|
|
149
|
+
|
|
150
|
+
## Include self-containment checks
|
|
151
|
+
|
|
152
|
+
**File:** `Plugins/Voxel/Source/VoxelTests/Private/VoxelCoreIncludeTestGenerator.cpp`
|
|
153
|
+
|
|
154
|
+
On startup (when `VOXEL_DEV_WORKFLOW && VOXEL_DEBUG`) the module:
|
|
155
|
+
|
|
156
|
+
1. Scans `VoxelCore/Public/VoxelMinimal/` for every `.h`.
|
|
157
|
+
2. Generates one `.cpp` stub per header, including it in isolation:
|
|
158
|
+
```cpp
|
|
159
|
+
// Example: VoxelCoreIncludeTest_Containers_VoxelArray.cpp
|
|
160
|
+
#include "VoxelCoreMinimal.h"
|
|
161
|
+
#if VOXEL_DEV_WORKFLOW && VOXEL_DEBUG
|
|
162
|
+
#include "VoxelMinimal/Containers/VoxelArray.h" // the real include
|
|
163
|
+
#endif
|
|
164
|
+
```
|
|
165
|
+
3. Forces the PCH to `VoxelTestPCH.h` only when dev-workflow is on, so the linker compiles all 85+ stubs.
|
|
166
|
+
4. Any header that fails standalone (missing transitive include, circular dep) breaks the build.
|
|
167
|
+
|
|
168
|
+
Why it matters: this catches the classic "works in unity build, fails in incremental compile" failure mode without anyone writing a manual test. Header hygiene is enforced by the build, not by code review.
|
|
169
|
+
|
|
170
|
+
## Honest assessment
|
|
171
|
+
|
|
172
|
+
### Strengths
|
|
173
|
+
|
|
174
|
+
1. **Include-testing discipline is best-in-class.** The auto-generated stub generator is the standout pattern.
|
|
175
|
+
2. **Lightweight infrastructure** — no Catch2, no GoogleTest, no UE Automation boilerplate.
|
|
176
|
+
3. **Blueprint-testable gameplay** — designers can write integration tests in maps + event graphs.
|
|
177
|
+
4. **JSON output for CI** — pipeline-friendly result format.
|
|
178
|
+
5. **Built-in screenshot capture** — visual regression hook is in place even if not fully automated.
|
|
179
|
+
|
|
180
|
+
### Weaknesses
|
|
181
|
+
|
|
182
|
+
1. **Sparse unit-test coverage.** 91 `VoxelMinimal/` headers but only compile-validation, not runtime assertions on container ops.
|
|
183
|
+
2. **No spec / BDD language.** Test intent is implicit in map names.
|
|
184
|
+
3. **Content-heavy and fragile.** 23 maps × dozens of assets is a big footprint and renames silently break tests.
|
|
185
|
+
4. **Limited documentation.** No README per map explaining what it validates.
|
|
186
|
+
5. **Sequential map loading.** No parallelization for CI time savings.
|
|
187
|
+
6. **Manual failure diagnosis.** Errors go to log + JSON; reading logs is required to debug.
|
|
188
|
+
|
|
189
|
+
### Verdict
|
|
190
|
+
|
|
191
|
+
Solid but narrowly-focused. The include-testing pattern is excellent and worth lifting wholesale. The content-map integration layer is a workable smoke-test layer but not a template for comprehensive TDD.
|
|
192
|
+
|
|
193
|
+
## Patterns worth borrowing
|
|
194
|
+
|
|
195
|
+
### 1. Auto-generated header compliance tests
|
|
196
|
+
|
|
197
|
+
**Source:** `Plugins/Voxel/Source/VoxelTests/Private/VoxelCoreIncludeTestGenerator.cpp`
|
|
198
|
+
|
|
199
|
+
A startup hook that scans a module's `Public/` tree, generates one `.cpp` per `.h` including it standalone, and gates the PCH so the linker compiles them all. Catches transitive-include bugs and missing forward decls without writing manual tests.
|
|
200
|
+
|
|
201
|
+
Wire it up by gating a dedicated test PCH on a dev flag:
|
|
202
|
+
|
|
203
|
+
```csharp
|
|
204
|
+
if (bIsDevBuild)
|
|
205
|
+
{
|
|
206
|
+
PrivatePCHHeaderFile = "Private/YourModuleTestPCH.h";
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### 2. Blueprint-callable test harness
|
|
211
|
+
|
|
212
|
+
**Source:** `Plugins/Voxel/Source/VoxelTests/Private/VoxelTestLibrary.h`
|
|
213
|
+
|
|
214
|
+
Expose `StartTest(Name)`, `PassTest(Handle)`, `FailTest(Handle, Reason)` as `UFUNCTION(BlueprintCallable)`. Pairs naturally with map-driven testing — designers can author tests without touching C++.
|
|
215
|
+
|
|
216
|
+
Add gameplay-specific assertion helpers alongside:
|
|
217
|
+
|
|
218
|
+
```cpp
|
|
219
|
+
UCLASS()
|
|
220
|
+
class YOURMODULE_API UYourTestLibrary : public UBlueprintFunctionLibrary
|
|
221
|
+
{
|
|
222
|
+
public:
|
|
223
|
+
UFUNCTION(BlueprintCallable, Category = "YourModule|Tests")
|
|
224
|
+
static void AssertActorCount(const FString& TestName, int32 Expected, int32 Actual);
|
|
225
|
+
|
|
226
|
+
UFUNCTION(BlueprintCallable, Category = "YourModule|Tests")
|
|
227
|
+
static void AssertFloatAlmostEqual(const FString& TestName, float Expected, float Actual, float Tolerance = 0.01f);
|
|
228
|
+
};
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### 3. Automated screenshot capture for visual regression
|
|
232
|
+
|
|
233
|
+
**Source:** `Plugins/Voxel/Source/VoxelTests/Private/VoxelTestLibrary.cpp` (~lines 81–113)
|
|
234
|
+
|
|
235
|
+
`TakeScreenshot(FGuid)` wraps `HighResShot` and saves to `Saved/VoxelTests/<MapName>/<Guid>.png`. Adding hash- or perceptual-diff comparison turns it into a real visual baseline system.
|
|
236
|
+
|
|
237
|
+
### 4. Custom `FOutputDevice` for warning / error tracking
|
|
238
|
+
|
|
239
|
+
**Source:** `Plugins/Voxel/Source/VoxelTests/Private/VoxelTestManager.cpp` (~lines 22–100, `FVoxelTestsOutputDevice`)
|
|
240
|
+
|
|
241
|
+
Subclass `FOutputDevice`, register with `GLog`, intercept warnings/errors with stack traces, serialize to JSON. Detects silent failures — `ensure()` firing without an explicit `FailTest`.
|
|
242
|
+
|
|
243
|
+
### 5. Explicit test state machine
|
|
244
|
+
|
|
245
|
+
**Source:** `Plugins/Voxel/Source/VoxelTests/Private/VoxelTestManager.h` (~lines 9–14, `EVoxelTestState`)
|
|
246
|
+
|
|
247
|
+
`{ Started, Succeeded, Failed }` enum with transition validation. Catches double-pass / double-fail bugs in the test code itself.
|
|
248
|
+
|
|
249
|
+
### 6. Per-map JSON serialization for CI
|
|
250
|
+
|
|
251
|
+
**Source:** `Plugins/Voxel/Source/VoxelTests/Private/VoxelTestManager.cpp` (~lines 123–181)
|
|
252
|
+
|
|
253
|
+
Per-test pass/fail, screenshots, warnings, errors, raytracing status. Pipelines (Gitea Actions, Jenkins, GitHub Actions) parse this directly to fail the build and link to detailed reports.
|
|
254
|
+
|
|
255
|
+
## Recommended adoption order
|
|
256
|
+
|
|
257
|
+
1. **Include-testing pattern first.** Lowest friction, highest immediate value. Start with your smallest-surface module, then expand.
|
|
258
|
+
2. **Project test library** with gameplay-specific assertions: fuzzy compare, actor count, component state, GAS attribute equality.
|
|
259
|
+
3. **Visual baseline on top of screenshot capture** — hash or perceptual diff in CI.
|
|
260
|
+
4. **Document test maps** with a README per map (goal, expected result, manual verification).
|
|
261
|
+
5. **Defer parallelization** — sequential map loading is fine until tests exceed ~50.
|
|
262
|
+
6. **Add perf gates separately:** log frame time, draw calls, memory per map; fail on delta thresholds. Voxel doesn't do this and probably should.
|
|
263
|
+
|
|
264
|
+
## Summary
|
|
265
|
+
|
|
266
|
+
| Aspect | Voxel approach | Notes |
|
|
267
|
+
|---|---|---|
|
|
268
|
+
| Framework | Custom Blueprint + manager | Low overhead, gameplay-friendly. |
|
|
269
|
+
| Coverage | Content maps + include stubs | Integration-focused; unit coverage thin. |
|
|
270
|
+
| Assertion macros | None (UE `check`/`ensure` + custom output device) | No DSL to learn. |
|
|
271
|
+
| Fixtures | Disk-resident assets, per-map actors | Reusable, but fragile to refactor. |
|
|
272
|
+
| CI integration | JSON output | Parse anywhere. |
|
|
273
|
+
| Header safety | Auto-generated stubs | Best-in-class — adopt as-is. |
|
|
274
|
+
| BDD / spec | None | Consider adding for docs. |
|
|
275
|
+
| Mocking | Minimal (real GPU, threading) | May need expansion for subsystem tests. |
|
|
276
|
+
|
|
277
|
+
## Cross-references
|
|
278
|
+
|
|
279
|
+
- The headers being include-tested live in [VoxelCore](VoxelCore.md).
|
|
280
|
+
- `FVoxelTestsOutputDevice` integrates with the [VoxelCore message system](VoxelCore.md#messages).
|