@vizij/render 0.0.2 → 0.0.3
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 +12 -0
- package/dist/index.d.mts +113 -3
- package/dist/index.d.ts +113 -3
- package/dist/index.js +244 -41
- package/dist/index.mjs +240 -41
- package/package.json +3 -4
package/README.md
CHANGED
|
@@ -101,6 +101,18 @@ The store tracks world graph entries, controllers, debug overlays, and renderabl
|
|
|
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
|
+
### Dual-format Vizij bundles
|
|
105
|
+
|
|
106
|
+
Vizij scenes persist authoring metadata inside GLBs so third-party tools see baked animation, while Vizij runtimes retain orchestrator graphs and clips.
|
|
107
|
+
|
|
108
|
+
- Every renderable still carries a `RobotData` extension in `userData` describing features and animatable bindings.
|
|
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(group, { bundle, animations })` to embed both the Vizij bundle and optional baked `THREE.AnimationClip` instances. The helper attaches the bundle only for the export call and restores the original object.
|
|
111
|
+
- When loading assets, prefer `loadGLTFWithBundle` / `loadGLTFFromBlobWithBundle` to retrieve `{ world, animatables, bundle }`. The legacy tuple helpers remain available if you do not need bundle metadata.
|
|
112
|
+
- `extractVizijBundle(scene)` and `applyVizijBundle(scene, bundle)` (under `src/functions/vizij-bundle.ts`) let advanced tooling inspect or mutate bundles without triggering a fresh export.
|
|
113
|
+
|
|
114
|
+
With this structure, authoring tools can round-trip orchestrator assets while shipping native glTF animations for viewers that do not understand Vizij.
|
|
115
|
+
|
|
104
116
|
---
|
|
105
117
|
|
|
106
118
|
## Development & Testing
|
package/dist/index.d.mts
CHANGED
|
@@ -4,7 +4,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
4
4
|
import { Canvas, ThreeEvent } from '@react-three/fiber';
|
|
5
5
|
import * as zustand from 'zustand';
|
|
6
6
|
import * as THREE from 'three';
|
|
7
|
-
import { Mesh, Group as Group$1, BufferGeometry, ShapeGeometry } from 'three';
|
|
7
|
+
import { Mesh, Group as Group$1, BufferGeometry, ShapeGeometry, AnimationClip, Object3D } from 'three';
|
|
8
8
|
import { RawValue, AnimatableValue, RawVector2 } from '@vizij/utils';
|
|
9
9
|
|
|
10
10
|
declare function InnerController({ animatableId, namespace, subfield, className, }: {
|
|
@@ -282,6 +282,94 @@ interface Selection {
|
|
|
282
282
|
};
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
+
type VizijBundleVersion = 1;
|
|
286
|
+
type VizijBundleGraphKind = "rig" | "pose" | "pose-driver" | "animation-bridge" | "low-level" | string;
|
|
287
|
+
type VizijPoseId = string;
|
|
288
|
+
type VizijAnimationId = string;
|
|
289
|
+
type VizijGraphId = string;
|
|
290
|
+
interface VizijBundleGraphMetadata {
|
|
291
|
+
hash?: string;
|
|
292
|
+
source?: string;
|
|
293
|
+
kind?: VizijBundleGraphKind;
|
|
294
|
+
exportedAt?: string;
|
|
295
|
+
[key: string]: unknown;
|
|
296
|
+
}
|
|
297
|
+
interface VizijBundleGraphEntry {
|
|
298
|
+
id: VizijGraphId;
|
|
299
|
+
kind: VizijBundleGraphKind;
|
|
300
|
+
spec: Record<string, unknown>;
|
|
301
|
+
label?: string;
|
|
302
|
+
metadata?: VizijBundleGraphMetadata;
|
|
303
|
+
}
|
|
304
|
+
interface VizijPoseDefinition {
|
|
305
|
+
id: VizijPoseId;
|
|
306
|
+
name?: string;
|
|
307
|
+
description?: string;
|
|
308
|
+
values: Record<string, number | undefined>;
|
|
309
|
+
}
|
|
310
|
+
interface VizijPoseRigConfig {
|
|
311
|
+
version: number;
|
|
312
|
+
faceId?: string | null;
|
|
313
|
+
title?: string;
|
|
314
|
+
description?: string;
|
|
315
|
+
neutralInputs: Record<string, number>;
|
|
316
|
+
poses: VizijPoseDefinition[];
|
|
317
|
+
metadata?: Record<string, unknown>;
|
|
318
|
+
[key: string]: unknown;
|
|
319
|
+
}
|
|
320
|
+
interface VizijBundlePoseSection {
|
|
321
|
+
config: VizijPoseRigConfig;
|
|
322
|
+
metadata?: {
|
|
323
|
+
hash?: string;
|
|
324
|
+
exportedAt?: string;
|
|
325
|
+
[key: string]: unknown;
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
interface VizijBundleAnimationKeyframe {
|
|
329
|
+
time: number;
|
|
330
|
+
value: number;
|
|
331
|
+
easing?: "linear" | "easeIn" | "easeOut" | "easeInOut" | string;
|
|
332
|
+
inTangent?: number | null;
|
|
333
|
+
outTangent?: number | null;
|
|
334
|
+
[key: string]: unknown;
|
|
335
|
+
}
|
|
336
|
+
interface VizijBundleAnimationTrack {
|
|
337
|
+
channel: string;
|
|
338
|
+
keyframes: VizijBundleAnimationKeyframe[];
|
|
339
|
+
interpolation?: "step" | "linear" | "cubic" | string;
|
|
340
|
+
[key: string]: unknown;
|
|
341
|
+
}
|
|
342
|
+
interface VizijBundleAnimationClip {
|
|
343
|
+
id: VizijAnimationId;
|
|
344
|
+
name?: string;
|
|
345
|
+
duration?: number;
|
|
346
|
+
tracks: VizijBundleAnimationTrack[];
|
|
347
|
+
metadata?: Record<string, unknown>;
|
|
348
|
+
[key: string]: unknown;
|
|
349
|
+
}
|
|
350
|
+
interface VizijBundleAnimationEntry {
|
|
351
|
+
id: VizijAnimationId;
|
|
352
|
+
clip: VizijBundleAnimationClip;
|
|
353
|
+
metadata?: {
|
|
354
|
+
hash?: string;
|
|
355
|
+
sampleRateHz?: number;
|
|
356
|
+
rigGraphHash?: string;
|
|
357
|
+
poseGraphHash?: string | null;
|
|
358
|
+
bakedClipIndex?: number | null;
|
|
359
|
+
tolerance?: number;
|
|
360
|
+
exportedAt?: string;
|
|
361
|
+
[key: string]: unknown;
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
interface VizijBundleExtension {
|
|
365
|
+
version: VizijBundleVersion;
|
|
366
|
+
exportedAt?: string;
|
|
367
|
+
graphs?: VizijBundleGraphEntry[];
|
|
368
|
+
poses?: VizijBundlePoseSection | null;
|
|
369
|
+
animations?: VizijBundleAnimationEntry[];
|
|
370
|
+
metadata?: Record<string, unknown>;
|
|
371
|
+
}
|
|
372
|
+
|
|
285
373
|
interface VizijData {
|
|
286
374
|
world: World;
|
|
287
375
|
animatables: Record<string, AnimatableValue>;
|
|
@@ -442,6 +530,19 @@ declare function loadGLTFFromBlob(blob: Blob, namespaces: string[], aggressiveIm
|
|
|
442
530
|
center: RawVector2;
|
|
443
531
|
size: RawVector2;
|
|
444
532
|
}): Promise<[World, Record<string, AnimatableValue>]>;
|
|
533
|
+
type LoadedVizijAsset = {
|
|
534
|
+
world: World;
|
|
535
|
+
animatables: Record<string, AnimatableValue>;
|
|
536
|
+
bundle: VizijBundleExtension | null;
|
|
537
|
+
};
|
|
538
|
+
declare function loadGLTFWithBundle(url: string, namespaces: string[], aggressiveImport?: boolean, rootBounds?: {
|
|
539
|
+
center: RawVector2;
|
|
540
|
+
size: RawVector2;
|
|
541
|
+
}): Promise<LoadedVizijAsset>;
|
|
542
|
+
declare function loadGLTFFromBlobWithBundle(blob: Blob, namespaces: string[], aggressiveImport?: boolean, rootBounds?: {
|
|
543
|
+
center: RawVector2;
|
|
544
|
+
size: RawVector2;
|
|
545
|
+
}): Promise<LoadedVizijAsset>;
|
|
445
546
|
|
|
446
547
|
/**
|
|
447
548
|
* Loads a GLTF model from a Blob and returns the Three.js scene containing the model.
|
|
@@ -451,6 +552,15 @@ declare function loadGLTFFromBlob(blob: Blob, namespaces: string[], aggressiveIm
|
|
|
451
552
|
*/
|
|
452
553
|
declare const loadGltfFromBlob: (blob: Blob, namespaces: string[]) => Promise<[World, Record<string, AnimatableValue>]>;
|
|
453
554
|
|
|
454
|
-
|
|
555
|
+
type ExportSceneOptions = {
|
|
556
|
+
fileName?: string;
|
|
557
|
+
bundle?: VizijBundleExtension | null;
|
|
558
|
+
animations?: AnimationClip[];
|
|
559
|
+
binary?: boolean;
|
|
560
|
+
};
|
|
561
|
+
declare function exportScene(data: Group$1, fileNameOrOptions?: string | ExportSceneOptions): void;
|
|
562
|
+
|
|
563
|
+
declare function extractVizijBundle(object: Object3D, parserJson?: unknown): VizijBundleExtension | null;
|
|
564
|
+
declare function applyVizijBundle(object: Object3D, bundle: VizijBundleExtension | null): () => void;
|
|
455
565
|
|
|
456
|
-
export { type AnimatedFeature, Controller, type Ellipse, type EllipseFeature, EmptyModelError, type Feature, type Group, type GroupFeature, InnerVizij, type InnerVizijProps, 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, Vizij, type VizijActions, VizijContext, type VizijData, type VizijProps, VizijSlice, type VizijStore, type VizijStoreGetter, type VizijStoreSetter, type World, createVizijStore, exportScene, loadGLTF, loadGLTFFromBlob, loadGltfFromBlob, useDefaultVizijStore, useFeatures, useVizijStore, useVizijStoreGetter, useVizijStoreSetter, useVizijStoreSubscription };
|
|
566
|
+
export { type AnimatedFeature, Controller, 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, Vizij, type VizijActions, type VizijAnimationId, type VizijBundleAnimationClip, type VizijBundleAnimationEntry, type VizijBundleAnimationKeyframe, type VizijBundleAnimationTrack, type VizijBundleExtension, type VizijBundleGraphEntry, type VizijBundleGraphKind, type VizijBundleGraphMetadata, type VizijBundlePoseSection, type VizijBundleVersion, VizijContext, type VizijData, type VizijGraphId, type VizijPoseDefinition, type VizijPoseId, type VizijPoseRigConfig, type VizijProps, VizijSlice, type VizijStore, type VizijStoreGetter, type VizijStoreSetter, type World, applyVizijBundle, createVizijStore, exportScene, extractVizijBundle, loadGLTF, loadGLTFFromBlob, loadGLTFFromBlobWithBundle, loadGLTFWithBundle, loadGltfFromBlob, useDefaultVizijStore, useFeatures, useVizijStore, useVizijStoreGetter, useVizijStoreSetter, useVizijStoreSubscription };
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
4
4
|
import { Canvas, ThreeEvent } from '@react-three/fiber';
|
|
5
5
|
import * as zustand from 'zustand';
|
|
6
6
|
import * as THREE from 'three';
|
|
7
|
-
import { Mesh, Group as Group$1, BufferGeometry, ShapeGeometry } from 'three';
|
|
7
|
+
import { Mesh, Group as Group$1, BufferGeometry, ShapeGeometry, AnimationClip, Object3D } from 'three';
|
|
8
8
|
import { RawValue, AnimatableValue, RawVector2 } from '@vizij/utils';
|
|
9
9
|
|
|
10
10
|
declare function InnerController({ animatableId, namespace, subfield, className, }: {
|
|
@@ -282,6 +282,94 @@ interface Selection {
|
|
|
282
282
|
};
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
+
type VizijBundleVersion = 1;
|
|
286
|
+
type VizijBundleGraphKind = "rig" | "pose" | "pose-driver" | "animation-bridge" | "low-level" | string;
|
|
287
|
+
type VizijPoseId = string;
|
|
288
|
+
type VizijAnimationId = string;
|
|
289
|
+
type VizijGraphId = string;
|
|
290
|
+
interface VizijBundleGraphMetadata {
|
|
291
|
+
hash?: string;
|
|
292
|
+
source?: string;
|
|
293
|
+
kind?: VizijBundleGraphKind;
|
|
294
|
+
exportedAt?: string;
|
|
295
|
+
[key: string]: unknown;
|
|
296
|
+
}
|
|
297
|
+
interface VizijBundleGraphEntry {
|
|
298
|
+
id: VizijGraphId;
|
|
299
|
+
kind: VizijBundleGraphKind;
|
|
300
|
+
spec: Record<string, unknown>;
|
|
301
|
+
label?: string;
|
|
302
|
+
metadata?: VizijBundleGraphMetadata;
|
|
303
|
+
}
|
|
304
|
+
interface VizijPoseDefinition {
|
|
305
|
+
id: VizijPoseId;
|
|
306
|
+
name?: string;
|
|
307
|
+
description?: string;
|
|
308
|
+
values: Record<string, number | undefined>;
|
|
309
|
+
}
|
|
310
|
+
interface VizijPoseRigConfig {
|
|
311
|
+
version: number;
|
|
312
|
+
faceId?: string | null;
|
|
313
|
+
title?: string;
|
|
314
|
+
description?: string;
|
|
315
|
+
neutralInputs: Record<string, number>;
|
|
316
|
+
poses: VizijPoseDefinition[];
|
|
317
|
+
metadata?: Record<string, unknown>;
|
|
318
|
+
[key: string]: unknown;
|
|
319
|
+
}
|
|
320
|
+
interface VizijBundlePoseSection {
|
|
321
|
+
config: VizijPoseRigConfig;
|
|
322
|
+
metadata?: {
|
|
323
|
+
hash?: string;
|
|
324
|
+
exportedAt?: string;
|
|
325
|
+
[key: string]: unknown;
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
interface VizijBundleAnimationKeyframe {
|
|
329
|
+
time: number;
|
|
330
|
+
value: number;
|
|
331
|
+
easing?: "linear" | "easeIn" | "easeOut" | "easeInOut" | string;
|
|
332
|
+
inTangent?: number | null;
|
|
333
|
+
outTangent?: number | null;
|
|
334
|
+
[key: string]: unknown;
|
|
335
|
+
}
|
|
336
|
+
interface VizijBundleAnimationTrack {
|
|
337
|
+
channel: string;
|
|
338
|
+
keyframes: VizijBundleAnimationKeyframe[];
|
|
339
|
+
interpolation?: "step" | "linear" | "cubic" | string;
|
|
340
|
+
[key: string]: unknown;
|
|
341
|
+
}
|
|
342
|
+
interface VizijBundleAnimationClip {
|
|
343
|
+
id: VizijAnimationId;
|
|
344
|
+
name?: string;
|
|
345
|
+
duration?: number;
|
|
346
|
+
tracks: VizijBundleAnimationTrack[];
|
|
347
|
+
metadata?: Record<string, unknown>;
|
|
348
|
+
[key: string]: unknown;
|
|
349
|
+
}
|
|
350
|
+
interface VizijBundleAnimationEntry {
|
|
351
|
+
id: VizijAnimationId;
|
|
352
|
+
clip: VizijBundleAnimationClip;
|
|
353
|
+
metadata?: {
|
|
354
|
+
hash?: string;
|
|
355
|
+
sampleRateHz?: number;
|
|
356
|
+
rigGraphHash?: string;
|
|
357
|
+
poseGraphHash?: string | null;
|
|
358
|
+
bakedClipIndex?: number | null;
|
|
359
|
+
tolerance?: number;
|
|
360
|
+
exportedAt?: string;
|
|
361
|
+
[key: string]: unknown;
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
interface VizijBundleExtension {
|
|
365
|
+
version: VizijBundleVersion;
|
|
366
|
+
exportedAt?: string;
|
|
367
|
+
graphs?: VizijBundleGraphEntry[];
|
|
368
|
+
poses?: VizijBundlePoseSection | null;
|
|
369
|
+
animations?: VizijBundleAnimationEntry[];
|
|
370
|
+
metadata?: Record<string, unknown>;
|
|
371
|
+
}
|
|
372
|
+
|
|
285
373
|
interface VizijData {
|
|
286
374
|
world: World;
|
|
287
375
|
animatables: Record<string, AnimatableValue>;
|
|
@@ -442,6 +530,19 @@ declare function loadGLTFFromBlob(blob: Blob, namespaces: string[], aggressiveIm
|
|
|
442
530
|
center: RawVector2;
|
|
443
531
|
size: RawVector2;
|
|
444
532
|
}): Promise<[World, Record<string, AnimatableValue>]>;
|
|
533
|
+
type LoadedVizijAsset = {
|
|
534
|
+
world: World;
|
|
535
|
+
animatables: Record<string, AnimatableValue>;
|
|
536
|
+
bundle: VizijBundleExtension | null;
|
|
537
|
+
};
|
|
538
|
+
declare function loadGLTFWithBundle(url: string, namespaces: string[], aggressiveImport?: boolean, rootBounds?: {
|
|
539
|
+
center: RawVector2;
|
|
540
|
+
size: RawVector2;
|
|
541
|
+
}): Promise<LoadedVizijAsset>;
|
|
542
|
+
declare function loadGLTFFromBlobWithBundle(blob: Blob, namespaces: string[], aggressiveImport?: boolean, rootBounds?: {
|
|
543
|
+
center: RawVector2;
|
|
544
|
+
size: RawVector2;
|
|
545
|
+
}): Promise<LoadedVizijAsset>;
|
|
445
546
|
|
|
446
547
|
/**
|
|
447
548
|
* Loads a GLTF model from a Blob and returns the Three.js scene containing the model.
|
|
@@ -451,6 +552,15 @@ declare function loadGLTFFromBlob(blob: Blob, namespaces: string[], aggressiveIm
|
|
|
451
552
|
*/
|
|
452
553
|
declare const loadGltfFromBlob: (blob: Blob, namespaces: string[]) => Promise<[World, Record<string, AnimatableValue>]>;
|
|
453
554
|
|
|
454
|
-
|
|
555
|
+
type ExportSceneOptions = {
|
|
556
|
+
fileName?: string;
|
|
557
|
+
bundle?: VizijBundleExtension | null;
|
|
558
|
+
animations?: AnimationClip[];
|
|
559
|
+
binary?: boolean;
|
|
560
|
+
};
|
|
561
|
+
declare function exportScene(data: Group$1, fileNameOrOptions?: string | ExportSceneOptions): void;
|
|
562
|
+
|
|
563
|
+
declare function extractVizijBundle(object: Object3D, parserJson?: unknown): VizijBundleExtension | null;
|
|
564
|
+
declare function applyVizijBundle(object: Object3D, bundle: VizijBundleExtension | null): () => void;
|
|
455
565
|
|
|
456
|
-
export { type AnimatedFeature, Controller, type Ellipse, type EllipseFeature, EmptyModelError, type Feature, type Group, type GroupFeature, InnerVizij, type InnerVizijProps, 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, Vizij, type VizijActions, VizijContext, type VizijData, type VizijProps, VizijSlice, type VizijStore, type VizijStoreGetter, type VizijStoreSetter, type World, createVizijStore, exportScene, loadGLTF, loadGLTFFromBlob, loadGltfFromBlob, useDefaultVizijStore, useFeatures, useVizijStore, useVizijStoreGetter, useVizijStoreSetter, useVizijStoreSubscription };
|
|
566
|
+
export { type AnimatedFeature, Controller, 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, Vizij, type VizijActions, type VizijAnimationId, type VizijBundleAnimationClip, type VizijBundleAnimationEntry, type VizijBundleAnimationKeyframe, type VizijBundleAnimationTrack, type VizijBundleExtension, type VizijBundleGraphEntry, type VizijBundleGraphKind, type VizijBundleGraphMetadata, type VizijBundlePoseSection, type VizijBundleVersion, VizijContext, type VizijData, type VizijGraphId, type VizijPoseDefinition, type VizijPoseId, type VizijPoseRigConfig, type VizijProps, VizijSlice, type VizijStore, type VizijStoreGetter, type VizijStoreSetter, type World, applyVizijBundle, createVizijStore, exportScene, extractVizijBundle, loadGLTF, loadGLTFFromBlob, loadGLTFFromBlobWithBundle, loadGLTFWithBundle, loadGltfFromBlob, useDefaultVizijStore, useFeatures, useVizijStore, useVizijStoreGetter, useVizijStoreSetter, useVizijStoreSubscription };
|
package/dist/index.js
CHANGED
|
@@ -37,10 +37,14 @@ __export(index_exports, {
|
|
|
37
37
|
Vizij: () => Vizij,
|
|
38
38
|
VizijContext: () => VizijContext,
|
|
39
39
|
VizijSlice: () => VizijSlice,
|
|
40
|
+
applyVizijBundle: () => applyVizijBundle,
|
|
40
41
|
createVizijStore: () => createVizijStore,
|
|
41
42
|
exportScene: () => exportScene,
|
|
43
|
+
extractVizijBundle: () => extractVizijBundle,
|
|
42
44
|
loadGLTF: () => loadGLTF,
|
|
43
45
|
loadGLTFFromBlob: () => loadGLTFFromBlob,
|
|
46
|
+
loadGLTFFromBlobWithBundle: () => loadGLTFFromBlobWithBundle,
|
|
47
|
+
loadGLTFWithBundle: () => loadGLTFWithBundle,
|
|
44
48
|
loadGltfFromBlob: () => loadGltfFromBlob,
|
|
45
49
|
useDefaultVizijStore: () => useDefaultVizijStore,
|
|
46
50
|
useFeatures: () => useFeatures,
|
|
@@ -2521,7 +2525,9 @@ function traverseThree(group, namespaces, aggressiveImport = false, rootBounds)
|
|
|
2521
2525
|
});
|
|
2522
2526
|
const useRobotData = !aggressiveImport || hasRobotData;
|
|
2523
2527
|
if (useRobotData) {
|
|
2524
|
-
|
|
2528
|
+
const stack = [group];
|
|
2529
|
+
while (stack.length > 0) {
|
|
2530
|
+
const child = stack.pop();
|
|
2525
2531
|
if (child.userData?.gltfExtensions?.RobotData) {
|
|
2526
2532
|
const data = child.userData.gltfExtensions.RobotData;
|
|
2527
2533
|
applyStoredRenderableNames(child, data);
|
|
@@ -2590,7 +2596,10 @@ function traverseThree(group, namespaces, aggressiveImport = false, rootBounds)
|
|
|
2590
2596
|
throw new Error(`Unhandled type`);
|
|
2591
2597
|
}
|
|
2592
2598
|
}
|
|
2593
|
-
|
|
2599
|
+
if (child.children) {
|
|
2600
|
+
stack.push(...child.children);
|
|
2601
|
+
}
|
|
2602
|
+
}
|
|
2594
2603
|
} else {
|
|
2595
2604
|
const derivedRootBounds = rootBounds ?? deriveRootBounds(group);
|
|
2596
2605
|
if (!derivedRootBounds) {
|
|
@@ -2758,6 +2767,106 @@ function deriveRootBounds(group) {
|
|
|
2758
2767
|
};
|
|
2759
2768
|
}
|
|
2760
2769
|
|
|
2770
|
+
// src/functions/vizij-bundle.ts
|
|
2771
|
+
var BUNDLE_KEYS = ["VIZIJ_bundle"];
|
|
2772
|
+
function cloneBundle(value) {
|
|
2773
|
+
return JSON.parse(JSON.stringify(value));
|
|
2774
|
+
}
|
|
2775
|
+
function readExtensionValue(extensionContainer) {
|
|
2776
|
+
for (const key of BUNDLE_KEYS) {
|
|
2777
|
+
if (extensionContainer && Object.prototype.hasOwnProperty.call(extensionContainer, key)) {
|
|
2778
|
+
const value = extensionContainer[key];
|
|
2779
|
+
if (value && typeof value === "object") {
|
|
2780
|
+
return { key, value };
|
|
2781
|
+
}
|
|
2782
|
+
}
|
|
2783
|
+
}
|
|
2784
|
+
return null;
|
|
2785
|
+
}
|
|
2786
|
+
function searchObjectForBundle(object) {
|
|
2787
|
+
const stack = [object];
|
|
2788
|
+
while (stack.length > 0) {
|
|
2789
|
+
const current = stack.pop();
|
|
2790
|
+
const extensions = current?.userData?.gltfExtensions ?? current?.userData?.extensions ?? null;
|
|
2791
|
+
if (extensions && typeof extensions === "object") {
|
|
2792
|
+
const match = readExtensionValue(extensions);
|
|
2793
|
+
if (match) {
|
|
2794
|
+
return cloneBundle(match.value);
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2797
|
+
if (current.children && current.children.length > 0) {
|
|
2798
|
+
stack.push(...current.children);
|
|
2799
|
+
}
|
|
2800
|
+
}
|
|
2801
|
+
return null;
|
|
2802
|
+
}
|
|
2803
|
+
function searchParserJsonForBundle(parserJson) {
|
|
2804
|
+
if (!parserJson || typeof parserJson !== "object") {
|
|
2805
|
+
return null;
|
|
2806
|
+
}
|
|
2807
|
+
const nodes = Array.isArray(parserJson.nodes) ? parserJson.nodes : [];
|
|
2808
|
+
for (const node of nodes) {
|
|
2809
|
+
const extensions = node && typeof node === "object" ? node.extensions : null;
|
|
2810
|
+
if (extensions && typeof extensions === "object") {
|
|
2811
|
+
const match = readExtensionValue(extensions);
|
|
2812
|
+
if (match) {
|
|
2813
|
+
return cloneBundle(match.value);
|
|
2814
|
+
}
|
|
2815
|
+
}
|
|
2816
|
+
}
|
|
2817
|
+
const scenes = Array.isArray(parserJson.scenes) ? parserJson.scenes : [];
|
|
2818
|
+
for (const scene of scenes) {
|
|
2819
|
+
const extensions = scene && typeof scene === "object" ? scene.extensions : null;
|
|
2820
|
+
if (extensions && typeof extensions === "object") {
|
|
2821
|
+
const match = readExtensionValue(extensions);
|
|
2822
|
+
if (match) {
|
|
2823
|
+
return cloneBundle(match.value);
|
|
2824
|
+
}
|
|
2825
|
+
}
|
|
2826
|
+
}
|
|
2827
|
+
return null;
|
|
2828
|
+
}
|
|
2829
|
+
function extractVizijBundle(object, parserJson) {
|
|
2830
|
+
const fromObject = searchObjectForBundle(object);
|
|
2831
|
+
if (fromObject) {
|
|
2832
|
+
return fromObject;
|
|
2833
|
+
}
|
|
2834
|
+
const fromParser = searchParserJsonForBundle(parserJson);
|
|
2835
|
+
if (fromParser) {
|
|
2836
|
+
return fromParser;
|
|
2837
|
+
}
|
|
2838
|
+
return null;
|
|
2839
|
+
}
|
|
2840
|
+
function applyVizijBundle(object, bundle) {
|
|
2841
|
+
const userData = object.userData && typeof object.userData === "object" ? object.userData : {};
|
|
2842
|
+
const originalExtensions = userData.gltfExtensions;
|
|
2843
|
+
let applied = false;
|
|
2844
|
+
if (bundle) {
|
|
2845
|
+
userData.gltfExtensions = {
|
|
2846
|
+
...originalExtensions ?? {},
|
|
2847
|
+
VIZIJ_bundle: bundle
|
|
2848
|
+
};
|
|
2849
|
+
object.userData = userData;
|
|
2850
|
+
applied = true;
|
|
2851
|
+
}
|
|
2852
|
+
return () => {
|
|
2853
|
+
if (!applied) {
|
|
2854
|
+
return;
|
|
2855
|
+
}
|
|
2856
|
+
if (originalExtensions) {
|
|
2857
|
+
userData.gltfExtensions = originalExtensions;
|
|
2858
|
+
} else {
|
|
2859
|
+
if (userData.gltfExtensions) {
|
|
2860
|
+
delete userData.gltfExtensions;
|
|
2861
|
+
}
|
|
2862
|
+
if (Object.keys(userData).length === 0) {
|
|
2863
|
+
delete object.userData;
|
|
2864
|
+
}
|
|
2865
|
+
}
|
|
2866
|
+
applied = false;
|
|
2867
|
+
};
|
|
2868
|
+
}
|
|
2869
|
+
|
|
2761
2870
|
// src/functions/load-gltf.ts
|
|
2762
2871
|
THREE5.Object3D.DEFAULT_UP.set(0, 0, 1);
|
|
2763
2872
|
var EmptyModelError = class extends Error {
|
|
@@ -2771,24 +2880,27 @@ async function loadGLTF(url, namespaces, aggressiveImport = false, rootBounds) {
|
|
|
2771
2880
|
modelLoader.setDRACOLoader(new import_three_stdlib.DRACOLoader());
|
|
2772
2881
|
const modelData = await modelLoader.loadAsync(url);
|
|
2773
2882
|
const actualizedNamespaces = namespaces.length > 0 ? namespaces : ["default"];
|
|
2774
|
-
|
|
2883
|
+
const asset = parseScene(
|
|
2775
2884
|
modelData.scene,
|
|
2776
2885
|
actualizedNamespaces,
|
|
2777
2886
|
aggressiveImport,
|
|
2778
|
-
rootBounds
|
|
2887
|
+
rootBounds,
|
|
2888
|
+
modelData?.parser?.json
|
|
2779
2889
|
);
|
|
2890
|
+
return [asset.world, asset.animatables];
|
|
2780
2891
|
}
|
|
2781
2892
|
async function loadGLTFFromBlob(blob, namespaces, aggressiveImport = false, rootBounds) {
|
|
2782
2893
|
const actualizedNamespaces = namespaces.length > 0 ? namespaces : ["default"];
|
|
2783
2894
|
if (typeof URL !== "undefined" && typeof URL.createObjectURL === "function") {
|
|
2784
2895
|
const objectUrl = URL.createObjectURL(blob);
|
|
2785
2896
|
try {
|
|
2786
|
-
|
|
2897
|
+
const asset = await loadGLTFWithBundle(
|
|
2787
2898
|
objectUrl,
|
|
2788
2899
|
actualizedNamespaces,
|
|
2789
2900
|
aggressiveImport,
|
|
2790
2901
|
rootBounds
|
|
2791
2902
|
);
|
|
2903
|
+
return [asset.world, asset.animatables];
|
|
2792
2904
|
} finally {
|
|
2793
2905
|
URL.revokeObjectURL(objectUrl);
|
|
2794
2906
|
}
|
|
@@ -2802,14 +2914,83 @@ async function loadGLTFFromBlob(blob, namespaces, aggressiveImport = false, root
|
|
|
2802
2914
|
"",
|
|
2803
2915
|
(gltf) => {
|
|
2804
2916
|
try {
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
)
|
|
2917
|
+
const asset = parseScene(
|
|
2918
|
+
gltf.scene,
|
|
2919
|
+
actualizedNamespaces,
|
|
2920
|
+
aggressiveImport,
|
|
2921
|
+
rootBounds,
|
|
2922
|
+
gltf?.parser?.json
|
|
2812
2923
|
);
|
|
2924
|
+
resolve([asset.world, asset.animatables]);
|
|
2925
|
+
} catch (error) {
|
|
2926
|
+
if (error instanceof Error) {
|
|
2927
|
+
reject(error);
|
|
2928
|
+
} else {
|
|
2929
|
+
reject(new Error(String(error)));
|
|
2930
|
+
}
|
|
2931
|
+
}
|
|
2932
|
+
},
|
|
2933
|
+
(error) => {
|
|
2934
|
+
reject(new Error(`Error loading GLTF: ${error.message}`));
|
|
2935
|
+
}
|
|
2936
|
+
);
|
|
2937
|
+
});
|
|
2938
|
+
}
|
|
2939
|
+
function parseScene(scene, namespaces, aggressiveImport, rootBounds, parserJson) {
|
|
2940
|
+
const [world, animatables] = traverseThree(
|
|
2941
|
+
scene,
|
|
2942
|
+
namespaces,
|
|
2943
|
+
aggressiveImport,
|
|
2944
|
+
rootBounds
|
|
2945
|
+
);
|
|
2946
|
+
const bundle = extractVizijBundle(scene, parserJson);
|
|
2947
|
+
return { world, animatables, bundle };
|
|
2948
|
+
}
|
|
2949
|
+
async function loadGLTFWithBundle(url, namespaces, aggressiveImport = false, rootBounds) {
|
|
2950
|
+
const modelLoader = new import_three_stdlib.GLTFLoader();
|
|
2951
|
+
modelLoader.setDRACOLoader(new import_three_stdlib.DRACOLoader());
|
|
2952
|
+
const modelData = await modelLoader.loadAsync(url);
|
|
2953
|
+
const actualizedNamespaces = namespaces.length > 0 ? namespaces : ["default"];
|
|
2954
|
+
return parseScene(
|
|
2955
|
+
modelData.scene,
|
|
2956
|
+
actualizedNamespaces,
|
|
2957
|
+
aggressiveImport,
|
|
2958
|
+
rootBounds,
|
|
2959
|
+
modelData?.parser?.json
|
|
2960
|
+
);
|
|
2961
|
+
}
|
|
2962
|
+
async function loadGLTFFromBlobWithBundle(blob, namespaces, aggressiveImport = false, rootBounds) {
|
|
2963
|
+
const actualizedNamespaces = namespaces.length > 0 ? namespaces : ["default"];
|
|
2964
|
+
if (typeof URL !== "undefined" && typeof URL.createObjectURL === "function") {
|
|
2965
|
+
const objectUrl = URL.createObjectURL(blob);
|
|
2966
|
+
try {
|
|
2967
|
+
return await loadGLTFWithBundle(
|
|
2968
|
+
objectUrl,
|
|
2969
|
+
actualizedNamespaces,
|
|
2970
|
+
aggressiveImport,
|
|
2971
|
+
rootBounds
|
|
2972
|
+
);
|
|
2973
|
+
} finally {
|
|
2974
|
+
URL.revokeObjectURL(objectUrl);
|
|
2975
|
+
}
|
|
2976
|
+
}
|
|
2977
|
+
const arrayBuffer = typeof blob.arrayBuffer === "function" ? await blob.arrayBuffer() : await new Response(blob).arrayBuffer();
|
|
2978
|
+
return new Promise((resolve, reject) => {
|
|
2979
|
+
const loader = new import_three_stdlib.GLTFLoader();
|
|
2980
|
+
loader.setDRACOLoader(new import_three_stdlib.DRACOLoader());
|
|
2981
|
+
loader.parse(
|
|
2982
|
+
arrayBuffer,
|
|
2983
|
+
"",
|
|
2984
|
+
(gltf) => {
|
|
2985
|
+
try {
|
|
2986
|
+
const asset = parseScene(
|
|
2987
|
+
gltf.scene,
|
|
2988
|
+
actualizedNamespaces,
|
|
2989
|
+
aggressiveImport,
|
|
2990
|
+
rootBounds,
|
|
2991
|
+
gltf?.parser?.json
|
|
2992
|
+
);
|
|
2993
|
+
resolve(asset);
|
|
2813
2994
|
} catch (error) {
|
|
2814
2995
|
if (error instanceof Error) {
|
|
2815
2996
|
reject(error);
|
|
@@ -2858,7 +3039,11 @@ var loadGltfFromBlob = (blob, namespaces) => {
|
|
|
2858
3039
|
var import_three_stdlib3 = require("three-stdlib");
|
|
2859
3040
|
var THREE6 = __toESM(require("three"));
|
|
2860
3041
|
THREE6.Object3D.DEFAULT_UP.set(0, 0, 1);
|
|
2861
|
-
function exportScene(data,
|
|
3042
|
+
function exportScene(data, fileNameOrOptions = "scene.glb") {
|
|
3043
|
+
const options = typeof fileNameOrOptions === "string" ? { fileName: fileNameOrOptions } : fileNameOrOptions ?? {};
|
|
3044
|
+
const fileName = options.fileName ?? "scene.glb";
|
|
3045
|
+
const animationClips = Array.isArray(options.animations) ? options.animations.filter(Boolean) : [];
|
|
3046
|
+
const shouldAttachBundle = Boolean(options.bundle);
|
|
2862
3047
|
const exporter = new import_three_stdlib3.GLTFExporter();
|
|
2863
3048
|
exporter.register(() => ({
|
|
2864
3049
|
writeMesh(mesh, meshDef) {
|
|
@@ -2868,34 +3053,48 @@ function exportScene(data, fileName = "scene.glb") {
|
|
|
2868
3053
|
}
|
|
2869
3054
|
}
|
|
2870
3055
|
}));
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
3056
|
+
const detachBundle = shouldAttachBundle && options.bundle ? applyVizijBundle(data, options.bundle) : () => {
|
|
3057
|
+
};
|
|
3058
|
+
const binary = options.binary ?? true;
|
|
3059
|
+
const exporterOptions = {
|
|
3060
|
+
trs: true,
|
|
3061
|
+
onlyVisible: false,
|
|
3062
|
+
binary,
|
|
3063
|
+
includeCustomExtensions: true
|
|
3064
|
+
};
|
|
3065
|
+
if (animationClips.length > 0) {
|
|
3066
|
+
exporterOptions.animations = animationClips;
|
|
3067
|
+
}
|
|
3068
|
+
try {
|
|
3069
|
+
exporter.parse(
|
|
3070
|
+
data,
|
|
3071
|
+
(gltf) => {
|
|
3072
|
+
detachBundle();
|
|
3073
|
+
if (!(gltf instanceof ArrayBuffer)) {
|
|
3074
|
+
throw new Error("Failed to export scene!");
|
|
3075
|
+
}
|
|
3076
|
+
const link = document.createElement("a");
|
|
3077
|
+
link.href = URL.createObjectURL(
|
|
3078
|
+
new Blob([gltf], {
|
|
3079
|
+
type: "application/octet-stream"
|
|
3080
|
+
})
|
|
3081
|
+
);
|
|
3082
|
+
const trimmed = fileName.trim();
|
|
3083
|
+
const safeFileName = trimmed.length > 0 ? trimmed : "scene.glb";
|
|
3084
|
+
const downloadName = safeFileName.toLowerCase().endsWith(".glb") ? safeFileName : `${safeFileName}.glb`;
|
|
3085
|
+
link.download = downloadName;
|
|
3086
|
+
link.click();
|
|
3087
|
+
URL.revokeObjectURL(link.href);
|
|
3088
|
+
},
|
|
3089
|
+
() => {
|
|
3090
|
+
detachBundle();
|
|
3091
|
+
},
|
|
3092
|
+
exporterOptions
|
|
3093
|
+
);
|
|
3094
|
+
} catch (error) {
|
|
3095
|
+
detachBundle();
|
|
3096
|
+
throw error;
|
|
3097
|
+
}
|
|
2899
3098
|
}
|
|
2900
3099
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2901
3100
|
0 && (module.exports = {
|
|
@@ -2906,10 +3105,14 @@ function exportScene(data, fileName = "scene.glb") {
|
|
|
2906
3105
|
Vizij,
|
|
2907
3106
|
VizijContext,
|
|
2908
3107
|
VizijSlice,
|
|
3108
|
+
applyVizijBundle,
|
|
2909
3109
|
createVizijStore,
|
|
2910
3110
|
exportScene,
|
|
3111
|
+
extractVizijBundle,
|
|
2911
3112
|
loadGLTF,
|
|
2912
3113
|
loadGLTFFromBlob,
|
|
3114
|
+
loadGLTFFromBlobWithBundle,
|
|
3115
|
+
loadGLTFWithBundle,
|
|
2913
3116
|
loadGltfFromBlob,
|
|
2914
3117
|
useDefaultVizijStore,
|
|
2915
3118
|
useFeatures,
|
package/dist/index.mjs
CHANGED
|
@@ -2526,7 +2526,9 @@ function traverseThree(group, namespaces, aggressiveImport = false, rootBounds)
|
|
|
2526
2526
|
});
|
|
2527
2527
|
const useRobotData = !aggressiveImport || hasRobotData;
|
|
2528
2528
|
if (useRobotData) {
|
|
2529
|
-
|
|
2529
|
+
const stack = [group];
|
|
2530
|
+
while (stack.length > 0) {
|
|
2531
|
+
const child = stack.pop();
|
|
2530
2532
|
if (child.userData?.gltfExtensions?.RobotData) {
|
|
2531
2533
|
const data = child.userData.gltfExtensions.RobotData;
|
|
2532
2534
|
applyStoredRenderableNames(child, data);
|
|
@@ -2595,7 +2597,10 @@ function traverseThree(group, namespaces, aggressiveImport = false, rootBounds)
|
|
|
2595
2597
|
throw new Error(`Unhandled type`);
|
|
2596
2598
|
}
|
|
2597
2599
|
}
|
|
2598
|
-
|
|
2600
|
+
if (child.children) {
|
|
2601
|
+
stack.push(...child.children);
|
|
2602
|
+
}
|
|
2603
|
+
}
|
|
2599
2604
|
} else {
|
|
2600
2605
|
const derivedRootBounds = rootBounds ?? deriveRootBounds(group);
|
|
2601
2606
|
if (!derivedRootBounds) {
|
|
@@ -2763,6 +2768,106 @@ function deriveRootBounds(group) {
|
|
|
2763
2768
|
};
|
|
2764
2769
|
}
|
|
2765
2770
|
|
|
2771
|
+
// src/functions/vizij-bundle.ts
|
|
2772
|
+
var BUNDLE_KEYS = ["VIZIJ_bundle"];
|
|
2773
|
+
function cloneBundle(value) {
|
|
2774
|
+
return JSON.parse(JSON.stringify(value));
|
|
2775
|
+
}
|
|
2776
|
+
function readExtensionValue(extensionContainer) {
|
|
2777
|
+
for (const key of BUNDLE_KEYS) {
|
|
2778
|
+
if (extensionContainer && Object.prototype.hasOwnProperty.call(extensionContainer, key)) {
|
|
2779
|
+
const value = extensionContainer[key];
|
|
2780
|
+
if (value && typeof value === "object") {
|
|
2781
|
+
return { key, value };
|
|
2782
|
+
}
|
|
2783
|
+
}
|
|
2784
|
+
}
|
|
2785
|
+
return null;
|
|
2786
|
+
}
|
|
2787
|
+
function searchObjectForBundle(object) {
|
|
2788
|
+
const stack = [object];
|
|
2789
|
+
while (stack.length > 0) {
|
|
2790
|
+
const current = stack.pop();
|
|
2791
|
+
const extensions = current?.userData?.gltfExtensions ?? current?.userData?.extensions ?? null;
|
|
2792
|
+
if (extensions && typeof extensions === "object") {
|
|
2793
|
+
const match = readExtensionValue(extensions);
|
|
2794
|
+
if (match) {
|
|
2795
|
+
return cloneBundle(match.value);
|
|
2796
|
+
}
|
|
2797
|
+
}
|
|
2798
|
+
if (current.children && current.children.length > 0) {
|
|
2799
|
+
stack.push(...current.children);
|
|
2800
|
+
}
|
|
2801
|
+
}
|
|
2802
|
+
return null;
|
|
2803
|
+
}
|
|
2804
|
+
function searchParserJsonForBundle(parserJson) {
|
|
2805
|
+
if (!parserJson || typeof parserJson !== "object") {
|
|
2806
|
+
return null;
|
|
2807
|
+
}
|
|
2808
|
+
const nodes = Array.isArray(parserJson.nodes) ? parserJson.nodes : [];
|
|
2809
|
+
for (const node of nodes) {
|
|
2810
|
+
const extensions = node && typeof node === "object" ? node.extensions : null;
|
|
2811
|
+
if (extensions && typeof extensions === "object") {
|
|
2812
|
+
const match = readExtensionValue(extensions);
|
|
2813
|
+
if (match) {
|
|
2814
|
+
return cloneBundle(match.value);
|
|
2815
|
+
}
|
|
2816
|
+
}
|
|
2817
|
+
}
|
|
2818
|
+
const scenes = Array.isArray(parserJson.scenes) ? parserJson.scenes : [];
|
|
2819
|
+
for (const scene of scenes) {
|
|
2820
|
+
const extensions = scene && typeof scene === "object" ? scene.extensions : null;
|
|
2821
|
+
if (extensions && typeof extensions === "object") {
|
|
2822
|
+
const match = readExtensionValue(extensions);
|
|
2823
|
+
if (match) {
|
|
2824
|
+
return cloneBundle(match.value);
|
|
2825
|
+
}
|
|
2826
|
+
}
|
|
2827
|
+
}
|
|
2828
|
+
return null;
|
|
2829
|
+
}
|
|
2830
|
+
function extractVizijBundle(object, parserJson) {
|
|
2831
|
+
const fromObject = searchObjectForBundle(object);
|
|
2832
|
+
if (fromObject) {
|
|
2833
|
+
return fromObject;
|
|
2834
|
+
}
|
|
2835
|
+
const fromParser = searchParserJsonForBundle(parserJson);
|
|
2836
|
+
if (fromParser) {
|
|
2837
|
+
return fromParser;
|
|
2838
|
+
}
|
|
2839
|
+
return null;
|
|
2840
|
+
}
|
|
2841
|
+
function applyVizijBundle(object, bundle) {
|
|
2842
|
+
const userData = object.userData && typeof object.userData === "object" ? object.userData : {};
|
|
2843
|
+
const originalExtensions = userData.gltfExtensions;
|
|
2844
|
+
let applied = false;
|
|
2845
|
+
if (bundle) {
|
|
2846
|
+
userData.gltfExtensions = {
|
|
2847
|
+
...originalExtensions ?? {},
|
|
2848
|
+
VIZIJ_bundle: bundle
|
|
2849
|
+
};
|
|
2850
|
+
object.userData = userData;
|
|
2851
|
+
applied = true;
|
|
2852
|
+
}
|
|
2853
|
+
return () => {
|
|
2854
|
+
if (!applied) {
|
|
2855
|
+
return;
|
|
2856
|
+
}
|
|
2857
|
+
if (originalExtensions) {
|
|
2858
|
+
userData.gltfExtensions = originalExtensions;
|
|
2859
|
+
} else {
|
|
2860
|
+
if (userData.gltfExtensions) {
|
|
2861
|
+
delete userData.gltfExtensions;
|
|
2862
|
+
}
|
|
2863
|
+
if (Object.keys(userData).length === 0) {
|
|
2864
|
+
delete object.userData;
|
|
2865
|
+
}
|
|
2866
|
+
}
|
|
2867
|
+
applied = false;
|
|
2868
|
+
};
|
|
2869
|
+
}
|
|
2870
|
+
|
|
2766
2871
|
// src/functions/load-gltf.ts
|
|
2767
2872
|
THREE5.Object3D.DEFAULT_UP.set(0, 0, 1);
|
|
2768
2873
|
var EmptyModelError = class extends Error {
|
|
@@ -2776,24 +2881,27 @@ async function loadGLTF(url, namespaces, aggressiveImport = false, rootBounds) {
|
|
|
2776
2881
|
modelLoader.setDRACOLoader(new DRACOLoader());
|
|
2777
2882
|
const modelData = await modelLoader.loadAsync(url);
|
|
2778
2883
|
const actualizedNamespaces = namespaces.length > 0 ? namespaces : ["default"];
|
|
2779
|
-
|
|
2884
|
+
const asset = parseScene(
|
|
2780
2885
|
modelData.scene,
|
|
2781
2886
|
actualizedNamespaces,
|
|
2782
2887
|
aggressiveImport,
|
|
2783
|
-
rootBounds
|
|
2888
|
+
rootBounds,
|
|
2889
|
+
modelData?.parser?.json
|
|
2784
2890
|
);
|
|
2891
|
+
return [asset.world, asset.animatables];
|
|
2785
2892
|
}
|
|
2786
2893
|
async function loadGLTFFromBlob(blob, namespaces, aggressiveImport = false, rootBounds) {
|
|
2787
2894
|
const actualizedNamespaces = namespaces.length > 0 ? namespaces : ["default"];
|
|
2788
2895
|
if (typeof URL !== "undefined" && typeof URL.createObjectURL === "function") {
|
|
2789
2896
|
const objectUrl = URL.createObjectURL(blob);
|
|
2790
2897
|
try {
|
|
2791
|
-
|
|
2898
|
+
const asset = await loadGLTFWithBundle(
|
|
2792
2899
|
objectUrl,
|
|
2793
2900
|
actualizedNamespaces,
|
|
2794
2901
|
aggressiveImport,
|
|
2795
2902
|
rootBounds
|
|
2796
2903
|
);
|
|
2904
|
+
return [asset.world, asset.animatables];
|
|
2797
2905
|
} finally {
|
|
2798
2906
|
URL.revokeObjectURL(objectUrl);
|
|
2799
2907
|
}
|
|
@@ -2807,14 +2915,83 @@ async function loadGLTFFromBlob(blob, namespaces, aggressiveImport = false, root
|
|
|
2807
2915
|
"",
|
|
2808
2916
|
(gltf) => {
|
|
2809
2917
|
try {
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
)
|
|
2918
|
+
const asset = parseScene(
|
|
2919
|
+
gltf.scene,
|
|
2920
|
+
actualizedNamespaces,
|
|
2921
|
+
aggressiveImport,
|
|
2922
|
+
rootBounds,
|
|
2923
|
+
gltf?.parser?.json
|
|
2817
2924
|
);
|
|
2925
|
+
resolve([asset.world, asset.animatables]);
|
|
2926
|
+
} catch (error) {
|
|
2927
|
+
if (error instanceof Error) {
|
|
2928
|
+
reject(error);
|
|
2929
|
+
} else {
|
|
2930
|
+
reject(new Error(String(error)));
|
|
2931
|
+
}
|
|
2932
|
+
}
|
|
2933
|
+
},
|
|
2934
|
+
(error) => {
|
|
2935
|
+
reject(new Error(`Error loading GLTF: ${error.message}`));
|
|
2936
|
+
}
|
|
2937
|
+
);
|
|
2938
|
+
});
|
|
2939
|
+
}
|
|
2940
|
+
function parseScene(scene, namespaces, aggressiveImport, rootBounds, parserJson) {
|
|
2941
|
+
const [world, animatables] = traverseThree(
|
|
2942
|
+
scene,
|
|
2943
|
+
namespaces,
|
|
2944
|
+
aggressiveImport,
|
|
2945
|
+
rootBounds
|
|
2946
|
+
);
|
|
2947
|
+
const bundle = extractVizijBundle(scene, parserJson);
|
|
2948
|
+
return { world, animatables, bundle };
|
|
2949
|
+
}
|
|
2950
|
+
async function loadGLTFWithBundle(url, namespaces, aggressiveImport = false, rootBounds) {
|
|
2951
|
+
const modelLoader = new GLTFLoader();
|
|
2952
|
+
modelLoader.setDRACOLoader(new DRACOLoader());
|
|
2953
|
+
const modelData = await modelLoader.loadAsync(url);
|
|
2954
|
+
const actualizedNamespaces = namespaces.length > 0 ? namespaces : ["default"];
|
|
2955
|
+
return parseScene(
|
|
2956
|
+
modelData.scene,
|
|
2957
|
+
actualizedNamespaces,
|
|
2958
|
+
aggressiveImport,
|
|
2959
|
+
rootBounds,
|
|
2960
|
+
modelData?.parser?.json
|
|
2961
|
+
);
|
|
2962
|
+
}
|
|
2963
|
+
async function loadGLTFFromBlobWithBundle(blob, namespaces, aggressiveImport = false, rootBounds) {
|
|
2964
|
+
const actualizedNamespaces = namespaces.length > 0 ? namespaces : ["default"];
|
|
2965
|
+
if (typeof URL !== "undefined" && typeof URL.createObjectURL === "function") {
|
|
2966
|
+
const objectUrl = URL.createObjectURL(blob);
|
|
2967
|
+
try {
|
|
2968
|
+
return await loadGLTFWithBundle(
|
|
2969
|
+
objectUrl,
|
|
2970
|
+
actualizedNamespaces,
|
|
2971
|
+
aggressiveImport,
|
|
2972
|
+
rootBounds
|
|
2973
|
+
);
|
|
2974
|
+
} finally {
|
|
2975
|
+
URL.revokeObjectURL(objectUrl);
|
|
2976
|
+
}
|
|
2977
|
+
}
|
|
2978
|
+
const arrayBuffer = typeof blob.arrayBuffer === "function" ? await blob.arrayBuffer() : await new Response(blob).arrayBuffer();
|
|
2979
|
+
return new Promise((resolve, reject) => {
|
|
2980
|
+
const loader = new GLTFLoader();
|
|
2981
|
+
loader.setDRACOLoader(new DRACOLoader());
|
|
2982
|
+
loader.parse(
|
|
2983
|
+
arrayBuffer,
|
|
2984
|
+
"",
|
|
2985
|
+
(gltf) => {
|
|
2986
|
+
try {
|
|
2987
|
+
const asset = parseScene(
|
|
2988
|
+
gltf.scene,
|
|
2989
|
+
actualizedNamespaces,
|
|
2990
|
+
aggressiveImport,
|
|
2991
|
+
rootBounds,
|
|
2992
|
+
gltf?.parser?.json
|
|
2993
|
+
);
|
|
2994
|
+
resolve(asset);
|
|
2818
2995
|
} catch (error) {
|
|
2819
2996
|
if (error instanceof Error) {
|
|
2820
2997
|
reject(error);
|
|
@@ -2863,7 +3040,11 @@ var loadGltfFromBlob = (blob, namespaces) => {
|
|
|
2863
3040
|
import { GLTFExporter } from "three-stdlib";
|
|
2864
3041
|
import * as THREE6 from "three";
|
|
2865
3042
|
THREE6.Object3D.DEFAULT_UP.set(0, 0, 1);
|
|
2866
|
-
function exportScene(data,
|
|
3043
|
+
function exportScene(data, fileNameOrOptions = "scene.glb") {
|
|
3044
|
+
const options = typeof fileNameOrOptions === "string" ? { fileName: fileNameOrOptions } : fileNameOrOptions ?? {};
|
|
3045
|
+
const fileName = options.fileName ?? "scene.glb";
|
|
3046
|
+
const animationClips = Array.isArray(options.animations) ? options.animations.filter(Boolean) : [];
|
|
3047
|
+
const shouldAttachBundle = Boolean(options.bundle);
|
|
2867
3048
|
const exporter = new GLTFExporter();
|
|
2868
3049
|
exporter.register(() => ({
|
|
2869
3050
|
writeMesh(mesh, meshDef) {
|
|
@@ -2873,34 +3054,48 @@ function exportScene(data, fileName = "scene.glb") {
|
|
|
2873
3054
|
}
|
|
2874
3055
|
}
|
|
2875
3056
|
}));
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
3057
|
+
const detachBundle = shouldAttachBundle && options.bundle ? applyVizijBundle(data, options.bundle) : () => {
|
|
3058
|
+
};
|
|
3059
|
+
const binary = options.binary ?? true;
|
|
3060
|
+
const exporterOptions = {
|
|
3061
|
+
trs: true,
|
|
3062
|
+
onlyVisible: false,
|
|
3063
|
+
binary,
|
|
3064
|
+
includeCustomExtensions: true
|
|
3065
|
+
};
|
|
3066
|
+
if (animationClips.length > 0) {
|
|
3067
|
+
exporterOptions.animations = animationClips;
|
|
3068
|
+
}
|
|
3069
|
+
try {
|
|
3070
|
+
exporter.parse(
|
|
3071
|
+
data,
|
|
3072
|
+
(gltf) => {
|
|
3073
|
+
detachBundle();
|
|
3074
|
+
if (!(gltf instanceof ArrayBuffer)) {
|
|
3075
|
+
throw new Error("Failed to export scene!");
|
|
3076
|
+
}
|
|
3077
|
+
const link = document.createElement("a");
|
|
3078
|
+
link.href = URL.createObjectURL(
|
|
3079
|
+
new Blob([gltf], {
|
|
3080
|
+
type: "application/octet-stream"
|
|
3081
|
+
})
|
|
3082
|
+
);
|
|
3083
|
+
const trimmed = fileName.trim();
|
|
3084
|
+
const safeFileName = trimmed.length > 0 ? trimmed : "scene.glb";
|
|
3085
|
+
const downloadName = safeFileName.toLowerCase().endsWith(".glb") ? safeFileName : `${safeFileName}.glb`;
|
|
3086
|
+
link.download = downloadName;
|
|
3087
|
+
link.click();
|
|
3088
|
+
URL.revokeObjectURL(link.href);
|
|
3089
|
+
},
|
|
3090
|
+
() => {
|
|
3091
|
+
detachBundle();
|
|
3092
|
+
},
|
|
3093
|
+
exporterOptions
|
|
3094
|
+
);
|
|
3095
|
+
} catch (error) {
|
|
3096
|
+
detachBundle();
|
|
3097
|
+
throw error;
|
|
3098
|
+
}
|
|
2904
3099
|
}
|
|
2905
3100
|
export {
|
|
2906
3101
|
Controller,
|
|
@@ -2910,10 +3105,14 @@ export {
|
|
|
2910
3105
|
Vizij,
|
|
2911
3106
|
VizijContext,
|
|
2912
3107
|
VizijSlice,
|
|
3108
|
+
applyVizijBundle,
|
|
2913
3109
|
createVizijStore,
|
|
2914
3110
|
exportScene,
|
|
3111
|
+
extractVizijBundle,
|
|
2915
3112
|
loadGLTF,
|
|
2916
3113
|
loadGLTFFromBlob,
|
|
3114
|
+
loadGLTFFromBlobWithBundle,
|
|
3115
|
+
loadGLTFWithBundle,
|
|
2917
3116
|
loadGltfFromBlob,
|
|
2918
3117
|
useDefaultVizijStore,
|
|
2919
3118
|
useFeatures,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vizij/render",
|
|
3
3
|
"description": "Higher-level visualization and interaction components for robot and ai faces.",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.3",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"lint:fix": "pnpm --filter \"$npm_package_name\" exec eslint --ext .js,.jsx,.ts,.tsx --fix -- .",
|
|
32
32
|
"prettier:check": "prettier --check .",
|
|
33
33
|
"prettier:write": "prettier --write .",
|
|
34
|
-
"test": "
|
|
34
|
+
"test": "node --loader ./tests/node-ts-loader.mjs --test tests/*.node-test.mjs",
|
|
35
35
|
"clean": "rm -rf dist .turbo coverage tsconfig.tsbuildinfo",
|
|
36
36
|
"reset": "rm -rf node_modules",
|
|
37
37
|
"reset:hard": "pnpm run reset && rm -f pnpm-lock.yaml package-lock.json yarn.lock",
|
|
@@ -72,8 +72,7 @@
|
|
|
72
72
|
"zustand": "^5.0.2",
|
|
73
73
|
"tsup": "^8.0.1",
|
|
74
74
|
"typescript": "^5.5.0",
|
|
75
|
-
"prettier": "^3.4.2"
|
|
76
|
-
"vitest": "^3.2.4"
|
|
75
|
+
"prettier": "^3.4.2"
|
|
77
76
|
},
|
|
78
77
|
"size-limit": [
|
|
79
78
|
{
|