UNPKG

@babylonjs/loaders

Version:

For usage documentation please visit https://doc.babylonjs.com/features/featuresDeepDive/importers/loadingFileTypes/.

1,134 lines (1,133 loc) 76 kB
import { Logger } from "@babylonjs/core/Misc/logger.js"; import { getAnimationTypeByFlowGraphType } from "@babylonjs/core/FlowGraph/flowGraphRichTypes.js"; export function getMappingForFullOperationName(fullOperationName) { const [op, extension] = fullOperationName.split(":"); return getMappingForDeclaration({ op, extension }); } export function getMappingForDeclaration(declaration, returnNoOpIfNotAvailable = true) { const mapping = declaration.extension ? gltfExtensionsToFlowGraphMapping[declaration.extension]?.[declaration.op] : gltfToFlowGraphMapping[declaration.op]; if (!mapping) { Logger.Warn(`No mapping found for operation ${declaration.op} and extension ${declaration.extension || "KHR_interactivity"}`); if (returnNoOpIfNotAvailable) { const inputs = {}; const outputs = { flows: {}, }; if (declaration.inputValueSockets) { inputs.values = {}; for (const key in declaration.inputValueSockets) { inputs.values[key] = { name: key, }; } } if (declaration.outputValueSockets) { outputs.values = {}; Object.keys(declaration.outputValueSockets).forEach((key) => { outputs.values[key] = { name: key, }; }); } return { blocks: [], // no blocks, just mapping inputs, outputs, }; } } return mapping; } /** * This function will add new mapping to glTF interactivity. * Other extensions can define new types of blocks, this is the way to let interactivity know how to parse them. * @param key the type of node, i.e. "variable/get" * @param extension the extension of the interactivity operation, i.e. "KHR_selectability" * @param mapping The mapping object. See documentation or examples below. */ export function addNewInteractivityFlowGraphMapping(key, extension, mapping) { gltfExtensionsToFlowGraphMapping[extension] || (gltfExtensionsToFlowGraphMapping[extension] = {}); gltfExtensionsToFlowGraphMapping[extension][key] = mapping; } const gltfExtensionsToFlowGraphMapping = { /** * This is the BABYLON extension for glTF interactivity. * It defines babylon-specific blocks and operations. */ BABYLON: { /** * flow/log is a flow node that logs input to the console. * It has "in" and "out" flows, and takes a message as input. * The message can be any type of value. * The message is logged to the console when the "in" flow is triggered. * The "out" flow is triggered when the message is logged. */ "flow/log": { blocks: ["FlowGraphConsoleLogBlock" /* FlowGraphBlockNames.ConsoleLog */], inputs: { values: { message: { name: "message" }, }, }, }, }, }; // this mapper is just a way to convert the glTF nodes to FlowGraph nodes in terms of input/output connection names and values. const gltfToFlowGraphMapping = { "event/onStart": { blocks: ["FlowGraphSceneReadyEventBlock" /* FlowGraphBlockNames.SceneReadyEvent */], outputs: { flows: { out: { name: "done" }, }, }, }, "event/onTick": { blocks: ["FlowGraphSceneTickEventBlock" /* FlowGraphBlockNames.SceneTickEvent */], inputs: {}, outputs: { values: { timeSinceLastTick: { name: "deltaTime", gltfType: "number" /*, dataTransformer: (time: number) => time / 1000*/ }, }, flows: { out: { name: "done" }, }, }, }, "event/send": { blocks: ["FlowGraphSendCustomEventBlock" /* FlowGraphBlockNames.SendCustomEvent */], extraProcessor(gltfBlock, declaration, _mapping, parser, serializedObjects) { // set eventId and eventData. The configuration object of the glTF should have a single object. // validate that we are running it on the right block. if (declaration.op !== "event/send" || !gltfBlock.configuration || Object.keys(gltfBlock.configuration).length !== 1) { throw new Error("Receive event should have a single configuration object, the event itself"); } const eventConfiguration = gltfBlock.configuration["event"]; const eventId = eventConfiguration.value?.[0]; if (typeof eventId !== "number") { throw new Error("Event id should be a number"); } const event = parser.arrays.events[eventId]; const serializedObject = serializedObjects[0]; serializedObject.config || (serializedObject.config = {}); serializedObject.config.eventId = event.eventId; serializedObject.config.eventData = event.eventData; return serializedObjects; }, }, "event/receive": { blocks: ["FlowGraphReceiveCustomEventBlock" /* FlowGraphBlockNames.ReceiveCustomEvent */], outputs: { flows: { out: { name: "done" }, }, }, validation(gltfBlock, interactivityGraph) { if (!gltfBlock.configuration) { Logger.Error("Receive event should have a configuration object"); return { valid: false, error: "Receive event should have a configuration object" }; } const eventConfiguration = gltfBlock.configuration["event"]; if (!eventConfiguration) { Logger.Error("Receive event should have a single configuration object, the event itself"); return { valid: false, error: "Receive event should have a single configuration object, the event itself" }; } const eventId = eventConfiguration.value?.[0]; if (typeof eventId !== "number") { Logger.Error("Event id should be a number"); return { valid: false, error: "Event id should be a number" }; } const event = interactivityGraph.events?.[eventId]; if (!event) { Logger.Error(`Event with id ${eventId} not found`); return { valid: false, error: `Event with id ${eventId} not found` }; } return { valid: true }; }, extraProcessor(gltfBlock, declaration, _mapping, parser, serializedObjects) { // set eventId and eventData. The configuration object of the glTF should have a single object. // validate that we are running it on the right block. if (declaration.op !== "event/receive" || !gltfBlock.configuration || Object.keys(gltfBlock.configuration).length !== 1) { throw new Error("Receive event should have a single configuration object, the event itself"); } const eventConfiguration = gltfBlock.configuration["event"]; const eventId = eventConfiguration.value?.[0]; if (typeof eventId !== "number") { throw new Error("Event id should be a number"); } const event = parser.arrays.events[eventId]; const serializedObject = serializedObjects[0]; serializedObject.config || (serializedObject.config = {}); serializedObject.config.eventId = event.eventId; serializedObject.config.eventData = event.eventData; return serializedObjects; }, }, "math/E": getSimpleInputMapping("FlowGraphEBlock" /* FlowGraphBlockNames.E */), "math/Pi": getSimpleInputMapping("FlowGraphPIBlock" /* FlowGraphBlockNames.PI */), "math/Inf": getSimpleInputMapping("FlowGraphInfBlock" /* FlowGraphBlockNames.Inf */), "math/NaN": getSimpleInputMapping("FlowGraphNaNBlock" /* FlowGraphBlockNames.NaN */), "math/abs": getSimpleInputMapping("FlowGraphAbsBlock" /* FlowGraphBlockNames.Abs */), "math/sign": getSimpleInputMapping("FlowGraphSignBlock" /* FlowGraphBlockNames.Sign */), "math/trunc": getSimpleInputMapping("FlowGraphTruncBlock" /* FlowGraphBlockNames.Trunc */), "math/floor": getSimpleInputMapping("FlowGraphFloorBlock" /* FlowGraphBlockNames.Floor */), "math/ceil": getSimpleInputMapping("FlowGraphCeilBlock" /* FlowGraphBlockNames.Ceil */), "math/round": { blocks: ["FlowGraphRoundBlock" /* FlowGraphBlockNames.Round */], configuration: {}, inputs: { values: { a: { name: "a" }, }, }, outputs: { values: { value: { name: "value" }, }, }, extraProcessor(gltfBlock, declaration, _mapping, parser, serializedObjects) { var _a; // configure it to work the way glTF specifies (_a = serializedObjects[0]).config || (_a.config = {}); serializedObjects[0].config.roundHalfAwayFromZero = true; return serializedObjects; }, }, "math/fract": getSimpleInputMapping("FlowGraphFractBlock" /* FlowGraphBlockNames.Fraction */), "math/neg": getSimpleInputMapping("FlowGraphNegationBlock" /* FlowGraphBlockNames.Negation */), "math/add": getSimpleInputMapping("FlowGraphAddBlock" /* FlowGraphBlockNames.Add */, ["a", "b"], true), "math/sub": getSimpleInputMapping("FlowGraphSubtractBlock" /* FlowGraphBlockNames.Subtract */, ["a", "b"], true), "math/mul": { blocks: ["FlowGraphMultiplyBlock" /* FlowGraphBlockNames.Multiply */], extraProcessor(_gltfBlock, _declaration, _mapping, _parser, serializedObjects) { var _a; // configure it to work the way glTF specifies (_a = serializedObjects[0]).config || (_a.config = {}); serializedObjects[0].config.useMatrixPerComponent = true; serializedObjects[0].config.preventIntegerFloatArithmetic = true; // try to infer the type or fallback to Integer // check the gltf block for the inputs, see if they have a type let type = -1; Object.keys(_gltfBlock.values || {}).find((value) => { if (_gltfBlock.values?.[value].type !== undefined) { type = _gltfBlock.values[value].type; return true; } return false; }); if (type !== -1) { serializedObjects[0].config.type = _parser.arrays.types[type].flowGraphType; } return serializedObjects; }, validation(gltfBlock) { if (gltfBlock.values) { // make sure types are the same return ValidateTypes(gltfBlock); } return { valid: true }; }, }, "math/div": getSimpleInputMapping("FlowGraphDivideBlock" /* FlowGraphBlockNames.Divide */, ["a", "b"], true), "math/rem": getSimpleInputMapping("FlowGraphModuloBlock" /* FlowGraphBlockNames.Modulo */, ["a", "b"]), "math/min": getSimpleInputMapping("FlowGraphMinBlock" /* FlowGraphBlockNames.Min */, ["a", "b"]), "math/max": getSimpleInputMapping("FlowGraphMaxBlock" /* FlowGraphBlockNames.Max */, ["a", "b"]), "math/clamp": getSimpleInputMapping("FlowGraphClampBlock" /* FlowGraphBlockNames.Clamp */, ["a", "b", "c"]), "math/saturate": getSimpleInputMapping("FlowGraphSaturateBlock" /* FlowGraphBlockNames.Saturate */), "math/mix": getSimpleInputMapping("FlowGraphMathInterpolationBlock" /* FlowGraphBlockNames.MathInterpolation */, ["a", "b", "c"]), "math/eq": getSimpleInputMapping("FlowGraphEqualityBlock" /* FlowGraphBlockNames.Equality */, ["a", "b"]), "math/lt": getSimpleInputMapping("FlowGraphLessThanBlock" /* FlowGraphBlockNames.LessThan */, ["a", "b"]), "math/le": getSimpleInputMapping("FlowGraphLessThanOrEqualBlock" /* FlowGraphBlockNames.LessThanOrEqual */, ["a", "b"]), "math/gt": getSimpleInputMapping("FlowGraphGreaterThanBlock" /* FlowGraphBlockNames.GreaterThan */, ["a", "b"]), "math/ge": getSimpleInputMapping("FlowGraphGreaterThanOrEqualBlock" /* FlowGraphBlockNames.GreaterThanOrEqual */, ["a", "b"]), "math/isNaN": getSimpleInputMapping("FlowGraphIsNaNBlock" /* FlowGraphBlockNames.IsNaN */), "math/isInf": getSimpleInputMapping("FlowGraphIsInfBlock" /* FlowGraphBlockNames.IsInfinity */), "math/select": { blocks: ["FlowGraphConditionalBlock" /* FlowGraphBlockNames.Conditional */], inputs: { values: { condition: { name: "condition" }, // Should we validate those have the same type here, or assume it is already validated? a: { name: "onTrue" }, b: { name: "onFalse" }, }, }, outputs: { values: { value: { name: "output" }, }, }, }, "math/random": { blocks: ["FlowGraphRandomBlock" /* FlowGraphBlockNames.Random */], outputs: { values: { value: { name: "value" }, }, }, }, "math/sin": getSimpleInputMapping("FlowGraphSinBlock" /* FlowGraphBlockNames.Sin */), "math/cos": getSimpleInputMapping("FlowGraphCosBlock" /* FlowGraphBlockNames.Cos */), "math/tan": getSimpleInputMapping("FlowGraphTanBlock" /* FlowGraphBlockNames.Tan */), "math/asin": getSimpleInputMapping("FlowGraphASinBlock" /* FlowGraphBlockNames.Asin */), "math/acos": getSimpleInputMapping("FlowGraphACosBlock" /* FlowGraphBlockNames.Acos */), "math/atan": getSimpleInputMapping("FlowGraphATanBlock" /* FlowGraphBlockNames.Atan */), "math/atan2": getSimpleInputMapping("FlowGraphATan2Block" /* FlowGraphBlockNames.Atan2 */, ["a", "b"]), "math/sinh": getSimpleInputMapping("FlowGraphSinhBlock" /* FlowGraphBlockNames.Sinh */), "math/cosh": getSimpleInputMapping("FlowGraphCoshBlock" /* FlowGraphBlockNames.Cosh */), "math/tanh": getSimpleInputMapping("FlowGraphTanhBlock" /* FlowGraphBlockNames.Tanh */), "math/asinh": getSimpleInputMapping("FlowGraphASinhBlock" /* FlowGraphBlockNames.Asinh */), "math/acosh": getSimpleInputMapping("FlowGraphACoshBlock" /* FlowGraphBlockNames.Acosh */), "math/atanh": getSimpleInputMapping("FlowGraphATanhBlock" /* FlowGraphBlockNames.Atanh */), "math/exp": getSimpleInputMapping("FlowGraphExponentialBlock" /* FlowGraphBlockNames.Exponential */), "math/log": getSimpleInputMapping("FlowGraphLogBlock" /* FlowGraphBlockNames.Log */), "math/log2": getSimpleInputMapping("FlowGraphLog2Block" /* FlowGraphBlockNames.Log2 */), "math/log10": getSimpleInputMapping("FlowGraphLog10Block" /* FlowGraphBlockNames.Log10 */), "math/sqrt": getSimpleInputMapping("FlowGraphSquareRootBlock" /* FlowGraphBlockNames.SquareRoot */), "math/cbrt": getSimpleInputMapping("FlowGraphCubeRootBlock" /* FlowGraphBlockNames.CubeRoot */), "math/pow": getSimpleInputMapping("FlowGraphPowerBlock" /* FlowGraphBlockNames.Power */, ["a", "b"]), "math/length": getSimpleInputMapping("FlowGraphLengthBlock" /* FlowGraphBlockNames.Length */), "math/normalize": getSimpleInputMapping("FlowGraphNormalizeBlock" /* FlowGraphBlockNames.Normalize */), "math/dot": getSimpleInputMapping("FlowGraphDotBlock" /* FlowGraphBlockNames.Dot */, ["a", "b"]), "math/cross": getSimpleInputMapping("FlowGraphCrossBlock" /* FlowGraphBlockNames.Cross */, ["a", "b"]), "math/rotate2D": { blocks: ["FlowGraphRotate2DBlock" /* FlowGraphBlockNames.Rotate2D */], inputs: { values: { a: { name: "a" }, angle: { name: "b" }, }, }, outputs: { values: { value: { name: "value" }, }, }, }, "math/rotate3D": { blocks: ["FlowGraphRotate3DBlock" /* FlowGraphBlockNames.Rotate3D */], inputs: { values: { a: { name: "a" }, rotation: { name: "b" }, }, }, outputs: { values: { value: { name: "value" }, }, }, }, "math/transform": { // glTF transform is vectorN with matrixN blocks: ["FlowGraphTransformVectorBlock" /* FlowGraphBlockNames.TransformVector */], inputs: { values: { a: { name: "a" }, b: { name: "b" }, }, }, outputs: { values: { value: { name: "value" }, }, }, }, "math/combine2": { blocks: ["FlowGraphCombineVector2Block" /* FlowGraphBlockNames.CombineVector2 */], inputs: { values: { a: { name: "input_0", gltfType: "number" }, b: { name: "input_1", gltfType: "number" }, }, }, outputs: { values: { value: { name: "value" }, }, }, }, "math/combine3": { blocks: ["FlowGraphCombineVector3Block" /* FlowGraphBlockNames.CombineVector3 */], inputs: { values: { a: { name: "input_0", gltfType: "number" }, b: { name: "input_1", gltfType: "number" }, c: { name: "input_2", gltfType: "number" }, }, }, outputs: { values: { value: { name: "value" }, }, }, }, "math/combine4": { blocks: ["FlowGraphCombineVector4Block" /* FlowGraphBlockNames.CombineVector4 */], inputs: { values: { a: { name: "input_0", gltfType: "number" }, b: { name: "input_1", gltfType: "number" }, c: { name: "input_2", gltfType: "number" }, d: { name: "input_3", gltfType: "number" }, }, }, outputs: { values: { value: { name: "value" }, }, }, }, // one input, N outputs! outputs named using numbers. "math/extract2": { blocks: ["FlowGraphExtractVector2Block" /* FlowGraphBlockNames.ExtractVector2 */], inputs: { values: { a: { name: "input", gltfType: "number" }, }, }, outputs: { values: { "0": { name: "output_0" }, "1": { name: "output_1" }, }, }, }, "math/extract3": { blocks: ["FlowGraphExtractVector3Block" /* FlowGraphBlockNames.ExtractVector3 */], inputs: { values: { a: { name: "input", gltfType: "number" }, }, }, outputs: { values: { "0": { name: "output_0" }, "1": { name: "output_1" }, "2": { name: "output_2" }, }, }, }, "math/extract4": { blocks: ["FlowGraphExtractVector4Block" /* FlowGraphBlockNames.ExtractVector4 */], inputs: { values: { a: { name: "input", gltfType: "number" }, }, }, outputs: { values: { "0": { name: "output_0" }, "1": { name: "output_1" }, "2": { name: "output_2" }, "3": { name: "output_3" }, }, }, }, "math/transpose": getSimpleInputMapping("FlowGraphTransposeBlock" /* FlowGraphBlockNames.Transpose */), "math/determinant": getSimpleInputMapping("FlowGraphDeterminantBlock" /* FlowGraphBlockNames.Determinant */), "math/inverse": getSimpleInputMapping("FlowGraphInvertMatrixBlock" /* FlowGraphBlockNames.InvertMatrix */), "math/matMul": getSimpleInputMapping("FlowGraphMatrixMultiplicationBlock" /* FlowGraphBlockNames.MatrixMultiplication */, ["a", "b"]), "math/matCompose": { blocks: ["FlowGraphMatrixCompose" /* FlowGraphBlockNames.MatrixCompose */], inputs: { values: { translation: { name: "position", gltfType: "float3" }, rotation: { name: "rotationQuaternion", gltfType: "float4" }, scale: { name: "scaling", gltfType: "float3" }, }, }, outputs: { values: { value: { name: "value" }, }, }, extraProcessor(_gltfBlock, _declaration, _mapping, _parser, serializedObjects, context) { // configure it to work the way glTF specifies const d = serializedObjects[0].dataInputs.find((input) => input.name === "rotationQuaternion"); if (!d) { throw new Error("Rotation quaternion input not found"); } // if value is defined, set the type to quaternion if (context._connectionValues[d.uniqueId]) { context._connectionValues[d.uniqueId].type = "Quaternion" /* FlowGraphTypes.Quaternion */; } return serializedObjects; }, }, "math/matDecompose": { blocks: ["FlowGraphMatrixDecompose" /* FlowGraphBlockNames.MatrixDecompose */], inputs: { values: { a: { name: "input", gltfType: "number" }, }, }, outputs: { values: { translation: { name: "position" }, rotation: { name: "rotationQuaternion" }, scale: { name: "scaling" }, }, }, }, "math/quatConjugate": getSimpleInputMapping("FlowGraphConjugateBlock" /* FlowGraphBlockNames.Conjugate */, ["a"]), "math/quatMul": { blocks: ["FlowGraphMultiplyBlock" /* FlowGraphBlockNames.Multiply */], inputs: { values: { a: { name: "a", gltfType: "vector4" }, b: { name: "b", gltfType: "vector4" }, }, }, outputs: { values: { value: { name: "value" }, }, }, extraProcessor(_gltfBlock, _declaration, _mapping, _parser, serializedObjects) { var _a; (_a = serializedObjects[0]).config || (_a.config = {}); serializedObjects[0].config.type = "Quaternion" /* FlowGraphTypes.Quaternion */; return serializedObjects; }, }, "math/quatAngleBetween": getSimpleInputMapping("FlowGraphAngleBetweenBlock" /* FlowGraphBlockNames.AngleBetween */, ["a", "b"]), "math/quatFromAxisAngle": { blocks: ["FlowGraphQuaternionFromAxisAngleBlock" /* FlowGraphBlockNames.QuaternionFromAxisAngle */], inputs: { values: { axis: { name: "a", gltfType: "float3" }, angle: { name: "b", gltfType: "number" }, }, }, outputs: { values: { value: { name: "value" }, }, }, }, "math/quatToAxisAngle": getSimpleInputMapping("FlowGraphAxisAngleFromQuaternionBlock" /* FlowGraphBlockNames.AxisAngleFromQuaternion */, ["a"]), "math/quatFromDirections": getSimpleInputMapping("FlowGraphQuaternionFromDirectionsBlock" /* FlowGraphBlockNames.QuaternionFromDirections */, ["a", "b"]), "math/combine2x2": { blocks: ["FlowGraphCombineMatrix2DBlock" /* FlowGraphBlockNames.CombineMatrix2D */], inputs: { values: { a: { name: "input_0", gltfType: "number" }, b: { name: "input_1", gltfType: "number" }, c: { name: "input_2", gltfType: "number" }, d: { name: "input_3", gltfType: "number" }, }, }, outputs: { values: { value: { name: "value" }, }, }, extraProcessor(_gltfBlock, _declaration, _mapping, _parser, serializedObjects) { var _a; // configure it to work the way glTF specifies (_a = serializedObjects[0]).config || (_a.config = {}); serializedObjects[0].config.inputIsColumnMajor = true; return serializedObjects; }, }, "math/extract2x2": { blocks: ["FlowGraphExtractMatrix2DBlock" /* FlowGraphBlockNames.ExtractMatrix2D */], inputs: { values: { a: { name: "input", gltfType: "float2x2" }, }, }, outputs: { values: { "0": { name: "output_0" }, "1": { name: "output_1" }, "2": { name: "output_2" }, "3": { name: "output_3" }, }, }, }, "math/combine3x3": { blocks: ["FlowGraphCombineMatrix3DBlock" /* FlowGraphBlockNames.CombineMatrix3D */], inputs: { values: { a: { name: "input_0", gltfType: "number" }, b: { name: "input_1", gltfType: "number" }, c: { name: "input_2", gltfType: "number" }, d: { name: "input_3", gltfType: "number" }, e: { name: "input_4", gltfType: "number" }, f: { name: "input_5", gltfType: "number" }, g: { name: "input_6", gltfType: "number" }, h: { name: "input_7", gltfType: "number" }, i: { name: "input_8", gltfType: "number" }, }, }, outputs: { values: { value: { name: "value" }, }, }, extraProcessor(_gltfBlock, _declaration, _mapping, _parser, serializedObjects) { var _a; // configure it to work the way glTF specifies (_a = serializedObjects[0]).config || (_a.config = {}); serializedObjects[0].config.inputIsColumnMajor = true; return serializedObjects; }, }, "math/extract3x3": { blocks: ["FlowGraphExtractMatrix3DBlock" /* FlowGraphBlockNames.ExtractMatrix3D */], inputs: { values: { a: { name: "input", gltfType: "float3x3" }, }, }, outputs: { values: { "0": { name: "output_0" }, "1": { name: "output_1" }, "2": { name: "output_2" }, "3": { name: "output_3" }, "4": { name: "output_4" }, "5": { name: "output_5" }, "6": { name: "output_6" }, "7": { name: "output_7" }, "8": { name: "output_8" }, }, }, }, "math/combine4x4": { blocks: ["FlowGraphCombineMatrixBlock" /* FlowGraphBlockNames.CombineMatrix */], inputs: { values: { a: { name: "input_0", gltfType: "number" }, b: { name: "input_1", gltfType: "number" }, c: { name: "input_2", gltfType: "number" }, d: { name: "input_3", gltfType: "number" }, e: { name: "input_4", gltfType: "number" }, f: { name: "input_5", gltfType: "number" }, g: { name: "input_6", gltfType: "number" }, h: { name: "input_7", gltfType: "number" }, i: { name: "input_8", gltfType: "number" }, j: { name: "input_9", gltfType: "number" }, k: { name: "input_10", gltfType: "number" }, l: { name: "input_11", gltfType: "number" }, m: { name: "input_12", gltfType: "number" }, n: { name: "input_13", gltfType: "number" }, o: { name: "input_14", gltfType: "number" }, p: { name: "input_15", gltfType: "number" }, }, }, outputs: { values: { value: { name: "value" }, }, }, extraProcessor(_gltfBlock, _declaration, _mapping, _parser, serializedObjects) { var _a; // configure it to work the way glTF specifies (_a = serializedObjects[0]).config || (_a.config = {}); serializedObjects[0].config.inputIsColumnMajor = true; return serializedObjects; }, }, "math/extract4x4": { blocks: ["FlowGraphExtractMatrixBlock" /* FlowGraphBlockNames.ExtractMatrix */], configuration: {}, inputs: { values: { a: { name: "input", gltfType: "number" }, }, }, outputs: { values: { "0": { name: "output_0" }, "1": { name: "output_1" }, "2": { name: "output_2" }, "3": { name: "output_3" }, "4": { name: "output_4" }, "5": { name: "output_5" }, "6": { name: "output_6" }, "7": { name: "output_7" }, "8": { name: "output_8" }, "9": { name: "output_9" }, "10": { name: "output_10" }, "11": { name: "output_11" }, "12": { name: "output_12" }, "13": { name: "output_13" }, "14": { name: "output_14" }, "15": { name: "output_15" }, }, }, }, "math/not": { blocks: ["FlowGraphBitwiseNotBlock" /* FlowGraphBlockNames.BitwiseNot */], inputs: { values: { a: { name: "a" }, }, }, outputs: { values: { value: { name: "value" }, }, }, extraProcessor(_gltfBlock, _declaration, _mapping, _parser, serializedObjects, context) { var _a; // configure it to work the way glTF specifies (_a = serializedObjects[0]).config || (_a.config = {}); // try to infer the type or fallback to Integer const socketIn = serializedObjects[0].dataInputs[0]; serializedObjects[0].config.valueType = context._connectionValues[socketIn.uniqueId]?.type ?? "FlowGraphInteger" /* FlowGraphTypes.Integer */; return serializedObjects; }, }, "math/and": { blocks: ["FlowGraphBitwiseAndBlock" /* FlowGraphBlockNames.BitwiseAnd */], inputs: { values: { a: { name: "a" }, b: { name: "b" }, }, }, outputs: { values: { value: { name: "value" }, }, }, extraProcessor(_gltfBlock, _declaration, _mapping, _parser, serializedObjects, context) { var _a; // configure it to work the way glTF specifies (_a = serializedObjects[0]).config || (_a.config = {}); // try to infer the type or fallback to Integer const socketInA = serializedObjects[0].dataInputs[0]; const socketInB = serializedObjects[0].dataInputs[1]; serializedObjects[0].config.valueType = context._connectionValues[socketInA.uniqueId]?.type ?? context._connectionValues[socketInB.uniqueId]?.type ?? "FlowGraphInteger" /* FlowGraphTypes.Integer */; return serializedObjects; }, }, "math/or": { blocks: ["FlowGraphBitwiseOrBlock" /* FlowGraphBlockNames.BitwiseOr */], inputs: { values: { a: { name: "a" }, b: { name: "b" }, }, }, outputs: { values: { value: { name: "value" }, }, }, extraProcessor(_gltfBlock, _declaration, _mapping, _parser, serializedObjects, context) { var _a; // configure it to work the way glTF specifies (_a = serializedObjects[0]).config || (_a.config = {}); // try to infer the type or fallback to Integer const socketInA = serializedObjects[0].dataInputs[0]; const socketInB = serializedObjects[0].dataInputs[1]; serializedObjects[0].config.valueType = context._connectionValues[socketInA.uniqueId]?.type ?? context._connectionValues[socketInB.uniqueId]?.type ?? "FlowGraphInteger" /* FlowGraphTypes.Integer */; return serializedObjects; }, }, "math/xor": { blocks: ["FlowGraphBitwiseXorBlock" /* FlowGraphBlockNames.BitwiseXor */], inputs: { values: { a: { name: "a" }, b: { name: "b" }, }, }, outputs: { values: { value: { name: "value" }, }, }, extraProcessor(_gltfBlock, _declaration, _mapping, _parser, serializedObjects, context) { var _a; // configure it to work the way glTF specifies (_a = serializedObjects[0]).config || (_a.config = {}); // try to infer the type or fallback to Integer const socketInA = serializedObjects[0].dataInputs[0]; const socketInB = serializedObjects[0].dataInputs[1]; serializedObjects[0].config.valueType = context._connectionValues[socketInA.uniqueId]?.type ?? context._connectionValues[socketInB.uniqueId]?.type ?? "FlowGraphInteger" /* FlowGraphTypes.Integer */; return serializedObjects; }, }, "math/asr": getSimpleInputMapping("FlowGraphBitwiseRightShiftBlock" /* FlowGraphBlockNames.BitwiseRightShift */, ["a", "b"]), "math/lsl": getSimpleInputMapping("FlowGraphBitwiseLeftShiftBlock" /* FlowGraphBlockNames.BitwiseLeftShift */, ["a", "b"]), "math/clz": getSimpleInputMapping("FlowGraphLeadingZerosBlock" /* FlowGraphBlockNames.LeadingZeros */), "math/ctz": getSimpleInputMapping("FlowGraphTrailingZerosBlock" /* FlowGraphBlockNames.TrailingZeros */), "math/popcnt": getSimpleInputMapping("FlowGraphOneBitsCounterBlock" /* FlowGraphBlockNames.OneBitsCounter */), "math/rad": getSimpleInputMapping("FlowGraphDegToRadBlock" /* FlowGraphBlockNames.DegToRad */), "math/deg": getSimpleInputMapping("FlowGraphRadToDegBlock" /* FlowGraphBlockNames.RadToDeg */), "type/boolToInt": getSimpleInputMapping("FlowGraphBooleanToInt" /* FlowGraphBlockNames.BooleanToInt */), "type/boolToFloat": getSimpleInputMapping("FlowGraphBooleanToFloat" /* FlowGraphBlockNames.BooleanToFloat */), "type/intToBool": getSimpleInputMapping("FlowGraphIntToBoolean" /* FlowGraphBlockNames.IntToBoolean */), "type/intToFloat": getSimpleInputMapping("FlowGraphIntToFloat" /* FlowGraphBlockNames.IntToFloat */), "type/floatToInt": getSimpleInputMapping("FlowGraphFloatToInt" /* FlowGraphBlockNames.FloatToInt */), "type/floatToBool": getSimpleInputMapping("FlowGraphFloatToBoolean" /* FlowGraphBlockNames.FloatToBoolean */), // flows "flow/sequence": { blocks: ["FlowGraphSequenceBlock" /* FlowGraphBlockNames.Sequence */], extraProcessor(gltfBlock, _declaration, _mapping, _arrays, serializedObjects) { const serializedObject = serializedObjects[0]; serializedObject.config || (serializedObject.config = {}); serializedObject.config.outputSignalCount = Object.keys(gltfBlock.flows || []).length; serializedObject.signalOutputs.forEach((output, index) => { output.name = "out_" + index; }); return serializedObjects; }, }, "flow/branch": { blocks: ["FlowGraphBranchBlock" /* FlowGraphBlockNames.Branch */], outputs: { flows: { true: { name: "onTrue" }, false: { name: "onFalse" }, }, }, }, "flow/switch": { blocks: ["FlowGraphSwitchBlock" /* FlowGraphBlockNames.Switch */], configuration: { cases: { name: "cases", isArray: true, inOptions: true, defaultValue: [] }, }, inputs: { values: { selection: { name: "case" }, default: { name: "default" }, }, }, validation(gltfBlock) { const cases = gltfBlock.configuration?.cases; if (cases && cases.value) { const onlyIntegers = cases.value.every((caseValue) => { // case value should be an integer. Since Number.isInteger(1.0) is true, we need to check if toString has only digits. return typeof caseValue === "number" && /^-?\d+$/.test(caseValue.toString()); }); if (!onlyIntegers) { Logger.Warn("Switch cases should be integers. Using empty array instead."); cases.value = []; return { valid: true }; } // check for duplicates const uniqueCases = new Set(cases.value); cases.value = Array.from(uniqueCases); } return { valid: true }; }, extraProcessor(gltfBlock, declaration, _mapping, _arrays, serializedObjects) { // convert all names of output flow to out_$1 apart from "default" if (declaration.op !== "flow/switch" || !gltfBlock.flows || Object.keys(gltfBlock.flows).length === 0) { throw new Error("Switch should have a single configuration object, the cases array"); } const serializedObject = serializedObjects[0]; serializedObject.signalOutputs.forEach((output) => { if (output.name !== "default") { output.name = "out_" + output.name; } }); return serializedObjects; }, }, "flow/while": { blocks: ["FlowGraphWhileLoopBlock" /* FlowGraphBlockNames.WhileLoop */], outputs: { flows: { loopBody: { name: "executionFlow" }, }, }, }, "flow/for": { blocks: ["FlowGraphForLoopBlock" /* FlowGraphBlockNames.ForLoop */], configuration: { initialIndex: { name: "initialIndex", gltfType: "number", inOptions: true, defaultValue: 0 }, }, inputs: { values: { startIndex: { name: "startIndex", gltfType: "number" }, endIndex: { name: "endIndex", gltfType: "number" }, }, }, outputs: { values: { index: { name: "index" }, }, flows: { loopBody: { name: "executionFlow" }, }, }, extraProcessor(_gltfBlock, _declaration, _mapping, _arrays, serializedObjects) { const serializedObject = serializedObjects[0]; serializedObject.config || (serializedObject.config = {}); serializedObject.config.incrementIndexWhenLoopDone = true; return serializedObjects; }, }, "flow/doN": { blocks: ["FlowGraphDoNBlock" /* FlowGraphBlockNames.DoN */], configuration: {}, inputs: { values: { n: { name: "maxExecutions", gltfType: "number" }, }, }, outputs: { values: { currentCount: { name: "executionCount" }, }, }, }, "flow/multiGate": { blocks: ["FlowGraphMultiGateBlock" /* FlowGraphBlockNames.MultiGate */], configuration: { isRandom: { name: "isRandom", gltfType: "boolean", inOptions: true, defaultValue: false }, isLoop: { name: "isLoop", gltfType: "boolean", inOptions: true, defaultValue: false }, }, extraProcessor(gltfBlock, declaration, _mapping, _arrays, serializedObjects) { if (declaration.op !== "flow/multiGate" || !gltfBlock.flows || Object.keys(gltfBlock.flows).length === 0) { throw new Error("MultiGate should have a single configuration object, the number of output flows"); } const serializedObject = serializedObjects[0]; serializedObject.config || (serializedObject.config = {}); serializedObject.config.outputSignalCount = Object.keys(gltfBlock.flows).length; serializedObject.signalOutputs.forEach((output, index) => { output.name = "out_" + index; }); return serializedObjects; }, }, "flow/waitAll": { blocks: ["FlowGraphWaitAllBlock" /* FlowGraphBlockNames.WaitAll */], configuration: { inputFlows: { name: "inputSignalCount", gltfType: "number", inOptions: true, defaultValue: 0 }, }, inputs: { flows: { reset: { name: "reset" }, "[segment]": { name: "in_$1" }, }, }, validation(gltfBlock) { // check that the configuration value is an integer if (typeof gltfBlock.configuration?.inputFlows?.value?.[0] !== "number") { gltfBlock.configuration = gltfBlock.configuration || { inputFlows: { value: [0] }, }; gltfBlock.configuration.inputFlows.value = [0]; } return { valid: true }; }, }, "flow/throttle": { blocks: ["FlowGraphThrottleBlock" /* FlowGraphBlockNames.Throttle */], outputs: { flows: { err: { name: "error" }, }, }, }, "flow/setDelay": { blocks: ["FlowGraphSetDelayBlock" /* FlowGraphBlockNames.SetDelay */], outputs: { flows: { err: { name: "error" }, }, }, }, "flow/cancelDelay": { blocks: ["FlowGraphCancelDelayBlock" /* FlowGraphBlockNames.CancelDelay */], }, "variable/get": { blocks: ["FlowGraphGetVariableBlock" /* FlowGraphBlockNames.GetVariable */], validation(gltfBlock) { if (!gltfBlock.configuration?.variable?.value) { Logger.Error("Variable get block should have a variable configuration"); return { valid: false, error: "Variable get block should have a variable configuration" }; } return { valid: true }; }, configuration: { variable: { name: "variable", gltfType: "number", flowGraphType: "string", inOptions: true, isVariable: true, dataTransformer(index, parser) { return parser.getVariableName(index); }, }, }, }, "variable/set": { blocks: ["FlowGraphSetVariableBlock" /* FlowGraphBlockNames.SetVariable */], configuration: { variables: { name: "variables", gltfType: "number", flowGraphType: "string", inOptions: true, isArray: true, dataTransformer(index, parser) { return index.map((i) => parser.getVariableName(i)); }, }, }, extraProcessor(_gltfBlock, _declaration, _mapping, parser, serializedObjects) { // variable/get configuration const serializedGetVariable = serializedObjects[0]; serializedGetVariable.dataInputs.forEach((input) => { input.name = parser.getVariableName(+input.name); }); return serializedObjects; }, }, "variable/interpolate": { blocks: [ "FlowGraphInterpolationBlock" /* FlowGraphBlockNames.ValueInterpolation */, "FlowGraphContextBlock" /* FlowGraphBlockNames.Context */, "FlowGraphPlayAnimationBlock" /* FlowGraphBlockNames.PlayAnimation */, "FlowGraphBezierCurveEasing" /* FlowGraphBlockNames.BezierCurveEasing */, "FlowGraphGetVariableBlock" /* FlowGraphBlockNames.GetVariable */, ], configuration: { variable: { name: "propertyName", inOptions: true, isVariable: true, dataTransformer(index, parser) { return parser.getVariableName(index); }, }, useSlerp: { name: "animationType", inOptions: true, defaultValue: false, dataTransformer(value) { return value === true ? "Quaternion" /* FlowGraphTypes.Quaternion */ : undefined; }, }, }, inputs: { values: { value: { name: "value_1" }, duration: { name: "duration_1", gltfType: "number" }, p1: { name: "controlPoint1", toBlock: "FlowGraphBezierCurveEasing" /* FlowGraphBlockNames.BezierCurveEasing */ }, p2: { name: "controlPoint2", toBlock: "FlowGraphBezierCurveEasing" /* FlowGraphBlockNames.BezierCurveEasing */ }, }, flows: { in: { name: "in", toBlock: "FlowGraphPlayAnimationBlock" /* FlowGraphBlockNames.PlayAnimation */ }, }, }, outputs: { flows: { err: { name: "error", toBlock: "FlowGraphPlayAnimationBlock" /* FlowGraphBlockNames.PlayAnimation */ }, out: { name: "out", toBlock: "FlowGraphPlayAnimationBlock" /* FlowGraphBlockNames.PlayAnimation */ }, done: { name: "done", toBlock: "FlowGraphPlayAnimationBlock" /* FlowGraphBlockNames.PlayAnimation */ }, }, }, interBlockConnectors: [ { input: "object", output: "userVariables", inputBlockIndex: 2, outputBlockIndex: 1, isVariable: true, }, { input: "animation", output: "animation", inputBlockIndex: 2, outputBlockIndex: 0, isVariable: true, }, { input: "easingFunction", output: "easingFunction", inputBlockIndex: 0, outputBlockIndex: 3, isVariable: true, }, { input: "value_0", output: "value", inputBlockIndex: 0, outputBlockIndex: 4, isVariable: true, }, ], extraProcessor(gltfBlock, _declaration, _mapping, parser, serializedObjects) { var _a, _b; // is useSlerp is used, animationType should be set to be quaternion! const serializedValueInterpolation = serializedObjects[0]; const propertyIndex = gltfBlock.configuration?.variable.value?.[0]; if (typeof propertyIndex !== "number") { Logger.Error("Variable index is not defined for variable interpolation block"); throw new Error("Variable index is not defined for variable interpolation block"); } const variable = parser.arrays.staticVariables[propertyIndex]; // if not set by useSlerp if (typeof serializedValueInterpolation.config?.animationType?.value === "undefined") { serializedValueInterpolation.config || (serializedValueInterpolation.config = {}); (_a = serializedValueInterpolation.config).animationType || (_a.animationType = {}); serializedValueInterpolation.config.animationType.value = getAnimationTypeByFlowGraphType(variable.type); } // variable/get configuration const serializedGetVariable = serializedObjects[4]; serializedGetVariable.config || (serializedGetVariable.config = {}); (_b = serializedGetVariable.config).variable || (_b.variable = {}); serializedGetVariable.config.variable.value = parser.getVariableName(propertyIndex); return serializedObjects; }, }, "pointer/get": { blocks: ["FlowGraphGetPropertyBlock" /* FlowGraphBlockNames.GetProperty */, "FlowGraphJsonPointerParserBlock" /* FlowGraphBlockNames.JsonPointerParser */], configuration: { pointer: { name: "jsonPointer", toBlock: "FlowGraphJsonPointerParserBlock" /* FlowGraphBlockNames.JsonPointerParser */ }, }, inputs: { values: { "[segment]": { name: "$1", toBlock: "FlowGraphJsonPointerParserBlock" /* FlowGraphBlockNames.JsonPointerParser */ }, }, }, interBlockConnectors: [ { input: "object", output: "object", inputBlockIndex: 0, outputBlockIndex: 1, isVariable: true, }, { input: "propertyName", output: "propertyName", inputBlockIndex: 0, outputBlockIndex: 1, isVariable: true, }, { input: "customGetFunction", output: "getFunction", inputBlockIndex: 0, outputBlockIndex: 1, isVariable: true, }, ], extraProcessor(gltfBlock, _declaration, _mapping, parser, serializedObjects) { serializedObjects.forEach((serializedObject) => { // check if it is the json pointer block if (serializedObject.className === "FlowGraphJsonPointerParserBlock" /* FlowGraphBlockNames.JsonPointerParser */) { serializedObject.config || (serializedObject.config = {}); serializedObject.config.outputValue = true; } }); return serializedObjects; }, }, "pointer/set": {