nodeMaterialBlockConnectionPoint.ts 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. import { NodeMaterialBlockConnectionPointTypes } from './nodeMaterialBlockConnectionPointTypes';
  2. import { NodeMaterialBlockTargets } from './nodeMaterialBlockTargets';
  3. import { Nullable } from '../../types';
  4. import { Effect } from '../effect';
  5. import { NodeMaterialWellKnownValues } from './nodeMaterialWellKnownValues';
  6. import { Scene } from '../../scene';
  7. import { Matrix } from '../../Maths/math';
  8. declare type NodeMaterialBlock = import("./nodeMaterialBlock").NodeMaterialBlock;
  9. /**
  10. * Defines a connection point for a block
  11. */
  12. export class NodeMaterialConnectionPoint {
  13. /** @hidden */
  14. public _ownerBlock: NodeMaterialBlock;
  15. /** @hidden */
  16. public _connectedPoint: Nullable<NodeMaterialConnectionPoint>;
  17. private _associatedVariableName: string;
  18. private _endpoints = new Array<NodeMaterialConnectionPoint>();
  19. private _storedValue: any;
  20. private _valueCallback: () => any;
  21. private _isVarying = false;
  22. /** @hidden */
  23. public _wellKnownValue: Nullable<NodeMaterialWellKnownValues> = null;
  24. /**
  25. * Gets or sets the connection point type (default is float)
  26. */
  27. public type: NodeMaterialBlockConnectionPointTypes = NodeMaterialBlockConnectionPointTypes.Float;
  28. /**
  29. * Gets or sets the connection point name
  30. */
  31. public name: string;
  32. /**
  33. * Gets or sets the swizzle to apply to this connection point when reading or writing
  34. */
  35. public swizzle: string;
  36. /**
  37. * Gets or sets a boolean indicating that this connection point can be omitted
  38. */
  39. public isOptional: boolean;
  40. /**
  41. * Gets or sets a string indicating that this uniform must be defined under a #ifdef
  42. */
  43. public define: string;
  44. /** Gets or sets the target of that connection point */
  45. public target: NodeMaterialBlockTargets = NodeMaterialBlockTargets.VertexAndFragment;
  46. /**
  47. * Gets or sets the value of that point.
  48. * Please note that this value will be ignored if valueCallback is defined
  49. */
  50. public get value(): any {
  51. return this._storedValue;
  52. }
  53. public set value(value: any) {
  54. this._storedValue = value;
  55. this.isUniform = true;
  56. }
  57. /**
  58. * Gets or sets a callback used to get the value of that point.
  59. * Please note that setting this value will force the connection point to ignore the value property
  60. */
  61. public get valueCallback(): () => any {
  62. return this._valueCallback;
  63. }
  64. public set valueCallback(value: () => any) {
  65. this._valueCallback = value;
  66. this.isUniform = true;
  67. }
  68. /**
  69. * Gets or sets the associated variable name in the shader
  70. */
  71. public get associatedVariableName(): string {
  72. if (!this._associatedVariableName && this._connectedPoint) {
  73. return this._connectedPoint.associatedVariableName;
  74. }
  75. return this._associatedVariableName;
  76. }
  77. public set associatedVariableName(value: string) {
  78. this._associatedVariableName = value;
  79. }
  80. /**
  81. * Gets or sets a boolean indicating that this connection point is coming from an uniform.
  82. * In this case the connection point name must be the name of the uniform to use.
  83. * Can only be set on inputs
  84. */
  85. public isUniform: boolean;
  86. /**
  87. * Gets or sets a boolean indicating that this connection point is coming from an attribute.
  88. * In this case the connection point name must be the name of the attribute to use
  89. * Can only be set on inputs
  90. */
  91. public isAttribute: boolean;
  92. /**
  93. * Gets or sets a boolean indicating that this connection point is generating a varying variable.
  94. * Can only be set on exit points
  95. */
  96. public get isVarying(): boolean {
  97. return this._isVarying;
  98. }
  99. public set isVarying(value: boolean) {
  100. this._isVarying = value;
  101. }
  102. /** Get the other side of the connection (if any) */
  103. public get connectedPoint(): Nullable<NodeMaterialConnectionPoint> {
  104. return this._connectedPoint;
  105. }
  106. /** Get the block that owns this connection point */
  107. public get ownerBlock(): NodeMaterialBlock {
  108. return this._ownerBlock;
  109. }
  110. /** Get the block connected on the other side of this connection (if any) */
  111. public get sourceBlock(): Nullable<NodeMaterialBlock> {
  112. if (!this._connectedPoint) {
  113. return null;
  114. }
  115. return this._connectedPoint.ownerBlock;
  116. }
  117. /** Get the block connected on the endpoints of this connection (if any) */
  118. public get connectedBlocks(): Array<NodeMaterialBlock> {
  119. if (this._endpoints.length === 0) {
  120. return [];
  121. }
  122. return this._endpoints.map((e) => e.ownerBlock);
  123. }
  124. /**
  125. * Creates a new connection point
  126. * @param name defines the connection point name
  127. * @param ownerBlock defines the block hosting this connection point
  128. */
  129. public constructor(name: string, ownerBlock: NodeMaterialBlock) {
  130. this._ownerBlock = ownerBlock;
  131. this.name = name;
  132. }
  133. /**
  134. * Gets the current class name e.g. "NodeMaterialConnectionPoint"
  135. * @returns the class name
  136. */
  137. public getClassName(): string {
  138. return "NodeMaterialConnectionPoint";
  139. }
  140. /**
  141. * Set the source of this connection point to a vertex attribute
  142. * @param attributeName defines the attribute name (position, uv, normal, etc...). If not specified it will take the connection point name
  143. * @returns the current connection point
  144. */
  145. public setAsAttribute(attributeName?: string): NodeMaterialConnectionPoint {
  146. if (attributeName) {
  147. this.name = attributeName;
  148. }
  149. this.isAttribute = true;
  150. return this;
  151. }
  152. /**
  153. * Set the source of this connection point to a well known value
  154. * @param value define the well known value to use (world, view, etc...)
  155. * @returns the current connection point
  156. */
  157. public setAsWellKnownValue(value: NodeMaterialWellKnownValues): NodeMaterialConnectionPoint {
  158. this.isUniform = true;
  159. this._wellKnownValue = value;
  160. return this;
  161. }
  162. private _getTypeLength(type: NodeMaterialBlockConnectionPointTypes) {
  163. switch (type) {
  164. case NodeMaterialBlockConnectionPointTypes.Float:
  165. return 1;
  166. case NodeMaterialBlockConnectionPointTypes.Vector2:
  167. return 2;
  168. case NodeMaterialBlockConnectionPointTypes.Vector3:
  169. case NodeMaterialBlockConnectionPointTypes.Color3:
  170. return 3;
  171. case NodeMaterialBlockConnectionPointTypes.Vector4:
  172. case NodeMaterialBlockConnectionPointTypes.Color4:
  173. return 3;
  174. }
  175. return -1;
  176. }
  177. /**
  178. * Connect this point to another connection point
  179. * @param connectionPoint defines the other connection point
  180. * @returns the current connection point
  181. */
  182. public connectTo(connectionPoint: NodeMaterialConnectionPoint): NodeMaterialConnectionPoint {
  183. if ((this.type & connectionPoint.type) === 0) {
  184. let fail = true;
  185. // Check swizzle
  186. if (this.swizzle) {
  187. let swizzleLength = this.swizzle.length;
  188. let connectionLength = this._getTypeLength(connectionPoint.type);
  189. if (swizzleLength === connectionLength) {
  190. fail = false;
  191. }
  192. }
  193. if (fail) {
  194. throw "Cannot connect two different connection types.";
  195. }
  196. }
  197. this._endpoints.push(connectionPoint);
  198. connectionPoint._connectedPoint = this;
  199. return this;
  200. }
  201. /**
  202. * Disconnect this point from one of his endpoint
  203. * @param endpoint defines the other connection point
  204. * @returns the current connection point
  205. */
  206. public disconnectFrom(endpoint: NodeMaterialConnectionPoint): NodeMaterialConnectionPoint {
  207. let index = this._endpoints.indexOf(endpoint);
  208. if (index === -1) {
  209. return this;
  210. }
  211. this._endpoints.splice(index, 1);
  212. endpoint._connectedPoint = null;
  213. return this;
  214. }
  215. /**
  216. * When connection point is an uniform, this function will send its value to the effect
  217. * @param effect defines the effect to transmit value to
  218. * @param world defines the world matrix
  219. * @param worldView defines the worldxview matrix
  220. * @param worldViewProjection defines the worldxviewxprojection matrix
  221. */
  222. public transmitWorld(effect: Effect, world: Matrix, worldView: Matrix, worldViewProjection: Matrix) {
  223. if (!this._wellKnownValue) {
  224. return;
  225. }
  226. let variableName = this.associatedVariableName;
  227. switch (this._wellKnownValue) {
  228. case NodeMaterialWellKnownValues.World:
  229. effect.setMatrix(variableName, world);
  230. break;
  231. case NodeMaterialWellKnownValues.WorldView:
  232. effect.setMatrix(variableName, worldView);
  233. break;
  234. case NodeMaterialWellKnownValues.WorldViewProjection:
  235. effect.setMatrix(variableName, worldViewProjection);
  236. break;
  237. }
  238. }
  239. /**
  240. * When connection point is an uniform, this function will send its value to the effect
  241. * @param effect defines the effect to transmit value to
  242. * @param scene defines the hosting scene
  243. */
  244. public transmit(effect: Effect, scene: Scene) {
  245. if (this._wellKnownValue) {
  246. let variableName = this.associatedVariableName;
  247. switch (this._wellKnownValue) {
  248. case NodeMaterialWellKnownValues.World:
  249. case NodeMaterialWellKnownValues.WorldView:
  250. case NodeMaterialWellKnownValues.WorldViewProjection:
  251. return;
  252. case NodeMaterialWellKnownValues.View:
  253. effect.setMatrix(variableName, scene.getViewMatrix());
  254. break;
  255. case NodeMaterialWellKnownValues.Projection:
  256. effect.setMatrix(variableName, scene.getProjectionMatrix());
  257. break;
  258. case NodeMaterialWellKnownValues.ViewProjection:
  259. effect.setMatrix(variableName, scene.getTransformMatrix());
  260. break;
  261. }
  262. return;
  263. }
  264. let value = this._valueCallback ? this._valueCallback() : this._storedValue;
  265. switch (this.type) {
  266. case NodeMaterialBlockConnectionPointTypes.Float:
  267. effect.setFloat(this.name, value);
  268. break;
  269. case NodeMaterialBlockConnectionPointTypes.Int:
  270. effect.setInt(this.name, value);
  271. break;
  272. case NodeMaterialBlockConnectionPointTypes.Color3OrColor4:
  273. case NodeMaterialBlockConnectionPointTypes.Color3:
  274. effect.setColor3(this.name, value);
  275. break;
  276. case NodeMaterialBlockConnectionPointTypes.Color4:
  277. effect.setDirectColor4(this.name, value);
  278. break;
  279. case NodeMaterialBlockConnectionPointTypes.Vector2:
  280. effect.setVector2(this.name, value);
  281. break;
  282. case NodeMaterialBlockConnectionPointTypes.Vector3:
  283. effect.setVector3(this.name, value);
  284. break;
  285. case NodeMaterialBlockConnectionPointTypes.Vector4OrColor4:
  286. case NodeMaterialBlockConnectionPointTypes.Vector4:
  287. effect.setVector4(this.name, value);
  288. break;
  289. case NodeMaterialBlockConnectionPointTypes.Matrix:
  290. effect.setMatrix(this.name, value);
  291. break;
  292. case NodeMaterialBlockConnectionPointTypes.Texture:
  293. case NodeMaterialBlockConnectionPointTypes.Texture3D:
  294. effect.setTexture(this.name, value);
  295. break;
  296. }
  297. }
  298. }