@vizij/render 0.1.2 → 1.0.1
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 +5 -4
- package/dist/index.d.mts +293 -92
- package/dist/index.d.ts +293 -92
- package/dist/index.js +634 -496
- package/dist/index.mjs +601 -462
- package/package.json +3 -5
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// src/vizij.tsx
|
|
2
2
|
import { Suspense, memo as memo6, useContext as useContext3, useEffect as useEffect7 } from "react";
|
|
3
3
|
import { ErrorBoundary } from "react-error-boundary";
|
|
4
|
-
import { Object3D as Object3D4, SRGBColorSpace
|
|
4
|
+
import { Object3D as Object3D4, SRGBColorSpace } from "three";
|
|
5
5
|
import { Canvas, useThree } from "@react-three/fiber";
|
|
6
6
|
import { Line as Line3, OrthographicCamera, Text } from "@react-three/drei";
|
|
7
7
|
import { useShallow as useShallow7 } from "zustand/react/shallow";
|
|
8
8
|
|
|
9
9
|
// src/renderables/renderable.tsx
|
|
10
|
-
import { memo as memo5
|
|
10
|
+
import { memo as memo5 } from "react";
|
|
11
11
|
import { useShallow as useShallow5 } from "zustand/react/shallow";
|
|
12
12
|
|
|
13
13
|
// src/hooks/use-vizij-store.ts
|
|
@@ -84,35 +84,33 @@ function useFeatures(namespace, features, callbacks, debugInfo) {
|
|
|
84
84
|
}, [features, callbacks, store, debugInfo, namespace]);
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
// src/functions/create-stored-data.ts
|
|
88
|
-
import { omit } from "lodash";
|
|
89
|
-
|
|
90
87
|
// src/functions/create-stored-features.ts
|
|
91
|
-
import { mapValues } from "lodash";
|
|
92
88
|
function createStoredFeatures(objectFeatures, animatableValues) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
89
|
+
const stored = Object.entries(objectFeatures).map(
|
|
90
|
+
([key, feat]) => {
|
|
91
|
+
if (feat.animated) {
|
|
92
|
+
const storedFeat = {
|
|
93
|
+
animated: true,
|
|
94
|
+
value: animatableValues[feat.value],
|
|
95
|
+
...feat.label ? { label: feat.label } : {}
|
|
96
|
+
};
|
|
97
|
+
return [key, storedFeat];
|
|
98
|
+
}
|
|
102
99
|
const staticFeature = feat;
|
|
103
|
-
return staticFeature.label ? { ...staticFeature } : staticFeature;
|
|
100
|
+
return [key, staticFeature.label ? { ...staticFeature } : staticFeature];
|
|
104
101
|
}
|
|
105
|
-
|
|
102
|
+
);
|
|
103
|
+
return Object.fromEntries(stored);
|
|
106
104
|
}
|
|
107
105
|
|
|
108
106
|
// src/functions/create-stored-data.ts
|
|
109
107
|
function createStoredRenderable(data, animatableValues) {
|
|
110
|
-
const
|
|
108
|
+
const { geometry: _geometry, ...stored } = data;
|
|
111
109
|
const storedFeatures = createStoredFeatures(
|
|
112
110
|
data.features,
|
|
113
111
|
animatableValues
|
|
114
112
|
);
|
|
115
|
-
return { ...
|
|
113
|
+
return { ...stored, features: storedFeatures };
|
|
116
114
|
}
|
|
117
115
|
|
|
118
116
|
// src/renderables/group.tsx
|
|
@@ -125,7 +123,9 @@ function InnerRenderedGroup({
|
|
|
125
123
|
}) {
|
|
126
124
|
const ref = useRef(null);
|
|
127
125
|
const group = useVizijStore(useShallow((state) => state.world[id]));
|
|
128
|
-
const refIsNull =
|
|
126
|
+
const refIsNull = useVizijStore(
|
|
127
|
+
(state) => !state.refs[id]?.[namespace]?.current
|
|
128
|
+
);
|
|
129
129
|
const animatables = useVizijStore(useShallow((state) => state.animatables));
|
|
130
130
|
const setHoveredElement = useVizijStore(
|
|
131
131
|
useShallow((state) => state.setHoveredElement)
|
|
@@ -267,7 +267,9 @@ function InnerRenderedEllipse({
|
|
|
267
267
|
const ellipse = useVizijStore(
|
|
268
268
|
useShallow2((state) => state.world[id])
|
|
269
269
|
);
|
|
270
|
-
const refIsNull =
|
|
270
|
+
const refIsNull = useVizijStore(
|
|
271
|
+
(state) => !state.refs[id]?.[namespace]?.current
|
|
272
|
+
);
|
|
271
273
|
const animatables = useVizijStore(useShallow2((state) => state.animatables));
|
|
272
274
|
const animatableValues = useMemo2(() => {
|
|
273
275
|
const av = {};
|
|
@@ -561,7 +563,9 @@ function InnerRenderedRectangle({
|
|
|
561
563
|
const rectangle = useVizijStore(
|
|
562
564
|
useShallow3((state) => state.world[id])
|
|
563
565
|
);
|
|
564
|
-
const refIsNull =
|
|
566
|
+
const refIsNull = useVizijStore(
|
|
567
|
+
(state) => !state.refs[id]?.[namespace]?.current
|
|
568
|
+
);
|
|
565
569
|
const animatables = useVizijStore(useShallow3((state) => state.animatables));
|
|
566
570
|
const animatableValues = useMemo3(() => {
|
|
567
571
|
const av = {};
|
|
@@ -833,6 +837,61 @@ import {
|
|
|
833
837
|
instanceOfRawRGB as instanceOfRawRGB3,
|
|
834
838
|
instanceOfRawVector3 as instanceOfRawVector34
|
|
835
839
|
} from "@vizij/utils";
|
|
840
|
+
|
|
841
|
+
// src/functions/material-name.ts
|
|
842
|
+
var MATERIAL_FEATURE_KEYS = [
|
|
843
|
+
"color",
|
|
844
|
+
"opacity",
|
|
845
|
+
"roughness",
|
|
846
|
+
"metalness",
|
|
847
|
+
"shininess",
|
|
848
|
+
"emissive",
|
|
849
|
+
"emissiveIntensity",
|
|
850
|
+
"specular"
|
|
851
|
+
];
|
|
852
|
+
var MATERIAL_NAME_SUFFIXES = [
|
|
853
|
+
" color",
|
|
854
|
+
" colours",
|
|
855
|
+
" colour",
|
|
856
|
+
" opacity",
|
|
857
|
+
" roughness",
|
|
858
|
+
" metalness",
|
|
859
|
+
" shininess",
|
|
860
|
+
" emissive intensity",
|
|
861
|
+
" emissive",
|
|
862
|
+
" specular"
|
|
863
|
+
];
|
|
864
|
+
function deriveMaterialName(shape, values) {
|
|
865
|
+
for (const key of MATERIAL_FEATURE_KEYS) {
|
|
866
|
+
const feature = shape.features[key];
|
|
867
|
+
if (feature && feature.animated) {
|
|
868
|
+
const animatable = values[feature.value];
|
|
869
|
+
const candidate = extractMaterialName(animatable?.name);
|
|
870
|
+
if (candidate) {
|
|
871
|
+
return candidate;
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
return void 0;
|
|
876
|
+
}
|
|
877
|
+
function extractMaterialName(name) {
|
|
878
|
+
if (!name) {
|
|
879
|
+
return void 0;
|
|
880
|
+
}
|
|
881
|
+
const trimmed = name.trim();
|
|
882
|
+
if (!trimmed) {
|
|
883
|
+
return void 0;
|
|
884
|
+
}
|
|
885
|
+
const lowered = trimmed.toLowerCase();
|
|
886
|
+
for (const suffix of MATERIAL_NAME_SUFFIXES) {
|
|
887
|
+
if (lowered.endsWith(suffix)) {
|
|
888
|
+
return trimmed.slice(0, trimmed.length - suffix.length).trim();
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
return trimmed;
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
// src/renderables/shape.tsx
|
|
836
895
|
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
837
896
|
THREE2.Object3D.DEFAULT_UP.set(0, 0, 1);
|
|
838
897
|
function InnerRenderedShape({
|
|
@@ -843,10 +902,9 @@ function InnerRenderedShape({
|
|
|
843
902
|
const refGroup = useRef4(null);
|
|
844
903
|
const ref = useRef4(null);
|
|
845
904
|
const shape = useVizijStore(useShallow4((state) => state.world[id]));
|
|
846
|
-
const
|
|
847
|
-
|
|
905
|
+
const refIsNull = useVizijStore(
|
|
906
|
+
(state) => !state.refs[id]?.[namespace]?.current
|
|
848
907
|
);
|
|
849
|
-
const refIsNull = !refs[namespace]?.current;
|
|
850
908
|
const animatables = useVizijStore(useShallow4((state) => state.animatables));
|
|
851
909
|
const animatableValues = useMemo4(() => {
|
|
852
910
|
const av = {};
|
|
@@ -1131,125 +1189,44 @@ function InnerRenderedShape({
|
|
|
1131
1189
|
);
|
|
1132
1190
|
}
|
|
1133
1191
|
var RenderedShape = memo4(InnerRenderedShape);
|
|
1134
|
-
var MATERIAL_FEATURE_KEYS = [
|
|
1135
|
-
"color",
|
|
1136
|
-
"opacity",
|
|
1137
|
-
"roughness",
|
|
1138
|
-
"metalness",
|
|
1139
|
-
"shininess",
|
|
1140
|
-
"emissive",
|
|
1141
|
-
"emissiveIntensity",
|
|
1142
|
-
"specular"
|
|
1143
|
-
];
|
|
1144
|
-
var MATERIAL_NAME_SUFFIXES = [
|
|
1145
|
-
" color",
|
|
1146
|
-
" colours",
|
|
1147
|
-
" colour",
|
|
1148
|
-
" opacity",
|
|
1149
|
-
" roughness",
|
|
1150
|
-
" metalness",
|
|
1151
|
-
" shininess",
|
|
1152
|
-
" emissive intensity",
|
|
1153
|
-
" emissive",
|
|
1154
|
-
" specular"
|
|
1155
|
-
];
|
|
1156
|
-
function deriveMaterialName(shape, values) {
|
|
1157
|
-
for (const key of MATERIAL_FEATURE_KEYS) {
|
|
1158
|
-
const feature = shape.features[key];
|
|
1159
|
-
if (feature && feature.animated) {
|
|
1160
|
-
const animatable = values[feature.value];
|
|
1161
|
-
const candidate = extractMaterialName(animatable?.name);
|
|
1162
|
-
if (candidate) {
|
|
1163
|
-
return candidate;
|
|
1164
|
-
}
|
|
1165
|
-
}
|
|
1166
|
-
}
|
|
1167
|
-
return void 0;
|
|
1168
|
-
}
|
|
1169
|
-
function extractMaterialName(name) {
|
|
1170
|
-
if (!name) {
|
|
1171
|
-
return void 0;
|
|
1172
|
-
}
|
|
1173
|
-
const trimmed = name.trim();
|
|
1174
|
-
if (!trimmed) {
|
|
1175
|
-
return void 0;
|
|
1176
|
-
}
|
|
1177
|
-
const lowered = trimmed.toLowerCase();
|
|
1178
|
-
for (const suffix of MATERIAL_NAME_SUFFIXES) {
|
|
1179
|
-
if (lowered.endsWith(suffix)) {
|
|
1180
|
-
return trimmed.slice(0, trimmed.length - suffix.length).trim();
|
|
1181
|
-
}
|
|
1182
|
-
}
|
|
1183
|
-
return trimmed;
|
|
1184
|
-
}
|
|
1185
1192
|
|
|
1186
1193
|
// src/renderables/renderable.tsx
|
|
1187
|
-
import {
|
|
1194
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
1188
1195
|
function InnerRenderable({
|
|
1189
1196
|
id,
|
|
1190
1197
|
namespace,
|
|
1191
1198
|
chain
|
|
1192
1199
|
}) {
|
|
1193
1200
|
const type = useVizijStore(useShallow5((state) => state.world[id].type));
|
|
1194
|
-
const
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1201
|
+
const key = `${namespace}.${id}`;
|
|
1202
|
+
switch (type) {
|
|
1203
|
+
case "group":
|
|
1204
|
+
return /* @__PURE__ */ jsx5(RenderedGroup, { id, namespace, chain }, key);
|
|
1205
|
+
case "ellipse":
|
|
1206
|
+
return /* @__PURE__ */ jsx5(
|
|
1207
|
+
RenderedEllipse,
|
|
1208
|
+
{
|
|
1209
|
+
id,
|
|
1210
|
+
namespace,
|
|
1211
|
+
chain
|
|
1212
|
+
},
|
|
1213
|
+
key
|
|
1214
|
+
);
|
|
1215
|
+
case "rectangle":
|
|
1216
|
+
return /* @__PURE__ */ jsx5(
|
|
1217
|
+
RenderedRectangle,
|
|
1218
|
+
{
|
|
1219
|
+
id,
|
|
1220
|
+
namespace,
|
|
1221
|
+
chain
|
|
1222
|
+
},
|
|
1223
|
+
key
|
|
1224
|
+
);
|
|
1225
|
+
case "shape":
|
|
1226
|
+
return /* @__PURE__ */ jsx5(RenderedShape, { id, namespace, chain }, key);
|
|
1227
|
+
default:
|
|
1228
|
+
return null;
|
|
1206
1229
|
}
|
|
1207
|
-
return /* @__PURE__ */ jsx5(Fragment3, { children: resolvedNamespaces.map((ns) => {
|
|
1208
|
-
switch (type) {
|
|
1209
|
-
case "group":
|
|
1210
|
-
return /* @__PURE__ */ jsx5(
|
|
1211
|
-
RenderedGroup,
|
|
1212
|
-
{
|
|
1213
|
-
id,
|
|
1214
|
-
namespace: ns,
|
|
1215
|
-
chain
|
|
1216
|
-
},
|
|
1217
|
-
`${ns}.${id}`
|
|
1218
|
-
);
|
|
1219
|
-
case "ellipse":
|
|
1220
|
-
return /* @__PURE__ */ jsx5(
|
|
1221
|
-
RenderedEllipse,
|
|
1222
|
-
{
|
|
1223
|
-
id,
|
|
1224
|
-
namespace: ns,
|
|
1225
|
-
chain
|
|
1226
|
-
},
|
|
1227
|
-
`${ns}.${id}`
|
|
1228
|
-
);
|
|
1229
|
-
case "rectangle":
|
|
1230
|
-
return /* @__PURE__ */ jsx5(
|
|
1231
|
-
RenderedRectangle,
|
|
1232
|
-
{
|
|
1233
|
-
id,
|
|
1234
|
-
namespace: ns,
|
|
1235
|
-
chain
|
|
1236
|
-
},
|
|
1237
|
-
`${ns}.${id}`
|
|
1238
|
-
);
|
|
1239
|
-
case "shape":
|
|
1240
|
-
return /* @__PURE__ */ jsx5(
|
|
1241
|
-
RenderedShape,
|
|
1242
|
-
{
|
|
1243
|
-
id,
|
|
1244
|
-
namespace: ns,
|
|
1245
|
-
chain
|
|
1246
|
-
},
|
|
1247
|
-
`${ns}.${id}`
|
|
1248
|
-
);
|
|
1249
|
-
default:
|
|
1250
|
-
return null;
|
|
1251
|
-
}
|
|
1252
|
-
}) });
|
|
1253
1230
|
}
|
|
1254
1231
|
var Renderable = memo5(InnerRenderable);
|
|
1255
1232
|
|
|
@@ -1260,10 +1237,6 @@ import { produce, enableMapSet } from "immer";
|
|
|
1260
1237
|
import * as THREE3 from "three";
|
|
1261
1238
|
import { getLookup as getLookup2 } from "@vizij/utils";
|
|
1262
1239
|
|
|
1263
|
-
// src/actions/create-new-element.ts
|
|
1264
|
-
import { createRef } from "react";
|
|
1265
|
-
import { mapValues as mapValues2 } from "lodash";
|
|
1266
|
-
|
|
1267
1240
|
// src/functions/create-world-element.ts
|
|
1268
1241
|
import { createBrowserSafeId } from "@vizij/utils";
|
|
1269
1242
|
function createDefaultGroup(partialBody) {
|
|
@@ -1275,7 +1248,6 @@ function createDefaultGroup(partialBody) {
|
|
|
1275
1248
|
name: partialBody.name || "new-body",
|
|
1276
1249
|
type: partialBody.type || "group",
|
|
1277
1250
|
tags: partialBody.tags || [],
|
|
1278
|
-
refs: partialBody.refs || {},
|
|
1279
1251
|
features: { translation, rotation, scale },
|
|
1280
1252
|
root: partialBody.root ?? false,
|
|
1281
1253
|
children: partialBody.children || []
|
|
@@ -1292,11 +1264,9 @@ function createNewElement(state, type, root = false) {
|
|
|
1292
1264
|
});
|
|
1293
1265
|
if (Object.entries(state.world).length === 0) {
|
|
1294
1266
|
const name = `New-Root`;
|
|
1295
|
-
const refs = { default: createRef() };
|
|
1296
1267
|
const newElement = createDefaultGroup({
|
|
1297
1268
|
name,
|
|
1298
|
-
root: true
|
|
1299
|
-
refs
|
|
1269
|
+
root: true
|
|
1300
1270
|
});
|
|
1301
1271
|
state.world[newElement.id] = newElement;
|
|
1302
1272
|
state.elementSelection = [buildSelection(newElement.id)];
|
|
@@ -1308,11 +1278,7 @@ function createNewElement(state, type, root = false) {
|
|
|
1308
1278
|
return;
|
|
1309
1279
|
}
|
|
1310
1280
|
const name = `New-Body`;
|
|
1311
|
-
const
|
|
1312
|
-
worldRootEntry.refs,
|
|
1313
|
-
() => createRef()
|
|
1314
|
-
);
|
|
1315
|
-
const newChild = createDefaultGroup({ name, root, refs });
|
|
1281
|
+
const newChild = createDefaultGroup({ name, root });
|
|
1316
1282
|
worldRootEntry.children.push(newChild.id);
|
|
1317
1283
|
state.world[newChild.id] = newChild;
|
|
1318
1284
|
state.elementSelection = [buildSelection(newChild.id)];
|
|
@@ -1512,6 +1478,7 @@ enableMapSet();
|
|
|
1512
1478
|
var VizijSlice = (set, get) => ({
|
|
1513
1479
|
// worldRef: createRef<THREE.Group>(),
|
|
1514
1480
|
world: {},
|
|
1481
|
+
refs: {},
|
|
1515
1482
|
animatables: {},
|
|
1516
1483
|
values: /* @__PURE__ */ new Map(),
|
|
1517
1484
|
renderHit: false,
|
|
@@ -1585,12 +1552,10 @@ var VizijSlice = (set, get) => ({
|
|
|
1585
1552
|
worldData,
|
|
1586
1553
|
filterIds
|
|
1587
1554
|
);
|
|
1555
|
+
const refs = get().refs;
|
|
1588
1556
|
return candidateGroups.flatMap((entry) => {
|
|
1589
|
-
const
|
|
1590
|
-
|
|
1591
|
-
);
|
|
1592
|
-
const resolved = refs.find((ref) => ref?.current)?.current ?? null;
|
|
1593
|
-
return resolved ? [resolved] : [];
|
|
1557
|
+
const mounted = Object.values(refs[entry.id] ?? {}).map((ref) => ref.current).find((object) => Boolean(object));
|
|
1558
|
+
return mounted ? [mounted] : [];
|
|
1594
1559
|
});
|
|
1595
1560
|
},
|
|
1596
1561
|
setGeometry: (id, geometry) => {
|
|
@@ -1812,14 +1777,12 @@ var VizijSlice = (set, get) => ({
|
|
|
1812
1777
|
}));
|
|
1813
1778
|
},
|
|
1814
1779
|
setReference: (id, namespace, ref) => {
|
|
1815
|
-
set(
|
|
1816
|
-
|
|
1817
|
-
state.
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
})
|
|
1822
|
-
);
|
|
1780
|
+
set((state) => ({
|
|
1781
|
+
refs: {
|
|
1782
|
+
...state.refs,
|
|
1783
|
+
[id]: { ...state.refs[id], [namespace]: ref }
|
|
1784
|
+
}
|
|
1785
|
+
}));
|
|
1823
1786
|
}
|
|
1824
1787
|
});
|
|
1825
1788
|
var useDefaultVizijStore = create()(
|
|
@@ -1834,8 +1797,57 @@ var createVizijStore = (initial) => create()(
|
|
|
1834
1797
|
}))
|
|
1835
1798
|
);
|
|
1836
1799
|
|
|
1800
|
+
// src/types/shape.ts
|
|
1801
|
+
var ShapeMaterial = /* @__PURE__ */ ((ShapeMaterial2) => {
|
|
1802
|
+
ShapeMaterial2["Standard"] = "standard";
|
|
1803
|
+
ShapeMaterial2["Phong"] = "phong";
|
|
1804
|
+
ShapeMaterial2["Basic"] = "basic";
|
|
1805
|
+
ShapeMaterial2["Lambert"] = "lambert";
|
|
1806
|
+
ShapeMaterial2["Normal"] = "normal";
|
|
1807
|
+
return ShapeMaterial2;
|
|
1808
|
+
})(ShapeMaterial || {});
|
|
1809
|
+
|
|
1810
|
+
// src/types/tone-mapping.ts
|
|
1811
|
+
import {
|
|
1812
|
+
ACESFilmicToneMapping,
|
|
1813
|
+
AgXToneMapping,
|
|
1814
|
+
NeutralToneMapping,
|
|
1815
|
+
NoToneMapping
|
|
1816
|
+
} from "three";
|
|
1817
|
+
var TONE_MAPPING_MODES = [
|
|
1818
|
+
"none",
|
|
1819
|
+
"agx",
|
|
1820
|
+
"aces",
|
|
1821
|
+
"neutral"
|
|
1822
|
+
];
|
|
1823
|
+
var TONE_MAPPING_LABELS = {
|
|
1824
|
+
none: "None (web match)",
|
|
1825
|
+
agx: "AgX (Blender)",
|
|
1826
|
+
aces: "ACES Filmic",
|
|
1827
|
+
neutral: "Neutral"
|
|
1828
|
+
};
|
|
1829
|
+
var DEFAULT_TONE_MAPPING_MODE = "none";
|
|
1830
|
+
var TONE_MAPPING_CONSTANTS = {
|
|
1831
|
+
none: NoToneMapping,
|
|
1832
|
+
agx: AgXToneMapping,
|
|
1833
|
+
aces: ACESFilmicToneMapping,
|
|
1834
|
+
neutral: NeutralToneMapping
|
|
1835
|
+
};
|
|
1836
|
+
function isToneMappingMode(value) {
|
|
1837
|
+
return typeof value === "string" && Object.prototype.hasOwnProperty.call(TONE_MAPPING_CONSTANTS, value);
|
|
1838
|
+
}
|
|
1839
|
+
function resolveToneMapping(mode) {
|
|
1840
|
+
if (isToneMappingMode(mode)) {
|
|
1841
|
+
return TONE_MAPPING_CONSTANTS[mode];
|
|
1842
|
+
}
|
|
1843
|
+
return TONE_MAPPING_CONSTANTS[DEFAULT_TONE_MAPPING_MODE];
|
|
1844
|
+
}
|
|
1845
|
+
function normalizeToneMappingMode(value) {
|
|
1846
|
+
return isToneMappingMode(value) ? value : DEFAULT_TONE_MAPPING_MODE;
|
|
1847
|
+
}
|
|
1848
|
+
|
|
1837
1849
|
// src/effects/selection-glow-effect.tsx
|
|
1838
|
-
import { Fragment as
|
|
1850
|
+
import { Fragment as Fragment3, useEffect as useEffect6, useMemo as useMemo5, useRef as useRef5 } from "react";
|
|
1839
1851
|
import { useFrame } from "@react-three/fiber";
|
|
1840
1852
|
import { useShallow as useShallow6 } from "zustand/react/shallow";
|
|
1841
1853
|
import {
|
|
@@ -1862,7 +1874,7 @@ function SelectionGlowEffect({
|
|
|
1862
1874
|
if (!enabled || selections.length === 0) {
|
|
1863
1875
|
return null;
|
|
1864
1876
|
}
|
|
1865
|
-
return /* @__PURE__ */ jsx6(
|
|
1877
|
+
return /* @__PURE__ */ jsx6(Fragment3, { children: selections.map((selection) => /* @__PURE__ */ jsx6(
|
|
1866
1878
|
SelectionOutline,
|
|
1867
1879
|
{
|
|
1868
1880
|
selection,
|
|
@@ -1882,19 +1894,19 @@ function SelectionOutline({
|
|
|
1882
1894
|
const target = useVizijStore(
|
|
1883
1895
|
useShallow6((state) => {
|
|
1884
1896
|
const entry = state.world[selection.id];
|
|
1885
|
-
const ref =
|
|
1897
|
+
const ref = state.refs[selection.id]?.[selection.namespace];
|
|
1886
1898
|
const geometry = entry?.geometry ?? null;
|
|
1887
1899
|
return { ref, geometry };
|
|
1888
1900
|
})
|
|
1889
1901
|
);
|
|
1890
1902
|
const sourceRef = target.ref;
|
|
1891
|
-
const edgesGeometry =
|
|
1903
|
+
const edgesGeometry = useMemo5(() => {
|
|
1892
1904
|
if (!target.geometry) return null;
|
|
1893
1905
|
const edges = new EdgesGeometry(target.geometry, thresholdAngle);
|
|
1894
1906
|
return edges;
|
|
1895
1907
|
}, [target.geometry, thresholdAngle]);
|
|
1896
1908
|
useEffect6(() => () => edgesGeometry?.dispose(), [edgesGeometry]);
|
|
1897
|
-
const material =
|
|
1909
|
+
const material = useMemo5(() => {
|
|
1898
1910
|
const mat = new LineBasicMaterial({
|
|
1899
1911
|
color: new Color(color),
|
|
1900
1912
|
transparent: true,
|
|
@@ -1944,7 +1956,7 @@ function copyWorldTransform(source, target) {
|
|
|
1944
1956
|
}
|
|
1945
1957
|
|
|
1946
1958
|
// src/vizij.tsx
|
|
1947
|
-
import { Fragment as
|
|
1959
|
+
import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1948
1960
|
Object3D4.DEFAULT_UP.set(0, 0, 1);
|
|
1949
1961
|
function Vizij({
|
|
1950
1962
|
style,
|
|
@@ -1953,6 +1965,7 @@ function Vizij({
|
|
|
1953
1965
|
namespace = "default",
|
|
1954
1966
|
showSafeArea = false,
|
|
1955
1967
|
showSelectionGlow = false,
|
|
1968
|
+
toneMapping = "none",
|
|
1956
1969
|
onPointerMissed
|
|
1957
1970
|
}) {
|
|
1958
1971
|
const ctx = useContext3(VizijContext);
|
|
@@ -1973,7 +1986,6 @@ function Vizij({
|
|
|
1973
1986
|
onPointerMissed,
|
|
1974
1987
|
gl: {
|
|
1975
1988
|
outputColorSpace: SRGBColorSpace,
|
|
1976
|
-
toneMapping: NoToneMapping,
|
|
1977
1989
|
antialias: true
|
|
1978
1990
|
},
|
|
1979
1991
|
children: /* @__PURE__ */ jsx7(
|
|
@@ -1982,7 +1994,8 @@ function Vizij({
|
|
|
1982
1994
|
rootId,
|
|
1983
1995
|
namespace,
|
|
1984
1996
|
showSafeArea,
|
|
1985
|
-
showSelectionGlow
|
|
1997
|
+
showSelectionGlow,
|
|
1998
|
+
toneMapping
|
|
1986
1999
|
}
|
|
1987
2000
|
)
|
|
1988
2001
|
}
|
|
@@ -1996,7 +2009,6 @@ function Vizij({
|
|
|
1996
2009
|
onPointerMissed,
|
|
1997
2010
|
gl: {
|
|
1998
2011
|
outputColorSpace: SRGBColorSpace,
|
|
1999
|
-
toneMapping: NoToneMapping,
|
|
2000
2012
|
antialias: true
|
|
2001
2013
|
},
|
|
2002
2014
|
children: /* @__PURE__ */ jsx7(
|
|
@@ -2005,7 +2017,8 @@ function Vizij({
|
|
|
2005
2017
|
rootId,
|
|
2006
2018
|
namespace,
|
|
2007
2019
|
showSafeArea,
|
|
2008
|
-
showSelectionGlow
|
|
2020
|
+
showSelectionGlow,
|
|
2021
|
+
toneMapping
|
|
2009
2022
|
}
|
|
2010
2023
|
)
|
|
2011
2024
|
}
|
|
@@ -2017,14 +2030,16 @@ function InnerVizij({
|
|
|
2017
2030
|
namespace = "default",
|
|
2018
2031
|
container,
|
|
2019
2032
|
showSafeArea,
|
|
2020
|
-
showSelectionGlow
|
|
2033
|
+
showSelectionGlow,
|
|
2034
|
+
toneMapping = "none"
|
|
2021
2035
|
}) {
|
|
2022
2036
|
const sceneParentSizing = container ? {
|
|
2023
2037
|
width: container.width * container.resolution,
|
|
2024
2038
|
height: container.height * container.resolution
|
|
2025
2039
|
} : void 0;
|
|
2026
|
-
return /* @__PURE__ */ jsxs4(
|
|
2040
|
+
return /* @__PURE__ */ jsxs4(Fragment4, { children: [
|
|
2027
2041
|
/* @__PURE__ */ jsx7("ambientLight", { intensity: Math.PI / 2 }),
|
|
2042
|
+
/* @__PURE__ */ jsx7(ToneMappingController, { mode: toneMapping }),
|
|
2028
2043
|
/* @__PURE__ */ jsx7(
|
|
2029
2044
|
OrthographicCamera,
|
|
2030
2045
|
{
|
|
@@ -2047,6 +2062,31 @@ function InnerVizij({
|
|
|
2047
2062
|
] });
|
|
2048
2063
|
}
|
|
2049
2064
|
var MemoizedInnerVizij = memo6(InnerVizij);
|
|
2065
|
+
function ToneMappingController({ mode }) {
|
|
2066
|
+
const gl = useThree((state) => state.gl);
|
|
2067
|
+
const scene = useThree((state) => state.scene);
|
|
2068
|
+
useEffect7(() => {
|
|
2069
|
+
const resolved = resolveToneMapping(mode);
|
|
2070
|
+
if (gl.toneMapping === resolved) {
|
|
2071
|
+
return;
|
|
2072
|
+
}
|
|
2073
|
+
gl.toneMapping = resolved;
|
|
2074
|
+
scene.traverse((object) => {
|
|
2075
|
+
const material = object.material;
|
|
2076
|
+
if (!material) {
|
|
2077
|
+
return;
|
|
2078
|
+
}
|
|
2079
|
+
if (Array.isArray(material)) {
|
|
2080
|
+
material.forEach((mat) => {
|
|
2081
|
+
mat.needsUpdate = true;
|
|
2082
|
+
});
|
|
2083
|
+
} else {
|
|
2084
|
+
material.needsUpdate = true;
|
|
2085
|
+
}
|
|
2086
|
+
});
|
|
2087
|
+
}, [gl, scene, mode]);
|
|
2088
|
+
return null;
|
|
2089
|
+
}
|
|
2050
2090
|
function InnerWorld({
|
|
2051
2091
|
rootId,
|
|
2052
2092
|
namespace = "default",
|
|
@@ -2136,16 +2176,6 @@ var defaultRootBounds = {
|
|
|
2136
2176
|
size: { x: 5, y: 4 }
|
|
2137
2177
|
};
|
|
2138
2178
|
|
|
2139
|
-
// src/types/shape.ts
|
|
2140
|
-
var ShapeMaterial = /* @__PURE__ */ ((ShapeMaterial2) => {
|
|
2141
|
-
ShapeMaterial2["Standard"] = "standard";
|
|
2142
|
-
ShapeMaterial2["Phong"] = "phong";
|
|
2143
|
-
ShapeMaterial2["Basic"] = "basic";
|
|
2144
|
-
ShapeMaterial2["Lambert"] = "lambert";
|
|
2145
|
-
ShapeMaterial2["Normal"] = "normal";
|
|
2146
|
-
return ShapeMaterial2;
|
|
2147
|
-
})(ShapeMaterial || {});
|
|
2148
|
-
|
|
2149
2179
|
// src/hooks/use-vizij-store-subscription.ts
|
|
2150
2180
|
import { useContext as useContext4, useEffect as useEffect8 } from "react";
|
|
2151
2181
|
function useVizijStoreSubscription(selector, listener) {
|
|
@@ -2179,7 +2209,6 @@ import * as THREE5 from "three";
|
|
|
2179
2209
|
import { GLTFLoader, DRACOLoader } from "three-stdlib";
|
|
2180
2210
|
|
|
2181
2211
|
// src/functions/gltf-loading/traverse-three.ts
|
|
2182
|
-
import { createRef as createRef3 } from "react";
|
|
2183
2212
|
import * as THREE4 from "three";
|
|
2184
2213
|
|
|
2185
2214
|
// src/functions/gltf-loading/map-features.ts
|
|
@@ -2211,12 +2240,6 @@ import { Object3D as Object3D7 } from "three";
|
|
|
2211
2240
|
import { Object3D as Object3D6 } from "three";
|
|
2212
2241
|
import { createBrowserSafeId as createBrowserSafeId5 } from "@vizij/utils";
|
|
2213
2242
|
|
|
2214
|
-
// src/functions/util.ts
|
|
2215
|
-
import { createRef as createRef2 } from "react";
|
|
2216
|
-
function namespaceArrayToRefs(namespaces) {
|
|
2217
|
-
return namespaces.reduce((acc, ns) => ({ ...acc, [ns]: createRef2() }), {});
|
|
2218
|
-
}
|
|
2219
|
-
|
|
2220
2243
|
// src/functions/gltf-loading/import-mesh.ts
|
|
2221
2244
|
import { Object3D as Object3D5 } from "three";
|
|
2222
2245
|
import { createBrowserSafeId as createBrowserSafeId4 } from "@vizij/utils";
|
|
@@ -2225,10 +2248,15 @@ import { createBrowserSafeId as createBrowserSafeId4 } from "@vizij/utils";
|
|
|
2225
2248
|
import {
|
|
2226
2249
|
createBrowserSafeId as createBrowserSafeId3
|
|
2227
2250
|
} from "@vizij/utils";
|
|
2228
|
-
|
|
2251
|
+
|
|
2252
|
+
// src/functions/gltf-loading/morph-keys.ts
|
|
2253
|
+
function slugifyMorphName(name, fallbackIndex) {
|
|
2229
2254
|
const baseName = name && name.trim().length > 0 ? name.trim() : `morph_${fallbackIndex + 1}`;
|
|
2230
2255
|
const slug = baseName.toLowerCase().replace(/[^a-z0-9]+/gi, "_").replace(/^_+|_+$/g, "");
|
|
2231
|
-
|
|
2256
|
+
return slug.length > 0 ? slug : `morph_${fallbackIndex + 1}`;
|
|
2257
|
+
}
|
|
2258
|
+
function sanitizeMorphKey(name, fallbackIndex, used) {
|
|
2259
|
+
const safeBase = slugifyMorphName(name, fallbackIndex);
|
|
2232
2260
|
let candidate = safeBase;
|
|
2233
2261
|
let counter = 1;
|
|
2234
2262
|
while (used.has(candidate)) {
|
|
@@ -2237,6 +2265,12 @@ function sanitizeMorphKey(name, fallbackIndex, used) {
|
|
|
2237
2265
|
used.add(candidate);
|
|
2238
2266
|
return candidate;
|
|
2239
2267
|
}
|
|
2268
|
+
function deriveMorphFeatureKeys(names) {
|
|
2269
|
+
const used = /* @__PURE__ */ new Set();
|
|
2270
|
+
return names.map((name, index) => sanitizeMorphKey(name, index, used));
|
|
2271
|
+
}
|
|
2272
|
+
|
|
2273
|
+
// src/functions/gltf-loading/import-geometry.ts
|
|
2240
2274
|
function importGeometry(geometry, mesh) {
|
|
2241
2275
|
const features = {};
|
|
2242
2276
|
const animatableValues = {};
|
|
@@ -2279,7 +2313,7 @@ function importGeometry(geometry, mesh) {
|
|
|
2279
2313
|
|
|
2280
2314
|
// src/functions/gltf-loading/import-mesh.ts
|
|
2281
2315
|
Object3D5.DEFAULT_UP.set(0, 0, 1);
|
|
2282
|
-
function importMesh(mesh,
|
|
2316
|
+
function importMesh(mesh, colorLookup) {
|
|
2283
2317
|
let world = {};
|
|
2284
2318
|
let animatables = {};
|
|
2285
2319
|
let newColorLookup = {};
|
|
@@ -2448,7 +2482,7 @@ function importMesh(mesh, namespaces, colorLookup) {
|
|
|
2448
2482
|
const children = [];
|
|
2449
2483
|
mesh.children.forEach((child) => {
|
|
2450
2484
|
if (child.isMesh) {
|
|
2451
|
-
const [newWorldItems, newAnimatables, childId, newMeshColors] = importMesh(child,
|
|
2485
|
+
const [newWorldItems, newAnimatables, childId, newMeshColors] = importMesh(child, {
|
|
2452
2486
|
...colorLookup,
|
|
2453
2487
|
...newColorLookup
|
|
2454
2488
|
});
|
|
@@ -2457,7 +2491,7 @@ function importMesh(mesh, namespaces, colorLookup) {
|
|
|
2457
2491
|
animatables = { ...animatables, ...newAnimatables };
|
|
2458
2492
|
children.push(childId);
|
|
2459
2493
|
} else if (shouldImportAsGroupChild(child)) {
|
|
2460
|
-
const [newWorldItems, newAnimatables, childId, newMeshColors] = importGroup(child,
|
|
2494
|
+
const [newWorldItems, newAnimatables, childId, newMeshColors] = importGroup(child, {
|
|
2461
2495
|
...colorLookup,
|
|
2462
2496
|
...newColorLookup
|
|
2463
2497
|
});
|
|
@@ -2494,8 +2528,7 @@ function importMesh(mesh, namespaces, colorLookup) {
|
|
|
2494
2528
|
...materialIds.specular ? { specular: { animated: true, value: materialIds.specular } } : {},
|
|
2495
2529
|
...geometryFeatures
|
|
2496
2530
|
},
|
|
2497
|
-
children: children.length > 0 ? children : void 0
|
|
2498
|
-
refs: namespaceArrayToRefs(namespaces)
|
|
2531
|
+
children: children.length > 0 ? children : void 0
|
|
2499
2532
|
};
|
|
2500
2533
|
world = { ...world, [newShape.id]: newShape };
|
|
2501
2534
|
return [world, animatables, newShape.id, newColorLookup];
|
|
@@ -2537,7 +2570,7 @@ function shouldImportAsGroupChild(child) {
|
|
|
2537
2570
|
|
|
2538
2571
|
// src/functions/gltf-loading/import-group.ts
|
|
2539
2572
|
Object3D6.DEFAULT_UP.set(0, 0, 1);
|
|
2540
|
-
function importGroup(group,
|
|
2573
|
+
function importGroup(group, colorLookup, rootBounds) {
|
|
2541
2574
|
let world = {};
|
|
2542
2575
|
let animatables = {};
|
|
2543
2576
|
let newColorLookup = {};
|
|
@@ -2585,7 +2618,7 @@ function importGroup(group, namespaces, colorLookup, rootBounds) {
|
|
|
2585
2618
|
animatables = { ...animatables, [scaleAnimatable.id]: scaleAnimatable };
|
|
2586
2619
|
group.children.forEach((child) => {
|
|
2587
2620
|
if (child.isMesh) {
|
|
2588
|
-
const [newWorldItems, newAnimatables, childId, newMeshColors] = importMesh(child,
|
|
2621
|
+
const [newWorldItems, newAnimatables, childId, newMeshColors] = importMesh(child, {
|
|
2589
2622
|
...colorLookup,
|
|
2590
2623
|
...newColorLookup
|
|
2591
2624
|
});
|
|
@@ -2594,7 +2627,7 @@ function importGroup(group, namespaces, colorLookup, rootBounds) {
|
|
|
2594
2627
|
animatables = { ...animatables, ...newAnimatables };
|
|
2595
2628
|
children.push(childId);
|
|
2596
2629
|
} else if (shouldImportAsGroupChild2(child)) {
|
|
2597
|
-
const [newWorldItems, newAnimatables, childId, newMeshColors] = importGroup(child,
|
|
2630
|
+
const [newWorldItems, newAnimatables, childId, newMeshColors] = importGroup(child, {
|
|
2598
2631
|
...colorLookup,
|
|
2599
2632
|
...newColorLookup
|
|
2600
2633
|
});
|
|
@@ -2616,8 +2649,7 @@ function importGroup(group, namespaces, colorLookup, rootBounds) {
|
|
|
2616
2649
|
},
|
|
2617
2650
|
root: Boolean(rootBounds),
|
|
2618
2651
|
rootBounds,
|
|
2619
|
-
children
|
|
2620
|
-
refs: namespaceArrayToRefs(namespaces)
|
|
2652
|
+
children
|
|
2621
2653
|
};
|
|
2622
2654
|
world = { ...world, [newGroup.id]: newGroup };
|
|
2623
2655
|
return [world, animatables, newGroup.id, newColorLookup];
|
|
@@ -2643,12 +2675,11 @@ function shouldImportAsGroupChild2(child) {
|
|
|
2643
2675
|
|
|
2644
2676
|
// src/functions/gltf-loading/import-scene.ts
|
|
2645
2677
|
Object3D7.DEFAULT_UP.set(0, 0, 1);
|
|
2646
|
-
function importScene(scene,
|
|
2678
|
+
function importScene(scene, rootBounds) {
|
|
2647
2679
|
let world = {};
|
|
2648
2680
|
let animatables = {};
|
|
2649
2681
|
const [newWorldItems, newAnimatables] = importGroup(
|
|
2650
2682
|
scene,
|
|
2651
|
-
namespaces,
|
|
2652
2683
|
{},
|
|
2653
2684
|
rootBounds
|
|
2654
2685
|
);
|
|
@@ -2659,7 +2690,7 @@ function importScene(scene, namespaces, rootBounds) {
|
|
|
2659
2690
|
|
|
2660
2691
|
// src/functions/gltf-loading/traverse-three.ts
|
|
2661
2692
|
THREE4.Object3D.DEFAULT_UP.set(0, 0, 1);
|
|
2662
|
-
function traverseThree(group,
|
|
2693
|
+
function traverseThree(group, aggressiveImport = false, rootBounds) {
|
|
2663
2694
|
const worldData = {};
|
|
2664
2695
|
const animatableData = {};
|
|
2665
2696
|
let hasRobotData = false;
|
|
@@ -2682,11 +2713,7 @@ function traverseThree(group, namespaces, aggressiveImport = false, rootBounds)
|
|
|
2682
2713
|
switch (data.type) {
|
|
2683
2714
|
case "group":
|
|
2684
2715
|
loadedData = {
|
|
2685
|
-
...data
|
|
2686
|
-
refs: namespaces.reduce(
|
|
2687
|
-
(acc, ns) => ({ ...acc, [ns]: createRef3() }),
|
|
2688
|
-
{}
|
|
2689
|
-
)
|
|
2716
|
+
...data
|
|
2690
2717
|
};
|
|
2691
2718
|
[mappedFeatures, animatableValues] = mapFeatures(data.features);
|
|
2692
2719
|
isGroupFeatures(mappedFeatures);
|
|
@@ -2697,11 +2724,7 @@ function traverseThree(group, namespaces, aggressiveImport = false, rootBounds)
|
|
|
2697
2724
|
case "shape":
|
|
2698
2725
|
loadedData = {
|
|
2699
2726
|
...data,
|
|
2700
|
-
geometry: child.geometry
|
|
2701
|
-
refs: namespaces.reduce(
|
|
2702
|
-
(acc, ns) => ({ ...acc, [ns]: createRef3() }),
|
|
2703
|
-
{}
|
|
2704
|
-
)
|
|
2727
|
+
geometry: child.geometry
|
|
2705
2728
|
};
|
|
2706
2729
|
[mappedFeatures, animatableValues] = mapFeatures(data.features);
|
|
2707
2730
|
isShapeFeatures(mappedFeatures);
|
|
@@ -2711,11 +2734,7 @@ function traverseThree(group, namespaces, aggressiveImport = false, rootBounds)
|
|
|
2711
2734
|
break;
|
|
2712
2735
|
case "ellipse":
|
|
2713
2736
|
loadedData = {
|
|
2714
|
-
...data
|
|
2715
|
-
refs: namespaces.reduce(
|
|
2716
|
-
(acc, ns) => ({ ...acc, [ns]: createRef3() }),
|
|
2717
|
-
{}
|
|
2718
|
-
)
|
|
2737
|
+
...data
|
|
2719
2738
|
};
|
|
2720
2739
|
[mappedFeatures, animatableValues] = mapFeatures(data.features);
|
|
2721
2740
|
isEllipseFeatures(mappedFeatures);
|
|
@@ -2725,11 +2744,7 @@ function traverseThree(group, namespaces, aggressiveImport = false, rootBounds)
|
|
|
2725
2744
|
break;
|
|
2726
2745
|
case "rectangle":
|
|
2727
2746
|
loadedData = {
|
|
2728
|
-
...data
|
|
2729
|
-
refs: namespaces.reduce(
|
|
2730
|
-
(acc, ns) => ({ ...acc, [ns]: createRef3() }),
|
|
2731
|
-
{}
|
|
2732
|
-
)
|
|
2747
|
+
...data
|
|
2733
2748
|
};
|
|
2734
2749
|
[mappedFeatures, animatableValues] = mapFeatures(data.features);
|
|
2735
2750
|
isRectangleFeatures(mappedFeatures);
|
|
@@ -2752,7 +2767,6 @@ function traverseThree(group, namespaces, aggressiveImport = false, rootBounds)
|
|
|
2752
2767
|
}
|
|
2753
2768
|
const [newWorldData, newAnimatableData] = importScene(
|
|
2754
2769
|
group,
|
|
2755
|
-
namespaces,
|
|
2756
2770
|
derivedRootBounds
|
|
2757
2771
|
);
|
|
2758
2772
|
Object.assign(worldData, newWorldData);
|
|
@@ -3468,16 +3482,6 @@ async function resolveParserJson(parserJson, fallback) {
|
|
|
3468
3482
|
return fromArrayBuffer;
|
|
3469
3483
|
}
|
|
3470
3484
|
}
|
|
3471
|
-
if (fallback.blob) {
|
|
3472
|
-
try {
|
|
3473
|
-
const blobBuffer = typeof fallback.blob.arrayBuffer === "function" ? await fallback.blob.arrayBuffer() : await new Response(fallback.blob).arrayBuffer();
|
|
3474
|
-
const fromBlob = parseGlbJsonChunk(blobBuffer);
|
|
3475
|
-
if (fromBlob && typeof fromBlob === "object") {
|
|
3476
|
-
return fromBlob;
|
|
3477
|
-
}
|
|
3478
|
-
} catch {
|
|
3479
|
-
}
|
|
3480
|
-
}
|
|
3481
3485
|
if (fallback.url && typeof fetch === "function") {
|
|
3482
3486
|
try {
|
|
3483
3487
|
const response = await fetch(fallback.url);
|
|
@@ -3493,73 +3497,21 @@ async function resolveParserJson(parserJson, fallback) {
|
|
|
3493
3497
|
}
|
|
3494
3498
|
return parserJson;
|
|
3495
3499
|
}
|
|
3496
|
-
async function loadGLTF(url,
|
|
3497
|
-
const asset = await
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
+
async function loadGLTF(url, aggressiveImport = false, rootBounds) {
|
|
3501
|
+
const asset = await loadGLTFWithBundle(url, aggressiveImport, rootBounds);
|
|
3502
|
+
return [asset.world, asset.animatables, asset.animations];
|
|
3503
|
+
}
|
|
3504
|
+
async function loadGLTFFromBlob(blob, aggressiveImport = false, rootBounds) {
|
|
3505
|
+
const asset = await loadGLTFFromBlobWithBundle(
|
|
3506
|
+
blob,
|
|
3500
3507
|
aggressiveImport,
|
|
3501
|
-
rootBounds
|
|
3502
|
-
"url"
|
|
3508
|
+
rootBounds
|
|
3503
3509
|
);
|
|
3504
3510
|
return [asset.world, asset.animatables, asset.animations];
|
|
3505
3511
|
}
|
|
3506
|
-
|
|
3507
|
-
const actualizedNamespaces = namespaces.length > 0 ? namespaces : ["default"];
|
|
3508
|
-
if (typeof URL !== "undefined" && typeof URL.createObjectURL === "function") {
|
|
3509
|
-
const objectUrl = URL.createObjectURL(blob);
|
|
3510
|
-
try {
|
|
3511
|
-
const asset = await loadGLTFWithBundleInternal(
|
|
3512
|
-
objectUrl,
|
|
3513
|
-
actualizedNamespaces,
|
|
3514
|
-
aggressiveImport,
|
|
3515
|
-
rootBounds,
|
|
3516
|
-
"blob",
|
|
3517
|
-
{ blob }
|
|
3518
|
-
);
|
|
3519
|
-
return [asset.world, asset.animatables, asset.animations];
|
|
3520
|
-
} finally {
|
|
3521
|
-
URL.revokeObjectURL(objectUrl);
|
|
3522
|
-
}
|
|
3523
|
-
}
|
|
3524
|
-
const arrayBuffer = typeof blob.arrayBuffer === "function" ? await blob.arrayBuffer() : await new Response(blob).arrayBuffer();
|
|
3525
|
-
return new Promise((resolve, reject) => {
|
|
3526
|
-
const loader = createTrackedGLTFLoader();
|
|
3527
|
-
loader.parse(
|
|
3528
|
-
arrayBuffer,
|
|
3529
|
-
"",
|
|
3530
|
-
async (gltf) => {
|
|
3531
|
-
try {
|
|
3532
|
-
const parserJson = await resolveParserJson(
|
|
3533
|
-
gltf?.parser?.json,
|
|
3534
|
-
{ arrayBuffer }
|
|
3535
|
-
);
|
|
3536
|
-
const asset = parseScene(
|
|
3537
|
-
gltf.scene,
|
|
3538
|
-
actualizedNamespaces,
|
|
3539
|
-
aggressiveImport,
|
|
3540
|
-
rootBounds,
|
|
3541
|
-
parserJson,
|
|
3542
|
-
gltf.animations
|
|
3543
|
-
);
|
|
3544
|
-
resolve([asset.world, asset.animatables, asset.animations]);
|
|
3545
|
-
} catch (error) {
|
|
3546
|
-
if (error instanceof Error) {
|
|
3547
|
-
reject(error);
|
|
3548
|
-
} else {
|
|
3549
|
-
reject(new Error(String(error)));
|
|
3550
|
-
}
|
|
3551
|
-
}
|
|
3552
|
-
},
|
|
3553
|
-
(error) => {
|
|
3554
|
-
reject(new Error(`Error loading GLTF: ${error.message}`));
|
|
3555
|
-
}
|
|
3556
|
-
);
|
|
3557
|
-
});
|
|
3558
|
-
}
|
|
3559
|
-
function parseScene(scene, namespaces, aggressiveImport, rootBounds, parserJson, clips) {
|
|
3512
|
+
function parseScene(scene, aggressiveImport, rootBounds, parserJson, clips) {
|
|
3560
3513
|
const [world, animatables] = traverseThree(
|
|
3561
3514
|
scene,
|
|
3562
|
-
namespaces,
|
|
3563
3515
|
aggressiveImport,
|
|
3564
3516
|
rootBounds
|
|
3565
3517
|
);
|
|
@@ -3574,122 +3526,42 @@ function createTrackedGLTFLoader() {
|
|
|
3574
3526
|
modelLoader.setDRACOLoader(new DRACOLoader());
|
|
3575
3527
|
return modelLoader;
|
|
3576
3528
|
}
|
|
3577
|
-
async function
|
|
3578
|
-
|
|
3579
|
-
recordRenderCounter("gltfUrlLoadCount");
|
|
3580
|
-
} else {
|
|
3581
|
-
recordRenderCounter("gltfBlobLoadCount");
|
|
3582
|
-
}
|
|
3529
|
+
async function loadGLTFWithBundle(url, aggressiveImport = false, rootBounds, parserJsonFallback) {
|
|
3530
|
+
recordRenderCounter("gltfUrlLoadCount");
|
|
3583
3531
|
const modelLoader = createTrackedGLTFLoader();
|
|
3584
3532
|
const modelData = await modelLoader.loadAsync(url);
|
|
3585
3533
|
const parserJson = await resolveParserJson(modelData?.parser?.json, {
|
|
3586
3534
|
url,
|
|
3587
3535
|
...parserJsonFallback
|
|
3588
3536
|
});
|
|
3589
|
-
const actualizedNamespaces = namespaces.length > 0 ? namespaces : ["default"];
|
|
3590
3537
|
return parseScene(
|
|
3591
3538
|
modelData.scene,
|
|
3592
|
-
actualizedNamespaces,
|
|
3593
3539
|
aggressiveImport,
|
|
3594
3540
|
rootBounds,
|
|
3595
3541
|
parserJson,
|
|
3596
3542
|
modelData.animations
|
|
3597
3543
|
);
|
|
3598
3544
|
}
|
|
3599
|
-
async function
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3545
|
+
async function loadGLTFFromBlobWithBundle(blob, aggressiveImport = false, rootBounds) {
|
|
3546
|
+
recordRenderCounter("gltfBlobLoadCount");
|
|
3547
|
+
const arrayBuffer = await blob.arrayBuffer();
|
|
3548
|
+
const loader = createTrackedGLTFLoader();
|
|
3549
|
+
const gltf = await new Promise((resolve, reject) => {
|
|
3550
|
+
loader.parse(arrayBuffer, "", resolve, (error) => {
|
|
3551
|
+
reject(new Error(`Error loading GLTF: ${error.message}`));
|
|
3552
|
+
});
|
|
3553
|
+
});
|
|
3554
|
+
const parserJson = await resolveParserJson(gltf?.parser?.json, {
|
|
3555
|
+
arrayBuffer
|
|
3556
|
+
});
|
|
3557
|
+
return parseScene(
|
|
3558
|
+
gltf.scene,
|
|
3603
3559
|
aggressiveImport,
|
|
3604
3560
|
rootBounds,
|
|
3605
|
-
|
|
3606
|
-
|
|
3561
|
+
parserJson,
|
|
3562
|
+
gltf.animations
|
|
3607
3563
|
);
|
|
3608
3564
|
}
|
|
3609
|
-
async function loadGLTFFromBlobWithBundle(blob, namespaces, aggressiveImport = false, rootBounds) {
|
|
3610
|
-
const actualizedNamespaces = namespaces.length > 0 ? namespaces : ["default"];
|
|
3611
|
-
if (typeof URL !== "undefined" && typeof URL.createObjectURL === "function") {
|
|
3612
|
-
const objectUrl = URL.createObjectURL(blob);
|
|
3613
|
-
try {
|
|
3614
|
-
return await loadGLTFWithBundleInternal(
|
|
3615
|
-
objectUrl,
|
|
3616
|
-
actualizedNamespaces,
|
|
3617
|
-
aggressiveImport,
|
|
3618
|
-
rootBounds,
|
|
3619
|
-
"blob",
|
|
3620
|
-
{ blob }
|
|
3621
|
-
);
|
|
3622
|
-
} finally {
|
|
3623
|
-
URL.revokeObjectURL(objectUrl);
|
|
3624
|
-
}
|
|
3625
|
-
}
|
|
3626
|
-
const arrayBuffer = typeof blob.arrayBuffer === "function" ? await blob.arrayBuffer() : await new Response(blob).arrayBuffer();
|
|
3627
|
-
return new Promise((resolve, reject) => {
|
|
3628
|
-
const loader = createTrackedGLTFLoader();
|
|
3629
|
-
loader.parse(
|
|
3630
|
-
arrayBuffer,
|
|
3631
|
-
"",
|
|
3632
|
-
async (gltf) => {
|
|
3633
|
-
try {
|
|
3634
|
-
const parserJson = await resolveParserJson(
|
|
3635
|
-
gltf?.parser?.json,
|
|
3636
|
-
{ arrayBuffer }
|
|
3637
|
-
);
|
|
3638
|
-
const asset = parseScene(
|
|
3639
|
-
gltf.scene,
|
|
3640
|
-
actualizedNamespaces,
|
|
3641
|
-
aggressiveImport,
|
|
3642
|
-
rootBounds,
|
|
3643
|
-
parserJson,
|
|
3644
|
-
gltf.animations
|
|
3645
|
-
);
|
|
3646
|
-
resolve(asset);
|
|
3647
|
-
} catch (error) {
|
|
3648
|
-
if (error instanceof Error) {
|
|
3649
|
-
reject(error);
|
|
3650
|
-
} else {
|
|
3651
|
-
reject(new Error(String(error)));
|
|
3652
|
-
}
|
|
3653
|
-
}
|
|
3654
|
-
},
|
|
3655
|
-
(error) => {
|
|
3656
|
-
reject(new Error(`Error loading GLTF: ${error.message}`));
|
|
3657
|
-
}
|
|
3658
|
-
);
|
|
3659
|
-
});
|
|
3660
|
-
}
|
|
3661
|
-
|
|
3662
|
-
// src/functions/load-gltf-blob.ts
|
|
3663
|
-
import { DRACOLoader as DRACOLoader2, GLTFLoader as GLTFLoader2 } from "three-stdlib";
|
|
3664
|
-
var loadGltfFromBlob = (blob, namespaces) => {
|
|
3665
|
-
recordRenderCounter("gltfLoadCount");
|
|
3666
|
-
recordRenderCounter("gltfBlobLoadCount");
|
|
3667
|
-
recordRenderCounter("dracoLoaderCreationCount");
|
|
3668
|
-
return new Promise((resolve, reject) => {
|
|
3669
|
-
const loader = new GLTFLoader2();
|
|
3670
|
-
loader.setDRACOLoader(new DRACOLoader2());
|
|
3671
|
-
const reader = new FileReader();
|
|
3672
|
-
reader.onload = () => {
|
|
3673
|
-
const arrayBuffer = reader.result;
|
|
3674
|
-
loader.parse(
|
|
3675
|
-
arrayBuffer,
|
|
3676
|
-
"",
|
|
3677
|
-
// Base path for resolving external resources
|
|
3678
|
-
(gltf) => {
|
|
3679
|
-
const actualizedNamespaces = namespaces.length > 0 ? namespaces : ["default"];
|
|
3680
|
-
resolve(traverseThree(gltf.scene, actualizedNamespaces));
|
|
3681
|
-
},
|
|
3682
|
-
(error) => {
|
|
3683
|
-
reject(new Error(`Error loading GLTF: ${error.message}`));
|
|
3684
|
-
}
|
|
3685
|
-
);
|
|
3686
|
-
};
|
|
3687
|
-
reader.onerror = () => {
|
|
3688
|
-
reject(new Error("Failed to read Blob as ArrayBuffer."));
|
|
3689
|
-
};
|
|
3690
|
-
reader.readAsArrayBuffer(blob);
|
|
3691
|
-
});
|
|
3692
|
-
};
|
|
3693
3565
|
|
|
3694
3566
|
// src/functions/export.ts
|
|
3695
3567
|
import { GLTFExporter } from "three-stdlib";
|
|
@@ -3704,17 +3576,6 @@ function normalizeExportError(error) {
|
|
|
3704
3576
|
}
|
|
3705
3577
|
return new Error("Failed to export scene.");
|
|
3706
3578
|
}
|
|
3707
|
-
function triggerBlobDownload(blob, filename) {
|
|
3708
|
-
const url = URL.createObjectURL(blob);
|
|
3709
|
-
const link = document.createElement("a");
|
|
3710
|
-
link.href = url;
|
|
3711
|
-
link.download = filename;
|
|
3712
|
-
link.style.display = "none";
|
|
3713
|
-
document.body.appendChild(link);
|
|
3714
|
-
link.click();
|
|
3715
|
-
document.body.removeChild(link);
|
|
3716
|
-
setTimeout(() => URL.revokeObjectURL(url), 0);
|
|
3717
|
-
}
|
|
3718
3579
|
var GLB_MAGIC2 = 1179937895;
|
|
3719
3580
|
var GLB_VERSION2 = 2;
|
|
3720
3581
|
var GLB_JSON_CHUNK_TYPE2 = 1313821514;
|
|
@@ -3796,7 +3657,7 @@ function normalizeExportedSceneJson(json, fallbackSceneName) {
|
|
|
3796
3657
|
}
|
|
3797
3658
|
return changed;
|
|
3798
3659
|
}
|
|
3799
|
-
function
|
|
3660
|
+
function patchGlbJson(buffer, mutate) {
|
|
3800
3661
|
if (buffer.byteLength < GLB_HEADER_BYTES2 + GLB_CHUNK_HEADER_BYTES2) {
|
|
3801
3662
|
return buffer;
|
|
3802
3663
|
}
|
|
@@ -3826,8 +3687,7 @@ function sanitizeExportedGlb(buffer, fallbackSceneName) {
|
|
|
3826
3687
|
} catch {
|
|
3827
3688
|
return buffer;
|
|
3828
3689
|
}
|
|
3829
|
-
|
|
3830
|
-
if (!changed) {
|
|
3690
|
+
if (!mutate(jsonPayload)) {
|
|
3831
3691
|
return buffer;
|
|
3832
3692
|
}
|
|
3833
3693
|
const encodedJson = new TextEncoder().encode(JSON.stringify(jsonPayload));
|
|
@@ -3849,11 +3709,41 @@ function sanitizeExportedGlb(buffer, fallbackSceneName) {
|
|
|
3849
3709
|
sanitizedBytes.set(remainingChunks, jsonChunkStart + paddedJsonLength);
|
|
3850
3710
|
return sanitized;
|
|
3851
3711
|
}
|
|
3852
|
-
function
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3712
|
+
function sanitizeExportedGlb(buffer, fallbackSceneName) {
|
|
3713
|
+
return patchGlbJson(
|
|
3714
|
+
buffer,
|
|
3715
|
+
(json) => normalizeExportedSceneJson(json, fallbackSceneName)
|
|
3716
|
+
);
|
|
3717
|
+
}
|
|
3718
|
+
function patchVizijBundleMetadata(glb, metadata) {
|
|
3719
|
+
return patchGlbJson(glb, (json) => {
|
|
3720
|
+
const carriers = [];
|
|
3721
|
+
const rootExtensions = json.extensions;
|
|
3722
|
+
if (rootExtensions && typeof rootExtensions === "object") {
|
|
3723
|
+
carriers.push(rootExtensions);
|
|
3724
|
+
}
|
|
3725
|
+
const nodes = Array.isArray(json.nodes) ? json.nodes : [];
|
|
3726
|
+
for (const node of nodes) {
|
|
3727
|
+
const extensions = node?.extensions;
|
|
3728
|
+
if (extensions && typeof extensions === "object") {
|
|
3729
|
+
carriers.push(extensions);
|
|
3730
|
+
}
|
|
3731
|
+
}
|
|
3732
|
+
let patched = false;
|
|
3733
|
+
for (const extensions of carriers) {
|
|
3734
|
+
const bundle = extensions.VIZIJ_bundle;
|
|
3735
|
+
if (!bundle || typeof bundle !== "object") {
|
|
3736
|
+
continue;
|
|
3737
|
+
}
|
|
3738
|
+
const record = bundle;
|
|
3739
|
+
const existing = record.metadata && typeof record.metadata === "object" ? record.metadata : {};
|
|
3740
|
+
record.metadata = { ...existing, ...metadata };
|
|
3741
|
+
patched = true;
|
|
3742
|
+
}
|
|
3743
|
+
return patched;
|
|
3744
|
+
});
|
|
3745
|
+
}
|
|
3746
|
+
async function exportScene(root, options = {}) {
|
|
3857
3747
|
const exporter = new GLTFExporter();
|
|
3858
3748
|
exporter.register(() => ({
|
|
3859
3749
|
writeMesh(mesh, meshDef) {
|
|
@@ -3863,81 +3753,330 @@ function exportScene(data, fileNameOrOptions = "scene.glb") {
|
|
|
3863
3753
|
}
|
|
3864
3754
|
}
|
|
3865
3755
|
}));
|
|
3866
|
-
const
|
|
3867
|
-
const exportRoot = sourceRoot instanceof THREE6.Scene ? sourceRoot : sourceRoot.clone(true);
|
|
3756
|
+
const exportRoot = root instanceof THREE6.Scene ? root : root.clone(true);
|
|
3868
3757
|
const exportTarget = exportRoot instanceof THREE6.Scene ? exportRoot : (() => {
|
|
3869
3758
|
const scene = new THREE6.Scene();
|
|
3870
|
-
scene.name =
|
|
3759
|
+
scene.name = root.name?.trim() || "Scene";
|
|
3871
3760
|
scene.add(exportRoot);
|
|
3872
3761
|
return scene;
|
|
3873
3762
|
})();
|
|
3874
|
-
const detachBundle =
|
|
3763
|
+
const detachBundle = options.bundle ? applyVizijBundle(exportRoot, options.bundle) : () => {
|
|
3875
3764
|
};
|
|
3876
|
-
const
|
|
3877
|
-
|
|
3878
|
-
trs: true,
|
|
3879
|
-
onlyVisible: false,
|
|
3880
|
-
binary,
|
|
3881
|
-
includeCustomExtensions: true
|
|
3882
|
-
};
|
|
3883
|
-
if (animationClips.length > 0) {
|
|
3884
|
-
exporterOptions.animations = animationClips;
|
|
3885
|
-
}
|
|
3765
|
+
const animations = (options.animations ?? []).filter(Boolean);
|
|
3766
|
+
let gltf;
|
|
3886
3767
|
try {
|
|
3887
|
-
exporter.
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
return;
|
|
3895
|
-
}
|
|
3896
|
-
const sanitizedGltf = sanitizeExportedGlb(
|
|
3897
|
-
gltf,
|
|
3898
|
-
data.name?.trim() || void 0
|
|
3899
|
-
);
|
|
3900
|
-
const trimmed = fileName.trim();
|
|
3901
|
-
const safeFileName = trimmed.length > 0 ? trimmed : "scene.glb";
|
|
3902
|
-
const downloadName = safeFileName.toLowerCase().endsWith(".glb") ? safeFileName : `${safeFileName}.glb`;
|
|
3903
|
-
triggerBlobDownload(
|
|
3904
|
-
new Blob([sanitizedGltf], {
|
|
3905
|
-
type: "application/octet-stream"
|
|
3906
|
-
}),
|
|
3907
|
-
downloadName
|
|
3908
|
-
);
|
|
3909
|
-
options.onComplete?.();
|
|
3910
|
-
},
|
|
3911
|
-
(error) => {
|
|
3912
|
-
detachBundle();
|
|
3913
|
-
options.onError?.(normalizeExportError(error));
|
|
3914
|
-
},
|
|
3915
|
-
exporterOptions
|
|
3916
|
-
);
|
|
3768
|
+
gltf = await exporter.parseAsync(exportTarget, {
|
|
3769
|
+
trs: true,
|
|
3770
|
+
onlyVisible: false,
|
|
3771
|
+
binary: true,
|
|
3772
|
+
includeCustomExtensions: true,
|
|
3773
|
+
...animations.length > 0 ? { animations } : {}
|
|
3774
|
+
});
|
|
3917
3775
|
} catch (error) {
|
|
3776
|
+
throw normalizeExportError(error);
|
|
3777
|
+
} finally {
|
|
3918
3778
|
detachBundle();
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
throw
|
|
3779
|
+
}
|
|
3780
|
+
if (!(gltf instanceof ArrayBuffer)) {
|
|
3781
|
+
throw new Error("Failed to export scene.");
|
|
3782
|
+
}
|
|
3783
|
+
return sanitizeExportedGlb(gltf, root.name?.trim() || void 0);
|
|
3784
|
+
}
|
|
3785
|
+
|
|
3786
|
+
// src/functions/build-scene-graph.ts
|
|
3787
|
+
import * as THREE7 from "three";
|
|
3788
|
+
import {
|
|
3789
|
+
instanceOfRawEuler as instanceOfRawEuler5,
|
|
3790
|
+
instanceOfRawHSL as instanceOfRawHSL4,
|
|
3791
|
+
instanceOfRawNumber as instanceOfRawNumber5,
|
|
3792
|
+
instanceOfRawRGB as instanceOfRawRGB4,
|
|
3793
|
+
instanceOfRawVector2 as instanceOfRawVector24,
|
|
3794
|
+
instanceOfRawVector3 as instanceOfRawVector35
|
|
3795
|
+
} from "@vizij/utils";
|
|
3796
|
+
THREE7.Object3D.DEFAULT_UP.set(0, 0, 1);
|
|
3797
|
+
function buildSceneGraph(world, animatables, rootId) {
|
|
3798
|
+
const entry = world[rootId];
|
|
3799
|
+
if (!entry) {
|
|
3800
|
+
throw new Error(`The world has no element "${rootId}".`);
|
|
3801
|
+
}
|
|
3802
|
+
const used = {};
|
|
3803
|
+
for (const feature of Object.values(entry.features)) {
|
|
3804
|
+
if (feature.animated) {
|
|
3805
|
+
used[feature.value] = animatableOf(animatables, feature.value);
|
|
3806
|
+
}
|
|
3807
|
+
}
|
|
3808
|
+
const robotData = createStoredRenderable(entry, used);
|
|
3809
|
+
switch (entry.type) {
|
|
3810
|
+
case "group": {
|
|
3811
|
+
const object = new THREE7.Group();
|
|
3812
|
+
object.name = entry.name;
|
|
3813
|
+
object.userData = { gltfExtensions: { RobotData: robotData } };
|
|
3814
|
+
applyFeatures(entry.features, animatables, groupTransform(object));
|
|
3815
|
+
for (const child of entry.children) {
|
|
3816
|
+
object.add(buildSceneGraph(world, animatables, child));
|
|
3817
|
+
}
|
|
3818
|
+
return object;
|
|
3819
|
+
}
|
|
3820
|
+
case "shape": {
|
|
3821
|
+
const geometry = entry.geometry.clone();
|
|
3822
|
+
if (entry.name) {
|
|
3823
|
+
geometry.name = entry.name;
|
|
3824
|
+
}
|
|
3825
|
+
const material = createMaterial(entry.material);
|
|
3826
|
+
material.name = deriveMaterialName(entry, used) ?? entry.name ?? "";
|
|
3827
|
+
const object = new THREE7.Mesh(geometry, material);
|
|
3828
|
+
object.name = entry.name;
|
|
3829
|
+
object.userData = { gltfExtensions: { RobotData: robotData } };
|
|
3830
|
+
applyFeatures(entry.features, animatables, {
|
|
3831
|
+
...shapeTransform(object),
|
|
3832
|
+
...materialFactors(material),
|
|
3833
|
+
...morphWeights(object, entry)
|
|
3834
|
+
});
|
|
3835
|
+
for (const child of entry.children ?? []) {
|
|
3836
|
+
object.add(buildSceneGraph(world, animatables, child));
|
|
3837
|
+
}
|
|
3838
|
+
return object;
|
|
3839
|
+
}
|
|
3840
|
+
default:
|
|
3841
|
+
throw new Error(
|
|
3842
|
+
`Element "${rootId}" is a ${entry.type}, which has no exported form.`
|
|
3843
|
+
);
|
|
3844
|
+
}
|
|
3845
|
+
}
|
|
3846
|
+
function animatableOf(animatables, id) {
|
|
3847
|
+
const animatable = animatables[id];
|
|
3848
|
+
if (!animatable) {
|
|
3849
|
+
throw new Error(`No animatable "${id}".`);
|
|
3850
|
+
}
|
|
3851
|
+
return animatable;
|
|
3852
|
+
}
|
|
3853
|
+
function applyFeatures(features, animatables, handlers) {
|
|
3854
|
+
for (const [key, handler] of Object.entries(handlers)) {
|
|
3855
|
+
const feature = features[key];
|
|
3856
|
+
if (!feature) {
|
|
3857
|
+
continue;
|
|
3858
|
+
}
|
|
3859
|
+
const value = feature.animated ? authoredDefault(animatableOf(animatables, feature.value)) : feature.value;
|
|
3860
|
+
if (value !== void 0) {
|
|
3861
|
+
handler(value);
|
|
3862
|
+
}
|
|
3863
|
+
}
|
|
3864
|
+
}
|
|
3865
|
+
function groupTransform(object) {
|
|
3866
|
+
return {
|
|
3867
|
+
translation: (value) => {
|
|
3868
|
+
if (instanceOfRawVector35(value)) {
|
|
3869
|
+
object.position.set(value.x, value.y, value.z);
|
|
3870
|
+
} else if (instanceOfRawVector24(value)) {
|
|
3871
|
+
object.position.set(value.x, value.y, object.position.z);
|
|
3872
|
+
}
|
|
3873
|
+
},
|
|
3874
|
+
rotation: (value) => {
|
|
3875
|
+
if (instanceOfRawEuler5(value)) {
|
|
3876
|
+
object.rotation.set(value.x, value.y, value.z, "ZYX");
|
|
3877
|
+
} else if (instanceOfRawNumber5(value)) {
|
|
3878
|
+
object.rotation.set(0, 0, 0);
|
|
3879
|
+
object.rotateZ(value);
|
|
3880
|
+
}
|
|
3881
|
+
},
|
|
3882
|
+
scale: (value) => {
|
|
3883
|
+
if (instanceOfRawVector35(value)) {
|
|
3884
|
+
if (value.x === null || value.y === null || value.z === null) {
|
|
3885
|
+
object.scale.set(0.1, 0.1, 0.1);
|
|
3886
|
+
} else {
|
|
3887
|
+
object.scale.set(value.x, value.y, value.z);
|
|
3888
|
+
}
|
|
3889
|
+
} else if (instanceOfRawNumber5(value)) {
|
|
3890
|
+
object.scale.set(value, value, value);
|
|
3891
|
+
} else {
|
|
3892
|
+
object.scale.set(1, 1, 1);
|
|
3893
|
+
}
|
|
3894
|
+
}
|
|
3895
|
+
};
|
|
3896
|
+
}
|
|
3897
|
+
function shapeTransform(object) {
|
|
3898
|
+
return {
|
|
3899
|
+
translation: (value) => {
|
|
3900
|
+
if (instanceOfRawVector35(value)) {
|
|
3901
|
+
object.position.set(value.x, value.y, value.z);
|
|
3902
|
+
}
|
|
3903
|
+
},
|
|
3904
|
+
rotation: (value) => {
|
|
3905
|
+
if (instanceOfRawEuler5(value)) {
|
|
3906
|
+
object.rotation.set(value.x, value.y, value.z, "ZYX");
|
|
3907
|
+
}
|
|
3908
|
+
},
|
|
3909
|
+
scale: (value) => {
|
|
3910
|
+
if (instanceOfRawVector35(value)) {
|
|
3911
|
+
object.scale.set(value.x, value.y, value.z);
|
|
3912
|
+
} else if (instanceOfRawNumber5(value)) {
|
|
3913
|
+
object.scale.set(value, value, value);
|
|
3914
|
+
} else {
|
|
3915
|
+
object.scale.set(1, 1, 1);
|
|
3916
|
+
}
|
|
3917
|
+
}
|
|
3918
|
+
};
|
|
3919
|
+
}
|
|
3920
|
+
function materialFactors(material) {
|
|
3921
|
+
const standard = material;
|
|
3922
|
+
const phong = material;
|
|
3923
|
+
return {
|
|
3924
|
+
opacity: (value) => {
|
|
3925
|
+
if (instanceOfRawNumber5(value)) {
|
|
3926
|
+
material.opacity = value;
|
|
3927
|
+
material.transparent = value < 1;
|
|
3928
|
+
}
|
|
3929
|
+
},
|
|
3930
|
+
color: (value) => {
|
|
3931
|
+
if (!standard.color) {
|
|
3932
|
+
return;
|
|
3933
|
+
}
|
|
3934
|
+
if (instanceOfRawRGB4(value)) {
|
|
3935
|
+
standard.color.setRGB(value.r, value.g, value.b);
|
|
3936
|
+
} else if (instanceOfRawVector35(value)) {
|
|
3937
|
+
standard.color.setRGB(value.x, value.y, value.z);
|
|
3938
|
+
} else if (instanceOfRawHSL4(value)) {
|
|
3939
|
+
standard.color.setHSL(value.h, value.s, value.l);
|
|
3940
|
+
}
|
|
3941
|
+
},
|
|
3942
|
+
roughness: (value) => {
|
|
3943
|
+
if (standard.roughness !== void 0 && instanceOfRawNumber5(value)) {
|
|
3944
|
+
standard.roughness = value;
|
|
3945
|
+
}
|
|
3946
|
+
},
|
|
3947
|
+
metalness: (value) => {
|
|
3948
|
+
if (standard.metalness !== void 0 && instanceOfRawNumber5(value)) {
|
|
3949
|
+
standard.metalness = value;
|
|
3950
|
+
}
|
|
3951
|
+
},
|
|
3952
|
+
shininess: (value) => {
|
|
3953
|
+
if (phong.shininess !== void 0 && instanceOfRawNumber5(value)) {
|
|
3954
|
+
phong.shininess = value;
|
|
3955
|
+
}
|
|
3956
|
+
},
|
|
3957
|
+
emissive: (value) => {
|
|
3958
|
+
if (standard.emissive && instanceOfRawRGB4(value)) {
|
|
3959
|
+
standard.emissive.setRGB(value.r, value.g, value.b);
|
|
3960
|
+
}
|
|
3961
|
+
},
|
|
3962
|
+
emissiveIntensity: (value) => {
|
|
3963
|
+
if (standard.emissiveIntensity !== void 0 && instanceOfRawNumber5(value)) {
|
|
3964
|
+
standard.emissiveIntensity = value;
|
|
3965
|
+
}
|
|
3966
|
+
},
|
|
3967
|
+
specular: (value) => {
|
|
3968
|
+
if (phong.specular && instanceOfRawRGB4(value)) {
|
|
3969
|
+
phong.specular.setRGB(value.r, value.g, value.b);
|
|
3970
|
+
}
|
|
3971
|
+
}
|
|
3972
|
+
};
|
|
3973
|
+
}
|
|
3974
|
+
function morphWeights(object, shape) {
|
|
3975
|
+
const targets = shape.morphTargets ?? [];
|
|
3976
|
+
if (targets.length === 0) {
|
|
3977
|
+
return {};
|
|
3978
|
+
}
|
|
3979
|
+
const influences = targets.map(() => 0);
|
|
3980
|
+
object.morphTargetDictionary = Object.fromEntries(
|
|
3981
|
+
targets.map((target, index) => [target, index])
|
|
3982
|
+
);
|
|
3983
|
+
object.morphTargetInfluences = influences;
|
|
3984
|
+
return Object.fromEntries(
|
|
3985
|
+
targets.map((target, index) => [
|
|
3986
|
+
target,
|
|
3987
|
+
(value) => {
|
|
3988
|
+
if (instanceOfRawNumber5(value)) {
|
|
3989
|
+
influences[index] = value;
|
|
3990
|
+
}
|
|
3991
|
+
}
|
|
3992
|
+
])
|
|
3993
|
+
);
|
|
3994
|
+
}
|
|
3995
|
+
function createMaterial(kind) {
|
|
3996
|
+
const parameters = { side: THREE7.DoubleSide };
|
|
3997
|
+
switch (kind) {
|
|
3998
|
+
case "basic" /* Basic */:
|
|
3999
|
+
return new THREE7.MeshBasicMaterial(parameters);
|
|
4000
|
+
case "lambert" /* Lambert */:
|
|
4001
|
+
return new THREE7.MeshLambertMaterial(parameters);
|
|
4002
|
+
case "phong" /* Phong */:
|
|
4003
|
+
return new THREE7.MeshPhongMaterial(parameters);
|
|
4004
|
+
case "normal" /* Normal */:
|
|
4005
|
+
return new THREE7.MeshNormalMaterial(parameters);
|
|
4006
|
+
case "standard" /* Standard */:
|
|
4007
|
+
return new THREE7.MeshStandardMaterial(parameters);
|
|
4008
|
+
}
|
|
4009
|
+
}
|
|
4010
|
+
var SCALAR_KEYS = ["f32", "f64", "i64", "i32", "u64", "u32", "float"];
|
|
4011
|
+
function scalarOf(value) {
|
|
4012
|
+
if (typeof value === "number") {
|
|
4013
|
+
return value;
|
|
4014
|
+
}
|
|
4015
|
+
if (value && typeof value === "object") {
|
|
4016
|
+
for (const key of SCALAR_KEYS) {
|
|
4017
|
+
const scalar = value[key];
|
|
4018
|
+
if (typeof scalar === "number") {
|
|
4019
|
+
return scalar;
|
|
4020
|
+
}
|
|
4021
|
+
}
|
|
4022
|
+
}
|
|
4023
|
+
return void 0;
|
|
4024
|
+
}
|
|
4025
|
+
function authoredDefault(animatable) {
|
|
4026
|
+
const value = animatable.default;
|
|
4027
|
+
const scalar = scalarOf(value);
|
|
4028
|
+
if (scalar !== void 0) {
|
|
4029
|
+
return scalar;
|
|
4030
|
+
}
|
|
4031
|
+
const fields = value?.struct?.fields;
|
|
4032
|
+
if (!Array.isArray(fields)) {
|
|
4033
|
+
return value;
|
|
4034
|
+
}
|
|
4035
|
+
const n = fields.map(
|
|
4036
|
+
(field) => scalarOf(field?.value) ?? 0
|
|
4037
|
+
);
|
|
4038
|
+
switch (animatable.type) {
|
|
4039
|
+
case "vector3":
|
|
4040
|
+
case "euler":
|
|
4041
|
+
return { x: n[0], y: n[1], z: n[2] };
|
|
4042
|
+
case "vector2":
|
|
4043
|
+
return { x: n[0], y: n[1] };
|
|
4044
|
+
case "rgb":
|
|
4045
|
+
return { r: n[0], g: n[1], b: n[2] };
|
|
4046
|
+
case "hsl":
|
|
4047
|
+
return { h: n[0], s: n[1], l: n[2] };
|
|
4048
|
+
default:
|
|
4049
|
+
return void 0;
|
|
3922
4050
|
}
|
|
3923
4051
|
}
|
|
3924
4052
|
export {
|
|
4053
|
+
DEFAULT_TONE_MAPPING_MODE,
|
|
3925
4054
|
EmptyModelError,
|
|
3926
4055
|
InnerVizij,
|
|
3927
4056
|
ShapeMaterial,
|
|
4057
|
+
TONE_MAPPING_LABELS,
|
|
4058
|
+
TONE_MAPPING_MODES,
|
|
3928
4059
|
Vizij,
|
|
3929
4060
|
VizijContext,
|
|
3930
4061
|
VizijSlice,
|
|
3931
4062
|
applyVizijBundle,
|
|
4063
|
+
buildSceneGraph,
|
|
3932
4064
|
createVizijStore,
|
|
4065
|
+
deriveMorphFeatureKeys,
|
|
4066
|
+
deriveRootBounds,
|
|
3933
4067
|
exportScene,
|
|
3934
4068
|
extractVizijBundle,
|
|
4069
|
+
isToneMappingMode,
|
|
3935
4070
|
loadGLTF,
|
|
3936
4071
|
loadGLTFFromBlob,
|
|
3937
4072
|
loadGLTFFromBlobWithBundle,
|
|
3938
4073
|
loadGLTFWithBundle,
|
|
3939
|
-
|
|
4074
|
+
normalizeToneMappingMode,
|
|
3940
4075
|
parseGlbJsonChunk,
|
|
4076
|
+
patchGlbJson,
|
|
4077
|
+
patchVizijBundleMetadata,
|
|
4078
|
+
resolveToneMapping,
|
|
4079
|
+
sanitizeMorphKey,
|
|
3941
4080
|
useDefaultVizijStore,
|
|
3942
4081
|
useFeatures,
|
|
3943
4082
|
useVizijStore,
|