import { BaseGraphNode, getNodeTypeComponents } from '../node.js';
import { defineProps } from '../../serialization/types.js';

/**
 * Vector constructor node
 *
 * @remarks
 * Constructs a vector (vec2, vec3, or vec4) from individual components or smaller vectors.
 * Accepts 1-4 inputs which can be scalars (float) or vectors (vec2, vec3).
 * The output vector size is determined by the total number of components from all inputs.
 *
 * Valid combinations:
 * - vec2: float + float, or vec2
 * - vec3: float + float + float, vec2 + float, float + vec2, or vec3
 * - vec4: float + float + float + float, vec2 + vec2, vec3 + float, etc.
 *
 * @example
 * ```typescript
 * // Create vec3 from three floats
 * const makeVec3 = new MakeVectorNode();
 * makeVec3.connectInput(1, xNode, 1);
 * makeVec3.connectInput(2, yNode, 1);
 * makeVec3.connectInput(3, zNode, 1);
 *
 * // Create vec4 from vec3 and float
 * const makeVec4 = new MakeVectorNode();
 * makeVec4.connectInput(1, rgbNode, 1);
 * makeVec4.connectInput(2, alphaNode, 1);
 * ```
 *
 * @public
 */ class MakeVectorNode extends BaseGraphNode {
    /**
   * Creates a new make vector node
   *
   * @remarks
   * Initializes with 4 optional input slots (a, b, c, d).
   * At least one input must be connected. Unused trailing inputs can be left disconnected.
   */ constructor(){
        super();
        this._inputs = [
            {
                id: 1,
                name: 'a',
                type: [
                    'float',
                    'vec2',
                    'vec3'
                ],
                required: true
            },
            {
                id: 2,
                name: 'b',
                type: [
                    'float',
                    'vec2',
                    'vec3'
                ]
            },
            {
                id: 3,
                name: 'c',
                type: [
                    'float',
                    'vec2',
                    'vec3'
                ]
            },
            {
                id: 4,
                name: 'd',
                type: [
                    'float',
                    'vec2',
                    'vec3'
                ]
            }
        ];
        this._outputs = [
            {
                id: 1,
                name: ''
            }
        ];
    }
    /**
   * Generates a string representation of this node
   *
   * @returns 'MakeVector'
   */ toString() {
        return 'MakeVector';
    }
    /**
   * Gets the serialization descriptor for this node type
   *
   * @returns Serialization class descriptor
   *
   * @remarks
   * No properties need to be serialized beyond the base node data.
   */ static getSerializationCls() {
        return {
            ctor: MakeVectorNode,
            name: 'MakeVectorNode',
            getProps () {
                return [];
            }
        };
    }
    /**
   * Validates the node state and input types
   *
   * @returns Error message if invalid, empty string if valid
   *
   * @remarks
   * Validation checks:
   * - At least one input must be connected
   * - All inputs up to the last connected one must be present
   * - Total component count must be between 2 and 4
   * - All input types must be valid (float, vec2, or vec3)
   */ validate() {
        const err = super.validate();
        if (err) {
            return err;
        }
        let index = this._inputs.length - 1;
        while(index >= 0 && !this._inputs[index].inputNode){
            index--;
        }
        if (index < 0) {
            return 'Missing arguments';
        }
        let n = 0;
        const types = [];
        for(let i = 0; i <= index; i++){
            const name1 = this._inputs[i].name;
            if (!this._inputs[i].inputNode) {
                return `Missing argument \`${name1}\``;
            }
            const type = this._inputs[i].inputNode.getOutputType(this._inputs[i].inputId);
            if (!type) {
                return `Cannot determine type of argument \`${name1}\``;
            }
            if (!this._inputs[i].type.includes(type)) {
                return `Invalid input type ${type}`;
            }
            types.push(type);
            n += type === 'float' ? 1 : type === 'vec2' ? 2 : type === 'vec3' ? 3 : 0;
        }
        if (n < 2 || n > 4) {
            return `Invalid type combination ${types.join(',')}`;
        }
        return '';
    }
    /**
   * Gets the output type based on connected inputs
   *
   * @returns 'vec2', 'vec3', 'vec4', or empty string if invalid
   *
   * @remarks
   * Counts total components from all connected inputs:
   * - float = 1 component
   * - vec2 = 2 components
   * - vec3 = 3 components
   * Returns vecN where N is the total component count (2-4).
   */ getType() {
        let index = this._inputs.length - 1;
        while(index >= 0 && !this._inputs[index].inputNode){
            index--;
        }
        if (index < 0) {
            return '';
        }
        let n = 0;
        for(let i = 0; i <= index; i++){
            if (!this._inputs[i].inputNode) {
                return '';
            }
            const type = this._inputs[i].inputNode.getOutputType(this._inputs[i].inputId);
            if (!type) {
                return '';
            }
            n += type === 'float' ? 1 : type === 'vec2' ? 2 : type === 'vec3' ? 3 : 0;
        }
        if (n < 2 || n > 4) {
            return '';
        }
        return `vec${n}`;
    }
}
/**
 * Vector swizzle node
 *
 * @public
 */ class SwizzleNode extends BaseGraphNode {
    _swizzle;
    /**
   * Creates a new swizzle node
   */ constructor(){
        super();
        this._swizzle = '';
        this._inputs = [
            {
                id: 1,
                name: '',
                type: [
                    'float',
                    'vec2',
                    'vec3',
                    'vec4'
                ],
                required: true
            }
        ];
        this._outputs = [
            {
                id: 1,
                name: ''
            }
        ];
    }
    /** Swizzle */ get swizzle() {
        return this._swizzle;
    }
    set swizzle(val) {
        this._swizzle = val;
    }
    /**
   * Generates a string representation of this node
   *
   * @returns 'Swizzle'
   */ toString() {
        return 'Swizzle';
    }
    /**
   * Gets the serialization descriptor for this node type
   *
   * @returns Serialization class descriptor
   *
   * @remarks
   * No properties need to be serialized beyond the base node data.
   */ static getSerializationCls() {
        return {
            ctor: SwizzleNode,
            name: 'SwizzleNode',
            getProps () {
                return defineProps([
                    {
                        name: 'Swizzle',
                        type: 'string',
                        get (value) {
                            value.str[0] = this.swizzle;
                        },
                        set (value) {
                            this.swizzle = value.str[0];
                        }
                    }
                ]);
            }
        };
    }
    /**
   * Validates the node state and input types
   *
   * @returns Error message if invalid, empty string if valid
   *
   * @remarks
   * Validation checks:
   * - At least one input must be connected
   * - All inputs up to the last connected one must be present
   * - Total component count must be between 2 and 4
   * - All input types must be valid (float, vec2, or vec3)
   */ validate() {
        const err = super.validate();
        if (err) {
            return err;
        }
        const type = this._inputs[0].inputNode.getOutputType(this._inputs[0].inputId);
        if (!type) {
            return `Cannot determine type of argument \`${name}\``;
        }
        if (!this._inputs[0].type.includes(type)) {
            return `Invalid input type ${type}`;
        }
        let n;
        if (type === 'float') {
            n = 1;
        } else if (type === 'vec2') {
            n = 2;
        } else if (type === 'vec3') {
            n = 3;
        } else {
            n = 4;
        }
        if (this._swizzle.length === 0 || this._swizzle.length > 4 || [
            ...this._swizzle
        ].some((val)=>'xyzw'.slice(0, n).indexOf(val) < 0) && [
            ...this._swizzle
        ].some((val)=>'rgba'.slice(0, n).indexOf(val) < 0)) {
            return `Invalid swizzle pattern: ${this._swizzle}`;
        }
        return '';
    }
    /**
   * Gets the output type based on connected inputs
   *
   * @returns 'float', 'vec2', 'vec3', 'vec4', or empty string if invalid
   *
   */ getType() {
        const err = this.validate();
        if (err) {
            return '';
        }
        if (!this._inputs[0].inputNode) {
            return '';
        }
        const type = this._inputs[0].inputNode.getOutputType(this._inputs[0].inputId);
        if (!type) {
            return '';
        }
        if (!this._inputs[0].type.includes(type)) {
            return '';
        }
        let n;
        if (type === 'float') {
            n = 1;
        } else if (type === 'vec2') {
            n = 2;
        } else if (type === 'vec3') {
            n = 3;
        } else {
            n = 4;
        }
        if (this._swizzle.length === 0 || this._swizzle.length > 4 || [
            ...this._swizzle
        ].some((val)=>'xyzw'.slice(0, n).indexOf(val) < 0) && [
            ...this._swizzle
        ].some((val)=>'rgba'.slice(0, n).indexOf(val) < 0)) {
            return '';
        }
        return this._swizzle.length === 1 ? 'float' : `vec${this._swizzle.length}`;
    }
}
/**
 * Vector comparison node
 *
 * @public
 */ class CompComparisonNode extends BaseGraphNode {
    _mode;
    /**
   * Creates a new swizzle node
   */ constructor(){
        super();
        this._mode = 'eq';
        this._inputs = [
            {
                id: 1,
                name: '',
                type: [
                    'vec2',
                    'vec3',
                    'vec4'
                ],
                required: true
            },
            {
                id: 2,
                name: '',
                type: [
                    'vec2',
                    'vec3',
                    'vec4'
                ],
                required: true
            }
        ];
        this._outputs = [
            {
                id: 1,
                name: ''
            }
        ];
    }
    /** Swizzle */ get mode() {
        return this._mode;
    }
    set mode(val) {
        this._mode = val;
    }
    /**
   * Generates a string representation of this node
   *
   * @returns 'Swizzle'
   */ toString() {
        return 'Comparison';
    }
    /**
   * Gets the serialization descriptor for this node type
   *
   * @returns Serialization class descriptor
   *
   * @remarks
   * No properties need to be serialized beyond the base node data.
   */ static getSerializationCls() {
        return {
            ctor: CompComparisonNode,
            name: 'CompComparisonNode',
            getProps () {
                return defineProps([
                    {
                        name: 'mode',
                        type: 'string',
                        options: {
                            enum: {
                                labels: [
                                    'Equal',
                                    'NotEqual',
                                    'LessThan',
                                    'LessThanEqual',
                                    'GreaterThan',
                                    'GreaterThanEqual'
                                ],
                                values: [
                                    'eq',
                                    'ne',
                                    'lt',
                                    'le',
                                    'gt',
                                    'ge'
                                ]
                            }
                        },
                        get (value) {
                            value.str[0] = this.mode;
                        },
                        set (value) {
                            this.mode = value.str[0];
                        }
                    }
                ]);
            }
        };
    }
    /**
   * Validates the node state and input types
   *
   * @returns Error message if invalid, empty string if valid
   */ validate() {
        const err = super.validate();
        if (err) {
            return err;
        }
        const type0 = this._inputs[0].inputNode.getOutputType(this._inputs[0].inputId);
        const type1 = this._inputs[1].inputNode.getOutputType(this._inputs[1].inputId);
        if (type0 !== type1) {
            return 'Input arguments must be the same type';
        }
        return '';
    }
    /**
   * Gets the output type based on connected inputs
   *
   * @returns 'bvec2', 'bvec3', 'bvec4', or empty string if invalid
   *
   */ getType() {
        const err = this.validate();
        if (err) {
            return '';
        }
        const type = this._inputs[0].inputNode.getOutputType(this._inputs[0].inputId);
        return `bvec${getNodeTypeComponents(type)}`;
    }
}
/**
 * Any condition node
 *
 * @public
 */ class AnyConditionNode extends BaseGraphNode {
    /**
   * Creates a new any-condition node
   */ constructor(){
        super();
        this._inputs = [
            {
                id: 1,
                name: '',
                type: [
                    'bool',
                    'bvec2',
                    'bvec3',
                    'bvec4'
                ],
                required: true
            }
        ];
        this._outputs = [
            {
                id: 1,
                name: ''
            }
        ];
    }
    /**
   * Generates a string representation of this node
   *
   * @returns 'Any'
   */ toString() {
        return 'Any';
    }
    /**
   * Gets the serialization descriptor for this node type
   *
   * @returns Serialization class descriptor
   *
   * @remarks
   * No properties need to be serialized beyond the base node data.
   */ static getSerializationCls() {
        return {
            ctor: AnyConditionNode,
            name: 'AnyConditionNode',
            getProps () {
                return [];
            }
        };
    }
    /**
   * Gets the output type based on connected inputs
   *
   * @returns 'bool'
   *
   */ getType() {
        return this.validate() ? '' : 'bool';
    }
}
/**
 * All condition node
 *
 * @public
 */ class AllConditionNode extends BaseGraphNode {
    /**
   * Creates a new all-condition node
   */ constructor(){
        super();
        this._inputs = [
            {
                id: 1,
                name: '',
                type: [
                    'bool',
                    'bvec2',
                    'bvec3',
                    'bvec4'
                ],
                required: true
            }
        ];
        this._outputs = [
            {
                id: 1,
                name: ''
            }
        ];
    }
    /**
   * Generates a string representation of this node
   *
   * @returns 'All'
   */ toString() {
        return 'All';
    }
    /**
   * Gets the serialization descriptor for this node type
   *
   * @returns Serialization class descriptor
   *
   * @remarks
   * No properties need to be serialized beyond the base node data.
   */ static getSerializationCls() {
        return {
            ctor: AllConditionNode,
            name: 'AllConditionNode',
            getProps () {
                return [];
            }
        };
    }
    /**
   * Gets the output type based on connected inputs
   *
   * @returns 'bool'
   *
   */ getType() {
        return this.validate() ? '' : 'bool';
    }
}
/**
 * Selection node
 *
 * @public
 */ class SelectionNode extends BaseGraphNode {
    /**
   * Creates a new selection node
   */ constructor(){
        super();
        this._inputs = [
            {
                id: 1,
                name: 'a',
                type: [
                    'float',
                    'vec2',
                    'vec3',
                    'vec4'
                ],
                required: true
            },
            {
                id: 2,
                name: 'b',
                type: [
                    'float',
                    'vec2',
                    'vec3',
                    'vec4'
                ],
                required: true
            },
            {
                id: 3,
                name: 'condition',
                type: [
                    'bool',
                    'bvec2',
                    'bvec3',
                    'bvec4'
                ],
                required: true
            }
        ];
        this._outputs = [
            {
                id: 1,
                name: ''
            }
        ];
    }
    /**
   * Generates a string representation of this node
   *
   * @returns 'Selection'
   */ toString() {
        return 'Selection';
    }
    /**
   * Gets the serialization descriptor for this node type
   *
   * @returns Serialization class descriptor
   *
   * @remarks
   * No properties need to be serialized beyond the base node data.
   */ static getSerializationCls() {
        return {
            ctor: SelectionNode,
            name: 'SelectionNode',
            getProps () {
                return [];
            }
        };
    }
    /**
   * Validates the node state and input types
   *
   * @returns Error message if invalid, empty string if valid
   */ validate() {
        const err = super.validate();
        if (err) {
            return err;
        }
        const type0 = this._inputs[0].inputNode.getOutputType(this._inputs[0].inputId);
        const type1 = this._inputs[1].inputNode.getOutputType(this._inputs[1].inputId);
        if (type0 !== type1) {
            return 'Input arguments 0-1 must be the same type';
        }
        const type2 = this._inputs[2].inputNode.getOutputType(this._inputs[2].inputId);
        const n = getNodeTypeComponents(type2);
        if (n > 1 && n !== getNodeTypeComponents(type0)) {
            return 'Invalid type of argument 2';
        }
        return '';
    }
    /**
   * Gets the output type based on connected inputs
   *
   * @returns 'bool'
   *
   */ getType() {
        const err = this.validate();
        if (err) {
            return '';
        }
        return this._inputs[0].inputNode.getOutputType(this._inputs[0].inputId);
    }
}
/**
 * Matrix-vector transformation node
 *
 * @remarks
 * Performs matrix-vector or matrix-matrix multiplication using the shader's mul() function.
 * Supports transformations for 2D, 3D, and 4D spaces:
 * - mat2 * vec2 or vec2 * mat2
 * - mat3 * vec3 or vec3 * mat3
 * - mat4 * vec4 or vec4 * mat4
 * - mat2 * mat2, mat3 * mat3, mat4 * mat4
 *
 * Common uses:
 * - Transform positions by model/view/projection matrices
 * - Transform normals by inverse transpose matrices
 * - Chain matrix transformations
 *
 * @example
 * ```typescript
 * // Transform position by view-projection matrix
 * const transform = new TransformNode();
 * transform.connectInput(1, positionNode, 1); // vec4 position
 * transform.connectInput(2, viewProjMatrixNode, 1); // mat4 matrix
 *
 * // Transform normal by normal matrix
 * const normalTransform = new TransformNode();
 * normalTransform.connectInput(1, normalNode, 1); // vec3 normal
 * normalTransform.connectInput(2, normalMatrixNode, 1); // mat3 matrix
 * ```
 *
 * @public
 */ class TransformNode extends BaseGraphNode {
    /**
   * Creates a new transform node
   *
   * @remarks
   * Initializes with two required inputs: the value to transform (a) and the transformation matrix (b).
   */ constructor(){
        super();
        this._inputs = [
            {
                id: 1,
                name: 'a',
                type: [
                    'vec2',
                    'vec3',
                    'vec4',
                    'mat2',
                    'mat3',
                    'mat4'
                ],
                required: true
            },
            {
                id: 2,
                name: 'b',
                type: [
                    'vec2',
                    'vec3',
                    'vec4',
                    'mat2',
                    'mat3',
                    'mat4'
                ]
            }
        ];
        this._outputs = [
            {
                id: 1,
                name: ''
            }
        ];
    }
    /**
   * Generates a string representation of this node
   *
   * @returns 'Transform'
   */ toString() {
        return 'Transform';
    }
    /**
   * Gets the serialization descriptor for this node type
   *
   * @returns Serialization class descriptor
   *
   * @remarks
   * No properties need to be serialized beyond the base node data.
   */ static getSerializationCls() {
        return {
            ctor: TransformNode,
            name: 'TransformNode',
            getProps () {
                return [];
            }
        };
    }
    /**
   * Validates the node state and input type compatibility
   *
   * @returns Error message if invalid, empty string if valid
   *
   * @remarks
   * Validates that the input types are compatible for multiplication:
   * - vec2 with mat2
   * - vec3 with mat3
   * - vec4 with mat4
   * - Compatible matrix-matrix multiplications
   */ validate() {
        const err = super.validate();
        if (err) {
            return err;
        }
        const types = [];
        for(let i = 0; i < 2; i++){
            const name1 = this._inputs[i].name;
            if (!this._inputs[i].inputNode) {
                return `Missing argument \`${name1}\``;
            }
            const type = this._inputs[i].inputNode.getOutputType(this._inputs[i].inputId);
            if (!type) {
                return `Cannot determine type of argument \`${name1}\``;
            }
            if (!this._inputs[i].type.includes(type)) {
                return `Invalid input type ${type}`;
            }
            types.push(type);
        }
        if (types[0] === 'vec2' && types[1] === 'mat2') {
            return '';
        }
        if (types[0] === 'vec3' && types[1] === 'mat3') {
            return '';
        }
        if (types[0] === 'vec4' && types[1] === 'mat4') {
            return '';
        }
        if (types[0] === 'mat2' && (types[1] === 'mat2' || types[1] === 'vec2')) {
            return '';
        }
        if (types[0] === 'mat3' && (types[1] === 'mat3' || types[1] === 'vec3')) {
            return '';
        }
        if (types[0] === 'mat4' && (types[1] === 'mat4' || types[1] === 'vec4')) {
            return '';
        }
        return 'Invalid argument types of transformation';
    }
    /**
   * Gets the output type based on input types
   *
   * @returns The result type of the transformation, or empty string if invalid
   *
   * @remarks
   * Result type rules:
   * - vec * mat = vec (same dimension)
   * - mat * vec = vec (same dimension)
   * - mat * mat = mat (same dimension)
   */ getType() {
        const err = this.validate();
        if (err) {
            return '';
        }
        const types = [];
        for(let i = 0; i < 2; i++){
            if (!this._inputs[i].inputNode) {
                return '';
            }
            const type = this._inputs[i].inputNode.getOutputType(this._inputs[i].inputId);
            if (!type) {
                return '';
            }
            if (!this._inputs[i].type.includes(type)) {
                return '';
            }
            types.push(type);
        }
        if (types[0] === 'vec2' && types[1] === 'mat2') {
            return 'vec2';
        }
        if (types[0] === 'vec3' && types[1] === 'mat3') {
            return 'vec3';
        }
        if (types[0] === 'vec4' && types[1] === 'mat4') {
            return 'vec4';
        }
        if (types[0] === 'mat2' && (types[1] === 'mat2' || types[1] === 'vec2')) {
            return types[1] === 'mat2' ? 'mat2' : 'vec2';
        }
        if (types[0] === 'mat3' && (types[1] === 'mat3' || types[1] === 'vec3')) {
            return types[1] === 'mat3' ? 'mat3' : 'vec3';
        }
        if (types[0] === 'mat4' && (types[1] === 'mat4' || types[1] === 'vec4')) {
            return types[1] === 'mat4' ? 'mat4' : 'vec4';
        }
        return '';
    }
}
/**
 * Rotate about axis node
 *
 * @remarks
 * Rotates a position around a pivot along a normalized axis by a given angle.
 * Angle input is in turns (1.0 = 360 degrees).
 *
 * Outputs:
 * - Output 1: Rotated position (vec3)
 *
 * @example
 * ```typescript
 * const rotate = new RotateAboutAxisNode();
 * rotate.connectInput(1, axisNode, 1); // normalized axis (vec3)
 * rotate.connectInput(2, angleNode, 1); // angle in turns (float)
 * rotate.connectInput(3, pivotNode, 1); // pivot (vec3)
 * rotate.connectInput(4, posNode, 1); // position (vec3)
 * ```
 *
 * @public
 */ class RotateAboutAxisNode extends BaseGraphNode {
    /**
   * Creates a new rotate-about-axis node
   *
   * @remarks
   * Initializes with four inputs and one output.
   */ constructor(){
        super();
        this._inputs = [
            {
                id: 1,
                name: 'NormalizedRotationAxis',
                type: [
                    'vec3'
                ],
                required: true
            },
            {
                id: 2,
                name: 'RotationAngle',
                type: [
                    'float'
                ],
                defaultValue: [
                    0
                ]
            },
            {
                id: 3,
                name: 'PivotPoint',
                type: [
                    'vec3'
                ],
                defaultValue: [
                    0,
                    0,
                    0
                ]
            },
            {
                id: 4,
                name: 'Position',
                type: [
                    'vec3'
                ],
                required: true
            }
        ];
        this._outputs = [
            {
                id: 1,
                name: ''
            }
        ];
    }
    /**
   * Generates a string representation of this node
   *
   * @returns 'RotateAboutAxis'
   */ toString() {
        return 'RotateAboutAxis';
    }
    /**
   * Gets the serialization descriptor for this node type
   *
   * @returns Serialization class descriptor
   */ static getSerializationCls() {
        return {
            ctor: RotateAboutAxisNode,
            name: 'RotateAboutAxisNode',
            getProps () {
                return [];
            }
        };
    }
    /**
   * Validates the node state
   *
   * @returns Empty string (always valid beyond base validation)
   */ validate() {
        return super.validate();
    }
    /**
   * Gets the output type
   *
   * @returns 'vec3'
   */ getType() {
        return 'vec3';
    }
}
/**
 * Abstract base class for generic mathematical function nodes
 *
 * @remarks
 * Provides a flexible framework for shader math functions that:
 * - Accept N arguments of specified types
 * - Perform type validation and inference
 * - Support both uniform input types and mixed types
 *
 * Type handling:
 * - By default, all inputs must be the same type (float, vec2, vec3, or vec4)
 * - `explicitInTypes` allows specific inputs to accept only certain types
 * - `additionalInTypes` allows specific inputs to accept additional mixed types
 * - `originTypes` specifies type casting requirements
 *
 * The output type is either:
 * - Explicitly specified via `outType`
 * - Inferred from the common input type
 *
 * @example
 * ```typescript
 * // Simple function with uniform types (all float or all vec3, etc.)
 * class AddNode extends GenericMathNode {
 *   constructor() {
 *     super('add', 2); // 2 arguments, output type = input type
 *   }
 * }
 *
 * // Function with explicit output type
 * class LengthNode extends GenericMathNode {
 *   constructor() {
 *     super('length', 1, 'float'); // 1 argument, always outputs float
 *   }
 * }
 *
 * // Function with mixed input types
 * class MulNode extends GenericMathNode {
 *   constructor() {
 *     // Allow scalar multiplication: vec * float or float * vec
 *     super('mul', 2, null, null, null, { '1': ['float'], '2': ['float'] });
 *   }
 * }
 * ```
 *
 * @public
 */ class GenericMathNode extends BaseGraphNode {
    /** The shader function name (e.g., 'sin', 'add', 'normalize') */ func;
    /** The explicit output type, if specified (otherwise inferred from inputs) */ outType;
    /** Maps input slot IDs to allowed types for that specific slot */ explicitInTypes;
    /** Maps input slot IDs to additional allowed types beyond the common type */ additionalInTypes;
    /**
   * Creates a new generic math node
   *
   * @param func - The shader function name
   * @param numArgs - Number of input arguments
   * @param outType - Explicit output type (null to infer from inputs)
   * @param inTypes - Default allowed input types (defaults to all vector types)
   * @param explicitInTypes - Per-slot type restrictions
   * @param additionalInTypes - Per-slot additional allowed types
   * @param originTypes - Per-slot type casting requirements
   *
   * @remarks
   * Creates input slots named 'a', 'b', 'c', etc. based on numArgs.
   * All inputs are required by default.
   */ constructor(func, numArgs, outType, inTypes, explicitInTypes, additionalInTypes, originTypes){
        super();
        this.func = func;
        this.outType = outType ?? '';
        this.explicitInTypes = explicitInTypes ?? null;
        this.additionalInTypes = additionalInTypes ?? null;
        inTypes = inTypes ?? [
            'float',
            'vec2',
            'vec3',
            'vec4'
        ];
        this._inputs = Array.from({
            length: numArgs
        }).map((_, index)=>({
                id: index + 1,
                name: 'abcdefghijklmn'[index],
                type: this.explicitInTypes?.[index + 1] ?? [
                    ...new Set([
                        ...inTypes,
                        ...this.additionalInTypes?.[index + 1] ?? []
                    ])
                ],
                required: true,
                originType: originTypes?.[index]
            }));
        this._outputs = [
            {
                id: 1,
                name: ''
            }
        ];
    }
    /**
   * Generates a string representation of this node
   *
   * @returns The function name
   */ toString() {
        return this.func;
    }
    /**
   * Validates the node state and input type compatibility
   *
   * @returns Error message if invalid, empty string if valid
   *
   * @remarks
   * Ensures all inputs:
   * - Have determinable types
   * - Have allowed types for their slot
   * - Share a common type (unless explicitly or additionally typed)
   */ validate() {
        const err = super.validate();
        if (err) {
            return err;
        }
        let type = '';
        for(let i = 0; i < this._inputs.length; i++){
            const name1 = 'abcdefghijklmn'[i];
            const t = this._inputs[i].inputNode.getOutputType(this._inputs[i].inputId);
            if (!t) {
                return `Cannot determine type of argument \`${name1}\``;
            }
            if (!this._inputs[i].type.includes(t)) {
                return `Invalid input type ${t}`;
            }
            if (!this.explicitInTypes || !this.explicitInTypes[this._inputs[i].id]) {
                if (!this.additionalInTypes || !this.additionalInTypes[this._inputs[i].id]?.includes(t)) {
                    if (type && t !== type) {
                        return 'Invalid Arguments types';
                    } else {
                        type = t;
                    }
                }
            }
        }
        return '';
    }
    /**
   * Gets the output type based on input types
   *
   * @returns The output type, or empty string if invalid
   *
   * @remarks
   * Returns the explicit output type if specified, otherwise infers
   * the common type from non-explicit, non-additional inputs.
   */ getType() {
        if (this.outType) {
            return this.outType;
        }
        let type = '';
        for(let i = 0; i < this._inputs.length; i++){
            if (!this._inputs[i].inputNode) {
                return '';
            }
            const t = this._inputs[i].inputNode.getOutputType(this._inputs[i].inputId);
            if (!t) {
                return '';
            }
            if (!this.explicitInTypes || !this.explicitInTypes[this._inputs[i].id]) {
                if (!this.additionalInTypes || !this.additionalInTypes[this._inputs[i].id]?.includes(t)) {
                    if (type && t !== type) {
                        return 'Invalid Arguments types';
                    } else {
                        type = t;
                    }
                }
            }
        }
        return type;
    }
}
/**
 * Converts degrees to radians
 *
 * @remarks
 * Applies the formula: radians = degrees * (π / 180)
 * Supports scalar and vector inputs.
 *
 * @public
 */ class Degrees2RadiansNode extends GenericMathNode {
    constructor(){
        super('degrees2radians', 1);
    }
    static getSerializationCls() {
        return {
            ctor: Degrees2RadiansNode,
            name: 'Degrees2RadiansNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Converts radians to degrees
 *
 * @remarks
 * Applies the formula: degrees = radians * (180 / π)
 * Supports scalar and vector inputs.
 *
 * @public
 */ class Radians2DegreesNode extends GenericMathNode {
    constructor(){
        super('radians2degrees', 1);
    }
    static getSerializationCls() {
        return {
            ctor: Radians2DegreesNode,
            name: 'Radians2DegreesNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Computes the sine function
 *
 * @remarks
 * Returns sin(x) for input x in radians.
 * Supports scalar and vector inputs (component-wise for vectors).
 *
 * @public
 */ class SinNode extends GenericMathNode {
    constructor(){
        super('sin', 1);
    }
    static getSerializationCls() {
        return {
            ctor: SinNode,
            name: 'SinNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Computes the cosine function
 *
 * @remarks
 * Returns cos(x) for input x in radians.
 * Supports scalar and vector inputs (component-wise for vectors).
 *
 * @public
 */ class CosNode extends GenericMathNode {
    constructor(){
        super('cos', 1);
    }
    static getSerializationCls() {
        return {
            ctor: CosNode,
            name: 'CosNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Computes the tangent function
 *
 * @remarks
 * Returns tan(x) for input x in radians.
 * Supports scalar and vector inputs (component-wise for vectors).
 *
 * @public
 */ class TanNode extends GenericMathNode {
    constructor(){
        super('tan', 1);
    }
    static getSerializationCls() {
        return {
            ctor: TanNode,
            name: 'TanNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Computes the arcsine (inverse sine) function
 *
 * @remarks
 * Returns asin(x) in radians for input x in the range [-1, 1].
 * Supports scalar and vector inputs (component-wise for vectors).
 *
 * @public
 */ class ArcSinNode extends GenericMathNode {
    constructor(){
        super('asin', 1);
    }
    static getSerializationCls() {
        return {
            ctor: ArcSinNode,
            name: 'ArcSinNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Computes the arccosine (inverse cosine) function
 *
 * @remarks
 * Returns acos(x) in radians for input x in the range [-1, 1].
 * Supports scalar and vector inputs (component-wise for vectors).
 *
 * @public
 */ class ArcCosNode extends GenericMathNode {
    constructor(){
        super('acos', 1);
    }
    static getSerializationCls() {
        return {
            ctor: ArcCosNode,
            name: 'ArcCosNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Computes the arctangent (inverse tangent) function
 *
 * @remarks
 * Returns atan(x) in radians for input x.
 * Result is in the range [-π/2, π/2].
 * Supports scalar and vector inputs (component-wise for vectors).
 *
 * @public
 */ class ArcTanNode extends GenericMathNode {
    constructor(){
        super('atan', 1);
    }
    static getSerializationCls() {
        return {
            ctor: ArcTanNode,
            name: 'ArcTanNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Computes the two-argument arctangent function
 *
 * @remarks
 * Returns atan2(y, x) in radians, the angle in the range [-π, π]
 * whose tangent is y/x, using the signs of both arguments to determine
 * the quadrant of the result.
 * Supports scalar and vector inputs (component-wise for vectors).
 *
 * @public
 */ class ArcTan2Node extends GenericMathNode {
    constructor(){
        super('atan2', 2);
    }
    static getSerializationCls() {
        return {
            ctor: ArcTan2Node,
            name: 'ArcTan2Node',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Computes the hyperbolic sine function
 *
 * @remarks
 * Returns sinh(x) = (e^x - e^(-x)) / 2
 * Supports scalar and vector inputs (component-wise for vectors).
 *
 * @public
 */ class SinHNode extends GenericMathNode {
    constructor(){
        super('sinh', 1);
    }
    static getSerializationCls() {
        return {
            ctor: SinHNode,
            name: 'SinHNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Computes the hyperbolic cosine function
 *
 * @remarks
 * Returns cosh(x) = (e^x + e^(-x)) / 2
 * Supports scalar and vector inputs (component-wise for vectors).
 *
 * @public
 */ class CosHNode extends GenericMathNode {
    constructor(){
        super('cosh', 1);
    }
    static getSerializationCls() {
        return {
            ctor: CosHNode,
            name: 'CosHNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Computes the hyperbolic tangent function
 *
 * @remarks
 * Returns tanh(x) = sinh(x) / cosh(x)
 * Result is in the range [-1, 1].
 * Supports scalar and vector inputs (component-wise for vectors).
 *
 * @public
 */ class TanHNode extends GenericMathNode {
    constructor(){
        super('tanh', 1);
    }
    static getSerializationCls() {
        return {
            ctor: TanHNode,
            name: 'TanHNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Computes the inverse hyperbolic sine function
 *
 * @remarks
 * Returns asinh(x) = ln(x + sqrt(x^2 + 1))
 * Supports scalar and vector inputs (component-wise for vectors).
 *
 * @public
 */ class ArcsineHNode extends GenericMathNode {
    constructor(){
        super('asinh', 1);
    }
    static getSerializationCls() {
        return {
            ctor: ArcsineHNode,
            name: 'ArcsineHNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Computes the inverse hyperbolic cosine function
 *
 * @remarks
 * Returns acosh(x) = ln(x + sqrt(x^2 - 1)) for x \>= 1
 * Supports scalar and vector inputs (component-wise for vectors).
 *
 * @public
 */ class ArccosineHNode extends GenericMathNode {
    constructor(){
        super('acosh', 1);
    }
    static getSerializationCls() {
        return {
            ctor: ArccosineHNode,
            name: 'ArccosineHNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Computes the inverse hyperbolic tangent function
 *
 * @remarks
 * Returns atanh(x) = 0.5 * ln((1 + x) / (1 - x)) for |x| \< 1
 * Supports scalar and vector inputs (component-wise for vectors).
 *
 * @public
 */ class ArctangentHNode extends GenericMathNode {
    constructor(){
        super('atanh', 1);
    }
    static getSerializationCls() {
        return {
            ctor: ArctangentHNode,
            name: 'ArctangentHNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Computes the natural exponential function
 *
 * @remarks
 * Returns e^x (Euler's number raised to the power x).
 * Supports scalar and vector inputs (component-wise for vectors).
 *
 * @public
 */ class ExpNode extends GenericMathNode {
    constructor(){
        super('exp', 1);
    }
    static getSerializationCls() {
        return {
            ctor: ExpNode,
            name: 'ExpNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Computes the base-2 exponential function
 *
 * @remarks
 * Returns 2^x (2 raised to the power x).
 * Supports scalar and vector inputs (component-wise for vectors).
 *
 * @public
 */ class Exp2Node extends GenericMathNode {
    constructor(){
        super('exp2', 1);
    }
    static getSerializationCls() {
        return {
            ctor: Exp2Node,
            name: 'Exp2Node',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Computes the natural logarithm
 *
 * @remarks
 * Returns ln(x) (logarithm base e) for x \> 0.
 * Supports scalar and vector inputs (component-wise for vectors).
 *
 * @public
 */ class LogNode extends GenericMathNode {
    constructor(){
        super('log', 1);
    }
    static getSerializationCls() {
        return {
            ctor: LogNode,
            name: 'LogNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Computes the base-2 logarithm
 *
 * @remarks
 * Returns log₂(x) (logarithm base 2) for x \> 0.
 * Supports scalar and vector inputs (component-wise for vectors).
 *
 * @public
 */ class Log2Node extends GenericMathNode {
    constructor(){
        super('log2', 1);
    }
    static getSerializationCls() {
        return {
            ctor: Log2Node,
            name: 'Log2Node',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Computes the square root
 *
 * @remarks
 * Returns √x for x \>= 0.
 * Supports scalar and vector inputs (component-wise for vectors).
 *
 * @public
 */ class SqrtNode extends GenericMathNode {
    constructor(){
        super('sqrt', 1);
    }
    static getSerializationCls() {
        return {
            ctor: SqrtNode,
            name: 'SqrtNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Computes the inverse square root
 *
 * @remarks
 * Returns 1/√x for x \> 0.
 * Often more efficient than computing sqrt then dividing.
 * Supports scalar and vector inputs (component-wise for vectors).
 *
 * @public
 */ class InvSqrtNode extends GenericMathNode {
    constructor(){
        super('inverseSqrt', 1);
    }
    static getSerializationCls() {
        return {
            ctor: InvSqrtNode,
            name: 'InvSqrtNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Computes the absolute value
 *
 * @remarks
 * Returns |x| (magnitude without sign).
 * Supports scalar and vector inputs (component-wise for vectors).
 *
 * @public
 */ class AbsNode extends GenericMathNode {
    constructor(){
        super('abs', 1);
    }
    static getSerializationCls() {
        return {
            ctor: AbsNode,
            name: 'AbsNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Extracts the sign of a value
 *
 * @remarks
 * Returns -1 if x \< 0, 0 if x = 0, +1 if x \> 0.
 * Supports scalar and vector inputs (component-wise for vectors).
 *
 * @public
 */ class SignNode extends GenericMathNode {
    constructor(){
        super('sign', 1);
    }
    static getSerializationCls() {
        return {
            ctor: SignNode,
            name: 'SignNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Rounds down to the nearest integer
 *
 * @remarks
 * Returns the largest integer value not greater than x.
 * Supports scalar and vector inputs (component-wise for vectors).
 *
 * @public
 */ class FloorNode extends GenericMathNode {
    constructor(){
        super('floor', 1);
    }
    static getSerializationCls() {
        return {
            ctor: FloorNode,
            name: 'FloorNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Rounds up to the nearest integer
 *
 * @remarks
 * Returns the smallest integer value not less than x.
 * Supports scalar and vector inputs (component-wise for vectors).
 *
 * @public
 */ class CeilNode extends GenericMathNode {
    constructor(){
        super('ceil', 1);
    }
    static getSerializationCls() {
        return {
            ctor: CeilNode,
            name: 'CeilNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Computes the fractional part
 *
 * @remarks
 * Returns x - floor(x), the decimal part of x.
 * Result is always in the range [0, 1).
 * Supports scalar and vector inputs (component-wise for vectors).
 *
 * @public
 */ class FractNode extends GenericMathNode {
    constructor(){
        super('fract', 1);
    }
    static getSerializationCls() {
        return {
            ctor: FractNode,
            name: 'FractNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Computes the partial derivative with respect to screen-space X
 *
 * @remarks
 * Returns the rate of change of the input value across adjacent pixels in the X direction.
 * Only available in fragment shaders.
 * Useful for computing gradients, detecting edges, and adjusting sampling rates.
 * Supports scalar and vector inputs (component-wise for vectors).
 *
 * @public
 */ class DDXNode extends GenericMathNode {
    constructor(){
        super('dpdx', 1);
    }
    static getSerializationCls() {
        return {
            ctor: DDXNode,
            name: 'DDXNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Computes the partial derivative with respect to screen-space Y
 *
 * @remarks
 * Returns the rate of change of the input value across adjacent pixels in the Y direction.
 * Only available in fragment shaders.
 * Useful for computing gradients, detecting edges, and adjusting sampling rates.
 * Supports scalar and vector inputs (component-wise for vectors).
 *
 * @public
 */ class DDYNode extends GenericMathNode {
    constructor(){
        super('dpdy', 1);
    }
    static getSerializationCls() {
        return {
            ctor: DDYNode,
            name: 'DDYNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Computes the sum of absolute derivatives
 *
 * @remarks
 * Returns abs(dpdx(x)) + abs(dpdy(x)), representing the total rate of change
 * across both screen axes. Useful for automatic LOD calculation and edge detection.
 * Only available in fragment shaders.
 * Supports scalar and vector inputs (component-wise for vectors).
 *
 * @public
 */ class FWidthNode extends GenericMathNode {
    constructor(){
        super('fwidth', 1);
    }
    static getSerializationCls() {
        return {
            ctor: FWidthNode,
            name: 'FWidthNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Component-wise addition
 *
 * @remarks
 * Returns a + b for each component.
 * Both inputs must be the same type (float, vec2, vec3, or vec4).
 *
 * @public
 */ class CompAddNode extends GenericMathNode {
    constructor(){
        super('add', 2);
    }
    static getSerializationCls() {
        return {
            ctor: CompAddNode,
            name: 'CompAddNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Component-wise subtraction
 *
 * @remarks
 * Returns a - b for each component.
 * Both inputs must be the same type (float, vec2, vec3, or vec4).
 *
 * @public
 */ class CompSubNode extends GenericMathNode {
    constructor(){
        super('sub', 2);
    }
    static getSerializationCls() {
        return {
            ctor: CompSubNode,
            name: 'CompSubNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Component-wise multiplication with scalar support
 *
 * @remarks
 * Returns a * b for each component.
 * Supports:
 * - vec * vec (component-wise)
 * - vec * float (scalar multiplication)
 * - float * vec (scalar multiplication)
 * - float * float
 *
 * For matrix multiplication, use TransformNode instead.
 *
 * @public
 */ class CompMulNode extends GenericMathNode {
    constructor(){
        super('mul', 2, null, null, null, {
            '1': [
                'float'
            ],
            '2': [
                'float'
            ]
        });
    }
    static getSerializationCls() {
        return {
            ctor: CompMulNode,
            name: 'CompMulNode',
            getProps () {
                return [];
            }
        };
    }
    getType() {
        const type1 = this.inputs[0].inputNode ? this.inputs[0].inputNode.getOutputType(this.inputs[0].inputId) : '';
        const type2 = this.inputs[1].inputNode ? this.inputs[1].inputNode.getOutputType(this.inputs[1].inputId) : '';
        if (!type1 || !type2) {
            return '';
        }
        return type1 === 'float' ? type2 : type1;
    }
}
/**
 * Component-wise division
 *
 * @remarks
 * Returns a / b for each component.
 * Both inputs must be the same type (float, vec2, vec3, or vec4).
 * Division by zero produces undefined results.
 *
 * @public
 */ class CompDivNode extends GenericMathNode {
    constructor(){
        super('div', 2);
    }
    static getSerializationCls() {
        return {
            ctor: CompDivNode,
            name: 'CompDivNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Modulo operation
 *
 * @remarks
 * Returns a - b * floor(a / b), the remainder of a divided by b.
 * Both inputs must be the same type (float, vec2, vec3, or vec4).
 * Component-wise for vectors.
 *
 * @public
 */ class ModNode extends GenericMathNode {
    constructor(){
        super('mod', 2);
    }
    static getSerializationCls() {
        return {
            ctor: ModNode,
            name: 'ModNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Returns the minimum of two values
 *
 * @remarks
 * Returns min(a, b) for each component.
 * Both inputs must be the same type (float, vec2, vec3, or vec4).
 * Component-wise for vectors.
 *
 * @public
 */ class MinNode extends GenericMathNode {
    constructor(){
        super('min', 2);
    }
    static getSerializationCls() {
        return {
            ctor: MinNode,
            name: 'MinNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Returns the maximum of two values
 *
 * @remarks
 * Returns max(a, b) for each component.
 * Both inputs must be the same type (float, vec2, vec3, or vec4).
 * Component-wise for vectors.
 *
 * @public
 */ class MaxNode extends GenericMathNode {
    constructor(){
        super('max', 2);
    }
    static getSerializationCls() {
        return {
            ctor: MaxNode,
            name: 'MaxNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Raises a value to a power
 *
 * @remarks
 * Returns a^b (a raised to the power b).
 * Both inputs must be the same type (float, vec2, vec3, or vec4).
 * Component-wise for vectors.
 *
 * @public
 */ class PowNode extends GenericMathNode {
    constructor(){
        super('pow', 2);
    }
    static getSerializationCls() {
        return {
            ctor: PowNode,
            name: 'PowNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Step function (Heaviside step)
 *
 * @remarks
 * Returns 0 if x \< edge, otherwise 1.
 * Useful for creating hard thresholds.
 * Both inputs must be the same type (float, vec2, vec3, or vec4).
 * Component-wise for vectors.
 *
 * @public
 */ class StepNode extends GenericMathNode {
    constructor(){
        super('step', 2);
    }
    static getSerializationCls() {
        return {
            ctor: StepNode,
            name: 'StepNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * SmoothStep function
 *
 * @public
 */ class SmoothStepNode extends GenericMathNode {
    constructor(){
        super('smoothStep', 3);
    }
    static getSerializationCls() {
        return {
            ctor: SmoothStepNode,
            name: 'SmoothStepNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Fused multiply-add operation
 *
 * @remarks
 * Returns a * b + c in a single operation.
 * More accurate and potentially faster than separate multiply and add.
 * All three inputs must be the same type (float, vec2, vec3, or vec4).
 * Component-wise for vectors.
 *
 * @public
 */ class FmaNode extends GenericMathNode {
    constructor(){
        super('fma', 3);
    }
    static getSerializationCls() {
        return {
            ctor: FmaNode,
            name: 'FmaNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Clamps a value to a specified range
 *
 * @remarks
 * Returns min(max(x, minVal), maxVal).
 * Constrains x to be between minVal and maxVal.
 * All three inputs must be the same type (float, vec2, vec3, or vec4).
 * Component-wise for vectors.
 *
 * @public
 */ class ClampNode extends GenericMathNode {
    constructor(){
        super('clamp', 3);
    }
    static getSerializationCls() {
        return {
            ctor: ClampNode,
            name: 'ClampNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Clamps a value to the range [0, 1]
 *
 * @remarks
 * Returns clamp(x, 0, 1).
 * Commonly used to ensure color values are in valid range.
 * Supports float, vec2, vec3, and vec4 inputs.
 * Component-wise for vectors.
 *
 * @public
 */ class SaturateNode extends GenericMathNode {
    constructor(){
        super('saturate', 1);
    }
    static getSerializationCls() {
        return {
            ctor: SaturateNode,
            name: 'SaturateNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Linear interpolation between two values
 *
 * @remarks
 * Returns a * (1 - t) + b * t, blending between a and b based on t.
 * When t = 0, returns a; when t = 1, returns b.
 * The first two inputs must be the same type (float, vec2, vec3, or vec4).
 * The third input (t) can be a float for uniform interpolation or a vector for component-wise interpolation.
 *
 * @public
 */ class MixNode extends GenericMathNode {
    constructor(){
        super('mix', 3, null, null, null, {
            '3': [
                'float'
            ]
        });
    }
    static getSerializationCls() {
        return {
            ctor: MixNode,
            name: 'MixNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Normalizes a vector to unit length
 *
 * @remarks
 * Returns x / length(x), a vector in the same direction with length 1.
 * Only supports vector inputs (vec2, vec3, vec4).
 * Essential for working with directions, normals, and lighting calculations.
 *
 * @public
 */ class NormalizeNode extends GenericMathNode {
    constructor(){
        super('normalize', 1, null, [
            'vec2',
            'vec3',
            'vec4'
        ]);
    }
    static getSerializationCls() {
        return {
            ctor: NormalizeNode,
            name: 'NormalizeNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Flips a vector to face forward
 *
 * @remarks
 * Returns N if dot(Nref, I) \< 0, otherwise -N.
 * Used to orient a normal to face away from a surface (opposite to incident direction).
 * All three inputs must be the same vector type (vec2 or vec3).
 *
 * @public
 */ class FaceForwardNode extends GenericMathNode {
    constructor(){
        super('faceForward', 3, null, [
            'vec2',
            'vec3'
        ]);
    }
    static getSerializationCls() {
        return {
            ctor: FaceForwardNode,
            name: 'FaceForwardNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Calculates the reflection direction
 *
 * @remarks
 * Returns I - 2 * dot(N, I) * N, the reflection of incident vector I about normal N.
 * Both inputs must be the same vector type (vec2 or vec3).
 * Used for environment mapping and reflections.
 *
 * @public
 */ class ReflectNode extends GenericMathNode {
    constructor(){
        super('reflect', 2, null, [
            'vec2',
            'vec3'
        ]);
    }
    static getSerializationCls() {
        return {
            ctor: ReflectNode,
            name: 'ReflectNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Calculates the refraction direction
 *
 * @remarks
 * Returns the refraction of incident vector I through surface with normal N
 * using the ratio of indices of refraction eta.
 * The first two inputs must be the same vector type (vec2 or vec3).
 * The third input (eta) is always a float scalar.
 * Used for transparent materials and refractive effects.
 *
 * @public
 */ class RefractNode extends GenericMathNode {
    constructor(){
        super('refract', 3, null, [
            'vec2',
            'vec3'
        ], {
            '3': [
                'float'
            ]
        });
    }
    static getSerializationCls() {
        return {
            ctor: RefractNode,
            name: 'RefractNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Calculates the length of a vector
 *
 * @remarks
 * Returns sqrt(x.x + x.y + x.z + ...), the Euclidean length of the vector.
 * Supports vector inputs (vec2, vec3, vec4).
 * Always returns a float scalar.
 *
 * @public
 */ class LengthNode extends GenericMathNode {
    constructor(){
        super('length', 1, 'float');
    }
    static getSerializationCls() {
        return {
            ctor: LengthNode,
            name: 'LengthNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Calculates the distance between two points
 *
 * @remarks
 * Returns length(a - b), the Euclidean distance between points a and b.
 * Both inputs must be the same vector type (vec2, vec3, or vec4).
 * Always returns a float scalar.
 *
 * @public
 */ class DistanceNode extends GenericMathNode {
    constructor(){
        super('distance', 2, 'float');
    }
    static getSerializationCls() {
        return {
            ctor: DistanceNode,
            name: 'DistanceNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Logically and
 *
 * @public
 */ class LogicallyAndNode extends GenericMathNode {
    constructor(){
        super('and', 2, 'bool', [
            'bool'
        ]);
    }
    static getSerializationCls() {
        return {
            ctor: LogicallyAndNode,
            name: 'LogicallyAndNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Logically or
 *
 * @public
 */ class LogicallyOrNode extends GenericMathNode {
    constructor(){
        super('or', 2, 'bool', [
            'bool'
        ]);
    }
    static getSerializationCls() {
        return {
            ctor: LogicallyOrNode,
            name: 'LogicallyOrNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Equal test across two scalar or vectors
 *
 * @public
 */ class EqualNode extends GenericMathNode {
    constructor(){
        super('equal', 2, 'bool', [
            'float',
            'vec2',
            'vec3',
            'vec4'
        ]);
    }
    static getSerializationCls() {
        return {
            ctor: EqualNode,
            name: 'EqualNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Not-Equal test across two scalar or vectors
 *
 * @public
 */ class NotEqualNode extends GenericMathNode {
    constructor(){
        super('notEqual', 2, 'bool', [
            'float',
            'vec2',
            'vec3',
            'vec4'
        ]);
    }
    static getSerializationCls() {
        return {
            ctor: NotEqualNode,
            name: 'NotEqualNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Calculates the dot product of two vectors
 *
 * @remarks
 * Returns a.x * b.x + a.y * b.y + ... (sum of component-wise products).
 * Both inputs must be the same vector type (vec2, vec3, or vec4).
 * Always returns a float scalar.
 *
 * Used for:
 * - Calculating angles between vectors (via cosine)
 * - Projecting one vector onto another
 * - Lighting calculations (Lambert's cosine law)
 *
 * @public
 */ class DotProductNode extends GenericMathNode {
    constructor(){
        super('dot', 2, 'float', [
            'vec2',
            'vec3',
            'vec4'
        ]);
    }
    static getSerializationCls() {
        return {
            ctor: DotProductNode,
            name: 'DotProductNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Calculates the cross product of two 3D vectors
 *
 * @remarks
 * Returns a vector perpendicular to both input vectors.
 * Both inputs must be vec3.
 * Always returns vec3.
 *
 * The magnitude of the result equals the area of the parallelogram
 * formed by the two input vectors.
 *
 * Used for:
 * - Calculating surface normals from tangent vectors
 * - Finding perpendicular directions
 * - Computing oriented areas
 *
 * @public
 */ class CrossProductNode extends GenericMathNode {
    constructor(){
        super('cross', 2, null, [
            'vec3'
        ]);
    }
    static getSerializationCls() {
        return {
            ctor: CrossProductNode,
            name: 'CrossProductNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Calculates a simplex noise by input UV and scale value
 *
 * @remarks
 * Returns a float value
 *
 * @public
 */ class SimplexNoise2DNode extends GenericMathNode {
    constructor(){
        super('Z_simplexNoise2D', 2, 'float', null, {
            '1': [
                'vec2'
            ],
            '2': [
                'float'
            ]
        });
    }
    static getSerializationCls() {
        return {
            ctor: SimplexNoise2DNode,
            name: 'SimplexNoise2DNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Calculates a perlin noise by input UV and scale value
 *
 * @remarks
 * Returns a float value
 *
 * @public
 */ class PerlinNoise2DNode extends GenericMathNode {
    constructor(){
        super('Z_perlinNoise2D', 2, 'float', null, {
            '1': [
                'vec2'
            ],
            '2': [
                'float'
            ]
        });
    }
    static getSerializationCls() {
        return {
            ctor: PerlinNoise2DNode,
            name: 'PerlinNoise2DNode',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Calculates float hash by input scalar value or vector value
 *
 * @public
 */ class Hash1Node extends GenericMathNode {
    constructor(){
        super('Z_hash1', 1, 'float', null, {
            '1': [
                'float',
                'vec2',
                'vec3'
            ]
        });
    }
    static getSerializationCls() {
        return {
            ctor: Hash1Node,
            name: 'Hash1Node',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Calculates vec2 hash by input scalar value or vector value
 *
 * @public
 */ class Hash2Node extends GenericMathNode {
    constructor(){
        super('Z_hash2', 1, 'vec2', null, {
            '1': [
                'float',
                'vec2',
                'vec3'
            ]
        });
    }
    static getSerializationCls() {
        return {
            ctor: Hash2Node,
            name: 'Hash2Node',
            getProps () {
                return [];
            }
        };
    }
}
/**
 * Calculates vec3 hash by input scalar value or vector value
 *
 * @public
 */ class Hash3Node extends GenericMathNode {
    constructor(){
        super('Z_hash3', 1, 'vec3', null, {
            '1': [
                'float',
                'vec2',
                'vec3'
            ]
        });
    }
    static getSerializationCls() {
        return {
            ctor: Hash3Node,
            name: 'Hash3Node',
            getProps () {
                return [];
            }
        };
    }
}

export { AbsNode, AllConditionNode, AnyConditionNode, ArcCosNode, ArcSinNode, ArcTan2Node, ArcTanNode, ArccosineHNode, ArcsineHNode, ArctangentHNode, CeilNode, ClampNode, CompAddNode, CompComparisonNode, CompDivNode, CompMulNode, CompSubNode, CosHNode, CosNode, CrossProductNode, DDXNode, DDYNode, Degrees2RadiansNode, DistanceNode, DotProductNode, EqualNode, Exp2Node, ExpNode, FWidthNode, FaceForwardNode, FloorNode, FmaNode, FractNode, GenericMathNode, Hash1Node, Hash2Node, Hash3Node, InvSqrtNode, LengthNode, Log2Node, LogNode, LogicallyAndNode, LogicallyOrNode, MakeVectorNode, MaxNode, MinNode, MixNode, ModNode, NormalizeNode, NotEqualNode, PerlinNoise2DNode, PowNode, Radians2DegreesNode, ReflectNode, RefractNode, RotateAboutAxisNode, SaturateNode, SelectionNode, SignNode, SimplexNoise2DNode, SinHNode, SinNode, SmoothStepNode, SqrtNode, StepNode, SwizzleNode, TanHNode, TanNode, TransformNode };
//# sourceMappingURL=math.js.map
