@vgai/engine 0.5.11 → 0.5.12
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 +6 -5
- package/dist/adapter/authoring.d.ts +51 -28
- package/dist/adapter/authoring.d.ts.map +1 -1
- package/dist/adapter/body-marks.d.ts +59 -0
- package/dist/adapter/body-marks.d.ts.map +1 -0
- package/dist/adapter/body-marks.js +62 -0
- package/dist/adapter/constraint.d.ts +41 -0
- package/dist/adapter/constraint.d.ts.map +1 -0
- package/dist/adapter/constraint.js +27 -0
- package/dist/adapter/hierarchy-marks.d.ts +138 -0
- package/dist/adapter/hierarchy-marks.d.ts.map +1 -0
- package/dist/adapter/hierarchy-marks.js +148 -0
- package/dist/adapter/index.d.ts +1 -1
- package/dist/adapter/index.d.ts.map +1 -1
- package/dist/adapter/ingest/contract-system-adapters.d.ts +64 -0
- package/dist/adapter/ingest/contract-system-adapters.d.ts.map +1 -0
- package/dist/adapter/ingest/contract-system-adapters.js +134 -0
- package/dist/adapter/ingest/game-contract.d.ts +87 -9
- package/dist/adapter/ingest/game-contract.d.ts.map +1 -1
- package/dist/adapter/ingest/game-contract.js +7 -6
- package/dist/adapter/ingest/scene-capture.d.ts +31 -4
- package/dist/adapter/ingest/scene-capture.d.ts.map +1 -1
- package/dist/adapter/ingest/scene-capture.js +29 -7
- package/dist/adapter/ingest/structural-ids.d.ts +1 -1
- package/dist/adapter/ingest/structural-ids.js +2 -2
- package/dist/adapter/reflection-probe.d.ts +53 -0
- package/dist/adapter/reflection-probe.d.ts.map +1 -0
- package/dist/adapter/reflection-probe.js +18 -0
- package/dist/asset-formats/index.d.ts +4 -10
- package/dist/asset-formats/index.d.ts.map +1 -1
- package/dist/asset-formats/index.js +3 -8
- package/dist/asset-formats/material.d.ts +0 -66
- package/dist/asset-formats/material.d.ts.map +1 -1
- package/dist/asset-formats/material.js +0 -8
- package/dist/asset-formats/mesh.d.ts +1 -2
- package/dist/asset-formats/mesh.d.ts.map +1 -1
- package/dist/asset-formats/mesh.js +3 -13
- package/dist/asset-formats/render-env.d.ts +2 -2
- package/dist/asset-parse-error.d.ts +4 -5
- package/dist/asset-parse-error.d.ts.map +1 -1
- package/dist/asset-parse-error.js +4 -5
- package/dist/config.d.ts +7 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +7 -0
- package/dist/data/curve.d.ts +116 -0
- package/dist/data/curve.d.ts.map +1 -0
- package/dist/data/curve.js +230 -0
- package/dist/data/vite-plugin-data.d.ts +2 -2
- package/dist/data/vite-plugin-data.d.ts.map +1 -1
- package/dist/data/vite-plugin-data.js +24 -15
- package/dist/dev/performance-profiler.d.ts +1 -0
- package/dist/dev/performance-profiler.d.ts.map +1 -1
- package/dist/dev/performance-profiler.js +25 -2
- package/dist/ecs/user-data.d.ts +49 -1
- package/dist/ecs/user-data.d.ts.map +1 -1
- package/dist/ecs/user-data.js +34 -0
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -3
- package/dist/manifest/index.d.ts +3 -3
- package/dist/manifest/index.d.ts.map +1 -1
- package/dist/manifest/index.js +2 -2
- package/dist/manifest/load.d.ts +15 -67
- package/dist/manifest/load.d.ts.map +1 -1
- package/dist/manifest/load.js +11 -103
- package/dist/manifest/schema.d.ts +18 -103
- package/dist/manifest/schema.d.ts.map +1 -1
- package/dist/manifest/schema.js +59 -179
- package/dist/pixi/index.d.ts +2 -3
- package/dist/pixi/index.d.ts.map +1 -1
- package/dist/pixi/index.js +2 -3
- package/dist/pixi/ingest.d.ts +7 -75
- package/dist/pixi/ingest.d.ts.map +1 -1
- package/dist/pixi/ingest.js +6 -14
- package/dist/pixi/scene-capture.d.ts +2 -2
- package/dist/pixi/scene-capture.js +2 -2
- package/dist/react/use-data.d.ts +10 -5
- package/dist/react/use-data.d.ts.map +1 -1
- package/dist/react/use-data.js +15 -15
- package/dist/render/viewport-shading.d.ts +1 -1
- package/dist/render/viewport-shading.d.ts.map +1 -1
- package/dist/render/viewport-shading.js +14 -0
- package/dist/runtime/create-runtime.d.ts +12 -0
- package/dist/runtime/create-runtime.d.ts.map +1 -1
- package/dist/runtime/create-runtime.js +7 -2
- package/dist/runtime/mount-game.d.ts +1 -1
- package/dist/runtime/mount-game.d.ts.map +1 -1
- package/dist/runtime/mount-manifest.d.ts.map +1 -1
- package/dist/runtime/mount-manifest.js +5 -1
- package/dist/world3d-react/r3f-adapter.d.ts.map +1 -1
- package/dist/world3d-react/r3f-adapter.js +69 -39
- package/dist/world3d-react/renderer-config.d.ts +15 -0
- package/dist/world3d-react/renderer-config.d.ts.map +1 -1
- package/dist/world3d-react/renderer-config.js +15 -0
- package/dist/world3d-react/world-context.d.ts +2 -1
- package/dist/world3d-react/world-context.d.ts.map +1 -1
- package/dist-config/config.js +140 -20
- package/dist-config/config.js.map +4 -4
- package/package.json +1 -1
- package/schemas/engine-capabilities.json +10 -10
- package/schemas/vgai-project.schema.json +21 -76
- package/src/adapter/authoring.ts +54 -31
- package/src/adapter/body-marks.ts +69 -0
- package/src/adapter/constraint.ts +71 -0
- package/src/adapter/hierarchy-marks.ts +155 -0
- package/src/adapter/index.ts +2 -3
- package/src/adapter/ingest/contract-system-adapters.ts +174 -0
- package/src/adapter/ingest/game-contract.ts +98 -9
- package/src/adapter/ingest/scene-capture.ts +61 -11
- package/src/adapter/ingest/structural-ids.ts +2 -2
- package/src/adapter/reflection-probe.ts +75 -0
- package/src/asset-formats/index.ts +4 -10
- package/src/asset-formats/material.ts +0 -11
- package/src/asset-formats/mesh.ts +3 -16
- package/src/asset-parse-error.ts +4 -5
- package/src/config.ts +13 -0
- package/src/data/curve.ts +263 -0
- package/src/data/vite-plugin-data.ts +48 -14
- package/src/dev/performance-profiler.ts +21 -2
- package/src/ecs/user-data.ts +50 -0
- package/src/index.ts +2 -3
- package/src/manifest/index.ts +3 -15
- package/src/manifest/load.ts +27 -143
- package/src/manifest/schema.ts +65 -223
- package/src/pixi/index.ts +2 -15
- package/src/pixi/ingest.ts +13 -87
- package/src/pixi/scene-capture.ts +2 -2
- package/src/react/use-data.ts +15 -20
- package/src/render/viewport-shading.ts +16 -1
- package/src/runtime/create-runtime.ts +30 -5
- package/src/runtime/mount-game.ts +1 -1
- package/src/runtime/mount-manifest.ts +5 -1
- package/src/world3d-react/r3f-adapter.tsx +73 -39
- package/src/world3d-react/renderer-config.ts +31 -0
- package/src/world3d-react/world-context.ts +2 -1
- package/dist/asset-formats/instances.d.ts +0 -17
- package/dist/asset-formats/instances.d.ts.map +0 -1
- package/dist/asset-formats/instances.js +0 -31
- package/dist/asset-formats/parse.d.ts +0 -20
- package/dist/asset-formats/parse.d.ts.map +0 -1
- package/dist/asset-formats/parse.js +0 -34
- package/dist/pixi/ingest-iframe.d.ts +0 -82
- package/dist/pixi/ingest-iframe.d.ts.map +0 -1
- package/dist/pixi/ingest-iframe.js +0 -166
- package/dist/render/instance-mesh.d.ts +0 -5
- package/dist/render/instance-mesh.d.ts.map +0 -1
- package/dist/render/instance-mesh.js +0 -19
- package/schemas/mat.schema.json +0 -255
- package/src/asset-formats/instances.ts +0 -38
- package/src/asset-formats/parse.ts +0 -39
- package/src/pixi/ingest-iframe.ts +0 -255
- package/src/render/instance-mesh.ts +0 -25
package/src/pixi/ingest.ts
CHANGED
|
@@ -1,88 +1,20 @@
|
|
|
1
1
|
import { installSceneCapture2D, type SceneCapture2DHandle } from './scene-capture';
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* A manifest's `extraDeps` resolve to TWO kinds of importmap entry:
|
|
5
|
-
* `namespaces` are today's registry-known bare specifiers
|
|
6
|
-
* (host-namespace-registry.ts), re-exported via a blob module
|
|
7
|
-
* (`ingest-iframe-2d.ts`'s `makeHostNamespaceReexportUrl`); `urls` are the
|
|
8
|
-
* D-Z3 fallback — a specifier that isn't registered but IS present in the
|
|
9
|
-
* open project's own `node_modules`, mapped DIRECTLY to its
|
|
10
|
-
* `/project-game-static/node_modules/<spec>/<esm entry>` URL (no host-side
|
|
11
|
-
* import, no blob — the dep executes in the iframe realm and its own
|
|
12
|
-
* transitive `import 'pixi.js'` resolves through the same importmap back to
|
|
13
|
-
* the host pixi trap). All probing/decision logic (which kind a specifier
|
|
14
|
-
* resolves to, exports-map parsing, anti-shim throws) lives editor-side
|
|
15
|
-
* (`host-namespace-registry.ts`) — this engine module only carries the
|
|
16
|
-
* ALREADY-DECIDED shape; `ingest-iframe-2d.ts` stays decision-free and just
|
|
17
|
-
* merges both maps into the iframe importmap.
|
|
18
|
-
*/
|
|
19
|
-
export interface ExtraDepsResolution2D {
|
|
20
|
-
namespaces: Record<string, Record<string, unknown>>;
|
|
21
|
-
urls: Record<string, string>;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
3
|
/** A registered unmodified PixiJS game (the Pixi analog of `IngestGame`). */
|
|
25
4
|
export interface IngestGame2D {
|
|
26
5
|
id: string;
|
|
27
6
|
name: string;
|
|
28
7
|
description: string;
|
|
29
|
-
/**
|
|
30
|
-
load
|
|
31
|
-
/**
|
|
32
|
-
tier?: 'shared' | 'iframe-reachable' | 'opaque-embed';
|
|
8
|
+
/** Import + run the unmodified game module in the host's own realm. */
|
|
9
|
+
load: () => Promise<unknown>;
|
|
10
|
+
/** How long to wait for the game's first captured frame before failing. */
|
|
33
11
|
captureTimeoutMs?: number;
|
|
34
|
-
/**
|
|
35
|
-
* IFRAME-REACHABLE-MULTI fields (Track P): an externalized built bundle
|
|
36
|
-
* mounted via `mountIngestGame2DIframeReachableMulti`
|
|
37
|
-
* (`./ingest-iframe-2d.ts`) instead of `load()` — populated only when `tier`
|
|
38
|
-
* is `'iframe-reachable'` AND `load` is absent. Mirror
|
|
39
|
-
* `IframeReachableMultiOpts`'s fields, EXCEPT `extraDeps`/`pixiNamespace` are
|
|
40
|
-
* THUNKS here, not resolved values — the same "lazy, only invoked at mount
|
|
41
|
-
* time" shape `load` already uses, so building this descriptor
|
|
42
|
-
* (`resolveIngest2DDescriptor` / the canvas surface's
|
|
43
|
-
* `ingest/surface-canvas.ts`, editor-side — Wave 0.6 replaced the three
|
|
44
|
-
* per-surface `discovery*.ts` modules with one manifest-driven registry) never
|
|
45
|
-
* has to be async just to wire up which specifiers/ version-skew URL a game
|
|
46
|
-
* needs; only actually MOUNTING it (the ingest-mode mount bridge) pays for the
|
|
47
|
-
* dynamic import of `@pixi/sound`/`gsap`/spine/ a standalone pixi build.
|
|
48
|
-
*/
|
|
49
|
-
bundleUrl?: string;
|
|
50
|
-
/** <base href> for the iframe (see `IframeReachableMultiOpts.baseHref`). */
|
|
51
|
-
baseHref?: string;
|
|
52
|
-
/** Host-side Assets.init basePath remap (see `IframeReachableMultiOpts.assetBaseUrl`). */
|
|
53
|
-
assetBaseUrl?: string;
|
|
54
|
-
/**
|
|
55
|
-
* Lazily resolve this game's bare-specifier -> extraDeps resolution via the
|
|
56
|
-
* editor's host-namespace registry. Absent (or omitted) means no extra deps
|
|
57
|
-
* beyond pixi.js.
|
|
58
|
-
*/
|
|
59
|
-
extraDeps?: () => Promise<ExtraDepsResolution2D>;
|
|
60
|
-
/**
|
|
61
|
-
* Lazily resolve the trapped-pixi namespace for version-skewed games (a
|
|
62
|
-
* dynamic `import()` of the manifest's `pixiModuleUrl`) — absent means
|
|
63
|
-
* "mount against the host's own `pixi.js`" (no skew).
|
|
64
|
-
*/
|
|
65
|
-
pixiNamespace?: () => Promise<unknown>;
|
|
66
|
-
/** DOM the game expects before boot (see `IframeReachableMultiOpts.bodyHtml`). */
|
|
67
|
-
bodyHtml?: string;
|
|
68
|
-
/**
|
|
69
|
-
* Lazily read an OPAQUE prebuilt bundle's self-contained HTML (D-W2) — the pixi
|
|
70
|
-
* twin of `IngestGame.embedHtml`. Always a lazy thunk here (no in-tree Pixi
|
|
71
|
-
* opaque-embed fixture exists yet to need a plain-string form, unlike the three
|
|
72
|
-
* side): `resolveIngest2DDescriptor` (adapter-resolver.ts) builds one that reads
|
|
73
|
-
* the declared `entryHtml` file's bytes through the `/project-game-static/`
|
|
74
|
-
* route, only when the game is actually mounted. The host runs the resolved HTML
|
|
75
|
-
* in a sandboxed iframe at the embed-only floor (Tier 0-1),
|
|
76
|
-
* `mountIngestGame2DEmbed` (`./ingest-iframe-2d.ts`).
|
|
77
|
-
*/
|
|
78
|
-
embedHtml?: () => Promise<string>;
|
|
79
12
|
}
|
|
80
13
|
|
|
81
14
|
export interface IngestMount2D {
|
|
82
|
-
/** The captured live stage Container
|
|
83
|
-
stage: unknown
|
|
15
|
+
/** The captured live stage Container. */
|
|
16
|
+
stage: unknown;
|
|
84
17
|
capture: SceneCapture2DHandle;
|
|
85
|
-
embedOnly: boolean;
|
|
86
18
|
setPaused(paused: boolean): void;
|
|
87
19
|
dispose(): void;
|
|
88
20
|
}
|
|
@@ -91,9 +23,8 @@ export interface IngestMount2D {
|
|
|
91
23
|
* Mount an UNMODIFIED PixiJS game via the shared-instance capture path — the 2D
|
|
92
24
|
* analog of `mountIngestGame`. Installs the render trap on the host's pixi
|
|
93
25
|
* instance, runs the game's `load()`, waits for the game to render its first
|
|
94
|
-
* frame (capturing its live stage), and exposes loop gating + cleanup.
|
|
95
|
-
*
|
|
96
|
-
* never a silent failure.
|
|
26
|
+
* frame (capturing its live stage), and exposes loop gating + cleanup. A game
|
|
27
|
+
* whose pixi the trap cannot reach never captures, and the mount FAILS by name.
|
|
97
28
|
*/
|
|
98
29
|
export async function mountIngestGame2D(
|
|
99
30
|
pixiNamespace: unknown,
|
|
@@ -102,7 +33,7 @@ export async function mountIngestGame2D(
|
|
|
102
33
|
): Promise<IngestMount2D> {
|
|
103
34
|
const capture = installSceneCapture2D(pixiNamespace);
|
|
104
35
|
try {
|
|
105
|
-
await game.load
|
|
36
|
+
await game.load();
|
|
106
37
|
} catch (err) {
|
|
107
38
|
capture.uninstall();
|
|
108
39
|
throw new Error(`pixi ingest: game "${game.id}" failed to load: ${err}`);
|
|
@@ -114,18 +45,13 @@ export async function mountIngestGame2D(
|
|
|
114
45
|
return {
|
|
115
46
|
stage: rt.stage,
|
|
116
47
|
capture,
|
|
117
|
-
embedOnly: false,
|
|
118
48
|
setPaused: (p) => capture.setPaused(p),
|
|
119
49
|
dispose: () => capture.uninstall(),
|
|
120
50
|
};
|
|
121
|
-
} catch {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
embedOnly: true,
|
|
127
|
-
setPaused: () => {},
|
|
128
|
-
dispose: () => capture.uninstall(),
|
|
129
|
-
};
|
|
51
|
+
} catch (err) {
|
|
52
|
+
capture.uninstall();
|
|
53
|
+
throw new Error(
|
|
54
|
+
`pixi ingest: game "${game.id}" rendered no capturable frame within ${timeout}ms: ${err}`,
|
|
55
|
+
);
|
|
130
56
|
}
|
|
131
57
|
}
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
* CRITICAL (same module-identity gatekeeper as the 3D path): the trap must be
|
|
15
15
|
* installed on the SAME `pixi.js` module instance the game uses. A bundler/dev-server
|
|
16
16
|
* that dedupes `pixi.js` makes an ESM game's `import 'pixi.js'` resolve to the host
|
|
17
|
-
* instance, so it is trapped; a game bundling its own pixi cannot be captured
|
|
18
|
-
*
|
|
17
|
+
* instance, so it is trapped; a game bundling its own pixi cannot be captured at
|
|
18
|
+
* all, and its mount fails by name.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
21
|
/** A live Pixi runtime captured from an external PixiJS game. */
|
package/src/react/use-data.ts
CHANGED
|
@@ -59,11 +59,16 @@ export function useData<T>(handle: DataHandle<T>): T {
|
|
|
59
59
|
* this rejects with a teaching error (a shipped game could never reach the
|
|
60
60
|
* route anyway — builds strip `src/tools/` entirely, §4).
|
|
61
61
|
*
|
|
62
|
-
*
|
|
63
|
-
* `
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
62
|
+
* The body is PARSED VALUES, never serialized text: the dev server's fold
|
|
63
|
+
* (`packages/editor/server/data-file-serialize.ts`) owns key order and the
|
|
64
|
+
* `"$schema"`-first diff-minimal serialization, and it must — a parsed JS
|
|
65
|
+
* object has already reindexed integer-like keys ("1","2","10"), so only the
|
|
66
|
+
* server, which still has the file's raw text, can keep a one-field write a
|
|
67
|
+
* one-line diff. When `value` carries no `"$schema"` key (the common case —
|
|
68
|
+
* `DataHandle.get()` strips it), the conventional sibling reference
|
|
69
|
+
* (`./<name>.schema.json`, §2.1) is restored so a tool write never silently
|
|
70
|
+
* drops VS Code validation from the file. Undo for data writes is git;
|
|
71
|
+
* every accepted write is recorded server-side as a project revision.
|
|
67
72
|
*/
|
|
68
73
|
export async function writeData(
|
|
69
74
|
projectRelativePath: string,
|
|
@@ -77,9 +82,9 @@ export async function writeData(
|
|
|
77
82
|
);
|
|
78
83
|
}
|
|
79
84
|
|
|
80
|
-
// "$schema"
|
|
81
|
-
//
|
|
82
|
-
//
|
|
85
|
+
// Restore the conventional sibling "$schema" reference when the caller's
|
|
86
|
+
// object (typically `{ ...handle.get() }`, which never carries it) omits
|
|
87
|
+
// it; the server fold serializes it first.
|
|
83
88
|
const { $schema, ...rest } = value;
|
|
84
89
|
const schemaRef =
|
|
85
90
|
$schema ??
|
|
@@ -87,24 +92,14 @@ export async function writeData(
|
|
|
87
92
|
.split('/')
|
|
88
93
|
.pop()
|
|
89
94
|
?.replace(/\.data\.json$/, '')}.schema.json`;
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
const transactionalWriter = (
|
|
93
|
-
globalThis as typeof globalThis & {
|
|
94
|
-
__vgaiHistoryWriteData?: (path: string, content: string) => Promise<void>;
|
|
95
|
-
}
|
|
96
|
-
).__vgaiHistoryWriteData;
|
|
97
|
-
if (transactionalWriter) {
|
|
98
|
-
await transactionalWriter(projectRelativePath, content);
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
95
|
+
const values = { $schema: schemaRef, ...rest };
|
|
101
96
|
|
|
102
97
|
let res: Response;
|
|
103
98
|
try {
|
|
104
99
|
res = await fetch('/__editor/data-file', {
|
|
105
100
|
method: 'POST',
|
|
106
101
|
headers: { 'Content-Type': 'application/json' },
|
|
107
|
-
body: JSON.stringify({ path: projectRelativePath,
|
|
102
|
+
body: JSON.stringify({ path: projectRelativePath, values }),
|
|
108
103
|
});
|
|
109
104
|
} catch (err) {
|
|
110
105
|
throw new Error(
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import * as THREE from 'three';
|
|
2
2
|
|
|
3
3
|
/** Temporary developer-facing shading modes. These never become scene data. */
|
|
4
|
-
export type ViewportShadingMode = 'solid' | 'unlit' | 'wireframe' | 'normals' | 'overdraw';
|
|
4
|
+
export type ViewportShadingMode = 'solid' | 'clay' | 'unlit' | 'wireframe' | 'normals' | 'overdraw';
|
|
5
5
|
|
|
6
6
|
type MaterialPair = {
|
|
7
|
+
clay: THREE.MeshStandardMaterial;
|
|
7
8
|
unlit: THREE.MeshBasicMaterial;
|
|
8
9
|
wireframe: THREE.MeshBasicMaterial;
|
|
9
10
|
};
|
|
@@ -73,6 +74,7 @@ export class ViewportShadingRenderer {
|
|
|
73
74
|
|
|
74
75
|
dispose(): void {
|
|
75
76
|
for (const pair of this._derived.values()) {
|
|
77
|
+
pair.clay.dispose();
|
|
76
78
|
pair.unlit.dispose();
|
|
77
79
|
pair.wireframe.dispose();
|
|
78
80
|
}
|
|
@@ -106,6 +108,19 @@ export class ViewportShadingRenderer {
|
|
|
106
108
|
fog: (material as THREE.Material & { fog?: boolean }).fog ?? true,
|
|
107
109
|
};
|
|
108
110
|
pair = {
|
|
111
|
+
clay: new THREE.MeshStandardMaterial({
|
|
112
|
+
color: 0xaeb6c0,
|
|
113
|
+
roughness: 0.82,
|
|
114
|
+
metalness: 0,
|
|
115
|
+
flatShading: true,
|
|
116
|
+
alphaMap: textureOf(material, 'alphaMap'),
|
|
117
|
+
alphaTest: material.alphaTest,
|
|
118
|
+
opacity: material.opacity,
|
|
119
|
+
transparent: material.transparent,
|
|
120
|
+
side: material.side,
|
|
121
|
+
depthTest: material.depthTest,
|
|
122
|
+
depthWrite: material.depthWrite,
|
|
123
|
+
}),
|
|
109
124
|
unlit: new THREE.MeshBasicMaterial(common),
|
|
110
125
|
wireframe: new THREE.MeshBasicMaterial({ ...common, wireframe: true }),
|
|
111
126
|
};
|
|
@@ -280,6 +280,18 @@ export interface RootsRuntimeConfig {
|
|
|
280
280
|
* a 2D canvas renderer with no GPU. Never set `true` in a real host.
|
|
281
281
|
*/
|
|
282
282
|
headless?: boolean | undefined;
|
|
283
|
+
/**
|
|
284
|
+
* `vgai.project.json`'s `rendering.antialias` — whether every three root's
|
|
285
|
+
* WebGL context is built with a multisampled drawing buffer.
|
|
286
|
+
*
|
|
287
|
+
* It is a RUNTIME-CONFIG option rather than a world's own
|
|
288
|
+
* `WorldRendererConfig` field for the reason that file's header gives: a
|
|
289
|
+
* context's sample count is fixed at CREATION, before any world exists, so
|
|
290
|
+
* there is no honest moment at which a world could ask for it. The
|
|
291
|
+
* manifest-aware boot path (`mount-manifest.ts`) is the real reader;
|
|
292
|
+
* omitting it leaves `createHostRenderer`'s own registry default alone.
|
|
293
|
+
*/
|
|
294
|
+
antialias?: boolean | undefined;
|
|
283
295
|
/** D15 (T-D15.1) — the root seed `ctx.random` boots from on every world
|
|
284
296
|
* mounted onto this session's Game, forwarded to `createGame` BEFORE any
|
|
285
297
|
* world's `mount()`/`setup()` runs (this function constructs the Game
|
|
@@ -414,6 +426,9 @@ interface OneRootContext {
|
|
|
414
426
|
readonly dpr: number;
|
|
415
427
|
readonly isBottom: boolean;
|
|
416
428
|
readonly headless: boolean;
|
|
429
|
+
/** `RootsRuntimeConfig.antialias` — see that field. Undefined leaves
|
|
430
|
+
* `createHostRenderer`'s own registry default alone. */
|
|
431
|
+
readonly antialias: boolean | undefined;
|
|
417
432
|
readonly assets: ReturnType<typeof createAssetCache>;
|
|
418
433
|
}
|
|
419
434
|
|
|
@@ -425,13 +440,22 @@ async function mountOneThreeRoot(
|
|
|
425
440
|
spec: ThreeRootMountSpec,
|
|
426
441
|
ctx: OneRootContext,
|
|
427
442
|
): Promise<OneRootResult> {
|
|
428
|
-
const { game, canvas, w, h, dpr, isBottom, headless, assets } = ctx;
|
|
443
|
+
const { game, canvas, w, h, dpr, isBottom, headless, assets, antialias } = ctx;
|
|
429
444
|
const renderer = headless
|
|
430
445
|
? createHeadlessRendererStub()
|
|
431
|
-
: createHostRenderer(
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
446
|
+
: createHostRenderer(
|
|
447
|
+
canvas,
|
|
448
|
+
w,
|
|
449
|
+
h,
|
|
450
|
+
// The manifest's `rendering.antialias` reaches the WebGL context here and NOWHERE else:
|
|
451
|
+
// `createHostRenderer` passes it straight to the constructor, and the sample count is
|
|
452
|
+
// fixed from that moment. Omitted → the render-settings registry's own default.
|
|
453
|
+
antialias === undefined ? undefined : { antialias },
|
|
454
|
+
{
|
|
455
|
+
alpha: !isBottom,
|
|
456
|
+
preserveDrawingBuffer: true,
|
|
457
|
+
},
|
|
458
|
+
);
|
|
435
459
|
renderer.setSize(w, h, false); // backing resolution only — CSS stacking owns layout size
|
|
436
460
|
// Defect E4.R1 (Fable review): `createHostRenderer`'s OWN construction-time
|
|
437
461
|
// `setSize` call (`setup-renderer.ts`, `updateStyle` defaulting `true` —
|
|
@@ -896,6 +920,7 @@ async function createRootsGameRuntime(config: RootsRuntimeConfig): Promise<GameS
|
|
|
896
920
|
dpr,
|
|
897
921
|
headless,
|
|
898
922
|
assets,
|
|
923
|
+
antialias: config.antialias,
|
|
899
924
|
});
|
|
900
925
|
|
|
901
926
|
// --- Delegating input router (D5 §2a) ---
|
|
@@ -56,7 +56,7 @@ export interface ManifestHost {
|
|
|
56
56
|
/** Resolve asset/scene URLs relative to the project — forwarded to a
|
|
57
57
|
* registered {@link AdapterSurfaceFactory} via {@link AdapterSurfaceFactoryContext},
|
|
58
58
|
* never called by this module itself (a factory only needs it for a
|
|
59
|
-
* non-default resolution scheme, e.g. a
|
|
59
|
+
* non-default resolution scheme, e.g. a project served under a base path). */
|
|
60
60
|
resolveUrl?(path: string): string;
|
|
61
61
|
readonly width?: number | undefined;
|
|
62
62
|
readonly height?: number | undefined;
|
|
@@ -276,7 +276,7 @@ function resolveThreeAdapter(
|
|
|
276
276
|
throw new Error(
|
|
277
277
|
`mountManifestRoots: world "${world.id}" (three) declares an { ingest } adapter — ` +
|
|
278
278
|
"ingest roots require the editor's dev-server-backed mount machinery (an EditorStore " +
|
|
279
|
-
"plus
|
|
279
|
+
"plus in-realm scene capture, see adapter-resolver.ts's resolveIngestThreeAdapter) and are " +
|
|
280
280
|
'not supported by mountManifestRoots (no porting aids, no hosted ingest routes).',
|
|
281
281
|
);
|
|
282
282
|
}
|
|
@@ -442,6 +442,10 @@ export async function mountManifestRoots(opts: MountManifestOptions): Promise<Ga
|
|
|
442
442
|
width: opts.width ?? manifest.resolution?.width,
|
|
443
443
|
height: opts.height ?? manifest.resolution?.height,
|
|
444
444
|
headless: opts.headless,
|
|
445
|
+
// `rendering.antialias` reaches the WebGL context at CONSTRUCTION and can be honoured
|
|
446
|
+
// nowhere else — see the manifest schema's own `rendering` block and
|
|
447
|
+
// `world3d-react/renderer-config.ts`'s header for why it is not a world-level declaration.
|
|
448
|
+
...(manifest.rendering === undefined ? {} : { antialias: manifest.rendering.antialias }),
|
|
445
449
|
seed: resolvedSeed,
|
|
446
450
|
playtest: opts.playtest,
|
|
447
451
|
});
|
|
@@ -29,7 +29,14 @@ import {
|
|
|
29
29
|
import { createElement, type ReactNode } from 'react';
|
|
30
30
|
import type { MountedThreeRoot, RootAdapter, ThreeHostContext } from '../adapter';
|
|
31
31
|
import { type RenderVitalsRegistration, registerRenderVitals } from '../dev/register-render-vitals';
|
|
32
|
+
import {
|
|
33
|
+
createRenderDebugAdapter,
|
|
34
|
+
frameCaptureContextFor,
|
|
35
|
+
type RenderDebugWiring,
|
|
36
|
+
} from '../dev/render-debug-adapter';
|
|
37
|
+
import { collectRenderMemory } from '../dev/render-memory';
|
|
32
38
|
import { RENDER_SUBMIT_PHASE } from '../dev/render-vitals';
|
|
39
|
+
import { createWebGLFrameCapture } from '../dev/webgl-frame-capture';
|
|
33
40
|
import { WorldProvider } from '../react/world-state';
|
|
34
41
|
import { devLayersEnabled } from '../runtime/dev-layers';
|
|
35
42
|
import { EngineBridge, type EngineBridgeValue } from './engine-bridge';
|
|
@@ -395,6 +402,26 @@ export function createR3FAdapter(options: CreateR3FAdapterOptions): RootAdapter
|
|
|
395
402
|
});
|
|
396
403
|
}
|
|
397
404
|
|
|
405
|
+
// Engine-owned render introspection, built over the SAME renderer and
|
|
406
|
+
// scene Fiber uses. A design-time stand-in has no context and a
|
|
407
|
+
// headless mount returned above, so both honestly omit the capability.
|
|
408
|
+
// `frameCaptureContextFor` is the same construction gate as the classic
|
|
409
|
+
// Three adapter; no editor-side renderer inference is involved.
|
|
410
|
+
const rendererContext =
|
|
411
|
+
typeof host.renderer.getContext === 'function' ? host.renderer.getContext() : undefined;
|
|
412
|
+
const frameCaptureContext = frameCaptureContextFor(false, rendererContext);
|
|
413
|
+
const frameCapture = frameCaptureContext
|
|
414
|
+
? createWebGLFrameCapture(frameCaptureContext)
|
|
415
|
+
: null;
|
|
416
|
+
const renderDebugWiring: RenderDebugWiring | null = frameCapture
|
|
417
|
+
? createRenderDebugAdapter({
|
|
418
|
+
capture: frameCapture,
|
|
419
|
+
scene: state.scene,
|
|
420
|
+
memory: () => collectRenderMemory(live().scene, host.renderer.info),
|
|
421
|
+
})
|
|
422
|
+
: null;
|
|
423
|
+
if (renderDebugWiring) runtime.systemAdapters.renderDebug = renderDebugWiring.adapter;
|
|
424
|
+
|
|
398
425
|
// The engine drives every `useFrame` through the mounted world's
|
|
399
426
|
// `update(dt)` hook, never off a raw host-loop callback. That is the
|
|
400
427
|
// whole pause story: `runFrameImpl` (`runtime/game.ts`) calls
|
|
@@ -447,9 +474,10 @@ export function createR3FAdapter(options: CreateR3FAdapterOptions): RootAdapter
|
|
|
447
474
|
return live().camera;
|
|
448
475
|
},
|
|
449
476
|
drivesOwnLoop: false,
|
|
450
|
-
// Adapter surface: `debug`
|
|
451
|
-
//
|
|
452
|
-
// `ctx.registerSystemAdapter` exactly
|
|
477
|
+
// Adapter surface: `debug` (the shared game registry) and, when a real
|
|
478
|
+
// WebGL2 context exists, `renderDebug` are engine-seeded. Game code
|
|
479
|
+
// adds its own capabilities via `ctx.registerSystemAdapter` exactly
|
|
480
|
+
// as in a classic world.
|
|
453
481
|
systems: runtime.systemAdapters,
|
|
454
482
|
update(dt: number): void {
|
|
455
483
|
elapsed += dt;
|
|
@@ -467,50 +495,56 @@ export function createR3FAdapter(options: CreateR3FAdapterOptions): RootAdapter
|
|
|
467
495
|
// then fiber's advance (useFrame callbacks + the actual render see
|
|
468
496
|
// the fresh state). Both are host-gated: neither runs while frozen.
|
|
469
497
|
systems.run(dt);
|
|
470
|
-
|
|
471
|
-
if (!profiler?.enabled) {
|
|
472
|
-
advance(elapsed, true, current);
|
|
473
|
-
return;
|
|
474
|
-
}
|
|
475
|
-
// Issue #1504's measurement, produced where the draw actually
|
|
476
|
-
// happens. `advance()` under `frameloop: 'never'` is what calls
|
|
477
|
-
// `gl.render(scene, camera)`, so this bracket — not a phase span
|
|
478
|
-
// inside `systems` — is the frame's CPU submission cost, and it is
|
|
479
|
-
// also what makes this frame a PRESENTATION as far as the vitals
|
|
480
|
-
// fold is concerned (`../dev/render-vitals.ts`: no bracket, no
|
|
481
|
-
// display frame). The profiler's phase clock is a stack, so
|
|
482
|
-
// bracketing here cannot truncate an enclosing phase.
|
|
483
|
-
const info = host.renderer.info as RendererCounters | undefined;
|
|
484
|
-
const passesBefore = info?.render.frame ?? 0;
|
|
485
|
-
profiler.beginPhase();
|
|
498
|
+
renderDebugWiring?.beforeRender();
|
|
486
499
|
try {
|
|
487
|
-
|
|
500
|
+
const profiler = host.game?.profiler;
|
|
501
|
+
if (!profiler?.enabled) {
|
|
502
|
+
advance(elapsed, true, current);
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
// Issue #1504's measurement, produced where the draw actually
|
|
506
|
+
// happens. `advance()` under `frameloop: 'never'` is what calls
|
|
507
|
+
// `gl.render(scene, camera)`, so this bracket — not a phase span
|
|
508
|
+
// inside `systems` — is the frame's CPU submission cost, and it is
|
|
509
|
+
// also what makes this frame a PRESENTATION as far as the vitals
|
|
510
|
+
// fold is concerned (`../dev/render-vitals.ts`: no bracket, no
|
|
511
|
+
// display frame). The profiler's phase clock is a stack, so
|
|
512
|
+
// bracketing here cannot truncate an enclosing phase.
|
|
513
|
+
const info = host.renderer.info as RendererCounters | undefined;
|
|
514
|
+
const passesBefore = info?.render.frame ?? 0;
|
|
515
|
+
profiler.beginPhase();
|
|
516
|
+
try {
|
|
517
|
+
advance(elapsed, true, current);
|
|
518
|
+
} finally {
|
|
519
|
+
profiler.endPhase(RENDER_SUBMIT_PHASE);
|
|
520
|
+
}
|
|
521
|
+
// Checked, not assumed — a duck-typed/design-time renderer supplies
|
|
522
|
+
// only what a mount needs, and a mount with no counters must report
|
|
523
|
+
// NOTHING rather than throw once per frame (the classic adapter's
|
|
524
|
+
// `postFrame` pays for the same assumption for the same reason).
|
|
525
|
+
// `gpuMs` is null: this path runs no GPU timer, and the profiler
|
|
526
|
+
// keeps the previous reading rather than inventing a zero.
|
|
527
|
+
if (info) {
|
|
528
|
+
profiler.reportRender({
|
|
529
|
+
gpuMs: null,
|
|
530
|
+
drawCalls: info.render.calls,
|
|
531
|
+
triangles: info.render.triangles,
|
|
532
|
+
geometries: info.memory.geometries,
|
|
533
|
+
textures: info.memory.textures,
|
|
534
|
+
renderPasses: info.render.frame - passesBefore,
|
|
535
|
+
});
|
|
536
|
+
}
|
|
488
537
|
} finally {
|
|
489
|
-
|
|
490
|
-
}
|
|
491
|
-
// Checked, not assumed — a duck-typed/design-time renderer supplies
|
|
492
|
-
// only what a mount needs, and a mount with no counters must report
|
|
493
|
-
// NOTHING rather than throw once per frame (the classic adapter's
|
|
494
|
-
// `postFrame` pays for the same assumption for the same reason).
|
|
495
|
-
// `gpuMs` is null: this path runs no GPU timer, and the profiler
|
|
496
|
-
// keeps the previous reading rather than inventing a zero.
|
|
497
|
-
if (info) {
|
|
498
|
-
profiler.reportRender({
|
|
499
|
-
gpuMs: null,
|
|
500
|
-
drawCalls: info.render.calls,
|
|
501
|
-
triangles: info.render.triangles,
|
|
502
|
-
geometries: info.memory.geometries,
|
|
503
|
-
textures: info.memory.textures,
|
|
504
|
-
renderPasses: info.render.frame - passesBefore,
|
|
505
|
-
});
|
|
538
|
+
renderDebugWiring?.afterRender();
|
|
506
539
|
}
|
|
507
540
|
},
|
|
508
541
|
resize(width: number, height: number): void {
|
|
509
542
|
live().setSize(width, height);
|
|
510
543
|
},
|
|
511
544
|
dispose(): void {
|
|
512
|
-
//
|
|
513
|
-
//
|
|
545
|
+
// Reject/restore a pending capture while its renderables still
|
|
546
|
+
// exist, then unmount component effects and strip runtime state.
|
|
547
|
+
renderDebugWiring?.dispose();
|
|
514
548
|
root.unmount();
|
|
515
549
|
// The vitals fold owns two `profiler.subscribe` registrations, and
|
|
516
550
|
// `runtime.dispose()`'s `strip(id)` removes the REGISTRATIONS only —
|
|
@@ -47,11 +47,27 @@ export type WorldToneMapping =
|
|
|
47
47
|
*/
|
|
48
48
|
export type WorldOutputColorSpace = 'srgb' | 'srgb-linear';
|
|
49
49
|
|
|
50
|
+
/**
|
|
51
|
+
* The shadow-map filter, named as data rather than as three's numeric enum.
|
|
52
|
+
*
|
|
53
|
+
* This is a renderer INSTANCE property (`WebGLRenderer.shadowMap.type`), not a context attribute,
|
|
54
|
+
* so unlike MSAA it has an honest moment at which a world can ask for it — which is the whole test
|
|
55
|
+
* this file's header states. A source engine that declares its own shadow filter (Godot 3's
|
|
56
|
+
* `rendering/quality/shadows/filter_mode`) would otherwise inherit whatever the host built with.
|
|
57
|
+
*/
|
|
58
|
+
export type WorldShadowMapType = 'basic' | 'pcf' | 'pcf-soft' | 'vsm';
|
|
59
|
+
|
|
50
60
|
/** What a world may declare about the renderer that draws it. Every field is optional; see header. */
|
|
51
61
|
export interface WorldRendererConfig {
|
|
52
62
|
readonly toneMapping?: WorldToneMapping | undefined;
|
|
53
63
|
readonly toneMappingExposure?: number | undefined;
|
|
54
64
|
readonly outputColorSpace?: WorldOutputColorSpace | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* `WebGLRenderer.shadowMap.type`. Writing it after a shadow map has already been built needs
|
|
67
|
+
* `shadowMap.needsUpdate`, which this function sets — three caches the compiled depth material
|
|
68
|
+
* per type and would otherwise keep filtering with the previous one.
|
|
69
|
+
*/
|
|
70
|
+
readonly shadowMapType?: WorldShadowMapType | undefined;
|
|
55
71
|
/**
|
|
56
72
|
* The colour the frame is cleared to, as a CSS hex string. The renderer's existing clear ALPHA
|
|
57
73
|
* is preserved: a stacked canvas is transparent on purpose (`create-runtime.ts` gives every
|
|
@@ -95,6 +111,12 @@ export function applyWorldRendererConfig(
|
|
|
95
111
|
srgb: three.SRGBColorSpace,
|
|
96
112
|
'srgb-linear': three.LinearSRGBColorSpace,
|
|
97
113
|
};
|
|
114
|
+
const shadowMapTypes: Record<WorldShadowMapType, THREE.ShadowMapType> = {
|
|
115
|
+
basic: three.BasicShadowMap,
|
|
116
|
+
pcf: three.PCFShadowMap,
|
|
117
|
+
'pcf-soft': three.PCFSoftShadowMap,
|
|
118
|
+
vsm: three.VSMShadowMap,
|
|
119
|
+
};
|
|
98
120
|
|
|
99
121
|
const restores: (() => void)[] = [];
|
|
100
122
|
|
|
@@ -119,6 +141,15 @@ export function applyWorldRendererConfig(
|
|
|
119
141
|
renderer.outputColorSpace = previous;
|
|
120
142
|
});
|
|
121
143
|
}
|
|
144
|
+
if (config.shadowMapType !== undefined && renderer.shadowMap !== undefined) {
|
|
145
|
+
const previous = renderer.shadowMap.type;
|
|
146
|
+
renderer.shadowMap.type = shadowMapTypes[config.shadowMapType];
|
|
147
|
+
renderer.shadowMap.needsUpdate = true;
|
|
148
|
+
restores.push(() => {
|
|
149
|
+
renderer.shadowMap.type = previous;
|
|
150
|
+
renderer.shadowMap.needsUpdate = true;
|
|
151
|
+
});
|
|
152
|
+
}
|
|
122
153
|
if (config.clearColor !== undefined) {
|
|
123
154
|
const previousColor = new three.Color();
|
|
124
155
|
renderer.getClearColor(previousColor);
|
|
@@ -130,7 +130,8 @@ export interface R3FRootRuntime {
|
|
|
130
130
|
/** The world-local phase runner `mount().update(dt)` ticks. */
|
|
131
131
|
readonly systems: ReturnType<typeof createSystemRunner>;
|
|
132
132
|
/** The mounted world's `SystemAdapters` bag (`mounted.systems`) —
|
|
133
|
-
* `ctx.registerSystemAdapter` writes into it; `debug` is pre-seeded
|
|
133
|
+
* `ctx.registerSystemAdapter` writes into it; `debug` is pre-seeded here,
|
|
134
|
+
* and the R3F mount adds renderer-backed engine capabilities after commit. */
|
|
134
135
|
readonly systemAdapters: SystemAdapters;
|
|
135
136
|
/** The registry every registration of this world's lands in — the game's
|
|
136
137
|
* own when a `Game` hosts it, a private mount-local one otherwise. Exposed
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
/**
|
|
3
|
-
* `.instances.json` — a declarative, authored-data instance-transform asset
|
|
4
|
-
* (F3). Referenced by `mesh.instances` as a bare array of 10-number tuples,
|
|
5
|
-
* one per instance, each `[posX,posY,posZ, quatX,quatY,quatZ,quatW,
|
|
6
|
-
* scaleX,scaleY,scaleZ]`. The scene loader fetches+parses this file and
|
|
7
|
-
* renders it as one `THREE.InstancedMesh` (one draw call) — bulk transform
|
|
8
|
-
* data is referenced as an asset, never inlined into the referencing
|
|
9
|
-
* document (gate G4).
|
|
10
|
-
*
|
|
11
|
-
* WO-8: the document that referenced it was `.vscn.json`, and that format is
|
|
12
|
-
* deleted. `.instances.json` survives as a FETCHED-ASSET format with its own
|
|
13
|
-
* `parseInstancesFile` — nothing in the shipped tree references one today.
|
|
14
|
-
*/
|
|
15
|
-
export declare const InstancesFileSchema: z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber, z.ZodNumber, z.ZodNumber, z.ZodNumber, z.ZodNumber, z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
|
|
16
|
-
export type InstancesFile = z.infer<typeof InstancesFileSchema>;
|
|
17
|
-
//# sourceMappingURL=instances.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"instances.d.ts","sourceRoot":"","sources":["../../src/asset-formats/instances.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,mBAAmB,kKAoB7B,CAAC;AAEJ,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC"}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
/**
|
|
3
|
-
* `.instances.json` — a declarative, authored-data instance-transform asset
|
|
4
|
-
* (F3). Referenced by `mesh.instances` as a bare array of 10-number tuples,
|
|
5
|
-
* one per instance, each `[posX,posY,posZ, quatX,quatY,quatZ,quatW,
|
|
6
|
-
* scaleX,scaleY,scaleZ]`. The scene loader fetches+parses this file and
|
|
7
|
-
* renders it as one `THREE.InstancedMesh` (one draw call) — bulk transform
|
|
8
|
-
* data is referenced as an asset, never inlined into the referencing
|
|
9
|
-
* document (gate G4).
|
|
10
|
-
*
|
|
11
|
-
* WO-8: the document that referenced it was `.vscn.json`, and that format is
|
|
12
|
-
* deleted. `.instances.json` survives as a FETCHED-ASSET format with its own
|
|
13
|
-
* `parseInstancesFile` — nothing in the shipped tree references one today.
|
|
14
|
-
*/
|
|
15
|
-
export const InstancesFileSchema = z
|
|
16
|
-
.array(z.tuple([
|
|
17
|
-
z.number().describe('posX'),
|
|
18
|
-
z.number().describe('posY'),
|
|
19
|
-
z.number().describe('posZ'),
|
|
20
|
-
z.number().describe('quatX'),
|
|
21
|
-
z.number().describe('quatY'),
|
|
22
|
-
z.number().describe('quatZ'),
|
|
23
|
-
z.number().describe('quatW'),
|
|
24
|
-
z.number().describe('scaleX'),
|
|
25
|
-
z.number().describe('scaleY'),
|
|
26
|
-
z.number().describe('scaleZ'),
|
|
27
|
-
]))
|
|
28
|
-
.describe('Instance-transform asset (.instances.json): an array of 10-number tuples ' +
|
|
29
|
-
'[posX,posY,posZ, quatX,quatY,quatZ,quatW, scaleX,scaleY,scaleZ], one per instance. ' +
|
|
30
|
-
'Referenced by a mesh via `mesh.instances` and rendered as a single THREE.InstancedMesh ' +
|
|
31
|
-
'(one draw call).');
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { AssetParseError } from '../asset-parse-error';
|
|
2
|
-
import type { InstancesFile } from './instances';
|
|
3
|
-
import type { MaterialFile } from './material';
|
|
4
|
-
export { AssetParseError };
|
|
5
|
-
/**
|
|
6
|
-
* Parse a `.mat.json` shared material asset (T4.6). There is no version-range
|
|
7
|
-
* gate for this format — `MaterialFileSchema`'s `version` field is RESERVED
|
|
8
|
-
* (see `schema-consumption-map.ts`).
|
|
9
|
-
*
|
|
10
|
-
* Formerly `@engine/scene/parse`'s `parseMaterialFile`; moved here when WO-8
|
|
11
|
-
* deleted the `.vscn` scene format that module was named for.
|
|
12
|
-
*/
|
|
13
|
-
export declare function parseMaterialFile(json: unknown, filePath?: string): MaterialFile;
|
|
14
|
-
/**
|
|
15
|
-
* Parse a `.instances.json` instance-transform asset (F3). Mirrors
|
|
16
|
-
* `parseMaterialFile` exactly — no version-range gate (the format is a bare
|
|
17
|
-
* tuple array, no `version` field).
|
|
18
|
-
*/
|
|
19
|
-
export declare function parseInstancesFile(json: unknown, filePath?: string): InstancesFile;
|
|
20
|
-
//# sourceMappingURL=parse.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/asset-formats/parse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAM/C,OAAO,EAAE,eAAe,EAAE,CAAC;AAE3B;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,YAAY,CAMhF;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,aAAa,CAMlF"}
|