You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
131 lines
2.5 KiB
131 lines
2.5 KiB
6 months ago
|
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 );
|