@vgai/engine 0.5.41 → 0.5.44
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/dist/adapter/adapter-module.d.ts +28 -29
- package/dist/adapter/adapter-module.d.ts.map +1 -1
- package/dist/adapter/adapter-module.js +11 -34
- package/dist/adapter/authoring-seam-contract.d.ts +10 -0
- package/dist/adapter/authoring-seam-contract.d.ts.map +1 -1
- package/dist/adapter/authoring-seam-contract.js +2 -0
- package/dist/adapter/authoring.d.ts +31 -0
- package/dist/adapter/authoring.d.ts.map +1 -1
- package/dist/adapter/finders/finder-result.d.ts +2 -2
- package/dist/adapter/finders/finder-result.d.ts.map +1 -1
- package/dist/adapter/finders/index.d.ts +15 -2
- package/dist/adapter/finders/index.d.ts.map +1 -1
- package/dist/adapter/finders/index.js +38 -10
- package/dist/adapter/finders/prefabs-from-stories.d.ts.map +1 -1
- package/dist/adapter/finders/registry.d.ts +45 -0
- package/dist/adapter/finders/registry.d.ts.map +1 -0
- package/dist/adapter/finders/registry.js +56 -0
- package/dist/adapter/ingest/scene-capture.d.ts.map +1 -1
- package/dist/adapter/ingest/scene-capture.js +50 -20
- package/dist/adapter/system-adapter.d.ts +3 -1
- package/dist/adapter/system-adapter.d.ts.map +1 -1
- package/dist/canvas-react/pixi-react-root-factory.d.ts.map +1 -1
- package/dist/canvas-react/pixi-react-root-factory.js +21 -11
- package/dist/data/vite-plugin-data.d.ts +1 -1
- package/dist/data/vite-plugin-data.d.ts.map +1 -1
- package/dist/data/vite-plugin-data.js +2 -2
- package/dist/ecs/user-data.d.ts +6 -0
- package/dist/ecs/user-data.d.ts.map +1 -1
- package/dist/ecs/user-data.js +4 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/input/host-pointer.d.ts +18 -0
- package/dist/input/host-pointer.d.ts.map +1 -1
- package/dist/input/host-pointer.js +54 -5
- package/dist/input/input-manager.d.ts +83 -1
- package/dist/input/input-manager.d.ts.map +1 -1
- package/dist/input/input-manager.js +357 -8
- package/dist/manifest/configuration-kinds.d.ts +97 -0
- package/dist/manifest/configuration-kinds.d.ts.map +1 -0
- package/dist/manifest/configuration-kinds.js +148 -0
- package/dist/manifest/index.d.ts +2 -1
- package/dist/manifest/index.d.ts.map +1 -1
- package/dist/manifest/index.js +4 -3
- package/dist/manifest/kind-modules.d.ts +18 -0
- package/dist/manifest/kind-modules.d.ts.map +1 -0
- package/dist/manifest/kind-modules.js +58 -0
- package/dist/manifest/load-file.d.ts +3 -3
- package/dist/manifest/load-file.d.ts.map +1 -1
- package/dist/manifest/load-file.js +4 -4
- package/dist/manifest/load.d.ts +17 -12
- package/dist/manifest/load.d.ts.map +1 -1
- package/dist/manifest/load.js +29 -19
- package/dist/manifest/runtime-environment.d.ts +11 -0
- package/dist/manifest/runtime-environment.d.ts.map +1 -0
- package/dist/manifest/runtime-environment.js +44 -0
- package/dist/manifest/schema.d.ts +10 -9
- package/dist/manifest/schema.d.ts.map +1 -1
- package/dist/manifest/schema.js +32 -27
- package/dist/react/use-data.d.ts +1 -1
- package/dist/react/use-data.js +1 -1
- package/dist/render/environment-capture.d.ts +10 -1
- package/dist/render/environment-capture.d.ts.map +1 -1
- package/dist/render/environment-capture.js +25 -0
- package/dist/render/ibl-override-material.d.ts +11 -2
- package/dist/render/ibl-override-material.d.ts.map +1 -1
- package/dist/render/ibl-override-material.js +16 -2
- package/dist/render/matcap-texture.d.ts +5 -0
- package/dist/render/matcap-texture.d.ts.map +1 -0
- package/dist/render/matcap-texture.js +82 -0
- package/dist/render/soft-particle-depth.d.ts +14 -8
- package/dist/render/soft-particle-depth.d.ts.map +1 -1
- package/dist/render/soft-particle-depth.js +37 -14
- package/dist/render/viewport-shading.d.ts +11 -1
- package/dist/render/viewport-shading.d.ts.map +1 -1
- package/dist/render/viewport-shading.js +25 -0
- package/dist/runtime/create-runtime.js +6 -5
- package/dist/runtime/debug-bridge.d.ts.map +1 -1
- package/dist/runtime/debug-bridge.js +17 -3
- package/dist/runtime/mount-manifest.d.ts.map +1 -1
- package/dist/runtime/mount-manifest.js +11 -2
- package/dist/settings/schema.d.ts +99 -0
- package/dist/settings/schema.d.ts.map +1 -0
- package/dist/settings/schema.js +110 -0
- package/dist/world3d-react/r3f-root-factory.d.ts.map +1 -1
- package/dist/world3d-react/r3f-root-factory.js +34 -36
- package/dist/world3d-react/rapier-physics-bridge.d.ts.map +1 -1
- package/dist/world3d-react/rapier-physics-bridge.js +21 -6
- package/dist-config/config.js +1 -1
- package/dist-config/config.js.map +2 -2
- package/package.json +2 -1
- package/schemas/engine-capabilities.json +4 -4
- package/schemas/vgai-project.schema.json +41 -36
- package/schemas/vgai-settings.schema.json +112 -0
- package/src/adapter/adapter-module.ts +33 -51
- package/src/adapter/authoring-seam-contract.ts +2 -0
- package/src/adapter/authoring.ts +31 -0
- package/src/adapter/finders/finder-result.ts +2 -2
- package/src/adapter/finders/index.ts +68 -12
- package/src/adapter/finders/prefabs-from-stories.ts +2 -2
- package/src/adapter/finders/registry.ts +95 -0
- package/src/adapter/finders/scenes-from-entrypoint-selection.ts +4 -4
- package/src/adapter/ingest/scene-capture.ts +48 -19
- package/src/adapter/system-adapter.ts +3 -1
- package/src/canvas-react/pixi-react-root-factory.tsx +21 -11
- package/src/data/vite-plugin-data.ts +4 -2
- package/src/ecs/user-data.ts +6 -0
- package/src/index.ts +1 -1
- package/src/input/host-pointer.ts +84 -5
- package/src/input/input-manager.ts +404 -7
- package/src/manifest/configuration-kinds.ts +241 -0
- package/src/manifest/index.ts +4 -3
- package/src/manifest/kind-modules.ts +58 -0
- package/src/manifest/load-file.ts +11 -5
- package/src/manifest/load.ts +53 -22
- package/src/manifest/runtime-environment.ts +48 -0
- package/src/manifest/schema.ts +39 -33
- package/src/react/use-data.ts +1 -1
- package/src/render/environment-capture.ts +30 -1
- package/src/render/ibl-override-material.ts +32 -2
- package/src/render/matcap-texture.ts +92 -0
- package/src/render/soft-particle-depth.ts +43 -14
- package/src/render/viewport-shading.ts +33 -1
- package/src/runtime/create-runtime.ts +6 -5
- package/src/runtime/debug-bridge.ts +21 -3
- package/src/runtime/mount-manifest.ts +13 -2
- package/src/settings/schema.ts +127 -0
- package/src/world3d-react/r3f-root-factory.tsx +45 -39
- package/src/world3d-react/rapier-physics-bridge.tsx +22 -8
|
@@ -150,19 +150,19 @@ function canvasWorldAdapter(id: string, component: ComponentType): RootAdapter<'
|
|
|
150
150
|
const unmounted = new Promise<void>((resolve) => {
|
|
151
151
|
resolveUnmounted = resolve;
|
|
152
152
|
});
|
|
153
|
+
let resolveEffectsUnmounted!: () => void;
|
|
154
|
+
const effectsUnmounted = new Promise<void>((resolve) => {
|
|
155
|
+
resolveEffectsUnmounted = resolve;
|
|
156
|
+
});
|
|
153
157
|
/**
|
|
154
|
-
* Signals the tree's FIRST COMMIT and
|
|
155
|
-
*
|
|
158
|
+
* Signals the tree's FIRST COMMIT and both unmount cleanup phases. Rendered as the LAST
|
|
159
|
+
* child deliberately:
|
|
156
160
|
*
|
|
157
161
|
* - mount: layout effects run synchronously inside the commit, before
|
|
158
162
|
* any passive effect and before any tick can be scheduled;
|
|
159
|
-
* - unmount:
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
* finished tearing down" signal — and it is load-bearing, because
|
|
163
|
-
* `useTick`'s own cleanup calls `ticker.remove()`. Destroying the
|
|
164
|
-
* Application before that cleanup lands throws inside React's commit
|
|
165
|
-
* on every teardown of any world with a tick hook.
|
|
163
|
+
* - unmount: the layout cleanup fences `useTick` and the passive cleanup fences ordinary
|
|
164
|
+
* project effects. Native destruction waits for BOTH; resolving only from layout left
|
|
165
|
+
* passive listener/resource cleanup racing an Application whose renderer was null.
|
|
166
166
|
*/
|
|
167
167
|
function Lifecycle(): null {
|
|
168
168
|
useLayoutEffect(() => {
|
|
@@ -172,7 +172,10 @@ function canvasWorldAdapter(id: string, component: ComponentType): RootAdapter<'
|
|
|
172
172
|
// This component is the last sibling. Reaching its passive effect
|
|
173
173
|
// means the initial tree's provider/command effects have registered,
|
|
174
174
|
// so mount() can truthfully back Play's ack.
|
|
175
|
-
useEffect(
|
|
175
|
+
useEffect(() => {
|
|
176
|
+
resolveEffectsReady();
|
|
177
|
+
return resolveEffectsUnmounted;
|
|
178
|
+
}, []);
|
|
176
179
|
return null;
|
|
177
180
|
}
|
|
178
181
|
|
|
@@ -282,7 +285,14 @@ function canvasWorldAdapter(id: string, component: ComponentType): RootAdapter<'
|
|
|
282
285
|
// Adapter surface: the host's shared debug registry. The game's own
|
|
283
286
|
// capabilities arrive as the entry module's declared `systems`.
|
|
284
287
|
const systemAdapters: SystemAdapters = registry ? { debug: registry.adapter } : {};
|
|
285
|
-
const disposeComplete = unmounted.then(() => {
|
|
288
|
+
const disposeComplete = Promise.all([unmounted, effectsUnmounted]).then(() => {
|
|
289
|
+
// React can tear the root down itself after a fatal layout/effect error. In that path the
|
|
290
|
+
// host has not called dispose() yet, but Application.destroy() still clears Pixi's ticker
|
|
291
|
+
// and renderer. Wait for both layout and passive cleanup first: project effects may own
|
|
292
|
+
// window/document listeners and can still read the Pixi Application while React drains
|
|
293
|
+
// passive deletion effects. Fence the mounted root before clearing the native slots so
|
|
294
|
+
// subsequent host frames and the eventual host teardown cannot re-enter them.
|
|
295
|
+
disposed = true;
|
|
286
296
|
mountedApp.destroy(false, { children: true });
|
|
287
297
|
});
|
|
288
298
|
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* target file" hole, closed for declared refs — see
|
|
28
28
|
* `collectDeclaredRefFields`/`findMissingRefTargets` in `data-check-core.ts`).
|
|
29
29
|
* 3. **Tools never ship** (`generateBundle`): no emitted chunk may contain a
|
|
30
|
-
* module from `src/tools/` or a `*.tool.*` file (§4: tester serves and
|
|
30
|
+
* module from `src/contributions/`, `src/tools/` or a `*.tool.*` file (§4: tester serves and
|
|
31
31
|
* standalone builds strip tools entirely; W4 made this true by
|
|
32
32
|
* construction — nothing imports tools — and this check PINS it against
|
|
33
33
|
* the day some game module imports a tool "just for a helper").
|
|
@@ -268,7 +268,9 @@ export async function collectDataCheckProblems(options: VgaiDataCheckOptions): P
|
|
|
268
268
|
/** True iff a bundled module id is tool code that must never ship (§4). Pure, unit-tested. */
|
|
269
269
|
export function isToolModuleId(id: string): boolean {
|
|
270
270
|
const normalized = id.split('\\').join('/');
|
|
271
|
-
return
|
|
271
|
+
return (
|
|
272
|
+
/\/src\/(?:tools|contributions)\//.test(normalized) || /\.tool\.[tj]sx?(\?|$)/.test(normalized)
|
|
273
|
+
);
|
|
272
274
|
}
|
|
273
275
|
|
|
274
276
|
/**
|
package/src/ecs/user-data.ts
CHANGED
|
@@ -82,6 +82,9 @@
|
|
|
82
82
|
* association; unlike the label, never user-facing copy.
|
|
83
83
|
* - `authoringDocument` — generic reference to the project-tool document
|
|
84
84
|
* that owns this scene instance's authored asset.
|
|
85
|
+
* - `authoringHierarchyId`, `authoringHierarchyParentId`,
|
|
86
|
+
* `authoringHierarchyOrder` — source-owned semantic identity, parent identity,
|
|
87
|
+
* and sibling ordinal shared across native surfaces.
|
|
85
88
|
* - `editorHelper` — `true` for editor-only helper objects (gizmos, wireframes).
|
|
86
89
|
*
|
|
87
90
|
* Hierarchy-presentation convention (written by GAME code, read by the editor —
|
|
@@ -195,6 +198,8 @@ export interface UserDataSchema {
|
|
|
195
198
|
};
|
|
196
199
|
/** Project-owned identity used to join authored hierarchy rows across adapter roots. */
|
|
197
200
|
authoringHierarchyId: string;
|
|
201
|
+
/** Project-owned parent identity when the authored parent can live on another surface. */
|
|
202
|
+
authoringHierarchyParentId: string;
|
|
198
203
|
/** Source-owned sibling ordinal used when hierarchy rows cross native roots. */
|
|
199
204
|
authoringHierarchyOrder: number;
|
|
200
205
|
editorHelper: boolean;
|
|
@@ -254,6 +259,7 @@ export const UserDataKeys = {
|
|
|
254
259
|
authoringComponent: 'authoringComponent',
|
|
255
260
|
authoringDocument: 'authoringDocument',
|
|
256
261
|
authoringHierarchyId: 'authoringHierarchyId',
|
|
262
|
+
authoringHierarchyParentId: 'authoringHierarchyParentId',
|
|
257
263
|
authoringHierarchyOrder: 'authoringHierarchyOrder',
|
|
258
264
|
editorHelper: 'editorHelper',
|
|
259
265
|
editorHelperType: 'editorHelperType',
|
package/src/index.ts
CHANGED
|
@@ -32,7 +32,7 @@ export type {
|
|
|
32
32
|
ResolvedGameManifest,
|
|
33
33
|
RootAdapter,
|
|
34
34
|
} from './manifest';
|
|
35
|
-
export {
|
|
35
|
+
export { loadGameManifest } from './manifest';
|
|
36
36
|
export type { GameSession } from './runtime/create-runtime';
|
|
37
37
|
export type {
|
|
38
38
|
MountEntry,
|
|
@@ -72,6 +72,8 @@ export interface HostPointerTouch {
|
|
|
72
72
|
* differently is holding a button nothing will ever release.
|
|
73
73
|
*/
|
|
74
74
|
readonly phase: 'start' | 'move' | 'end';
|
|
75
|
+
/** True only when the browser ended this contact with `pointercancel`. */
|
|
76
|
+
readonly canceled: boolean;
|
|
75
77
|
/**
|
|
76
78
|
* DENSE finger index — the lowest slot free when this finger went down, and
|
|
77
79
|
* free again the moment it lifts. NOT the browser's `pointerId`, which never
|
|
@@ -80,6 +82,22 @@ export interface HostPointerTouch {
|
|
|
80
82
|
readonly index: number;
|
|
81
83
|
/** Position in the design space (see {@link HostPointerOptions.designSize}). */
|
|
82
84
|
readonly position: Vector2;
|
|
85
|
+
/** Position before design-resolution scaling, in surface CSS pixels. */
|
|
86
|
+
readonly screenPosition: Vector2;
|
|
87
|
+
/** Delta since this contact's preceding sample, in design pixels. */
|
|
88
|
+
readonly relative: Vector2;
|
|
89
|
+
/** Delta since this contact's preceding sample, in surface CSS pixels. */
|
|
90
|
+
readonly screenRelative: Vector2;
|
|
91
|
+
/** Design-pixel velocity derived from the browser event timestamps. */
|
|
92
|
+
readonly velocity: Vector2;
|
|
93
|
+
/** Surface CSS-pixel velocity derived from the browser event timestamps. */
|
|
94
|
+
readonly screenVelocity: Vector2;
|
|
95
|
+
/** Native PointerEvent pressure in the normalized [0, 1] range. */
|
|
96
|
+
readonly pressure: number;
|
|
97
|
+
/** Native PointerEvent tilt, in degrees. Touch contacts normally report zero. */
|
|
98
|
+
readonly tilt: Vector2;
|
|
99
|
+
/** Touch pointers are never an inverted pen; retained for Godot's event value contract. */
|
|
100
|
+
readonly penInverted: false;
|
|
83
101
|
}
|
|
84
102
|
|
|
85
103
|
/** What {@link createHostPointer} needs. */
|
|
@@ -141,6 +159,14 @@ export function createHostPointer(options: HostPointerOptions): HostPointer {
|
|
|
141
159
|
const touches: HostPointerTouch[] = [];
|
|
142
160
|
/** Browser `pointerId` -> dense finger index, for fingers currently down. */
|
|
143
161
|
const fingerOfPointer = new Map<number, number>();
|
|
162
|
+
const sampleOfPointer = new Map<
|
|
163
|
+
number,
|
|
164
|
+
{
|
|
165
|
+
readonly position: Vector2;
|
|
166
|
+
readonly screenPosition: Vector2;
|
|
167
|
+
readonly timestamp: number;
|
|
168
|
+
}
|
|
169
|
+
>();
|
|
144
170
|
const freeFinger = (): number => {
|
|
145
171
|
const taken = new Set(fingerOfPointer.values());
|
|
146
172
|
let index = 0;
|
|
@@ -152,11 +178,52 @@ export function createHostPointer(options: HostPointerOptions): HostPointer {
|
|
|
152
178
|
if (touches.length > TOUCH_QUEUE_MAX) touches.shift();
|
|
153
179
|
};
|
|
154
180
|
|
|
155
|
-
const queueTouch = (event: PointerEvent, point: Vector2): void => {
|
|
181
|
+
const queueTouch = (event: PointerEvent, point: Vector2, screenPoint: Vector2): void => {
|
|
182
|
+
const previous = sampleOfPointer.get(event.pointerId);
|
|
183
|
+
const relative =
|
|
184
|
+
previous === undefined
|
|
185
|
+
? { x: 0, y: 0 }
|
|
186
|
+
: { x: point.x - previous.position.x, y: point.y - previous.position.y };
|
|
187
|
+
const screenRelative =
|
|
188
|
+
previous === undefined
|
|
189
|
+
? { x: 0, y: 0 }
|
|
190
|
+
: {
|
|
191
|
+
x: screenPoint.x - previous.screenPosition.x,
|
|
192
|
+
y: screenPoint.y - previous.screenPosition.y,
|
|
193
|
+
};
|
|
194
|
+
const elapsedSeconds =
|
|
195
|
+
previous === undefined ? 0 : Math.max(0, event.timeStamp - previous.timestamp) / 1000;
|
|
196
|
+
const velocity =
|
|
197
|
+
elapsedSeconds > 0
|
|
198
|
+
? { x: relative.x / elapsedSeconds, y: relative.y / elapsedSeconds }
|
|
199
|
+
: { x: 0, y: 0 };
|
|
200
|
+
const screenVelocity =
|
|
201
|
+
elapsedSeconds > 0
|
|
202
|
+
? { x: screenRelative.x / elapsedSeconds, y: screenRelative.y / elapsedSeconds }
|
|
203
|
+
: { x: 0, y: 0 };
|
|
204
|
+
const common = {
|
|
205
|
+
position: point,
|
|
206
|
+
screenPosition: screenPoint,
|
|
207
|
+
relative,
|
|
208
|
+
screenRelative,
|
|
209
|
+
velocity,
|
|
210
|
+
screenVelocity,
|
|
211
|
+
pressure: Number.isFinite(event.pressure) ? Math.max(0, Math.min(1, event.pressure)) : 0,
|
|
212
|
+
tilt: {
|
|
213
|
+
x: Number.isFinite(event.tiltX) ? event.tiltX : 0,
|
|
214
|
+
y: Number.isFinite(event.tiltY) ? event.tiltY : 0,
|
|
215
|
+
},
|
|
216
|
+
penInverted: false as const,
|
|
217
|
+
};
|
|
156
218
|
if (event.type === 'pointerdown') {
|
|
157
219
|
const index = freeFinger();
|
|
158
220
|
fingerOfPointer.set(event.pointerId, index);
|
|
159
|
-
|
|
221
|
+
sampleOfPointer.set(event.pointerId, {
|
|
222
|
+
position: point,
|
|
223
|
+
screenPosition: screenPoint,
|
|
224
|
+
timestamp: event.timeStamp,
|
|
225
|
+
});
|
|
226
|
+
queue({ phase: 'start', canceled: false, index, ...common });
|
|
160
227
|
return;
|
|
161
228
|
}
|
|
162
229
|
// A move or a release from a pointer that never went down on this surface
|
|
@@ -165,10 +232,21 @@ export function createHostPointer(options: HostPointerOptions): HostPointer {
|
|
|
165
232
|
if (index === undefined) return;
|
|
166
233
|
if (event.type === 'pointerup' || event.type === 'pointercancel') {
|
|
167
234
|
fingerOfPointer.delete(event.pointerId);
|
|
168
|
-
|
|
235
|
+
sampleOfPointer.delete(event.pointerId);
|
|
236
|
+
queue({
|
|
237
|
+
phase: 'end',
|
|
238
|
+
canceled: event.type === 'pointercancel',
|
|
239
|
+
index,
|
|
240
|
+
...common,
|
|
241
|
+
});
|
|
169
242
|
return;
|
|
170
243
|
}
|
|
171
|
-
|
|
244
|
+
sampleOfPointer.set(event.pointerId, {
|
|
245
|
+
position: point,
|
|
246
|
+
screenPosition: screenPoint,
|
|
247
|
+
timestamp: event.timeStamp,
|
|
248
|
+
});
|
|
249
|
+
queue({ phase: 'move', canceled: false, index, ...common });
|
|
172
250
|
};
|
|
173
251
|
|
|
174
252
|
/** A client-space event as a point in the design space, via the surface rect
|
|
@@ -188,6 +266,7 @@ export function createHostPointer(options: HostPointerOptions): HostPointer {
|
|
|
188
266
|
if (surface === null) return;
|
|
189
267
|
const rect = surface.getBoundingClientRect();
|
|
190
268
|
if (rect.width <= 0 || rect.height <= 0) return;
|
|
269
|
+
const screenPoint = { x: event.clientX - rect.left, y: event.clientY - rect.top };
|
|
191
270
|
const point = toDesignSpace(event, rect);
|
|
192
271
|
|
|
193
272
|
if (event.type === 'pointermove') {
|
|
@@ -199,7 +278,7 @@ export function createHostPointer(options: HostPointerOptions): HostPointer {
|
|
|
199
278
|
}
|
|
200
279
|
// A mouse or a pen is not a finger. A control that answered them here would
|
|
201
280
|
// steal the clicks of a player who cannot see it.
|
|
202
|
-
if (event.pointerType === 'touch') queueTouch(event, point);
|
|
281
|
+
if (event.pointerType === 'touch') queueTouch(event, point, screenPoint);
|
|
203
282
|
};
|
|
204
283
|
|
|
205
284
|
const KINDS = ['pointerdown', 'pointermove', 'pointerup', 'pointercancel'] as const;
|