import { g as RegisterClass, V as Vector2, b as Vector3, C as Constants, Q as Quaternion, p as Matrix, z as Vector4, h as Color4, b1 as Color3, L as Logger } from './index-D9EJJo2H.esm.js';

/**
 * Class that represents an integer value.
 */
class FlowGraphInteger {
    constructor(value) {
        this.value = this._toInt(value);
    }
    /**
     * Converts a float to an integer.
     * @param n the float to convert
     * @returns the result of n | 0 - converting it to a int
     */
    _toInt(n) {
        return n | 0;
    }
    /**
     * Adds two integers together.
     * @param other the other integer to add
     * @returns a FlowGraphInteger with the result of the addition
     */
    add(other) {
        return new FlowGraphInteger(this.value + other.value);
    }
    /**
     * Subtracts two integers.
     * @param other the other integer to subtract
     * @returns a FlowGraphInteger with the result of the subtraction
     */
    subtract(other) {
        return new FlowGraphInteger(this.value - other.value);
    }
    /**
     * Multiplies two integers.
     * @param other the other integer to multiply
     * @returns a FlowGraphInteger with the result of the multiplication
     */
    multiply(other) {
        return new FlowGraphInteger(Math.imul(this.value, other.value));
    }
    /**
     * Divides two integers.
     * @param other the other integer to divide
     * @returns a FlowGraphInteger with the result of the division
     */
    divide(other) {
        return new FlowGraphInteger(this.value / other.value);
    }
    /**
     * The class name of this type.
     * @returns
     */
    getClassName() {
        return FlowGraphInteger.ClassName;
    }
    /**
     * Compares two integers for equality.
     * @param other the other integer to compare
     * @returns
     */
    equals(other) {
        return this.value === other.value;
    }
    /**
     * Parses a FlowGraphInteger from a serialization object.
     * @param value te number to parse
     * @returns
     */
    static FromValue(value) {
        return new FlowGraphInteger(value);
    }
    toString() {
        return this.value.toString();
    }
}
FlowGraphInteger.ClassName = "FlowGraphInteger";
RegisterClass("FlowGraphInteger", FlowGraphInteger);

// Note - the matrix classes are basically column-major, and work similarly to Babylon.js' Matrix class.
/**
 * A 2x2 matrix.
 */
class FlowGraphMatrix2D {
    constructor(m = [1, 0, 0, 1]) {
        this._m = m;
    }
    get m() {
        return this._m;
    }
    transformVector(v) {
        return this.transformVectorToRef(v, new Vector2());
    }
    transformVectorToRef(v, result) {
        result.x = v.x * this._m[0] + v.y * this._m[1];
        result.y = v.x * this._m[2] + v.y * this._m[3];
        return result;
    }
    asArray() {
        return this.toArray();
    }
    toArray(emptyArray = []) {
        for (let i = 0; i < 4; i++) {
            emptyArray[i] = this._m[i];
        }
        return emptyArray;
    }
    fromArray(array) {
        for (let i = 0; i < 4; i++) {
            this._m[i] = array[i];
        }
        return this;
    }
    multiplyToRef(other, result) {
        const otherMatrix = other._m;
        const thisMatrix = this._m;
        const r = result._m;
        // other * this
        r[0] = otherMatrix[0] * thisMatrix[0] + otherMatrix[1] * thisMatrix[2];
        r[1] = otherMatrix[0] * thisMatrix[1] + otherMatrix[1] * thisMatrix[3];
        r[2] = otherMatrix[2] * thisMatrix[0] + otherMatrix[3] * thisMatrix[2];
        r[3] = otherMatrix[2] * thisMatrix[1] + otherMatrix[3] * thisMatrix[3];
        return result;
    }
    multiply(other) {
        return this.multiplyToRef(other, new FlowGraphMatrix2D());
    }
    divideToRef(other, result) {
        const m = this._m;
        const o = other._m;
        const r = result._m;
        r[0] = m[0] / o[0];
        r[1] = m[1] / o[1];
        r[2] = m[2] / o[2];
        r[3] = m[3] / o[3];
        return result;
    }
    divide(other) {
        return this.divideToRef(other, new FlowGraphMatrix2D());
    }
    addToRef(other, result) {
        const m = this._m;
        const o = other.m;
        const r = result.m;
        r[0] = m[0] + o[0];
        r[1] = m[1] + o[1];
        r[2] = m[2] + o[2];
        r[3] = m[3] + o[3];
        return result;
    }
    add(other) {
        return this.addToRef(other, new FlowGraphMatrix2D());
    }
    subtractToRef(other, result) {
        const m = this._m;
        const o = other.m;
        const r = result.m;
        r[0] = m[0] - o[0];
        r[1] = m[1] - o[1];
        r[2] = m[2] - o[2];
        r[3] = m[3] - o[3];
        return result;
    }
    subtract(other) {
        return this.subtractToRef(other, new FlowGraphMatrix2D());
    }
    transpose() {
        const m = this._m;
        return new FlowGraphMatrix2D([m[0], m[2], m[1], m[3]]);
    }
    determinant() {
        const m = this._m;
        return m[0] * m[3] - m[1] * m[2];
    }
    inverse() {
        const det = this.determinant();
        if (det === 0) {
            throw new Error("Matrix is not invertible");
        }
        const m = this._m;
        const invDet = 1 / det;
        return new FlowGraphMatrix2D([m[3] * invDet, -m[1] * invDet, -m[2] * invDet, m[0] * invDet]);
    }
    equals(other, epsilon = 0) {
        const m = this._m;
        const o = other.m;
        if (epsilon === 0) {
            return m[0] === o[0] && m[1] === o[1] && m[2] === o[2] && m[3] === o[3];
        }
        return Math.abs(m[0] - o[0]) < epsilon && Math.abs(m[1] - o[1]) < epsilon && Math.abs(m[2] - o[2]) < epsilon && Math.abs(m[3] - o[3]) < epsilon;
    }
    getClassName() {
        return "FlowGraphMatrix2D";
    }
    toString() {
        return `FlowGraphMatrix2D(${this._m.join(", ")})`;
    }
}
/**
 * A 3x3 matrix.
 */
