123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- import CodeNode from './CodeNode.js';
- import NodeFunctionInput from './NodeFunctionInput.js';
- import FunctionCallNode from './FunctionCallNode.js';
- const declarationRegexp = /^\s*(highp|mediump|lowp)?\s*([a-z_0-9]+)\s*([a-z_0-9]+)?\s*\((.*?)\)/i;
- const propertiesRegexp = /[a-z_0-9]+/ig;
- const pragmaMain = '#pragma main';
- class FunctionNode extends CodeNode {
- constructor( code = '' ) {
- super( code );
- this.inputs = [];
- this.name = '';
- this.needsUpdate = true;
- this.useKeywords = true;
- this.presicion = '';
- this._includeCode = '';
- this._internalCode = '';
- }
- getType( /*builder*/ ) {
- if ( this.needsUpdate === true ) {
- this.parse();
- }
- return this.type;
- }
- getInputs( /*builder*/ ) {
- if ( this.needsUpdate === true ) {
- this.parse();
- }
- return this.inputs;
- }
- parse() {
- const code = this.code;
- const pragmaMainIndex = code.indexOf( pragmaMain );
- const mainCode = pragmaMainIndex !== - 1 ? code.substr( pragmaMainIndex + pragmaMain.length ) : code;
- const declaration = mainCode.match( declarationRegexp );
- if ( declaration !== null && declaration.length === 5 ) {
- // tokenizer
- const paramsCode = declaration[ 4 ];
- const propsMatches = [];
- let nameMatch = null;
- while ( ( nameMatch = propertiesRegexp.exec( paramsCode ) ) !== null ) {
- propsMatches.push( nameMatch );
- }
- // parser
- const inputs = [];
- let i = 0;
- while ( i < propsMatches.length ) {
- const isConst = propsMatches[ i ][ 0 ] === 'const';
- if ( isConst === true ) {
- i ++;
- }
- let qualifier = propsMatches[ i ][ 0 ];
- if ( qualifier === 'in' || qualifier === 'out' || qualifier === 'inout' ) {
- i ++;
- } else {
- qualifier = '';
- }
- const type = propsMatches[ i ++ ][ 0 ];
- const name = propsMatches[ i ++ ][ 0 ];
- inputs.push( new NodeFunctionInput( type, name, qualifier, isConst ) );
- }
- const blockCode = mainCode.substring( declaration[ 0 ].length );
- this.name = declaration[ 3 ] !== undefined ? declaration[ 3 ] : '';
- this.type = declaration[ 2 ];
- this.presicion = declaration[ 1 ] !== undefined ? declaration[ 1 ] : '';
- this.inputs = inputs;
- this._includeCode = pragmaMainIndex !== - 1 ? code.substr( 0, pragmaMainIndex ) : '';
- this._internalCode = `( ${paramsCode} ) ${blockCode}`;
- } else {
- throw new Error( 'FunctionNode: Function is not a GLSL code.' );
- }
- this.code = code;
- this.needsUpdate = false;
- }
- call( parameters = null ) {
- return new FunctionCallNode( this, parameters );
- }
- generate( builder, output ) {
- super.generate( builder );
- const type = this.getType( builder );
- const nodeCode = builder.getCodeFromNode( this, type );
- if ( this.name !== '' ) {
- // use a custom property name
- nodeCode.name = this.name;
- }
- const propertyName = builder.getPropertyName( nodeCode );
- const presicion = this.presicion;
- const includeCode = this._includeCode;
- let code = `${type} ${propertyName} ${this._internalCode}`;
- if ( presicion !== '' ) {
- code = `${presicion} ${code}`;
- }
- if ( includeCode !== '' ) {
- code = `${includeCode} ${code}`;
- }
- nodeCode.code = code;
- if ( output === 'property' ) {
- return propertyName;
- } else {
- return builder.format( `${propertyName}()`, type, output );
- }
- }
- }
- export default FunctionNode;
|