GLSLNodeFunction.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import NodeFunction from '../core/NodeFunction.js';
  2. import NodeFunctionInput from '../core/NodeFunctionInput.js';
  3. const declarationRegexp = /^\s*(highp|mediump|lowp)?\s*([a-z_0-9]+)\s*([a-z_0-9]+)?\s*\(([\s\S]*?)\)/i;
  4. const propertiesRegexp = /[a-z_0-9]+/ig;
  5. const pragmaMain = '#pragma main';
  6. const parse = ( source ) => {
  7. const pragmaMainIndex = source.indexOf( pragmaMain );
  8. const mainCode = pragmaMainIndex !== - 1 ? source.substr( pragmaMainIndex + pragmaMain.length ) : source;
  9. const declaration = mainCode.match( declarationRegexp );
  10. if ( declaration !== null && declaration.length === 5 ) {
  11. // tokenizer
  12. const inputsCode = declaration[ 4 ];
  13. const propsMatches = [];
  14. let nameMatch = null;
  15. while ( ( nameMatch = propertiesRegexp.exec( inputsCode ) ) !== null ) {
  16. propsMatches.push( nameMatch );
  17. }
  18. // parser
  19. const inputs = [];
  20. let i = 0;
  21. while ( i < propsMatches.length ) {
  22. const isConst = propsMatches[ i ][ 0 ] === 'const';
  23. if ( isConst === true ) {
  24. i ++;
  25. }
  26. let qualifier = propsMatches[ i ][ 0 ];
  27. if ( qualifier === 'in' || qualifier === 'out' || qualifier === 'inout' ) {
  28. i ++;
  29. } else {
  30. qualifier = '';
  31. }
  32. const type = propsMatches[ i ++ ][ 0 ];
  33. let count = Number.parseInt( propsMatches[ i ][ 0 ] );
  34. if ( Number.isNaN( count ) === false ) i ++;
  35. else count = null;
  36. const name = propsMatches[ i ++ ][ 0 ];
  37. inputs.push( new NodeFunctionInput( type, name, count, qualifier, isConst ) );
  38. }
  39. //
  40. const blockCode = mainCode.substring( declaration[ 0 ].length );
  41. const name = declaration[ 3 ] !== undefined ? declaration[ 3 ] : '';
  42. const type = declaration[ 2 ];
  43. const presicion = declaration[ 1 ] !== undefined ? declaration[ 1 ] : '';
  44. const headerCode = pragmaMainIndex !== - 1 ? source.substr( 0, pragmaMainIndex ) : '';
  45. return {
  46. type,
  47. inputs,
  48. name,
  49. presicion,
  50. inputsCode,
  51. blockCode,
  52. headerCode
  53. };
  54. } else {
  55. throw new Error( 'FunctionNode: Function is not a GLSL code.' );
  56. }
  57. };
  58. class GLSLNodeFunction extends NodeFunction {
  59. constructor( source ) {
  60. const { type, inputs, name, presicion, inputsCode, blockCode, headerCode } = parse( source );
  61. super( type, inputs, name, presicion );
  62. this.inputsCode = inputsCode;
  63. this.blockCode = blockCode;
  64. this.headerCode = headerCode;
  65. }
  66. getCode( name = this.name ) {
  67. const headerCode = this.headerCode;
  68. const presicion = this.presicion;
  69. let declarationCode = `${ this.type } ${ name } ( ${ this.inputsCode.trim() } )`;
  70. if ( presicion !== '' ) {
  71. declarationCode = `${ presicion } ${ declarationCode }`;
  72. }
  73. return headerCode + declarationCode + this.blockCode;
  74. }
  75. }
  76. export default GLSLNodeFunction;