class FlowGraphMatrix3D {
    constructor(array = [1, 0, 0, 0, 1, 0, 0, 0, 1]) {
        this._m = array;
    }
    get m() {
        return this._m;
    }
    transformVector(v) {
        return this.transformVectorToRef(v, new Vector3());
    }
    transformVectorToRef(v, result) {
        const m = this._m;
        result.x = v.x * m[0] + v.y * m[1] + v.z * m[2];
        result.y = v.x * m[3] + v.y * m[4] + v.z * m[5];
        result.z = v.x * m[6] + v.y * m[7] + v.z * m[8];
        return result;
    }
    multiplyToRef(other, result) {
        const otherMatrix = other._m;
        const thisMatrix = this._m;
        const r = result.m;
        r[0] = otherMatrix[0] * thisMatrix[0] + otherMatrix[1] * thisMatrix[3] + otherMatrix[2] * thisMatrix[6];
        r[1] = otherMatrix[0] * thisMatrix[1] + otherMatrix[1] * thisMatrix[4] + otherMatrix[2] * thisMatrix[7];
        r[2] = otherMatrix[0] * thisMatrix[2] + otherMatrix[1] * thisMatrix[5] + otherMatrix[2] * thisMatrix[8];
        r[3] = otherMatrix[3] * thisMatrix[0] + otherMatrix[4] * thisMatrix[3] + otherMatrix[5] * thisMatrix[6];
        r[4] = otherMatrix[3] * thisMatrix[1] + otherMatrix[4] * thisMatrix[4] + otherMatrix[5] * thisMatrix[7];
        r[5] = otherMatrix[3] * thisMatrix[2] + otherMatrix[4] * thisMatrix[5] + otherMatrix[5] * thisMatrix[8];
        r[6] = otherMatrix[6] * thisMatrix[0] + otherMatrix[7] * thisMatrix[3] + otherMatrix[8] * thisMatrix[6];
        r[7] = otherMatrix[6] * thisMatrix[1] + otherMatrix[7] * thisMatrix[4] + otherMatrix[8] * thisMatrix[7];
        r[8] = otherMatrix[6] * thisMatrix[2] + otherMatrix[7] * thisMatrix[5] + otherMatrix[8] * thisMatrix[8];
        return result;
    }
    multiply(other) {
        return this.multiplyToRef(other, new FlowGraphMatrix3D());
    }
    divideToRef(other, result) {
        const m = this._m;
        const o = other.m;
        const r = result.m;
        r[0] = m[0] / o[0];
        r[1] = m[1] / o[1];
        r[2] = m[2] / o[2];
        r[3] = m[3] / o[3];
        r[4] = m[4] / o[4];
        r[5] = m[5] / o[5];
        r[6] = m[6] / o[6];
        r[7] = m[7] / o[7];
        r[8] = m[8] / o[8];
        return result;
    }
    divide(other) {
        return this.divideToRef(other, new FlowGraphMatrix3D());
    }
    addToRef(other, result) {
        const m = this._m;
        const o = other.m;
        const r = result.m;
        r[0] = m[0] + o[0];
        r[1] = m[1] + o[1];
        r[2] = m[2] + o[2];
        r[3] = m[3] + o[3];
        r[4] = m[4] + o[4];
        r[5] = m[5] + o[5];
        r[6] = m[6] + o[6];
        r[7] = m[7] + o[7];
        r[8] = m[8] + o[8];
        return result;
    }
    add(other) {
        return this.addToRef(other, new FlowGraphMatrix3D());
    }
    subtractToRef(other, result) {
        const m = this._m;
        const o = other.m;
        const r = result.m;
        r[0] = m[0] - o[0];
        r[1] = m[1] - o[1];
        r[2] = m[2] - o[2];
        r[3] = m[3] - o[3];
        r[4] = m[4] - o[4];
        r[5] = m[5] - o[5];
        r[6] = m[6] - o[6];
        r[7] = m[7] - o[7];
        r[8] = m[8] - o[8];
        return result;
    }
    subtract(other) {
        return this.subtractToRef(other, new FlowGraphMatrix3D());
    }
    toArray(emptyArray = []) {
        for (let i = 0; i < 9; i++) {
            emptyArray[i] = this._m[i];
        }
        return emptyArray;
    }
    asArray() {
        return this.toArray();
    }
    fromArray(array) {
        for (let i = 0; i < 9; i++) {
            this._m[i] = array[i];
        }
        return this;
    }
    transpose() {
        const m = this._m;
        return new FlowGraphMatrix3D([m[0], m[3], m[6], m[1], m[4], m[7], m[2], m[5], m[8]]);
    }
    determinant() {
        const m = this._m;
        return m[0] * (m[4] * m[8] - m[5] * m[7]) - m[1] * (m[3] * m[8] - m[5] * m[6]) + m[2] * (m[3] * m[7] - m[4] * m[6]);
    }
    inverse() {
        const det = this.determinant();
        if (det === 0) {
            throw new Error("Matrix is not invertible");
        }
        const m = this._m;
        const invDet = 1 / det;
        return new FlowGraphMatrix3D([
            (m[4] * m[8] - m[5] * m[7]) * invDet,
            (m[2] * m[7] - m[1] * m[8]) * invDet,
            (m[1] * m[5] - m[2] * m[4]) * invDet,
            (m[5] * m[6] - m[3] * m[8]) * invDet,
            (m[0] * m[8] - m[2] * m[6]) * invDet,
            (m[2] * m[3] - m[0] * m[5]) * invDet,
            (m[3] * m[7] - m[4] * m[6]) * invDet,
            (m[1] * m[6] - m[0] * m[7]) * invDet,
            (m[0] * m[4] - m[1] * m[3]) * invDet,
        ]);
    }
    equals(other, epsilon = 0) {
        const m = this._m;
        const o = other.m;
        // performance shortcut
        if (epsilon === 0) {
            return m[0] === o[0] && m[1] === o[1] && m[2] === o[2] && m[3] === o[3] && m[4] === o[4] && m[5] === o[5] && m[6] === o[6] && m[7] === o[7] && m[8] === o[8];
        }
        return (Math.abs(m[0] - o[0]) < epsilon &&
            Math.abs(m[1] - o[1]) < epsilon &&
            Math.abs(m[2] - o[2]) < epsilon &&
            Math.abs(m[3] - o[3]) < epsilon &&
            Math.abs(m[4] - o[4]) < epsilon &&
            Math.abs(m[5] - o[5]) < epsilon &&
            Math.abs(m[6] - o[6]) < epsilon &&
            Math.abs(m[7] - o[7]) < epsilon &&
            Math.abs(m[8] - o[8]) < epsilon);
    }
    getClassName() {
        return "FlowGraphMatrix3D";
    }
    toString() {
        return `FlowGraphMatrix3D(${this._m.join(", ")})`;
    }
}

