Home Reference Source

cables_dev/cables/src/core/core_port.js

  1. import { Logger } from "cables-shared-client";
  2. import { EventTarget } from "./eventtarget.js";
  3. import { Anim, ANIM } from "./anim.js";
  4. import { CONSTANTS } from "./constants.js";
  5. import { cleanJson } from "./utils.js";
  6.  
  7.  
  8. /**
  9. * data is coming into and out of ops through input and output ports
  10. * @namespace external:CABLES#Port
  11. * @class
  12. * @hideconstructor
  13. * @param ___op
  14. * @param name
  15. * @param type
  16. * @param uiAttribs
  17. * @example
  18. * const myPort=op.inString("String Port");
  19. */
  20. const Port = function (___op, name, type, uiAttribs)
  21. {
  22. EventTarget.apply(this);
  23.  
  24. this.data = {}; // UNUSED, DEPRECATED, only left in for backwards compatibility with userops
  25. this._log = new Logger("core_port");
  26. /**
  27. * @type {Number}
  28. * @name direction
  29. * @instance
  30. * @memberof Port
  31. * @description direction of port (input(0) or output(1))
  32. */
  33. this.direction = CONSTANTS.PORT.PORT_DIR_IN;
  34. this.id = String(CABLES.simpleId());
  35. this._op = ___op;
  36.  
  37. /**
  38. * @type {Array<Link>}
  39. * @name links
  40. * @instance
  41. * @memberof Port
  42. * @description links of port
  43. */
  44. this.links = [];
  45. this.value = 0.0;
  46. this.name = name;
  47. this.type = type || CONSTANTS.OP.OP_PORT_TYPE_VALUE;
  48. this.uiAttribs = uiAttribs || {};
  49. this.anim = null;
  50. this._oldAnimVal = -5711;
  51. this.defaultValue = null;
  52.  
  53.  
  54. this._uiActiveState = true;
  55. this.ignoreValueSerialize = false;
  56. this.onLinkChanged = null;
  57. this.crashed = false;
  58.  
  59. this._valueBeforeLink = null;
  60. this._lastAnimFrame = -1;
  61. this._animated = false;
  62.  
  63. this.onValueChanged = null;
  64. this.onTriggered = null;
  65. this.onUiActiveStateChange = null;
  66. this.changeAlways = false;
  67. this.forceRefChange = false;
  68.  
  69. this._useVariableName = null;
  70.  
  71. this.activityCounter = 0;
  72. this.apf = 0;
  73. this.activityCounterStartFrame = 0;
  74.  
  75. this._tempLastUiValue = null;
  76.  
  77. Object.defineProperty(this, "title", {
  78. get()
  79. {
  80. return this.uiAttribs.title || this.name;
  81. } });
  82.  
  83. Object.defineProperty(this, "parent", {
  84. get()
  85. {
  86. this._log.stack("use port.op, not .parent");
  87. return this._op;
  88. } });
  89.  
  90. Object.defineProperty(this, "op", {
  91. get()
  92. {
  93. return this._op;
  94. } });
  95.  
  96. Object.defineProperty(this, "val", {
  97. get()
  98. {
  99. // this._log.warn("val getter deprecated!", this);
  100. // this._log.stack("val getter deprecated");
  101. return this.get();
  102. },
  103. set(v)
  104. {
  105. // this._log.warn("val setter deprecated!", this);
  106. // this._log.stack("val setter deprecated");
  107. this.setValue(v);
  108. }
  109. });
  110. };
  111.  
  112.  
  113. /**
  114. * copy over a uiattrib from an external connected port to another port
  115. * @function copyLinkedUiAttrib
  116. * @memberof Port
  117. * @param {string} which attrib name
  118. * @param {Port} port source port
  119. * @instance
  120. * @example
  121.  
  122. inArray.onLinkChanged=()=>
  123. {
  124. if(inArray) inArray.copyLinkedUiAttrib("stride", outArray);
  125. };
  126.  
  127. */
  128. Port.prototype.copyLinkedUiAttrib = function (which, port)
  129. {
  130. if (!CABLES.UI) return;
  131. if (!this.isLinked()) return;
  132.  
  133. const attr = {};
  134. attr[which] = this.links[0].getOtherPort(this).getUiAttrib(which);
  135. port.setUiAttribs(attr);
  136. };
  137.  
  138.  
  139. // TODO make extend class for ports, like for ops only for ui
  140. Port.prototype.getValueForDisplay = function ()
  141. {
  142. let str = this.value;
  143.  
  144. if (typeof this.value === "string" || this.value instanceof String)
  145. {
  146. if (str.length > 1000)
  147. {
  148. str = str.substring(0, 999);
  149. str += "...";
  150. }
  151. if (this.uiAttribs && (this.uiAttribs.display == "boolnum"))
  152. {
  153. str += " - ";
  154.  
  155. if (!this.value) str += "false";
  156. else str += "true";
  157. }
  158.  
  159. str = str.replace(/[\u00A0-\u9999<>\&]/g, function (i)
  160. {
  161. return "&#" + i.charCodeAt(0) + ";";
  162. });
  163.  
  164.  
  165. if (str.length > 100) str = str.substring(0, 100);
  166. }
  167. else
  168. {
  169. str = this.value;
  170. }
  171. return str;
  172. };
  173.  
  174. /**
  175. * change listener for input value ports, overwrite to react to changes
  176. * @function onChange
  177. * @memberof Port
  178. * @instance
  179. * @example
  180. * const myPort=op.inString("MyPort");
  181. * myPort.onChange=function()
  182. * {
  183. * console.log("was changed to: ",myPort.get());
  184. * }
  185. *
  186. */
  187. Port.prototype.onAnimToggle = function () {};
  188. Port.prototype._onAnimToggle = function ()
  189. {
  190. this.onAnimToggle();
  191. };
  192.  
  193.  
  194. /**
  195. * @function remove
  196. * @memberof Port
  197. * @instance
  198. * @description remove port
  199. */
  200. Port.prototype.remove = function ()
  201. {
  202. // this.setUiAttribs({ "hidePort": true });
  203. this.removeLinks();
  204. this._op.removePort(this);
  205. };
  206.  
  207. /**
  208. * set ui attributes
  209. * @function setUiAttribs
  210. * @memberof Port
  211. * @instance
  212. * @param {Object} newAttribs
  213. * <pre>
  214. * title - overwrite title of port (by default this is portname)
  215. * greyout - port paramater will appear greyed out, can not be
  216. * hidePort - port will be hidden from op
  217. * hideParam - port params will be hidden from parameter panel
  218. * showIndex - only for dropdowns - show value index (e.g. `0 - normal` )
  219. * editorSyntax - set syntax highlighting theme for editor port
  220. * ignoreObjTypeErrors - do not auto check object types
  221. * </pre>
  222. * @example
  223. * myPort.setUiAttribs({greyout:true});
  224. */
  225. Port.prototype.setUiAttribs = function (newAttribs)
  226. {
  227. let changed = false;
  228. if (!this.uiAttribs) this.uiAttribs = {};
  229.  
  230. for (const p in newAttribs)
  231. {
  232. if (newAttribs[p] === undefined)
  233. {
  234. // delete newAttribs[p];
  235. delete this.uiAttribs[p];
  236. continue;
  237. }
  238. if (this.uiAttribs[p] != newAttribs[p]) changed = true;
  239. this.uiAttribs[p] = newAttribs[p];
  240.  
  241. if (p == "group" && this.indexPort) this.indexPort.setUiAttribs({ "group": newAttribs[p] });
  242. }
  243.  
  244. if (newAttribs.hasOwnProperty("expose")) this._op.patch.emitEvent("subpatchExpose", this._op.uiAttribs.subPatch);
  245.  
  246. if (changed) this.emitEvent("onUiAttrChange", newAttribs, this);
  247. };
  248.  
  249. /**
  250. * get ui attributes
  251. * @function getUiAttribs
  252. * @memberof Port
  253. * @example
  254. * myPort.getUiAttribs();
  255. */
  256. Port.prototype.getUiAttribs = function ()
  257. {
  258. return this.uiAttribs;
  259. };
  260.  
  261. /**
  262. * get ui attribute
  263. * @function getUiAttrib
  264. * @memberof Port
  265. * @instance
  266. * @param {String} attribName
  267. * <pre>
  268. * attribName - return value of the ui-attribute, or null on unknown attribute
  269. * </pre>
  270. * @example
  271. * myPort.setUiAttribs("values");
  272. */
  273. Port.prototype.getUiAttrib = function (attribName)
  274. {
  275. if (!this.uiAttribs || !this.uiAttribs.hasOwnProperty(attribName))
  276. {
  277. return null;
  278. }
  279. return this.uiAttribs[attribName];
  280. };
  281.  
  282. /**
  283. * @function get
  284. * @memberof Port
  285. * @instance
  286. * @description get value of port
  287. */
  288. Port.prototype.get = function ()
  289. {
  290. if (this._animated && this._lastAnimFrame != this._op.patch.getFrameNum())
  291. {
  292. this._lastAnimFrame = this._op.patch.getFrameNum();
  293.  
  294. let animval = this.anim.getValue(this._op.patch.timer.getTime());
  295.  
  296. if (this.value != animval)
  297. {
  298. this.value = animval;
  299. this._oldAnimVal = this.value;
  300. this.forceChange();
  301. }
  302. }
  303.  
  304. return this.value;
  305. };
  306.  
  307. Port.prototype.setRef = function (v)
  308. {
  309. this.forceRefChange = true;
  310. this.set(v);
  311. };
  312.  
  313. /**
  314. * @function setValue
  315. * @memberof Port
  316. * @instance
  317. * @description set value of port / will send value to all linked ports (only for output ports)
  318. */
  319. Port.prototype.set = Port.prototype.setValue = function (v)
  320. {
  321. if (v === undefined) v = null;
  322.  
  323.  
  324. if (CABLES.UI && CABLES.UI.showDevInfos)
  325. if (this.direction == CONSTANTS.PORT.PORT_DIR_OUT && this.type == CONSTANTS.OP.OP_PORT_TYPE_OBJECT && v && !this.forceRefChange)
  326. this._log.warn("object port uses .set", this.name, this.op.objName);
  327.  
  328.  
  329. if (this._op.enabled && !this.crashed)
  330. {
  331. if (v !== this.value || this.changeAlways || this.type == CONSTANTS.OP.OP_PORT_TYPE_TEXTURE || this.type == CONSTANTS.OP.OP_PORT_TYPE_ARRAY)
  332. {
  333. if (this._animated)
  334. {
  335. this.anim.setValue(this._op.patch.timer.getTime(), v);
  336. }
  337. else
  338. {
  339. try
  340. {
  341. this.value = v;
  342. this.forceChange();
  343. }
  344. catch (ex)
  345. {
  346. this.crashed = true;
  347.  
  348. this.setValue = function (_v) {};
  349. this.onTriggered = function () {};
  350.  
  351. this._log.error("exception in ", this._op);
  352. this._log.error(ex);
  353.  
  354. this._op.patch.emitEvent("exception", ex, this._op);
  355. }
  356.  
  357. if (this._op && this._op.patch && this._op.patch.isEditorMode() && this.type == CONSTANTS.OP.OP_PORT_TYPE_TEXTURE) gui.texturePreview().updateTexturePort(this);
  358. }
  359.  
  360. if (this.direction == CONSTANTS.PORT.PORT_DIR_OUT) for (let i = 0; i < this.links.length; ++i) this.links[i].setValue();
  361. }
  362. }
  363. };
  364.  
  365. Port.prototype.updateAnim = function ()
  366. {
  367. if (this._animated)
  368. {
  369. this.value = this.get();
  370.  
  371. if (this._oldAnimVal != this.value || this.changeAlways)
  372. {
  373. this._oldAnimVal = this.value;
  374. this.forceChange();
  375. }
  376. this._oldAnimVal = this.value;
  377. }
  378. };
  379.  
  380. Port.prototype.forceChange = function ()
  381. {
  382. if (this.onValueChanged || this.onChange)
  383. {
  384. // very temporary: deprecated warning!!!!!!!!!
  385. // if(params.length>0) this._log.warn('TOM: port has onchange params!',this._op.objName,this.name);
  386. }
  387. this._activity();
  388. this.emitEvent("change", this.value, this);
  389.  
  390. // try
  391. // {
  392. if (this.onChange) this.onChange(this, this.value);
  393. else if (this.onValueChanged) this.onValueChanged(this, this.value); // deprecated
  394. // }
  395. // catch (e)
  396. // {
  397. // console.log(e);
  398. // }
  399. };
  400.  
  401. /**
  402. * @function getTypeString
  403. * @memberof Port
  404. * @instance
  405. * @description get port type as string, e.g. "Function","Value"...
  406. * @return {String} type
  407. */
  408. Port.prototype.getTypeString = function ()
  409. {
  410. if (this.type == CONSTANTS.OP.OP_PORT_TYPE_VALUE) return "Number";
  411. if (this.type == CONSTANTS.OP.OP_PORT_TYPE_FUNCTION) return "Trigger";
  412. if (this.type == CONSTANTS.OP.OP_PORT_TYPE_OBJECT) return "Object";
  413. if (this.type == CONSTANTS.OP.OP_PORT_TYPE_DYNAMIC) return "Dynamic";
  414. if (this.type == CONSTANTS.OP.OP_PORT_TYPE_ARRAY) return "Array";
  415. if (this.type == CONSTANTS.OP.OP_PORT_TYPE_STRING) return "String";
  416. return "Unknown";
  417. };
  418.  
  419. Port.prototype.deSerializeSettings = function (objPort)
  420. {
  421. if (!objPort) return;
  422. if (objPort.animated) this.setAnimated(objPort.animated);
  423. if (objPort.useVariable) this.setVariableName(objPort.useVariable);
  424. if (objPort.title) this.setUiAttribs({ "title": objPort.title });
  425. if (objPort.expose) this.setUiAttribs({ "expose": true });
  426. if (objPort.order) this.setUiAttribs({ "order": objPort.order });
  427.  
  428. if (objPort.multiPortManual) this.setUiAttribs({ "multiPortManual": objPort.multiPortManual });
  429. if (objPort.multiPortNum) this.setUiAttribs({ "multiPortNum": objPort.multiPortNum });
  430.  
  431. if (objPort.anim)
  432. {
  433. if (!this.anim) this.anim = new Anim({ "name": "port " + this.name });
  434. this._op._hasAnimPort = true;
  435. this.anim.addEventListener("onChange", () =>
  436. {
  437. this._op.patch.emitEvent("portAnimUpdated", this._op, this, this.anim);
  438. });
  439. if (objPort.anim.loop) this.anim.loop = objPort.anim.loop;
  440. for (const ani in objPort.anim.keys)
  441. {
  442. this.anim.keys.push(new ANIM.Key(objPort.anim.keys[ani]));
  443. }
  444. this.anim.sortKeys();
  445. }
  446. };
  447.  
  448.  
  449. Port.prototype.setInitialValue = function (v)
  450. {
  451. if (this.op.preservedPortLinks[this.name])
  452. {
  453. for (let i = 0; i < this.op.preservedPortLinks[this.name].length; i++)
  454. {
  455. const lobj = this.op.preservedPortLinks[this.name][i];
  456. this.op.patch._addLink(
  457. lobj.objIn,
  458. lobj.objOut,
  459. lobj.portIn,
  460. lobj.portOut);
  461. }
  462. }
  463.  
  464.  
  465. if (this.op.preservedPortValues && this.op.preservedPortValues.hasOwnProperty(this.name) && this.op.preservedPortValues[this.name] !== undefined)
  466. {
  467. this.set(this.op.preservedPortValues[this.name]);
  468. }
  469. else
  470. if (v !== undefined) this.set(v);
  471. if (v !== undefined) this.defaultValue = v;
  472. };
  473.  
  474.  
  475.  
  476.  
  477. Port.prototype.getSerialized = function ()
  478. {
  479. let obj = { "name": this.getName() };
  480.  
  481.  
  482. if (!this.ignoreValueSerialize && this.links.length === 0)
  483. {
  484. if (this.type == CONSTANTS.OP.OP_PORT_TYPE_OBJECT && this.value && this.value.tex) {}
  485. else obj.value = this.value;
  486. }
  487. if (this._useVariableName) obj.useVariable = this._useVariableName;
  488. if (this._animated) obj.animated = true;
  489. if (this.anim) obj.anim = this.anim.getSerialized();
  490. if (this.uiAttribs.multiPortNum) obj.multiPortNum = this.uiAttribs.multiPortNum;
  491. if (this.uiAttribs.multiPortManual) obj.multiPortManual = this.uiAttribs.multiPortManual;
  492.  
  493. if (this.uiAttribs.display == "file") obj.display = this.uiAttribs.display;
  494. if (this.uiAttribs.expose)
  495. {
  496. obj.expose = true;
  497. if (this.uiAttribs.hasOwnProperty("order")) obj.order = this.uiAttribs.order;
  498. }
  499. if (this.uiAttribs.title) obj.title = this.uiAttribs.title;
  500. if ((this.preserveLinks || this.direction == CONSTANTS.PORT.PORT_DIR_OUT) && this.links.length > 0)
  501. {
  502. obj.links = [];
  503. for (const i in this.links)
  504. {
  505. if (!this.links[i].ignoreInSerialize && (this.links[i].portIn && this.links[i].portOut)) obj.links.push(this.links[i].getSerialized());
  506. }
  507. }
  508.  
  509. if (this.direction == CONSTANTS.PORT.PORT_DIR_IN && this.links.length > 0)
  510. {
  511. for (const i in this.links)
  512. {
  513. if (!this.links[i].portIn || !this.links[i].portOut) continue;
  514.  
  515. const otherp = this.links[i].getOtherPort(this);
  516. // check if functions exist, are defined in core_extend_ops code in ui
  517. if (otherp.op.isInBlueprint2 && this.op.isInBlueprint2)
  518. {
  519. if (otherp.op.isInBlueprint2() && !this.op.isInBlueprint2())
  520. {
  521. obj.links = obj.links || [];
  522. obj.links.push(this.links[i].getSerialized());
  523. }
  524. }
  525. }
  526. }
  527.  
  528. if (obj.links && obj.links.length == 0) delete obj.links;
  529. if (this.type === CONSTANTS.OP.OP_PORT_TYPE_FUNCTION) delete obj.value;
  530. if (this.type === CONSTANTS.OP.OP_PORT_TYPE_FUNCTION && this.links.length == 0) obj = null;
  531. if (obj && Object.keys(obj).length == 1 && obj.name)obj = null; // obj is null if there is no real information other than name
  532.  
  533. // console.log(obj);
  534. cleanJson(obj);
  535.  
  536. return obj;
  537. };
  538.  
  539. Port.prototype.shouldLink = function ()
  540. {
  541. return true;
  542. };
  543.  
  544. /**
  545. * @function removeLinks
  546. * @memberof Port
  547. * @instance
  548. * @description remove all links from port
  549. */
  550. Port.prototype.removeLinks = function ()
  551. {
  552. let count = 0;
  553. while (this.links.length > 0)
  554. {
  555. count++;
  556. if (count > 5000)
  557. {
  558. this._log.warn("could not delete links... / infinite loop");
  559. this.links.length = 0;
  560. break;
  561. }
  562. this.links[0].remove();
  563. }
  564. };
  565.  
  566. /**
  567. * @function removeLink
  568. * @memberof Port
  569. * @instance
  570. * @description remove all link from port
  571. * @param {CABLES.Link} link
  572. */
  573. Port.prototype.removeLink = function (link)
  574. {
  575. for (const i in this.links)
  576. if (this.links[i] == link)
  577. this.links.splice(i, 1);
  578.  
  579. if (this.direction == CONSTANTS.PORT.PORT_DIR_IN)
  580. {
  581. if (this.type == CONSTANTS.OP.OP_PORT_TYPE_VALUE) this.setValue(this._valueBeforeLink || 0);
  582. else this.setValue(this._valueBeforeLink || null);
  583. }
  584.  
  585. if (CABLES.UI && this._op.checkLinkTimeWarnings) this._op.checkLinkTimeWarnings();
  586.  
  587. try
  588. {
  589. if (this.onLinkChanged) this.onLinkChanged();
  590. this.emitEvent("onLinkChanged");
  591. this.emitEvent("onLinkRemoved");
  592. this._op.emitEvent("onLinkChanged");
  593. }
  594. catch (e)
  595. {
  596. this._log.error(e);
  597. }
  598. };
  599.  
  600. /**
  601. * @function getName
  602. * @memberof Port
  603. * @instance
  604. * @description return port name
  605. */
  606. Port.prototype.getName = function ()
  607. {
  608. return this.name;
  609. };
  610.  
  611. /**
  612. * @function getTitle
  613. * @memberof Port
  614. * @instance
  615. * @description return port name or title
  616. */
  617. Port.prototype.getTitle = function ()
  618. {
  619. if (this.uiAttribs.title) return this.uiAttribs.title;
  620. return this.name;
  621. };
  622.  
  623. Port.prototype.addLink = function (l)
  624. {
  625. this._valueBeforeLink = this.value;
  626. this.links.push(l);
  627. if (CABLES.UI && this._op.checkLinkTimeWarnings) this._op.checkLinkTimeWarnings();
  628.  
  629. try
  630. {
  631. if (this.onLinkChanged) this.onLinkChanged();
  632. this.emitEvent("onLinkChanged");
  633. this._op.emitEvent("onLinkChanged");
  634. }
  635. catch (e)
  636. {
  637. this._log.error(e);
  638. }
  639. };
  640.  
  641. /**
  642. * @function getLinkTo
  643. * @memberof Port
  644. * @instance
  645. * @param {Port} p2 otherPort
  646. * @description return link, which is linked to otherPort
  647. */
  648. Port.prototype.getLinkTo = function (p2)
  649. {
  650. for (const i in this.links) if (this.links[i].portIn == p2 || this.links[i].portOut == p2) return this.links[i];
  651. };
  652.  
  653. /**
  654. * @function removeLinkTo
  655. * @memberof Port
  656. * @instance
  657. * @param {Port} p2 otherPort
  658. * @description removes link, which is linked to otherPort
  659. */
  660. Port.prototype.removeLinkTo = function (p2)
  661. {
  662. for (const i in this.links)
  663. {
  664. if (this.links[i].portIn == p2 || this.links[i].portOut == p2)
  665. {
  666. this.links[i].remove();
  667. if (CABLES.UI && this._op.checkLinkTimeWarnings) this._op.checkLinkTimeWarnings();
  668.  
  669. if (this.onLinkChanged) this.onLinkChanged();
  670. this.emitEvent("onLinkChanged");
  671. this.emitEvent("onLinkRemoved");
  672. return;
  673. }
  674. }
  675. };
  676.  
  677. /**
  678. * @function isLinkedTo
  679. * @memberof Port
  680. * @instance
  681. * @param {Port} p2 otherPort
  682. * @description returns true if port is linked to otherPort
  683. */
  684. Port.prototype.isLinkedTo = function (p2)
  685. {
  686. for (const i in this.links) if (this.links[i].portIn == p2 || this.links[i].portOut == p2) return true;
  687.  
  688. return false;
  689. };
  690.  
  691. Port.prototype._activity = function ()
  692. {
  693. this.activityCounter++;
  694. };
  695.  
  696. /**
  697. * @function trigger
  698. * @memberof Port
  699. * @instance
  700. * @description trigger the linked port (usually invoked on an output function port)
  701. */
  702. Port.prototype.trigger = function ()
  703. {
  704. const linksLength = this.links.length;
  705.  
  706. this._activity();
  707. if (linksLength === 0) return;
  708. if (!this._op.enabled) return;
  709.  
  710. let portTriggered = null;
  711. try
  712. {
  713. for (let i = 0; i < linksLength; ++i)
  714. {
  715. if (this.links[i].portIn)
  716. {
  717. portTriggered = this.links[i].portIn;
  718.  
  719. portTriggered.op.patch.pushTriggerStack(portTriggered);
  720. portTriggered._onTriggered();
  721.  
  722. portTriggered.op.patch.popTriggerStack();
  723. }
  724. if (this.links[i]) this.links[i].activity();
  725. }
  726. }
  727. catch (ex)
  728. {
  729. portTriggered.op.enabled = false;
  730.  
  731. if (this._op.patch.isEditorMode())
  732. {
  733. // this._op.patch.emitEvent("exception", ex, portTriggered.op);
  734. // this._op.patch.emitEvent("opcrash", portTriggered);
  735. // console.log("crash", portTriggered.op.objName);
  736.  
  737. if (portTriggered.op.onError) portTriggered.op.onError(ex);
  738. }
  739. this._log.error("exception in port: ", portTriggered.name, portTriggered.op.name, portTriggered.op);
  740. this._log.error(ex);
  741. }
  742. };
  743.  
  744. Port.prototype.call = function ()
  745. {
  746. this._log.warn("call deprecated - use trigger() ");
  747. this.trigger();
  748. };
  749.  
  750. Port.prototype.execute = function ()
  751. {
  752. this._log.warn("### execute port: " + this.getName(), this.goals.length);
  753. };
  754.  
  755. Port.prototype.setVariableName = function (n)
  756. {
  757. this._useVariableName = n;
  758.  
  759.  
  760. this._op.patch.on("variableRename", (oldname, newname) =>
  761. {
  762. if (oldname != this._useVariableName) return;
  763. this._useVariableName = newname;
  764. });
  765. };
  766.  
  767. Port.prototype.getVariableName = function ()
  768. {
  769. return this._useVariableName;
  770. };
  771.  
  772. Port.prototype.setVariable = function (v)
  773. {
  774. this.setAnimated(false);
  775. const attr = { "useVariable": false };
  776.  
  777. if (this._variableIn && this._varChangeListenerId)
  778. {
  779. this._variableIn.off(this._varChangeListenerId);
  780. this._variableIn = null;
  781. }
  782.  
  783. if (v)
  784. {
  785. this._variableIn = this._op.patch.getVar(v);
  786.  
  787. if (!this._variableIn)
  788. {
  789. this._log.warn("PORT VAR NOT FOUND!!!", v);
  790. }
  791. else
  792. {
  793. if (this.type == CONSTANTS.OP.OP_PORT_TYPE_OBJECT)
  794. {
  795. this._varChangeListenerId = this._variableIn.on("change", () => { this.set(null); this.set(this._variableIn.getValue()); });
  796. }
  797. else
  798. {
  799. this._varChangeListenerId = this._variableIn.on("change", this.set.bind(this));
  800. }
  801. this.set(this._variableIn.getValue());
  802. }
  803. this._useVariableName = v;
  804. attr.useVariable = true;
  805. attr.variableName = this._useVariableName;
  806. }
  807. else
  808. {
  809. attr.variableName = this._useVariableName = null;
  810. attr.useVariable = false;
  811. }
  812.  
  813. this.setUiAttribs(attr);
  814. this._op.patch.emitEvent("portSetVariable", this._op, this, v);
  815. };
  816.  
  817. Port.prototype._handleNoTriggerOpAnimUpdates = function (a)
  818. {
  819. let hasTriggerPort = false;
  820. for (let i = 0; i < this._op.portsIn.length; i++)
  821. {
  822. if (this._op.portsIn.type == CONSTANTS.OP.OP_PORT_TYPE_FUNCTION)
  823. {
  824. hasTriggerPort = true;
  825. break;
  826. }
  827. }
  828.  
  829. if (!hasTriggerPort)
  830. {
  831. if (a) this._notriggerAnimUpdate = this._op.patch.on("onRenderFrame",
  832. () =>
  833. {
  834. this.updateAnim();
  835. });
  836. else this._op.patch.removeEventListener(this._notriggerAnimUpdate);
  837. }
  838. };
  839.  
  840. Port.prototype.setAnimated = function (a)
  841. {
  842. if (this._animated != a)
  843. {
  844. this._animated = a;
  845. this._op._hasAnimPort = true;
  846.  
  847. if (this._animated && !this.anim)
  848. {
  849. this.anim = new Anim({ "name": "port " + this.name });
  850. this.anim.addEventListener("onChange", () =>
  851. {
  852. this._op.patch.emitEvent("portAnimUpdated", this._op, this, this.anim);
  853. });
  854. }
  855. this._onAnimToggle();
  856. }
  857.  
  858. this._handleNoTriggerOpAnimUpdates(a);
  859. if (!a)
  860. {
  861. this.anim = null;
  862. }
  863.  
  864. this.setUiAttribs({ "isAnimated": this._animated });
  865. };
  866.  
  867. Port.prototype.toggleAnim = function ()
  868. {
  869. this._animated = !this._animated;
  870. if (this._animated && !this.anim)
  871. {
  872. this.anim = new Anim({ "name": "port " + this.name });
  873. this.anim.addEventListener("onChange", () =>
  874. {
  875. this._op.patch.emitEvent("portAnimUpdated", this._op, this, this.anim);
  876. });
  877. }
  878. this.setAnimated(this._animated);
  879. this._onAnimToggle();
  880. this.setUiAttribs({ "isAnimated": this._animated });
  881. };
  882.  
  883. /**
  884. * <pre>
  885. * CABLES.CONSTANTS.OP.OP_PORT_TYPE_VALUE = 0;
  886. * CABLES.CONSTANTS.OP.OP_PORT_TYPE_FUNCTION = 1;
  887. * CABLES.CONSTANTS.OP.OP_PORT_TYPE_OBJECT = 2;
  888. * CABLES.CONSTANTS.OP.OP_PORT_TYPE_TEXTURE = 2;
  889. * CABLES.CONSTANTS.OP.OP_PORT_TYPE_ARRAY = 3;
  890. * CABLES.CONSTANTS.OP.OP_PORT_TYPE_DYNAMIC = 4;
  891. * CABLES.CONSTANTS.OP.OP_PORT_TYPE_STRING = 5;
  892. * </pre>
  893. * @function getType
  894. * @memberof Port
  895. * @instance
  896. * @return {Number} type of port
  897. */
  898. Port.prototype.getType = function ()
  899. {
  900. return this.type;
  901. };
  902.  
  903. /**
  904. * @function isLinked
  905. * @memberof Port
  906. * @instance
  907. * @return {Boolean} true if port is linked
  908. */
  909. Port.prototype.isLinked = function ()
  910. {
  911. return this.links.length > 0 || this._animated || this._useVariableName != null;
  912. };
  913.  
  914. Port.prototype.isBoundToVar = function ()
  915. {
  916. const b = this._useVariableName != null;
  917. this.uiAttribs.boundToVar = b;
  918. return b;
  919. };
  920. /**
  921. * @function isAnimated
  922. * @memberof Port
  923. * @instance
  924. * @return {Boolean} true if port is animated
  925. */
  926. Port.prototype.isAnimated = function ()
  927. {
  928. return this._animated;
  929. };
  930.  
  931. /**
  932. * @function isHidden
  933. * @memberof Port
  934. * @instance
  935. * @return {Boolean} true if port is hidden
  936. */
  937. Port.prototype.isHidden = function ()
  938. {
  939. return this.uiAttribs.hidePort;
  940. };
  941.  
  942. /**
  943. * @function onTriggered
  944. * @memberof Port
  945. * @instance
  946. * @param {function} a onTriggeredCallback
  947. * @description set callback, which will be executed when port was triggered (usually output port)
  948. */
  949. Port.prototype._onTriggered = function (a)
  950. {
  951. this._activity();
  952. this._op.updateAnims();
  953. if (this._op.enabled && this.onTriggered) this.onTriggered(a);
  954.  
  955. if (this._op.enabled) this.emitEvent("trigger");
  956. };
  957.  
  958. Port.prototype._onSetProfiling = function (v)
  959. {
  960. this._op.patch.profiler.add("port", this);
  961. this.setValue(v);
  962. this._op.patch.profiler.add("port", null);
  963. };
  964.  
  965. Port.prototype._onTriggeredProfiling = function ()
  966. {
  967. if (this._op.enabled && this.onTriggered)
  968. {
  969. this._op.patch.profiler.add("port", this);
  970. this.onTriggered();
  971. this._op.patch.profiler.add("port", null);
  972. }
  973. };
  974.  
  975.  
  976.  
  977. Port.prototype.getUiActiveState = function ()
  978. {
  979. return this._uiActiveState;
  980. };
  981.  
  982. Port.prototype.setUiActiveState = function (onoff)
  983. {
  984. this._uiActiveState = onoff;
  985. if (this.onUiActiveStateChange) this.onUiActiveStateChange();
  986. };
  987.  
  988. /**
  989. * @deprecated
  990. * @param {function} cb
  991. */
  992. Port.prototype.onValueChange = function (cb)
  993. {
  994. this.onChange = cb;
  995. };
  996.  
  997. /**
  998. * @deprecated
  999. */
  1000. Port.prototype.hidePort = function () {};
  1001.  
  1002.  
  1003. /**
  1004. * Returns the port type string, e.g. "value" based on the port type number
  1005. * @function portTypeNumberToString
  1006. * @instance
  1007. * @memberof Port
  1008. * @param {Number} type - The port type number
  1009. * @returns {String} - The port type as string
  1010. */
  1011. Port.portTypeNumberToString = function (type)
  1012. {
  1013. if (type == CONSTANTS.OP.OP_PORT_TYPE_VALUE) return "value";
  1014. if (type == CONSTANTS.OP.OP_PORT_TYPE_FUNCTION) return "function";
  1015. if (type == CONSTANTS.OP.OP_PORT_TYPE_OBJECT) return "object";
  1016. if (type == CONSTANTS.OP.OP_PORT_TYPE_ARRAY) return "array";
  1017. if (type == CONSTANTS.OP.OP_PORT_TYPE_STRING) return "string";
  1018. if (type == CONSTANTS.OP.OP_PORT_TYPE_DYNAMIC) return "dynamic";
  1019. return "unknown";
  1020. };
  1021.  
  1022. export { Port };