SplitNode.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. import Node from '../core/Node.js';
  2. import { vectorComponents } from '../core/constants.js';
  3. const _stringVectorComponents = vectorComponents.join( '' );
  4. /**
  5. * This module is part of the TSL core and usually not used in app level code.
  6. * `SplitNode` represents a property access operation which means it is
  7. * used to implement any `.xyzw`, `.rgba` and `stpq` usage on node objects.
  8. * For example:
  9. * ```js
  10. * const redValue = color.r;
  11. * ```
  12. *
  13. * @augments Node
  14. */
  15. class SplitNode extends Node {
  16. static get type() {
  17. return 'SplitNode';
  18. }
  19. /**
  20. * Constructs a new split node.
  21. *
  22. * @param {Node} node - The node that should be accessed.
  23. * @param {String} [components='x'] - The components that should be accessed.
  24. */
  25. constructor( node, components = 'x' ) {
  26. super();
  27. /**
  28. * The node that should be accessed.
  29. *
  30. * @type {Node}
  31. */
  32. this.node = node;
  33. /**
  34. * The components that should be accessed.
  35. *
  36. * @type {string}
  37. */
  38. this.components = components;
  39. /**
  40. * This flag can be used for type testing.
  41. *
  42. * @type {Boolean}
  43. * @readonly
  44. * @default true
  45. */
  46. this.isSplitNode = true;
  47. }
  48. /**
  49. * Returns the vector length which is computed based on the requested components.
  50. *
  51. * @return {Number} The vector length.
  52. */
  53. getVectorLength() {
  54. let vectorLength = this.components.length;
  55. for ( const c of this.components ) {
  56. vectorLength = Math.max( vectorComponents.indexOf( c ) + 1, vectorLength );
  57. }
  58. return vectorLength;
  59. }
  60. /**
  61. * Returns the component type of the node's type.
  62. *
  63. * @param {NodeBuilder} builder - The current node builder.
  64. * @return {String} The component type.
  65. */
  66. getComponentType( builder ) {
  67. return builder.getComponentType( this.node.getNodeType( builder ) );
  68. }
  69. /**
  70. * This method is overwritten since the node type is inferred from requested components.
  71. *
  72. * @param {NodeBuilder} builder - The current node builder.
  73. * @return {String} The node type.
  74. */
  75. getNodeType( builder ) {
  76. return builder.getTypeFromLength( this.components.length, this.getComponentType( builder ) );
  77. }
  78. generate( builder, output ) {
  79. const node = this.node;
  80. const nodeTypeLength = builder.getTypeLength( node.getNodeType( builder ) );
  81. let snippet = null;
  82. if ( nodeTypeLength > 1 ) {
  83. let type = null;
  84. const componentsLength = this.getVectorLength();
  85. if ( componentsLength >= nodeTypeLength ) {
  86. // needed expand the input node
  87. type = builder.getTypeFromLength( this.getVectorLength(), this.getComponentType( builder ) );
  88. }
  89. const nodeSnippet = node.build( builder, type );
  90. if ( this.components.length === nodeTypeLength && this.components === _stringVectorComponents.slice( 0, this.components.length ) ) {
  91. // unnecessary swizzle
  92. snippet = builder.format( nodeSnippet, type, output );
  93. } else {
  94. snippet = builder.format( `${nodeSnippet}.${this.components}`, this.getNodeType( builder ), output );
  95. }
  96. } else {
  97. // ignore .components if .node returns float/integer
  98. snippet = node.build( builder, output );
  99. }
  100. return snippet;
  101. }
  102. serialize( data ) {
  103. super.serialize( data );
  104. data.components = this.components;
  105. }
  106. deserialize( data ) {
  107. super.deserialize( data );
  108. this.components = data.components;
  109. }
  110. }
  111. export default SplitNode;
粤ICP备19079148号