/**
 * The types supported by the flow graph.
 */
var FlowGraphTypes;
(function (FlowGraphTypes) {
    FlowGraphTypes["Any"] = "any";
    FlowGraphTypes["String"] = "string";
    FlowGraphTypes["Number"] = "number";
    FlowGraphTypes["Boolean"] = "boolean";
    FlowGraphTypes["Object"] = "object";
    FlowGraphTypes["Integer"] = "FlowGraphInteger";
    FlowGraphTypes["Vector2"] = "Vector2";
    FlowGraphTypes["Vector3"] = "Vector3";
    FlowGraphTypes["Vector4"] = "Vector4";
    FlowGraphTypes["Quaternion"] = "Quaternion";
    FlowGraphTypes["Matrix"] = "Matrix";
    FlowGraphTypes["Matrix2D"] = "Matrix2D";
    FlowGraphTypes["Matrix3D"] = "Matrix3D";
    FlowGraphTypes["Color3"] = "Color3";
    FlowGraphTypes["Color4"] = "Color4";
})(FlowGraphTypes || (FlowGraphTypes = {}));
/**
 * A rich type represents extra information about a type,
 * such as its name and a default value constructor.
 */
class RichType {
    constructor(
    /**
     * The name given to the type.
     */
    typeName, 
    /**
     * The default value of the type.
     */
    defaultValue, 
    /**
     * [-1] The ANIMATIONTYPE of the type, if available
     */
    animationType = -1) {
        this.typeName = typeName;
        this.defaultValue = defaultValue;
        this.animationType = animationType;
    }
    /**
     * Serializes this rich type into a serialization object.
     * @param serializationObject the object to serialize to
     */
    serialize(serializationObject) {
        serializationObject.typeName = this.typeName;
        serializationObject.defaultValue = this.defaultValue;
    }
}
const RichTypeAny = new RichType("any" /* FlowGraphTypes.Any */, undefined);
const RichTypeString = new RichType("string" /* FlowGraphTypes.String */, "");
const RichTypeNumber = new RichType("number" /* FlowGraphTypes.Number */, 0, Constants.ANIMATIONTYPE_FLOAT);
const RichTypeBoolean = new RichType("boolean" /* FlowGraphTypes.Boolean */, false);
const RichTypeVector2 = new RichType("Vector2" /* FlowGraphTypes.Vector2 */, Vector2.Zero(), Constants.ANIMATIONTYPE_VECTOR2);
const RichTypeVector3 = new RichType("Vector3" /* FlowGraphTypes.Vector3 */, Vector3.Zero(), Constants.ANIMATIONTYPE_VECTOR3);
const RichTypeVector4 = new RichType("Vector4" /* FlowGraphTypes.Vector4 */, Vector4.Zero());
const RichTypeMatrix = new RichType("Matrix" /* FlowGraphTypes.Matrix */, Matrix.Identity(), Constants.ANIMATIONTYPE_MATRIX);
const RichTypeMatrix2D = new RichType("Matrix2D" /* FlowGraphTypes.Matrix2D */, new FlowGraphMatrix2D());
const RichTypeMatrix3D = new RichType("Matrix3D" /* FlowGraphTypes.Matrix3D */, new FlowGraphMatrix3D());
const RichTypeColor3 = new RichType("Color3" /* FlowGraphTypes.Color3 */, Color3.Black(), Constants.ANIMATIONTYPE_COLOR3);
const RichTypeColor4 = new RichType("Color4" /* FlowGraphTypes.Color4 */, new Color4(0, 0, 0, 0), Constants.ANIMATIONTYPE_COLOR4);
const RichTypeQuaternion = new RichType("Quaternion" /* FlowGraphTypes.Quaternion */, Quaternion.Identity(), Constants.ANIMATIONTYPE_QUATERNION);
RichTypeQuaternion.typeTransformer = (value) => {
    if (value.getClassName) {
        if (value.getClassName() === "Vector4" /* FlowGraphTypes.Vector4 */) {
            return Quaternion.FromArray(value.asArray());
        }
        else if (value.getClassName() === "Vector3" /* FlowGraphTypes.Vector3 */) {
            return Quaternion.FromEulerVector(value);
        }
        else if (value.getClassName() === "Matrix" /* FlowGraphTypes.Matrix */) {
            return Quaternion.FromRotationMatrix(value);
        }
    }
    return value;
};
const RichTypeFlowGraphInteger = new RichType("FlowGraphInteger" /* FlowGraphTypes.Integer */, new FlowGraphInteger(0), Constants.ANIMATIONTYPE_FLOAT);
/**
 * Given a value, try to deduce its rich type.
 * @param value the value to deduce the rich type from
 * @returns the value's rich type, or RichTypeAny if the type could not be deduced.
 */
