@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.js
CHANGED
|
@@ -30,22 +30,33 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.tsx
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
DEFAULT_TONE_MAPPING_MODE: () => DEFAULT_TONE_MAPPING_MODE,
|
|
33
34
|
EmptyModelError: () => EmptyModelError,
|
|
34
35
|
InnerVizij: () => InnerVizij,
|
|
35
36
|
ShapeMaterial: () => ShapeMaterial,
|
|
37
|
+
TONE_MAPPING_LABELS: () => TONE_MAPPING_LABELS,
|
|
38
|
+
TONE_MAPPING_MODES: () => TONE_MAPPING_MODES,
|
|
36
39
|
Vizij: () => Vizij,
|
|
37
40
|
VizijContext: () => VizijContext,
|
|
38
41
|
VizijSlice: () => VizijSlice,
|
|
39
42
|
applyVizijBundle: () => applyVizijBundle,
|
|
43
|
+
buildSceneGraph: () => buildSceneGraph,
|
|
40
44
|
createVizijStore: () => createVizijStore,
|
|
45
|
+
deriveMorphFeatureKeys: () => deriveMorphFeatureKeys,
|
|
46
|
+
deriveRootBounds: () => deriveRootBounds,
|
|
41
47
|
exportScene: () => exportScene,
|
|
42
48
|
extractVizijBundle: () => extractVizijBundle,
|
|
49
|
+
isToneMappingMode: () => isToneMappingMode,
|
|
43
50
|
loadGLTF: () => loadGLTF,
|
|
44
51
|
loadGLTFFromBlob: () => loadGLTFFromBlob,
|
|
45
52
|
loadGLTFFromBlobWithBundle: () => loadGLTFFromBlobWithBundle,
|
|
46
53
|
loadGLTFWithBundle: () => loadGLTFWithBundle,
|
|
47
|
-
|
|
54
|
+
normalizeToneMappingMode: () => normalizeToneMappingMode,
|
|
48
55
|
parseGlbJsonChunk: () => parseGlbJsonChunk,
|
|
56
|
+
patchGlbJson: () => patchGlbJson,
|
|
57
|
+
patchVizijBundleMetadata: () => patchVizijBundleMetadata,
|
|
58
|
+
resolveToneMapping: () => resolveToneMapping,
|
|
59
|
+
sanitizeMorphKey: () => sanitizeMorphKey,
|
|
49
60
|
useDefaultVizijStore: () => useDefaultVizijStore,
|
|
50
61
|
useFeatures: () => useFeatures,
|
|
51
62
|
useVizijStore: () => useVizijStore,
|
|
@@ -56,9 +67,9 @@ __export(index_exports, {
|
|
|
56
67
|
module.exports = __toCommonJS(index_exports);
|
|
57
68
|
|
|
58
69
|
// src/vizij.tsx
|
|
59
|
-
var
|
|
70
|
+
var import_react10 = require("react");
|
|
60
71
|
var import_react_error_boundary = require("react-error-boundary");
|
|
61
|
-
var
|
|
72
|
+
var import_three3 = require("three");
|
|
62
73
|
var import_fiber2 = require("@react-three/fiber");
|
|
63
74
|
var import_drei3 = require("@react-three/drei");
|
|
64
75
|
var import_shallow8 = require("zustand/react/shallow");
|
|
@@ -136,35 +147,33 @@ function useFeatures(namespace, features, callbacks, debugInfo) {
|
|
|
136
147
|
}, [features, callbacks, store, debugInfo, namespace]);
|
|
137
148
|
}
|
|
138
149
|
|
|
139
|
-
// src/functions/create-stored-data.ts
|
|
140
|
-
var import_lodash2 = require("lodash");
|
|
141
|
-
|
|
142
150
|
// src/functions/create-stored-features.ts
|
|
143
|
-
var import_lodash = require("lodash");
|
|
144
151
|
function createStoredFeatures(objectFeatures, animatableValues) {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
152
|
+
const stored = Object.entries(objectFeatures).map(
|
|
153
|
+
([key, feat]) => {
|
|
154
|
+
if (feat.animated) {
|
|
155
|
+
const storedFeat = {
|
|
156
|
+
animated: true,
|
|
157
|
+
value: animatableValues[feat.value],
|
|
158
|
+
...feat.label ? { label: feat.label } : {}
|
|
159
|
+
};
|
|
160
|
+
return [key, storedFeat];
|
|
161
|
+
}
|
|
154
162
|
const staticFeature = feat;
|
|
155
|
-
return staticFeature.label ? { ...staticFeature } : staticFeature;
|
|
163
|
+
return [key, staticFeature.label ? { ...staticFeature } : staticFeature];
|
|
156
164
|
}
|
|
157
|
-
|
|
165
|
+
);
|
|
166
|
+
return Object.fromEntries(stored);
|
|
158
167
|
}
|
|
159
168
|
|
|
160
169
|
// src/functions/create-stored-data.ts
|
|
161
170
|
function createStoredRenderable(data, animatableValues) {
|
|
162
|
-
const
|
|
171
|
+
const { geometry: _geometry, ...stored } = data;
|
|
163
172
|
const storedFeatures = createStoredFeatures(
|
|
164
173
|
data.features,
|
|
165
174
|
animatableValues
|
|
166
175
|
);
|
|
167
|
-
return { ...
|
|
176
|
+
return { ...stored, features: storedFeatures };
|
|
168
177
|
}
|
|
169
178
|
|
|
170
179
|
// src/renderables/group.tsx
|
|
@@ -177,7 +186,9 @@ function InnerRenderedGroup({
|
|
|
177
186
|
}) {
|
|
178
187
|
const ref = (0, import_react4.useRef)(null);
|
|
179
188
|
const group = useVizijStore((0, import_shallow2.useShallow)((state) => state.world[id]));
|
|
180
|
-
const refIsNull =
|
|
189
|
+
const refIsNull = useVizijStore(
|
|
190
|
+
(state) => !state.refs[id]?.[namespace]?.current
|
|
191
|
+
);
|
|
181
192
|
const animatables = useVizijStore((0, import_shallow2.useShallow)((state) => state.animatables));
|
|
182
193
|
const setHoveredElement = useVizijStore(
|
|
183
194
|
(0, import_shallow2.useShallow)((state) => state.setHoveredElement)
|
|
@@ -312,7 +323,9 @@ function InnerRenderedEllipse({
|
|
|
312
323
|
const ellipse = useVizijStore(
|
|
313
324
|
(0, import_shallow3.useShallow)((state) => state.world[id])
|
|
314
325
|
);
|
|
315
|
-
const refIsNull =
|
|
326
|
+
const refIsNull = useVizijStore(
|
|
327
|
+
(state) => !state.refs[id]?.[namespace]?.current
|
|
328
|
+
);
|
|
316
329
|
const animatables = useVizijStore((0, import_shallow3.useShallow)((state) => state.animatables));
|
|
317
330
|
const animatableValues = (0, import_react5.useMemo)(() => {
|
|
318
331
|
const av = {};
|
|
@@ -599,7 +612,9 @@ function InnerRenderedRectangle({
|
|
|
599
612
|
const rectangle = useVizijStore(
|
|
600
613
|
(0, import_shallow4.useShallow)((state) => state.world[id])
|
|
601
614
|
);
|
|
602
|
-
const refIsNull =
|
|
615
|
+
const refIsNull = useVizijStore(
|
|
616
|
+
(state) => !state.refs[id]?.[namespace]?.current
|
|
617
|
+
);
|
|
603
618
|
const animatables = useVizijStore((0, import_shallow4.useShallow)((state) => state.animatables));
|
|
604
619
|
const animatableValues = (0, import_react6.useMemo)(() => {
|
|
605
620
|
const av = {};
|
|
@@ -865,6 +880,61 @@ var import_react7 = require("react");
|
|
|
865
880
|
var THREE2 = __toESM(require("three"));
|
|
866
881
|
var import_shallow5 = require("zustand/react/shallow");
|
|
867
882
|
var import_utils5 = require("@vizij/utils");
|
|
883
|
+
|
|
884
|
+
// src/functions/material-name.ts
|
|
885
|
+
var MATERIAL_FEATURE_KEYS = [
|
|
886
|
+
"color",
|
|
887
|
+
"opacity",
|
|
888
|
+
"roughness",
|
|
889
|
+
"metalness",
|
|
890
|
+
"shininess",
|
|
891
|
+
"emissive",
|
|
892
|
+
"emissiveIntensity",
|
|
893
|
+
"specular"
|
|
894
|
+
];
|
|
895
|
+
var MATERIAL_NAME_SUFFIXES = [
|
|
896
|
+
" color",
|
|
897
|
+
" colours",
|
|
898
|
+
" colour",
|
|
899
|
+
" opacity",
|
|
900
|
+
" roughness",
|
|
901
|
+
" metalness",
|
|
902
|
+
" shininess",
|
|
903
|
+
" emissive intensity",
|
|
904
|
+
" emissive",
|
|
905
|
+
" specular"
|
|
906
|
+
];
|
|
907
|
+
function deriveMaterialName(shape, values) {
|
|
908
|
+
for (const key of MATERIAL_FEATURE_KEYS) {
|
|
909
|
+
const feature = shape.features[key];
|
|
910
|
+
if (feature && feature.animated) {
|
|
911
|
+
const animatable = values[feature.value];
|
|
912
|
+
const candidate = extractMaterialName(animatable?.name);
|
|
913
|
+
if (candidate) {
|
|
914
|
+
return candidate;
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
return void 0;
|
|
919
|
+
}
|
|
920
|
+
function extractMaterialName(name) {
|
|
921
|
+
if (!name) {
|
|
922
|
+
return void 0;
|
|
923
|
+
}
|
|
924
|
+
const trimmed = name.trim();
|
|
925
|
+
if (!trimmed) {
|
|
926
|
+
return void 0;
|
|
927
|
+
}
|
|
928
|
+
const lowered = trimmed.toLowerCase();
|
|
929
|
+
for (const suffix of MATERIAL_NAME_SUFFIXES) {
|
|
930
|
+
if (lowered.endsWith(suffix)) {
|
|
931
|
+
return trimmed.slice(0, trimmed.length - suffix.length).trim();
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
return trimmed;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
// src/renderables/shape.tsx
|
|
868
938
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
869
939
|
THREE2.Object3D.DEFAULT_UP.set(0, 0, 1);
|
|
870
940
|
function InnerRenderedShape({
|
|
@@ -875,10 +945,9 @@ function InnerRenderedShape({
|
|
|
875
945
|
const refGroup = (0, import_react7.useRef)(null);
|
|
876
946
|
const ref = (0, import_react7.useRef)(null);
|
|
877
947
|
const shape = useVizijStore((0, import_shallow5.useShallow)((state) => state.world[id]));
|
|
878
|
-
const
|
|
879
|
-
(
|
|
948
|
+
const refIsNull = useVizijStore(
|
|
949
|
+
(state) => !state.refs[id]?.[namespace]?.current
|
|
880
950
|
);
|
|
881
|
-
const refIsNull = !refs[namespace]?.current;
|
|
882
951
|
const animatables = useVizijStore((0, import_shallow5.useShallow)((state) => state.animatables));
|
|
883
952
|
const animatableValues = (0, import_react7.useMemo)(() => {
|
|
884
953
|
const av = {};
|
|
@@ -1163,57 +1232,6 @@ function InnerRenderedShape({
|
|
|
1163
1232
|
);
|
|
1164
1233
|
}
|
|
1165
1234
|
var RenderedShape = (0, import_react7.memo)(InnerRenderedShape);
|
|
1166
|
-
var MATERIAL_FEATURE_KEYS = [
|
|
1167
|
-
"color",
|
|
1168
|
-
"opacity",
|
|
1169
|
-
"roughness",
|
|
1170
|
-
"metalness",
|
|
1171
|
-
"shininess",
|
|
1172
|
-
"emissive",
|
|
1173
|
-
"emissiveIntensity",
|
|
1174
|
-
"specular"
|
|
1175
|
-
];
|
|
1176
|
-
var MATERIAL_NAME_SUFFIXES = [
|
|
1177
|
-
" color",
|
|
1178
|
-
" colours",
|
|
1179
|
-
" colour",
|
|
1180
|
-
" opacity",
|
|
1181
|
-
" roughness",
|
|
1182
|
-
" metalness",
|
|
1183
|
-
" shininess",
|
|
1184
|
-
" emissive intensity",
|
|
1185
|
-
" emissive",
|
|
1186
|
-
" specular"
|
|
1187
|
-
];
|
|
1188
|
-
function deriveMaterialName(shape, values) {
|
|
1189
|
-
for (const key of MATERIAL_FEATURE_KEYS) {
|
|
1190
|
-
const feature = shape.features[key];
|
|
1191
|
-
if (feature && feature.animated) {
|
|
1192
|
-
const animatable = values[feature.value];
|
|
1193
|
-
const candidate = extractMaterialName(animatable?.name);
|
|
1194
|
-
if (candidate) {
|
|
1195
|
-
return candidate;
|
|
1196
|
-
}
|
|
1197
|
-
}
|
|
1198
|
-
}
|
|
1199
|
-
return void 0;
|
|
1200
|
-
}
|
|
1201
|
-
function extractMaterialName(name) {
|
|
1202
|
-
if (!name) {
|
|
1203
|
-
return void 0;
|
|
1204
|
-
}
|
|
1205
|
-
const trimmed = name.trim();
|
|
1206
|
-
if (!trimmed) {
|
|
1207
|
-
return void 0;
|
|
1208
|
-
}
|
|
1209
|
-
const lowered = trimmed.toLowerCase();
|
|
1210
|
-
for (const suffix of MATERIAL_NAME_SUFFIXES) {
|
|
1211
|
-
if (lowered.endsWith(suffix)) {
|
|
1212
|
-
return trimmed.slice(0, trimmed.length - suffix.length).trim();
|
|
1213
|
-
}
|
|
1214
|
-
}
|
|
1215
|
-
return trimmed;
|
|
1216
|
-
}
|
|
1217
1235
|
|
|
1218
1236
|
// src/renderables/renderable.tsx
|
|
1219
1237
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
@@ -1223,65 +1241,35 @@ function InnerRenderable({
|
|
|
1223
1241
|
chain
|
|
1224
1242
|
}) {
|
|
1225
1243
|
const type = useVizijStore((0, import_shallow6.useShallow)((state) => state.world[id].type));
|
|
1226
|
-
const
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1244
|
+
const key = `${namespace}.${id}`;
|
|
1245
|
+
switch (type) {
|
|
1246
|
+
case "group":
|
|
1247
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RenderedGroup, { id, namespace, chain }, key);
|
|
1248
|
+
case "ellipse":
|
|
1249
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1250
|
+
RenderedEllipse,
|
|
1251
|
+
{
|
|
1252
|
+
id,
|
|
1253
|
+
namespace,
|
|
1254
|
+
chain
|
|
1255
|
+
},
|
|
1256
|
+
key
|
|
1257
|
+
);
|
|
1258
|
+
case "rectangle":
|
|
1259
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1260
|
+
RenderedRectangle,
|
|
1261
|
+
{
|
|
1262
|
+
id,
|
|
1263
|
+
namespace,
|
|
1264
|
+
chain
|
|
1265
|
+
},
|
|
1266
|
+
key
|
|
1267
|
+
);
|
|
1268
|
+
case "shape":
|
|
1269
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RenderedShape, { id, namespace, chain }, key);
|
|
1270
|
+
default:
|
|
1271
|
+
return null;
|
|
1238
1272
|
}
|
|
1239
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children: resolvedNamespaces.map((ns) => {
|
|
1240
|
-
switch (type) {
|
|
1241
|
-
case "group":
|
|
1242
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1243
|
-
RenderedGroup,
|
|
1244
|
-
{
|
|
1245
|
-
id,
|
|
1246
|
-
namespace: ns,
|
|
1247
|
-
chain
|
|
1248
|
-
},
|
|
1249
|
-
`${ns}.${id}`
|
|
1250
|
-
);
|
|
1251
|
-
case "ellipse":
|
|
1252
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1253
|
-
RenderedEllipse,
|
|
1254
|
-
{
|
|
1255
|
-
id,
|
|
1256
|
-
namespace: ns,
|
|
1257
|
-
chain
|
|
1258
|
-
},
|
|
1259
|
-
`${ns}.${id}`
|
|
1260
|
-
);
|
|
1261
|
-
case "rectangle":
|
|
1262
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1263
|
-
RenderedRectangle,
|
|
1264
|
-
{
|
|
1265
|
-
id,
|
|
1266
|
-
namespace: ns,
|
|
1267
|
-
chain
|
|
1268
|
-
},
|
|
1269
|
-
`${ns}.${id}`
|
|
1270
|
-
);
|
|
1271
|
-
case "shape":
|
|
1272
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1273
|
-
RenderedShape,
|
|
1274
|
-
{
|
|
1275
|
-
id,
|
|
1276
|
-
namespace: ns,
|
|
1277
|
-
chain
|
|
1278
|
-
},
|
|
1279
|
-
`${ns}.${id}`
|
|
1280
|
-
);
|
|
1281
|
-
default:
|
|
1282
|
-
return null;
|
|
1283
|
-
}
|
|
1284
|
-
}) });
|
|
1285
1273
|
}
|
|
1286
1274
|
var Renderable = (0, import_react8.memo)(InnerRenderable);
|
|
1287
1275
|
|
|
@@ -1292,10 +1280,6 @@ var import_immer = require("immer");
|
|
|
1292
1280
|
var THREE3 = __toESM(require("three"));
|
|
1293
1281
|
var import_utils8 = require("@vizij/utils");
|
|
1294
1282
|
|
|
1295
|
-
// src/actions/create-new-element.ts
|
|
1296
|
-
var import_react9 = require("react");
|
|
1297
|
-
var import_lodash3 = require("lodash");
|
|
1298
|
-
|
|
1299
1283
|
// src/functions/create-world-element.ts
|
|
1300
1284
|
var import_utils6 = require("@vizij/utils");
|
|
1301
1285
|
function createDefaultGroup(partialBody) {
|
|
@@ -1307,7 +1291,6 @@ function createDefaultGroup(partialBody) {
|
|
|
1307
1291
|
name: partialBody.name || "new-body",
|
|
1308
1292
|
type: partialBody.type || "group",
|
|
1309
1293
|
tags: partialBody.tags || [],
|
|
1310
|
-
refs: partialBody.refs || {},
|
|
1311
1294
|
features: { translation, rotation, scale },
|
|
1312
1295
|
root: partialBody.root ?? false,
|
|
1313
1296
|
children: partialBody.children || []
|
|
@@ -1324,11 +1307,9 @@ function createNewElement(state, type, root = false) {
|
|
|
1324
1307
|
});
|
|
1325
1308
|
if (Object.entries(state.world).length === 0) {
|
|
1326
1309
|
const name = `New-Root`;
|
|
1327
|
-
const refs = { default: (0, import_react9.createRef)() };
|
|
1328
1310
|
const newElement = createDefaultGroup({
|
|
1329
1311
|
name,
|
|
1330
|
-
root: true
|
|
1331
|
-
refs
|
|
1312
|
+
root: true
|
|
1332
1313
|
});
|
|
1333
1314
|
state.world[newElement.id] = newElement;
|
|
1334
1315
|
state.elementSelection = [buildSelection(newElement.id)];
|
|
@@ -1340,11 +1321,7 @@ function createNewElement(state, type, root = false) {
|
|
|
1340
1321
|
return;
|
|
1341
1322
|
}
|
|
1342
1323
|
const name = `New-Body`;
|
|
1343
|
-
const
|
|
1344
|
-
worldRootEntry.refs,
|
|
1345
|
-
() => (0, import_react9.createRef)()
|
|
1346
|
-
);
|
|
1347
|
-
const newChild = createDefaultGroup({ name, root, refs });
|
|
1324
|
+
const newChild = createDefaultGroup({ name, root });
|
|
1348
1325
|
worldRootEntry.children.push(newChild.id);
|
|
1349
1326
|
state.world[newChild.id] = newChild;
|
|
1350
1327
|
state.elementSelection = [buildSelection(newChild.id)];
|
|
@@ -1544,6 +1521,7 @@ THREE3.Object3D.DEFAULT_UP.set(0, 0, 1);
|
|
|
1544
1521
|
var VizijSlice = (set, get) => ({
|
|
1545
1522
|
// worldRef: createRef<THREE.Group>(),
|
|
1546
1523
|
world: {},
|
|
1524
|
+
refs: {},
|
|
1547
1525
|
animatables: {},
|
|
1548
1526
|
values: /* @__PURE__ */ new Map(),
|
|
1549
1527
|
renderHit: false,
|
|
@@ -1617,12 +1595,10 @@ var VizijSlice = (set, get) => ({
|
|
|
1617
1595
|
worldData,
|
|
1618
1596
|
filterIds
|
|
1619
1597
|
);
|
|
1598
|
+
const refs = get().refs;
|
|
1620
1599
|
return candidateGroups.flatMap((entry) => {
|
|
1621
|
-
const
|
|
1622
|
-
|
|
1623
|
-
);
|
|
1624
|
-
const resolved = refs.find((ref) => ref?.current)?.current ?? null;
|
|
1625
|
-
return resolved ? [resolved] : [];
|
|
1600
|
+
const mounted = Object.values(refs[entry.id] ?? {}).map((ref) => ref.current).find((object) => Boolean(object));
|
|
1601
|
+
return mounted ? [mounted] : [];
|
|
1626
1602
|
});
|
|
1627
1603
|
},
|
|
1628
1604
|
setGeometry: (id, geometry) => {
|
|
@@ -1844,14 +1820,12 @@ var VizijSlice = (set, get) => ({
|
|
|
1844
1820
|
}));
|
|
1845
1821
|
},
|
|
1846
1822
|
setReference: (id, namespace, ref) => {
|
|
1847
|
-
set(
|
|
1848
|
-
|
|
1849
|
-
state.
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
})
|
|
1854
|
-
);
|
|
1823
|
+
set((state) => ({
|
|
1824
|
+
refs: {
|
|
1825
|
+
...state.refs,
|
|
1826
|
+
[id]: { ...state.refs[id], [namespace]: ref }
|
|
1827
|
+
}
|
|
1828
|
+
}));
|
|
1855
1829
|
}
|
|
1856
1830
|
});
|
|
1857
1831
|
var useDefaultVizijStore = (0, import_zustand2.create)()(
|
|
@@ -1866,11 +1840,55 @@ var createVizijStore = (initial) => (0, import_zustand2.create)()(
|
|
|
1866
1840
|
}))
|
|
1867
1841
|
);
|
|
1868
1842
|
|
|
1843
|
+
// src/types/shape.ts
|
|
1844
|
+
var ShapeMaterial = /* @__PURE__ */ ((ShapeMaterial2) => {
|
|
1845
|
+
ShapeMaterial2["Standard"] = "standard";
|
|
1846
|
+
ShapeMaterial2["Phong"] = "phong";
|
|
1847
|
+
ShapeMaterial2["Basic"] = "basic";
|
|
1848
|
+
ShapeMaterial2["Lambert"] = "lambert";
|
|
1849
|
+
ShapeMaterial2["Normal"] = "normal";
|
|
1850
|
+
return ShapeMaterial2;
|
|
1851
|
+
})(ShapeMaterial || {});
|
|
1852
|
+
|
|
1853
|
+
// src/types/tone-mapping.ts
|
|
1854
|
+
var import_three = require("three");
|
|
1855
|
+
var TONE_MAPPING_MODES = [
|
|
1856
|
+
"none",
|
|
1857
|
+
"agx",
|
|
1858
|
+
"aces",
|
|
1859
|
+
"neutral"
|
|
1860
|
+
];
|
|
1861
|
+
var TONE_MAPPING_LABELS = {
|
|
1862
|
+
none: "None (web match)",
|
|
1863
|
+
agx: "AgX (Blender)",
|
|
1864
|
+
aces: "ACES Filmic",
|
|
1865
|
+
neutral: "Neutral"
|
|
1866
|
+
};
|
|
1867
|
+
var DEFAULT_TONE_MAPPING_MODE = "none";
|
|
1868
|
+
var TONE_MAPPING_CONSTANTS = {
|
|
1869
|
+
none: import_three.NoToneMapping,
|
|
1870
|
+
agx: import_three.AgXToneMapping,
|
|
1871
|
+
aces: import_three.ACESFilmicToneMapping,
|
|
1872
|
+
neutral: import_three.NeutralToneMapping
|
|
1873
|
+
};
|
|
1874
|
+
function isToneMappingMode(value) {
|
|
1875
|
+
return typeof value === "string" && Object.prototype.hasOwnProperty.call(TONE_MAPPING_CONSTANTS, value);
|
|
1876
|
+
}
|
|
1877
|
+
function resolveToneMapping(mode) {
|
|
1878
|
+
if (isToneMappingMode(mode)) {
|
|
1879
|
+
return TONE_MAPPING_CONSTANTS[mode];
|
|
1880
|
+
}
|
|
1881
|
+
return TONE_MAPPING_CONSTANTS[DEFAULT_TONE_MAPPING_MODE];
|
|
1882
|
+
}
|
|
1883
|
+
function normalizeToneMappingMode(value) {
|
|
1884
|
+
return isToneMappingMode(value) ? value : DEFAULT_TONE_MAPPING_MODE;
|
|
1885
|
+
}
|
|
1886
|
+
|
|
1869
1887
|
// src/effects/selection-glow-effect.tsx
|
|
1870
|
-
var
|
|
1888
|
+
var import_react9 = require("react");
|
|
1871
1889
|
var import_fiber = require("@react-three/fiber");
|
|
1872
1890
|
var import_shallow7 = require("zustand/react/shallow");
|
|
1873
|
-
var
|
|
1891
|
+
var import_three2 = require("three");
|
|
1874
1892
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1875
1893
|
function SelectionGlowEffect({
|
|
1876
1894
|
enabled = false,
|
|
@@ -1886,7 +1904,7 @@ function SelectionGlowEffect({
|
|
|
1886
1904
|
if (!enabled || selections.length === 0) {
|
|
1887
1905
|
return null;
|
|
1888
1906
|
}
|
|
1889
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1907
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react9.Fragment, { children: selections.map((selection) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1890
1908
|
SelectionOutline,
|
|
1891
1909
|
{
|
|
1892
1910
|
selection,
|
|
@@ -1906,32 +1924,32 @@ function SelectionOutline({
|
|
|
1906
1924
|
const target = useVizijStore(
|
|
1907
1925
|
(0, import_shallow7.useShallow)((state) => {
|
|
1908
1926
|
const entry = state.world[selection.id];
|
|
1909
|
-
const ref =
|
|
1927
|
+
const ref = state.refs[selection.id]?.[selection.namespace];
|
|
1910
1928
|
const geometry = entry?.geometry ?? null;
|
|
1911
1929
|
return { ref, geometry };
|
|
1912
1930
|
})
|
|
1913
1931
|
);
|
|
1914
1932
|
const sourceRef = target.ref;
|
|
1915
|
-
const edgesGeometry = (0,
|
|
1933
|
+
const edgesGeometry = (0, import_react9.useMemo)(() => {
|
|
1916
1934
|
if (!target.geometry) return null;
|
|
1917
|
-
const edges = new
|
|
1935
|
+
const edges = new import_three2.EdgesGeometry(target.geometry, thresholdAngle);
|
|
1918
1936
|
return edges;
|
|
1919
1937
|
}, [target.geometry, thresholdAngle]);
|
|
1920
|
-
(0,
|
|
1921
|
-
const material = (0,
|
|
1922
|
-
const mat = new
|
|
1923
|
-
color: new
|
|
1938
|
+
(0, import_react9.useEffect)(() => () => edgesGeometry?.dispose(), [edgesGeometry]);
|
|
1939
|
+
const material = (0, import_react9.useMemo)(() => {
|
|
1940
|
+
const mat = new import_three2.LineBasicMaterial({
|
|
1941
|
+
color: new import_three2.Color(color),
|
|
1924
1942
|
transparent: true,
|
|
1925
1943
|
opacity,
|
|
1926
|
-
blending:
|
|
1944
|
+
blending: import_three2.AdditiveBlending,
|
|
1927
1945
|
depthTest: false,
|
|
1928
1946
|
depthWrite: false,
|
|
1929
1947
|
toneMapped: false
|
|
1930
1948
|
});
|
|
1931
1949
|
return mat;
|
|
1932
1950
|
}, [color, opacity]);
|
|
1933
|
-
(0,
|
|
1934
|
-
const lineRef = (0,
|
|
1951
|
+
(0, import_react9.useEffect)(() => () => material.dispose(), [material]);
|
|
1952
|
+
const lineRef = (0, import_react9.useRef)(null);
|
|
1935
1953
|
(0, import_fiber.useFrame)(() => {
|
|
1936
1954
|
const source = sourceRef?.current;
|
|
1937
1955
|
const line = lineRef.current;
|
|
@@ -1953,10 +1971,10 @@ function SelectionOutline({
|
|
|
1953
1971
|
}
|
|
1954
1972
|
);
|
|
1955
1973
|
}
|
|
1956
|
-
var tempMatrix = new
|
|
1957
|
-
var tempPosition = new
|
|
1958
|
-
var tempQuaternion = new
|
|
1959
|
-
var tempScale = new
|
|
1974
|
+
var tempMatrix = new import_three2.Matrix4();
|
|
1975
|
+
var tempPosition = new import_three2.Vector3();
|
|
1976
|
+
var tempQuaternion = new import_three2.Quaternion();
|
|
1977
|
+
var tempScale = new import_three2.Vector3();
|
|
1960
1978
|
function copyWorldTransform(source, target) {
|
|
1961
1979
|
source.updateWorldMatrix(true, false);
|
|
1962
1980
|
tempMatrix.copy(source.matrixWorld);
|
|
@@ -1969,7 +1987,7 @@ function copyWorldTransform(source, target) {
|
|
|
1969
1987
|
|
|
1970
1988
|
// src/vizij.tsx
|
|
1971
1989
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1972
|
-
|
|
1990
|
+
import_three3.Object3D.DEFAULT_UP.set(0, 0, 1);
|
|
1973
1991
|
function Vizij({
|
|
1974
1992
|
style,
|
|
1975
1993
|
className,
|
|
@@ -1977,10 +1995,11 @@ function Vizij({
|
|
|
1977
1995
|
namespace = "default",
|
|
1978
1996
|
showSafeArea = false,
|
|
1979
1997
|
showSelectionGlow = false,
|
|
1998
|
+
toneMapping = "none",
|
|
1980
1999
|
onPointerMissed
|
|
1981
2000
|
}) {
|
|
1982
|
-
const ctx = (0,
|
|
1983
|
-
(0,
|
|
2001
|
+
const ctx = (0, import_react10.useContext)(VizijContext);
|
|
2002
|
+
(0, import_react10.useEffect)(() => {
|
|
1984
2003
|
recordRenderCounter("canvasMountCount");
|
|
1985
2004
|
recordRenderCounter("mountedCanvasCount");
|
|
1986
2005
|
return () => {
|
|
@@ -1996,8 +2015,7 @@ function Vizij({
|
|
|
1996
2015
|
className,
|
|
1997
2016
|
onPointerMissed,
|
|
1998
2017
|
gl: {
|
|
1999
|
-
outputColorSpace:
|
|
2000
|
-
toneMapping: import_three2.NoToneMapping,
|
|
2018
|
+
outputColorSpace: import_three3.SRGBColorSpace,
|
|
2001
2019
|
antialias: true
|
|
2002
2020
|
},
|
|
2003
2021
|
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
@@ -2006,7 +2024,8 @@ function Vizij({
|
|
|
2006
2024
|
rootId,
|
|
2007
2025
|
namespace,
|
|
2008
2026
|
showSafeArea,
|
|
2009
|
-
showSelectionGlow
|
|
2027
|
+
showSelectionGlow,
|
|
2028
|
+
toneMapping
|
|
2010
2029
|
}
|
|
2011
2030
|
)
|
|
2012
2031
|
}
|
|
@@ -2019,8 +2038,7 @@ function Vizij({
|
|
|
2019
2038
|
className,
|
|
2020
2039
|
onPointerMissed,
|
|
2021
2040
|
gl: {
|
|
2022
|
-
outputColorSpace:
|
|
2023
|
-
toneMapping: import_three2.NoToneMapping,
|
|
2041
|
+
outputColorSpace: import_three3.SRGBColorSpace,
|
|
2024
2042
|
antialias: true
|
|
2025
2043
|
},
|
|
2026
2044
|
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
@@ -2029,7 +2047,8 @@ function Vizij({
|
|
|
2029
2047
|
rootId,
|
|
2030
2048
|
namespace,
|
|
2031
2049
|
showSafeArea,
|
|
2032
|
-
showSelectionGlow
|
|
2050
|
+
showSelectionGlow,
|
|
2051
|
+
toneMapping
|
|
2033
2052
|
}
|
|
2034
2053
|
)
|
|
2035
2054
|
}
|
|
@@ -2041,7 +2060,8 @@ function InnerVizij({
|
|
|
2041
2060
|
namespace = "default",
|
|
2042
2061
|
container,
|
|
2043
2062
|
showSafeArea,
|
|
2044
|
-
showSelectionGlow
|
|
2063
|
+
showSelectionGlow,
|
|
2064
|
+
toneMapping = "none"
|
|
2045
2065
|
}) {
|
|
2046
2066
|
const sceneParentSizing = container ? {
|
|
2047
2067
|
width: container.width * container.resolution,
|
|
@@ -2049,6 +2069,7 @@ function InnerVizij({
|
|
|
2049
2069
|
} : void 0;
|
|
2050
2070
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
2051
2071
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("ambientLight", { intensity: Math.PI / 2 }),
|
|
2072
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ToneMappingController, { mode: toneMapping }),
|
|
2052
2073
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2053
2074
|
import_drei3.OrthographicCamera,
|
|
2054
2075
|
{
|
|
@@ -2058,7 +2079,7 @@ function InnerVizij({
|
|
|
2058
2079
|
far: 1e3
|
|
2059
2080
|
}
|
|
2060
2081
|
),
|
|
2061
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2082
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react10.Suspense, { fallback: null, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2062
2083
|
World,
|
|
2063
2084
|
{
|
|
2064
2085
|
rootId,
|
|
@@ -2070,7 +2091,32 @@ function InnerVizij({
|
|
|
2070
2091
|
showSafeArea && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SafeAreaRenderer, { rootId })
|
|
2071
2092
|
] });
|
|
2072
2093
|
}
|
|
2073
|
-
var MemoizedInnerVizij = (0,
|
|
2094
|
+
var MemoizedInnerVizij = (0, import_react10.memo)(InnerVizij);
|
|
2095
|
+
function ToneMappingController({ mode }) {
|
|
2096
|
+
const gl = (0, import_fiber2.useThree)((state) => state.gl);
|
|
2097
|
+
const scene = (0, import_fiber2.useThree)((state) => state.scene);
|
|
2098
|
+
(0, import_react10.useEffect)(() => {
|
|
2099
|
+
const resolved = resolveToneMapping(mode);
|
|
2100
|
+
if (gl.toneMapping === resolved) {
|
|
2101
|
+
return;
|
|
2102
|
+
}
|
|
2103
|
+
gl.toneMapping = resolved;
|
|
2104
|
+
scene.traverse((object) => {
|
|
2105
|
+
const material = object.material;
|
|
2106
|
+
if (!material) {
|
|
2107
|
+
return;
|
|
2108
|
+
}
|
|
2109
|
+
if (Array.isArray(material)) {
|
|
2110
|
+
material.forEach((mat) => {
|
|
2111
|
+
mat.needsUpdate = true;
|
|
2112
|
+
});
|
|
2113
|
+
} else {
|
|
2114
|
+
material.needsUpdate = true;
|
|
2115
|
+
}
|
|
2116
|
+
});
|
|
2117
|
+
}, [gl, scene, mode]);
|
|
2118
|
+
return null;
|
|
2119
|
+
}
|
|
2074
2120
|
function InnerWorld({
|
|
2075
2121
|
rootId,
|
|
2076
2122
|
namespace = "default",
|
|
@@ -2087,7 +2133,7 @@ function InnerWorld({
|
|
|
2087
2133
|
camera: state.camera,
|
|
2088
2134
|
size: state.size
|
|
2089
2135
|
}));
|
|
2090
|
-
(0,
|
|
2136
|
+
(0, import_react10.useEffect)(() => {
|
|
2091
2137
|
const width = rootBounds.size.x;
|
|
2092
2138
|
const height = rootBounds.size.y;
|
|
2093
2139
|
if (camera && parentSizing === void 0 && camera.isOrthographicCamera) {
|
|
@@ -2130,7 +2176,7 @@ function InnerWorld({
|
|
|
2130
2176
|
)
|
|
2131
2177
|
] });
|
|
2132
2178
|
}
|
|
2133
|
-
var World = (0,
|
|
2179
|
+
var World = (0, import_react10.memo)(InnerWorld);
|
|
2134
2180
|
function SafeAreaRenderer({ rootId }) {
|
|
2135
2181
|
const rootBounds = useVizijStore((state) => {
|
|
2136
2182
|
const group = state.world[rootId];
|
|
@@ -2160,22 +2206,12 @@ var defaultRootBounds = {
|
|
|
2160
2206
|
size: { x: 5, y: 4 }
|
|
2161
2207
|
};
|
|
2162
2208
|
|
|
2163
|
-
// src/types/shape.ts
|
|
2164
|
-
var ShapeMaterial = /* @__PURE__ */ ((ShapeMaterial2) => {
|
|
2165
|
-
ShapeMaterial2["Standard"] = "standard";
|
|
2166
|
-
ShapeMaterial2["Phong"] = "phong";
|
|
2167
|
-
ShapeMaterial2["Basic"] = "basic";
|
|
2168
|
-
ShapeMaterial2["Lambert"] = "lambert";
|
|
2169
|
-
ShapeMaterial2["Normal"] = "normal";
|
|
2170
|
-
return ShapeMaterial2;
|
|
2171
|
-
})(ShapeMaterial || {});
|
|
2172
|
-
|
|
2173
2209
|
// src/hooks/use-vizij-store-subscription.ts
|
|
2174
|
-
var
|
|
2210
|
+
var import_react11 = require("react");
|
|
2175
2211
|
function useVizijStoreSubscription(selector, listener) {
|
|
2176
|
-
const store = (0,
|
|
2212
|
+
const store = (0, import_react11.useContext)(VizijContext);
|
|
2177
2213
|
if (!store) throw new Error("Missing VizijProvider in the tree");
|
|
2178
|
-
(0,
|
|
2214
|
+
(0, import_react11.useEffect)(() => {
|
|
2179
2215
|
const initialValue = selector(store.getState());
|
|
2180
2216
|
listener(initialValue);
|
|
2181
2217
|
return store.subscribe(selector, listener);
|
|
@@ -2183,17 +2219,17 @@ function useVizijStoreSubscription(selector, listener) {
|
|
|
2183
2219
|
}
|
|
2184
2220
|
|
|
2185
2221
|
// src/hooks/use-vizij-store-setter.ts
|
|
2186
|
-
var
|
|
2222
|
+
var import_react12 = require("react");
|
|
2187
2223
|
function useVizijStoreSetter() {
|
|
2188
|
-
const store = (0,
|
|
2224
|
+
const store = (0, import_react12.useContext)(VizijContext);
|
|
2189
2225
|
if (!store) throw new Error("Missing VizijProvider in the tree");
|
|
2190
2226
|
return store.setState;
|
|
2191
2227
|
}
|
|
2192
2228
|
|
|
2193
2229
|
// src/hooks/use-vizij-store-getter.ts
|
|
2194
|
-
var
|
|
2230
|
+
var import_react13 = require("react");
|
|
2195
2231
|
function useVizijStoreGetter() {
|
|
2196
|
-
const store = (0,
|
|
2232
|
+
const store = (0, import_react13.useContext)(VizijContext);
|
|
2197
2233
|
if (!store) throw new Error("Missing VizijProvider in the tree");
|
|
2198
2234
|
return store.getState;
|
|
2199
2235
|
}
|
|
@@ -2203,7 +2239,6 @@ var THREE5 = __toESM(require("three"));
|
|
|
2203
2239
|
var import_three_stdlib = require("three-stdlib");
|
|
2204
2240
|
|
|
2205
2241
|
// src/functions/gltf-loading/traverse-three.ts
|
|
2206
|
-
var import_react16 = require("react");
|
|
2207
2242
|
var THREE4 = __toESM(require("three"));
|
|
2208
2243
|
|
|
2209
2244
|
// src/functions/gltf-loading/map-features.ts
|
|
@@ -2229,28 +2264,27 @@ function mapFeatures(features) {
|
|
|
2229
2264
|
}
|
|
2230
2265
|
|
|
2231
2266
|
// src/functions/gltf-loading/import-scene.ts
|
|
2232
|
-
var
|
|
2267
|
+
var import_three6 = require("three");
|
|
2233
2268
|
|
|
2234
2269
|
// src/functions/gltf-loading/import-group.ts
|
|
2235
|
-
var
|
|
2270
|
+
var import_three5 = require("three");
|
|
2236
2271
|
var import_utils11 = require("@vizij/utils");
|
|
2237
2272
|
|
|
2238
|
-
// src/functions/util.ts
|
|
2239
|
-
var import_react15 = require("react");
|
|
2240
|
-
function namespaceArrayToRefs(namespaces) {
|
|
2241
|
-
return namespaces.reduce((acc, ns) => ({ ...acc, [ns]: (0, import_react15.createRef)() }), {});
|
|
2242
|
-
}
|
|
2243
|
-
|
|
2244
2273
|
// src/functions/gltf-loading/import-mesh.ts
|
|
2245
|
-
var
|
|
2274
|
+
var import_three4 = require("three");
|
|
2246
2275
|
var import_utils10 = require("@vizij/utils");
|
|
2247
2276
|
|
|
2248
2277
|
// src/functions/gltf-loading/import-geometry.ts
|
|
2249
2278
|
var import_utils9 = require("@vizij/utils");
|
|
2250
|
-
|
|
2279
|
+
|
|
2280
|
+
// src/functions/gltf-loading/morph-keys.ts
|
|
2281
|
+
function slugifyMorphName(name, fallbackIndex) {
|
|
2251
2282
|
const baseName = name && name.trim().length > 0 ? name.trim() : `morph_${fallbackIndex + 1}`;
|
|
2252
2283
|
const slug = baseName.toLowerCase().replace(/[^a-z0-9]+/gi, "_").replace(/^_+|_+$/g, "");
|
|
2253
|
-
|
|
2284
|
+
return slug.length > 0 ? slug : `morph_${fallbackIndex + 1}`;
|
|
2285
|
+
}
|
|
2286
|
+
function sanitizeMorphKey(name, fallbackIndex, used) {
|
|
2287
|
+
const safeBase = slugifyMorphName(name, fallbackIndex);
|
|
2254
2288
|
let candidate = safeBase;
|
|
2255
2289
|
let counter = 1;
|
|
2256
2290
|
while (used.has(candidate)) {
|
|
@@ -2259,6 +2293,12 @@ function sanitizeMorphKey(name, fallbackIndex, used) {
|
|
|
2259
2293
|
used.add(candidate);
|
|
2260
2294
|
return candidate;
|
|
2261
2295
|
}
|
|
2296
|
+
function deriveMorphFeatureKeys(names) {
|
|
2297
|
+
const used = /* @__PURE__ */ new Set();
|
|
2298
|
+
return names.map((name, index) => sanitizeMorphKey(name, index, used));
|
|
2299
|
+
}
|
|
2300
|
+
|
|
2301
|
+
// src/functions/gltf-loading/import-geometry.ts
|
|
2262
2302
|
function importGeometry(geometry, mesh) {
|
|
2263
2303
|
const features = {};
|
|
2264
2304
|
const animatableValues = {};
|
|
@@ -2300,8 +2340,8 @@ function importGeometry(geometry, mesh) {
|
|
|
2300
2340
|
}
|
|
2301
2341
|
|
|
2302
2342
|
// src/functions/gltf-loading/import-mesh.ts
|
|
2303
|
-
|
|
2304
|
-
function importMesh(mesh,
|
|
2343
|
+
import_three4.Object3D.DEFAULT_UP.set(0, 0, 1);
|
|
2344
|
+
function importMesh(mesh, colorLookup) {
|
|
2305
2345
|
let world = {};
|
|
2306
2346
|
let animatables = {};
|
|
2307
2347
|
let newColorLookup = {};
|
|
@@ -2470,7 +2510,7 @@ function importMesh(mesh, namespaces, colorLookup) {
|
|
|
2470
2510
|
const children = [];
|
|
2471
2511
|
mesh.children.forEach((child) => {
|
|
2472
2512
|
if (child.isMesh) {
|
|
2473
|
-
const [newWorldItems, newAnimatables, childId, newMeshColors] = importMesh(child,
|
|
2513
|
+
const [newWorldItems, newAnimatables, childId, newMeshColors] = importMesh(child, {
|
|
2474
2514
|
...colorLookup,
|
|
2475
2515
|
...newColorLookup
|
|
2476
2516
|
});
|
|
@@ -2479,7 +2519,7 @@ function importMesh(mesh, namespaces, colorLookup) {
|
|
|
2479
2519
|
animatables = { ...animatables, ...newAnimatables };
|
|
2480
2520
|
children.push(childId);
|
|
2481
2521
|
} else if (shouldImportAsGroupChild(child)) {
|
|
2482
|
-
const [newWorldItems, newAnimatables, childId, newMeshColors] = importGroup(child,
|
|
2522
|
+
const [newWorldItems, newAnimatables, childId, newMeshColors] = importGroup(child, {
|
|
2483
2523
|
...colorLookup,
|
|
2484
2524
|
...newColorLookup
|
|
2485
2525
|
});
|
|
@@ -2516,8 +2556,7 @@ function importMesh(mesh, namespaces, colorLookup) {
|
|
|
2516
2556
|
...materialIds.specular ? { specular: { animated: true, value: materialIds.specular } } : {},
|
|
2517
2557
|
...geometryFeatures
|
|
2518
2558
|
},
|
|
2519
|
-
children: children.length > 0 ? children : void 0
|
|
2520
|
-
refs: namespaceArrayToRefs(namespaces)
|
|
2559
|
+
children: children.length > 0 ? children : void 0
|
|
2521
2560
|
};
|
|
2522
2561
|
world = { ...world, [newShape.id]: newShape };
|
|
2523
2562
|
return [world, animatables, newShape.id, newColorLookup];
|
|
@@ -2558,8 +2597,8 @@ function shouldImportAsGroupChild(child) {
|
|
|
2558
2597
|
}
|
|
2559
2598
|
|
|
2560
2599
|
// src/functions/gltf-loading/import-group.ts
|
|
2561
|
-
|
|
2562
|
-
function importGroup(group,
|
|
2600
|
+
import_three5.Object3D.DEFAULT_UP.set(0, 0, 1);
|
|
2601
|
+
function importGroup(group, colorLookup, rootBounds) {
|
|
2563
2602
|
let world = {};
|
|
2564
2603
|
let animatables = {};
|
|
2565
2604
|
let newColorLookup = {};
|
|
@@ -2607,7 +2646,7 @@ function importGroup(group, namespaces, colorLookup, rootBounds) {
|
|
|
2607
2646
|
animatables = { ...animatables, [scaleAnimatable.id]: scaleAnimatable };
|
|
2608
2647
|
group.children.forEach((child) => {
|
|
2609
2648
|
if (child.isMesh) {
|
|
2610
|
-
const [newWorldItems, newAnimatables, childId, newMeshColors] = importMesh(child,
|
|
2649
|
+
const [newWorldItems, newAnimatables, childId, newMeshColors] = importMesh(child, {
|
|
2611
2650
|
...colorLookup,
|
|
2612
2651
|
...newColorLookup
|
|
2613
2652
|
});
|
|
@@ -2616,7 +2655,7 @@ function importGroup(group, namespaces, colorLookup, rootBounds) {
|
|
|
2616
2655
|
animatables = { ...animatables, ...newAnimatables };
|
|
2617
2656
|
children.push(childId);
|
|
2618
2657
|
} else if (shouldImportAsGroupChild2(child)) {
|
|
2619
|
-
const [newWorldItems, newAnimatables, childId, newMeshColors] = importGroup(child,
|
|
2658
|
+
const [newWorldItems, newAnimatables, childId, newMeshColors] = importGroup(child, {
|
|
2620
2659
|
...colorLookup,
|
|
2621
2660
|
...newColorLookup
|
|
2622
2661
|
});
|
|
@@ -2638,8 +2677,7 @@ function importGroup(group, namespaces, colorLookup, rootBounds) {
|
|
|
2638
2677
|
},
|
|
2639
2678
|
root: Boolean(rootBounds),
|
|
2640
2679
|
rootBounds,
|
|
2641
|
-
children
|
|
2642
|
-
refs: namespaceArrayToRefs(namespaces)
|
|
2680
|
+
children
|
|
2643
2681
|
};
|
|
2644
2682
|
world = { ...world, [newGroup.id]: newGroup };
|
|
2645
2683
|
return [world, animatables, newGroup.id, newColorLookup];
|
|
@@ -2664,13 +2702,12 @@ function shouldImportAsGroupChild2(child) {
|
|
|
2664
2702
|
}
|
|
2665
2703
|
|
|
2666
2704
|
// src/functions/gltf-loading/import-scene.ts
|
|
2667
|
-
|
|
2668
|
-
function importScene(scene,
|
|
2705
|
+
import_three6.Object3D.DEFAULT_UP.set(0, 0, 1);
|
|
2706
|
+
function importScene(scene, rootBounds) {
|
|
2669
2707
|
let world = {};
|
|
2670
2708
|
let animatables = {};
|
|
2671
2709
|
const [newWorldItems, newAnimatables] = importGroup(
|
|
2672
2710
|
scene,
|
|
2673
|
-
namespaces,
|
|
2674
2711
|
{},
|
|
2675
2712
|
rootBounds
|
|
2676
2713
|
);
|
|
@@ -2681,7 +2718,7 @@ function importScene(scene, namespaces, rootBounds) {
|
|
|
2681
2718
|
|
|
2682
2719
|
// src/functions/gltf-loading/traverse-three.ts
|
|
2683
2720
|
THREE4.Object3D.DEFAULT_UP.set(0, 0, 1);
|
|
2684
|
-
function traverseThree(group,
|
|
2721
|
+
function traverseThree(group, aggressiveImport = false, rootBounds) {
|
|
2685
2722
|
const worldData = {};
|
|
2686
2723
|
const animatableData = {};
|
|
2687
2724
|
let hasRobotData = false;
|
|
@@ -2704,11 +2741,7 @@ function traverseThree(group, namespaces, aggressiveImport = false, rootBounds)
|
|
|
2704
2741
|
switch (data.type) {
|
|
2705
2742
|
case "group":
|
|
2706
2743
|
loadedData = {
|
|
2707
|
-
...data
|
|
2708
|
-
refs: namespaces.reduce(
|
|
2709
|
-
(acc, ns) => ({ ...acc, [ns]: (0, import_react16.createRef)() }),
|
|
2710
|
-
{}
|
|
2711
|
-
)
|
|
2744
|
+
...data
|
|
2712
2745
|
};
|
|
2713
2746
|
[mappedFeatures, animatableValues] = mapFeatures(data.features);
|
|
2714
2747
|
isGroupFeatures(mappedFeatures);
|
|
@@ -2719,11 +2752,7 @@ function traverseThree(group, namespaces, aggressiveImport = false, rootBounds)
|
|
|
2719
2752
|
case "shape":
|
|
2720
2753
|
loadedData = {
|
|
2721
2754
|
...data,
|
|
2722
|
-
geometry: child.geometry
|
|
2723
|
-
refs: namespaces.reduce(
|
|
2724
|
-
(acc, ns) => ({ ...acc, [ns]: (0, import_react16.createRef)() }),
|
|
2725
|
-
{}
|
|
2726
|
-
)
|
|
2755
|
+
geometry: child.geometry
|
|
2727
2756
|
};
|
|
2728
2757
|
[mappedFeatures, animatableValues] = mapFeatures(data.features);
|
|
2729
2758
|
isShapeFeatures(mappedFeatures);
|
|
@@ -2733,11 +2762,7 @@ function traverseThree(group, namespaces, aggressiveImport = false, rootBounds)
|
|
|
2733
2762
|
break;
|
|
2734
2763
|
case "ellipse":
|
|
2735
2764
|
loadedData = {
|
|
2736
|
-
...data
|
|
2737
|
-
refs: namespaces.reduce(
|
|
2738
|
-
(acc, ns) => ({ ...acc, [ns]: (0, import_react16.createRef)() }),
|
|
2739
|
-
{}
|
|
2740
|
-
)
|
|
2765
|
+
...data
|
|
2741
2766
|
};
|
|
2742
2767
|
[mappedFeatures, animatableValues] = mapFeatures(data.features);
|
|
2743
2768
|
isEllipseFeatures(mappedFeatures);
|
|
@@ -2747,11 +2772,7 @@ function traverseThree(group, namespaces, aggressiveImport = false, rootBounds)
|
|
|
2747
2772
|
break;
|
|
2748
2773
|
case "rectangle":
|
|
2749
2774
|
loadedData = {
|
|
2750
|
-
...data
|
|
2751
|
-
refs: namespaces.reduce(
|
|
2752
|
-
(acc, ns) => ({ ...acc, [ns]: (0, import_react16.createRef)() }),
|
|
2753
|
-
{}
|
|
2754
|
-
)
|
|
2775
|
+
...data
|
|
2755
2776
|
};
|
|
2756
2777
|
[mappedFeatures, animatableValues] = mapFeatures(data.features);
|
|
2757
2778
|
isRectangleFeatures(mappedFeatures);
|
|
@@ -2774,7 +2795,6 @@ function traverseThree(group, namespaces, aggressiveImport = false, rootBounds)
|
|
|
2774
2795
|
}
|
|
2775
2796
|
const [newWorldData, newAnimatableData] = importScene(
|
|
2776
2797
|
group,
|
|
2777
|
-
namespaces,
|
|
2778
2798
|
derivedRootBounds
|
|
2779
2799
|
);
|
|
2780
2800
|
Object.assign(worldData, newWorldData);
|
|
@@ -3490,16 +3510,6 @@ async function resolveParserJson(parserJson, fallback) {
|
|
|
3490
3510
|
return fromArrayBuffer;
|
|
3491
3511
|
}
|
|
3492
3512
|
}
|
|
3493
|
-
if (fallback.blob) {
|
|
3494
|
-
try {
|
|
3495
|
-
const blobBuffer = typeof fallback.blob.arrayBuffer === "function" ? await fallback.blob.arrayBuffer() : await new Response(fallback.blob).arrayBuffer();
|
|
3496
|
-
const fromBlob = parseGlbJsonChunk(blobBuffer);
|
|
3497
|
-
if (fromBlob && typeof fromBlob === "object") {
|
|
3498
|
-
return fromBlob;
|
|
3499
|
-
}
|
|
3500
|
-
} catch {
|
|
3501
|
-
}
|
|
3502
|
-
}
|
|
3503
3513
|
if (fallback.url && typeof fetch === "function") {
|
|
3504
3514
|
try {
|
|
3505
3515
|
const response = await fetch(fallback.url);
|
|
@@ -3515,73 +3525,21 @@ async function resolveParserJson(parserJson, fallback) {
|
|
|
3515
3525
|
}
|
|
3516
3526
|
return parserJson;
|
|
3517
3527
|
}
|
|
3518
|
-
async function loadGLTF(url,
|
|
3519
|
-
const asset = await
|
|
3520
|
-
|
|
3521
|
-
|
|
3528
|
+
async function loadGLTF(url, aggressiveImport = false, rootBounds) {
|
|
3529
|
+
const asset = await loadGLTFWithBundle(url, aggressiveImport, rootBounds);
|
|
3530
|
+
return [asset.world, asset.animatables, asset.animations];
|
|
3531
|
+
}
|
|
3532
|
+
async function loadGLTFFromBlob(blob, aggressiveImport = false, rootBounds) {
|
|
3533
|
+
const asset = await loadGLTFFromBlobWithBundle(
|
|
3534
|
+
blob,
|
|
3522
3535
|
aggressiveImport,
|
|
3523
|
-
rootBounds
|
|
3524
|
-
"url"
|
|
3536
|
+
rootBounds
|
|
3525
3537
|
);
|
|
3526
3538
|
return [asset.world, asset.animatables, asset.animations];
|
|
3527
3539
|
}
|
|
3528
|
-
|
|
3529
|
-
const actualizedNamespaces = namespaces.length > 0 ? namespaces : ["default"];
|
|
3530
|
-
if (typeof URL !== "undefined" && typeof URL.createObjectURL === "function") {
|
|
3531
|
-
const objectUrl = URL.createObjectURL(blob);
|
|
3532
|
-
try {
|
|
3533
|
-
const asset = await loadGLTFWithBundleInternal(
|
|
3534
|
-
objectUrl,
|
|
3535
|
-
actualizedNamespaces,
|
|
3536
|
-
aggressiveImport,
|
|
3537
|
-
rootBounds,
|
|
3538
|
-
"blob",
|
|
3539
|
-
{ blob }
|
|
3540
|
-
);
|
|
3541
|
-
return [asset.world, asset.animatables, asset.animations];
|
|
3542
|
-
} finally {
|
|
3543
|
-
URL.revokeObjectURL(objectUrl);
|
|
3544
|
-
}
|
|
3545
|
-
}
|
|
3546
|
-
const arrayBuffer = typeof blob.arrayBuffer === "function" ? await blob.arrayBuffer() : await new Response(blob).arrayBuffer();
|
|
3547
|
-
return new Promise((resolve, reject) => {
|
|
3548
|
-
const loader = createTrackedGLTFLoader();
|
|
3549
|
-
loader.parse(
|
|
3550
|
-
arrayBuffer,
|
|
3551
|
-
"",
|
|
3552
|
-
async (gltf) => {
|
|
3553
|
-
try {
|
|
3554
|
-
const parserJson = await resolveParserJson(
|
|
3555
|
-
gltf?.parser?.json,
|
|
3556
|
-
{ arrayBuffer }
|
|
3557
|
-
);
|
|
3558
|
-
const asset = parseScene(
|
|
3559
|
-
gltf.scene,
|
|
3560
|
-
actualizedNamespaces,
|
|
3561
|
-
aggressiveImport,
|
|
3562
|
-
rootBounds,
|
|
3563
|
-
parserJson,
|
|
3564
|
-
gltf.animations
|
|
3565
|
-
);
|
|
3566
|
-
resolve([asset.world, asset.animatables, asset.animations]);
|
|
3567
|
-
} catch (error) {
|
|
3568
|
-
if (error instanceof Error) {
|
|
3569
|
-
reject(error);
|
|
3570
|
-
} else {
|
|
3571
|
-
reject(new Error(String(error)));
|
|
3572
|
-
}
|
|
3573
|
-
}
|
|
3574
|
-
},
|
|
3575
|
-
(error) => {
|
|
3576
|
-
reject(new Error(`Error loading GLTF: ${error.message}`));
|
|
3577
|
-
}
|
|
3578
|
-
);
|
|
3579
|
-
});
|
|
3580
|
-
}
|
|
3581
|
-
function parseScene(scene, namespaces, aggressiveImport, rootBounds, parserJson, clips) {
|
|
3540
|
+
function parseScene(scene, aggressiveImport, rootBounds, parserJson, clips) {
|
|
3582
3541
|
const [world, animatables] = traverseThree(
|
|
3583
3542
|
scene,
|
|
3584
|
-
namespaces,
|
|
3585
3543
|
aggressiveImport,
|
|
3586
3544
|
rootBounds
|
|
3587
3545
|
);
|
|
@@ -3596,125 +3554,45 @@ function createTrackedGLTFLoader() {
|
|
|
3596
3554
|
modelLoader.setDRACOLoader(new import_three_stdlib.DRACOLoader());
|
|
3597
3555
|
return modelLoader;
|
|
3598
3556
|
}
|
|
3599
|
-
async function
|
|
3600
|
-
|
|
3601
|
-
recordRenderCounter("gltfUrlLoadCount");
|
|
3602
|
-
} else {
|
|
3603
|
-
recordRenderCounter("gltfBlobLoadCount");
|
|
3604
|
-
}
|
|
3557
|
+
async function loadGLTFWithBundle(url, aggressiveImport = false, rootBounds, parserJsonFallback) {
|
|
3558
|
+
recordRenderCounter("gltfUrlLoadCount");
|
|
3605
3559
|
const modelLoader = createTrackedGLTFLoader();
|
|
3606
3560
|
const modelData = await modelLoader.loadAsync(url);
|
|
3607
3561
|
const parserJson = await resolveParserJson(modelData?.parser?.json, {
|
|
3608
3562
|
url,
|
|
3609
3563
|
...parserJsonFallback
|
|
3610
3564
|
});
|
|
3611
|
-
const actualizedNamespaces = namespaces.length > 0 ? namespaces : ["default"];
|
|
3612
3565
|
return parseScene(
|
|
3613
3566
|
modelData.scene,
|
|
3614
|
-
actualizedNamespaces,
|
|
3615
3567
|
aggressiveImport,
|
|
3616
3568
|
rootBounds,
|
|
3617
3569
|
parserJson,
|
|
3618
3570
|
modelData.animations
|
|
3619
3571
|
);
|
|
3620
3572
|
}
|
|
3621
|
-
async function
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3573
|
+
async function loadGLTFFromBlobWithBundle(blob, aggressiveImport = false, rootBounds) {
|
|
3574
|
+
recordRenderCounter("gltfBlobLoadCount");
|
|
3575
|
+
const arrayBuffer = await blob.arrayBuffer();
|
|
3576
|
+
const loader = createTrackedGLTFLoader();
|
|
3577
|
+
const gltf = await new Promise((resolve, reject) => {
|
|
3578
|
+
loader.parse(arrayBuffer, "", resolve, (error) => {
|
|
3579
|
+
reject(new Error(`Error loading GLTF: ${error.message}`));
|
|
3580
|
+
});
|
|
3581
|
+
});
|
|
3582
|
+
const parserJson = await resolveParserJson(gltf?.parser?.json, {
|
|
3583
|
+
arrayBuffer
|
|
3584
|
+
});
|
|
3585
|
+
return parseScene(
|
|
3586
|
+
gltf.scene,
|
|
3625
3587
|
aggressiveImport,
|
|
3626
3588
|
rootBounds,
|
|
3627
|
-
|
|
3628
|
-
|
|
3589
|
+
parserJson,
|
|
3590
|
+
gltf.animations
|
|
3629
3591
|
);
|
|
3630
3592
|
}
|
|
3631
|
-
async function loadGLTFFromBlobWithBundle(blob, namespaces, aggressiveImport = false, rootBounds) {
|
|
3632
|
-
const actualizedNamespaces = namespaces.length > 0 ? namespaces : ["default"];
|
|
3633
|
-
if (typeof URL !== "undefined" && typeof URL.createObjectURL === "function") {
|
|
3634
|
-
const objectUrl = URL.createObjectURL(blob);
|
|
3635
|
-
try {
|
|
3636
|
-
return await loadGLTFWithBundleInternal(
|
|
3637
|
-
objectUrl,
|
|
3638
|
-
actualizedNamespaces,
|
|
3639
|
-
aggressiveImport,
|
|
3640
|
-
rootBounds,
|
|
3641
|
-
"blob",
|
|
3642
|
-
{ blob }
|
|
3643
|
-
);
|
|
3644
|
-
} finally {
|
|
3645
|
-
URL.revokeObjectURL(objectUrl);
|
|
3646
|
-
}
|
|
3647
|
-
}
|
|
3648
|
-
const arrayBuffer = typeof blob.arrayBuffer === "function" ? await blob.arrayBuffer() : await new Response(blob).arrayBuffer();
|
|
3649
|
-
return new Promise((resolve, reject) => {
|
|
3650
|
-
const loader = createTrackedGLTFLoader();
|
|
3651
|
-
loader.parse(
|
|
3652
|
-
arrayBuffer,
|
|
3653
|
-
"",
|
|
3654
|
-
async (gltf) => {
|
|
3655
|
-
try {
|
|
3656
|
-
const parserJson = await resolveParserJson(
|
|
3657
|
-
gltf?.parser?.json,
|
|
3658
|
-
{ arrayBuffer }
|
|
3659
|
-
);
|
|
3660
|
-
const asset = parseScene(
|
|
3661
|
-
gltf.scene,
|
|
3662
|
-
actualizedNamespaces,
|
|
3663
|
-
aggressiveImport,
|
|
3664
|
-
rootBounds,
|
|
3665
|
-
parserJson,
|
|
3666
|
-
gltf.animations
|
|
3667
|
-
);
|
|
3668
|
-
resolve(asset);
|
|
3669
|
-
} catch (error) {
|
|
3670
|
-
if (error instanceof Error) {
|
|
3671
|
-
reject(error);
|
|
3672
|
-
} else {
|
|
3673
|
-
reject(new Error(String(error)));
|
|
3674
|
-
}
|
|
3675
|
-
}
|
|
3676
|
-
},
|
|
3677
|
-
(error) => {
|
|
3678
|
-
reject(new Error(`Error loading GLTF: ${error.message}`));
|
|
3679
|
-
}
|
|
3680
|
-
);
|
|
3681
|
-
});
|
|
3682
|
-
}
|
|
3683
|
-
|
|
3684
|
-
// src/functions/load-gltf-blob.ts
|
|
3685
|
-
var import_three_stdlib2 = require("three-stdlib");
|
|
3686
|
-
var loadGltfFromBlob = (blob, namespaces) => {
|
|
3687
|
-
recordRenderCounter("gltfLoadCount");
|
|
3688
|
-
recordRenderCounter("gltfBlobLoadCount");
|
|
3689
|
-
recordRenderCounter("dracoLoaderCreationCount");
|
|
3690
|
-
return new Promise((resolve, reject) => {
|
|
3691
|
-
const loader = new import_three_stdlib2.GLTFLoader();
|
|
3692
|
-
loader.setDRACOLoader(new import_three_stdlib2.DRACOLoader());
|
|
3693
|
-
const reader = new FileReader();
|
|
3694
|
-
reader.onload = () => {
|
|
3695
|
-
const arrayBuffer = reader.result;
|
|
3696
|
-
loader.parse(
|
|
3697
|
-
arrayBuffer,
|
|
3698
|
-
"",
|
|
3699
|
-
// Base path for resolving external resources
|
|
3700
|
-
(gltf) => {
|
|
3701
|
-
const actualizedNamespaces = namespaces.length > 0 ? namespaces : ["default"];
|
|
3702
|
-
resolve(traverseThree(gltf.scene, actualizedNamespaces));
|
|
3703
|
-
},
|
|
3704
|
-
(error) => {
|
|
3705
|
-
reject(new Error(`Error loading GLTF: ${error.message}`));
|
|
3706
|
-
}
|
|
3707
|
-
);
|
|
3708
|
-
};
|
|
3709
|
-
reader.onerror = () => {
|
|
3710
|
-
reject(new Error("Failed to read Blob as ArrayBuffer."));
|
|
3711
|
-
};
|
|
3712
|
-
reader.readAsArrayBuffer(blob);
|
|
3713
|
-
});
|
|
3714
|
-
};
|
|
3715
3593
|
|
|
3716
3594
|
// src/functions/export.ts
|
|
3717
|
-
var
|
|
3595
|
+
var import_three_stdlib2 = require("three-stdlib");
|
|
3718
3596
|
var THREE6 = __toESM(require("three"));
|
|
3719
3597
|
THREE6.Object3D.DEFAULT_UP.set(0, 0, 1);
|
|
3720
3598
|
function normalizeExportError(error) {
|
|
@@ -3726,17 +3604,6 @@ function normalizeExportError(error) {
|
|
|
3726
3604
|
}
|
|
3727
3605
|
return new Error("Failed to export scene.");
|
|
3728
3606
|
}
|
|
3729
|
-
function triggerBlobDownload(blob, filename) {
|
|
3730
|
-
const url = URL.createObjectURL(blob);
|
|
3731
|
-
const link = document.createElement("a");
|
|
3732
|
-
link.href = url;
|
|
3733
|
-
link.download = filename;
|
|
3734
|
-
link.style.display = "none";
|
|
3735
|
-
document.body.appendChild(link);
|
|
3736
|
-
link.click();
|
|
3737
|
-
document.body.removeChild(link);
|
|
3738
|
-
setTimeout(() => URL.revokeObjectURL(url), 0);
|
|
3739
|
-
}
|
|
3740
3607
|
var GLB_MAGIC2 = 1179937895;
|
|
3741
3608
|
var GLB_VERSION2 = 2;
|
|
3742
3609
|
var GLB_JSON_CHUNK_TYPE2 = 1313821514;
|
|
@@ -3818,7 +3685,7 @@ function normalizeExportedSceneJson(json, fallbackSceneName) {
|
|
|
3818
3685
|
}
|
|
3819
3686
|
return changed;
|
|
3820
3687
|
}
|
|
3821
|
-
function
|
|
3688
|
+
function patchGlbJson(buffer, mutate) {
|
|
3822
3689
|
if (buffer.byteLength < GLB_HEADER_BYTES2 + GLB_CHUNK_HEADER_BYTES2) {
|
|
3823
3690
|
return buffer;
|
|
3824
3691
|
}
|
|
@@ -3848,8 +3715,7 @@ function sanitizeExportedGlb(buffer, fallbackSceneName) {
|
|
|
3848
3715
|
} catch {
|
|
3849
3716
|
return buffer;
|
|
3850
3717
|
}
|
|
3851
|
-
|
|
3852
|
-
if (!changed) {
|
|
3718
|
+
if (!mutate(jsonPayload)) {
|
|
3853
3719
|
return buffer;
|
|
3854
3720
|
}
|
|
3855
3721
|
const encodedJson = new TextEncoder().encode(JSON.stringify(jsonPayload));
|
|
@@ -3871,12 +3737,42 @@ function sanitizeExportedGlb(buffer, fallbackSceneName) {
|
|
|
3871
3737
|
sanitizedBytes.set(remainingChunks, jsonChunkStart + paddedJsonLength);
|
|
3872
3738
|
return sanitized;
|
|
3873
3739
|
}
|
|
3874
|
-
function
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3740
|
+
function sanitizeExportedGlb(buffer, fallbackSceneName) {
|
|
3741
|
+
return patchGlbJson(
|
|
3742
|
+
buffer,
|
|
3743
|
+
(json) => normalizeExportedSceneJson(json, fallbackSceneName)
|
|
3744
|
+
);
|
|
3745
|
+
}
|
|
3746
|
+
function patchVizijBundleMetadata(glb, metadata) {
|
|
3747
|
+
return patchGlbJson(glb, (json) => {
|
|
3748
|
+
const carriers = [];
|
|
3749
|
+
const rootExtensions = json.extensions;
|
|
3750
|
+
if (rootExtensions && typeof rootExtensions === "object") {
|
|
3751
|
+
carriers.push(rootExtensions);
|
|
3752
|
+
}
|
|
3753
|
+
const nodes = Array.isArray(json.nodes) ? json.nodes : [];
|
|
3754
|
+
for (const node of nodes) {
|
|
3755
|
+
const extensions = node?.extensions;
|
|
3756
|
+
if (extensions && typeof extensions === "object") {
|
|
3757
|
+
carriers.push(extensions);
|
|
3758
|
+
}
|
|
3759
|
+
}
|
|
3760
|
+
let patched = false;
|
|
3761
|
+
for (const extensions of carriers) {
|
|
3762
|
+
const bundle = extensions.VIZIJ_bundle;
|
|
3763
|
+
if (!bundle || typeof bundle !== "object") {
|
|
3764
|
+
continue;
|
|
3765
|
+
}
|
|
3766
|
+
const record = bundle;
|
|
3767
|
+
const existing = record.metadata && typeof record.metadata === "object" ? record.metadata : {};
|
|
3768
|
+
record.metadata = { ...existing, ...metadata };
|
|
3769
|
+
patched = true;
|
|
3770
|
+
}
|
|
3771
|
+
return patched;
|
|
3772
|
+
});
|
|
3773
|
+
}
|
|
3774
|
+
async function exportScene(root, options = {}) {
|
|
3775
|
+
const exporter = new import_three_stdlib2.GLTFExporter();
|
|
3880
3776
|
exporter.register(() => ({
|
|
3881
3777
|
writeMesh(mesh, meshDef) {
|
|
3882
3778
|
const meshName = mesh.name?.trim() || mesh.geometry?.name?.trim() || void 0;
|
|
@@ -3885,82 +3781,324 @@ function exportScene(data, fileNameOrOptions = "scene.glb") {
|
|
|
3885
3781
|
}
|
|
3886
3782
|
}
|
|
3887
3783
|
}));
|
|
3888
|
-
const
|
|
3889
|
-
const exportRoot = sourceRoot instanceof THREE6.Scene ? sourceRoot : sourceRoot.clone(true);
|
|
3784
|
+
const exportRoot = root instanceof THREE6.Scene ? root : root.clone(true);
|
|
3890
3785
|
const exportTarget = exportRoot instanceof THREE6.Scene ? exportRoot : (() => {
|
|
3891
3786
|
const scene = new THREE6.Scene();
|
|
3892
|
-
scene.name =
|
|
3787
|
+
scene.name = root.name?.trim() || "Scene";
|
|
3893
3788
|
scene.add(exportRoot);
|
|
3894
3789
|
return scene;
|
|
3895
3790
|
})();
|
|
3896
|
-
const detachBundle =
|
|
3897
|
-
};
|
|
3898
|
-
const binary = options.binary ?? true;
|
|
3899
|
-
const exporterOptions = {
|
|
3900
|
-
trs: true,
|
|
3901
|
-
onlyVisible: false,
|
|
3902
|
-
binary,
|
|
3903
|
-
includeCustomExtensions: true
|
|
3791
|
+
const detachBundle = options.bundle ? applyVizijBundle(exportRoot, options.bundle) : () => {
|
|
3904
3792
|
};
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
}
|
|
3793
|
+
const animations = (options.animations ?? []).filter(Boolean);
|
|
3794
|
+
let gltf;
|
|
3908
3795
|
try {
|
|
3909
|
-
exporter.
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
return;
|
|
3917
|
-
}
|
|
3918
|
-
const sanitizedGltf = sanitizeExportedGlb(
|
|
3919
|
-
gltf,
|
|
3920
|
-
data.name?.trim() || void 0
|
|
3921
|
-
);
|
|
3922
|
-
const trimmed = fileName.trim();
|
|
3923
|
-
const safeFileName = trimmed.length > 0 ? trimmed : "scene.glb";
|
|
3924
|
-
const downloadName = safeFileName.toLowerCase().endsWith(".glb") ? safeFileName : `${safeFileName}.glb`;
|
|
3925
|
-
triggerBlobDownload(
|
|
3926
|
-
new Blob([sanitizedGltf], {
|
|
3927
|
-
type: "application/octet-stream"
|
|
3928
|
-
}),
|
|
3929
|
-
downloadName
|
|
3930
|
-
);
|
|
3931
|
-
options.onComplete?.();
|
|
3932
|
-
},
|
|
3933
|
-
(error) => {
|
|
3934
|
-
detachBundle();
|
|
3935
|
-
options.onError?.(normalizeExportError(error));
|
|
3936
|
-
},
|
|
3937
|
-
exporterOptions
|
|
3938
|
-
);
|
|
3796
|
+
gltf = await exporter.parseAsync(exportTarget, {
|
|
3797
|
+
trs: true,
|
|
3798
|
+
onlyVisible: false,
|
|
3799
|
+
binary: true,
|
|
3800
|
+
includeCustomExtensions: true,
|
|
3801
|
+
...animations.length > 0 ? { animations } : {}
|
|
3802
|
+
});
|
|
3939
3803
|
} catch (error) {
|
|
3804
|
+
throw normalizeExportError(error);
|
|
3805
|
+
} finally {
|
|
3940
3806
|
detachBundle();
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
throw
|
|
3807
|
+
}
|
|
3808
|
+
if (!(gltf instanceof ArrayBuffer)) {
|
|
3809
|
+
throw new Error("Failed to export scene.");
|
|
3810
|
+
}
|
|
3811
|
+
return sanitizeExportedGlb(gltf, root.name?.trim() || void 0);
|
|
3812
|
+
}
|
|
3813
|
+
|
|
3814
|
+
// src/functions/build-scene-graph.ts
|
|
3815
|
+
var THREE7 = __toESM(require("three"));
|
|
3816
|
+
var import_utils14 = require("@vizij/utils");
|
|
3817
|
+
THREE7.Object3D.DEFAULT_UP.set(0, 0, 1);
|
|
3818
|
+
function buildSceneGraph(world, animatables, rootId) {
|
|
3819
|
+
const entry = world[rootId];
|
|
3820
|
+
if (!entry) {
|
|
3821
|
+
throw new Error(`The world has no element "${rootId}".`);
|
|
3822
|
+
}
|
|
3823
|
+
const used = {};
|
|
3824
|
+
for (const feature of Object.values(entry.features)) {
|
|
3825
|
+
if (feature.animated) {
|
|
3826
|
+
used[feature.value] = animatableOf(animatables, feature.value);
|
|
3827
|
+
}
|
|
3828
|
+
}
|
|
3829
|
+
const robotData = createStoredRenderable(entry, used);
|
|
3830
|
+
switch (entry.type) {
|
|
3831
|
+
case "group": {
|
|
3832
|
+
const object = new THREE7.Group();
|
|
3833
|
+
object.name = entry.name;
|
|
3834
|
+
object.userData = { gltfExtensions: { RobotData: robotData } };
|
|
3835
|
+
applyFeatures(entry.features, animatables, groupTransform(object));
|
|
3836
|
+
for (const child of entry.children) {
|
|
3837
|
+
object.add(buildSceneGraph(world, animatables, child));
|
|
3838
|
+
}
|
|
3839
|
+
return object;
|
|
3840
|
+
}
|
|
3841
|
+
case "shape": {
|
|
3842
|
+
const geometry = entry.geometry.clone();
|
|
3843
|
+
if (entry.name) {
|
|
3844
|
+
geometry.name = entry.name;
|
|
3845
|
+
}
|
|
3846
|
+
const material = createMaterial(entry.material);
|
|
3847
|
+
material.name = deriveMaterialName(entry, used) ?? entry.name ?? "";
|
|
3848
|
+
const object = new THREE7.Mesh(geometry, material);
|
|
3849
|
+
object.name = entry.name;
|
|
3850
|
+
object.userData = { gltfExtensions: { RobotData: robotData } };
|
|
3851
|
+
applyFeatures(entry.features, animatables, {
|
|
3852
|
+
...shapeTransform(object),
|
|
3853
|
+
...materialFactors(material),
|
|
3854
|
+
...morphWeights(object, entry)
|
|
3855
|
+
});
|
|
3856
|
+
for (const child of entry.children ?? []) {
|
|
3857
|
+
object.add(buildSceneGraph(world, animatables, child));
|
|
3858
|
+
}
|
|
3859
|
+
return object;
|
|
3860
|
+
}
|
|
3861
|
+
default:
|
|
3862
|
+
throw new Error(
|
|
3863
|
+
`Element "${rootId}" is a ${entry.type}, which has no exported form.`
|
|
3864
|
+
);
|
|
3865
|
+
}
|
|
3866
|
+
}
|
|
3867
|
+
function animatableOf(animatables, id) {
|
|
3868
|
+
const animatable = animatables[id];
|
|
3869
|
+
if (!animatable) {
|
|
3870
|
+
throw new Error(`No animatable "${id}".`);
|
|
3871
|
+
}
|
|
3872
|
+
return animatable;
|
|
3873
|
+
}
|
|
3874
|
+
function applyFeatures(features, animatables, handlers) {
|
|
3875
|
+
for (const [key, handler] of Object.entries(handlers)) {
|
|
3876
|
+
const feature = features[key];
|
|
3877
|
+
if (!feature) {
|
|
3878
|
+
continue;
|
|
3879
|
+
}
|
|
3880
|
+
const value = feature.animated ? authoredDefault(animatableOf(animatables, feature.value)) : feature.value;
|
|
3881
|
+
if (value !== void 0) {
|
|
3882
|
+
handler(value);
|
|
3883
|
+
}
|
|
3884
|
+
}
|
|
3885
|
+
}
|
|
3886
|
+
function groupTransform(object) {
|
|
3887
|
+
return {
|
|
3888
|
+
translation: (value) => {
|
|
3889
|
+
if ((0, import_utils14.instanceOfRawVector3)(value)) {
|
|
3890
|
+
object.position.set(value.x, value.y, value.z);
|
|
3891
|
+
} else if ((0, import_utils14.instanceOfRawVector2)(value)) {
|
|
3892
|
+
object.position.set(value.x, value.y, object.position.z);
|
|
3893
|
+
}
|
|
3894
|
+
},
|
|
3895
|
+
rotation: (value) => {
|
|
3896
|
+
if ((0, import_utils14.instanceOfRawEuler)(value)) {
|
|
3897
|
+
object.rotation.set(value.x, value.y, value.z, "ZYX");
|
|
3898
|
+
} else if ((0, import_utils14.instanceOfRawNumber)(value)) {
|
|
3899
|
+
object.rotation.set(0, 0, 0);
|
|
3900
|
+
object.rotateZ(value);
|
|
3901
|
+
}
|
|
3902
|
+
},
|
|
3903
|
+
scale: (value) => {
|
|
3904
|
+
if ((0, import_utils14.instanceOfRawVector3)(value)) {
|
|
3905
|
+
if (value.x === null || value.y === null || value.z === null) {
|
|
3906
|
+
object.scale.set(0.1, 0.1, 0.1);
|
|
3907
|
+
} else {
|
|
3908
|
+
object.scale.set(value.x, value.y, value.z);
|
|
3909
|
+
}
|
|
3910
|
+
} else if ((0, import_utils14.instanceOfRawNumber)(value)) {
|
|
3911
|
+
object.scale.set(value, value, value);
|
|
3912
|
+
} else {
|
|
3913
|
+
object.scale.set(1, 1, 1);
|
|
3914
|
+
}
|
|
3915
|
+
}
|
|
3916
|
+
};
|
|
3917
|
+
}
|
|
3918
|
+
function shapeTransform(object) {
|
|
3919
|
+
return {
|
|
3920
|
+
translation: (value) => {
|
|
3921
|
+
if ((0, import_utils14.instanceOfRawVector3)(value)) {
|
|
3922
|
+
object.position.set(value.x, value.y, value.z);
|
|
3923
|
+
}
|
|
3924
|
+
},
|
|
3925
|
+
rotation: (value) => {
|
|
3926
|
+
if ((0, import_utils14.instanceOfRawEuler)(value)) {
|
|
3927
|
+
object.rotation.set(value.x, value.y, value.z, "ZYX");
|
|
3928
|
+
}
|
|
3929
|
+
},
|
|
3930
|
+
scale: (value) => {
|
|
3931
|
+
if ((0, import_utils14.instanceOfRawVector3)(value)) {
|
|
3932
|
+
object.scale.set(value.x, value.y, value.z);
|
|
3933
|
+
} else if ((0, import_utils14.instanceOfRawNumber)(value)) {
|
|
3934
|
+
object.scale.set(value, value, value);
|
|
3935
|
+
} else {
|
|
3936
|
+
object.scale.set(1, 1, 1);
|
|
3937
|
+
}
|
|
3938
|
+
}
|
|
3939
|
+
};
|
|
3940
|
+
}
|
|
3941
|
+
function materialFactors(material) {
|
|
3942
|
+
const standard = material;
|
|
3943
|
+
const phong = material;
|
|
3944
|
+
return {
|
|
3945
|
+
opacity: (value) => {
|
|
3946
|
+
if ((0, import_utils14.instanceOfRawNumber)(value)) {
|
|
3947
|
+
material.opacity = value;
|
|
3948
|
+
material.transparent = value < 1;
|
|
3949
|
+
}
|
|
3950
|
+
},
|
|
3951
|
+
color: (value) => {
|
|
3952
|
+
if (!standard.color) {
|
|
3953
|
+
return;
|
|
3954
|
+
}
|
|
3955
|
+
if ((0, import_utils14.instanceOfRawRGB)(value)) {
|
|
3956
|
+
standard.color.setRGB(value.r, value.g, value.b);
|
|
3957
|
+
} else if ((0, import_utils14.instanceOfRawVector3)(value)) {
|
|
3958
|
+
standard.color.setRGB(value.x, value.y, value.z);
|
|
3959
|
+
} else if ((0, import_utils14.instanceOfRawHSL)(value)) {
|
|
3960
|
+
standard.color.setHSL(value.h, value.s, value.l);
|
|
3961
|
+
}
|
|
3962
|
+
},
|
|
3963
|
+
roughness: (value) => {
|
|
3964
|
+
if (standard.roughness !== void 0 && (0, import_utils14.instanceOfRawNumber)(value)) {
|
|
3965
|
+
standard.roughness = value;
|
|
3966
|
+
}
|
|
3967
|
+
},
|
|
3968
|
+
metalness: (value) => {
|
|
3969
|
+
if (standard.metalness !== void 0 && (0, import_utils14.instanceOfRawNumber)(value)) {
|
|
3970
|
+
standard.metalness = value;
|
|
3971
|
+
}
|
|
3972
|
+
},
|
|
3973
|
+
shininess: (value) => {
|
|
3974
|
+
if (phong.shininess !== void 0 && (0, import_utils14.instanceOfRawNumber)(value)) {
|
|
3975
|
+
phong.shininess = value;
|
|
3976
|
+
}
|
|
3977
|
+
},
|
|
3978
|
+
emissive: (value) => {
|
|
3979
|
+
if (standard.emissive && (0, import_utils14.instanceOfRawRGB)(value)) {
|
|
3980
|
+
standard.emissive.setRGB(value.r, value.g, value.b);
|
|
3981
|
+
}
|
|
3982
|
+
},
|
|
3983
|
+
emissiveIntensity: (value) => {
|
|
3984
|
+
if (standard.emissiveIntensity !== void 0 && (0, import_utils14.instanceOfRawNumber)(value)) {
|
|
3985
|
+
standard.emissiveIntensity = value;
|
|
3986
|
+
}
|
|
3987
|
+
},
|
|
3988
|
+
specular: (value) => {
|
|
3989
|
+
if (phong.specular && (0, import_utils14.instanceOfRawRGB)(value)) {
|
|
3990
|
+
phong.specular.setRGB(value.r, value.g, value.b);
|
|
3991
|
+
}
|
|
3992
|
+
}
|
|
3993
|
+
};
|
|
3994
|
+
}
|
|
3995
|
+
function morphWeights(object, shape) {
|
|
3996
|
+
const targets = shape.morphTargets ?? [];
|
|
3997
|
+
if (targets.length === 0) {
|
|
3998
|
+
return {};
|
|
3999
|
+
}
|
|
4000
|
+
const influences = targets.map(() => 0);
|
|
4001
|
+
object.morphTargetDictionary = Object.fromEntries(
|
|
4002
|
+
targets.map((target, index) => [target, index])
|
|
4003
|
+
);
|
|
4004
|
+
object.morphTargetInfluences = influences;
|
|
4005
|
+
return Object.fromEntries(
|
|
4006
|
+
targets.map((target, index) => [
|
|
4007
|
+
target,
|
|
4008
|
+
(value) => {
|
|
4009
|
+
if ((0, import_utils14.instanceOfRawNumber)(value)) {
|
|
4010
|
+
influences[index] = value;
|
|
4011
|
+
}
|
|
4012
|
+
}
|
|
4013
|
+
])
|
|
4014
|
+
);
|
|
4015
|
+
}
|
|
4016
|
+
function createMaterial(kind) {
|
|
4017
|
+
const parameters = { side: THREE7.DoubleSide };
|
|
4018
|
+
switch (kind) {
|
|
4019
|
+
case "basic" /* Basic */:
|
|
4020
|
+
return new THREE7.MeshBasicMaterial(parameters);
|
|
4021
|
+
case "lambert" /* Lambert */:
|
|
4022
|
+
return new THREE7.MeshLambertMaterial(parameters);
|
|
4023
|
+
case "phong" /* Phong */:
|
|
4024
|
+
return new THREE7.MeshPhongMaterial(parameters);
|
|
4025
|
+
case "normal" /* Normal */:
|
|
4026
|
+
return new THREE7.MeshNormalMaterial(parameters);
|
|
4027
|
+
case "standard" /* Standard */:
|
|
4028
|
+
return new THREE7.MeshStandardMaterial(parameters);
|
|
4029
|
+
}
|
|
4030
|
+
}
|
|
4031
|
+
var SCALAR_KEYS = ["f32", "f64", "i64", "i32", "u64", "u32", "float"];
|
|
4032
|
+
function scalarOf(value) {
|
|
4033
|
+
if (typeof value === "number") {
|
|
4034
|
+
return value;
|
|
4035
|
+
}
|
|
4036
|
+
if (value && typeof value === "object") {
|
|
4037
|
+
for (const key of SCALAR_KEYS) {
|
|
4038
|
+
const scalar = value[key];
|
|
4039
|
+
if (typeof scalar === "number") {
|
|
4040
|
+
return scalar;
|
|
4041
|
+
}
|
|
4042
|
+
}
|
|
4043
|
+
}
|
|
4044
|
+
return void 0;
|
|
4045
|
+
}
|
|
4046
|
+
function authoredDefault(animatable) {
|
|
4047
|
+
const value = animatable.default;
|
|
4048
|
+
const scalar = scalarOf(value);
|
|
4049
|
+
if (scalar !== void 0) {
|
|
4050
|
+
return scalar;
|
|
4051
|
+
}
|
|
4052
|
+
const fields = value?.struct?.fields;
|
|
4053
|
+
if (!Array.isArray(fields)) {
|
|
4054
|
+
return value;
|
|
4055
|
+
}
|
|
4056
|
+
const n = fields.map(
|
|
4057
|
+
(field) => scalarOf(field?.value) ?? 0
|
|
4058
|
+
);
|
|
4059
|
+
switch (animatable.type) {
|
|
4060
|
+
case "vector3":
|
|
4061
|
+
case "euler":
|
|
4062
|
+
return { x: n[0], y: n[1], z: n[2] };
|
|
4063
|
+
case "vector2":
|
|
4064
|
+
return { x: n[0], y: n[1] };
|
|
4065
|
+
case "rgb":
|
|
4066
|
+
return { r: n[0], g: n[1], b: n[2] };
|
|
4067
|
+
case "hsl":
|
|
4068
|
+
return { h: n[0], s: n[1], l: n[2] };
|
|
4069
|
+
default:
|
|
4070
|
+
return void 0;
|
|
3944
4071
|
}
|
|
3945
4072
|
}
|
|
3946
4073
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3947
4074
|
0 && (module.exports = {
|
|
4075
|
+
DEFAULT_TONE_MAPPING_MODE,
|
|
3948
4076
|
EmptyModelError,
|
|
3949
4077
|
InnerVizij,
|
|
3950
4078
|
ShapeMaterial,
|
|
4079
|
+
TONE_MAPPING_LABELS,
|
|
4080
|
+
TONE_MAPPING_MODES,
|
|
3951
4081
|
Vizij,
|
|
3952
4082
|
VizijContext,
|
|
3953
4083
|
VizijSlice,
|
|
3954
4084
|
applyVizijBundle,
|
|
4085
|
+
buildSceneGraph,
|
|
3955
4086
|
createVizijStore,
|
|
4087
|
+
deriveMorphFeatureKeys,
|
|
4088
|
+
deriveRootBounds,
|
|
3956
4089
|
exportScene,
|
|
3957
4090
|
extractVizijBundle,
|
|
4091
|
+
isToneMappingMode,
|
|
3958
4092
|
loadGLTF,
|
|
3959
4093
|
loadGLTFFromBlob,
|
|
3960
4094
|
loadGLTFFromBlobWithBundle,
|
|
3961
4095
|
loadGLTFWithBundle,
|
|
3962
|
-
|
|
4096
|
+
normalizeToneMappingMode,
|
|
3963
4097
|
parseGlbJsonChunk,
|
|
4098
|
+
patchGlbJson,
|
|
4099
|
+
patchVizijBundleMetadata,
|
|
4100
|
+
resolveToneMapping,
|
|
4101
|
+
sanitizeMorphKey,
|
|
3964
4102
|
useDefaultVizijStore,
|
|
3965
4103
|
useFeatures,
|
|
3966
4104
|
useVizijStore,
|