@vizij/render 0.1.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -11
- package/dist/index.d.mts +296 -92
- package/dist/index.d.ts +296 -92
- package/dist/index.js +894 -555
- package/dist/index.mjs +854 -512
- package/package.json +18 -19
- package/LICENSE +0 -201
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> Three.js + React renderer, scene store, and helper controllers for Vizij faces.
|
|
4
4
|
|
|
5
|
-
This package exposes the `Vizij` canvas component along with hooks, stores, and GLTF helpers that power Vizij’s real-time character visualisation. It is the foundation that other packages (`@vizij/
|
|
5
|
+
This package exposes the `Vizij` canvas component along with hooks, stores, and GLTF helpers that power Vizij’s real-time character visualisation. It is the foundation that other packages (`@vizij/runtime-react`, etc.) build upon.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -23,7 +23,7 @@ This package exposes the `Vizij` canvas component along with hooks, stores, and
|
|
|
23
23
|
|
|
24
24
|
- `Vizij` renders a fully managed `@react-three/fiber` canvas with sensible defaults for orthographic cameras and safe-area overlays.
|
|
25
25
|
- A Zustand-powered store (`useVizijStore`) tracks renderables, controllers, and transient state. Hooks let you read or mutate slices without re-rendering entire scenes.
|
|
26
|
-
-
|
|
26
|
+
- The loader (`loadGLTF`, `loadGLTFFromBlob` and their `WithBundle` forms) turns a rigged GLB into the world model; `buildSceneGraph` and `exportScene` turn the world model back into GLB bytes. Both run in Node as well as in a browser. The tuple helpers return `[world, animatables, animations]`, where `animations` contains parsed clip metadata for any channels embedded in the GLB.
|
|
27
27
|
- Controllers wrap common behaviours (e.g., pointer interaction, safe-area visualisation) so you can compose features quickly.
|
|
28
28
|
|
|
29
29
|
---
|
|
@@ -96,23 +96,24 @@ The store tracks world graph entries, controllers, debug overlays, and renderabl
|
|
|
96
96
|
## Controllers & Helpers
|
|
97
97
|
|
|
98
98
|
- Controllers under `src/controllers` encapsulate input handling, camera logic, and other behaviours. Compose them with your own React components.
|
|
99
|
-
- `loadGLTF` / `
|
|
100
|
-
- `
|
|
99
|
+
- `loadGLTF` / `loadGLTFFromBlob` load rig assets and extract the animatable metadata used by `@vizij/runtime-react`. A blob is parsed in memory, with nothing fetched.
|
|
100
|
+
- `buildSceneGraph(world, animatables, rootId)` builds the three.js graph of a world element with no renderer, and `exportScene(root, { bundle, animations })` encodes a graph as GLB bytes. Saving or uploading the bytes is the caller's job.
|
|
101
101
|
|
|
102
102
|
All exports are re-exported through `src/index.tsx`, so a simple `import { loadGLTF } from "@vizij/render"` works.
|
|
103
103
|
|
|
104
104
|
### Dual-format Vizij bundles
|
|
105
105
|
|
|
106
|
-
Vizij scenes persist authoring metadata inside GLBs so third-party tools see baked animation, while Vizij runtimes retain
|
|
106
|
+
Vizij scenes persist authoring metadata inside GLBs so third-party tools see baked animation, while Vizij runtimes retain the authored graphs and clips.
|
|
107
107
|
|
|
108
108
|
- Every renderable still carries a `RobotData` extension in `userData` describing features and animatable bindings.
|
|
109
109
|
- The exporter now writes a root-level `extensions.VIZIJ_bundle` block following the schema in [`src/types/vizij-bundle.ts`](./src/types/vizij-bundle.ts). It contains rig graphs, pose configs, stored Vizij clips, and provenance hashes.
|
|
110
|
-
- Use `exportScene(
|
|
110
|
+
- Use `exportScene(root, { bundle, animations })` to embed both the Vizij bundle and optional baked `THREE.AnimationClip` instances; it resolves to the GLB as an `ArrayBuffer`. The helper attaches the bundle only for the export call and restores the original object.
|
|
111
|
+
- A graph from `buildSceneGraph` carries each element's authored values: node translation, rotation and scale, morph weights and material factors equal the `RobotData` defaults written beside them, not a runtime pose.
|
|
111
112
|
- When loading assets, prefer `loadGLTFWithBundle` / `loadGLTFFromBlobWithBundle` to retrieve `{ world, animatables, bundle, animations }`. The legacy tuple helpers return `[world, animatables, animations]` if you only need the renderer state.
|
|
112
113
|
- The new `animations` field exposes `VizijAnimationClipData[]`, which maps each glTF animation channel back to Vizij animatable ids (`RobotData.features.*.value.id`). Each track provides component-aware `times`/`values` arrays so runtimes can register clips without re-parsing the GLB.
|
|
113
114
|
- `extractVizijBundle(scene)` and `applyVizijBundle(scene, bundle)` (under `src/functions/vizij-bundle.ts`) let advanced tooling inspect or mutate bundles without triggering a fresh export.
|
|
114
115
|
|
|
115
|
-
With this structure, authoring tools can round-trip
|
|
116
|
+
With this structure, authoring tools can round-trip Vizij runtime assets while shipping native glTF animations for viewers that do not understand Vizij.
|
|
116
117
|
|
|
117
118
|
---
|
|
118
119
|
|
|
@@ -132,14 +133,17 @@ pnpm --filter "@vizij/render" size
|
|
|
132
133
|
|
|
133
134
|
## Publishing
|
|
134
135
|
|
|
135
|
-
Use the shared workflow at [`.github/workflows/publish-npm.yml`](
|
|
136
|
+
Use the shared workflow at [`.github/workflows/publish-npm.yml`](../../../.github/workflows/publish-npm.yml).
|
|
136
137
|
|
|
137
138
|
1. Align dependency versions (`three`, `@react-three/*`, `zustand`, Vizij packages) and generate a changeset:
|
|
139
|
+
|
|
138
140
|
```bash
|
|
139
141
|
pnpm changeset
|
|
140
142
|
pnpm version:packages
|
|
141
143
|
```
|
|
144
|
+
|
|
142
145
|
2. Validate locally:
|
|
146
|
+
|
|
143
147
|
```bash
|
|
144
148
|
pnpm install
|
|
145
149
|
pnpm --filter "@vizij/render" build
|
|
@@ -148,13 +152,14 @@ Use the shared workflow at [`.github/workflows/publish-npm.yml`](../../.github/w
|
|
|
148
152
|
pnpm --filter "@vizij/render" lint
|
|
149
153
|
pnpm --filter "@vizij/render" exec npm pack --dry-run
|
|
150
154
|
```
|
|
151
|
-
|
|
155
|
+
|
|
156
|
+
3. Merge the version bump to `main`. CI publishes any `@vizij/*` version not yet on npm (with provenance) — no release tag. See the root [README → Publishing & Versioning](../../../README.md#publishing--versioning).
|
|
152
157
|
|
|
153
158
|
---
|
|
154
159
|
|
|
155
160
|
## Related Packages
|
|
156
161
|
|
|
157
|
-
- [`@vizij/
|
|
158
|
-
- [`@vizij/animation-react`](
|
|
162
|
+
- [`@vizij/runtime-react`](../runtime-react/README.md) – Hooks that consume the renderer to load rigged models.
|
|
163
|
+
- [`@vizij/animation-react`](../animation-react/README.md) – React bindings that feed animation values back into the renderer.
|
|
159
164
|
|
|
160
165
|
Questions or contributions? Open an issue so we can keep the renderer API and docs sharp for the whole Vizij ecosystem. 🎨
|
package/dist/index.d.mts
CHANGED
|
@@ -2,49 +2,11 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
2
2
|
import * as react from 'react';
|
|
3
3
|
import { CSSProperties, ComponentProps, ReactNode, RefObject, MouseEvent } from 'react';
|
|
4
4
|
import { Canvas, ThreeEvent } from '@react-three/fiber';
|
|
5
|
-
import * as zustand from 'zustand';
|
|
6
5
|
import * as THREE from 'three';
|
|
7
|
-
import {
|
|
6
|
+
import { BufferGeometry, ShapeGeometry, ToneMapping, Group as Group$1, Mesh, AnimationClip, Object3D } from 'three';
|
|
7
|
+
import * as zustand from 'zustand';
|
|
8
8
|
import { RawValue, AnimatableValue, RawVector2 } from '@vizij/utils';
|
|
9
9
|
|
|
10
|
-
interface VizijProps {
|
|
11
|
-
style?: CSSProperties;
|
|
12
|
-
className?: string;
|
|
13
|
-
rootId: string;
|
|
14
|
-
namespace?: string;
|
|
15
|
-
showSafeArea?: boolean;
|
|
16
|
-
showSelectionGlow?: boolean;
|
|
17
|
-
onPointerMissed?: ComponentProps<typeof Canvas>["onPointerMissed"];
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Renders the Vizij component.
|
|
21
|
-
*
|
|
22
|
-
* @param style - The style object for the Vizij component.
|
|
23
|
-
*
|
|
24
|
-
* @param className - The CSS class name for the Vizij component
|
|
25
|
-
*
|
|
26
|
-
* @param rootId - The root identifier for the Vizij component.
|
|
27
|
-
*
|
|
28
|
-
* @param namespace - The namespace for the Vizij component
|
|
29
|
-
*
|
|
30
|
-
* @param showSafeArea - Whether to show the safe area.
|
|
31
|
-
*
|
|
32
|
-
* @returns The rendered ReactNode.
|
|
33
|
-
*/
|
|
34
|
-
declare function Vizij({ style, className, rootId, namespace, showSafeArea, showSelectionGlow, onPointerMissed, }: VizijProps): ReactNode;
|
|
35
|
-
interface InnerVizijProps {
|
|
36
|
-
rootId: string;
|
|
37
|
-
namespace: string;
|
|
38
|
-
container?: {
|
|
39
|
-
width: number;
|
|
40
|
-
height: number;
|
|
41
|
-
resolution: number;
|
|
42
|
-
};
|
|
43
|
-
showSafeArea?: boolean;
|
|
44
|
-
showSelectionGlow?: boolean;
|
|
45
|
-
}
|
|
46
|
-
declare function InnerVizij({ rootId, namespace, container, showSafeArea, showSelectionGlow, }: InnerVizijProps): react_jsx_runtime.JSX.Element;
|
|
47
|
-
|
|
48
10
|
/**
|
|
49
11
|
* A wrapping type to reference an attribute that is animatable.
|
|
50
12
|
*
|
|
@@ -92,7 +54,6 @@ interface RenderableBase {
|
|
|
92
54
|
name: string;
|
|
93
55
|
tags: string[];
|
|
94
56
|
type: string;
|
|
95
|
-
refs: Record<string, RefObject<any>>;
|
|
96
57
|
features: Record<string, Feature>;
|
|
97
58
|
}
|
|
98
59
|
|
|
@@ -109,19 +70,17 @@ interface Stored<T extends Omit<RenderableBase, "refs">> {
|
|
|
109
70
|
type StoredRenderable = Stored<RenderableBase>;
|
|
110
71
|
|
|
111
72
|
/**
|
|
112
|
-
* An object for creating
|
|
73
|
+
* An object for creating rectangles
|
|
113
74
|
*
|
|
114
|
-
* @param id - The id of the
|
|
115
|
-
* @param name - The name of the
|
|
116
|
-
* @param tags - The tags of the
|
|
75
|
+
* @param id - The id of the rectangle
|
|
76
|
+
* @param name - The name of the rectangle
|
|
77
|
+
* @param tags - The tags of the rectangle
|
|
117
78
|
* @param type - Type flag
|
|
118
|
-
* @param
|
|
119
|
-
* @param
|
|
120
|
-
* @param children - The children of the ellipse (list of ids for other bodies or shapes)
|
|
79
|
+
* @param features - The features of the rectangle (translation, rotation, and scale)
|
|
80
|
+
* @param children - The children of the rectangle (list of ids for other bodies or shapes)
|
|
121
81
|
*/
|
|
122
|
-
interface
|
|
123
|
-
type: "
|
|
124
|
-
refs: Record<string, RefObject<Mesh>>;
|
|
82
|
+
interface Rectangle extends RenderableBase {
|
|
83
|
+
type: "rectangle";
|
|
125
84
|
features: {
|
|
126
85
|
height: Feature;
|
|
127
86
|
width: Feature;
|
|
@@ -130,28 +89,27 @@ interface Ellipse extends RenderableBase {
|
|
|
130
89
|
fillColor?: Feature;
|
|
131
90
|
strokeColor?: Feature;
|
|
132
91
|
strokeWidth?: Feature;
|
|
92
|
+
strokeRadius?: Feature;
|
|
133
93
|
strokeOffset?: Feature;
|
|
134
94
|
translation: Feature;
|
|
135
95
|
rotation: Feature;
|
|
136
96
|
};
|
|
137
97
|
}
|
|
138
|
-
type
|
|
139
|
-
type
|
|
98
|
+
type RectangleFeature = keyof Rectangle["features"];
|
|
99
|
+
type StoredRectangle = Stored<Rectangle>;
|
|
140
100
|
|
|
141
101
|
/**
|
|
142
|
-
* An object for creating
|
|
102
|
+
* An object for creating hierarchies/bodies
|
|
143
103
|
*
|
|
144
|
-
* @param id - The id of the
|
|
145
|
-
* @param name - The name of the
|
|
146
|
-
* @param tags - The tags of the
|
|
104
|
+
* @param id - The id of the ellipse
|
|
105
|
+
* @param name - The name of the ellipse
|
|
106
|
+
* @param tags - The tags of the ellipse
|
|
147
107
|
* @param type - Type flag
|
|
148
|
-
* @param
|
|
149
|
-
* @param
|
|
150
|
-
* @param children - The children of the rectangle (list of ids for other bodies or shapes)
|
|
108
|
+
* @param features - The features of the ellipse (translation, rotation, and scale)
|
|
109
|
+
* @param children - The children of the ellipse (list of ids for other bodies or shapes)
|
|
151
110
|
*/
|
|
152
|
-
interface
|
|
153
|
-
type: "
|
|
154
|
-
refs: Record<string, RefObject<Mesh>>;
|
|
111
|
+
interface Ellipse extends RenderableBase {
|
|
112
|
+
type: "ellipse";
|
|
155
113
|
features: {
|
|
156
114
|
height: Feature;
|
|
157
115
|
width: Feature;
|
|
@@ -160,14 +118,13 @@ interface Rectangle extends RenderableBase {
|
|
|
160
118
|
fillColor?: Feature;
|
|
161
119
|
strokeColor?: Feature;
|
|
162
120
|
strokeWidth?: Feature;
|
|
163
|
-
strokeRadius?: Feature;
|
|
164
121
|
strokeOffset?: Feature;
|
|
165
122
|
translation: Feature;
|
|
166
123
|
rotation: Feature;
|
|
167
124
|
};
|
|
168
125
|
}
|
|
169
|
-
type
|
|
170
|
-
type
|
|
126
|
+
type EllipseFeature = keyof Ellipse["features"];
|
|
127
|
+
type StoredEllipse = Stored<Ellipse>;
|
|
171
128
|
|
|
172
129
|
/**
|
|
173
130
|
* An object for creating hierarchies/groups
|
|
@@ -176,14 +133,12 @@ type StoredRectangle = Stored<Rectangle>;
|
|
|
176
133
|
* @param name - The name of the group
|
|
177
134
|
* @param tags - The tags of the group
|
|
178
135
|
* @param type - Type flag
|
|
179
|
-
* @param refs - The reference to the group[s] in the vizij, for each namespace
|
|
180
136
|
* @param features - The features of the group (translation, rotation, and scale)
|
|
181
137
|
* @param root - Whether the group is a root node
|
|
182
138
|
* @param children - The children of the group (list of ids for other groups or shapes)
|
|
183
139
|
*/
|
|
184
140
|
interface Group extends RenderableBase {
|
|
185
141
|
type: "group";
|
|
186
|
-
refs: Record<string, RefObject<Group$1>>;
|
|
187
142
|
root: boolean;
|
|
188
143
|
features: {
|
|
189
144
|
translation: Feature;
|
|
@@ -209,7 +164,6 @@ type StoredGroup = Stored<Group>;
|
|
|
209
164
|
* @property name - Human-readable name for the shape
|
|
210
165
|
* @property tags - List of tags for categorizing and filtering
|
|
211
166
|
* @property type - Always "shape"
|
|
212
|
-
* @property refs - Map of React refs to Three.js Mesh objects
|
|
213
167
|
* @property features - Visual and transformation properties that can be animated
|
|
214
168
|
* @property material - The type of Three.js material to use for rendering
|
|
215
169
|
* @property geometry - The Three.js geometry defining the shape's structure
|
|
@@ -220,13 +174,15 @@ type StoredGroup = Stored<Group>;
|
|
|
220
174
|
*/
|
|
221
175
|
interface Shape extends RenderableBase {
|
|
222
176
|
type: "shape";
|
|
223
|
-
refs: Record<string, RefObject<Mesh>>;
|
|
224
177
|
features: {
|
|
225
178
|
shininess?: Feature;
|
|
226
179
|
opacity?: Feature;
|
|
227
180
|
roughness?: Feature;
|
|
228
181
|
metalness?: Feature;
|
|
229
182
|
color?: Feature;
|
|
183
|
+
emissive?: Feature;
|
|
184
|
+
emissiveIntensity?: Feature;
|
|
185
|
+
specular?: Feature;
|
|
230
186
|
translation: Feature;
|
|
231
187
|
rotation: Feature;
|
|
232
188
|
scale?: Feature;
|
|
@@ -252,8 +208,6 @@ declare enum ShapeMaterial {
|
|
|
252
208
|
type ShapeFeature = keyof Shape["features"];
|
|
253
209
|
type StoredShape = Stored<Omit<Shape, "geometry">>;
|
|
254
210
|
|
|
255
|
-
type World = Record<string, Group | Ellipse | Rectangle | Shape>;
|
|
256
|
-
|
|
257
211
|
type RenderableFeature = GroupFeature | EllipseFeature;
|
|
258
212
|
|
|
259
213
|
/**
|
|
@@ -276,6 +230,57 @@ interface Selection {
|
|
|
276
230
|
};
|
|
277
231
|
}
|
|
278
232
|
|
|
233
|
+
type World = Record<string, Group | Ellipse | Rectangle | Shape>;
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Vizij-level tone-mapping selection.
|
|
237
|
+
*
|
|
238
|
+
* This is a stable, serializable string enum rather than a raw three.js
|
|
239
|
+
* constant so it can be persisted in the `VIZIJ_bundle` extension and round-trip
|
|
240
|
+
* through import/export without leaking three's numeric enum values into stored
|
|
241
|
+
* data.
|
|
242
|
+
*
|
|
243
|
+
* - `"none"` — no tone mapping. Values are written to the framebuffer as-is and
|
|
244
|
+
* clip at 1.0. This matches plain web/canvas rendering and is the historical
|
|
245
|
+
* vizij default (chosen so studio colors match the canvas).
|
|
246
|
+
* - `"agx"` — AgX, Blender 4.x's default view transform. Compresses
|
|
247
|
+
* over-1.0 emissive into soft, slightly-desaturated color; matches faces
|
|
248
|
+
* authored/exported from Blender.
|
|
249
|
+
* - `"aces"` — ACES Filmic, a punchier cinematic curve.
|
|
250
|
+
* - `"neutral"` — Khronos PBR Neutral, a mild curve that preserves hue/saturation
|
|
251
|
+
* while taming highlights.
|
|
252
|
+
*/
|
|
253
|
+
type ToneMappingMode = "none" | "agx" | "aces" | "neutral";
|
|
254
|
+
/**
|
|
255
|
+
* The set of supported tone-mapping modes, in display order. Useful for
|
|
256
|
+
* building selection UIs.
|
|
257
|
+
*/
|
|
258
|
+
declare const TONE_MAPPING_MODES: ToneMappingMode[];
|
|
259
|
+
/**
|
|
260
|
+
* Human-readable labels for each tone-mapping mode.
|
|
261
|
+
*/
|
|
262
|
+
declare const TONE_MAPPING_LABELS: Record<ToneMappingMode, string>;
|
|
263
|
+
/**
|
|
264
|
+
* The default tone-mapping mode used when a face/scene has not specified one.
|
|
265
|
+
* `"none"` preserves the historical web-matching behavior.
|
|
266
|
+
*/
|
|
267
|
+
declare const DEFAULT_TONE_MAPPING_MODE: ToneMappingMode;
|
|
268
|
+
/**
|
|
269
|
+
* Type guard: is `value` a valid {@link ToneMappingMode}?
|
|
270
|
+
*/
|
|
271
|
+
declare function isToneMappingMode(value: unknown): value is ToneMappingMode;
|
|
272
|
+
/**
|
|
273
|
+
* Resolve a {@link ToneMappingMode} (or an unknown/undefined stored value) to
|
|
274
|
+
* the corresponding three.js tone-mapping constant. Falls back to
|
|
275
|
+
* {@link DEFAULT_TONE_MAPPING_MODE} for missing/invalid input.
|
|
276
|
+
*/
|
|
277
|
+
declare function resolveToneMapping(mode: unknown): ToneMapping;
|
|
278
|
+
/**
|
|
279
|
+
* Normalize an unknown/stored value into a valid {@link ToneMappingMode},
|
|
280
|
+
* falling back to {@link DEFAULT_TONE_MAPPING_MODE}.
|
|
281
|
+
*/
|
|
282
|
+
declare function normalizeToneMappingMode(value: unknown): ToneMappingMode;
|
|
283
|
+
|
|
279
284
|
type VizijBundleVersion = 1;
|
|
280
285
|
type VizijBundleGraphKind = "rig" | "pose" | "pose-driver" | "animation-bridge" | "low-level" | string;
|
|
281
286
|
type VizijPoseId = string;
|
|
@@ -288,6 +293,40 @@ interface VizijBundleGraphMetadata {
|
|
|
288
293
|
exportedAt?: string;
|
|
289
294
|
[key: string]: unknown;
|
|
290
295
|
}
|
|
296
|
+
/**
|
|
297
|
+
* One path in a profile, with its type and constraints — arora's `KeyInfo`
|
|
298
|
+
* shape, so a profile round-trips through the descriptor the runtime already
|
|
299
|
+
* speaks.
|
|
300
|
+
*/
|
|
301
|
+
interface VizijProfileKey {
|
|
302
|
+
path: string;
|
|
303
|
+
kind?: string;
|
|
304
|
+
value_type?: string;
|
|
305
|
+
min?: number;
|
|
306
|
+
max?: number;
|
|
307
|
+
default_value?: unknown;
|
|
308
|
+
/** Standard metadata: the FACS action unit, ARKit blendshape, and tier. */
|
|
309
|
+
meta?: {
|
|
310
|
+
au?: number;
|
|
311
|
+
arkit?: string;
|
|
312
|
+
tier?: string;
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* A profile the face declares it speaks: a set of paths and their types — the
|
|
317
|
+
* vocabulary its graphs are authored against.
|
|
318
|
+
*
|
|
319
|
+
* A profile is names and types, not a graph, so it sits beside `graphs` rather
|
|
320
|
+
* than inside it. Declaring it on the asset is what lets a reader know which
|
|
321
|
+
* vocabulary to hold the face to.
|
|
322
|
+
*/
|
|
323
|
+
interface VizijBundleProfile {
|
|
324
|
+
id: string;
|
|
325
|
+
version: string;
|
|
326
|
+
title?: string;
|
|
327
|
+
description?: string;
|
|
328
|
+
keys: VizijProfileKey[];
|
|
329
|
+
}
|
|
291
330
|
interface VizijBundleGraphEntry {
|
|
292
331
|
id: VizijGraphId;
|
|
293
332
|
kind: VizijBundleGraphKind;
|
|
@@ -357,6 +396,19 @@ interface VizijBundleAnimationEntry {
|
|
|
357
396
|
[key: string]: unknown;
|
|
358
397
|
};
|
|
359
398
|
}
|
|
399
|
+
type VizijStarredKind = "driver" | "pose";
|
|
400
|
+
/**
|
|
401
|
+
* A starred reference collected into the "Starred" control surface. Points at a
|
|
402
|
+
* real driver (standard-input id) or pose (pose id) by stable id so both the
|
|
403
|
+
* source panel and the Starred panel render the same underlying object.
|
|
404
|
+
*/
|
|
405
|
+
interface VizijStarredItem {
|
|
406
|
+
kind: VizijStarredKind;
|
|
407
|
+
id: string;
|
|
408
|
+
}
|
|
409
|
+
interface VizijBundleStarredSection {
|
|
410
|
+
items: VizijStarredItem[];
|
|
411
|
+
}
|
|
360
412
|
interface VizijSpeechConfig {
|
|
361
413
|
/** TTS voice name (e.g., "Ruth") */
|
|
362
414
|
voice?: string;
|
|
@@ -385,8 +437,22 @@ interface VizijBundleExtension {
|
|
|
385
437
|
version: VizijBundleVersion;
|
|
386
438
|
exportedAt?: string;
|
|
387
439
|
graphs?: VizijBundleGraphEntry[];
|
|
440
|
+
/** The profiles this face declares it speaks (see {@link VizijBundleProfile}). */
|
|
441
|
+
profiles?: VizijBundleProfile[];
|
|
388
442
|
poses?: VizijBundlePoseSection | null;
|
|
389
443
|
animations?: VizijBundleAnimationEntry[];
|
|
444
|
+
/**
|
|
445
|
+
* Scene-level view transform this face should be rendered with. Travels with
|
|
446
|
+
* the asset so a face authored in Blender (which typically wants `"agx"`)
|
|
447
|
+
* renders consistently wherever it is loaded. Omitted/unknown falls back to
|
|
448
|
+
* the renderer default (`"none"` — web match).
|
|
449
|
+
*/
|
|
450
|
+
toneMapping?: ToneMappingMode;
|
|
451
|
+
/**
|
|
452
|
+
* Designer-curated set of starred drivers/poses (the "Starred" control
|
|
453
|
+
* surface). References real functionality by stable id.
|
|
454
|
+
*/
|
|
455
|
+
starred?: VizijBundleStarredSection | null;
|
|
390
456
|
/**
|
|
391
457
|
* Bundle-level metadata. May include `speechConfig: VizijSpeechConfig`
|
|
392
458
|
* for configuring the STT/LLM/TTS speech pipeline.
|
|
@@ -437,8 +503,59 @@ interface VizijAnimationClipData {
|
|
|
437
503
|
tracks: VizijAnimationTrackData[];
|
|
438
504
|
}
|
|
439
505
|
|
|
506
|
+
interface VizijProps {
|
|
507
|
+
style?: CSSProperties;
|
|
508
|
+
className?: string;
|
|
509
|
+
rootId: string;
|
|
510
|
+
namespace?: string;
|
|
511
|
+
showSafeArea?: boolean;
|
|
512
|
+
showSelectionGlow?: boolean;
|
|
513
|
+
/**
|
|
514
|
+
* View-transform applied by the WebGL renderer. Defaults to `"none"`
|
|
515
|
+
* (no tone mapping — matches plain web/canvas rendering). Faces authored in
|
|
516
|
+
* Blender typically want `"agx"` to compress over-driven emissive. Applied
|
|
517
|
+
* reactively, so it can be changed at runtime without remounting the canvas.
|
|
518
|
+
*/
|
|
519
|
+
toneMapping?: ToneMappingMode;
|
|
520
|
+
onPointerMissed?: ComponentProps<typeof Canvas>["onPointerMissed"];
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Renders the Vizij component.
|
|
524
|
+
*
|
|
525
|
+
* @param style - The style object for the Vizij component.
|
|
526
|
+
*
|
|
527
|
+
* @param className - The CSS class name for the Vizij component
|
|
528
|
+
*
|
|
529
|
+
* @param rootId - The root identifier for the Vizij component.
|
|
530
|
+
*
|
|
531
|
+
* @param namespace - The namespace for the Vizij component
|
|
532
|
+
*
|
|
533
|
+
* @param showSafeArea - Whether to show the safe area.
|
|
534
|
+
*
|
|
535
|
+
* @returns The rendered ReactNode.
|
|
536
|
+
*/
|
|
537
|
+
declare function Vizij({ style, className, rootId, namespace, showSafeArea, showSelectionGlow, toneMapping, onPointerMissed, }: VizijProps): ReactNode;
|
|
538
|
+
interface InnerVizijProps {
|
|
539
|
+
rootId: string;
|
|
540
|
+
namespace: string;
|
|
541
|
+
container?: {
|
|
542
|
+
width: number;
|
|
543
|
+
height: number;
|
|
544
|
+
resolution: number;
|
|
545
|
+
};
|
|
546
|
+
showSafeArea?: boolean;
|
|
547
|
+
showSelectionGlow?: boolean;
|
|
548
|
+
toneMapping?: ToneMappingMode;
|
|
549
|
+
}
|
|
550
|
+
declare function InnerVizij({ rootId, namespace, container, showSafeArea, showSelectionGlow, toneMapping, }: InnerVizijProps): react_jsx_runtime.JSX.Element;
|
|
551
|
+
|
|
440
552
|
interface VizijData {
|
|
441
553
|
world: World;
|
|
554
|
+
/**
|
|
555
|
+
* The mounted three.js object of each world element, by element id and then
|
|
556
|
+
* namespace. It lives beside `world` so that the world stays plain data.
|
|
557
|
+
*/
|
|
558
|
+
refs: Record<string, Record<string, RefObject<Group$1 | Mesh | null>>>;
|
|
442
559
|
animatables: Record<string, AnimatableValue>;
|
|
443
560
|
values: Map<string, RawValue | undefined>;
|
|
444
561
|
renderHit: boolean;
|
|
@@ -481,7 +598,7 @@ interface VizijActions {
|
|
|
481
598
|
setChildren: (id: string, children: string[]) => void;
|
|
482
599
|
setGeometry: (id: string, geometry: THREE.BufferGeometry) => void;
|
|
483
600
|
setMaterial: (id: string, material: string) => void;
|
|
484
|
-
setReference: (id: string, namespace: string, object: RefObject<Group$1 | Mesh>) => void;
|
|
601
|
+
setReference: (id: string, namespace: string, object: RefObject<Group$1 | Mesh | null>) => void;
|
|
485
602
|
createGroup: (root: boolean) => void;
|
|
486
603
|
createAnimatable: (elementId: string, featureName: string, value: Partial<AnimatableValue>) => void;
|
|
487
604
|
createStatic: (elementId: string, featureName: string, value: RawValue) => void;
|
|
@@ -491,6 +608,7 @@ type VizijStoreGetter = () => VizijData & VizijActions;
|
|
|
491
608
|
|
|
492
609
|
declare const VizijSlice: (set: VizijStoreSetter, get: VizijStoreGetter) => {
|
|
493
610
|
world: {};
|
|
611
|
+
refs: {};
|
|
494
612
|
animatables: {};
|
|
495
613
|
values: Map<any, any>;
|
|
496
614
|
renderHit: boolean;
|
|
@@ -534,7 +652,7 @@ declare const VizijSlice: (set: VizijStoreSetter, get: VizijStoreGetter) => {
|
|
|
534
652
|
setVizij: (scene: World, animatables: Record<string, AnimatableValue>) => void;
|
|
535
653
|
addWorldElements(world: World, animatables: Record<string, AnimatableValue>, replace?: boolean): void;
|
|
536
654
|
setPreferences: (preferences: Partial<VizijData["preferences"]>) => void;
|
|
537
|
-
setReference: (id: string, namespace: string, ref: RefObject<Group$1 | Mesh>) => void;
|
|
655
|
+
setReference: (id: string, namespace: string, ref: RefObject<Group$1 | Mesh | null>) => void;
|
|
538
656
|
};
|
|
539
657
|
declare const useDefaultVizijStore: zustand.UseBoundStore<Omit<zustand.StoreApi<VizijData & VizijActions>, "subscribe"> & {
|
|
540
658
|
subscribe: {
|
|
@@ -601,15 +719,14 @@ declare class EmptyModelError extends Error {
|
|
|
601
719
|
}
|
|
602
720
|
type ParserJsonFallbackSource = {
|
|
603
721
|
url?: string;
|
|
604
|
-
blob?: Blob;
|
|
605
722
|
arrayBuffer?: ArrayBuffer;
|
|
606
723
|
};
|
|
607
724
|
declare function parseGlbJsonChunk(buffer: ArrayBuffer): unknown | undefined;
|
|
608
|
-
declare function loadGLTF(url: string,
|
|
725
|
+
declare function loadGLTF(url: string, aggressiveImport?: boolean, rootBounds?: {
|
|
609
726
|
center: RawVector2;
|
|
610
727
|
size: RawVector2;
|
|
611
728
|
}): Promise<[World, Record<string, AnimatableValue>, VizijAnimationClipData[]]>;
|
|
612
|
-
declare function loadGLTFFromBlob(blob: Blob,
|
|
729
|
+
declare function loadGLTFFromBlob(blob: Blob, aggressiveImport?: boolean, rootBounds?: {
|
|
613
730
|
center: RawVector2;
|
|
614
731
|
size: RawVector2;
|
|
615
732
|
}): Promise<[World, Record<string, AnimatableValue>, VizijAnimationClipData[]]>;
|
|
@@ -620,34 +737,121 @@ type LoadedVizijAsset = {
|
|
|
620
737
|
animations: VizijAnimationClipData[];
|
|
621
738
|
scene: Group$1;
|
|
622
739
|
};
|
|
623
|
-
declare function loadGLTFWithBundle(url: string,
|
|
740
|
+
declare function loadGLTFWithBundle(url: string, aggressiveImport?: boolean, rootBounds?: {
|
|
624
741
|
center: RawVector2;
|
|
625
742
|
size: RawVector2;
|
|
626
743
|
}, parserJsonFallback?: ParserJsonFallbackSource): Promise<LoadedVizijAsset>;
|
|
627
|
-
|
|
744
|
+
/**
|
|
745
|
+
* Load a GLB or self-contained glTF from `blob`.
|
|
746
|
+
*
|
|
747
|
+
* The bytes are read into memory and parsed there; nothing is fetched, so this
|
|
748
|
+
* runs the same in a browser and in Node.
|
|
749
|
+
*/
|
|
750
|
+
declare function loadGLTFFromBlobWithBundle(blob: Blob, aggressiveImport?: boolean, rootBounds?: {
|
|
628
751
|
center: RawVector2;
|
|
629
752
|
size: RawVector2;
|
|
630
753
|
}): Promise<LoadedVizijAsset>;
|
|
631
754
|
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
* @returns A Promise that resolves with the THREE.Scene containing the loaded model.
|
|
637
|
-
*/
|
|
638
|
-
declare const loadGltfFromBlob: (blob: Blob, namespaces: string[]) => Promise<[World, Record<string, AnimatableValue>]>;
|
|
755
|
+
declare function deriveRootBounds(group: Group$1): {
|
|
756
|
+
center: RawVector2;
|
|
757
|
+
size: RawVector2;
|
|
758
|
+
} | null;
|
|
639
759
|
|
|
640
760
|
type ExportSceneOptions = {
|
|
641
|
-
|
|
761
|
+
/** Written into the GLB as the `VIZIJ_bundle` extension of the root node. */
|
|
642
762
|
bundle?: VizijBundleExtension | null;
|
|
763
|
+
/** Baked clips, written as glTF animations. */
|
|
643
764
|
animations?: AnimationClip[];
|
|
644
|
-
binary?: boolean;
|
|
645
|
-
onError?: (error: Error) => void;
|
|
646
|
-
onComplete?: () => void;
|
|
647
765
|
};
|
|
648
|
-
|
|
766
|
+
/**
|
|
767
|
+
* Rewrite a GLB's JSON chunk in place.
|
|
768
|
+
*
|
|
769
|
+
* `mutate` returns whether it changed anything; when it did not, the original
|
|
770
|
+
* buffer is handed back untouched rather than re-encoded. Any malformed input
|
|
771
|
+
* — wrong magic, missing JSON chunk, unparseable payload — returns the buffer
|
|
772
|
+
* as-is, since a patch is never worth corrupting an export over.
|
|
773
|
+
*
|
|
774
|
+
* Exists so a caller can amend an already-exported GLB instead of exporting
|
|
775
|
+
* twice: `GLTFExporter` is the expensive part, and running it again to change
|
|
776
|
+
* a few bytes of metadata froze the UI thread on real assets.
|
|
777
|
+
*/
|
|
778
|
+
declare function patchGlbJson(buffer: ArrayBuffer, mutate: (json: Record<string, unknown>) => boolean): ArrayBuffer;
|
|
779
|
+
/**
|
|
780
|
+
* Merge `metadata` into the `VIZIJ_bundle` extension already written into
|
|
781
|
+
* `glb`, wherever it landed — the exporter attaches it to a node, but a
|
|
782
|
+
* root-level extension is read back too, so both are handled.
|
|
783
|
+
*/
|
|
784
|
+
declare function patchVizijBundleMetadata(glb: ArrayBuffer, metadata: Record<string, unknown>): ArrayBuffer;
|
|
785
|
+
/**
|
|
786
|
+
* Encode `root` and its descendants as a GLB.
|
|
787
|
+
*
|
|
788
|
+
* Every node is written with its local translation, rotation and scale, every
|
|
789
|
+
* mesh with its morph weights, and each object's `userData` as glTF
|
|
790
|
+
* extensions and extras, which is where `RobotData` travels. A root that is
|
|
791
|
+
* not a `Scene` is cloned into one, so the caller's graph is left as it was.
|
|
792
|
+
*
|
|
793
|
+
* Only textures need a DOM; a scene without images encodes in Node.
|
|
794
|
+
*/
|
|
795
|
+
declare function exportScene(root: THREE.Object3D, options?: ExportSceneOptions): Promise<ArrayBuffer>;
|
|
796
|
+
|
|
797
|
+
/**
|
|
798
|
+
* Build the three.js graph of the world element `rootId` and its descendants,
|
|
799
|
+
* for `exportScene`.
|
|
800
|
+
*
|
|
801
|
+
* Each group becomes a `THREE.Group` and each shape a `THREE.Mesh` carrying a
|
|
802
|
+
* copy of its geometry and a material of its kind, as the renderer mounts
|
|
803
|
+
* them, with the element's `RobotData` in `userData`. No renderer is involved,
|
|
804
|
+
* so this runs in Node.
|
|
805
|
+
*
|
|
806
|
+
* Every feature takes its authored value: a static feature its value, an
|
|
807
|
+
* animated one its animatable's `default` in `animatables`. Node translation,
|
|
808
|
+
* rotation and scale, morph weights and material factors in the exported file
|
|
809
|
+
* are therefore the same numbers as the `RobotData` defaults, never a runtime
|
|
810
|
+
* pose. A caller that wants other values in the file passes them as the
|
|
811
|
+
* defaults of `animatables`.
|
|
812
|
+
*
|
|
813
|
+
* Throws when an element is missing from `world`, when an animated feature
|
|
814
|
+
* names an animatable missing from `animatables`, and for ellipse and
|
|
815
|
+
* rectangle elements, which have no exported form.
|
|
816
|
+
*/
|
|
817
|
+
declare function buildSceneGraph(world: World, animatables: Record<string, AnimatableValue>, rootId: string): THREE.Object3D;
|
|
649
818
|
|
|
650
819
|
declare function extractVizijBundle(object: Object3D, parserJson?: unknown): VizijBundleExtension | null;
|
|
651
820
|
declare function applyVizijBundle(object: Object3D, bundle: VizijBundleExtension | null): () => void;
|
|
652
821
|
|
|
653
|
-
|
|
822
|
+
/**
|
|
823
|
+
* Canonical morph-target key derivation.
|
|
824
|
+
*
|
|
825
|
+
* Morph feature keys are part of the animation binding contract: a propsrig
|
|
826
|
+
* input path is built from `(elementName, featureKey, component)`, and for a
|
|
827
|
+
* morph the feature key is derived from the morph's name. Import (building
|
|
828
|
+
* animatables from geometry) and animation channel resolution must therefore
|
|
829
|
+
* agree exactly, so both use the helpers here rather than re-deriving the rule.
|
|
830
|
+
*
|
|
831
|
+
* Note the slug is normalized twice on the path route: keys produced here are
|
|
832
|
+
* later passed through `normalizeStandardRigGroup` when the propsrig path is
|
|
833
|
+
* built, which independently lowercases and collapses separators. Casing here
|
|
834
|
+
* is therefore not load-bearing for path resolution — but it *is* the stored
|
|
835
|
+
* feature key on the renderable (and in exported `RobotData`), so changing it
|
|
836
|
+
* still changes the shape of authored data. Unit tests pin the rule directly;
|
|
837
|
+
* the corpus test cannot see a casing change because of the double pass.
|
|
838
|
+
*/
|
|
839
|
+
/**
|
|
840
|
+
* Allocates the feature key for a single morph target, deduplicating against
|
|
841
|
+
* keys already handed out for the same mesh.
|
|
842
|
+
*
|
|
843
|
+
* `used` is mutated: callers iterating a mesh's morph targets must share one
|
|
844
|
+
* set so collisions resolve deterministically in iteration order.
|
|
845
|
+
*/
|
|
846
|
+
declare function sanitizeMorphKey(name: string, fallbackIndex: number, used: Set<string>): string;
|
|
847
|
+
/**
|
|
848
|
+
* Derives feature keys for a mesh's morph targets in order, applying the same
|
|
849
|
+
* dedupe sequence `sanitizeMorphKey` applies during import.
|
|
850
|
+
*
|
|
851
|
+
* Pass morph names in the mesh's own target order (glTF
|
|
852
|
+
* `meshes[].extras.targetNames`, or `morphTargetDictionary` insertion order)
|
|
853
|
+
* so the result matches the keys import produced for that mesh.
|
|
854
|
+
*/
|
|
855
|
+
declare function deriveMorphFeatureKeys(names: ReadonlyArray<string>): string[];
|
|
856
|
+
|
|
857
|
+
export { type AnimatedFeature, DEFAULT_TONE_MAPPING_MODE, type Ellipse, type EllipseFeature, EmptyModelError, type ExportSceneOptions, type Feature, type Group, type GroupFeature, InnerVizij, type InnerVizijProps, type LoadedVizijAsset, type Rectangle, type RectangleFeature, type RenderableBase, type RenderableFeature, type Selection, type Shape, type ShapeFeature, ShapeMaterial, type StaticFeature, type Stored, type StoredAnimatedFeature, type StoredEllipse, type StoredFeatures, type StoredGroup, type StoredRectangle, type StoredRenderable, type StoredShape, TONE_MAPPING_LABELS, TONE_MAPPING_MODES, type ToneMappingMode, Vizij, type VizijActions, type VizijAnimationClipData, type VizijAnimationId, type VizijAnimationTrackData, type VizijBundleAnimationClip, type VizijBundleAnimationEntry, type VizijBundleAnimationKeyframe, type VizijBundleAnimationTrack, type VizijBundleExtension, type VizijBundleGraphEntry, type VizijBundleGraphKind, type VizijBundleGraphMetadata, type VizijBundlePoseSection, type VizijBundleProfile, type VizijBundleStarredSection, type VizijBundleVersion, VizijContext, type VizijData, type VizijGraphId, type VizijPoseDefinition, type VizijPoseId, type VizijPoseRigConfig, type VizijProfileKey, type VizijProps, VizijSlice, type VizijSpeechConfig, type VizijStarredItem, type VizijStarredKind, type VizijStore, type VizijStoreGetter, type VizijStoreSetter, type World, applyVizijBundle, buildSceneGraph, createVizijStore, deriveMorphFeatureKeys, deriveRootBounds, exportScene, extractVizijBundle, isToneMappingMode, loadGLTF, loadGLTFFromBlob, loadGLTFFromBlobWithBundle, loadGLTFWithBundle, normalizeToneMappingMode, parseGlbJsonChunk, patchGlbJson, patchVizijBundleMetadata, resolveToneMapping, sanitizeMorphKey, useDefaultVizijStore, useFeatures, useVizijStore, useVizijStoreGetter, useVizijStoreSetter, useVizijStoreSubscription };
|