NodeSocket.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. import {Circle} from "../Circle";
  2. import {Node} from "./Node";
  3. import {NodeConnector} from "./NodeConnector";
  4. import {Text} from "../Text";
  5. /**
  6. * Represents a node hook point. Is attached to the node element and represented visually.
  7. *
  8. * Can be used as a node input, output or as a bidirectional connection.
  9. *
  10. * @class NodeSocket
  11. * @param {Node} node Node of this hook.
  12. * @param {number} direction Direction of the hook.
  13. * @param {string} type Data type of the node socket.
  14. * @param {string} name Name of the node socket.
  15. */
  16. function NodeSocket(node, direction, type, name)
  17. {
  18. Circle.call(this);
  19. this.draggable = true;
  20. this.radius = 6;
  21. this.layer = 1;
  22. /**
  23. * Name of the socket presented to the user.
  24. *
  25. * @type {string}
  26. */
  27. this.name = name !== undefined ? name : "";
  28. /**
  29. * Type of data available from this socket, only hooks of the same type can be connected.
  30. *
  31. * @type {string}
  32. */
  33. this.type = type !== undefined ? type : "";
  34. /**
  35. * Direction of the node hook.
  36. *
  37. * @type {number}
  38. */
  39. this.direction = direction;
  40. /**
  41. * Node where this input element in attached.
  42. *
  43. * @type {Node}
  44. */
  45. this.node = node;
  46. /**
  47. * Node connector used to connect this hook to another node hook.
  48. *
  49. * @type {NodeConnector}
  50. */
  51. this.connector = null;
  52. /**
  53. * Text object used to present the name of the socket.
  54. *
  55. * @type {Text}
  56. */
  57. this.text = new Text();
  58. this.text.text = this.name;
  59. if(this.direction === NodeSocket.INPUT)
  60. {
  61. this.text.position.x -= 10;
  62. this.text.textAlign = "right";
  63. }
  64. else if(this.direction === NodeSocket.OUTPUT)
  65. {
  66. this.text.position.x += 10;
  67. this.text.textAlign = "left";
  68. }
  69. this.add(this.text);
  70. }
  71. /**
  72. * Input hook can only be connected to an output.
  73. *
  74. * Is used to read data from the output.
  75. *
  76. * @type {number}
  77. */
  78. NodeSocket.INPUT = 1;
  79. /**
  80. * Output hook can only be connected to an input.
  81. *
  82. * Writes data to the output.
  83. *
  84. * @type {number}
  85. */
  86. NodeSocket.OUTPUT = 2;
  87. NodeSocket.prototype = Object.create(Circle.prototype);
  88. /**
  89. * Connect this node socket to another socket.
  90. *
  91. * Sockets have to be compatible otherwise the connection cannot be made and an error will be thrown.
  92. *
  93. * @param {NodeSocket} socket Socket to be connected with this
  94. * @return {NodeConnector} Node connector created.
  95. */
  96. NodeSocket.prototype.connectTo = function(socket)
  97. {
  98. if(!this.isCompatible(socket))
  99. {
  100. throw new Error("Sockets are not compatible they cannot be connected.");
  101. }
  102. var connector = new NodeConnector();
  103. this.attachConnector(connector);
  104. socket.attachConnector(connector);
  105. return connector;
  106. };
  107. /**
  108. * Attach a node connector to this socket. Sets the correct input/output attributes on the socket and the connector.
  109. *
  110. * Automatically adds the connector to the same parent and the node socket if no parent defined for the connector.
  111. *
  112. * @param {NodeConnector} connector Connector to be attached to this socket.
  113. */
  114. NodeSocket.prototype.attachConnector = function(connector)
  115. {
  116. if(this.direction === NodeSocket.INPUT)
  117. {
  118. connector.inputSocket = this;
  119. }
  120. else if(this.direction === NodeSocket.OUTPUT)
  121. {
  122. connector.outputSocket = this;
  123. }
  124. this.connector = connector;
  125. if(connector.parent === null)
  126. {
  127. this.parent.add(connector);
  128. }
  129. };
  130. /**
  131. * Check if this socket can be connected (is compatible) with another socket.
  132. *
  133. * For two sockets to be compatible the data flow should be correct (one input and a output) and they should carry the same data type.
  134. *
  135. * @param {NodeSocket} socket Socket to verify compatibility with.
  136. * @return {boolean} Returns true if the two sockets are compatible.
  137. */
  138. NodeSocket.prototype.isCompatible = function(socket)
  139. {
  140. return this.direction !== socket.direction && this.type === socket.type;
  141. };
  142. NodeSocket.prototype.onPointerDragStart = function(pointer, viewport)
  143. {
  144. if(this.connector === null)
  145. {
  146. this.attachConnector(new NodeConnector());
  147. }
  148. };
  149. NodeSocket.prototype.onPointerDrag = function(pointer, viewport, delta, position)
  150. {
  151. if(this.connector !== null)
  152. {
  153. if(this.direction === NodeSocket.INPUT)
  154. {
  155. this.connector.from.copy(position);
  156. }
  157. else if(this.direction === NodeSocket.OUTPUT)
  158. {
  159. this.connector.to.copy(position);
  160. }
  161. }
  162. };
  163. NodeSocket.prototype.onPointerDragEnd = function(pointer, viewport)
  164. {
  165. if(this.connector !== null)
  166. {
  167. var position = viewport.inverseMatrix.transformPoint(pointer.position);
  168. var objects = this.parent.getWorldPointIntersections(position);
  169. var found = false;
  170. for(var i = 0; i < objects.length; i++)
  171. {
  172. if(objects[i] instanceof NodeSocket)
  173. {
  174. if(this.isCompatible(objects[i]))
  175. {
  176. objects[i].attachConnector(this.connector);
  177. found = true;
  178. break;
  179. }
  180. }
  181. }
  182. if(!found)
  183. {
  184. this.connector.destroy();
  185. }
  186. }
  187. };
  188. export {NodeSocket};