131 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			131 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
import CodeNode from './CodeNode.js';
 | 
						|
import { addNodeClass } from '../core/Node.js';
 | 
						|
import { nodeObject } from '../shadernode/ShaderNode.js';
 | 
						|
 | 
						|
class FunctionNode extends CodeNode {
 | 
						|
 | 
						|
	constructor( code = '', includes = [], language = '' ) {
 | 
						|
 | 
						|
		super( code, includes, language );
 | 
						|
 | 
						|
		this.keywords = {};
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
	getNodeType( builder ) {
 | 
						|
 | 
						|
		return this.getNodeFunction( builder ).type;
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
	getInputs( builder ) {
 | 
						|
 | 
						|
		return this.getNodeFunction( builder ).inputs;
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
	getNodeFunction( builder ) {
 | 
						|
 | 
						|
		const nodeData = builder.getDataFromNode( this );
 | 
						|
 | 
						|
		let nodeFunction = nodeData.nodeFunction;
 | 
						|
 | 
						|
		if ( nodeFunction === undefined ) {
 | 
						|
 | 
						|
			nodeFunction = builder.parser.parseFunction( this.code );
 | 
						|
 | 
						|
			nodeData.nodeFunction = nodeFunction;
 | 
						|
 | 
						|
		}
 | 
						|
 | 
						|
		return nodeFunction;
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
	generate( builder, output ) {
 | 
						|
 | 
						|
		super.generate( builder );
 | 
						|
 | 
						|
		const nodeFunction = this.getNodeFunction( builder );
 | 
						|
 | 
						|
		const name = nodeFunction.name;
 | 
						|
		const type = nodeFunction.type;
 | 
						|
 | 
						|
		const nodeCode = builder.getCodeFromNode( this, type );
 | 
						|
 | 
						|
		if ( name !== '' ) {
 | 
						|
 | 
						|
			// use a custom property name
 | 
						|
 | 
						|
			nodeCode.name = name;
 | 
						|
 | 
						|
		}
 | 
						|
 | 
						|
		const propertyName = builder.getPropertyName( nodeCode );
 | 
						|
 | 
						|
		let code = this.getNodeFunction( builder ).getCode( propertyName );
 | 
						|
 | 
						|
		const keywords = this.keywords;
 | 
						|
		const keywordsProperties = Object.keys( keywords );
 | 
						|
 | 
						|
		if ( keywordsProperties.length > 0 ) {
 | 
						|
 | 
						|
			for ( const property of keywordsProperties ) {
 | 
						|
 | 
						|
				const propertyRegExp = new RegExp( `\\b${property}\\b`, 'g' );
 | 
						|
				const nodeProperty = keywords[ property ].build( builder, 'property' );
 | 
						|
 | 
						|
				code = code.replace( propertyRegExp, nodeProperty );
 | 
						|
 | 
						|
			}
 | 
						|
 | 
						|
		}
 | 
						|
 | 
						|
		nodeCode.code = code + '\n';
 | 
						|
 | 
						|
		if ( output === 'property' ) {
 | 
						|
 | 
						|
			return propertyName;
 | 
						|
 | 
						|
		} else {
 | 
						|
 | 
						|
			return builder.format( `${ propertyName }()`, type, output );
 | 
						|
 | 
						|
		}
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
export default FunctionNode;
 | 
						|
 | 
						|
const nativeFn = ( code, includes = [], language = '' ) => {
 | 
						|
 | 
						|
	for ( let i = 0; i < includes.length; i ++ ) {
 | 
						|
 | 
						|
		const include = includes[ i ];
 | 
						|
 | 
						|
		// TSL Function: glslFn, wgslFn
 | 
						|
 | 
						|
		if ( typeof include === 'function' ) {
 | 
						|
 | 
						|
			includes[ i ] = include.functionNode;
 | 
						|
 | 
						|
		}
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
	const functionNode = nodeObject( new FunctionNode( code, includes, language ) );
 | 
						|
 | 
						|
	const fn = ( ...params ) => functionNode.call( ...params );
 | 
						|
	fn.functionNode = functionNode;
 | 
						|
 | 
						|
	return fn;
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
export const glslFn = ( code, includes ) => nativeFn( code, includes, 'glsl' );
 | 
						|
export const wgslFn = ( code, includes ) => nativeFn( code, includes, 'wgsl' );
 | 
						|
 | 
						|
addNodeClass( 'FunctionNode', FunctionNode );
 |