@onerjs/core 8.44.7 → 8.44.9
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/Bones/skeleton.d.ts +5 -0
- package/Bones/skeleton.js +35 -8
- package/Bones/skeleton.js.map +1 -1
- package/Collisions/collider.js +2 -2
- package/Collisions/collider.js.map +1 -1
- package/Culling/Helper/computeShaderBoundingHelper.js +8 -1
- package/Culling/Helper/computeShaderBoundingHelper.js.map +1 -1
- package/Culling/Helper/transformFeedbackBoundingHelper.js +1 -1
- package/Culling/Helper/transformFeedbackBoundingHelper.js.map +1 -1
- package/Engines/WebGPU/webgpuShaderProcessingContext.d.ts +1 -0
- package/Engines/WebGPU/webgpuShaderProcessingContext.js.map +1 -1
- package/Engines/WebGPU/webgpuShaderProcessor.d.ts +1 -1
- package/Engines/WebGPU/webgpuShaderProcessor.js +2 -2
- package/Engines/WebGPU/webgpuShaderProcessor.js.map +1 -1
- package/Engines/WebGPU/webgpuShaderProcessorsWGSL.js +20 -2
- package/Engines/WebGPU/webgpuShaderProcessorsWGSL.js.map +1 -1
- package/Engines/abstractEngine.js +2 -2
- package/Engines/abstractEngine.js.map +1 -1
- package/Engines/engine.d.ts +2 -1
- package/Engines/engineCapabilities.d.ts +2 -0
- package/Engines/engineCapabilities.js.map +1 -1
- package/Engines/nullEngine.js +1 -0
- package/Engines/nullEngine.js.map +1 -1
- package/Engines/thinEngine.js +1 -0
- package/Engines/thinEngine.js.map +1 -1
- package/Engines/thinNativeEngine.js +1 -0
- package/Engines/thinNativeEngine.js.map +1 -1
- package/Engines/webgpuEngine.js +1 -0
- package/Engines/webgpuEngine.js.map +1 -1
- package/FlowGraph/Blocks/Data/flowGraphDebugBlock.d.ts +45 -0
- package/FlowGraph/Blocks/Data/flowGraphDebugBlock.js +98 -0
- package/FlowGraph/Blocks/Data/flowGraphDebugBlock.js.map +1 -0
- package/FlowGraph/Blocks/Data/flowGraphGetPropertyBlock.d.ts +16 -0
- package/FlowGraph/Blocks/Data/flowGraphGetPropertyBlock.js +15 -2
- package/FlowGraph/Blocks/Data/flowGraphGetPropertyBlock.js.map +1 -1
- package/FlowGraph/Blocks/Event/flowGraphPointerDownEventBlock.d.ts +64 -0
- package/FlowGraph/Blocks/Event/flowGraphPointerDownEventBlock.js +54 -0
- package/FlowGraph/Blocks/Event/flowGraphPointerDownEventBlock.js.map +1 -0
- package/FlowGraph/Blocks/Event/flowGraphPointerMoveEventBlock.d.ts +64 -0
- package/FlowGraph/Blocks/Event/flowGraphPointerMoveEventBlock.js +54 -0
- package/FlowGraph/Blocks/Event/flowGraphPointerMoveEventBlock.js.map +1 -0
- package/FlowGraph/Blocks/Event/flowGraphPointerUpEventBlock.d.ts +64 -0
- package/FlowGraph/Blocks/Event/flowGraphPointerUpEventBlock.js +54 -0
- package/FlowGraph/Blocks/Event/flowGraphPointerUpEventBlock.js.map +1 -0
- package/FlowGraph/Blocks/Event/flowGraphReceiveCustomEventBlock.d.ts +1 -0
- package/FlowGraph/Blocks/Event/flowGraphReceiveCustomEventBlock.js +17 -1
- package/FlowGraph/Blocks/Event/flowGraphReceiveCustomEventBlock.js.map +1 -1
- package/FlowGraph/Blocks/Event/flowGraphSendCustomEventBlock.d.ts +1 -0
- package/FlowGraph/Blocks/Event/flowGraphSendCustomEventBlock.js +23 -3
- package/FlowGraph/Blocks/Event/flowGraphSendCustomEventBlock.js.map +1 -1
- package/FlowGraph/Blocks/Execution/Animation/flowGraphInterpolationBlock.js +2 -2
- package/FlowGraph/Blocks/Execution/Animation/flowGraphInterpolationBlock.js.map +1 -1
- package/FlowGraph/Blocks/Execution/Animation/flowGraphPlayAnimationBlock.js +7 -1
- package/FlowGraph/Blocks/Execution/Animation/flowGraphPlayAnimationBlock.js.map +1 -1
- package/FlowGraph/Blocks/Execution/flowGraphConsoleLogBlock.d.ts +4 -0
- package/FlowGraph/Blocks/Execution/flowGraphConsoleLogBlock.js +6 -2
- package/FlowGraph/Blocks/Execution/flowGraphConsoleLogBlock.js.map +1 -1
- package/FlowGraph/Blocks/Execution/flowGraphSetPropertyBlock.js +2 -2
- package/FlowGraph/Blocks/Execution/flowGraphSetPropertyBlock.js.map +1 -1
- package/FlowGraph/Blocks/Execution/flowGraphSetVariableBlock.js +0 -4
- package/FlowGraph/Blocks/Execution/flowGraphSetVariableBlock.js.map +1 -1
- package/FlowGraph/Blocks/flowGraphBlockFactory.js +16 -0
- package/FlowGraph/Blocks/flowGraphBlockFactory.js.map +1 -1
- package/FlowGraph/Blocks/flowGraphBlockNames.d.ts +2 -1
- package/FlowGraph/Blocks/flowGraphBlockNames.js +1 -0
- package/FlowGraph/Blocks/flowGraphBlockNames.js.map +1 -1
- package/FlowGraph/flowGraph.d.ts +63 -2
- package/FlowGraph/flowGraph.js +210 -19
- package/FlowGraph/flowGraph.js.map +1 -1
- package/FlowGraph/flowGraphContext.d.ts +73 -0
- package/FlowGraph/flowGraphContext.js +115 -0
- package/FlowGraph/flowGraphContext.js.map +1 -1
- package/FlowGraph/flowGraphExecutionBlock.d.ts +7 -0
- package/FlowGraph/flowGraphExecutionBlock.js +7 -0
- package/FlowGraph/flowGraphExecutionBlock.js.map +1 -1
- package/FlowGraph/flowGraphParser.js +1 -0
- package/FlowGraph/flowGraphParser.js.map +1 -1
- package/FlowGraph/flowGraphSceneEventCoordinator.d.ts +3 -0
- package/FlowGraph/flowGraphSceneEventCoordinator.js +13 -1
- package/FlowGraph/flowGraphSceneEventCoordinator.js.map +1 -1
- package/FlowGraph/flowGraphSignalConnection.d.ts +5 -0
- package/FlowGraph/flowGraphSignalConnection.js +12 -0
- package/FlowGraph/flowGraphSignalConnection.js.map +1 -1
- package/FlowGraph/flowGraphValidator.d.ts +66 -0
- package/FlowGraph/flowGraphValidator.js +324 -0
- package/FlowGraph/flowGraphValidator.js.map +1 -0
- package/FlowGraph/index.d.ts +1 -0
- package/FlowGraph/index.js +1 -0
- package/FlowGraph/index.js.map +1 -1
- package/FlowGraph/serialization.js +10 -3
- package/FlowGraph/serialization.js.map +1 -1
- package/Layers/thinEffectLayer.js +1 -1
- package/Layers/thinEffectLayer.js.map +1 -1
- package/Layers/thinSelectionOutlineLayer.js +1 -1
- package/Layers/thinSelectionOutlineLayer.js.map +1 -1
- package/Lights/Shadows/shadowGenerator.js +1 -1
- package/Lights/Shadows/shadowGenerator.js.map +1 -1
- package/Materials/Node/Blocks/Vertex/bonesBlock.js +2 -2
- package/Materials/Node/Blocks/Vertex/bonesBlock.js.map +1 -1
- package/Materials/PBR/openpbrMaterial.js +1 -1
- package/Materials/PBR/openpbrMaterial.js.map +1 -1
- package/Materials/PBR/pbrBaseMaterial.js +1 -1
- package/Materials/PBR/pbrBaseMaterial.js.map +1 -1
- package/Materials/materialHelper.functions.js +2 -2
- package/Materials/materialHelper.functions.js.map +1 -1
- package/Materials/materialHelper.geometryrendering.js +1 -1
- package/Materials/materialHelper.geometryrendering.js.map +1 -1
- package/Materials/standardMaterial.js +1 -1
- package/Materials/standardMaterial.js.map +1 -1
- package/Meshes/mesh.js +2 -2
- package/Meshes/mesh.js.map +1 -1
- package/Misc/bitArray.js +1 -1
- package/Misc/bitArray.js.map +1 -1
- package/Misc/tools.js +3 -3
- package/Misc/tools.js.map +1 -1
- package/Particles/thinParticleSystem.js +2 -2
- package/Particles/thinParticleSystem.js.map +1 -1
- package/PostProcesses/volumetricLightScatteringPostProcess.js +1 -1
- package/PostProcesses/volumetricLightScatteringPostProcess.js.map +1 -1
- package/Rendering/depthRenderer.js +1 -1
- package/Rendering/depthRenderer.js.map +1 -1
- package/Rendering/geometryBufferRenderer.js +3 -3
- package/Rendering/geometryBufferRenderer.js.map +1 -1
- package/Rendering/outlineRenderer.js +1 -1
- package/Rendering/outlineRenderer.js.map +1 -1
- package/Shaders/ShadersInclude/bonesDeclaration.js +5 -7
- package/Shaders/ShadersInclude/bonesDeclaration.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/bonesDeclaration.js +3 -3
- package/ShadersWGSL/ShadersInclude/bonesDeclaration.js.map +1 -1
- package/ShadersWGSL/boundingInfo.compute.js +4 -3
- package/ShadersWGSL/boundingInfo.compute.js.map +1 -1
- package/package.json +1 -1
|
@@ -13,6 +13,11 @@ export class FlowGraphSignalConnection extends FlowGraphConnection {
|
|
|
13
13
|
* Set priority before adding the connection as sorting happens only when the connection is added.
|
|
14
14
|
*/
|
|
15
15
|
this.priority = 0;
|
|
16
|
+
/**
|
|
17
|
+
* Timestamp of the last activation (set on output signals when they fire).
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
20
|
+
this._lastActivationTime = -1;
|
|
16
21
|
}
|
|
17
22
|
_isSingularConnection() {
|
|
18
23
|
return false;
|
|
@@ -26,6 +31,7 @@ export class FlowGraphSignalConnection extends FlowGraphConnection {
|
|
|
26
31
|
* @internal
|
|
27
32
|
*/
|
|
28
33
|
_activateSignal(context) {
|
|
34
|
+
this._lastActivationTime = performance.now();
|
|
29
35
|
context.logger?.addLogItem({
|
|
30
36
|
action: "ActivateSignal" /* FlowGraphAction.ActivateSignal */,
|
|
31
37
|
className: this._ownerBlock.getClassName(),
|
|
@@ -36,8 +42,14 @@ export class FlowGraphSignalConnection extends FlowGraphConnection {
|
|
|
36
42
|
},
|
|
37
43
|
});
|
|
38
44
|
if (this.connectionType === 0 /* FlowGraphConnectionType.Input */) {
|
|
45
|
+
// Check breakpoint before executing
|
|
46
|
+
if (context._shouldBreak(this._ownerBlock, this)) {
|
|
47
|
+
return; // Execution paused — stored as pending activation
|
|
48
|
+
}
|
|
39
49
|
context._notifyExecuteNode(this._ownerBlock);
|
|
50
|
+
const startTime = performance.now();
|
|
40
51
|
this._ownerBlock._execute(context, this);
|
|
52
|
+
this._ownerBlock._lastExecutionTime = performance.now() - startTime;
|
|
41
53
|
context._increaseExecutionId();
|
|
42
54
|
}
|
|
43
55
|
else {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flowGraphSignalConnection.js","sourceRoot":"","sources":["../../../../dev/core/src/FlowGraph/flowGraphSignalConnection.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAA2B,MAAM,uBAAuB,CAAC;AAErF,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGlD;;;;GAIG;AACH,MAAM,OAAO,yBAA0B,SAAQ,mBAAuE;IAAtH;;QAMI;;;WAGG;QACI,aAAQ,GAAW,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"flowGraphSignalConnection.js","sourceRoot":"","sources":["../../../../dev/core/src/FlowGraph/flowGraphSignalConnection.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAA2B,MAAM,uBAAuB,CAAC;AAErF,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGlD;;;;GAIG;AACH,MAAM,OAAO,yBAA0B,SAAQ,mBAAuE;IAAtH;;QAMI;;;WAGG;QACI,aAAQ,GAAW,CAAC,CAAC;QAY5B;;;WAGG;QACI,wBAAmB,GAAW,CAAC,CAAC,CAAC;IAgC5C,CAAC;IA9CmB,qBAAqB;QACjC,OAAO,KAAK,CAAC;IACjB,CAAC;IAEe,SAAS,CAAC,KAAgC;QACtD,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACvB,uDAAuD;QACvD,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;IACjE,CAAC;IAQD;;OAEG;IACI,eAAe,CAAC,OAAyB;QAC5C,IAAI,CAAC,mBAAmB,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAC7C,OAAO,CAAC,MAAM,EAAE,UAAU,CAAC;YACvB,MAAM,uDAAgC;YACtC,SAAS,EAAE,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE;YAC1C,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,QAAQ;YACnC,OAAO,EAAE;gBACL,cAAc,EAAE,IAAI,CAAC,cAAc;gBACnC,IAAI,EAAE,IAAI,CAAC,IAAI;aAClB;SACJ,CAAC,CAAC;QACH,IAAI,IAAI,CAAC,cAAc,0CAAkC,EAAE,CAAC;YACxD,oCAAoC;YACpC,IAAI,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,EAAE,CAAC;gBAC/C,OAAO,CAAC,kDAAkD;YAC9D,CAAC;YACD,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC7C,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;YACpC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YACzC,IAAI,CAAC,WAAW,CAAC,kBAAkB,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YACpE,OAAO,CAAC,oBAAoB,EAAE,CAAC;QACnC,CAAC;aAAM,CAAC;YACJ,KAAK,MAAM,cAAc,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;gBAChD,cAAc,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;YAC5C,CAAC;QACL,CAAC;IACL,CAAC;CACJ;AAED,aAAa,CAAC,2BAA2B,EAAE,yBAAyB,CAAC,CAAC","sourcesContent":["import type { FlowGraphExecutionBlock } from \"./flowGraphExecutionBlock\";\r\nimport { FlowGraphConnection, FlowGraphConnectionType } from \"./flowGraphConnection\";\r\nimport type { FlowGraphContext } from \"./flowGraphContext\";\r\nimport { RegisterClass } from \"../Misc/typeStore\";\r\nimport { FlowGraphAction } from \"./flowGraphLogger\";\r\n\r\n/**\r\n * Represents a connection point for a signal.\r\n * When an output point is activated, it will activate the connected input point.\r\n * When an input point is activated, it will execute the block it belongs to.\r\n */\r\nexport class FlowGraphSignalConnection extends FlowGraphConnection<FlowGraphExecutionBlock, FlowGraphSignalConnection> {\r\n /**\r\n * Optional payload. Can be used, for example, when an error is thrown to pass additional information.\r\n */\r\n public payload: any;\r\n\r\n /**\r\n * The priority of the signal. Signals with higher priority will be executed first.\r\n * Set priority before adding the connection as sorting happens only when the connection is added.\r\n */\r\n public priority: number = 0;\r\n\r\n public override _isSingularConnection(): boolean {\r\n return false;\r\n }\r\n\r\n public override connectTo(point: FlowGraphSignalConnection): void {\r\n super.connectTo(point);\r\n // sort according to priority to handle execution order\r\n this._connectedPoint.sort((a, b) => b.priority - a.priority);\r\n }\r\n\r\n /**\r\n * Timestamp of the last activation (set on output signals when they fire).\r\n * @internal\r\n */\r\n public _lastActivationTime: number = -1;\r\n\r\n /**\r\n * @internal\r\n */\r\n public _activateSignal(context: FlowGraphContext): void {\r\n this._lastActivationTime = performance.now();\r\n context.logger?.addLogItem({\r\n action: FlowGraphAction.ActivateSignal,\r\n className: this._ownerBlock.getClassName(),\r\n uniqueId: this._ownerBlock.uniqueId,\r\n payload: {\r\n connectionType: this.connectionType,\r\n name: this.name,\r\n },\r\n });\r\n if (this.connectionType === FlowGraphConnectionType.Input) {\r\n // Check breakpoint before executing\r\n if (context._shouldBreak(this._ownerBlock, this)) {\r\n return; // Execution paused — stored as pending activation\r\n }\r\n context._notifyExecuteNode(this._ownerBlock);\r\n const startTime = performance.now();\r\n this._ownerBlock._execute(context, this);\r\n this._ownerBlock._lastExecutionTime = performance.now() - startTime;\r\n context._increaseExecutionId();\r\n } else {\r\n for (const connectedPoint of this._connectedPoint) {\r\n connectedPoint._activateSignal(context);\r\n }\r\n }\r\n }\r\n}\r\n\r\nRegisterClass(\"FlowGraphSignalConnection\", FlowGraphSignalConnection);\r\n"]}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { FlowGraph } from "./flowGraph.js";
|
|
2
|
+
import type { FlowGraphBlock } from "./flowGraphBlock.js";
|
|
3
|
+
/**
|
|
4
|
+
* Severity level for a validation issue.
|
|
5
|
+
*/
|
|
6
|
+
export declare enum FlowGraphValidationSeverity {
|
|
7
|
+
/** A critical issue that will cause runtime failure. */
|
|
8
|
+
Error = 0,
|
|
9
|
+
/** A potential issue that may indicate a mistake. */
|
|
10
|
+
Warning = 1
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* A single validation issue found in the flow graph.
|
|
14
|
+
*/
|
|
15
|
+
export interface IFlowGraphValidationIssue {
|
|
16
|
+
/** The severity level. */
|
|
17
|
+
severity: FlowGraphValidationSeverity;
|
|
18
|
+
/** Human-readable description of the issue. */
|
|
19
|
+
message: string;
|
|
20
|
+
/** The block where the issue was found (if applicable). */
|
|
21
|
+
block?: FlowGraphBlock;
|
|
22
|
+
/** The connection name involved (if applicable). */
|
|
23
|
+
connectionName?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The result of validating a flow graph.
|
|
27
|
+
*/
|
|
28
|
+
export interface IFlowGraphValidationResult {
|
|
29
|
+
/** Whether the graph passed validation with no errors. */
|
|
30
|
+
isValid: boolean;
|
|
31
|
+
/** All issues found, ordered by severity (errors first). */
|
|
32
|
+
issues: IFlowGraphValidationIssue[];
|
|
33
|
+
/** Convenience: number of error-level issues. */
|
|
34
|
+
errorCount: number;
|
|
35
|
+
/** Convenience: number of warning-level issues. */
|
|
36
|
+
warningCount: number;
|
|
37
|
+
/** Map from block uniqueId to the issues affecting that block. */
|
|
38
|
+
issuesByBlock: Map<string, IFlowGraphValidationIssue[]>;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Validates a flow graph and returns all issues found.
|
|
42
|
+
*
|
|
43
|
+
* The following checks are performed:
|
|
44
|
+
* 1. **No event blocks** — the graph has no entry points.
|
|
45
|
+
* 2. **Unconnected required data inputs** — a non-optional data input with no connection.
|
|
46
|
+
* 3. **Unconnected signal inputs** — an execution block whose `in` signal has no connection and
|
|
47
|
+
* that is not an event block (entry point).
|
|
48
|
+
* 4. **Data type mismatches** — a data connection whose source richType is incompatible with the
|
|
49
|
+
* target richType.
|
|
50
|
+
* 5. **Unreachable blocks** — blocks not reachable from any event block via signal/data traversal.
|
|
51
|
+
* 6. **Data dependency cycles** — circular data-only connections that would cause infinite recursion.
|
|
52
|
+
*
|
|
53
|
+
* @param flowGraph - The flow graph to validate.
|
|
54
|
+
* @returns The validation result.
|
|
55
|
+
*/
|
|
56
|
+
export declare function ValidateFlowGraph(flowGraph: FlowGraph): IFlowGraphValidationResult;
|
|
57
|
+
/**
|
|
58
|
+
* Extended validation that also checks for unreachable blocks.
|
|
59
|
+
* Requires a full list of all blocks in the graph (including those not reachable
|
|
60
|
+
* from event blocks via the normal traversal).
|
|
61
|
+
*
|
|
62
|
+
* @param flowGraph - The flow graph to validate.
|
|
63
|
+
* @param allKnownBlocks - Complete list of all blocks (e.g., from the editor's node set).
|
|
64
|
+
* @returns The validation result.
|
|
65
|
+
*/
|
|
66
|
+
export declare function ValidateFlowGraphWithBlockList(flowGraph: FlowGraph, allKnownBlocks: FlowGraphBlock[]): IFlowGraphValidationResult;
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
import { FlowGraphExecutionBlock } from "./flowGraphExecutionBlock.js";
|
|
2
|
+
import { FlowGraphEventBlock } from "./flowGraphEventBlock.js";
|
|
3
|
+
/**
|
|
4
|
+
* Severity level for a validation issue.
|
|
5
|
+
*/
|
|
6
|
+
export var FlowGraphValidationSeverity;
|
|
7
|
+
(function (FlowGraphValidationSeverity) {
|
|
8
|
+
/** A critical issue that will cause runtime failure. */
|
|
9
|
+
FlowGraphValidationSeverity[FlowGraphValidationSeverity["Error"] = 0] = "Error";
|
|
10
|
+
/** A potential issue that may indicate a mistake. */
|
|
11
|
+
FlowGraphValidationSeverity[FlowGraphValidationSeverity["Warning"] = 1] = "Warning";
|
|
12
|
+
})(FlowGraphValidationSeverity || (FlowGraphValidationSeverity = {}));
|
|
13
|
+
// Types that are mutually coercible and should not produce type-mismatch warnings
|
|
14
|
+
const NumericLikeTypes = new Set(["number" /* FlowGraphTypes.Number */, "FlowGraphInteger" /* FlowGraphTypes.Integer */, "boolean" /* FlowGraphTypes.Boolean */]);
|
|
15
|
+
const VectorLikeTypes = new Set(["Vector4" /* FlowGraphTypes.Vector4 */, "Quaternion" /* FlowGraphTypes.Quaternion */]);
|
|
16
|
+
const ColorLikeTypes = new Set(["Color3" /* FlowGraphTypes.Color3 */, "Color4" /* FlowGraphTypes.Color4 */]);
|
|
17
|
+
/**
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
20
|
+
function _AreTypesCompatible(sourceType, targetType) {
|
|
21
|
+
if (sourceType === targetType) {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
// "any" is compatible with everything
|
|
25
|
+
if (sourceType === "any" /* FlowGraphTypes.Any */ || targetType === "any" /* FlowGraphTypes.Any */) {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
// Numeric coercion group
|
|
29
|
+
if (NumericLikeTypes.has(sourceType) && NumericLikeTypes.has(targetType)) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
// Vector4 / Quaternion are interchangeable
|
|
33
|
+
if (VectorLikeTypes.has(sourceType) && VectorLikeTypes.has(targetType)) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
// Color3 → Color4 widening is safe
|
|
37
|
+
if (ColorLikeTypes.has(sourceType) && ColorLikeTypes.has(targetType)) {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Validates a flow graph and returns all issues found.
|
|
44
|
+
*
|
|
45
|
+
* The following checks are performed:
|
|
46
|
+
* 1. **No event blocks** — the graph has no entry points.
|
|
47
|
+
* 2. **Unconnected required data inputs** — a non-optional data input with no connection.
|
|
48
|
+
* 3. **Unconnected signal inputs** — an execution block whose `in` signal has no connection and
|
|
49
|
+
* that is not an event block (entry point).
|
|
50
|
+
* 4. **Data type mismatches** — a data connection whose source richType is incompatible with the
|
|
51
|
+
* target richType.
|
|
52
|
+
* 5. **Unreachable blocks** — blocks not reachable from any event block via signal/data traversal.
|
|
53
|
+
* 6. **Data dependency cycles** — circular data-only connections that would cause infinite recursion.
|
|
54
|
+
*
|
|
55
|
+
* @param flowGraph - The flow graph to validate.
|
|
56
|
+
* @returns The validation result.
|
|
57
|
+
*/
|
|
58
|
+
export function ValidateFlowGraph(flowGraph) {
|
|
59
|
+
const issues = [];
|
|
60
|
+
const issuesByBlock = new Map();
|
|
61
|
+
const addIssue = (issue) => {
|
|
62
|
+
issues.push(issue);
|
|
63
|
+
if (issue.block) {
|
|
64
|
+
let arr = issuesByBlock.get(issue.block.uniqueId);
|
|
65
|
+
if (!arr) {
|
|
66
|
+
arr = [];
|
|
67
|
+
issuesByBlock.set(issue.block.uniqueId, arr);
|
|
68
|
+
}
|
|
69
|
+
arr.push(issue);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
// Collect ALL blocks via visitAllBlocks
|
|
73
|
+
const allBlocks = [];
|
|
74
|
+
flowGraph.visitAllBlocks((block) => {
|
|
75
|
+
allBlocks.push(block);
|
|
76
|
+
});
|
|
77
|
+
// ── Check 1: No event blocks ───────────────────────────────────────
|
|
78
|
+
const eventBlocks = _GetEventBlocks(flowGraph);
|
|
79
|
+
if (eventBlocks.length === 0) {
|
|
80
|
+
addIssue({
|
|
81
|
+
severity: 0 /* FlowGraphValidationSeverity.Error */,
|
|
82
|
+
message: "Graph has no event blocks — nothing will trigger execution.",
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
// ── Check 2: Unconnected required data inputs ──────────────────────
|
|
86
|
+
for (const block of allBlocks) {
|
|
87
|
+
for (const input of block.dataInputs) {
|
|
88
|
+
if (!input.optional && !input.isDisabled && !input.isConnected()) {
|
|
89
|
+
addIssue({
|
|
90
|
+
severity: 1 /* FlowGraphValidationSeverity.Warning */,
|
|
91
|
+
message: `"${input.name}" is not connected and will use its default value.`,
|
|
92
|
+
block,
|
|
93
|
+
connectionName: input.name,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// ── Check 3: Unconnected signal inputs on non-event execution blocks
|
|
99
|
+
for (const block of allBlocks) {
|
|
100
|
+
if (block instanceof FlowGraphExecutionBlock) {
|
|
101
|
+
// Skip event blocks — they are entry points and don't need an incoming signal.
|
|
102
|
+
if (_IsEventBlock(block)) {
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
const inSignal = block.signalInputs.find((s) => s.name === "in");
|
|
106
|
+
if (inSignal && !inSignal.isConnected()) {
|
|
107
|
+
addIssue({
|
|
108
|
+
severity: 0 /* FlowGraphValidationSeverity.Error */,
|
|
109
|
+
message: `Execution block has no incoming signal — it will never execute.`,
|
|
110
|
+
block,
|
|
111
|
+
connectionName: "in",
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// ── Check 4: Data type mismatches ──────────────────────────────────
|
|
117
|
+
for (const block of allBlocks) {
|
|
118
|
+
for (const input of block.dataInputs) {
|
|
119
|
+
if (!input.isConnected()) {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
const source = input._connectedPoint[0];
|
|
123
|
+
const srcType = source.richType?.typeName;
|
|
124
|
+
const tgtType = input.richType?.typeName;
|
|
125
|
+
if (srcType && tgtType && !_AreTypesCompatible(srcType, tgtType)) {
|
|
126
|
+
// If either side has a typeTransformer, it's intentionally converted
|
|
127
|
+
if (source.richType.typeTransformer !== undefined || input.richType.typeTransformer !== undefined) {
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
addIssue({
|
|
131
|
+
severity: 1 /* FlowGraphValidationSeverity.Warning */,
|
|
132
|
+
message: `Type mismatch: "${source._ownerBlock.name}.${source.name}" (${srcType}) → "${block.name}.${input.name}" (${tgtType}).`,
|
|
133
|
+
block,
|
|
134
|
+
connectionName: input.name,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// ── Check 5: Unreachable blocks ────────────────────────────────────
|
|
140
|
+
const reachableIds = new Set();
|
|
141
|
+
flowGraph.visitAllBlocks((block) => {
|
|
142
|
+
reachableIds.add(block.uniqueId);
|
|
143
|
+
});
|
|
144
|
+
// We need to also check standalone data blocks not visited by visitAllBlocks.
|
|
145
|
+
// visitAllBlocks starts from event blocks; any block not found is unreachable.
|
|
146
|
+
// Since we can only iterate blocks we know about, the allBlocks list IS
|
|
147
|
+
// from visitAllBlocks, so everything in it IS reachable.
|
|
148
|
+
// There's no separate registry of "all added blocks" in the FlowGraph.
|
|
149
|
+
// So: unreachable blocks are blocks that exist but aren't visited.
|
|
150
|
+
// Currently visitAllBlocks IS our source, so this check is a no-op for
|
|
151
|
+
// blocks added via the graph. However, the editor creates nodes and adds
|
|
152
|
+
// execution blocks, so we should compare against the editor's full list.
|
|
153
|
+
// For the core validator, we expose a variant that accepts an external block list.
|
|
154
|
+
// ── Check 6: Data dependency cycles ────────────────────────────────
|
|
155
|
+
_DetectDataCycles(allBlocks, addIssue);
|
|
156
|
+
// Sort: errors first, then warnings
|
|
157
|
+
issues.sort((a, b) => a.severity - b.severity);
|
|
158
|
+
return {
|
|
159
|
+
isValid: issues.every((i) => i.severity !== 0 /* FlowGraphValidationSeverity.Error */),
|
|
160
|
+
issues,
|
|
161
|
+
errorCount: issues.filter((i) => i.severity === 0 /* FlowGraphValidationSeverity.Error */).length,
|
|
162
|
+
warningCount: issues.filter((i) => i.severity === 1 /* FlowGraphValidationSeverity.Warning */).length,
|
|
163
|
+
issuesByBlock,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Extended validation that also checks for unreachable blocks.
|
|
168
|
+
* Requires a full list of all blocks in the graph (including those not reachable
|
|
169
|
+
* from event blocks via the normal traversal).
|
|
170
|
+
*
|
|
171
|
+
* @param flowGraph - The flow graph to validate.
|
|
172
|
+
* @param allKnownBlocks - Complete list of all blocks (e.g., from the editor's node set).
|
|
173
|
+
* @returns The validation result.
|
|
174
|
+
*/
|
|
175
|
+
export function ValidateFlowGraphWithBlockList(flowGraph, allKnownBlocks) {
|
|
176
|
+
const result = ValidateFlowGraph(flowGraph);
|
|
177
|
+
// Check for unreachable blocks
|
|
178
|
+
const reachableIds = new Set();
|
|
179
|
+
flowGraph.visitAllBlocks((block) => {
|
|
180
|
+
reachableIds.add(block.uniqueId);
|
|
181
|
+
});
|
|
182
|
+
for (const block of allKnownBlocks) {
|
|
183
|
+
if (!reachableIds.has(block.uniqueId)) {
|
|
184
|
+
const issue = {
|
|
185
|
+
severity: 1 /* FlowGraphValidationSeverity.Warning */,
|
|
186
|
+
message: `Block is unreachable from any event block.`,
|
|
187
|
+
block,
|
|
188
|
+
};
|
|
189
|
+
result.issues.push(issue);
|
|
190
|
+
result.warningCount++;
|
|
191
|
+
let arr = result.issuesByBlock.get(block.uniqueId);
|
|
192
|
+
if (!arr) {
|
|
193
|
+
arr = [];
|
|
194
|
+
result.issuesByBlock.set(block.uniqueId, arr);
|
|
195
|
+
}
|
|
196
|
+
arr.push(issue);
|
|
197
|
+
// Also run Check 2 and Check 3 on unreachable blocks so the editor
|
|
198
|
+
// can display all issues, not just reachability ones.
|
|
199
|
+
for (const input of block.dataInputs) {
|
|
200
|
+
if (!input.optional && !input.isDisabled && !input.isConnected()) {
|
|
201
|
+
const dataIssue = {
|
|
202
|
+
severity: 1 /* FlowGraphValidationSeverity.Warning */,
|
|
203
|
+
message: `"${input.name}" is not connected and will use its default value.`,
|
|
204
|
+
block,
|
|
205
|
+
connectionName: input.name,
|
|
206
|
+
};
|
|
207
|
+
result.issues.push(dataIssue);
|
|
208
|
+
result.warningCount++;
|
|
209
|
+
arr.push(dataIssue);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
if (block instanceof FlowGraphExecutionBlock && !_IsEventBlock(block)) {
|
|
213
|
+
const inSignal = block.signalInputs.find((s) => s.name === "in");
|
|
214
|
+
if (inSignal && !inSignal.isConnected()) {
|
|
215
|
+
const signalIssue = {
|
|
216
|
+
severity: 0 /* FlowGraphValidationSeverity.Error */,
|
|
217
|
+
message: `Execution block has no incoming signal — it will never execute.`,
|
|
218
|
+
block,
|
|
219
|
+
connectionName: "in",
|
|
220
|
+
};
|
|
221
|
+
result.issues.push(signalIssue);
|
|
222
|
+
result.errorCount++;
|
|
223
|
+
arr.push(signalIssue);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
result.isValid = result.issues.every((i) => i.severity !== 0 /* FlowGraphValidationSeverity.Error */);
|
|
229
|
+
result.issues.sort((a, b) => a.severity - b.severity);
|
|
230
|
+
return result;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Get all event blocks from a flow graph.
|
|
234
|
+
* @param flowGraph - the flow graph
|
|
235
|
+
* @returns the event blocks
|
|
236
|
+
*/
|
|
237
|
+
function _GetEventBlocks(flowGraph) {
|
|
238
|
+
const eventBlocks = [];
|
|
239
|
+
for (const type in flowGraph._eventBlocks) {
|
|
240
|
+
for (const block of flowGraph._eventBlocks[type]) {
|
|
241
|
+
eventBlocks.push(block);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return eventBlocks;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Detect whether a block is an event block (entry point).
|
|
248
|
+
* @param block - the block to check
|
|
249
|
+
* @returns true if it is an event block
|
|
250
|
+
*/
|
|
251
|
+
function _IsEventBlock(block) {
|
|
252
|
+
return block instanceof FlowGraphEventBlock;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Detects cycles among data-only blocks.
|
|
256
|
+
* A data cycle means that block A's output feeds into block B's input, and
|
|
257
|
+
* block B's output feeds back into block A (directly or indirectly).
|
|
258
|
+
* This would cause infinite recursion during getValue().
|
|
259
|
+
* @param allBlocks - all blocks to check
|
|
260
|
+
* @param addIssue - callback to report issues
|
|
261
|
+
*/
|
|
262
|
+
function _DetectDataCycles(allBlocks, addIssue) {
|
|
263
|
+
// Build adjacency: for each block, which blocks do its data inputs depend on?
|
|
264
|
+
// (Data inputs pull values from connected output blocks.)
|
|
265
|
+
const white = 0; // unvisited
|
|
266
|
+
const gray = 1; // in current DFS path
|
|
267
|
+
const black = 2; // fully explored
|
|
268
|
+
const color = new Map();
|
|
269
|
+
for (const block of allBlocks) {
|
|
270
|
+
color.set(block.uniqueId, white);
|
|
271
|
+
}
|
|
272
|
+
const blockMap = new Map();
|
|
273
|
+
for (const block of allBlocks) {
|
|
274
|
+
blockMap.set(block.uniqueId, block);
|
|
275
|
+
}
|
|
276
|
+
const reportedCycleBlocks = new Set();
|
|
277
|
+
function dfs(block) {
|
|
278
|
+
color.set(block.uniqueId, gray);
|
|
279
|
+
for (const input of block.dataInputs) {
|
|
280
|
+
if (!input.isConnected()) {
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
for (const connected of input._connectedPoint) {
|
|
284
|
+
const dep = connected._ownerBlock;
|
|
285
|
+
// Only consider data-only blocks (not execution blocks which are driven by signals)
|
|
286
|
+
if (dep instanceof FlowGraphExecutionBlock) {
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
const depColor = color.get(dep.uniqueId);
|
|
290
|
+
if (depColor === gray) {
|
|
291
|
+
// Cycle found
|
|
292
|
+
if (!reportedCycleBlocks.has(block.uniqueId)) {
|
|
293
|
+
reportedCycleBlocks.add(block.uniqueId);
|
|
294
|
+
addIssue({
|
|
295
|
+
severity: 0 /* FlowGraphValidationSeverity.Error */,
|
|
296
|
+
message: `Data dependency cycle detected — getValue() will recurse infinitely.`,
|
|
297
|
+
block,
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
if (!reportedCycleBlocks.has(dep.uniqueId)) {
|
|
301
|
+
reportedCycleBlocks.add(dep.uniqueId);
|
|
302
|
+
addIssue({
|
|
303
|
+
severity: 0 /* FlowGraphValidationSeverity.Error */,
|
|
304
|
+
message: `Data dependency cycle detected — getValue() will recurse infinitely.`,
|
|
305
|
+
block: dep,
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
return true;
|
|
309
|
+
}
|
|
310
|
+
if (depColor === white) {
|
|
311
|
+
dfs(dep);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
color.set(block.uniqueId, black);
|
|
316
|
+
return false;
|
|
317
|
+
}
|
|
318
|
+
for (const block of allBlocks) {
|
|
319
|
+
if (color.get(block.uniqueId) === white) {
|
|
320
|
+
dfs(block);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
//# sourceMappingURL=flowGraphValidator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flowGraphValidator.js","sourceRoot":"","sources":["../../../../dev/core/src/FlowGraph/flowGraphValidator.ts"],"names":[],"mappings":"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","sourcesContent":["import type { FlowGraph } from \"./flowGraph\";\nimport type { FlowGraphBlock } from \"./flowGraphBlock\";\nimport { FlowGraphExecutionBlock } from \"./flowGraphExecutionBlock\";\nimport type { FlowGraphDataConnection } from \"./flowGraphDataConnection\";\nimport { FlowGraphTypes } from \"./flowGraphRichTypes\";\nimport { FlowGraphEventBlock } from \"./flowGraphEventBlock\";\nimport type { FlowGraphEventType } from \"./flowGraphEventType\";\n\n/**\n * Severity level for a validation issue.\n */\nexport const enum FlowGraphValidationSeverity {\n /** A critical issue that will cause runtime failure. */\n Error,\n /** A potential issue that may indicate a mistake. */\n Warning,\n}\n\n/**\n * A single validation issue found in the flow graph.\n */\nexport interface IFlowGraphValidationIssue {\n /** The severity level. */\n severity: FlowGraphValidationSeverity;\n /** Human-readable description of the issue. */\n message: string;\n /** The block where the issue was found (if applicable). */\n block?: FlowGraphBlock;\n /** The connection name involved (if applicable). */\n connectionName?: string;\n}\n\n/**\n * The result of validating a flow graph.\n */\nexport interface IFlowGraphValidationResult {\n /** Whether the graph passed validation with no errors. */\n isValid: boolean;\n /** All issues found, ordered by severity (errors first). */\n issues: IFlowGraphValidationIssue[];\n /** Convenience: number of error-level issues. */\n errorCount: number;\n /** Convenience: number of warning-level issues. */\n warningCount: number;\n /** Map from block uniqueId to the issues affecting that block. */\n issuesByBlock: Map<string, IFlowGraphValidationIssue[]>;\n}\n\n// Types that are mutually coercible and should not produce type-mismatch warnings\nconst NumericLikeTypes = new Set<string>([FlowGraphTypes.Number, FlowGraphTypes.Integer, FlowGraphTypes.Boolean]);\nconst VectorLikeTypes = new Set<string>([FlowGraphTypes.Vector4, FlowGraphTypes.Quaternion]);\nconst ColorLikeTypes = new Set<string>([FlowGraphTypes.Color3, FlowGraphTypes.Color4]);\n\n/**\n * @internal\n */\nfunction _AreTypesCompatible(sourceType: string, targetType: string): boolean {\n if (sourceType === targetType) {\n return true;\n }\n // \"any\" is compatible with everything\n if (sourceType === FlowGraphTypes.Any || targetType === FlowGraphTypes.Any) {\n return true;\n }\n // Numeric coercion group\n if (NumericLikeTypes.has(sourceType) && NumericLikeTypes.has(targetType)) {\n return true;\n }\n // Vector4 / Quaternion are interchangeable\n if (VectorLikeTypes.has(sourceType) && VectorLikeTypes.has(targetType)) {\n return true;\n }\n // Color3 → Color4 widening is safe\n if (ColorLikeTypes.has(sourceType) && ColorLikeTypes.has(targetType)) {\n return true;\n }\n return false;\n}\n\n/**\n * Validates a flow graph and returns all issues found.\n *\n * The following checks are performed:\n * 1. **No event blocks** — the graph has no entry points.\n * 2. **Unconnected required data inputs** — a non-optional data input with no connection.\n * 3. **Unconnected signal inputs** — an execution block whose `in` signal has no connection and\n * that is not an event block (entry point).\n * 4. **Data type mismatches** — a data connection whose source richType is incompatible with the\n * target richType.\n * 5. **Unreachable blocks** — blocks not reachable from any event block via signal/data traversal.\n * 6. **Data dependency cycles** — circular data-only connections that would cause infinite recursion.\n *\n * @param flowGraph - The flow graph to validate.\n * @returns The validation result.\n */\nexport function ValidateFlowGraph(flowGraph: FlowGraph): IFlowGraphValidationResult {\n const issues: IFlowGraphValidationIssue[] = [];\n const issuesByBlock = new Map<string, IFlowGraphValidationIssue[]>();\n\n const addIssue = (issue: IFlowGraphValidationIssue) => {\n issues.push(issue);\n if (issue.block) {\n let arr = issuesByBlock.get(issue.block.uniqueId);\n if (!arr) {\n arr = [];\n issuesByBlock.set(issue.block.uniqueId, arr);\n }\n arr.push(issue);\n }\n };\n\n // Collect ALL blocks via visitAllBlocks\n const allBlocks: FlowGraphBlock[] = [];\n flowGraph.visitAllBlocks((block) => {\n allBlocks.push(block);\n });\n\n // ── Check 1: No event blocks ───────────────────────────────────────\n const eventBlocks = _GetEventBlocks(flowGraph);\n if (eventBlocks.length === 0) {\n addIssue({\n severity: FlowGraphValidationSeverity.Error,\n message: \"Graph has no event blocks — nothing will trigger execution.\",\n });\n }\n\n // ── Check 2: Unconnected required data inputs ──────────────────────\n for (const block of allBlocks) {\n for (const input of block.dataInputs) {\n if (!input.optional && !input.isDisabled && !input.isConnected()) {\n addIssue({\n severity: FlowGraphValidationSeverity.Warning,\n message: `\"${input.name}\" is not connected and will use its default value.`,\n block,\n connectionName: input.name,\n });\n }\n }\n }\n\n // ── Check 3: Unconnected signal inputs on non-event execution blocks\n for (const block of allBlocks) {\n if (block instanceof FlowGraphExecutionBlock) {\n // Skip event blocks — they are entry points and don't need an incoming signal.\n if (_IsEventBlock(block)) {\n continue;\n }\n const inSignal = block.signalInputs.find((s) => s.name === \"in\");\n if (inSignal && !inSignal.isConnected()) {\n addIssue({\n severity: FlowGraphValidationSeverity.Error,\n message: `Execution block has no incoming signal — it will never execute.`,\n block,\n connectionName: \"in\",\n });\n }\n }\n }\n\n // ── Check 4: Data type mismatches ──────────────────────────────────\n for (const block of allBlocks) {\n for (const input of block.dataInputs) {\n if (!input.isConnected()) {\n continue;\n }\n const source = input._connectedPoint[0] as FlowGraphDataConnection<any>;\n const srcType = source.richType?.typeName;\n const tgtType = input.richType?.typeName;\n if (srcType && tgtType && !_AreTypesCompatible(srcType, tgtType)) {\n // If either side has a typeTransformer, it's intentionally converted\n if (source.richType.typeTransformer !== undefined || input.richType.typeTransformer !== undefined) {\n continue;\n }\n addIssue({\n severity: FlowGraphValidationSeverity.Warning,\n message: `Type mismatch: \"${source._ownerBlock.name}.${source.name}\" (${srcType}) → \"${block.name}.${input.name}\" (${tgtType}).`,\n block,\n connectionName: input.name,\n });\n }\n }\n }\n\n // ── Check 5: Unreachable blocks ────────────────────────────────────\n const reachableIds = new Set<string>();\n flowGraph.visitAllBlocks((block) => {\n reachableIds.add(block.uniqueId);\n });\n // We need to also check standalone data blocks not visited by visitAllBlocks.\n // visitAllBlocks starts from event blocks; any block not found is unreachable.\n // Since we can only iterate blocks we know about, the allBlocks list IS\n // from visitAllBlocks, so everything in it IS reachable.\n // There's no separate registry of \"all added blocks\" in the FlowGraph.\n // So: unreachable blocks are blocks that exist but aren't visited.\n // Currently visitAllBlocks IS our source, so this check is a no-op for\n // blocks added via the graph. However, the editor creates nodes and adds\n // execution blocks, so we should compare against the editor's full list.\n // For the core validator, we expose a variant that accepts an external block list.\n\n // ── Check 6: Data dependency cycles ────────────────────────────────\n _DetectDataCycles(allBlocks, addIssue);\n\n // Sort: errors first, then warnings\n issues.sort((a, b) => a.severity - b.severity);\n\n return {\n isValid: issues.every((i) => i.severity !== FlowGraphValidationSeverity.Error),\n issues,\n errorCount: issues.filter((i) => i.severity === FlowGraphValidationSeverity.Error).length,\n warningCount: issues.filter((i) => i.severity === FlowGraphValidationSeverity.Warning).length,\n issuesByBlock,\n };\n}\n\n/**\n * Extended validation that also checks for unreachable blocks.\n * Requires a full list of all blocks in the graph (including those not reachable\n * from event blocks via the normal traversal).\n *\n * @param flowGraph - The flow graph to validate.\n * @param allKnownBlocks - Complete list of all blocks (e.g., from the editor's node set).\n * @returns The validation result.\n */\nexport function ValidateFlowGraphWithBlockList(flowGraph: FlowGraph, allKnownBlocks: FlowGraphBlock[]): IFlowGraphValidationResult {\n const result = ValidateFlowGraph(flowGraph);\n\n // Check for unreachable blocks\n const reachableIds = new Set<string>();\n flowGraph.visitAllBlocks((block) => {\n reachableIds.add(block.uniqueId);\n });\n\n for (const block of allKnownBlocks) {\n if (!reachableIds.has(block.uniqueId)) {\n const issue: IFlowGraphValidationIssue = {\n severity: FlowGraphValidationSeverity.Warning,\n message: `Block is unreachable from any event block.`,\n block,\n };\n result.issues.push(issue);\n result.warningCount++;\n let arr = result.issuesByBlock.get(block.uniqueId);\n if (!arr) {\n arr = [];\n result.issuesByBlock.set(block.uniqueId, arr);\n }\n arr.push(issue);\n\n // Also run Check 2 and Check 3 on unreachable blocks so the editor\n // can display all issues, not just reachability ones.\n for (const input of block.dataInputs) {\n if (!input.optional && !input.isDisabled && !input.isConnected()) {\n const dataIssue: IFlowGraphValidationIssue = {\n severity: FlowGraphValidationSeverity.Warning,\n message: `\"${input.name}\" is not connected and will use its default value.`,\n block,\n connectionName: input.name,\n };\n result.issues.push(dataIssue);\n result.warningCount++;\n arr.push(dataIssue);\n }\n }\n\n if (block instanceof FlowGraphExecutionBlock && !_IsEventBlock(block)) {\n const inSignal = block.signalInputs.find((s) => s.name === \"in\");\n if (inSignal && !inSignal.isConnected()) {\n const signalIssue: IFlowGraphValidationIssue = {\n severity: FlowGraphValidationSeverity.Error,\n message: `Execution block has no incoming signal — it will never execute.`,\n block,\n connectionName: \"in\",\n };\n result.issues.push(signalIssue);\n result.errorCount++;\n arr.push(signalIssue);\n }\n }\n }\n }\n\n result.isValid = result.issues.every((i) => i.severity !== FlowGraphValidationSeverity.Error);\n result.issues.sort((a, b) => a.severity - b.severity);\n return result;\n}\n\n/**\n * Get all event blocks from a flow graph.\n * @param flowGraph - the flow graph\n * @returns the event blocks\n */\nfunction _GetEventBlocks(flowGraph: FlowGraph): FlowGraphEventBlock[] {\n const eventBlocks: FlowGraphEventBlock[] = [];\n for (const type in flowGraph._eventBlocks) {\n for (const block of flowGraph._eventBlocks[type as FlowGraphEventType]) {\n eventBlocks.push(block);\n }\n }\n return eventBlocks;\n}\n\n/**\n * Detect whether a block is an event block (entry point).\n * @param block - the block to check\n * @returns true if it is an event block\n */\nfunction _IsEventBlock(block: FlowGraphBlock): boolean {\n return block instanceof FlowGraphEventBlock;\n}\n\n/**\n * Detects cycles among data-only blocks.\n * A data cycle means that block A's output feeds into block B's input, and\n * block B's output feeds back into block A (directly or indirectly).\n * This would cause infinite recursion during getValue().\n * @param allBlocks - all blocks to check\n * @param addIssue - callback to report issues\n */\nfunction _DetectDataCycles(allBlocks: FlowGraphBlock[], addIssue: (issue: IFlowGraphValidationIssue) => void): void {\n // Build adjacency: for each block, which blocks do its data inputs depend on?\n // (Data inputs pull values from connected output blocks.)\n const white = 0; // unvisited\n const gray = 1; // in current DFS path\n const black = 2; // fully explored\n const color = new Map<string, number>();\n\n for (const block of allBlocks) {\n color.set(block.uniqueId, white);\n }\n\n const blockMap = new Map<string, FlowGraphBlock>();\n for (const block of allBlocks) {\n blockMap.set(block.uniqueId, block);\n }\n\n const reportedCycleBlocks = new Set<string>();\n\n function dfs(block: FlowGraphBlock): boolean {\n color.set(block.uniqueId, gray);\n for (const input of block.dataInputs) {\n if (!input.isConnected()) {\n continue;\n }\n for (const connected of input._connectedPoint) {\n const dep = (connected as FlowGraphDataConnection<any>)._ownerBlock;\n // Only consider data-only blocks (not execution blocks which are driven by signals)\n if (dep instanceof FlowGraphExecutionBlock) {\n continue;\n }\n const depColor = color.get(dep.uniqueId);\n if (depColor === gray) {\n // Cycle found\n if (!reportedCycleBlocks.has(block.uniqueId)) {\n reportedCycleBlocks.add(block.uniqueId);\n addIssue({\n severity: FlowGraphValidationSeverity.Error,\n message: `Data dependency cycle detected — getValue() will recurse infinitely.`,\n block,\n });\n }\n if (!reportedCycleBlocks.has(dep.uniqueId)) {\n reportedCycleBlocks.add(dep.uniqueId);\n addIssue({\n severity: FlowGraphValidationSeverity.Error,\n message: `Data dependency cycle detected — getValue() will recurse infinitely.`,\n block: dep,\n });\n }\n return true;\n }\n if (depColor === white) {\n dfs(dep);\n }\n }\n }\n color.set(block.uniqueId, black);\n return false;\n }\n\n for (const block of allBlocks) {\n if (color.get(block.uniqueId) === white) {\n dfs(block);\n }\n }\n}\n"]}
|
package/FlowGraph/index.d.ts
CHANGED
|
@@ -14,5 +14,6 @@ export * from "./flowGraphParser.js";
|
|
|
14
14
|
export * from "./flowGraphPathConverter.js";
|
|
15
15
|
export * from "./flowGraphPathConverterComponent.js";
|
|
16
16
|
export * from "./flowGraphLogger.js";
|
|
17
|
+
export * from "./flowGraphValidator.js";
|
|
17
18
|
export * from "./Blocks/index.js";
|
|
18
19
|
export * from "./CustomTypes/index.js";
|
package/FlowGraph/index.js
CHANGED
|
@@ -14,6 +14,7 @@ export * from "./flowGraphParser.js";
|
|
|
14
14
|
export * from "./flowGraphPathConverter.js";
|
|
15
15
|
export * from "./flowGraphPathConverterComponent.js";
|
|
16
16
|
export * from "./flowGraphLogger.js";
|
|
17
|
+
export * from "./flowGraphValidator.js";
|
|
17
18
|
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
|
18
19
|
export * from "./Blocks/index.js";
|
|
19
20
|
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
package/FlowGraph/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../dev/core/src/FlowGraph/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,mCAAmC,CAAC;AAClD,cAAc,mBAAmB,CAAC;AAClC,oEAAoE;AACpE,cAAc,gBAAgB,CAAC;AAC/B,oEAAoE;AACpE,cAAc,qBAAqB,CAAC","sourcesContent":["export * from \"./flowGraph\";\r\nexport * from \"./flowGraphBlock\";\r\nexport * from \"./flowGraphSignalConnection\";\r\nexport * from \"./flowGraphExecutionBlock\";\r\nexport * from \"./flowGraphEventBlock\";\r\nexport * from \"./flowGraphRichTypes\";\r\nexport * from \"./flowGraphContext\";\r\nexport * from \"./flowGraphCoordinator\";\r\nexport * from \"./typeDefinitions\";\r\nexport * from \"./flowGraphConnection\";\r\nexport * from \"./flowGraphDataConnection\";\r\nexport * from \"./flowGraphAssetsContext\";\r\nexport * from \"./flowGraphParser\";\r\nexport * from \"./flowGraphPathConverter\";\r\nexport * from \"./flowGraphPathConverterComponent\";\r\nexport * from \"./flowGraphLogger\";\r\n// eslint-disable-next-line @typescript-eslint/no-restricted-imports\r\nexport * from \"./Blocks/index\";\r\n// eslint-disable-next-line @typescript-eslint/no-restricted-imports\r\nexport * from \"./CustomTypes/index\";\r\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../dev/core/src/FlowGraph/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,mCAAmC,CAAC;AAClD,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,oEAAoE;AACpE,cAAc,gBAAgB,CAAC;AAC/B,oEAAoE;AACpE,cAAc,qBAAqB,CAAC","sourcesContent":["export * from \"./flowGraph\";\r\nexport * from \"./flowGraphBlock\";\r\nexport * from \"./flowGraphSignalConnection\";\r\nexport * from \"./flowGraphExecutionBlock\";\r\nexport * from \"./flowGraphEventBlock\";\r\nexport * from \"./flowGraphRichTypes\";\r\nexport * from \"./flowGraphContext\";\r\nexport * from \"./flowGraphCoordinator\";\r\nexport * from \"./typeDefinitions\";\r\nexport * from \"./flowGraphConnection\";\r\nexport * from \"./flowGraphDataConnection\";\r\nexport * from \"./flowGraphAssetsContext\";\r\nexport * from \"./flowGraphParser\";\r\nexport * from \"./flowGraphPathConverter\";\r\nexport * from \"./flowGraphPathConverterComponent\";\r\nexport * from \"./flowGraphLogger\";\r\nexport * from \"./flowGraphValidator\";\r\n// eslint-disable-next-line @typescript-eslint/no-restricted-imports\r\nexport * from \"./Blocks/index\";\r\n// eslint-disable-next-line @typescript-eslint/no-restricted-imports\r\nexport * from \"./CustomTypes/index\";\r\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Logger } from "../Misc/logger.js";
|
|
1
2
|
import { Color3, Color4 } from "../Maths/math.color.js";
|
|
2
3
|
import { Matrix, Quaternion, Vector2, Vector3, Vector4 } from "../Maths/math.vector.js";
|
|
3
4
|
import { FlowGraphInteger } from "./CustomTypes/flowGraphInteger.js";
|
|
@@ -87,12 +88,18 @@ export function defaultValueSerializationFunction(key, value, serializationObjec
|
|
|
87
88
|
};
|
|
88
89
|
}
|
|
89
90
|
else {
|
|
90
|
-
|
|
91
|
-
if (typeof value !== "object") {
|
|
91
|
+
if (typeof value !== "object" || value === null) {
|
|
92
92
|
serializationObject[key] = value;
|
|
93
93
|
}
|
|
94
94
|
else {
|
|
95
|
-
|
|
95
|
+
// Plain object (e.g. parsed event config) — store it if JSON-safe,
|
|
96
|
+
// otherwise skip (e.g. objects containing functions like pathConverter).
|
|
97
|
+
try {
|
|
98
|
+
serializationObject[key] = JSON.parse(JSON.stringify(value));
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
Logger.Warn(`FlowGraph serialization: value for key "${key}" is not JSON-serializable and was skipped.`);
|
|
102
|
+
}
|
|
96
103
|
}
|
|
97
104
|
}
|
|
98
105
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serialization.js","sourceRoot":"","sources":["../../../../dev/core/src/FlowGraph/serialization.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IAssetContainer } from \"core/IAssetContainer\";\r\nimport { Color3, Color4 } from \"../Maths/math.color\";\r\nimport { Matrix, Quaternion, Vector2, Vector3, Vector4 } from \"../Maths/math.vector\";\r\nimport type { Scene } from \"../scene\";\r\nimport { FlowGraphBlockNames } from \"./Blocks/flowGraphBlockNames\";\r\nimport { FlowGraphInteger } from \"./CustomTypes/flowGraphInteger\";\r\nimport { FlowGraphTypes, getRichTypeByFlowGraphType } from \"./flowGraphRichTypes\";\r\nimport type { TransformNode } from \"core/Meshes/transformNode\";\r\nimport { FlowGraphMatrix2D, FlowGraphMatrix3D } from \"./CustomTypes/flowGraphMatrix\";\r\n\r\nfunction IsMeshClassName(className: string) {\r\n return (\r\n className === \"Mesh\" ||\r\n className === \"AbstractMesh\" ||\r\n className === \"GroundMesh\" ||\r\n className === \"InstanceMesh\" ||\r\n className === \"LinesMesh\" ||\r\n className === \"GoldbergMesh\" ||\r\n className === \"GreasedLineMesh\" ||\r\n className === \"TrailMesh\"\r\n );\r\n}\r\n\r\nfunction IsVectorClassName(className: string) {\r\n return (\r\n className === FlowGraphTypes.Vector2 ||\r\n className === FlowGraphTypes.Vector3 ||\r\n className === FlowGraphTypes.Vector4 ||\r\n className === FlowGraphTypes.Quaternion ||\r\n className === FlowGraphTypes.Color3 ||\r\n className === FlowGraphTypes.Color4\r\n );\r\n}\r\n\r\nfunction IsMatrixClassName(className: string) {\r\n return className === FlowGraphTypes.Matrix || className === FlowGraphTypes.Matrix2D || className === FlowGraphTypes.Matrix3D;\r\n}\r\n\r\nfunction IsAnimationGroupClassName(className: string) {\r\n return className === \"AnimationGroup\";\r\n}\r\n\r\nfunction ParseVector(className: string, value: Array<number>, flipHandedness = false) {\r\n if (className === FlowGraphTypes.Vector2) {\r\n return Vector2.FromArray(value);\r\n } else if (className === FlowGraphTypes.Vector3) {\r\n if (flipHandedness) {\r\n value[2] *= -1;\r\n }\r\n return Vector3.FromArray(value);\r\n } else if (className === FlowGraphTypes.Vector4) {\r\n return Vector4.FromArray(value);\r\n } else if (className === FlowGraphTypes.Quaternion) {\r\n if (flipHandedness) {\r\n value[2] *= -1;\r\n value[3] *= -1;\r\n }\r\n return Quaternion.FromArray(value);\r\n } else if (className === FlowGraphTypes.Color3) {\r\n return new Color3(value[0], value[1], value[2]);\r\n } else if (className === FlowGraphTypes.Color4) {\r\n return new Color4(value[0], value[1], value[2], value[3]);\r\n } else {\r\n throw new Error(`Unknown vector class name ${className}`);\r\n }\r\n}\r\n\r\n/**\r\n * The default function that serializes values in a context object to a serialization object\r\n * @param key the key where the value should be stored in the serialization object\r\n * @param value the value to store\r\n * @param serializationObject the object where the value will be stored\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function defaultValueSerializationFunction(key: string, value: any, serializationObject: any) {\r\n const className = value?.getClassName?.() ?? \"\";\r\n if (IsVectorClassName(className) || IsMatrixClassName(className)) {\r\n serializationObject[key] = {\r\n value: value.asArray(),\r\n className,\r\n };\r\n } else if (className === FlowGraphTypes.Integer) {\r\n serializationObject[key] = {\r\n value: value.value,\r\n className,\r\n };\r\n } else {\r\n if (className && (value.id || value.name)) {\r\n serializationObject[key] = {\r\n id: value.id,\r\n name: value.name,\r\n className,\r\n };\r\n } else {\r\n // only if it is not an object\r\n if (typeof value !== \"object\") {\r\n serializationObject[key] = value;\r\n } else {\r\n throw new Error(`Could not serialize value ${value}`);\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * The default function that parses values stored in a serialization object\r\n * @param key the key to the value that will be parsed\r\n * @param serializationObject the object that will be parsed\r\n * @param assetsContainer the assets container that will be used to find the objects\r\n * @param scene\r\n * @returns\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function defaultValueParseFunction(key: string, serializationObject: any, assetsContainer: IAssetContainer, scene: Scene) {\r\n const intermediateValue = serializationObject[key];\r\n let finalValue;\r\n const className = intermediateValue?.type ?? intermediateValue?.className;\r\n if (IsMeshClassName(className)) {\r\n let nodes: TransformNode[] = scene.meshes.filter((m) => (intermediateValue.id ? m.id === intermediateValue.id : m.name === intermediateValue.name));\r\n if (nodes.length === 0) {\r\n nodes = scene.transformNodes.filter((m) => (intermediateValue.id ? m.id === intermediateValue.id : m.name === intermediateValue.name));\r\n }\r\n finalValue = intermediateValue.uniqueId ? nodes.find((m) => m.uniqueId === intermediateValue.uniqueId) : nodes[0];\r\n } else if (IsVectorClassName(className)) {\r\n finalValue = ParseVector(className, intermediateValue.value);\r\n } else if (IsAnimationGroupClassName(className)) {\r\n // do not use the scene.getAnimationGroupByName because it is possible that two AGs will have the same name\r\n const ags = scene.animationGroups.filter((ag) => ag.name === intermediateValue.name);\r\n // uniqueId changes on each load. this is used for the glTF loader, that uses serialization after the scene was loaded.\r\n finalValue = ags.length === 1 ? ags[0] : ags.find((ag) => ag.uniqueId === intermediateValue.uniqueId);\r\n } else if (className === FlowGraphTypes.Matrix) {\r\n finalValue = Matrix.FromArray(intermediateValue.value);\r\n } else if (className === FlowGraphTypes.Matrix2D) {\r\n finalValue = new FlowGraphMatrix2D(intermediateValue.value);\r\n } else if (className === FlowGraphTypes.Matrix3D) {\r\n finalValue = new FlowGraphMatrix3D(intermediateValue.value);\r\n } else if (className === FlowGraphTypes.Integer) {\r\n finalValue = FlowGraphInteger.FromValue(intermediateValue.value);\r\n } else if (className === FlowGraphTypes.Number || className === FlowGraphTypes.String || className === FlowGraphTypes.Boolean) {\r\n finalValue = intermediateValue.value[0];\r\n } else if (intermediateValue && intermediateValue.value !== undefined) {\r\n finalValue = intermediateValue.value;\r\n } else {\r\n if (Array.isArray(intermediateValue)) {\r\n // configuration data of an event\r\n finalValue = intermediateValue.reduce((acc, val) => {\r\n if (!val.eventData) {\r\n return acc;\r\n }\r\n acc[val.id] = {\r\n type: getRichTypeByFlowGraphType(val.type),\r\n };\r\n if (typeof val.value !== \"undefined\") {\r\n acc[val.id].value = defaultValueParseFunction(\"value\", val, assetsContainer, scene);\r\n }\r\n return acc;\r\n }, {});\r\n } else {\r\n finalValue = intermediateValue;\r\n }\r\n }\r\n return finalValue;\r\n}\r\n\r\n/**\r\n * Given a name of a flow graph block class, return if this\r\n * class needs to be created with a path converter. Used in\r\n * parsing.\r\n * @param className the name of the flow graph block class\r\n * @returns a boolean indicating if the class needs a path converter\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function needsPathConverter(className: string) {\r\n // I am not using the ClassName property here because it was causing a circular dependency\r\n return className === FlowGraphBlockNames.JsonPointerParser;\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"serialization.js","sourceRoot":"","sources":["../../../../dev/core/src/FlowGraph/serialization.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IAssetContainer } from \"core/IAssetContainer\";\r\nimport { Logger } from \"../Misc/logger\";\r\nimport { Color3, Color4 } from \"../Maths/math.color\";\r\nimport { Matrix, Quaternion, Vector2, Vector3, Vector4 } from \"../Maths/math.vector\";\r\nimport type { Scene } from \"../scene\";\r\nimport { FlowGraphBlockNames } from \"./Blocks/flowGraphBlockNames\";\r\nimport { FlowGraphInteger } from \"./CustomTypes/flowGraphInteger\";\r\nimport { FlowGraphTypes, getRichTypeByFlowGraphType } from \"./flowGraphRichTypes\";\r\nimport type { TransformNode } from \"core/Meshes/transformNode\";\r\nimport { FlowGraphMatrix2D, FlowGraphMatrix3D } from \"./CustomTypes/flowGraphMatrix\";\r\n\r\nfunction IsMeshClassName(className: string) {\r\n return (\r\n className === \"Mesh\" ||\r\n className === \"AbstractMesh\" ||\r\n className === \"GroundMesh\" ||\r\n className === \"InstanceMesh\" ||\r\n className === \"LinesMesh\" ||\r\n className === \"GoldbergMesh\" ||\r\n className === \"GreasedLineMesh\" ||\r\n className === \"TrailMesh\"\r\n );\r\n}\r\n\r\nfunction IsVectorClassName(className: string) {\r\n return (\r\n className === FlowGraphTypes.Vector2 ||\r\n className === FlowGraphTypes.Vector3 ||\r\n className === FlowGraphTypes.Vector4 ||\r\n className === FlowGraphTypes.Quaternion ||\r\n className === FlowGraphTypes.Color3 ||\r\n className === FlowGraphTypes.Color4\r\n );\r\n}\r\n\r\nfunction IsMatrixClassName(className: string) {\r\n return className === FlowGraphTypes.Matrix || className === FlowGraphTypes.Matrix2D || className === FlowGraphTypes.Matrix3D;\r\n}\r\n\r\nfunction IsAnimationGroupClassName(className: string) {\r\n return className === \"AnimationGroup\";\r\n}\r\n\r\nfunction ParseVector(className: string, value: Array<number>, flipHandedness = false) {\r\n if (className === FlowGraphTypes.Vector2) {\r\n return Vector2.FromArray(value);\r\n } else if (className === FlowGraphTypes.Vector3) {\r\n if (flipHandedness) {\r\n value[2] *= -1;\r\n }\r\n return Vector3.FromArray(value);\r\n } else if (className === FlowGraphTypes.Vector4) {\r\n return Vector4.FromArray(value);\r\n } else if (className === FlowGraphTypes.Quaternion) {\r\n if (flipHandedness) {\r\n value[2] *= -1;\r\n value[3] *= -1;\r\n }\r\n return Quaternion.FromArray(value);\r\n } else if (className === FlowGraphTypes.Color3) {\r\n return new Color3(value[0], value[1], value[2]);\r\n } else if (className === FlowGraphTypes.Color4) {\r\n return new Color4(value[0], value[1], value[2], value[3]);\r\n } else {\r\n throw new Error(`Unknown vector class name ${className}`);\r\n }\r\n}\r\n\r\n/**\r\n * The default function that serializes values in a context object to a serialization object\r\n * @param key the key where the value should be stored in the serialization object\r\n * @param value the value to store\r\n * @param serializationObject the object where the value will be stored\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function defaultValueSerializationFunction(key: string, value: any, serializationObject: any) {\r\n const className = value?.getClassName?.() ?? \"\";\r\n if (IsVectorClassName(className) || IsMatrixClassName(className)) {\r\n serializationObject[key] = {\r\n value: value.asArray(),\r\n className,\r\n };\r\n } else if (className === FlowGraphTypes.Integer) {\r\n serializationObject[key] = {\r\n value: value.value,\r\n className,\r\n };\r\n } else {\r\n if (className && (value.id || value.name)) {\r\n serializationObject[key] = {\r\n id: value.id,\r\n name: value.name,\r\n className,\r\n };\r\n } else {\r\n if (typeof value !== \"object\" || value === null) {\r\n serializationObject[key] = value;\r\n } else {\r\n // Plain object (e.g. parsed event config) — store it if JSON-safe,\r\n // otherwise skip (e.g. objects containing functions like pathConverter).\r\n try {\r\n serializationObject[key] = JSON.parse(JSON.stringify(value));\r\n } catch {\r\n Logger.Warn(`FlowGraph serialization: value for key \"${key}\" is not JSON-serializable and was skipped.`);\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * The default function that parses values stored in a serialization object\r\n * @param key the key to the value that will be parsed\r\n * @param serializationObject the object that will be parsed\r\n * @param assetsContainer the assets container that will be used to find the objects\r\n * @param scene\r\n * @returns\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function defaultValueParseFunction(key: string, serializationObject: any, assetsContainer: IAssetContainer, scene: Scene) {\r\n const intermediateValue = serializationObject[key];\r\n let finalValue;\r\n const className = intermediateValue?.type ?? intermediateValue?.className;\r\n if (IsMeshClassName(className)) {\r\n let nodes: TransformNode[] = scene.meshes.filter((m) => (intermediateValue.id ? m.id === intermediateValue.id : m.name === intermediateValue.name));\r\n if (nodes.length === 0) {\r\n nodes = scene.transformNodes.filter((m) => (intermediateValue.id ? m.id === intermediateValue.id : m.name === intermediateValue.name));\r\n }\r\n finalValue = intermediateValue.uniqueId ? nodes.find((m) => m.uniqueId === intermediateValue.uniqueId) : nodes[0];\r\n } else if (IsVectorClassName(className)) {\r\n finalValue = ParseVector(className, intermediateValue.value);\r\n } else if (IsAnimationGroupClassName(className)) {\r\n // do not use the scene.getAnimationGroupByName because it is possible that two AGs will have the same name\r\n const ags = scene.animationGroups.filter((ag) => ag.name === intermediateValue.name);\r\n // uniqueId changes on each load. this is used for the glTF loader, that uses serialization after the scene was loaded.\r\n finalValue = ags.length === 1 ? ags[0] : ags.find((ag) => ag.uniqueId === intermediateValue.uniqueId);\r\n } else if (className === FlowGraphTypes.Matrix) {\r\n finalValue = Matrix.FromArray(intermediateValue.value);\r\n } else if (className === FlowGraphTypes.Matrix2D) {\r\n finalValue = new FlowGraphMatrix2D(intermediateValue.value);\r\n } else if (className === FlowGraphTypes.Matrix3D) {\r\n finalValue = new FlowGraphMatrix3D(intermediateValue.value);\r\n } else if (className === FlowGraphTypes.Integer) {\r\n finalValue = FlowGraphInteger.FromValue(intermediateValue.value);\r\n } else if (className === FlowGraphTypes.Number || className === FlowGraphTypes.String || className === FlowGraphTypes.Boolean) {\r\n finalValue = intermediateValue.value[0];\r\n } else if (intermediateValue && intermediateValue.value !== undefined) {\r\n finalValue = intermediateValue.value;\r\n } else {\r\n if (Array.isArray(intermediateValue)) {\r\n // configuration data of an event\r\n finalValue = intermediateValue.reduce((acc, val) => {\r\n if (!val.eventData) {\r\n return acc;\r\n }\r\n acc[val.id] = {\r\n type: getRichTypeByFlowGraphType(val.type),\r\n };\r\n if (typeof val.value !== \"undefined\") {\r\n acc[val.id].value = defaultValueParseFunction(\"value\", val, assetsContainer, scene);\r\n }\r\n return acc;\r\n }, {});\r\n } else {\r\n finalValue = intermediateValue;\r\n }\r\n }\r\n return finalValue;\r\n}\r\n\r\n/**\r\n * Given a name of a flow graph block class, return if this\r\n * class needs to be created with a path converter. Used in\r\n * parsing.\r\n * @param className the name of the flow graph block class\r\n * @returns a boolean indicating if the class needs a path converter\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport function needsPathConverter(className: string) {\r\n // I am not using the ClassName property here because it was causing a circular dependency\r\n return className === FlowGraphBlockNames.JsonPointerParser;\r\n}\r\n"]}
|