@triscope/core 0.4.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/LICENSE +21 -0
- package/README.md +39 -0
- package/dist/compose.d.ts +11 -0
- package/dist/compose.d.ts.map +1 -0
- package/dist/compose.js +152 -0
- package/dist/compose.js.map +1 -0
- package/dist/editor.d.ts +14 -0
- package/dist/editor.d.ts.map +1 -0
- package/dist/editor.js +131 -0
- package/dist/editor.js.map +1 -0
- package/dist/harness.d.ts +199 -0
- package/dist/harness.d.ts.map +1 -0
- package/dist/harness.js +1027 -0
- package/dist/harness.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/inspect.d.ts +94 -0
- package/dist/inspect.d.ts.map +1 -0
- package/dist/inspect.js +434 -0
- package/dist/inspect.js.map +1 -0
- package/dist/knob-utils.d.ts +22 -0
- package/dist/knob-utils.d.ts.map +1 -0
- package/dist/knob-utils.js +51 -0
- package/dist/knob-utils.js.map +1 -0
- package/dist/lab/css.d.ts +11 -0
- package/dist/lab/css.d.ts.map +1 -0
- package/dist/lab/css.js +57 -0
- package/dist/lab/css.js.map +1 -0
- package/dist/lab/dom.d.ts +13 -0
- package/dist/lab/dom.d.ts.map +1 -0
- package/dist/lab/dom.js +76 -0
- package/dist/lab/dom.js.map +1 -0
- package/dist/motion-probe.d.ts +47 -0
- package/dist/motion-probe.d.ts.map +1 -0
- package/dist/motion-probe.js +122 -0
- package/dist/motion-probe.js.map +1 -0
- package/dist/probe-utils.d.ts +14 -0
- package/dist/probe-utils.d.ts.map +1 -0
- package/dist/probe-utils.js +18 -0
- package/dist/probe-utils.js.map +1 -0
- package/dist/scene-cameras.d.ts +6 -0
- package/dist/scene-cameras.d.ts.map +1 -0
- package/dist/scene-cameras.js +20 -0
- package/dist/scene-cameras.js.map +1 -0
- package/dist/scene-delta.d.ts +21 -0
- package/dist/scene-delta.d.ts.map +1 -0
- package/dist/scene-delta.js +57 -0
- package/dist/scene-delta.js.map +1 -0
- package/dist/scene-introspect.d.ts +78 -0
- package/dist/scene-introspect.d.ts.map +1 -0
- package/dist/scene-introspect.js +164 -0
- package/dist/scene-introspect.js.map +1 -0
- package/dist/scene-registry.d.ts +36 -0
- package/dist/scene-registry.d.ts.map +1 -0
- package/dist/scene-registry.js +64 -0
- package/dist/scene-registry.js.map +1 -0
- package/dist/scene-view.d.ts +52 -0
- package/dist/scene-view.d.ts.map +1 -0
- package/dist/scene-view.js +171 -0
- package/dist/scene-view.js.map +1 -0
- package/dist/source-tag.d.ts +34 -0
- package/dist/source-tag.d.ts.map +1 -0
- package/dist/source-tag.js +120 -0
- package/dist/source-tag.js.map +1 -0
- package/dist/telemetry.d.ts +53 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +302 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/types.d.ts +142 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/dist/uniform-access.d.ts +32 -0
- package/dist/uniform-access.d.ts.map +1 -0
- package/dist/uniform-access.js +144 -0
- package/dist/uniform-access.js.map +1 -0
- package/dist/validate.d.ts +2 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +81 -0
- package/dist/validate.js.map +1 -0
- package/dist/vite.d.ts +3 -0
- package/dist/vite.d.ts.map +1 -0
- package/dist/vite.js +4 -0
- package/dist/vite.js.map +1 -0
- package/dist/warnings.d.ts +24 -0
- package/dist/warnings.d.ts.map +1 -0
- package/dist/warnings.js +26 -0
- package/dist/warnings.js.map +1 -0
- package/package.json +60 -0
- package/src/compose.ts +164 -0
- package/src/editor.ts +138 -0
- package/src/harness.ts +1263 -0
- package/src/index.ts +58 -0
- package/src/inspect.ts +498 -0
- package/src/knob-utils.ts +60 -0
- package/src/lab/css.ts +56 -0
- package/src/lab/dom.ts +88 -0
- package/src/motion-probe.ts +135 -0
- package/src/probe-utils.ts +17 -0
- package/src/scene-cameras.ts +33 -0
- package/src/scene-delta.ts +69 -0
- package/src/scene-introspect.ts +230 -0
- package/src/scene-registry.ts +103 -0
- package/src/scene-view.ts +204 -0
- package/src/source-tag.ts +139 -0
- package/src/telemetry.ts +337 -0
- package/src/three-webgpu-shim.d.ts +130 -0
- package/src/types.ts +121 -0
- package/src/uniform-access.ts +152 -0
- package/src/validate.ts +82 -0
- package/src/vite.ts +5 -0
- package/src/warnings.ts +41 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 triscope contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# @triscope/core
|
|
2
|
+
|
|
3
|
+
The triscope lab runtime. Wraps a Three.js + WebGPU scene in a small **Element**
|
|
4
|
+
contract and boots a deterministic, machine-inspectable "lab" page that the
|
|
5
|
+
[`@triscope/mcp`](https://www.npmjs.com/package/@triscope/mcp) tools (and a human)
|
|
6
|
+
can observe and tune live.
|
|
7
|
+
|
|
8
|
+
```ts
|
|
9
|
+
import { runLab, runSceneLab, runSceneView } from '@triscope/core';
|
|
10
|
+
|
|
11
|
+
// Single element:
|
|
12
|
+
runLab(myElement);
|
|
13
|
+
|
|
14
|
+
// A scene of N namespaced elements (runtime add/remove):
|
|
15
|
+
runSceneLab({ elements: [ship, sea, sky] });
|
|
16
|
+
|
|
17
|
+
// Zero-boilerplate: wrap any existing THREE.Object3D (auto cameras + autoKnobs):
|
|
18
|
+
runSceneView(myGroup, { autoKnobs: true });
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## What's in here
|
|
22
|
+
|
|
23
|
+
- **`runLab` / `runSceneLab` / `runSceneView`** — the lab entry points.
|
|
24
|
+
- **`Element`** — `{ name, cameras | 'auto', mount() → { root, dispose }, knobs?, telemetry?, motionProbes?, … }`.
|
|
25
|
+
- **`autoCameras(bounds)`** — four fitted camera presets from an AABB.
|
|
26
|
+
- The Vite telemetry plugin: `import { triscopeTelemetryPlugin } from '@triscope/core/vite'`
|
|
27
|
+
(serves `/__state`, `/__knob`, `/__manifest`, `/__scene`).
|
|
28
|
+
|
|
29
|
+
A single-element `runLab` page uses **bare** camera/knob names; a `runSceneLab`
|
|
30
|
+
scene namespaces them `<element>.<key>`.
|
|
31
|
+
|
|
32
|
+
## Scaffold a project
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
npm init triscope my-app # greenfield
|
|
36
|
+
npx triscope adopt # retrofit an existing Vite + Three project
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Part of the [triscope](https://github.com/tedin7/triscope) monorepo. MIT.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Element } from './types.js';
|
|
2
|
+
export interface ComposeOptions {
|
|
3
|
+
/** Name of the composite element. Used for the state file + manifest. Default: 'composite'. */
|
|
4
|
+
name?: string;
|
|
5
|
+
/** Override the auto-computed bounds (union of children's). */
|
|
6
|
+
bounds?: Element['bounds'];
|
|
7
|
+
/** Override the lab URL (otherwise inherits the first child's). */
|
|
8
|
+
labUrl?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function composeElements(elements: Element[], opts?: ComposeOptions): Element;
|
|
11
|
+
//# sourceMappingURL=compose.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAc,OAAO,EAA4C,MAAM,YAAY,CAAC;AAEhG,MAAM,WAAW,cAAc;IAC7B,+FAA+F;IAC/F,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC3B,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAMD,wBAAgB,eAAe,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,IAAI,GAAE,cAAmB,GAAG,OAAO,CAwGvF"}
|
package/dist/compose.js
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* composeElements — fold multiple Elements into one composite Element.
|
|
3
|
+
*
|
|
4
|
+
* The Element contract is already enough for composition (the README has
|
|
5
|
+
* said "composition is just an element that mounts other elements" from
|
|
6
|
+
* day one) but writing the boilerplate by hand is tedious. This helper
|
|
7
|
+
* does the bookkeeping: it merges cameras, knobs, motionProbes, events,
|
|
8
|
+
* and telemetry under a `<elementName>.<key>` namespace so two elements
|
|
9
|
+
* declaring a camera both named "top" don't collide.
|
|
10
|
+
*
|
|
11
|
+
* Pass the result to runLab(). Inspect mode keeps working — each
|
|
12
|
+
* underlying element's meshes still get their own auto source-tags
|
|
13
|
+
* (the patch is global, not per-element).
|
|
14
|
+
*
|
|
15
|
+
* Knob routing: when the harness calls onKnob('ship.windPressure', x),
|
|
16
|
+
* we split on the first dot, find the matching element, and forward to
|
|
17
|
+
* its onKnob with the un-prefixed key ('windPressure').
|
|
18
|
+
*/
|
|
19
|
+
import { autoCameras } from './scene-cameras.js';
|
|
20
|
+
export function composeElements(elements, opts = {}) {
|
|
21
|
+
if (!Array.isArray(elements) || elements.length === 0) {
|
|
22
|
+
throw new Error('composeElements: pass a non-empty array of Element');
|
|
23
|
+
}
|
|
24
|
+
const name = opts.name ?? 'composite';
|
|
25
|
+
const labUrl = opts.labUrl ?? elements[0]?.labUrl;
|
|
26
|
+
const bounds = opts.bounds ?? unionBounds(elements);
|
|
27
|
+
// Pre-build the merged camera/knob/motionProbe maps so the Element shape
|
|
28
|
+
// is correct before mount runs. onKnob/telemetry/motionProbes/events
|
|
29
|
+
// close over `elements` (static) and reach into handle.userData.handles
|
|
30
|
+
// (the live MountHandle list) for per-element lookups.
|
|
31
|
+
const cameras = {};
|
|
32
|
+
const knobs = {};
|
|
33
|
+
const motionProbes = {};
|
|
34
|
+
for (let i = 0; i < elements.length; i++) {
|
|
35
|
+
const el = elements[i];
|
|
36
|
+
const camSpecs = el.cameras === 'auto' ? autoCameras(el.bounds) : (el.cameras ?? {});
|
|
37
|
+
for (const [cn, c] of Object.entries(camSpecs)) {
|
|
38
|
+
cameras[nsKey(el.name, cn)] = c;
|
|
39
|
+
}
|
|
40
|
+
for (const [kn, k] of Object.entries(el.knobs ?? {})) {
|
|
41
|
+
knobs[nsKey(el.name, kn)] = k;
|
|
42
|
+
}
|
|
43
|
+
for (const [pn, p] of Object.entries(el.motionProbes ?? {})) {
|
|
44
|
+
const idx = i; // capture
|
|
45
|
+
motionProbes[nsKey(el.name, pn)] = (handle, ctx) => {
|
|
46
|
+
const childHandle = handle.userData?.handles?.[idx];
|
|
47
|
+
return childHandle ? p(childHandle, ctx) : 0;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
name,
|
|
53
|
+
labUrl,
|
|
54
|
+
bounds,
|
|
55
|
+
cameras,
|
|
56
|
+
knobs,
|
|
57
|
+
mount: ({ parent, ctx }) => {
|
|
58
|
+
const handles = elements.map((el) => el.mount({ parent, ctx }));
|
|
59
|
+
// name → child handle, so the SDL can show/hide a child at runtime
|
|
60
|
+
// (applyElementToggle) without dispose/remount.
|
|
61
|
+
const childrenByName = {};
|
|
62
|
+
elements.forEach((el, i) => {
|
|
63
|
+
childrenByName[el.name] = handles[i];
|
|
64
|
+
});
|
|
65
|
+
return {
|
|
66
|
+
root: parent,
|
|
67
|
+
userData: { handles, childrenByName },
|
|
68
|
+
dispose: () => {
|
|
69
|
+
for (const h of handles) {
|
|
70
|
+
try {
|
|
71
|
+
h.dispose();
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
/* keep tearing down the rest */
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
},
|
|
80
|
+
onKnob: (handle, key, value) => {
|
|
81
|
+
const [elName, knobKey] = splitNs(key);
|
|
82
|
+
if (!elName || !knobKey)
|
|
83
|
+
return;
|
|
84
|
+
const idx = elements.findIndex((e) => e.name === elName);
|
|
85
|
+
if (idx < 0)
|
|
86
|
+
return;
|
|
87
|
+
const childHandle = handle.userData?.handles?.[idx];
|
|
88
|
+
if (!childHandle)
|
|
89
|
+
return;
|
|
90
|
+
elements[idx].onKnob?.(childHandle, knobKey, value);
|
|
91
|
+
},
|
|
92
|
+
telemetry: (handle, ctx) => {
|
|
93
|
+
const out = {};
|
|
94
|
+
const childHandles = handle.userData?.handles ?? [];
|
|
95
|
+
for (let i = 0; i < elements.length; i++) {
|
|
96
|
+
const el = elements[i];
|
|
97
|
+
const h = childHandles[i];
|
|
98
|
+
out[el.name] = h && el.telemetry ? el.telemetry(h, ctx) : {};
|
|
99
|
+
}
|
|
100
|
+
return out;
|
|
101
|
+
},
|
|
102
|
+
motionProbes,
|
|
103
|
+
events: (handle, ctx) => {
|
|
104
|
+
const out = [];
|
|
105
|
+
const childHandles = handle.userData?.handles ?? [];
|
|
106
|
+
for (let i = 0; i < elements.length; i++) {
|
|
107
|
+
const el = elements[i];
|
|
108
|
+
const h = childHandles[i];
|
|
109
|
+
if (!el.events || !h)
|
|
110
|
+
continue;
|
|
111
|
+
try {
|
|
112
|
+
for (const ev of el.events(h, ctx) ?? []) {
|
|
113
|
+
// Namespace event types so a `collision` from ship and water
|
|
114
|
+
// are distinguishable downstream.
|
|
115
|
+
out.push({ ...ev, type: nsKey(el.name, ev.type) });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
/* ignore element-level failures */
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return out;
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function unionBounds(elements) {
|
|
127
|
+
const min = [Infinity, Infinity, Infinity];
|
|
128
|
+
const max = [-Infinity, -Infinity, -Infinity];
|
|
129
|
+
let any = false;
|
|
130
|
+
for (const el of elements) {
|
|
131
|
+
if (!el.bounds)
|
|
132
|
+
continue;
|
|
133
|
+
any = true;
|
|
134
|
+
for (let i = 0; i < 3; i++) {
|
|
135
|
+
if (el.bounds.min[i] < min[i])
|
|
136
|
+
min[i] = el.bounds.min[i];
|
|
137
|
+
if (el.bounds.max[i] > max[i])
|
|
138
|
+
max[i] = el.bounds.max[i];
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return any ? { min, max } : undefined;
|
|
142
|
+
}
|
|
143
|
+
function nsKey(elementName, key) {
|
|
144
|
+
return `${elementName}.${key}`;
|
|
145
|
+
}
|
|
146
|
+
function splitNs(key) {
|
|
147
|
+
const dot = key.indexOf('.');
|
|
148
|
+
if (dot < 0)
|
|
149
|
+
return ['', key];
|
|
150
|
+
return [key.slice(0, dot), key.slice(dot + 1)];
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=compose.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose.js","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"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"}
|
package/dist/editor.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Knob } from './types.js';
|
|
2
|
+
type KnobChange = (key: string, value: number | string | boolean) => void;
|
|
3
|
+
/**
|
|
4
|
+
* Render a minimal slider/color/checkbox editor for the element's knobs into the given DOM container.
|
|
5
|
+
* Returns a `setValue(key, value)` function so external sources (MCP) can keep the UI in sync.
|
|
6
|
+
*
|
|
7
|
+
* Stays deliberately bare-bones — the styling is the host page's job.
|
|
8
|
+
*/
|
|
9
|
+
export declare function mountEditor(container: HTMLElement, knobs: Record<string, Knob>, initial: Record<string, number | string | boolean>, onChange: KnobChange): {
|
|
10
|
+
setValue: (key: string, value: number | string | boolean) => void;
|
|
11
|
+
destroy: () => void;
|
|
12
|
+
};
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=editor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../src/editor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,KAAK,UAAU,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,KAAK,IAAI,CAAC;AAE1E;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,SAAS,EAAE,WAAW,EACtB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,EAC3B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,EAClD,QAAQ,EAAE,UAAU,GACnB;IAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,KAAK,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE,CAmH5F"}
|
package/dist/editor.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render a minimal slider/color/checkbox editor for the element's knobs into the given DOM container.
|
|
3
|
+
* Returns a `setValue(key, value)` function so external sources (MCP) can keep the UI in sync.
|
|
4
|
+
*
|
|
5
|
+
* Stays deliberately bare-bones — the styling is the host page's job.
|
|
6
|
+
*/
|
|
7
|
+
export function mountEditor(container, knobs, initial, onChange) {
|
|
8
|
+
container.replaceChildren();
|
|
9
|
+
container.classList.add('triscope-editor');
|
|
10
|
+
const inputs = new Map();
|
|
11
|
+
const values = new Map();
|
|
12
|
+
for (const [key, spec] of Object.entries(knobs)) {
|
|
13
|
+
const row = document.createElement('div');
|
|
14
|
+
row.className = 'triscope-editor__row';
|
|
15
|
+
row.dataset.knobKey = key;
|
|
16
|
+
const label = document.createElement('label');
|
|
17
|
+
label.textContent = spec.label ?? key;
|
|
18
|
+
label.title = key;
|
|
19
|
+
row.appendChild(label);
|
|
20
|
+
const input = document.createElement('input');
|
|
21
|
+
input.dataset.knobKey = key;
|
|
22
|
+
const out = document.createElement('output');
|
|
23
|
+
if (spec.type === 'number' || spec.type === 'int') {
|
|
24
|
+
input.type = 'range';
|
|
25
|
+
input.min = String(spec.min);
|
|
26
|
+
input.max = String(spec.max);
|
|
27
|
+
input.step = String(spec.type === 'int' ? 1 : (spec.step ?? (spec.max - spec.min) / 200));
|
|
28
|
+
const v = typeof initial[key] === 'number' ? Number(initial[key]) : spec.default;
|
|
29
|
+
input.value = String(v);
|
|
30
|
+
out.textContent = formatNumber(v, spec.type);
|
|
31
|
+
input.oninput = () => {
|
|
32
|
+
const num = spec.type === 'int' ? parseInt(input.value, 10) : parseFloat(input.value);
|
|
33
|
+
out.textContent = formatNumber(num, spec.type);
|
|
34
|
+
onChange(key, num);
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
else if (spec.type === 'color') {
|
|
38
|
+
input.type = 'color';
|
|
39
|
+
const v = typeof initial[key] === 'string' ? String(initial[key]) : spec.default;
|
|
40
|
+
input.value = v;
|
|
41
|
+
out.textContent = v;
|
|
42
|
+
input.oninput = () => {
|
|
43
|
+
out.textContent = input.value;
|
|
44
|
+
onChange(key, input.value);
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
else if (spec.type === 'boolean') {
|
|
48
|
+
input.type = 'checkbox';
|
|
49
|
+
const v = typeof initial[key] === 'boolean' ? Boolean(initial[key]) : spec.default;
|
|
50
|
+
input.checked = v;
|
|
51
|
+
out.textContent = v ? 'on' : 'off';
|
|
52
|
+
input.onchange = () => {
|
|
53
|
+
out.textContent = input.checked ? 'on' : 'off';
|
|
54
|
+
onChange(key, input.checked);
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
else if (spec.type === 'trigger') {
|
|
58
|
+
// Trigger renders as a button. Each click fires onChange(true) — the
|
|
59
|
+
// value carries no state, the act itself is the signal.
|
|
60
|
+
const btn = document.createElement('button');
|
|
61
|
+
btn.type = 'button';
|
|
62
|
+
btn.textContent = spec.label ?? key;
|
|
63
|
+
btn.dataset.knobKey = key;
|
|
64
|
+
btn.onclick = () => {
|
|
65
|
+
out.textContent = 'fired';
|
|
66
|
+
onChange(key, true);
|
|
67
|
+
setTimeout(() => {
|
|
68
|
+
out.textContent = '–';
|
|
69
|
+
}, 400);
|
|
70
|
+
};
|
|
71
|
+
out.textContent = '–';
|
|
72
|
+
row.appendChild(btn);
|
|
73
|
+
row.appendChild(out);
|
|
74
|
+
container.appendChild(row);
|
|
75
|
+
values.set(key, out);
|
|
76
|
+
// No persistent input element — leave inputs.set unset; setValue from
|
|
77
|
+
// external pulse will still flash the output.
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
row.appendChild(input);
|
|
81
|
+
row.appendChild(out);
|
|
82
|
+
container.appendChild(row);
|
|
83
|
+
inputs.set(key, input);
|
|
84
|
+
values.set(key, out);
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
setValue(key, value) {
|
|
88
|
+
const out = values.get(key);
|
|
89
|
+
const spec = knobs[key];
|
|
90
|
+
if (!out || !spec)
|
|
91
|
+
return;
|
|
92
|
+
if (spec.type === 'trigger') {
|
|
93
|
+
// External pulse — flash the output to confirm receipt; no input
|
|
94
|
+
// element to sync because trigger has no persistent state.
|
|
95
|
+
out.textContent = 'fired';
|
|
96
|
+
setTimeout(() => {
|
|
97
|
+
out.textContent = '–';
|
|
98
|
+
}, 400);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const inp = inputs.get(key);
|
|
102
|
+
if (!inp)
|
|
103
|
+
return;
|
|
104
|
+
if (spec.type === 'number' || spec.type === 'int') {
|
|
105
|
+
inp.value = String(value);
|
|
106
|
+
out.textContent = formatNumber(Number(value), spec.type);
|
|
107
|
+
}
|
|
108
|
+
else if (spec.type === 'color') {
|
|
109
|
+
inp.value = String(value);
|
|
110
|
+
out.textContent = String(value);
|
|
111
|
+
}
|
|
112
|
+
else if (spec.type === 'boolean') {
|
|
113
|
+
inp.checked = Boolean(value);
|
|
114
|
+
out.textContent = inp.checked ? 'on' : 'off';
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
destroy() {
|
|
118
|
+
container.replaceChildren();
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function formatNumber(v, type) {
|
|
123
|
+
if (type === 'int')
|
|
124
|
+
return String(Math.round(v));
|
|
125
|
+
if (Math.abs(v) >= 100)
|
|
126
|
+
return v.toFixed(1);
|
|
127
|
+
if (Math.abs(v) >= 1)
|
|
128
|
+
return v.toFixed(2);
|
|
129
|
+
return v.toFixed(3);
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=editor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editor.js","sourceRoot":"","sources":["../src/editor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import * as THREE from 'three/webgpu';
|
|
2
|
+
import { type InspectSelection } from './inspect.js';
|
|
3
|
+
import { type CameraDelta } from './scene-delta.js';
|
|
4
|
+
import { type LightNode, type SceneNode } from './scene-introspect.js';
|
|
5
|
+
import type { CameraSpec, Element, MountHandle } from './types.js';
|
|
6
|
+
import { type UniformReadResult, type UniformWriteResult } from './uniform-access.js';
|
|
7
|
+
import { type WarningEntry } from './warnings.js';
|
|
8
|
+
declare global {
|
|
9
|
+
interface Window {
|
|
10
|
+
__TRISCOPE__?: TriscopeGlobal;
|
|
11
|
+
/** Set when element.mount() throws or the contract is invalid; read by the
|
|
12
|
+
* MCP browser pool to report the real cause instead of a mount timeout. */
|
|
13
|
+
__TRISCOPE_MOUNT_ERROR__?: {
|
|
14
|
+
element?: string;
|
|
15
|
+
message: string;
|
|
16
|
+
problems: string[];
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
interface TriscopeGlobal {
|
|
21
|
+
element: Element;
|
|
22
|
+
handle: MountHandle;
|
|
23
|
+
renderer: THREE.WebGPURenderer;
|
|
24
|
+
scene: THREE.Scene;
|
|
25
|
+
cameras: Record<string, THREE.PerspectiveCamera>;
|
|
26
|
+
knobValues: Record<string, number | string | boolean>;
|
|
27
|
+
setKnob: (key: string, value: number | string | boolean) => void;
|
|
28
|
+
sampleTelemetry: () => Record<string, unknown>;
|
|
29
|
+
/** Inspect-mode selection — set by clicking a mesh in `?inspect=` mode. */
|
|
30
|
+
lastSelection?: InspectSelection | null;
|
|
31
|
+
/** Capture one frame per named camera; returns base64 PNGs keyed by camera. */
|
|
32
|
+
captureViews: () => Promise<Record<string, string>>;
|
|
33
|
+
/**
|
|
34
|
+
* Capture N frames of a single camera spaced by dt seconds. In `mode: 'time'`
|
|
35
|
+
* (default), the RAF loop is paused and `time.value` is stepped forward
|
|
36
|
+
* deterministically — works for shader-driven motion. In `mode: 'real'`, the
|
|
37
|
+
* RAF keeps running and frames are sampled at wall-clock intervals — needed
|
|
38
|
+
* for CPU-integrated state (springs, particles).
|
|
39
|
+
*/
|
|
40
|
+
captureMotionFrames: (camera: string, opts?: {
|
|
41
|
+
frames?: number;
|
|
42
|
+
dt?: number;
|
|
43
|
+
mode?: 'time' | 'real';
|
|
44
|
+
}) => Promise<string[]>;
|
|
45
|
+
/** Per-camera GPU probe stats from the most recent captureViews() call. */
|
|
46
|
+
lastGpuProbes?: Record<string, GpuProbeStats>;
|
|
47
|
+
/** Recent non-fatal failures the harness swallowed (telemetry/knob/probe). */
|
|
48
|
+
warnings?: WarningEntry[];
|
|
49
|
+
/**
|
|
50
|
+
* Snapshot the live scene graph: meshes/lights/groups with triangle counts,
|
|
51
|
+
* world positions, material kind/color, uniform names, and the file:line
|
|
52
|
+
* source tag. One call replaces a flurry of capture probes when an agent
|
|
53
|
+
* needs to know what's actually in the scene.
|
|
54
|
+
*/
|
|
55
|
+
queryScene: (maxNodes?: number) => {
|
|
56
|
+
nodes: SceneNode[];
|
|
57
|
+
lights: LightNode[];
|
|
58
|
+
total: number;
|
|
59
|
+
truncated: boolean;
|
|
60
|
+
};
|
|
61
|
+
/** Read any material uniform / material property / object property by
|
|
62
|
+
* "objectName|uuid.key" path — even undeclared ones. */
|
|
63
|
+
readUniform: (path: string) => UniformReadResult;
|
|
64
|
+
/** Write the same, live and transient (not persisted). Returns previous/current. */
|
|
65
|
+
setUniform: (path: string, value: unknown) => UniformWriteResult;
|
|
66
|
+
/**
|
|
67
|
+
* SDL: apply a scene delta live (repoint cameras, override knobs) WITHOUT a
|
|
68
|
+
* reload, and persist it via /__scene so it survives one. Returns the live
|
|
69
|
+
* scene state after applying.
|
|
70
|
+
*/
|
|
71
|
+
setSceneParam: (delta: {
|
|
72
|
+
cameras?: Record<string, CameraDelta>;
|
|
73
|
+
knobs?: Record<string, unknown>;
|
|
74
|
+
elements?: Record<string, {
|
|
75
|
+
enabled?: boolean;
|
|
76
|
+
}>;
|
|
77
|
+
}) => {
|
|
78
|
+
cameras: Record<string, {
|
|
79
|
+
position: number[];
|
|
80
|
+
target: number[];
|
|
81
|
+
fov: number;
|
|
82
|
+
}>;
|
|
83
|
+
knobs: Record<string, number | string | boolean>;
|
|
84
|
+
elements: Record<string, {
|
|
85
|
+
enabled: boolean;
|
|
86
|
+
}>;
|
|
87
|
+
};
|
|
88
|
+
/** Current live camera positions/targets/fov + knob values + element on/off. */
|
|
89
|
+
getScene: () => {
|
|
90
|
+
cameras: Record<string, {
|
|
91
|
+
position: number[];
|
|
92
|
+
target: number[];
|
|
93
|
+
fov: number;
|
|
94
|
+
}>;
|
|
95
|
+
knobs: Record<string, number | string | boolean>;
|
|
96
|
+
elements: Record<string, {
|
|
97
|
+
enabled: boolean;
|
|
98
|
+
}>;
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* Mount a registered-but-unmounted element live (runSceneLab scenes). Adds
|
|
102
|
+
* its namespaced cameras/knobs and rebuilds the grid. Returns false if the
|
|
103
|
+
* name is unknown or already mounted. A single-element runLab has nothing
|
|
104
|
+
* else to add, so this is a no-op there.
|
|
105
|
+
*/
|
|
106
|
+
addElement: (name: string) => boolean;
|
|
107
|
+
/** Dispose a mounted element live + rebuild the grid. False if not mounted. */
|
|
108
|
+
removeElement: (name: string) => boolean;
|
|
109
|
+
/** All element names in the scene registry (mounted or not). */
|
|
110
|
+
availableElements: () => string[];
|
|
111
|
+
/** Currently mounted element names, in registry order. */
|
|
112
|
+
mountedElements: () => string[];
|
|
113
|
+
/** Monotonic count of rendered frames since boot (gates capture readiness). */
|
|
114
|
+
framesRendered: () => number;
|
|
115
|
+
}
|
|
116
|
+
export interface CommonLabOptions {
|
|
117
|
+
canvas: HTMLCanvasElement;
|
|
118
|
+
editorContainer?: HTMLElement | null;
|
|
119
|
+
labelContainer?: HTMLElement | null;
|
|
120
|
+
hud?: HTMLElement | null;
|
|
121
|
+
bootOverlay?: HTMLElement | null;
|
|
122
|
+
telemetryIntervalMs?: number;
|
|
123
|
+
knobPollMs?: number;
|
|
124
|
+
/** Optional clear color for the scene before each frame. Default `#0a1a20`. */
|
|
125
|
+
clearColor?: number;
|
|
126
|
+
/**
|
|
127
|
+
* Fixed [width, height] in CSS pixels to which the canvas is resized for
|
|
128
|
+
* every captureViews / captureMotionFrames call, then restored. Use this
|
|
129
|
+
* when you need reproducible framing across page reloads (otherwise the
|
|
130
|
+
* canvas tracks clientWidth/clientHeight which can drift). Off by default.
|
|
131
|
+
*/
|
|
132
|
+
captureSize?: [number, number];
|
|
133
|
+
}
|
|
134
|
+
export interface LabOptions extends CommonLabOptions {
|
|
135
|
+
element: Element;
|
|
136
|
+
}
|
|
137
|
+
export interface SceneLabOptions extends CommonLabOptions {
|
|
138
|
+
/** Registry of element types the scene can mount/unmount at runtime. */
|
|
139
|
+
elements: Element[];
|
|
140
|
+
/** Names initially mounted (defaults to every registered element). */
|
|
141
|
+
mounted?: string[];
|
|
142
|
+
}
|
|
143
|
+
export interface LabHandle {
|
|
144
|
+
/** The primary mounted element (first slot); undefined-safe as slots change. */
|
|
145
|
+
element: Element;
|
|
146
|
+
setKnob: (key: string, value: number | string | boolean) => void;
|
|
147
|
+
captureViews: () => Promise<Record<string, string>>;
|
|
148
|
+
/** Mount a registered element live (runSceneLab). No-op for single-element labs. */
|
|
149
|
+
addElement: (name: string) => boolean;
|
|
150
|
+
/** Dispose a mounted element live (runSceneLab). */
|
|
151
|
+
removeElement: (name: string) => boolean;
|
|
152
|
+
/** All element names in the scene registry. */
|
|
153
|
+
availableElements: () => string[];
|
|
154
|
+
/** Currently mounted element names. */
|
|
155
|
+
mountedElements: () => string[];
|
|
156
|
+
stop: () => void;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Boot a multi-camera lab page for a single Element.
|
|
160
|
+
* One WebGPURenderer, one scene, one Element, N scissored viewports.
|
|
161
|
+
*
|
|
162
|
+
* Thin wrapper over {@link runSceneCore}: a one-entry, non-namespaced registry.
|
|
163
|
+
* The single-element path is behaviorally identical to before this was
|
|
164
|
+
* generalized — bare camera/knob names, `elements: { [name]: … }`,
|
|
165
|
+
* `project: name`.
|
|
166
|
+
*/
|
|
167
|
+
export declare function runLab(opts: LabOptions): Promise<LabHandle>;
|
|
168
|
+
/**
|
|
169
|
+
* Boot a multi-camera lab page for a SCENE of N Elements, with runtime
|
|
170
|
+
* mount/unmount via the returned handle's addElement/removeElement (and the
|
|
171
|
+
* MCP add_element/remove_element tools). Camera + knob keys are namespaced
|
|
172
|
+
* `<element>.<key>` so two elements that both declare `top`/`speed` never
|
|
173
|
+
* collide. Shares one renderer/scene with runLab through {@link runSceneCore}.
|
|
174
|
+
*/
|
|
175
|
+
export declare function runSceneLab(opts: SceneLabOptions): Promise<LabHandle>;
|
|
176
|
+
/**
|
|
177
|
+
* Aggregated brightness/contrast scalars computed from a rendered canvas.
|
|
178
|
+
* Probes are run by the harness during `captureViews()` — they validate
|
|
179
|
+
* that the GPU actually drew something (luminance > 0 means the frame is
|
|
180
|
+
* not black; p95/p5 ratio > 1 means there's contrast).
|
|
181
|
+
*/
|
|
182
|
+
export interface GpuProbeStats {
|
|
183
|
+
/** Mean perceptual luminance (Rec.709) in [0, 1]. */
|
|
184
|
+
luminance: number;
|
|
185
|
+
/** 5th percentile luminance. */
|
|
186
|
+
p5: number;
|
|
187
|
+
/** 95th percentile luminance. */
|
|
188
|
+
p95: number;
|
|
189
|
+
/** p95 / max(p5, 1/255) — dynamic range proxy. */
|
|
190
|
+
dynamicRange: number;
|
|
191
|
+
/** Number of pixels sampled (typically 64×36 = 2304). */
|
|
192
|
+
samples: number;
|
|
193
|
+
/** Set true when this camera's mean luminance indicates a black render. */
|
|
194
|
+
blackFrame?: boolean;
|
|
195
|
+
}
|
|
196
|
+
export declare function makeCamera(spec: CameraSpec, bounds?: Element['bounds']): THREE.PerspectiveCamera;
|
|
197
|
+
export declare function fitCameraToBounds(cam: THREE.PerspectiveCamera, spec: CameraSpec, bounds: NonNullable<Element['bounds']>): void;
|
|
198
|
+
export {};
|
|
199
|
+
//# sourceMappingURL=harness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../src/harness.ts"],"names":[],"mappings":"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"}
|