UNPKG

three

Version:

JavaScript 3D library

168 lines (104 loc) 3.51 kB
import TempNode from '../core/TempNode.js'; import { addMethodChaining, nodeArray, nodeObject, nodeObjects, float } from '../tsl/TSLCore.js'; /** * This module represents the call of a {@link FunctionNode}. Developers are usually not confronted * with this module since they use the predefined TSL syntax `wgslFn` and `glslFn` which encapsulate * this logic. * * @augments TempNode */ class FunctionCallNode extends TempNode { static get type() { return 'FunctionCallNode'; } /** * Constructs a new function call node. * * @param {?FunctionNode} functionNode - The function node. * @param {Object<string, Node>} [parameters={}] - The parameters for the function call. */ constructor( functionNode = null, parameters = {} ) { super(); /** * The function node. * * @type {?FunctionNode} * @default null */ this.functionNode = functionNode; /** * The parameters of the function call. * * @type {Object<string, Node>} * @default {} */ this.parameters = parameters; } /** * Sets the parameters of the function call node. * * @param {Object<string, Node>} parameters - The parameters to set. * @return {FunctionCallNode} A reference to this node. */ setParameters( parameters ) { this.parameters = parameters; return this; } /** * Returns the parameters of the function call node. * * @return {Object<string, Node>} The parameters of this node. */ getParameters() { return this.parameters; } getNodeType( builder ) { return this.functionNode.getNodeType( builder ); } generate( builder ) { const params = []; const functionNode = this.functionNode; const inputs = functionNode.getInputs( builder ); const parameters = this.parameters; const generateInput = ( node, inputNode ) => { const type = inputNode.type; const pointer = type === 'pointer'; let output; if ( pointer ) output = '&' + node.build( builder ); else output = node.build( builder, type ); return output; }; if ( Array.isArray( parameters ) ) { if ( parameters.length > inputs.length ) { console.error( 'THREE.TSL: The number of provided parameters exceeds the expected number of inputs in \'Fn()\'.' ); parameters.length = inputs.length; } else if ( parameters.length < inputs.length ) { console.error( 'THREE.TSL: The number of provided parameters is less than the expected number of inputs in \'Fn()\'.' ); while ( parameters.length < inputs.length ) { parameters.push( float( 0 ) ); } } for ( let i = 0; i < parameters.length; i ++ ) { params.push( generateInput( parameters[ i ], inputs[ i ] ) ); } } else { for ( const inputNode of inputs ) { const node = parameters[ inputNode.name ]; if ( node !== undefined ) { params.push( generateInput( node, inputNode ) ); } else { console.error( `THREE.TSL: Input '${ inputNode.name }' not found in \'Fn()\'.` ); params.push( generateInput( float( 0 ), inputNode ) ); } } } const functionName = functionNode.build( builder, 'property' ); return `${ functionName }( ${ params.join( ', ' ) } )`; } } export default FunctionCallNode; export const call = ( func, ...params ) => { params = params.length > 1 || ( params[ 0 ] && params[ 0 ].isNode === true ) ? nodeArray( params ) : nodeObjects( params[ 0 ] ); return nodeObject( new FunctionCallNode( nodeObject( func ), params ) ); }; addMethodChaining( 'call', call );