@babylonjs/loaders 9.26.2 → 9.27.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/EXT_texture_avif.pure.js +1 -1
- package/glTF/2.0/Extensions/EXT_texture_avif.pure.js.map +1 -1
- package/glTF/2.0/Extensions/EXT_texture_webp.pure.js +1 -1
- package/glTF/2.0/Extensions/EXT_texture_webp.pure.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_interactivity/declarationMapper.d.ts +33 -0
- package/glTF/2.0/Extensions/KHR_interactivity/declarationMapper.js +166 -37
- package/glTF/2.0/Extensions/KHR_interactivity/declarationMapper.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_interactivity/index.d.ts +1 -0
- package/glTF/2.0/Extensions/KHR_interactivity/index.js +1 -0
- package/glTF/2.0/Extensions/KHR_interactivity/index.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphExporter.d.ts +243 -0
- package/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphExporter.js +2335 -0
- package/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphExporter.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphModel.d.ts +82 -1
- package/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphModel.js +180 -34
- package/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphModel.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphParser.d.ts +14 -2
- package/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphParser.js +220 -34
- package/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphParser.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_interactivity/pure.d.ts +1 -0
- package/glTF/2.0/Extensions/KHR_interactivity/pure.js +1 -0
- package/glTF/2.0/Extensions/KHR_interactivity/pure.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_interactivity.pure.d.ts +4 -0
- package/glTF/2.0/Extensions/KHR_interactivity.pure.js +6 -2
- package/glTF/2.0/Extensions/KHR_interactivity.pure.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_texture_basisu.pure.js +1 -1
- package/glTF/2.0/Extensions/KHR_texture_basisu.pure.js.map +1 -1
- package/glTF/2.0/glTFLoader.pure.d.ts +2 -1
- package/glTF/2.0/glTFLoader.pure.js +41 -4
- package/glTF/2.0/glTFLoader.pure.js.map +1 -1
- package/glTF/2.0/glTFLoaderInterfaces.d.ts +9 -0
- package/glTF/2.0/glTFLoaderInterfaces.js.map +1 -1
- package/package.json +3 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type IKHRInteractivity, type IKHRInteractivity_Declaration, type IKHRInteractivity_Graph } from "babylonjs-gltf2interface";
|
|
1
|
+
import { type IKHRInteractivity, type IKHRInteractivity_Declaration, type IKHRInteractivity_Graph, type IKHRInteractivity_OutputSocketReference, type IKHRInteractivity_Variable } from "babylonjs-gltf2interface";
|
|
2
2
|
import { FlowGraphTypes } from "@babylonjs/core/FlowGraph/flowGraphRichTypes.js";
|
|
3
3
|
/**
|
|
4
4
|
* Ratified KHR_interactivity specification baseline used by this importer.
|
|
@@ -29,6 +29,87 @@ export interface IKHRInteractivityDiagnostic {
|
|
|
29
29
|
/** Diagnostic severity. */
|
|
30
30
|
severity: "error" | "warning";
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Stable source identity retained on every FlowGraph block lowered from a KHR_interactivity node.
|
|
34
|
+
*/
|
|
35
|
+
export interface IKHRInteractivityBlockProvenance {
|
|
36
|
+
/** Source graph index. */
|
|
37
|
+
graphIndex: number;
|
|
38
|
+
/** Source node index. */
|
|
39
|
+
nodeIndex: number;
|
|
40
|
+
/** Source declaration index. */
|
|
41
|
+
declarationIndex: number;
|
|
42
|
+
/** Full operation name. */
|
|
43
|
+
operation: string;
|
|
44
|
+
/** Role of this block in a one-to-many mapping. Negative roles identify generated helper blocks. */
|
|
45
|
+
role: number;
|
|
46
|
+
/** Stable JSON pointer to the source node. */
|
|
47
|
+
sourcePath: string;
|
|
48
|
+
/** Original and lowered configuration values used for safe inverse transforms. */
|
|
49
|
+
configuration?: Record<string, IKHRInteractivityConfigurationProvenance>;
|
|
50
|
+
/** Importer-generated primitive configuration that must remain unchanged for inverse export. */
|
|
51
|
+
generatedConfiguration?: Record<string, unknown>;
|
|
52
|
+
/** Runtime fingerprints for generated configuration that changes representation while parsing. */
|
|
53
|
+
generatedConfigurationRuntime?: Record<string, IKHRInteractivityInputDefaultProvenance>;
|
|
54
|
+
/** Importer-generated unconnected input defaults that have no authored KHR socket representation. */
|
|
55
|
+
generatedInputDefaults?: Record<string, IKHRInteractivityInputDefaultProvenance>;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Import-time value retained for an unconnected FlowGraph input that is not represented by an authored KHR socket.
|
|
59
|
+
*/
|
|
60
|
+
export interface IKHRInteractivityInputDefaultProvenance {
|
|
61
|
+
/** Type-tagged JSON-stable fingerprint of the normalized runtime input value. */
|
|
62
|
+
runtimeValueFingerprint?: string;
|
|
63
|
+
/** Whether the import-time value could not be fingerprinted safely. */
|
|
64
|
+
unrepresentable?: true;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Provenance for a transformed KHR configuration value.
|
|
68
|
+
*/
|
|
69
|
+
export interface IKHRInteractivityConfigurationProvenance {
|
|
70
|
+
/** Exact source configuration array. */
|
|
71
|
+
sourceValue?: unknown[];
|
|
72
|
+
/** Lowered FlowGraph configuration value immediately after import. */
|
|
73
|
+
runtimeValue?: unknown;
|
|
74
|
+
}
|
|
75
|
+
/** @internal */
|
|
76
|
+
export declare function _NormalizeKHRInteractivityRuntimeValue(value: unknown): unknown[] | undefined;
|
|
77
|
+
/** @internal */
|
|
78
|
+
export declare function _CreateKHRInteractivityRuntimeValueSnapshot(value: unknown): IKHRInteractivityInputDefaultProvenance;
|
|
79
|
+
/**
|
|
80
|
+
* Stable source identity retained on a FlowGraph connection lowered from a KHR_interactivity socket.
|
|
81
|
+
*/
|
|
82
|
+
export interface IKHRInteractivitySocketProvenance extends IKHRInteractivityBlockProvenance {
|
|
83
|
+
/** Socket category. */
|
|
84
|
+
kind: "value" | "flow";
|
|
85
|
+
/** Whether the socket is consumed by or produced from the logical KHR node. */
|
|
86
|
+
direction: "input" | "output";
|
|
87
|
+
/** Exact source KHR socket identifier. */
|
|
88
|
+
socket: string;
|
|
89
|
+
/** Exact canonical source value, when this is an input value socket. */
|
|
90
|
+
sourceValue?: IKHRInteractivity_Variable | IKHRInteractivity_OutputSocketReference;
|
|
91
|
+
/** Lowered inline runtime value immediately after import. */
|
|
92
|
+
runtimeValue?: unknown[];
|
|
93
|
+
/** Type-tagged runtime fingerprint used to distinguish parsing precision changes from edits. */
|
|
94
|
+
runtimeValueSnapshot?: IKHRInteractivityInputDefaultProvenance;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Canonical source retained on a FlowGraph lowered from KHR_interactivity.
|
|
98
|
+
*/
|
|
99
|
+
export interface IKHRInteractivityGraphProvenance {
|
|
100
|
+
/** Source graph index. */
|
|
101
|
+
graphIndex: number;
|
|
102
|
+
/** Ratified specification revision used by the importer. */
|
|
103
|
+
specificationCommit: string;
|
|
104
|
+
/** Detached canonical source graph. */
|
|
105
|
+
source: IKHRInteractivity_Graph;
|
|
106
|
+
/** Explicit editor-authored variable defaults keyed by canonical variable index. */
|
|
107
|
+
authoredVariableValues?: Record<number, unknown[]>;
|
|
108
|
+
/** Explicit editor-authored FlowGraph variable types keyed by canonical variable index. */
|
|
109
|
+
authoredVariableTypes?: Record<number, string>;
|
|
110
|
+
/** True when variables were explicitly added, renamed, or deleted in the editor. */
|
|
111
|
+
authoredVariableStructureChanged?: boolean;
|
|
112
|
+
}
|
|
32
113
|
/**
|
|
33
114
|
* Canonical declaration information retained during import.
|
|
34
115
|
*/
|
|
@@ -20,6 +20,95 @@ export const gltfTypeToBabylonType = {
|
|
|
20
20
|
ref: { length: 1, flowGraphType: "string" /* FlowGraphTypes.String */, elementType: "string" },
|
|
21
21
|
custom: { length: 0, flowGraphType: "any" /* FlowGraphTypes.Any */, elementType: "any" },
|
|
22
22
|
};
|
|
23
|
+
/** @internal */
|
|
24
|
+
export function _NormalizeKHRInteractivityRuntimeValue(value) {
|
|
25
|
+
if (value === undefined) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
if (value !== null && typeof value === "object") {
|
|
29
|
+
const asArray = value.asArray;
|
|
30
|
+
if (typeof asArray === "function") {
|
|
31
|
+
return Array.from(asArray.call(value));
|
|
32
|
+
}
|
|
33
|
+
if ("value" in value && typeof value.value !== "object") {
|
|
34
|
+
return [value.value];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return Array.isArray(value) ? value.slice() : [value];
|
|
38
|
+
}
|
|
39
|
+
function _EncodeRuntimeValueSnapshot(value, ancestors) {
|
|
40
|
+
if (value === undefined) {
|
|
41
|
+
return ["undefined"];
|
|
42
|
+
}
|
|
43
|
+
if (value === null) {
|
|
44
|
+
return ["null"];
|
|
45
|
+
}
|
|
46
|
+
switch (typeof value) {
|
|
47
|
+
case "boolean":
|
|
48
|
+
return ["boolean", value];
|
|
49
|
+
case "number":
|
|
50
|
+
return ["number", Number.isNaN(value) ? "NaN" : value === Infinity ? "Infinity" : value === -Infinity ? "-Infinity" : Object.is(value, -0) ? "-0" : value];
|
|
51
|
+
case "string":
|
|
52
|
+
return ["string", value];
|
|
53
|
+
case "object": {
|
|
54
|
+
if (Object.getOwnPropertySymbols(value).length > 0) {
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
if (Array.isArray(value)) {
|
|
58
|
+
const hasNonIndexProperty = Object.getOwnPropertyNames(value).some((key) => key !== "length" && (!/^(0|[1-9]\d*)$/.test(key) || Number(key) >= value.length || !("value" in Object.getOwnPropertyDescriptor(value, key))));
|
|
59
|
+
if (hasNonIndexProperty) {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
const prototype = Object.getPrototypeOf(value);
|
|
65
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
const hasNonJsonProperty = Object.getOwnPropertyNames(value).some((key) => !Object.prototype.propertyIsEnumerable.call(value, key) || !("value" in Object.getOwnPropertyDescriptor(value, key)));
|
|
69
|
+
if (hasNonJsonProperty) {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (ancestors.has(value)) {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
ancestors.add(value);
|
|
77
|
+
let encoded;
|
|
78
|
+
if (Array.isArray(value)) {
|
|
79
|
+
const entries = value.map((entry) => _EncodeRuntimeValueSnapshot(entry, ancestors));
|
|
80
|
+
encoded = entries.some((entry) => entry === undefined) ? undefined : ["array", entries];
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
const entries = [];
|
|
84
|
+
let unrepresentable = false;
|
|
85
|
+
for (const key of Object.keys(value).sort()) {
|
|
86
|
+
const entry = _EncodeRuntimeValueSnapshot(value[key], ancestors);
|
|
87
|
+
if (entry === undefined) {
|
|
88
|
+
unrepresentable = true;
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
entries.push([key, entry]);
|
|
92
|
+
}
|
|
93
|
+
encoded = unrepresentable ? undefined : ["object", entries];
|
|
94
|
+
}
|
|
95
|
+
ancestors.delete(value);
|
|
96
|
+
return encoded;
|
|
97
|
+
}
|
|
98
|
+
default:
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/** @internal */
|
|
103
|
+
export function _CreateKHRInteractivityRuntimeValueSnapshot(value) {
|
|
104
|
+
try {
|
|
105
|
+
const encoded = _EncodeRuntimeValueSnapshot(Array.isArray(value) ? value : _NormalizeKHRInteractivityRuntimeValue(value), new Set());
|
|
106
|
+
return encoded === undefined ? { unrepresentable: true } : { runtimeValueFingerprint: JSON.stringify(encoded) };
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return { unrepresentable: true };
|
|
110
|
+
}
|
|
111
|
+
}
|
|
23
112
|
function _cloneJson(value) {
|
|
24
113
|
if (Array.isArray(value)) {
|
|
25
114
|
return value.map((entry) => _cloneJson(entry));
|
|
@@ -49,6 +138,9 @@ export function CloneKHRInteractivityGraph(graph) {
|
|
|
49
138
|
function _isValidIndex(value, length) {
|
|
50
139
|
return typeof value === "number" && Number.isInteger(value) && value >= 0 && value < length;
|
|
51
140
|
}
|
|
141
|
+
function _isRecord(value) {
|
|
142
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
143
|
+
}
|
|
52
144
|
function _addError(diagnostics, path, message) {
|
|
53
145
|
diagnostics.push({ path, message, severity: "error" });
|
|
54
146
|
}
|
|
@@ -88,6 +180,10 @@ function _validateValue(value, graph, diagnostics, path) {
|
|
|
88
180
|
if (value.value === undefined) {
|
|
89
181
|
return;
|
|
90
182
|
}
|
|
183
|
+
if (!Array.isArray(value.value)) {
|
|
184
|
+
_addError(diagnostics, `${path}/value`, "Value must be an array when present.");
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
91
187
|
const type = graph.types[value.type];
|
|
92
188
|
const runtimeType = gltfTypeToBabylonType[type.signature];
|
|
93
189
|
if (runtimeType && type.signature !== "custom" && value.value.length !== runtimeType.length) {
|
|
@@ -144,12 +240,12 @@ function _isCompatibleExtensionDeclaration(declaration, graph, schema) {
|
|
|
144
240
|
if (actualKeys.length !== expectedKeys.length || actualKeys.some((key, index) => key !== expectedKeys[index])) {
|
|
145
241
|
return false;
|
|
146
242
|
}
|
|
147
|
-
return actualKeys.every((key) => graph.types?.[actual[key].type]?.signature === expected[key]);
|
|
243
|
+
return actualKeys.every((key) => _isRecord(actual[key]) && graph.types?.[actual[key].type]?.signature === expected[key]);
|
|
148
244
|
};
|
|
149
245
|
return matches(declaration.inputValueSockets, schema.inputValueSockets) && matches(declaration.outputValueSockets, schema.outputValueSockets);
|
|
150
246
|
}
|
|
151
247
|
function _validateConfigurationValue(value, type) {
|
|
152
|
-
if (!value) {
|
|
248
|
+
if (!Array.isArray(value)) {
|
|
153
249
|
return false;
|
|
154
250
|
}
|
|
155
251
|
const isInt = (entry) => typeof entry === "number" && Number.isInteger(entry) && entry >= -2147483648 && entry <= 2147483647;
|
|
@@ -208,30 +304,14 @@ function _isEffectiveConfigurationValue(configuration, property, graph, assetNod
|
|
|
208
304
|
return false;
|
|
209
305
|
}
|
|
210
306
|
}
|
|
307
|
+
if (property.allowedValues && configuration.value.some((value) => !property.allowedValues.includes(value))) {
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
211
310
|
if (property.debugLogTemplate && !ParseDebugLogTemplate(configuration.value[0]).valid) {
|
|
212
311
|
return false;
|
|
213
312
|
}
|
|
214
313
|
return true;
|
|
215
314
|
}
|
|
216
|
-
function _getAllowedDynamicFlowOutputSockets(node, mapping, graph, assetNodeCount) {
|
|
217
|
-
for (const [key, property] of Object.entries(mapping.configuration ?? {})) {
|
|
218
|
-
if (!property.generatesOutputFlowSockets) {
|
|
219
|
-
continue;
|
|
220
|
-
}
|
|
221
|
-
const configured = node.configuration?.[key];
|
|
222
|
-
const values = _isEffectiveConfigurationValue(configured, property, graph, assetNodeCount) ? configured.value : property.defaultValue;
|
|
223
|
-
return new Set(Array.isArray(values) ? values.map(String) : []);
|
|
224
|
-
}
|
|
225
|
-
return undefined;
|
|
226
|
-
}
|
|
227
|
-
function _matchesFlowOutputSocket(mapping, socket, allowedDynamicSockets) {
|
|
228
|
-
const flowMappings = mapping.outputs?.flows;
|
|
229
|
-
if (flowMappings && Object.prototype.hasOwnProperty.call(flowMappings, socket)) {
|
|
230
|
-
return true;
|
|
231
|
-
}
|
|
232
|
-
const hasWildcard = Object.keys(flowMappings ?? {}).some((name) => name.startsWith("[") && name.endsWith("]"));
|
|
233
|
-
return !hasWildcard || !allowedDynamicSockets || allowedDynamicSockets.has(socket);
|
|
234
|
-
}
|
|
235
315
|
/**
|
|
236
316
|
* Creates the executable graph view with all ratified configuration defaults and fallback rules
|
|
237
317
|
* applied without modifying the lossless source graph.
|
|
@@ -313,7 +393,11 @@ function _resolveOutputTypeIndex(nodeIndex, socket, graph, declarations, visited
|
|
|
313
393
|
if (declaredType !== undefined) {
|
|
314
394
|
return declaredType;
|
|
315
395
|
}
|
|
316
|
-
const
|
|
396
|
+
const findTypeIndex = (signature) => {
|
|
397
|
+
const index = graph.types?.findIndex((type) => type.signature === signature) ?? -1;
|
|
398
|
+
return index >= 0 ? index : undefined;
|
|
399
|
+
};
|
|
400
|
+
const booleanType = () => findTypeIndex("bool");
|
|
317
401
|
if (socket === "isValid") {
|
|
318
402
|
return booleanType();
|
|
319
403
|
}
|
|
@@ -335,14 +419,14 @@ function _resolveOutputTypeIndex(nodeIndex, socket, graph, declarations, visited
|
|
|
335
419
|
}
|
|
336
420
|
const fixedSignature = _getFixedOutputSignature(declaration.operation, socket);
|
|
337
421
|
if (fixedSignature) {
|
|
338
|
-
return
|
|
422
|
+
return findTypeIndex(String(fixedSignature));
|
|
339
423
|
}
|
|
340
424
|
const mapping = getMappingForDeclaration(declaration.source, false);
|
|
341
425
|
const outputMapping = mapping?.outputs?.values?.[socket];
|
|
342
426
|
const mappedType = outputMapping?.gltfType;
|
|
343
427
|
const signature = mappedType === "number" ? "float" : mappedType === "boolean" ? "bool" : mappedType;
|
|
344
428
|
if (signature && signature in gltfTypeToBabylonType) {
|
|
345
|
-
return
|
|
429
|
+
return findTypeIndex(signature);
|
|
346
430
|
}
|
|
347
431
|
const typeSource = outputMapping?.typeSourceInput ? sourceNode.values?.[outputMapping.typeSourceInput] : undefined;
|
|
348
432
|
return typeSource ? _resolveValueTypeIndex(typeSource, graph, declarations, visited) : undefined;
|
|
@@ -414,7 +498,14 @@ function _validateNode(node, nodeIndex, graph, declarations, diagnostics, graphP
|
|
|
414
498
|
}
|
|
415
499
|
};
|
|
416
500
|
for (const [key, configuration] of Object.entries(node.configuration ?? {})) {
|
|
417
|
-
if (configuration
|
|
501
|
+
if (!_isRecord(configuration)) {
|
|
502
|
+
_addError(diagnostics, `${path}/configuration/${key}`, `Configuration "${key}" must be an object.`);
|
|
503
|
+
continue;
|
|
504
|
+
}
|
|
505
|
+
if (configuration.value !== undefined && !Array.isArray(configuration.value)) {
|
|
506
|
+
_addError(diagnostics, `${path}/configuration/${key}/value`, "Configuration value must be an array when present.");
|
|
507
|
+
}
|
|
508
|
+
else if (configuration.value && configuration.value.length === 0) {
|
|
418
509
|
_addError(diagnostics, `${path}/configuration/${key}/value`, "Configuration value arrays must contain at least one item when present.");
|
|
419
510
|
}
|
|
420
511
|
}
|
|
@@ -445,6 +536,9 @@ function _validateNode(node, nodeIndex, graph, declarations, diagnostics, graphP
|
|
|
445
536
|
reportConfigurationIssue(property, `${path}/configuration/${key}/value/0`, `Type "${String(signature)}" is not supported by this operation.`);
|
|
446
537
|
}
|
|
447
538
|
}
|
|
539
|
+
if (isConfigurationValid && configuration.value && property.allowedValues && configuration.value.some((value) => !property.allowedValues.includes(value))) {
|
|
540
|
+
reportConfigurationIssue(property, `${path}/configuration/${key}/value`, `Configuration "${key}" contains an unsupported value.`);
|
|
541
|
+
}
|
|
448
542
|
if (isConfigurationValid && configuration.value && property.debugLogTemplate && !ParseDebugLogTemplate(configuration.value[0]).valid) {
|
|
449
543
|
reportConfigurationIssue(property, `${path}/configuration/${key}/value/0`, `Configuration "${key}" is not a valid debug message template.`);
|
|
450
544
|
}
|
|
@@ -549,6 +643,10 @@ function _validateNode(node, nodeIndex, graph, declarations, diagnostics, graphP
|
|
|
549
643
|
}
|
|
550
644
|
}
|
|
551
645
|
for (const [key, value] of Object.entries(node.values ?? {})) {
|
|
646
|
+
if (!_isRecord(value)) {
|
|
647
|
+
_addError(diagnostics, `${path}/values/${key}`, `Input value socket "${key}" must be an object.`);
|
|
648
|
+
continue;
|
|
649
|
+
}
|
|
552
650
|
if (declarationModel.support === "unsupported-extension" && !declarationModel.source.inputValueSockets?.[key]) {
|
|
553
651
|
_addError(diagnostics, `${path}/values/${key}`, `Input value socket "${key}" is not defined by operation "${declarationModel.operation}".`);
|
|
554
652
|
}
|
|
@@ -579,8 +677,28 @@ function _validateNode(node, nodeIndex, graph, declarations, diagnostics, graphP
|
|
|
579
677
|
}
|
|
580
678
|
const declaredOutputType = sourceDeclaration.source.outputValueSockets?.[sourceSocket]?.type;
|
|
581
679
|
const effectiveOutputType = declaredOutputType ?? _resolveOutputTypeIndex(value.node, sourceSocket, graph, declarations);
|
|
582
|
-
if (value.type !== undefined
|
|
583
|
-
|
|
680
|
+
if (value.type !== undefined) {
|
|
681
|
+
const mappedOutputs = sourceMapping?.outputs?.values;
|
|
682
|
+
const mappedOutput = mappedOutputs && Object.prototype.hasOwnProperty.call(mappedOutputs, sourceSocket) ? mappedOutputs[sourceSocket] : undefined;
|
|
683
|
+
const mappedType = mappedOutput?.gltfType;
|
|
684
|
+
const mappedOutputSignature = mappedType === "number"
|
|
685
|
+
? "float"
|
|
686
|
+
: mappedType === "boolean"
|
|
687
|
+
? "bool"
|
|
688
|
+
: mappedType === "vector2"
|
|
689
|
+
? "float2"
|
|
690
|
+
: mappedType === "vector3"
|
|
691
|
+
? "float3"
|
|
692
|
+
: mappedType === "vector4"
|
|
693
|
+
? "float4"
|
|
694
|
+
: mappedType;
|
|
695
|
+
const fixedOutputSignature = _getFixedOutputSignature(sourceDeclaration.operation, sourceSocket) ??
|
|
696
|
+
(mappedOutputSignature && Object.prototype.hasOwnProperty.call(gltfTypeToBabylonType, mappedOutputSignature) ? mappedOutputSignature : undefined);
|
|
697
|
+
const assertedSignature = graph.types?.[value.type]?.signature;
|
|
698
|
+
if ((fixedOutputSignature !== undefined && assertedSignature !== fixedOutputSignature) ||
|
|
699
|
+
(fixedOutputSignature === undefined && effectiveOutputType !== undefined && value.type !== effectiveOutputType)) {
|
|
700
|
+
_addError(diagnostics, `${path}/values/${key}/type`, `Type assertion does not match output socket "${sourceSocket}".`);
|
|
701
|
+
}
|
|
584
702
|
}
|
|
585
703
|
}
|
|
586
704
|
}
|
|
@@ -589,9 +707,9 @@ function _validateNode(node, nodeIndex, graph, declarations, diagnostics, graphP
|
|
|
589
707
|
}
|
|
590
708
|
}
|
|
591
709
|
for (const [key, flow] of Object.entries(node.flows ?? {})) {
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
710
|
+
if (!_isRecord(flow)) {
|
|
711
|
+
_addError(diagnostics, `${path}/flows/${key}`, `Output flow socket "${key}" must be an object.`);
|
|
712
|
+
continue;
|
|
595
713
|
}
|
|
596
714
|
if (!_isValidIndex(flow.node, graph.nodes?.length ?? 0)) {
|
|
597
715
|
_addError(diagnostics, `${path}/flows/${key}/node`, `Node index ${String(flow.node)} is out of range.`);
|
|
@@ -647,14 +765,23 @@ export function CreateKHRInteractivityGraphModel(graph, index = 0, supportedExte
|
|
|
647
765
|
}
|
|
648
766
|
}
|
|
649
767
|
for (let eventIndex = 0; eventIndex < (graph.events?.length ?? 0); eventIndex++) {
|
|
650
|
-
|
|
768
|
+
const event = graph.events[eventIndex];
|
|
769
|
+
if (event.values !== undefined && !_isRecord(event.values)) {
|
|
770
|
+
_addError(diagnostics, `${path}/events/${eventIndex}/values`, '"values" must be an object when present.');
|
|
771
|
+
event.values = undefined;
|
|
772
|
+
}
|
|
773
|
+
else if (event.values && Object.keys(event.values).length === 0) {
|
|
651
774
|
_addError(diagnostics, `${path}/events/${eventIndex}/values`, '"values" must contain at least one property when present.');
|
|
652
775
|
}
|
|
653
776
|
}
|
|
654
777
|
for (let declarationIndex = 0; declarationIndex < (graph.declarations?.length ?? 0); declarationIndex++) {
|
|
655
778
|
const declaration = graph.declarations[declarationIndex];
|
|
656
779
|
for (const key of ["inputValueSockets", "outputValueSockets"]) {
|
|
657
|
-
if (declaration[key] &&
|
|
780
|
+
if (declaration[key] !== undefined && !_isRecord(declaration[key])) {
|
|
781
|
+
_addError(diagnostics, `${path}/declarations/${declarationIndex}/${key}`, `"${key}" must be an object when present.`);
|
|
782
|
+
declaration[key] = undefined;
|
|
783
|
+
}
|
|
784
|
+
else if (declaration[key] && Object.keys(declaration[key]).length === 0) {
|
|
658
785
|
_addError(diagnostics, `${path}/declarations/${declarationIndex}/${key}`, `"${key}" must contain at least one property when present.`);
|
|
659
786
|
}
|
|
660
787
|
}
|
|
@@ -662,7 +789,11 @@ export function CreateKHRInteractivityGraphModel(graph, index = 0, supportedExte
|
|
|
662
789
|
for (let nodeIndex = 0; nodeIndex < (graph.nodes?.length ?? 0); nodeIndex++) {
|
|
663
790
|
const node = graph.nodes[nodeIndex];
|
|
664
791
|
for (const key of ["configuration", "values", "flows"]) {
|
|
665
|
-
if (node[key] &&
|
|
792
|
+
if (node[key] !== undefined && !_isRecord(node[key])) {
|
|
793
|
+
_addError(diagnostics, `${path}/nodes/${nodeIndex}/${key}`, `"${key}" must be an object when present.`);
|
|
794
|
+
node[key] = undefined;
|
|
795
|
+
}
|
|
796
|
+
else if (node[key] && Object.keys(node[key]).length === 0) {
|
|
666
797
|
_addError(diagnostics, `${path}/nodes/${nodeIndex}/${key}`, `"${key}" must contain at least one property when present.`);
|
|
667
798
|
}
|
|
668
799
|
}
|
|
@@ -671,7 +802,10 @@ export function CreateKHRInteractivityGraphModel(graph, index = 0, supportedExte
|
|
|
671
802
|
const declarations = (graph.declarations ?? []).map((declaration, declarationIndex) => {
|
|
672
803
|
const inputSockets = Object.keys(declaration.inputValueSockets ?? {})
|
|
673
804
|
.sort()
|
|
674
|
-
.map((key) =>
|
|
805
|
+
.map((key) => {
|
|
806
|
+
const definition = declaration.inputValueSockets[key];
|
|
807
|
+
return `${JSON.stringify(key)}:${_isRecord(definition) ? String(definition.type) : "invalid"}`;
|
|
808
|
+
})
|
|
675
809
|
.join(",");
|
|
676
810
|
const declarationKey = `${JSON.stringify(declaration.op)}:${JSON.stringify(declaration.extension ?? "")}:${inputSockets}`;
|
|
677
811
|
if (declarationKeys.has(declarationKey)) {
|
|
@@ -686,9 +820,17 @@ export function CreateKHRInteractivityGraphModel(graph, index = 0, supportedExte
|
|
|
686
820
|
_addError(diagnostics, `${path}/declarations/${declarationIndex}`, "Core operation declarations cannot define dynamic value sockets.");
|
|
687
821
|
}
|
|
688
822
|
for (const [socket, definition] of Object.entries(declaration.inputValueSockets ?? {})) {
|
|
823
|
+
if (!_isRecord(definition)) {
|
|
824
|
+
_addError(diagnostics, `${path}/declarations/${declarationIndex}/inputValueSockets/${socket}`, `Input value socket "${socket}" must be an object.`);
|
|
825
|
+
continue;
|
|
826
|
+
}
|
|
689
827
|
_validateTypeIndex(definition.type, graph, diagnostics, `${path}/declarations/${declarationIndex}/inputValueSockets/${socket}/type`);
|
|
690
828
|
}
|
|
691
829
|
for (const [socket, definition] of Object.entries(declaration.outputValueSockets ?? {})) {
|
|
830
|
+
if (!_isRecord(definition)) {
|
|
831
|
+
_addError(diagnostics, `${path}/declarations/${declarationIndex}/outputValueSockets/${socket}`, `Output value socket "${socket}" must be an object.`);
|
|
832
|
+
continue;
|
|
833
|
+
}
|
|
692
834
|
_validateTypeIndex(definition.type, graph, diagnostics, `${path}/declarations/${declarationIndex}/outputValueSockets/${socket}/type`);
|
|
693
835
|
}
|
|
694
836
|
return {
|
|
@@ -721,6 +863,10 @@ export function CreateKHRInteractivityGraphModel(graph, index = 0, supportedExte
|
|
|
721
863
|
_addError(diagnostics, `${path}/events/${eventIndex}/values/event`, 'Custom event value socket id "event" is reserved.');
|
|
722
864
|
}
|
|
723
865
|
for (const [socket, value] of Object.entries(graph.events[eventIndex].values ?? {})) {
|
|
866
|
+
if (!_isRecord(value)) {
|
|
867
|
+
_addError(diagnostics, `${path}/events/${eventIndex}/values/${socket}`, `Event value socket "${socket}" must be an object.`);
|
|
868
|
+
continue;
|
|
869
|
+
}
|
|
724
870
|
_validateValue(value, graph, diagnostics, `${path}/events/${eventIndex}/values/${socket}`);
|
|
725
871
|
}
|
|
726
872
|
}
|