nodeGeometryBlockConnectionPoint.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. import { Observable } from "../../Misc/observable.js";
  2. import { NodeGeometryBlockConnectionPointTypes } from "./Enums/nodeGeometryConnectionPointTypes.js";
  3. /**
  4. * Enum used to define the compatibility state between two connection points
  5. */
  6. export var NodeGeometryConnectionPointCompatibilityStates;
  7. (function (NodeGeometryConnectionPointCompatibilityStates) {
  8. /** Points are compatibles */
  9. NodeGeometryConnectionPointCompatibilityStates[NodeGeometryConnectionPointCompatibilityStates["Compatible"] = 0] = "Compatible";
  10. /** Points are incompatible because of their types */
  11. NodeGeometryConnectionPointCompatibilityStates[NodeGeometryConnectionPointCompatibilityStates["TypeIncompatible"] = 1] = "TypeIncompatible";
  12. /** Points are incompatible because they are in the same hierarchy **/
  13. NodeGeometryConnectionPointCompatibilityStates[NodeGeometryConnectionPointCompatibilityStates["HierarchyIssue"] = 2] = "HierarchyIssue";
  14. })(NodeGeometryConnectionPointCompatibilityStates || (NodeGeometryConnectionPointCompatibilityStates = {}));
  15. /**
  16. * Defines the direction of a connection point
  17. */
  18. export var NodeGeometryConnectionPointDirection;
  19. (function (NodeGeometryConnectionPointDirection) {
  20. /** Input */
  21. NodeGeometryConnectionPointDirection[NodeGeometryConnectionPointDirection["Input"] = 0] = "Input";
  22. /** Output */
  23. NodeGeometryConnectionPointDirection[NodeGeometryConnectionPointDirection["Output"] = 1] = "Output";
  24. })(NodeGeometryConnectionPointDirection || (NodeGeometryConnectionPointDirection = {}));
  25. /**
  26. * Defines a connection point for a block
  27. */
  28. export class NodeGeometryConnectionPoint {
  29. /** Gets the direction of the point */
  30. get direction() {
  31. return this._direction;
  32. }
  33. /**
  34. * Gets or sets the connection point type (default is float)
  35. */
  36. get type() {
  37. if (this._type === NodeGeometryBlockConnectionPointTypes.AutoDetect) {
  38. if (this._ownerBlock.isInput) {
  39. return this._ownerBlock.type;
  40. }
  41. if (this._connectedPoint) {
  42. return this._connectedPoint.type;
  43. }
  44. if (this._linkedConnectionSource && this._linkedConnectionSource.isConnected) {
  45. return this._linkedConnectionSource.type;
  46. }
  47. }
  48. if (this._type === NodeGeometryBlockConnectionPointTypes.BasedOnInput) {
  49. if (this._typeConnectionSource) {
  50. if (!this._typeConnectionSource.isConnected && this._defaultConnectionPointType) {
  51. return this._defaultConnectionPointType;
  52. }
  53. return this._typeConnectionSource.type;
  54. }
  55. else if (this._defaultConnectionPointType) {
  56. return this._defaultConnectionPointType;
  57. }
  58. }
  59. return this._type;
  60. }
  61. set type(value) {
  62. this._type = value;
  63. }
  64. /**
  65. * Gets a boolean indicating that the current point is connected to another NodeMaterialBlock
  66. */
  67. get isConnected() {
  68. return this.connectedPoint !== null || this.hasEndpoints;
  69. }
  70. /** Get the other side of the connection (if any) */
  71. get connectedPoint() {
  72. return this._connectedPoint;
  73. }
  74. /** Get the block that owns this connection point */
  75. get ownerBlock() {
  76. return this._ownerBlock;
  77. }
  78. /** Get the block connected on the other side of this connection (if any) */
  79. get sourceBlock() {
  80. if (!this._connectedPoint) {
  81. return null;
  82. }
  83. return this._connectedPoint.ownerBlock;
  84. }
  85. /** Get the block connected on the endpoints of this connection (if any) */
  86. get connectedBlocks() {
  87. if (this._endpoints.length === 0) {
  88. return [];
  89. }
  90. return this._endpoints.map((e) => e.ownerBlock);
  91. }
  92. /** Gets the list of connected endpoints */
  93. get endpoints() {
  94. return this._endpoints;
  95. }
  96. /** Gets a boolean indicating if that output point is connected to at least one input */
  97. get hasEndpoints() {
  98. return this._endpoints && this._endpoints.length > 0;
  99. }
  100. /** Get the inner type (ie AutoDetect for instance instead of the inferred one) */
  101. get innerType() {
  102. if (this._linkedConnectionSource && this._linkedConnectionSource.isConnected) {
  103. return this.type;
  104. }
  105. return this._type;
  106. }
  107. /** @internal */
  108. _resetCounters() {
  109. this._callCount = 0;
  110. this._executionCount = 0;
  111. }
  112. /**
  113. * Gets the number of times this point was called
  114. */
  115. get callCount() {
  116. return this._callCount;
  117. }
  118. /**
  119. * Gets the number of times this point was executed
  120. */
  121. get executionCount() {
  122. return this._executionCount;
  123. }
  124. /**
  125. * Gets the value represented by this connection point
  126. * @param state current evaluation state
  127. * @returns the connected value or the value if nothing is connected
  128. */
  129. getConnectedValue(state) {
  130. if (this.isConnected) {
  131. if (this._connectedPoint?._storedFunction) {
  132. this._connectedPoint._callCount++;
  133. this._connectedPoint._executionCount++;
  134. return this._connectedPoint._storedFunction(state);
  135. }
  136. this._connectedPoint._callCount++;
  137. this._connectedPoint._executionCount = 1;
  138. return this._connectedPoint._storedValue;
  139. }
  140. this._callCount++;
  141. this._executionCount = 1;
  142. return this.value;
  143. }
  144. /**
  145. * Creates a new connection point
  146. * @param name defines the connection point name
  147. * @param ownerBlock defines the block hosting this connection point
  148. * @param direction defines the direction of the connection point
  149. */
  150. constructor(name, ownerBlock, direction) {
  151. /** @internal */
  152. this._connectedPoint = null;
  153. /** @internal */
  154. this._storedValue = null;
  155. /** @internal */
  156. this._storedFunction = null;
  157. /** @internal */
  158. this._acceptedConnectionPointType = null;
  159. this._endpoints = new Array();
  160. this._type = NodeGeometryBlockConnectionPointTypes.Geometry;
  161. /** @internal */
  162. this._linkedConnectionSource = null;
  163. /** @internal */
  164. this._typeConnectionSource = null;
  165. /** @internal */
  166. this._defaultConnectionPointType = null;
  167. /**
  168. * Gets or sets the additional types supported by this connection point
  169. */
  170. this.acceptedConnectionPointTypes = [];
  171. /**
  172. * Gets or sets the additional types excluded by this connection point
  173. */
  174. this.excludedConnectionPointTypes = [];
  175. /**
  176. * Observable triggered when this point is connected
  177. */
  178. this.onConnectionObservable = new Observable();
  179. /**
  180. * Observable triggered when this point is disconnected
  181. */
  182. this.onDisconnectionObservable = new Observable();
  183. /**
  184. * Gets or sets a boolean indicating that this connection point is exposed on a frame
  185. */
  186. this.isExposedOnFrame = false;
  187. /**
  188. * Gets or sets number indicating the position that the port is exposed to on a frame
  189. */
  190. this.exposedPortPosition = -1;
  191. /**
  192. * Gets the default value used for this point at creation time
  193. */
  194. this.defaultValue = null;
  195. /**
  196. * Gets or sets the default value used for this point if nothing is connected
  197. */
  198. this.value = null;
  199. /**
  200. * Gets or sets the min value accepted for this point if nothing is connected
  201. */
  202. this.valueMin = null;
  203. /**
  204. * Gets or sets the max value accepted for this point if nothing is connected
  205. */
  206. this.valueMax = null;
  207. /** @internal */
  208. this._callCount = 0;
  209. /** @internal */
  210. this._executionCount = 0;
  211. this._ownerBlock = ownerBlock;
  212. this.name = name;
  213. this._direction = direction;
  214. }
  215. /**
  216. * Gets the current class name e.g. "NodeMaterialConnectionPoint"
  217. * @returns the class name
  218. */
  219. getClassName() {
  220. return "NodeGeometryConnectionPoint";
  221. }
  222. /**
  223. * Gets a boolean indicating if the current point can be connected to another point
  224. * @param connectionPoint defines the other connection point
  225. * @returns a boolean
  226. */
  227. canConnectTo(connectionPoint) {
  228. return this.checkCompatibilityState(connectionPoint) === NodeGeometryConnectionPointCompatibilityStates.Compatible;
  229. }
  230. /**
  231. * Gets a number indicating if the current point can be connected to another point
  232. * @param connectionPoint defines the other connection point
  233. * @returns a number defining the compatibility state
  234. */
  235. checkCompatibilityState(connectionPoint) {
  236. const ownerBlock = this._ownerBlock;
  237. const otherBlock = connectionPoint.ownerBlock;
  238. if (this.type !== connectionPoint.type && connectionPoint.innerType !== NodeGeometryBlockConnectionPointTypes.AutoDetect) {
  239. // Accepted types
  240. if (connectionPoint.acceptedConnectionPointTypes && connectionPoint.acceptedConnectionPointTypes.indexOf(this.type) !== -1) {
  241. return NodeGeometryConnectionPointCompatibilityStates.Compatible;
  242. }
  243. else {
  244. return NodeGeometryConnectionPointCompatibilityStates.TypeIncompatible;
  245. }
  246. }
  247. // Excluded
  248. if (connectionPoint.excludedConnectionPointTypes && connectionPoint.excludedConnectionPointTypes.indexOf(this.type) !== -1) {
  249. return NodeGeometryConnectionPointCompatibilityStates.TypeIncompatible;
  250. }
  251. // Check hierarchy
  252. let targetBlock = otherBlock;
  253. let sourceBlock = ownerBlock;
  254. if (this.direction === NodeGeometryConnectionPointDirection.Input) {
  255. targetBlock = ownerBlock;
  256. sourceBlock = otherBlock;
  257. }
  258. if (targetBlock.isAnAncestorOf(sourceBlock)) {
  259. return NodeGeometryConnectionPointCompatibilityStates.HierarchyIssue;
  260. }
  261. return NodeGeometryConnectionPointCompatibilityStates.Compatible;
  262. }
  263. /**
  264. * Connect this point to another connection point
  265. * @param connectionPoint defines the other connection point
  266. * @param ignoreConstraints defines if the system will ignore connection type constraints (default is false)
  267. * @returns the current connection point
  268. */
  269. connectTo(connectionPoint, ignoreConstraints = false) {
  270. if (!ignoreConstraints && !this.canConnectTo(connectionPoint)) {
  271. // eslint-disable-next-line no-throw-literal
  272. throw "Cannot connect these two connectors.";
  273. }
  274. this._endpoints.push(connectionPoint);
  275. connectionPoint._connectedPoint = this;
  276. this.onConnectionObservable.notifyObservers(connectionPoint);
  277. connectionPoint.onConnectionObservable.notifyObservers(this);
  278. return this;
  279. }
  280. /**
  281. * Disconnect this point from one of his endpoint
  282. * @param endpoint defines the other connection point
  283. * @returns the current connection point
  284. */
  285. disconnectFrom(endpoint) {
  286. const index = this._endpoints.indexOf(endpoint);
  287. if (index === -1) {
  288. return this;
  289. }
  290. this._endpoints.splice(index, 1);
  291. endpoint._connectedPoint = null;
  292. this.onDisconnectionObservable.notifyObservers(endpoint);
  293. endpoint.onDisconnectionObservable.notifyObservers(this);
  294. return this;
  295. }
  296. /**
  297. * Fill the list of excluded connection point types with all types other than those passed in the parameter
  298. * @param mask Types (ORed values of NodeMaterialBlockConnectionPointTypes) that are allowed, and thus will not be pushed to the excluded list
  299. */
  300. addExcludedConnectionPointFromAllowedTypes(mask) {
  301. let bitmask = 1;
  302. while (bitmask < NodeGeometryBlockConnectionPointTypes.All) {
  303. if (!(mask & bitmask)) {
  304. this.excludedConnectionPointTypes.push(bitmask);
  305. }
  306. bitmask = bitmask << 1;
  307. }
  308. }
  309. /**
  310. * Serializes this point in a JSON representation
  311. * @param isInput defines if the connection point is an input (default is true)
  312. * @returns the serialized point object
  313. */
  314. serialize(isInput = true) {
  315. const serializationObject = {};
  316. serializationObject.name = this.name;
  317. serializationObject.displayName = this.displayName;
  318. if (this.value !== undefined && this.value !== null) {
  319. if (this.value.asArray) {
  320. serializationObject.valueType = "BABYLON." + this.value.getClassName();
  321. serializationObject.value = this.value.asArray();
  322. }
  323. else {
  324. serializationObject.valueType = "number";
  325. serializationObject.value = this.value;
  326. }
  327. }
  328. if (isInput && this.connectedPoint) {
  329. serializationObject.inputName = this.name;
  330. serializationObject.targetBlockId = this.connectedPoint.ownerBlock.uniqueId;
  331. serializationObject.targetConnectionName = this.connectedPoint.name;
  332. }
  333. return serializationObject;
  334. }
  335. /**
  336. * Release resources
  337. */
  338. dispose() {
  339. this.onConnectionObservable.clear();
  340. this.onDisconnectionObservable.clear();
  341. }
  342. }
  343. //# sourceMappingURL=nodeGeometryBlockConnectionPoint.js.map