// eslint-disable-next-line @typescript-eslint/naming-convention
function getRichTypeFromValue(value) {
    const anyValue = value;
    switch (typeof value) {
        case "string" /* FlowGraphTypes.String */:
            return RichTypeString;
        case "number" /* FlowGraphTypes.Number */:
            return RichTypeNumber;
        case "boolean" /* FlowGraphTypes.Boolean */:
            return RichTypeBoolean;
        case "object" /* FlowGraphTypes.Object */:
            if (anyValue.getClassName) {
                switch (anyValue.getClassName()) {
                    case "Vector2" /* FlowGraphTypes.Vector2 */:
                        return RichTypeVector2;
                    case "Vector3" /* FlowGraphTypes.Vector3 */:
                        return RichTypeVector3;
                    case "Vector4" /* FlowGraphTypes.Vector4 */:
                        return RichTypeVector4;
                    case "Matrix" /* FlowGraphTypes.Matrix */:
                        return RichTypeMatrix;
                    case "Color3" /* FlowGraphTypes.Color3 */:
                        return RichTypeColor3;
                    case "Color4" /* FlowGraphTypes.Color4 */:
                        return RichTypeColor4;
                    case "Quaternion" /* FlowGraphTypes.Quaternion */:
                        return RichTypeQuaternion;
                    case "FlowGraphInteger" /* FlowGraphTypes.Integer */:
                        return RichTypeFlowGraphInteger;
                    case "Matrix2D" /* FlowGraphTypes.Matrix2D */:
                        return RichTypeMatrix2D;
                    case "Matrix3D" /* FlowGraphTypes.Matrix3D */:
                        return RichTypeMatrix3D;
                }
            }
            return RichTypeAny;
        default:
            return RichTypeAny;
    }
}
/**
 * Given a flow graph type, return the rich type that corresponds to it.
 * @param flowGraphType the flow graph type
 * @returns the rich type that corresponds to the flow graph type
 */
// eslint-disable-next-line @typescript-eslint/naming-convention
function getRichTypeByFlowGraphType(flowGraphType) {
    switch (flowGraphType) {
        case "string" /* FlowGraphTypes.String */:
            return RichTypeString;
        case "number" /* FlowGraphTypes.Number */:
            return RichTypeNumber;
        case "boolean" /* FlowGraphTypes.Boolean */:
            return RichTypeBoolean;
        case "Vector2" /* FlowGraphTypes.Vector2 */:
            return RichTypeVector2;
        case "Vector3" /* FlowGraphTypes.Vector3 */:
            return RichTypeVector3;
        case "Vector4" /* FlowGraphTypes.Vector4 */:
            return RichTypeVector4;
        case "Matrix" /* FlowGraphTypes.Matrix */:
            return RichTypeMatrix;
        case "Color3" /* FlowGraphTypes.Color3 */:
            return RichTypeColor3;
        case "Color4" /* FlowGraphTypes.Color4 */:
            return RichTypeColor4;
        case "Quaternion" /* FlowGraphTypes.Quaternion */:
            return RichTypeQuaternion;
        case "FlowGraphInteger" /* FlowGraphTypes.Integer */:
            return RichTypeFlowGraphInteger;
        case "Matrix2D" /* FlowGraphTypes.Matrix2D */:
            return RichTypeMatrix2D;
        case "Matrix3D" /* FlowGraphTypes.Matrix3D */:
            return RichTypeMatrix3D;
        default:
            return RichTypeAny;
    }
}
/**
 * get the animation type for a given flow graph type
 * @param flowGraphType the flow graph type
 * @returns the animation type for this flow graph type
 */
// eslint-disable-next-line @typescript-eslint/naming-convention
function getAnimationTypeByFlowGraphType(flowGraphType) {
    switch (flowGraphType) {
        case "number" /* FlowGraphTypes.Number */:
            return Constants.ANIMATIONTYPE_FLOAT;
        case "Vector2" /* FlowGraphTypes.Vector2 */:
            return Constants.ANIMATIONTYPE_VECTOR2;
        case "Vector3" /* FlowGraphTypes.Vector3 */:
            return Constants.ANIMATIONTYPE_VECTOR3;
        case "Matrix" /* FlowGraphTypes.Matrix */:
            return Constants.ANIMATIONTYPE_MATRIX;
        case "Color3" /* FlowGraphTypes.Color3 */:
            return Constants.ANIMATIONTYPE_COLOR3;
        case "Color4" /* FlowGraphTypes.Color4 */:
            return Constants.ANIMATIONTYPE_COLOR4;
        case "Quaternion" /* FlowGraphTypes.Quaternion */:
            return Constants.ANIMATIONTYPE_QUATERNION;
        default:
            return Constants.ANIMATIONTYPE_FLOAT;
    }
}
/**
 * Given an animation type, return the rich type that corresponds to it.
 * @param animationType the animation type
 * @returns the rich type that corresponds to the animation type
 */
// eslint-disable-next-line @typescript-eslint/naming-convention
function getRichTypeByAnimationType(animationType) {
    switch (animationType) {
        case Constants.ANIMATIONTYPE_FLOAT:
            return RichTypeNumber;
        case Constants.ANIMATIONTYPE_VECTOR2:
            return RichTypeVector2;
        case Constants.ANIMATIONTYPE_VECTOR3:
            return RichTypeVector3;
        case Constants.ANIMATIONTYPE_MATRIX:
            return RichTypeMatrix;
        case Constants.ANIMATIONTYPE_COLOR3:
            return RichTypeColor3;
        case Constants.ANIMATIONTYPE_COLOR4:
            return RichTypeColor4;
        case Constants.ANIMATIONTYPE_QUATERNION:
            return RichTypeQuaternion;
        default:
            return RichTypeAny;
    }
}

function getMappingForFullOperationName(fullOperationName) {
    const [op, extension] = fullOperationName.split(":");
    return getMappingForDeclaration({ op, extension });
}
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.
 */
