nodeMaterialBlockConnectionPoint.ts 12 KB

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