@babylonjs/loaders 9.29.0 → 9.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/glTF/2.0/Extensions/KHR_interactivity/declarationMapper.js +3 -3
- package/glTF/2.0/Extensions/KHR_interactivity/declarationMapper.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphExporter.d.ts +8 -1
- package/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphExporter.js +54 -19
- package/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphExporter.js.map +1 -1
- package/package.json +3 -3
|
@@ -129,7 +129,7 @@ export interface IKHRInteractivityExportProvider {
|
|
|
129
129
|
/**
|
|
130
130
|
* Builds the canonical extension after glTF entity indices are finalized.
|
|
131
131
|
* @param context final serializer remapping context
|
|
132
|
-
* @returns
|
|
132
|
+
* @returns KHR_interactivity extension payload
|
|
133
133
|
*/
|
|
134
134
|
build(context: IKHRInteractivitySerializerContext): IKHRInteractivity;
|
|
135
135
|
}
|
|
@@ -141,6 +141,12 @@ export interface IKHRInteractivityExportOptions {
|
|
|
141
141
|
document?: IKHRInteractivityDocument;
|
|
142
142
|
/** Loader glTF tree used to resolve original entity references. */
|
|
143
143
|
sourceGLTF?: IGLTF;
|
|
144
|
+
/**
|
|
145
|
+
* Whether export patches the retained source document instead of reserializing the scene.
|
|
146
|
+
* Preserves source entity indices, extension-backed pointers, and imported compatibility flow sockets.
|
|
147
|
+
* Requires sourceGLTF and buildWithSourceIndices; runtime scene changes are not exported.
|
|
148
|
+
*/
|
|
149
|
+
preserveSourceDocument?: boolean;
|
|
144
150
|
/** Root default graph index. Defaults to the canonical document selection or zero. */
|
|
145
151
|
defaultGraphIndex?: number;
|
|
146
152
|
/** Target animation frame rate used by imported animation composites. Defaults to 60. */
|
|
@@ -171,6 +177,7 @@ export declare class KHRInteractivityExportPlan implements IKHRInteractivityExpo
|
|
|
171
177
|
private _additionalExtensionsUsed;
|
|
172
178
|
private readonly _rootDiagnostics;
|
|
173
179
|
private _isPreflight;
|
|
180
|
+
private _sourceIndexContext?;
|
|
174
181
|
/** Whether KHR_interactivity is required in the exported asset. */
|
|
175
182
|
readonly required: boolean;
|
|
176
183
|
/** Additional operation/companion extensions referenced by the exported graphs. */
|
|
@@ -401,6 +401,9 @@ export class KHRInteractivityExportPlan {
|
|
|
401
401
|
this._additionalExtensionsUsed = [];
|
|
402
402
|
this._rootDiagnostics = [];
|
|
403
403
|
this._isPreflight = false;
|
|
404
|
+
if (_options.preserveSourceDocument && !_options.sourceGLTF) {
|
|
405
|
+
throw new Error("Source-preserving interactivity export requires the source glTF document.");
|
|
406
|
+
}
|
|
404
407
|
this.required = _options.required ?? true;
|
|
405
408
|
this.additionalExtensionsRequired = Array.from(new Set(_options.additionalExtensionsRequired ?? [])).sort();
|
|
406
409
|
this._refreshAnalysis();
|
|
@@ -463,6 +466,9 @@ export class KHRInteractivityExportPlan {
|
|
|
463
466
|
* @returns canonical KHR_interactivity payload
|
|
464
467
|
*/
|
|
465
468
|
build(context) {
|
|
469
|
+
if (this._options.preserveSourceDocument && context !== this._sourceIndexContext) {
|
|
470
|
+
throw new Error("Source-preserving interactivity export must use buildWithSourceIndices().");
|
|
471
|
+
}
|
|
466
472
|
this._refreshAnalysis();
|
|
467
473
|
if (!this._analysis.representable) {
|
|
468
474
|
throw new KHRInteractivityExportError(this._analysis.diagnostics);
|
|
@@ -509,9 +515,12 @@ export class KHRInteractivityExportPlan {
|
|
|
509
515
|
return provenance?.source ? CloneKHRInteractivityGraph(provenance.source) : undefined;
|
|
510
516
|
}
|
|
511
517
|
_createSourceIndexContext() {
|
|
518
|
+
if (this._sourceIndexContext) {
|
|
519
|
+
return this._sourceIndexContext;
|
|
520
|
+
}
|
|
512
521
|
const sourceGLTF = this._options.sourceGLTF;
|
|
513
522
|
const indexOrUndefined = (index) => (index !== undefined && index >= 0 ? index : undefined);
|
|
514
|
-
return {
|
|
523
|
+
return (this._sourceIndexContext = {
|
|
515
524
|
getNodeCount: () => sourceGLTF?.nodes?.length ?? 0,
|
|
516
525
|
getNodeIndex: (node) => indexOrUndefined(sourceGLTF?.nodes?.findIndex((candidate) => candidate._babylonTransformNode === node)),
|
|
517
526
|
getAnimationIndex: (animation) => indexOrUndefined(sourceGLTF?.animations?.findIndex((candidate) => candidate._babylonAnimationGroup === animation)),
|
|
@@ -519,7 +528,7 @@ export class KHRInteractivityExportPlan {
|
|
|
519
528
|
getMaterialIndex: (material) => indexOrUndefined(sourceGLTF?.materials?.findIndex((candidate) => Object.values(candidate._data ?? {}).some((entry) => entry.babylonMaterial === material))),
|
|
520
529
|
getRootIndex: (collection, entity) => this._getSourceRootIndex(collection, entity),
|
|
521
530
|
setNodeExtension: () => { },
|
|
522
|
-
};
|
|
531
|
+
});
|
|
523
532
|
}
|
|
524
533
|
_validateBuildWithSourceIndices() {
|
|
525
534
|
const diagnostics = [];
|
|
@@ -653,8 +662,9 @@ export class KHRInteractivityExportPlan {
|
|
|
653
662
|
const declaration = source.declarations?.[sourceNode.declaration];
|
|
654
663
|
const declarationModel = this._options.document?.graphs[graphIndex]?.declarations[sourceNode.declaration];
|
|
655
664
|
const operation = declaration ? _FullOperationName(declaration.op, declaration.extension) : "";
|
|
656
|
-
const mapping = declaration && declarationModel?.support !== "unsupported-extension" ? getMappingForDeclaration(declaration, false) : undefined;
|
|
657
665
|
const blocks = groups.get(nodeIndex) ?? [];
|
|
666
|
+
const hasCompatibilityRuntime = this._options.preserveSourceDocument && blocks.some((block) => block.getClassName() !== _UnsupportedBlockClassName);
|
|
667
|
+
const mapping = declaration && (declarationModel?.support !== "unsupported-extension" || hasCompatibilityRuntime) ? getMappingForDeclaration(declaration, false) : undefined;
|
|
658
668
|
const diagnostics = [];
|
|
659
669
|
let classification = mapping && mapping.blocks.length > 1 ? "inverse-composite" : "exact";
|
|
660
670
|
if (!declaration) {
|
|
@@ -667,7 +677,7 @@ export class KHRInteractivityExportPlan {
|
|
|
667
677
|
message: `Declaration index ${sourceNode.declaration} is unavailable.`,
|
|
668
678
|
});
|
|
669
679
|
}
|
|
670
|
-
else if (declaration.extension === "BABYLON") {
|
|
680
|
+
else if (declaration.extension === "BABYLON" && !this._options.preserveSourceDocument) {
|
|
671
681
|
classification = "unsupported";
|
|
672
682
|
_PushDiagnostic(diagnostics, {
|
|
673
683
|
code: "BLOCK_UNSUPPORTED",
|
|
@@ -1021,7 +1031,7 @@ export class KHRInteractivityExportPlan {
|
|
|
1021
1031
|
});
|
|
1022
1032
|
}
|
|
1023
1033
|
}
|
|
1024
|
-
return graph;
|
|
1034
|
+
return this._options.preserveSourceDocument && _JsonEquivalent(graph, analysis.source) ? CloneKHRInteractivityGraph(analysis.source) : graph;
|
|
1025
1035
|
}
|
|
1026
1036
|
_rebuildNode(graph, sourceNode, logicalNode, graphAnalysis, context, diagnostics) {
|
|
1027
1037
|
const node = _CloneJson(sourceNode);
|
|
@@ -1192,7 +1202,7 @@ export class KHRInteractivityExportPlan {
|
|
|
1192
1202
|
? _CloneJson(sourceNode.flows[socket])
|
|
1193
1203
|
: { node: provenance.nodeIndex };
|
|
1194
1204
|
rebuiltFlow.node = provenance.nodeIndex;
|
|
1195
|
-
if (provenance.socket === "in") {
|
|
1205
|
+
if (provenance.socket === "in" && !(this._options.preserveSourceDocument && rebuiltFlow.socket === "in")) {
|
|
1196
1206
|
delete rebuiltFlow.socket;
|
|
1197
1207
|
}
|
|
1198
1208
|
else {
|
|
@@ -1201,7 +1211,11 @@ export class KHRInteractivityExportPlan {
|
|
|
1201
1211
|
_SetOwnProperty(rebuiltFlows, socket, rebuiltFlow);
|
|
1202
1212
|
}
|
|
1203
1213
|
if (Object.keys(rebuiltFlows).length > 0) {
|
|
1204
|
-
node.flows =
|
|
1214
|
+
node.flows = this._options.preserveSourceDocument
|
|
1215
|
+
? Object.fromEntries([...new Set([...Object.keys(sourceNode.flows ?? {}), ...Object.keys(rebuiltFlows)])]
|
|
1216
|
+
.filter((socket) => Object.prototype.hasOwnProperty.call(rebuiltFlows, socket))
|
|
1217
|
+
.map((socket) => [socket, rebuiltFlows[socket]]))
|
|
1218
|
+
: rebuiltFlows;
|
|
1205
1219
|
}
|
|
1206
1220
|
else {
|
|
1207
1221
|
delete node.flows;
|
|
@@ -1318,7 +1332,7 @@ export class KHRInteractivityExportPlan {
|
|
|
1318
1332
|
return Object.prototype.hasOwnProperty.call(node.flows ?? {}, socket);
|
|
1319
1333
|
}
|
|
1320
1334
|
const fixed = _GetOwn(mappings, socket);
|
|
1321
|
-
if (fixed && !fixed.compatibilityOnly) {
|
|
1335
|
+
if (fixed && (!fixed.compatibilityOnly || (this._options.preserveSourceDocument && Object.prototype.hasOwnProperty.call(node.flows ?? {}, socket)))) {
|
|
1322
1336
|
return true;
|
|
1323
1337
|
}
|
|
1324
1338
|
if (!Object.keys(mappings ?? {}).some((key) => key.startsWith("[") && key.endsWith("]"))) {
|
|
@@ -1465,7 +1479,7 @@ export class KHRInteractivityExportPlan {
|
|
|
1465
1479
|
const rebuiltReference = _CloneJson(sourceValue);
|
|
1466
1480
|
delete rebuiltReference.value;
|
|
1467
1481
|
rebuiltReference.node = provenance.nodeIndex;
|
|
1468
|
-
if (provenance.socket === "value") {
|
|
1482
|
+
if (provenance.socket === "value" && !(this._options.preserveSourceDocument && rebuiltReference.socket === "value")) {
|
|
1469
1483
|
delete rebuiltReference.socket;
|
|
1470
1484
|
}
|
|
1471
1485
|
else {
|
|
@@ -1657,8 +1671,7 @@ export class KHRInteractivityExportPlan {
|
|
|
1657
1671
|
_JsonEquivalent(_GetConfigurationBlock(logicalNode, property)?.config?.[property.name], provenance.runtimeValue) &&
|
|
1658
1672
|
!_IsValidConfigurationValue(provenance.sourceValue, property, graph, this._options.sourceGLTF?.nodes?.length);
|
|
1659
1673
|
if (!preservesFallback && property.indexSource === "assetNodes" && current.length === 1 && typeof current[0] === "number") {
|
|
1660
|
-
const
|
|
1661
|
-
const remapped = sourceNode ? context.getNodeIndex(sourceNode) : undefined;
|
|
1674
|
+
const remapped = this._getRemappedRootIndex("nodes", current[0], context);
|
|
1662
1675
|
if (remapped === undefined) {
|
|
1663
1676
|
_PushDiagnostic(diagnostics, {
|
|
1664
1677
|
code: "REFERENCE_UNRESOLVED",
|
|
@@ -1701,6 +1714,9 @@ export class KHRInteractivityExportPlan {
|
|
|
1701
1714
|
const rootMatch = typeof rootReference === "string" ? /^\/([^/]+)$/.exec(rootReference) : undefined;
|
|
1702
1715
|
collection = rootMatch?.[1] ?? "";
|
|
1703
1716
|
if (!_KnownIndexedRootCollections.has(collection)) {
|
|
1717
|
+
if (this._options.preserveSourceDocument) {
|
|
1718
|
+
continue;
|
|
1719
|
+
}
|
|
1704
1720
|
_PushDiagnostic(diagnostics, {
|
|
1705
1721
|
code: "REFERENCE_UNRESOLVED",
|
|
1706
1722
|
graphIndex,
|
|
@@ -1726,6 +1742,9 @@ export class KHRInteractivityExportPlan {
|
|
|
1726
1742
|
const socket = node.values?.[indexPlaceholder[1]];
|
|
1727
1743
|
const path = `/graphs/${graphIndex}/nodes/${logicalNode.sourceIndex}/values/${indexPlaceholder[1]}`;
|
|
1728
1744
|
if (!socket || "node" in socket) {
|
|
1745
|
+
if (socket && this._options.preserveSourceDocument) {
|
|
1746
|
+
continue;
|
|
1747
|
+
}
|
|
1729
1748
|
_PushDiagnostic(diagnostics, {
|
|
1730
1749
|
code: "REFERENCE_UNRESOLVED",
|
|
1731
1750
|
graphIndex,
|
|
@@ -1981,7 +2000,7 @@ export class KHRInteractivityExportPlan {
|
|
|
1981
2000
|
for (const [socket, value] of Object.entries(node.values ?? {})) {
|
|
1982
2001
|
if (!("node" in value) && graph.types?.[value.type]?.signature === "ref" && value.value) {
|
|
1983
2002
|
const pointerCollection = this._getPointerReferenceCollection(node, mapping, socket);
|
|
1984
|
-
if (pointerCollection === null) {
|
|
2003
|
+
if (pointerCollection === null && !(this._options.preserveSourceDocument && typeof value.value[0] === "string")) {
|
|
1985
2004
|
_PushDiagnostic(diagnostics, {
|
|
1986
2005
|
code: "REFERENCE_UNRESOLVED",
|
|
1987
2006
|
graphIndex,
|
|
@@ -2074,6 +2093,9 @@ export class KHRInteractivityExportPlan {
|
|
|
2074
2093
|
return undefined;
|
|
2075
2094
|
}
|
|
2076
2095
|
_getRemappedRootIndex(collection, sourceIndex, context) {
|
|
2096
|
+
if (this._options.preserveSourceDocument) {
|
|
2097
|
+
return this._options.sourceGLTF?.[collection]?.[sourceIndex] ? sourceIndex : undefined;
|
|
2098
|
+
}
|
|
2077
2099
|
const indices = new Set(this._getSourceRootObjects(collection, sourceIndex)
|
|
2078
2100
|
.map((target) => this._getExportedObjectIndex(collection, target, context))
|
|
2079
2101
|
.filter((index) => index !== undefined));
|
|
@@ -2154,11 +2176,7 @@ export class KHRInteractivityExportPlan {
|
|
|
2154
2176
|
if (!match || !_KnownIndexedRootCollections.has(match[1])) {
|
|
2155
2177
|
return this._remapReference(reference, context, diagnostics, graphIndex, nodeIndex);
|
|
2156
2178
|
}
|
|
2157
|
-
const
|
|
2158
|
-
const targetIndices = new Set(targets
|
|
2159
|
-
.map((target) => this._getExportedObjectIndex(targetCollection, target, context))
|
|
2160
|
-
.filter((index) => index !== undefined));
|
|
2161
|
-
const targetIndex = targetIndices.size === 1 ? targetIndices.values().next().value : undefined;
|
|
2179
|
+
const targetIndex = this._getRemappedRootIndex(targetCollection, parseInt(match[2], 10), context);
|
|
2162
2180
|
if (targetIndex === undefined) {
|
|
2163
2181
|
_PushDiagnostic(diagnostics, {
|
|
2164
2182
|
code: "REFERENCE_UNRESOLVED",
|
|
@@ -2175,8 +2193,22 @@ export class KHRInteractivityExportPlan {
|
|
|
2175
2193
|
if (!reference || reference.startsWith("/extensions/KHR_interactivity/events/") || reference.startsWith("/extensions/KHR_interactivity/delays/")) {
|
|
2176
2194
|
return reference;
|
|
2177
2195
|
}
|
|
2178
|
-
const extensionCollection = /^\/extensions\/([^/]+)\/[^/]
|
|
2196
|
+
const extensionCollection = /^\/extensions\/([^/]+)\/([^/]+)\/(0|[1-9]\d*)(?:\/|$)/.exec(reference);
|
|
2179
2197
|
if (extensionCollection && extensionCollection[1] !== "KHR_interactivity") {
|
|
2198
|
+
if (this._options.preserveSourceDocument) {
|
|
2199
|
+
const collection = this._options.sourceGLTF?.extensions?.[extensionCollection[1]]?.[extensionCollection[2]];
|
|
2200
|
+
if (!Array.isArray(collection) || collection[Number(extensionCollection[3])] === undefined) {
|
|
2201
|
+
_PushDiagnostic(diagnostics, {
|
|
2202
|
+
code: "REFERENCE_UNRESOLVED",
|
|
2203
|
+
graphIndex,
|
|
2204
|
+
nodeIndex,
|
|
2205
|
+
path: `/graphs/${graphIndex}${nodeIndex === undefined ? "" : `/nodes/${nodeIndex}`}`,
|
|
2206
|
+
message: `Reference "${reference}" does not identify an entry in the retained source document.`,
|
|
2207
|
+
});
|
|
2208
|
+
return reference;
|
|
2209
|
+
}
|
|
2210
|
+
return reference;
|
|
2211
|
+
}
|
|
2180
2212
|
_PushDiagnostic(diagnostics, {
|
|
2181
2213
|
code: "REFERENCE_UNRESOLVED",
|
|
2182
2214
|
graphIndex,
|
|
@@ -2210,7 +2242,7 @@ export class KHRInteractivityExportPlan {
|
|
|
2210
2242
|
}
|
|
2211
2243
|
_validateExtensionReferencePreservation(reference, resolvedCollection, diagnostics, graphIndex, nodeIndex, path = `/graphs/${graphIndex}${nodeIndex === undefined ? "" : `/nodes/${nodeIndex}`}`) {
|
|
2212
2244
|
const nestedExtensions = _GetPointerExtensionNames(reference).filter((extension) => extension !== "KHR_interactivity");
|
|
2213
|
-
if (nestedExtensions.length === 0 || _CanPreserveNestedExtensionPointer(reference, resolvedCollection)) {
|
|
2245
|
+
if (this._options.preserveSourceDocument || nestedExtensions.length === 0 || _CanPreserveNestedExtensionPointer(reference, resolvedCollection)) {
|
|
2214
2246
|
return true;
|
|
2215
2247
|
}
|
|
2216
2248
|
_PushDiagnostic(diagnostics, {
|
|
@@ -2308,6 +2340,9 @@ export class KHRInteractivityExportPlan {
|
|
|
2308
2340
|
return Array.from(extensions).sort();
|
|
2309
2341
|
}
|
|
2310
2342
|
_writeCompanionNodeExtensions(context, diagnostics) {
|
|
2343
|
+
if (this._options.preserveSourceDocument) {
|
|
2344
|
+
return;
|
|
2345
|
+
}
|
|
2311
2346
|
for (let sourceIndex = 0; sourceIndex < (this._options.sourceGLTF?.nodes?.length ?? 0); sourceIndex++) {
|
|
2312
2347
|
const sourceNode = this._options.sourceGLTF.nodes[sourceIndex];
|
|
2313
2348
|
for (const extensionName of _CompanionNodeExtensions) {
|