function addNewInteractivityFlowGraphMapping(key, extension, mapping) {
    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.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.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) {
            // configure it to work the way glTF specifies
            serializedObjects[0].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) {
            // configure it to work the way glTF specifies
            serializedObjects[0].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) {
            serializedObjects[0].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) {
            // configure it to work the way glTF specifies
            serializedObjects[0].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) {
            // configure it to work the way glTF specifies
            serializedObjects[0].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) {
            // configure it to work the way glTF specifies
            serializedObjects[0].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) {
            // configure it to work the way glTF specifies
            serializedObjects[0].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) {
            // configure it to work the way glTF specifies
            serializedObjects[0].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) {
            // configure it to work the way glTF specifies
            serializedObjects[0].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) {
            // configure it to work the way glTF specifies
            serializedObjects[0].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.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.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.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) {
            // 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.animationType ||= {};
                serializedValueInterpolation.config.animationType.value = getAnimationTypeByFlowGraphType(variable.type);
            }
            // variable/get configuration
            const serializedGetVariable = serializedObjects[4];
            serializedGetVariable.config ||= {};
            serializedGetVariable.config.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.outputValue = true;
                }
            });
            return serializedObjects;
        },
    },
    "pointer/set": {
        blocks: ["FlowGraphSetPropertyBlock" /* FlowGraphBlockNames.SetProperty */, "FlowGraphJsonPointerParserBlock" /* FlowGraphBlockNames.JsonPointerParser */],
        configuration: {
            pointer: { name: "jsonPointer", toBlock: "FlowGraphJsonPointerParserBlock" /* FlowGraphBlockNames.JsonPointerParser */ },
        },
        inputs: {
            values: {
                // must be defined due to the array taking over
                value: { name: "value" },
                "[segment]": { name: "$1", toBlock: "FlowGraphJsonPointerParserBlock" /* FlowGraphBlockNames.JsonPointerParser */ },
            },
        },
        outputs: {
            flows: {
                err: { name: "error" },
            },
        },
        interBlockConnectors: [
            {
                input: "object",
                output: "object",
                inputBlockIndex: 0,
                outputBlockIndex: 1,
                isVariable: true,
            },
            {
                input: "propertyName",
                output: "propertyName",
                inputBlockIndex: 0,
                outputBlockIndex: 1,
                isVariable: true,
            },
            {
                input: "customSetFunction",
                output: "setFunction",
                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.outputValue = true;
                }
            });
            return serializedObjects;
        },
    },
    "pointer/interpolate": {
        // interpolate, parse the pointer and play the animation generated. 3 blocks!
        blocks: ["FlowGraphInterpolationBlock" /* FlowGraphBlockNames.ValueInterpolation */, "FlowGraphJsonPointerParserBlock" /* FlowGraphBlockNames.JsonPointerParser */, "FlowGraphPlayAnimationBlock" /* FlowGraphBlockNames.PlayAnimation */, "FlowGraphBezierCurveEasing" /* FlowGraphBlockNames.BezierCurveEasing */],
        configuration: {
            pointer: { name: "jsonPointer", toBlock: "FlowGraphJsonPointerParserBlock" /* FlowGraphBlockNames.JsonPointerParser */ },
        },
        inputs: {
            values: {
                value: { name: "value_1" },
                "[segment]": { name: "$1", toBlock: "FlowGraphJsonPointerParserBlock" /* FlowGraphBlockNames.JsonPointerParser */ },
                duration: { name: "duration_1", gltfType: "number" /*, inOptions: true */ },
                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: "object",
                inputBlockIndex: 2,
                outputBlockIndex: 1,
                isVariable: true,
            },
            {
                input: "propertyName",
                output: "propertyName",
                inputBlockIndex: 0,
                outputBlockIndex: 1,
                isVariable: true,
            },
            {
                input: "customBuildAnimation",
                output: "generateAnimationsFunction",
                inputBlockIndex: 0,
                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: 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.outputValue = true;
                }
                else if (serializedObject.className === "FlowGraphInterpolationBlock" /* FlowGraphBlockNames.ValueInterpolation */) {
                    serializedObject.config ||= {};
                    Object.keys(gltfBlock.values || []).forEach((key) => {
                        const value = gltfBlock.values?.[key];
                        if (key === "value" && value) {
                            // get the type of the value
                            const type = value.type;
                            if (type !== undefined) {
                                serializedObject.config.animationType = parser.arrays.types[type].flowGraphType;
                            }
                        }
                    });
                }
            });
            return serializedObjects;
        },
    },
    "animation/start": {
        blocks: ["FlowGraphPlayAnimationBlock" /* FlowGraphBlockNames.PlayAnimation */, "FlowGraphArrayIndexBlock" /* FlowGraphBlockNames.ArrayIndex */, "KHR_interactivity/FlowGraphGLTFDataProvider"],
        inputs: {
            values: {
                animation: { name: "index", gltfType: "number", toBlock: "FlowGraphArrayIndexBlock" /* FlowGraphBlockNames.ArrayIndex */ },
                speed: { name: "speed", gltfType: "number" },
                startTime: { name: "from", gltfType: "number", dataTransformer: (time, parser) => [time[0] * parser._animationTargetFps] },
                endTime: { name: "to", gltfType: "number", dataTransformer: (time, parser) => [time[0] * parser._animationTargetFps] },
            },
        },
        outputs: {
            flows: {
                err: { name: "error" },
            },
        },
        interBlockConnectors: [
            {
                input: "animationGroup",
                output: "value",
                inputBlockIndex: 0,
                outputBlockIndex: 1,
                isVariable: true,
            },
            {
                input: "array",
                output: "animationGroups",
                inputBlockIndex: 1,
                outputBlockIndex: 2,
                isVariable: true,
            },
        ],
        extraProcessor(_gltfBlock, _declaration, _mapping, _arrays, serializedObjects, _context, globalGLTF) {
            // add the glTF to the configuration of the last serialized object
            const serializedObject = serializedObjects[serializedObjects.length - 1];
            serializedObject.config ||= {};
            serializedObject.config.glTF = globalGLTF;
            return serializedObjects;
        },
    },
    "animation/stop": {
        blocks: ["FlowGraphStopAnimationBlock" /* FlowGraphBlockNames.StopAnimation */, "FlowGraphArrayIndexBlock" /* FlowGraphBlockNames.ArrayIndex */, "KHR_interactivity/FlowGraphGLTFDataProvider"],
        inputs: {
            values: {
                animation: { name: "index", gltfType: "number", toBlock: "FlowGraphArrayIndexBlock" /* FlowGraphBlockNames.ArrayIndex */ },
            },
        },
        outputs: {
            flows: {
                err: { name: "error" },
            },
        },
        interBlockConnectors: [
            {
                input: "animationGroup",
                output: "value",
                inputBlockIndex: 0,
                outputBlockIndex: 1,
                isVariable: true,
            },
            {
                input: "array",
                output: "animationGroups",
                inputBlockIndex: 1,
                outputBlockIndex: 2,
                isVariable: true,
            },
        ],
        extraProcessor(_gltfBlock, _declaration, _mapping, _arrays, serializedObjects, _context, globalGLTF) {
            // add the glTF to the configuration of the last serialized object
            const serializedObject = serializedObjects[serializedObjects.length - 1];
            serializedObject.config ||= {};
            serializedObject.config.glTF = globalGLTF;
            return serializedObjects;
        },
    },
    "animation/stopAt": {
        blocks: ["FlowGraphStopAnimationBlock" /* FlowGraphBlockNames.StopAnimation */, "FlowGraphArrayIndexBlock" /* FlowGraphBlockNames.ArrayIndex */, "KHR_interactivity/FlowGraphGLTFDataProvider"],
        configuration: {},
        inputs: {
            values: {
                animation: { name: "index", gltfType: "number", toBlock: "FlowGraphArrayIndexBlock" /* FlowGraphBlockNames.ArrayIndex */ },
                stopTime: { name: "stopAtFrame", gltfType: "number", dataTransformer: (time, parser) => [time[0] * parser._animationTargetFps] },
            },
        },
        outputs: {
            flows: {
                err: { name: "error" },
            },
        },
        interBlockConnectors: [
            {
                input: "animationGroup",
                output: "value",
                inputBlockIndex: 0,
                outputBlockIndex: 1,
                isVariable: true,
            },
            {
                input: "array",
                output: "animationGroups",
                inputBlockIndex: 1,
                outputBlockIndex: 2,
                isVariable: true,
            },
        ],
        extraProcessor(_gltfBlock, _declaration, _mapping, _arrays, serializedObjects, _context, globalGLTF) {
            // add the glTF to the configuration of the last serialized object
            const serializedObject = serializedObjects[serializedObjects.length - 1];
            serializedObject.config ||= {};
            serializedObject.config.glTF = globalGLTF;
            return serializedObjects;
        },
    },
    "math/switch": {
        blocks: ["FlowGraphDataSwitchBlock" /* FlowGraphBlockNames.DataSwitch */],
        configuration: {
            cases: { name: "cases", isArray: true, inOptions: true, defaultValue: [] },
        },
        inputs: {
            values: {
                selection: { name: "case" },
            },
        },
        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) {
            const serializedObject = serializedObjects[0];
            serializedObject.dataInputs.forEach((input) => {
                if (input.name !== "default" && input.name !== "case") {
                    input.name = "in_" + input.name;
                }
            });
            serializedObject.config ||= {};
            serializedObject.config.treatCasesAsIntegers = true;
            return serializedObjects;
        },
    },
    "debug/log": {
        blocks: ["FlowGraphConsoleLogBlock" /* FlowGraphBlockNames.ConsoleLog */],
        configuration: {
            message: { name: "messageTemplate", inOptions: true },
        },
    },
};
function getSimpleInputMapping(type, inputs = ["a"], inferType) {
    return {
        blocks: [type],
        inputs: {
            values: inputs.reduce((acc, input) => {
                acc[input] = { name: input };
                return acc;
            }, {}),
        },
        outputs: {
            values: {
                value: { name: "value" },
            },
        },
        extraProcessor(gltfBlock, _declaration, _mapping, _parser, serializedObjects) {
            if (inferType) {
                // configure it to work the way glTF specifies
                serializedObjects[0].config ||= {};
                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 (inferType) {
                // make sure types are the same
                return ValidateTypes(gltfBlock);
            }
            return { valid: true };
        },
    };
}
function ValidateTypes(gltfBlock) {
    if (gltfBlock.values) {
        const types = Object.keys(gltfBlock.values)
            .map((key) => gltfBlock.values[key].type)
            .filter((type) => type !== undefined);
        const allSameType = types.every((type) => type === types[0]);
        if (!allSameType) {
            return { valid: false, error: "All inputs must be of the same type" };
        }
    }
    return { valid: true };
}
/**
 *
 * These are the nodes from the specs:

### Math Nodes
1. **Constants**
   - E (`math/E`) FlowGraphBlockNames.E
   - Pi (`math/Pi`) FlowGraphBlockNames.PI
   - Infinity (`math/Inf`) FlowGraphBlockNames.Inf
   - Not a Number (`math/NaN`) FlowGraphBlockNames.NaN
2. **Arithmetic Nodes**
   - Absolute Value (`math/abs`) FlowGraphBlockNames.Abs
   - Sign (`math/sign`) FlowGraphBlockNames.Sign
   - Truncate (`math/trunc`) FlowGraphBlockNames.Trunc
   - Floor (`math/floor`) FlowGraphBlockNames.Floor
   - Ceil (`math/ceil`) FlowGraphBlockNames.Ceil
   - Round (`math/round`)  FlowGraphBlockNames.Round
   - Fraction (`math/fract`) FlowGraphBlockNames.Fract
   - Negation (`math/neg`) FlowGraphBlockNames.Negation
   - Addition (`math/add`) FlowGraphBlockNames.Add
   - Subtraction (`math/sub`) FlowGraphBlockNames.Subtract
   - Multiplication (`math/mul`) FlowGraphBlockNames.Multiply
   - Division (`math/div`) FlowGraphBlockNames.Divide
   - Remainder (`math/rem`) FlowGraphBlockNames.Modulo
   - Minimum (`math/min`) FlowGraphBlockNames.Min
   - Maximum (`math/max`) FlowGraphBlockNames.Max
   - Clamp (`math/clamp`) FlowGraphBlockNames.Clamp
   - Saturate (`math/saturate`) FlowGraphBlockNames.Saturate
   - Interpolate (`math/mix`) FlowGraphBlockNames.MathInterpolation
3. **Comparison Nodes**
   - Equality (`math/eq`) FlowGraphBlockNames.Equality
   - Less Than (`math/lt`) FlowGraphBlockNames.LessThan
   - Less Than Or Equal To (`math/le`) FlowGraphBlockNames.LessThanOrEqual
   - Greater Than (`math/gt`) FlowGraphBlockNames.GreaterThan
   - Greater Than Or Equal To (`math/ge`) FlowGraphBlockNames.GreaterThanOrEqual
4. **Special Nodes**
   - Is Not a Number (`math/isNaN`) FlowGraphBlockNames.IsNaN
   - Is Infinity (`math/isInf`) FlowGraphBlockNames.IsInfinity
   - Select (`math/select`) FlowGraphBlockNames.Conditional
   - Switch (`math/switch`) FlowGraphBlockNames.DataSwitch
   - Random (`math/random`) FlowGraphBlockNames.Random
5. **Angle and Trigonometry Nodes**
   - Degrees-To-Radians (`math/rad`) FlowGraphBlockNames.DegToRad
   - Radians-To-Degrees (`math/deg`) FlowGraphBlockNames.RadToDeg
   - Sine (`math/sin`)  FlowGraphBlockNames.Sin
   - Cosine (`math/cos`) FlowGraphBlockNames.Cos
   - Tangent (`math/tan`) FlowGraphBlockNames.Tan
   - Arcsine (`math/asin`) FlowGraphBlockNames.Asin
   - Arccosine (`math/acos`) FlowGraphBlockNames.Acos
   - Arctangent (`math/atan`) FlowGraphBlockNames.Atan
   - Arctangent 2 (`math/atan2`) FlowGraphBlockNames.Atan2
6. **Hyperbolic Nodes**
   - Hyperbolic Sine (`math/sinh`) FlowGraphBlockNames.Sinh
   - Hyperbolic Cosine (`math/cosh`) FlowGraphBlockNames.Cosh
   - Hyperbolic Tangent (`math/tanh`) FlowGraphBlockNames.Tanh
   - Inverse Hyperbolic Sine (`math/asinh`) FlowGraphBlockNames.Asinh
   - Inverse Hyperbolic Cosine (`math/acosh`) FlowGraphBlockNames.Acosh
   - Inverse Hyperbolic Tangent (`math/atanh`) FlowGraphBlockNames.Atanh
7. **Exponential Nodes**
   - Exponent (`math/exp`) FlowGraphBlockNames.Exponential
   - Natural Logarithm (`math/log`) FlowGraphBlockNames.Log
   - Base-2 Logarithm (`math/log2`) FlowGraphBlockNames.Log2
   - Base-10 Logarithm (`math/log10`) FlowGraphBlockNames.Log10
   - Square Root (`math/sqrt`) FlowGraphBlockNames.SquareRoot
   - Cube Root (`math/cbrt`) FlowGraphBlockNames.CubeRoot
   - Power (`math/pow`) FlowGraphBlockNames.Power
8. **Vector Nodes**
   - Length (`math/length`) FlowGraphBlockNames.Length
   - Normalize (`math/normalize`) FlowGraphBlockNames.Normalize
   - Dot Product (`math/dot`) FlowGraphBlockNames.Dot
   - Cross Product (`math/cross`) FlowGraphBlockNames.Cross
   - Rotate 2D (`math/rotate2D`) FlowGraphBlockNames.Rotate2D
   - Rotate 3D (`math/rotate3D`) FlowGraphBlockNames.Rotate3D
   - Transform (`math/transform`) FlowGraphBlockNames.TransformVector
9. **Matrix Nodes**
   - Transpose (`math/transpose`) FlowGraphBlockNames.Transpose
   - Determinant (`math/determinant`) FlowGraphBlockNames.Determinant
   - Inverse (`math/inverse`) FlowGraphBlockNames.InvertMatrix
   - Multiplication (`math/matMul`) FlowGraphBlockNames.MatrixMultiplication
   - Compose (`math/matCompose`) FlowGraphBlockNames.MatrixCompose
   - Decompose (`math/matDecompose`) FlowGraphBlockNames.MatrixDecompose
10. **Quaternion Nodes**
    - Conjugate (`math/quatConjugate`) FlowGraphBlockNames.Conjugate
    - Multiplication (`math/quatMul`) FlowGraphBlockNames.Multiply
    - Angle Between Quaternions (`math/quatAngleBetween`) FlowGraphBlockNames.AngleBetween
    - Quaternion From Axis Angle (`math/quatFromAxisAngle`) FlowGraphBlockNames.QuaternionFromAxisAngle
    - Quaternion To Axis Angle (`math/quatToAxisAngle`) FlowGraphBlockNames.QuaternionToAxisAngle
    - Quaternion From Two Directional Vectors (`math/quatFromDirections`) FlowGraphBlockNames.QuaternionFromDirections
11. **Swizzle Nodes**
    - Combine (`math/combine2`, `math/combine3`, `math/combine4`, `math/combine2x2`, `math/combine3x3`, `math/combine4x4`)
        FlowGraphBlockNames.CombineVector2, FlowGraphBlockNames.CombineVector3, FlowGraphBlockNames.CombineVector4
        FlowGraphBlockNames.CombineMatrix2D, FlowGraphBlockNames.CombineMatrix3D, FlowGraphBlockNames.CombineMatrix
    - Extract (`math/extract2`, `math/extract3`, `math/extract4`, `math/extract2x2`, `math/extract3x3`, `math/extract4x4`)
        FlowGraphBlockNames.ExtractVector2, FlowGraphBlockNames.ExtractVector3, FlowGraphBlockNames.ExtractVector4
        FlowGraphBlockNames.ExtractMatrix2D, FlowGraphBlockNames.ExtractMatrix3D, FlowGraphBlockNames.ExtractMatrix
12. **Integer Arithmetic Nodes**
    - Absolute Value (`math/abs`) FlowGraphBlockNames.Abs
    - Sign (`math/sign`) FlowGraphBlockNames.Sign
    - Negation (`math/neg`) FlowGraphBlockNames.Negation
    - Addition (`math/add`) FlowGraphBlockNames.Add
    - Subtraction (`math/sub`) FlowGraphBlockNames.Subtract
    - Multiplication (`math/mul`) FlowGraphBlockNames.Multiply
    - Division (`math/div`) FlowGraphBlockNames.Divide
    - Remainder (`math/rem`) FlowGraphBlockNames.Modulo
    - Minimum (`math/min`) FlowGraphBlockNames.Min
    - Maximum (`math/max`) FlowGraphBlockNames.Max
    - Clamp (`math/clamp`) FlowGraphBlockNames.Clamp
13. **Integer Comparison Nodes**
    - Equality (`math/eq`) FlowGraphBlockNames.Equality
    - Less Than (`math/lt`) FlowGraphBlockNames.LessThan
    - Less Than Or Equal To (`math/le`) FlowGraphBlockNames.LessThanOrEqual
    - Greater Than (`math/gt`) FlowGraphBlockNames.GreaterThan
    - Greater Than Or Equal To (`math/ge`) FlowGraphBlockNames.GreaterThanOrEqual
14. **Integer Bitwise Nodes**
    - Bitwise NOT (`math/not`) FlowGraphBlockNames.BitwiseNot
    - Bitwise AND (`math/and`) FlowGraphBlockNames.BitwiseAnd
    - Bitwise OR (`math/or`) FlowGraphBlockNames.BitwiseOr
    - Bitwise XOR (`math/xor`) FlowGraphBlockNames.BitwiseXor
    - Right Shift (`math/asr`) FlowGraphBlockNames.BitwiseRightShift
    - Left Shift (`math/lsl`) FlowGraphBlockNames.BitwiseLeftShift
    - Count Leading Zeros (`math/clz`) FlowGraphBlockNames.LeadingZeros
    - Count Trailing Zeros (`math/ctz`) FlowGraphBlockNames.TrailingZeros
    - Count One Bits (`math/popcnt`) FlowGraphBlockNames.OneBitsCounter
15. **Boolean Arithmetic Nodes**
    - Equality (`math/eq`) FlowGraphBlockNames.Equality
    - Boolean NOT (`math/not`) FlowGraphBlockNames.BitwiseNot
    - Boolean AND (`math/and`) FlowGraphBlockNames.BitwiseAnd
    - Boolean OR (`math/or`) FlowGraphBlockNames.BitwiseOr
    - Boolean XOR (`math/xor`) FlowGraphBlockNames.BitwiseXor

### Type Conversion Nodes
1. **Boolean Conversion Nodes**
   - Boolean to Integer (`type/boolToInt`) FlowGraphBlockNames.BooleanToInt
   - Boolean to Float (`type/boolToFloat`) FlowGraphBlockNames.BooleanToFloat
2. **Integer Conversion Nodes**
   - Integer to Boolean (`type/intToBool`) FlowGraphBlockNames.IntToBoolean
   - Integer to Float (`type/intToFloat`) FlowGraphBlockNames.IntToFloat
3. **Float Conversion Nodes**
   - Float to Boolean (`type/floatToBool`) FlowGraphBlockNames.FloatToBoolean
   - Float to Integer (`type/floatToInt`) FlowGraphBlockNames.FloatToInt

### Control Flow Nodes
1. **Sync Nodes**
   - Sequence (`flow/sequence`) FlowGraphBlockNames.Sequence
   - Branch (`flow/branch`) FlowGraphBlockNames.Branch
   - Switch (`flow/switch`) FlowGraphBlockNames.Switch
   - While Loop (`flow/while`) FlowGraphBlockNames.WhileLoop
   - For Loop (`flow/for`) FlowGraphBlockNames.ForLoop
   - Do N (`flow/doN`) FlowGraphBlockNames.DoN
   - Multi Gate (`flow/multiGate`) FlowGraphBlockNames.MultiGate
   - Wait All (`flow/waitAll`) FlowGraphBlockNames.WaitAll
   - Throttle (`flow/throttle`) FlowGraphBlockNames.Throttle
2. **Delay Nodes**
   - Set Delay (`flow/setDelay`) FlowGraphBlockNames.SetDelay
   - Cancel Delay (`flow/cancelDelay`) FlowGraphBlockNames.CancelDelay

### State Manipulation Nodes
1. **Custom Variable Access**
   - Variable Get (`variable/get`) FlowGraphBlockNames.GetVariable
   - Variable Set (`variable/set`) FlowGraphBlockNames.SetVariable
   - Variable Interpolate (`variable/interpolate`)
2. **Object Model Access** // TODO fully test this!!!
   - JSON Pointer Template Parsing (`pointer/get`) [FlowGraphBlockNames.GetProperty, FlowGraphBlockNames.JsonPointerParser]
   - Effective JSON Pointer Generation (`pointer/set`) [FlowGraphBlockNames.SetProperty, FlowGraphBlockNames.JsonPointerParser]
   - Pointer Get (`pointer/get`) [FlowGraphBlockNames.GetProperty, FlowGraphBlockNames.JsonPointerParser]
   - Pointer Set (`pointer/set`) [FlowGraphBlockNames.SetProperty, FlowGraphBlockNames.JsonPointerParser]
   - Pointer Interpolate (`pointer/interpolate`) [FlowGraphBlockNames.ValueInterpolation, FlowGraphBlockNames.JsonPointerParser, FlowGraphBlockNames.PlayAnimation, FlowGraphBlockNames.Easing]

### Animation Control Nodes
1. **Animation Play** (`animation/start`) FlowGraphBlockNames.PlayAnimation
2. **Animation Stop** (`animation/stop`) FlowGraphBlockNames.StopAnimation
3. **Animation Stop At** (`animation/stopAt`) FlowGraphBlockNames.StopAnimation

### Event Nodes
1. **Lifecycle Event Nodes**
   - On Start (`event/onStart`) FlowGraphBlockNames.SceneReadyEvent
   - On Tick (`event/onTick`) FlowGraphBlockNames.SceneTickEvent
2. **Custom Event Nodes**
   - Receive (`event/receive`) FlowGraphBlockNames.ReceiveCustomEvent
   - Send (`event/send`) FlowGraphBlockNames.SendCustomEvent

 */

export { FlowGraphMatrix2D as F, RichTypeAny as R, FlowGraphMatrix3D as a, FlowGraphInteger as b, getMappingForDeclaration as c, getMappingForFullOperationName as d, addNewInteractivityFlowGraphMapping as e, RichTypeNumber as f, getRichTypeByFlowGraphType as g, RichTypeBoolean as h, getRichTypeByAnimationType as i, RichTypeVector3 as j, RichTypeFlowGraphInteger as k, RichTypeQuaternion as l, RichTypeMatrix as m, RichTypeVector2 as n, getRichTypeFromValue as o, RichTypeVector4 as p, RichTypeMatrix2D as q, RichTypeMatrix3D as r, RichTypeString as s };
//# sourceMappingURL=declarationMapper-CyyfQT3q.esm.js.map
