Home Reference Source

cables_dev/cables/src/core/core_op.js

  1. import { Logger } from "cables-shared-client";
  2. import { EventTarget } from "./eventtarget.js";
  3. import { UTILS, cleanJson, shortId } from "./utils.js";
  4. import { CONSTANTS } from "./constants.js";
  5. import { Port } from "./core_port.js";
  6. import { SwitchPort } from "./core_port_switch.js";
  7. import { ValueSelectPort } from "./core_port_select.js";
  8. import { MultiPort } from "./core_port_multi.js";
  9.  
  10. /**
  11. * op the class of all operators
  12. * @namespace external:CABLES#Op
  13. * @hideconstructor
  14. */
  15.  
  16. /**
  17. * @type {Object}
  18. * @name attachments
  19. * @instance
  20. * @memberof Op
  21. * @description access file attachments as String values
  22. * @example
  23. * // set shader source to attached files (files are called shader.vert / shader.frag)
  24. * shader.setSource(attachments.shader_vert,attachments.shader_frag);
  25. */
  26.  
  27. const Ops = {};
  28.  
  29. const Op = function ()
  30. {
  31. EventTarget.apply(this);
  32.  
  33. this._log = new Logger("core_op");
  34. this.data = {}; // UNUSED, DEPRECATED, only left in for backwards compatibility with userops
  35. this.storage = {}; // op-specific data to be included in export
  36. this.__objName = "";
  37. this.portsOut = [];
  38. this.portsIn = [];
  39. this.portsInData = []; // original loaded patch data
  40. this.opId = ""; // unique op id
  41. this.uiAttribs = {};
  42. this.enabled = true;
  43. this.patch = arguments[0];
  44. this._name = arguments[1];
  45. this.preservedPortTitles = {};
  46. this.preservedPortValues = {};
  47. this.preservedPortLinks = {};
  48.  
  49. this._linkTimeRules = {
  50. "needsLinkedToWork": [],
  51. "needsParentOp": null
  52. };
  53.  
  54. this.shouldWork = {};
  55. this.hasUiErrors = false;
  56. this._uiErrors = {};
  57. this._hasAnimPort = false;
  58.  
  59. if (arguments[1])
  60. {
  61. this._shortOpName = CABLES.getShortOpName(arguments[1]);
  62. this.getTitle();
  63. }
  64.  
  65. this.id = arguments[2] || shortId(); // instance id
  66. this.onAddPort = null;
  67. this.onCreate = null;
  68. this.onResize = null;
  69. this.onLoaded = null;
  70. this.onDelete = null;
  71. this.onError = null;
  72.  
  73. this._instances = null;
  74.  
  75. /**
  76. * overwrite this to prerender shader and meshes / will be called by op `loadingStatus`
  77. * @function preRender
  78. * @memberof Op
  79. * @instance
  80. */
  81. this.preRender = null;
  82.  
  83. /**
  84. * overwrite this to initialize your op
  85. * @function init
  86. * @memberof Op
  87. * @instance
  88. */
  89. this.init = null;
  90.  
  91. Object.defineProperty(this, "name", {
  92. get() { return this.getTitle(); },
  93. set(v)
  94. {
  95. this.setTitle(v);
  96. }
  97. });
  98.  
  99. Object.defineProperty(this, "_objName", { set(on)
  100. {
  101. this.__objName = on; this._log = new Logger("op " + on);
  102. } });
  103.  
  104. Object.defineProperty(this, "objName", { get() { return this.__objName; } });
  105. Object.defineProperty(this, "shortName", { get() { return this._shortOpName; } });
  106.  
  107. if (this.initUi) this.initUi();
  108. };
  109.  
  110. {
  111. Op.prototype.clearUiAttrib = function (name)
  112. {
  113. const obj = {};
  114. // obj.name = null;
  115. this.uiAttrib(obj);
  116. };
  117.  
  118. Op.prototype.require = function (name)
  119. {
  120. if (CABLES.platform && CABLES.StandaloneElectron && !CABLES.platform.frontendOptions.isStandalone)
  121. this.setUiError("notstandalone", "This op will only work in cables standalone version", 3);
  122.  
  123. return null;
  124. };
  125.  
  126.  
  127. Op.prototype.checkMainloopExists = function ()
  128. {
  129. if (!CABLES.UI) return;
  130. if (!this.patch.tempData.mainloopOp) this.setUiError("nomainloop", "patch should have a mainloop to use this op");
  131. else this.setUiError("nomainloop", null);
  132. };
  133.  
  134. Op.prototype.getTitle = function ()
  135. {
  136. if (!this.uiAttribs) return "nouiattribs" + this._name;
  137.  
  138. // if ((this.uiAttribs.title === undefined || this.uiAttribs.title === "") && this.objName.indexOf("Ops.Ui.") == -1)
  139. // this.uiAttribs.title = this._shortOpName;
  140.  
  141. return this.uiAttribs.title || this._shortOpName;
  142. };
  143.  
  144. Op.prototype.setTitle = function (title)
  145. {
  146. // this._log.log("settitle", title);
  147. // this._log.log(
  148. // (new Error()).stack
  149. // );
  150.  
  151. if (title != this.getTitle()) this.uiAttr({ "title": title });
  152. };
  153.  
  154. Op.prototype.setStorage = function (newAttribs)
  155. {
  156. if (!newAttribs) return;
  157. this.storage = this.storage || {};
  158.  
  159. let changed = false;
  160. for (const p in newAttribs)
  161. {
  162. if (this.storage[p] != newAttribs[p]) changed = true;
  163. this.storage[p] = newAttribs[p];
  164. }
  165.  
  166. if (changed) this.emitEvent("onStorageChange", newAttribs);
  167. };
  168.  
  169. Op.prototype.isSubPatchOp = function ()
  170. {
  171. if (this.patchId && this.storage) return (this.storage.subPatchVer || this.storage.blueprintVer || 0);
  172. return false;
  173. };
  174.  
  175. const _setUiAttrib = function (newAttribs)
  176. {
  177. if (!newAttribs) return;
  178.  
  179. if (newAttribs.error || newAttribs.warning || newAttribs.hint)
  180. {
  181. this._log.warn("old ui error/warning attribute in " + this._name + ", use op.setUiError !", newAttribs);
  182. }
  183.  
  184.  
  185. if (typeof newAttribs != "object") this._log.error("op.uiAttrib attribs are not of type object");
  186. if (!this.uiAttribs) this.uiAttribs = {};
  187.  
  188. let changed = false;
  189. let emitMove = false;
  190. if (
  191. CABLES.UI &&
  192. newAttribs.hasOwnProperty("translate") &&
  193. (
  194. !this.uiAttribs.translate ||
  195. this.uiAttribs.translate.x != newAttribs.translate.x ||
  196. this.uiAttribs.translate.y != newAttribs.translate.y
  197. )) emitMove = true;
  198.  
  199.  
  200. if (newAttribs.hasOwnProperty("title") && newAttribs.title != this.uiAttribs.title)
  201. {
  202. // const doEmitEvent = newAttribs.title != this.getTitle();
  203. this.uiAttribs.title = newAttribs.title;
  204. // if (doEmitEvent) this.emitEvent("onTitleChange", newAttribs.title);
  205. changed = true;
  206. // this.setTitle(newAttribs.title);
  207. }
  208.  
  209. if (newAttribs.hasOwnProperty("disabled")) this.setEnabled(!newAttribs.disabled);
  210.  
  211. for (const p in newAttribs)
  212. {
  213. if (this.uiAttribs[p] != newAttribs[p]) changed = true;
  214. this.uiAttribs[p] = newAttribs[p];
  215. }
  216.  
  217.  
  218. if (this.uiAttribs.hasOwnProperty("selected") && this.uiAttribs.selected == false) delete this.uiAttribs.selected;
  219.  
  220.  
  221. if (changed)
  222. {
  223. this.emitEvent("onUiAttribsChange", newAttribs);
  224. this.patch.emitEvent("onUiAttribsChange", this, newAttribs);
  225. }
  226.  
  227.  
  228. if (emitMove) this.emitEvent("move");
  229. };
  230. /**
  231. * setUiAttrib
  232. * possible values:
  233. * <pre>
  234. * warning - warning message - showing up in op parameter panel
  235. * error - error message - showing up in op parameter panel
  236. * extendTitle - op title extension, e.g. [ + ]
  237. * </pre>
  238. * @function setUiAttrib
  239. * @param {Object} newAttribs, e.g. {"attrib":value}
  240. * @memberof Op
  241. * @instance
  242. * @example
  243. * op.setUiAttrib({"extendTitle":str});
  244. */
  245. Op.prototype.setUiAttribs = Op.prototype.setUiAttrib = Op.prototype.uiAttr = _setUiAttrib;
  246.  
  247. Op.prototype.getName = function ()
  248. {
  249. if (this.uiAttribs.name) return this.uiAttribs.name;
  250. return this._name;
  251. };
  252.  
  253. Op.prototype.addOutPort = function (p)
  254. {
  255. p.direction = CONSTANTS.PORT.PORT_DIR_OUT;
  256. p._op = this;
  257. this.portsOut.push(p);
  258. this.emitEvent("onPortAdd", p);
  259. return p;
  260. };
  261.  
  262. Op.prototype.hasDynamicPort = function ()
  263. {
  264. let i = 0;
  265. for (i = 0; i < this.portsIn.length; i++)
  266. {
  267. if (this.portsIn[i].type == CONSTANTS.OP.OP_PORT_TYPE_DYNAMIC) return true;
  268. if (this.portsIn[i].getName() == "dyn") return true;
  269. }
  270. for (i = 0; i < this.portsOut.length; i++)
  271. {
  272. if (this.portsOut[i].type == CONSTANTS.OP.OP_PORT_TYPE_DYNAMIC) return true;
  273. if (this.portsOut[i].getName() == "dyn") return true;
  274. }
  275.  
  276. return false;
  277. };
  278.  
  279. Op.prototype.addInPort = function (p)
  280. {
  281. if (!(p instanceof Port)) throw new Error("parameter is not a port!");
  282.  
  283. p.direction = CONSTANTS.PORT.PORT_DIR_IN;
  284. p._op = this;
  285.  
  286. this.portsIn.push(p);
  287. this.emitEvent("onPortAdd", p);
  288.  
  289. return p;
  290. };
  291.  
  292. /**
  293. * create a trigger input port
  294. * @function inTrigger
  295. * @instance
  296. * @memberof Op
  297. * @param {String} name
  298. * @return {Port} created port
  299. *
  300. */
  301. Op.prototype.inFunction = Op.prototype.inTrigger = function (name, v)
  302. {
  303. const p = this.addInPort(new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_FUNCTION));
  304. if (v !== undefined) p.set(v);
  305. return p;
  306. };
  307.  
  308. /**
  309. * create multiple UI trigger buttons
  310. * @function inTriggerButton
  311. * @memberof Op
  312. * @instance
  313. * @param {String} name
  314. * @param {Array} names
  315. * @return {Port} created port
  316. */
  317. Op.prototype.inFunctionButton = Op.prototype.inTriggerButton = function (name, v)
  318. {
  319. const p = this.addInPort(
  320. new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_FUNCTION, {
  321. "display": "button"
  322. })
  323. );
  324. if (v !== undefined) p.set(v);
  325. return p;
  326. };
  327.  
  328. Op.prototype.inFunctionButton = Op.prototype.inUiTriggerButtons = function (name, v)
  329. {
  330. const p = this.addInPort(
  331. new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_FUNCTION, {
  332. "display": "buttons"
  333. })
  334. );
  335. if (v !== undefined) p.set(v);
  336. return p;
  337. };
  338.  
  339.  
  340.  
  341. /**
  342. * create a number value input port
  343. * @function inFloat
  344. * @memberof Op
  345. * @instance
  346. * @param {String} name
  347. * @param {Number} value
  348. * @return {Port} created port
  349. */
  350. Op.prototype.inValueFloat = Op.prototype.inValue = Op.prototype.inFloat = function (name, v)
  351. {
  352. const p = this.addInPort(new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE));
  353.  
  354. p.setInitialValue(v);
  355.  
  356. return p;
  357. };
  358.  
  359. /**
  360. * create a boolean input port, displayed as a checkbox
  361. * @function inBool
  362. * @instance
  363. * @memberof Op
  364. * @param {String} name
  365. * @param {Boolean} value
  366. * @return {Port} created port
  367. */
  368. Op.prototype.inValueBool = Op.prototype.inBool = function (name, v)
  369. {
  370. const p = this.addInPort(
  371. new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_NUMBER, {
  372. "display": "bool"
  373. })
  374. );
  375.  
  376. if (v === true)v = 1;
  377. if (v === false)v = 0;
  378. p.setInitialValue(v);
  379.  
  380. return p;
  381. };
  382.  
  383.  
  384. Op.prototype.inMultiPort = function (name, type)
  385. {
  386. const p = new MultiPort(
  387. this,
  388. name,
  389. type,
  390. CONSTANTS.PORT.PORT_DIR_IN,
  391. {
  392. "addPort": true,
  393. "hidePort": true
  394. }
  395. );
  396. p.ignoreValueSerialize = true;
  397.  
  398. this.addInPort(p);
  399. p.initPorts();
  400.  
  401. return p;
  402. };
  403.  
  404. Op.prototype.outMultiPort = function (name, type, uiAttribsPort = {})
  405. {
  406. const p = new MultiPort(
  407. this,
  408. name,
  409. type,
  410. CONSTANTS.PORT.PORT_DIR_OUT,
  411. {
  412. "display": "multiport",
  413. "hidePort": true
  414. },
  415. uiAttribsPort
  416. );
  417. p.ignoreValueSerialize = true;
  418.  
  419. this.addOutPort(p);
  420. p.initPorts();
  421.  
  422. return p;
  423. };
  424.  
  425.  
  426.  
  427. Op.prototype.inValueString = function (name, v)
  428. {
  429. const p = this.addInPort(
  430. new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
  431. "type": "string"
  432. })
  433. );
  434. p.value = "";
  435.  
  436. p.setInitialValue(v);
  437. return p;
  438. };
  439.  
  440. /**
  441. * create a String value input port
  442. * @function inString
  443. * @instance
  444. * @memberof Op
  445. * @param {String} name
  446. * @param {String} value default value
  447. * @return {Port} created port
  448. */
  449. Op.prototype.inString = function (name, v)
  450. {
  451. const p = this.addInPort(
  452. new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_STRING, {
  453. "type": "string"
  454. })
  455. );
  456. v = v || "";
  457. // p.value = v;
  458.  
  459. p.setInitialValue(v);
  460. return p;
  461. };
  462.  
  463. /**
  464. * create a String value input port displayed as TextArea
  465. * @function inValueText
  466. * @instance
  467. * @memberof Op
  468. * @param {String} name
  469. * @param {String} value default value
  470. * @return {Port} created port
  471. */
  472. Op.prototype.inValueText = function (name, v)
  473. {
  474. const p = this.addInPort(
  475. new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
  476. "type": "string",
  477. "display": "text"
  478. })
  479. );
  480. p.value = "";
  481.  
  482. p.setInitialValue(v);
  483. // if (v !== undefined)
  484. // {
  485. // p.set(v);
  486. // p.defaultValue = v;
  487. // }
  488. return p;
  489. };
  490.  
  491. Op.prototype.inTextarea = function (name, v)
  492. {
  493. const p = this.addInPort(
  494. new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_STRING, {
  495. "type": "string",
  496. "display": "text"
  497. })
  498. );
  499. p.value = "";
  500. if (v !== undefined)
  501. {
  502. p.set(v);
  503. p.defaultValue = v;
  504. }
  505. return p;
  506. };
  507.  
  508. /**
  509. * create a String value input port displayed as editor
  510. * @function inStringEditor
  511. * @instance
  512. * @memberof Op
  513. * @param {String} name
  514. * @param {String} value default value
  515. * @return {Port} created port
  516. */
  517. // new string
  518. Op.prototype.inStringEditor = function (name, v, syntax, hideFormatButton = true)
  519. {
  520. const p = this.addInPort(
  521. new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_STRING, {
  522. "type": "string",
  523. "display": "editor",
  524. "editShortcut": true,
  525. "editorSyntax": syntax,
  526. "hideFormatButton": hideFormatButton
  527. }));
  528.  
  529. p.value = "";
  530. if (v !== undefined)
  531. {
  532. p.set(v);
  533. p.defaultValue = v;
  534. }
  535. return p;
  536. };
  537.  
  538. // old
  539. Op.prototype.inValueEditor = function (name, v, syntax, hideFormatButton = true)
  540. {
  541. const p = this.addInPort(
  542. new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_NUMBER, {
  543. "type": "string",
  544. "display": "editor",
  545. "editorSyntax": syntax,
  546. "hideFormatButton": hideFormatButton
  547. })
  548. );
  549. p.value = "";
  550. if (v !== undefined)
  551. {
  552. p.set(v);
  553. p.defaultValue = v;
  554. }
  555. return p;
  556. };
  557.  
  558. /**
  559. * create a string select box
  560. * @function inDropDown
  561. * @instance
  562. * @memberof Op
  563. * @param {String} name
  564. * @param {Array} values
  565. * @param {String} value default value
  566. * @return {Port} created port
  567. */
  568. Op.prototype.inValueSelect = Op.prototype.inDropDown = function (name, values, v, noindex)
  569. {
  570. let p = null;
  571. if (!noindex)
  572. {
  573. const indexPort = new Port(this, name + " index", CONSTANTS.OP.OP_PORT_TYPE_NUMBER, {
  574. "increment": "integer",
  575. "hideParam": true
  576. });
  577. const n = this.addInPort(indexPort);
  578.  
  579. if (values) for (let i = 0; i < values.length; i++) values[i] = String(values[i]);
  580.  
  581. const valuePort = new ValueSelectPort(
  582. this,
  583. name,
  584. CONSTANTS.OP.OP_PORT_TYPE_NUMBER,
  585. {
  586. "display": "dropdown",
  587. "hidePort": true,
  588. "type": "string",
  589. "values": values
  590. },
  591. n
  592. );
  593.  
  594. valuePort.indexPort = indexPort;
  595.  
  596. valuePort.on("change", (val, thePort) =>
  597. {
  598. if (!thePort.indexPort.isLinked() && thePort.uiAttribs.values)
  599. {
  600. const idx = thePort.uiAttribs.values.indexOf(val);
  601. if (idx > -1) thePort.indexPort.set(idx);
  602. }
  603. });
  604.  
  605. indexPort.onLinkChanged = function ()
  606. {
  607. valuePort.setUiAttribs({ "greyout": indexPort.isLinked() });
  608. };
  609.  
  610. p = this.addInPort(valuePort);
  611.  
  612. if (v !== undefined)
  613. {
  614. p.set(v);
  615. const index = values.findIndex((item) => { return item == v; });
  616. n.setValue(index);
  617. p.defaultValue = v;
  618. n.defaultValue = index;
  619. }
  620. }
  621. else
  622. {
  623. const valuePort = new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
  624. "display": "dropdown",
  625. "hidePort": true,
  626. "type": "string",
  627. values
  628. });
  629.  
  630. p = this.addInPort(valuePort);
  631. }
  632.  
  633. return p;
  634. };
  635.  
  636. /**
  637. * create a string switch box
  638. * @function inSwitch
  639. * @instance
  640. * @memberof Op
  641. * @param {String} name
  642. * @param {Array} values
  643. * @param {String} value default value
  644. * @return {Port} created port
  645. */
  646. Op.prototype.inSwitch = function (name, values, v, noindex)
  647. {
  648. let p = null;
  649. if (!noindex)
  650. {
  651. if (!v)v = values[0];
  652. const indexPort = new Port(this, name + " index", CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
  653. "increment": "integer",
  654. "values": values,
  655. "hideParam": true
  656. });
  657. const n = this.addInPort(indexPort);
  658.  
  659. if (values) for (let i = 0; i < values.length; i++) values[i] = String(values[i]);
  660.  
  661. const switchPort = new SwitchPort(
  662. this,
  663. name,
  664. CONSTANTS.OP.OP_PORT_TYPE_STRING,
  665. {
  666. "display": "switch",
  667. "hidePort": true,
  668. "type": "string",
  669. "values": values
  670. },
  671. n
  672. );
  673.  
  674. switchPort.indexPort = indexPort;
  675.  
  676. switchPort.on("change", (val, thePort) =>
  677. {
  678. if (!thePort.indexPort.isLinked() && thePort.uiAttribs.values)
  679. {
  680. const idx = thePort.uiAttribs.values.indexOf(val);
  681. if (idx > -1) thePort.indexPort.set(idx);
  682. }
  683. });
  684.  
  685. indexPort.onLinkChanged = function ()
  686. {
  687. switchPort.setUiAttribs({ "greyout": indexPort.isLinked() });
  688. };
  689. p = this.addInPort(switchPort);
  690.  
  691. if (v !== undefined)
  692. {
  693. p.set(v);
  694. const index = values.findIndex((item) => { return item == v; });
  695. n.setValue(index);
  696. p.defaultValue = v;
  697. n.defaultValue = index;
  698. }
  699. }
  700. else
  701. {
  702. const switchPort = new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_STRING, {
  703. "display": "switch",
  704. "hidePort": true,
  705. "type": "string",
  706. "values": values
  707. });
  708. p = this.addInPort(switchPort);
  709. }
  710.  
  711. return p;
  712. };
  713.  
  714. /**
  715. * create a integer input port
  716. * @function inInt
  717. * @instance
  718. * @memberof Op
  719. * @param {String} name
  720. * @param {number} value default value
  721. * @return {Port} created port
  722. */
  723. Op.prototype.inValueInt = Op.prototype.inInt = function (name, v)
  724. {
  725. // old
  726. const p = this.addInPort(
  727. new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
  728. "increment": "integer"
  729. })
  730. );
  731. if (v !== undefined)
  732. {
  733. p.set(v);
  734. p.defaultValue = v;
  735. }
  736. return p;
  737. };
  738.  
  739. /**
  740. * create a file/URL input port
  741. * @function inURL
  742. * @instance
  743. * @memberof Op
  744. * @param {String} name
  745. * @return {Port} created port
  746. */
  747. Op.prototype.inFile = function (name, filter, v)
  748. {
  749. const p = this.addInPort(
  750. new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
  751. "display": "file",
  752. "type": "string",
  753. "filter": filter
  754. })
  755. );
  756. if (v !== undefined)
  757. {
  758. p.set(v);
  759. p.defaultValue = v;
  760. }
  761. return p;
  762. };
  763.  
  764. Op.prototype.inUrl = function (name, filter, v)
  765. {
  766. const p = this.addInPort(
  767. new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_STRING, {
  768. "display": "file",
  769. "type": "string",
  770. "filter": filter
  771. })
  772. );
  773. if (v !== undefined)
  774. {
  775. p.set(v);
  776. p.defaultValue = v;
  777. }
  778. return p;
  779. };
  780.  
  781. /**
  782. * create a texture input port
  783. * @function inTexture
  784. * @instance
  785. * @memberof Op
  786. * @param {String} name
  787. * @return {Port} created port
  788. */
  789. Op.prototype.inTexture = function (name, v)
  790. {
  791. const p = this.addInPort(
  792. new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_OBJECT, {
  793. "display": "texture",
  794. "objType": "texture",
  795. "preview": true
  796. })
  797. );
  798. p.ignoreValueSerialize = true;
  799. if (v !== undefined) p.set(v);
  800. return p;
  801. };
  802.  
  803.  
  804. /**
  805. * create a object input port
  806. * @function inObject
  807. * @instance
  808. * @memberof Op
  809. * @param {String} name
  810. * @return {Port} created port
  811. */
  812. Op.prototype.inObject = function (name, v, objType)
  813. {
  814. const p = this.addInPort(new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_OBJECT, { "objType": objType }));
  815. p.ignoreValueSerialize = true;
  816.  
  817. if (v !== undefined) p.set(v);
  818. return p;
  819. };
  820.  
  821. Op.prototype.inGradient = function (name, v)
  822. {
  823. const p = this.addInPort(
  824. new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
  825. "display": "gradient"
  826. // "hidePort": true
  827. })
  828. );
  829. if (v !== undefined) p.set(v);
  830. return p;
  831. };
  832.  
  833.  
  834. Op.prototype.getPortVisibleIndex = function (p)
  835. {
  836. let ports = this.portsIn;
  837. if (p.direction == CONSTANTS.PORT_DIR_OUT)ports = this.portsOut;
  838.  
  839. let index = 0;
  840. for (let i = 0; i < ports.length; i++)
  841. {
  842. if (ports[i].uiAttribs.hidePort) continue;
  843. index++;
  844. if (ports[i] == p) return index;
  845. }
  846. };
  847.  
  848. /**
  849. * create a array input port
  850. * @function inArray
  851. * @instance
  852. * @memberof Op
  853. * @param {String} name
  854. * @return {Port} created port
  855. */
  856. Op.prototype.inArray = function (name, v, stride)
  857. {
  858. if (!stride && CABLES.UTILS.isNumeric(v))stride = v;
  859.  
  860. const p = this.addInPort(new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_ARRAY, { "stride": stride }));
  861.  
  862. if (v !== undefined && (Array.isArray(v) || v == null)) p.set(v);
  863.  
  864. // if (v !== undefined) p.set(v);
  865. return p;
  866. };
  867.  
  868. /**
  869. * create a value slider input port
  870. * @function inFloatSlider
  871. * @instance
  872. * @memberof Op
  873. * @param {String} name
  874. * @param {number} defaultvalue
  875. * @param {number} min
  876. * @param {number} max
  877. * @return {Port} created port
  878. */
  879. Op.prototype.inValueSlider = Op.prototype.inFloatSlider = function (name, v, min, max)
  880. {
  881. const uiattribs = { "display": "range" };
  882.  
  883. if (min != undefined && max != undefined)
  884. {
  885. uiattribs.min = min;
  886. uiattribs.max = max;
  887. }
  888.  
  889. const p = this.addInPort(new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, uiattribs));
  890. if (v !== undefined)
  891. {
  892. p.set(v);
  893. p.defaultValue = v;
  894. }
  895. return p;
  896. };
  897.  
  898. /**
  899. * create output trigger port
  900. * @function outTrigger
  901. * @instance
  902. * @memberof Op
  903. * @param {String} name
  904. * @return {Port} created port
  905. */
  906. Op.prototype.outFunction = Op.prototype.outTrigger = function (name, v)
  907. {
  908. // old
  909. const p = this.addOutPort(new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_FUNCTION));
  910. if (v !== undefined) p.set(v);
  911. return p;
  912. };
  913.  
  914. /**
  915. * create output value port
  916. * @function outNumber
  917. * @instance
  918. * @memberof Op
  919. * @param {String} name
  920. * @param {number} default value
  921. * @return {Port} created port
  922. */
  923. Op.prototype.outValue = Op.prototype.outNumber = function (name, v)
  924. {
  925. // old
  926. const p = this.addOutPort(new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE));
  927. if (v !== undefined) p.set(v);
  928. return p;
  929. };
  930.  
  931. /**
  932. * deprecated create output boolean port
  933. * @deprecated
  934. * @function outBool
  935. * @instance
  936. * @memberof Op
  937. * @param {String} name
  938. * @return {Port} created port
  939. */
  940. Op.prototype.outValueBool = Op.prototype.outBool = function (name, v)
  941. {
  942. // old: use outBoolNum
  943. const p = this.addOutPort(
  944. new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
  945. "display": "bool"
  946. })
  947. );
  948. if (v !== undefined) p.set(v);
  949. else p.set(0);
  950. return p;
  951. };
  952.  
  953. /**
  954. * create output boolean port,value will be converted to 0 or 1
  955. * @function outBoolNum
  956. * @instance
  957. * @memberof Op
  958. * @param {String} name
  959. * @return {Port} created port
  960. */
  961. Op.prototype.outBoolNum = function (name, v)
  962. {
  963. const p = this.addOutPort(
  964. new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
  965. "display": "boolnum"
  966. })
  967. );
  968.  
  969. p.set = function (b)
  970. {
  971. this.setValue(b ? 1 : 0);
  972. // this._log.log("bool set", b, this.get());
  973. }.bind(p);
  974.  
  975. if (v !== undefined) p.set(v);
  976. else p.set(0);
  977. return p;
  978. };
  979.  
  980. /**
  981. * create output string port
  982. * @function outString
  983. * @instance
  984. * @memberof Op
  985. * @param {String} name
  986. * @return {Port} created port
  987. */
  988. Op.prototype.outValueString = function (name, v)
  989. {
  990. const p = this.addOutPort(
  991. new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
  992. "type": "string"
  993. })
  994. );
  995. if (v !== undefined) p.set(v);
  996. return p;
  997. };
  998. Op.prototype.outString = function (name, v)
  999. {
  1000. const p = this.addOutPort(
  1001. new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_STRING, {
  1002. "type": "string"
  1003. })
  1004. );
  1005. if (v !== undefined) p.set(v);
  1006. else p.set("");
  1007. return p;
  1008. };
  1009.  
  1010. /**
  1011. * create output object port
  1012. * @function outObject
  1013. * @instance
  1014. * @memberof Op
  1015. * @param {String} name
  1016. * @return {Port} created port
  1017. */
  1018. Op.prototype.outObject = function (name, v, objType)
  1019. {
  1020. const p = this.addOutPort(new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_OBJECT, { "objType": objType || null }));
  1021. p.set(v || null);
  1022. p.ignoreValueSerialize = true;
  1023. return p;
  1024. };
  1025.  
  1026. /**
  1027. * create output array port
  1028. * @function outArray
  1029. * @instance
  1030. * @memberof Op
  1031. * @param {String} name
  1032. * @return {Port} created port
  1033. */
  1034. Op.prototype.outArray = function (name, v, stride)
  1035. {
  1036. if (!stride && CABLES.UTILS.isNumeric(v))stride = v;
  1037. const p = this.addOutPort(new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_ARRAY, { "stride": stride }));
  1038. if (v !== undefined && (Array.isArray(v) || v == null)) p.set(v);
  1039.  
  1040. p.ignoreValueSerialize = true;
  1041. return p;
  1042. };
  1043.  
  1044. /**
  1045. * create output texture port
  1046. * @function outTexture
  1047. * @instance
  1048. * @memberof Op
  1049. * @param {String} name
  1050. * @return {Port} created port
  1051. */
  1052. Op.prototype.outTexture = function (name, v)
  1053. {
  1054. const p = this.addOutPort(
  1055. new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_OBJECT, {
  1056. "preview": true,
  1057. "objType": "texture",
  1058. "display": "texture"
  1059. })
  1060. );
  1061. if (v !== undefined) p.setRef(v || CGL.Texture.getEmptyTexture(this.patch.cgl));
  1062.  
  1063. p.ignoreValueSerialize = true;
  1064. return p;
  1065. };
  1066.  
  1067. Op.prototype.inDynamic = function (name, filter, options, v)
  1068. {
  1069. const p = new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_DYNAMIC, options);
  1070.  
  1071. p.shouldLink = function (p1, p2)
  1072. {
  1073. if (filter && UTILS.isArray(filter))
  1074. {
  1075. for (let i = 0; i < filter.length; i++)
  1076. {
  1077. if (p1 == this && p2.type === filter[i]) return true;
  1078. if (p2 == this && p1.type === filter[i]) return true;
  1079. }
  1080. return false; // types do not match
  1081. }
  1082. return true; // no filter set
  1083. };
  1084.  
  1085. this.addInPort(p);
  1086. if (v !== undefined)
  1087. {
  1088. p.set(v);
  1089. p.defaultValue = v;
  1090. }
  1091. return p;
  1092. };
  1093.  
  1094. Op.prototype.removeLinks = function ()
  1095. {
  1096. for (let i = 0; i < this.portsIn.length; i++) this.portsIn[i].removeLinks();
  1097. for (let i = 0; i < this.portsOut.length; i++) this.portsOut[i].removeLinks();
  1098. };
  1099.  
  1100. Op.prototype.getSerialized = function ()
  1101. {
  1102. const opObj = {};
  1103.  
  1104. if (this.opId) opObj.opId = this.opId;
  1105. if (this.patch.storeObjNames) opObj.objName = this.objName;
  1106.  
  1107. opObj.id = this.id;
  1108. opObj.uiAttribs = JSON.parse(JSON.stringify(this.uiAttribs)) || {};
  1109.  
  1110. if (this.storage && Object.keys(this.storage).length > 0) opObj.storage = JSON.parse(JSON.stringify(this.storage));
  1111. if (this.uiAttribs.hasOwnProperty("working") && this.uiAttribs.working == true) delete this.uiAttribs.working;
  1112. if (opObj.uiAttribs.hasOwnProperty("uierrors")) delete opObj.uiAttribs.uierrors;
  1113.  
  1114. if (opObj.uiAttribs.title === "") delete opObj.uiAttribs.title;
  1115. if (opObj.uiAttribs.color === null) delete opObj.uiAttribs.color;
  1116. if (opObj.uiAttribs.comment === null) delete opObj.uiAttribs.comment;
  1117.  
  1118. if (opObj.uiAttribs.title == this._shortOpName ||
  1119. (this.uiAttribs.title || "").toLowerCase() == this._shortOpName.toLowerCase()) delete opObj.uiAttribs.title;
  1120.  
  1121. opObj.portsIn = [];
  1122. opObj.portsOut = [];
  1123.  
  1124. for (let i = 0; i < this.portsIn.length; i++)
  1125. {
  1126. const s = this.portsIn[i].getSerialized();
  1127. if (s) opObj.portsIn.push(s);
  1128. }
  1129.  
  1130. for (let i = 0; i < this.portsOut.length; i++)
  1131. {
  1132. const s = this.portsOut[i].getSerialized();
  1133. if (s) opObj.portsOut.push(s);
  1134. }
  1135.  
  1136. if (opObj.portsIn.length == 0) delete opObj.portsIn;
  1137. if (opObj.portsOut.length == 0) delete opObj.portsOut;
  1138. cleanJson(opObj);
  1139.  
  1140. return opObj;
  1141. };
  1142.  
  1143. Op.prototype.getFirstOutPortByType = function (type)
  1144. {
  1145. for (const ipo in this.portsOut) if (this.portsOut[ipo].type == type) return this.portsOut[ipo];
  1146. };
  1147.  
  1148. Op.prototype.getFirstInPortByType = function (type)
  1149. {
  1150. for (const ipo in this.portsIn) if (this.portsIn[ipo].type == type) return this.portsIn[ipo];
  1151. };
  1152.  
  1153. /**
  1154. * return port by the name portName
  1155. * @function getPort
  1156. * @instance
  1157. * @memberof Op
  1158. * @param {String} portName
  1159. * @return {Port}
  1160. */
  1161. Op.prototype.getPort = Op.prototype.getPortByName = function (name, lowerCase)
  1162. {
  1163. if (lowerCase)
  1164. {
  1165. for (let ipi = 0; ipi < this.portsIn.length; ipi++)
  1166. if (this.portsIn[ipi].getName().toLowerCase() == name || this.portsIn[ipi].id.toLowerCase() == name)
  1167. return this.portsIn[ipi];
  1168.  
  1169. for (let ipo = 0; ipo < this.portsOut.length; ipo++)
  1170. if (this.portsOut[ipo].getName().toLowerCase() == name || this.portsOut[ipo].id.toLowerCase() == name)
  1171. return this.portsOut[ipo];
  1172. }
  1173. else
  1174. {
  1175. for (let ipi = 0; ipi < this.portsIn.length; ipi++)
  1176. if (this.portsIn[ipi].getName() == name || this.portsIn[ipi].id == name)
  1177. return this.portsIn[ipi];
  1178.  
  1179. for (let ipo = 0; ipo < this.portsOut.length; ipo++)
  1180. if (this.portsOut[ipo].getName() == name || this.portsOut[ipo].id == name)
  1181. return this.portsOut[ipo];
  1182. }
  1183. };
  1184.  
  1185.  
  1186. /**
  1187. * return port by the name id
  1188. * @function getPortById
  1189. * @instance
  1190. * @memberof Op
  1191. * @param {String} id
  1192. * @return {Port}
  1193. */
  1194. Op.prototype.getPortById = function (id)
  1195. {
  1196. for (let ipi = 0; ipi < this.portsIn.length; ipi++) if (this.portsIn[ipi].id == id) return this.portsIn[ipi];
  1197. for (let ipo = 0; ipo < this.portsOut.length; ipo++) if (this.portsOut[ipo].id == id) return this.portsOut[ipo];
  1198. };
  1199.  
  1200. Op.prototype.updateAnims = function ()
  1201. {
  1202. if (this._hasAnimPort)
  1203. for (let i = 0; i < this.portsIn.length; i++) this.portsIn[i].updateAnim();
  1204. };
  1205.  
  1206. Op.prototype.log = function ()
  1207. {
  1208. this._log.log(...arguments);
  1209. };
  1210.  
  1211. Op.prototype.error = Op.prototype.logError = function ()
  1212. {
  1213. // if (!this)
  1214. // {
  1215. // this._log.error("no this...!!!");
  1216. // debugger;
  1217. // return;
  1218. // }
  1219. // const initiator = "op " + this.objName;
  1220. // if (CABLES.UI && !CABLES.UI.logFilter.filterLog({ "initiator": initiator, "opInstId": this.id, "level": 2 }, ...arguments)) return;
  1221.  
  1222. // // if (this.patch.silent) return;
  1223. // const args = ["[op " + CABLES.getShortOpName(this.objName) + "]"];
  1224. // args.push.apply(args, arguments);
  1225. // Function.prototype.apply.apply(this._log.error, [console, args]);// eslint-disable-line
  1226. // if (window.gui) window.gui.emitEvent("opLogEvent", this.objName, "error", arguments);
  1227. this._log.error(...arguments);
  1228. };
  1229.  
  1230. Op.prototype.warn = Op.prototype.logWarn = function ()
  1231. {
  1232. this._log.warn(...arguments);
  1233.  
  1234. // const initiator = "op " + this.objName;
  1235. // if (CABLES.UI && !CABLES.UI.logFilter.filterLog({ "initiator": initiator, "opInstId": this.id, "level": 1 }, ...arguments)) return;
  1236.  
  1237. // // if (this.patch.silent) return;
  1238. // const args = ["[op " + CABLES.getShortOpName(this.objName) + "]"];
  1239. // args.push.apply(args, arguments);
  1240. // Function.prototype.apply.apply(this._log.warn, [console, args]);// eslint-disable-line
  1241. };
  1242.  
  1243. Op.prototype.verbose = Op.prototype.logVerbose = function ()
  1244. {
  1245. // const initiator = "op " + CABLES.getShortOpName(this.objName);
  1246. // if (CABLES.UI && !CABLES.UI.logFilter.filterLog({ "initiator": initiator, "opInstId": this.id, "level": 0 }, ...arguments)) return;
  1247.  
  1248. // if (!CABLES.UI && this.patch.silent) return;
  1249.  
  1250. // const args = ["[" + initiator + "]"];
  1251. // args.push.apply(args, arguments);
  1252. // Function.prototype.apply.apply(this._log.info, [console, args]);// eslint-disable-line
  1253. this._log.verbose(...arguments);
  1254. };
  1255.  
  1256.  
  1257. Op.prototype.profile = function (enable)
  1258. {
  1259. for (let ipi = 0; ipi < this.portsIn.length; ipi++)
  1260. {
  1261. this.portsIn[ipi]._onTriggered = this.portsIn[ipi]._onTriggeredProfiling;
  1262. this.portsIn[ipi].set = this.portsIn[ipi]._onSetProfiling;
  1263. }
  1264. };
  1265.  
  1266. Op.prototype.findParent = function (objName)
  1267. {
  1268. for (let ipi = 0; ipi < this.portsIn.length; ipi++)
  1269. {
  1270. if (this.portsIn[ipi].isLinked())
  1271. {
  1272. if (this.portsIn[ipi].links[0].portOut.parent.objName == objName)
  1273. return this.portsIn[ipi].links[0].portOut.parent;
  1274.  
  1275. let found = null;
  1276. found = this.portsIn[ipi].links[0].portOut.parent.findParent(objName);
  1277. if (found) return found;
  1278. }
  1279. }
  1280. return null;
  1281. };
  1282.  
  1283.  
  1284. // todo: check instancing stuff?
  1285. Op.prototype.cleanUp = function ()
  1286. {
  1287. if (this._instances)
  1288. {
  1289. for (let i = 0; i < this._instances.length; i++)
  1290. {
  1291. if (this._instances[i].onDelete) this._instances[i].onDelete();
  1292. }
  1293.  
  1294.  
  1295. this._instances.length = 0;
  1296. }
  1297. for (let i = 0; i < this.portsIn.length; i++)
  1298. {
  1299. this.portsIn[i].setAnimated(false);
  1300. }
  1301.  
  1302. if (this.onAnimFrame) this.patch.removeOnAnimFrame(this);
  1303. };
  1304.  
  1305. // todo: check instancing stuff?
  1306. Op.prototype.instanced = function (triggerPort)
  1307. {
  1308. return false;
  1309. // this._log.log("instanced", this.patch.instancing.numCycles());
  1310. // if (this.patch.instancing.numCycles() === 0) return false;
  1311.  
  1312.  
  1313. // let i = 0;
  1314. // let ipi = 0;
  1315. // if (!this._instances || this._instances.length != this.patch.instancing.numCycles())
  1316. // {
  1317. // if (!this._instances) this._instances = [];
  1318. // this._.log("creating instances of ", this.objName, this.patch.instancing.numCycles(), this._instances.length);
  1319. // this._instances.length = this.patch.instancing.numCycles();
  1320.  
  1321. // for (i = 0; i < this._instances.length; i++)
  1322. // {
  1323. // this._instances[i] = this.patch.createOp(this.objName, true);
  1324. // this._instances[i].instanced = function ()
  1325. // {
  1326. // return false;
  1327. // };
  1328. // this._instances[i].uiAttr(this.uiAttribs);
  1329.  
  1330. // for (let ipo = 0; ipo < this.portsOut.length; ipo++)
  1331. // {
  1332. // if (this.portsOut[ipo].type == CONSTANTS.OP.OP_PORT_TYPE_FUNCTION)
  1333. // {
  1334. // this._instances[i].getPortByName(this.portsOut[ipo].name).trigger = this.portsOut[ipo].trigger.bind(this.portsOut[ipo]);
  1335. // }
  1336. // }
  1337. // }
  1338.  
  1339. // for (ipi = 0; ipi < this.portsIn.length; ipi++)
  1340. // {
  1341. // this.portsIn[ipi].onChange = null;
  1342. // this.portsIn[ipi].onValueChanged = null;
  1343. // }
  1344. // }
  1345.  
  1346. // const theTriggerPort = null;
  1347. // for (ipi = 0; ipi < this.portsIn.length; ipi++)
  1348. // {
  1349. // if (
  1350. // this.portsIn[ipi].type == CONSTANTS.OP.OP_PORT_TYPE_VALUE ||
  1351. // this.portsIn[ipi].type == CONSTANTS.OP.OP_PORT_TYPE_ARRAY
  1352. // )
  1353. // {
  1354. // this._instances[this.patch.instancing.index()].portsIn[ipi].set(this.portsIn[ipi].get());
  1355. // }
  1356. // if (this.portsIn[ipi].type == CONSTANTS.OP.OP_PORT_TYPE_FUNCTION)
  1357. // {
  1358. // // if(this._instances[ this.patch.instancing.index() ].portsIn[ipi].name==triggerPort.name)
  1359. // // theTriggerPort=this._instances[ this.patch.instancing.index() ].portsIn[ipi];
  1360. // }
  1361. // }
  1362.  
  1363. // if (theTriggerPort) theTriggerPort.onTriggered();
  1364.  
  1365. // for (ipi = 0; ipi < this.portsOut.length; ipi++)
  1366. // {
  1367. // if (this.portsOut[ipi].type == CONSTANTS.OP.OP_PORT_TYPE_VALUE)
  1368. // {
  1369. // this.portsOut[ipi].set(this._instances[this.patch.instancing.index()].portsOut[ipi].get());
  1370. // }
  1371. // }
  1372.  
  1373. // return true;
  1374. };
  1375.  
  1376. // todo: check instancing stuff?
  1377. Op.prototype.initInstancable = function ()
  1378. {
  1379. // if(this.isInstanced)
  1380. // {
  1381. // this._log.log('cancel instancing');
  1382. // return;
  1383. // }
  1384. // this._instances=[];
  1385. // for(var ipi=0;ipi<this.portsIn.length;ipi++)
  1386. // {
  1387. // if(this.portsIn[ipi].type==CONSTANTS.OP.OP_PORT_TYPE_VALUE)
  1388. // {
  1389. //
  1390. // }
  1391. // if(this.portsIn[ipi].type==CONSTANTS.OP.OP_PORT_TYPE_FUNCTION)
  1392. // {
  1393. // // var piIndex=ipi;
  1394. // this.portsIn[ipi].onTriggered=function(piIndex)
  1395. // {
  1396. //
  1397. // var i=0;
  1398. // // this._log.log('trigger',this._instances.length);
  1399. //
  1400. // }.bind(this,ipi );
  1401. //
  1402. // }
  1403. // };
  1404. // this._instances=null;
  1405. };
  1406.  
  1407. Op.prototype.setValues = function (obj)
  1408. {
  1409. for (const i in obj)
  1410. {
  1411. const port = this.getPortByName(i);
  1412. if (port) port.set(obj[i]);
  1413. else this._log.warn("op.setValues: port not found:", i);
  1414. }
  1415. };
  1416.  
  1417. /**
  1418. * return true if op has this error message id
  1419. * @function hasUiError
  1420. * @instance
  1421. * @memberof Op
  1422. * @param {id} error id
  1423. * @returns {Boolean} - has id
  1424. */
  1425. Op.prototype.hasUiError = function (id)
  1426. {
  1427. return this._uiErrors.hasOwnProperty(id) && this._uiErrors[id];
  1428. };
  1429.  
  1430. /**
  1431. * show op error message - set message to null to remove error message
  1432. * @function setUiError
  1433. * @instance
  1434. * @memberof Op
  1435. * @param {id} error id
  1436. * @param {txt} text message
  1437. * @param {level} level
  1438. */
  1439. Op.prototype.setUiError = function (id, txt, level)
  1440. {
  1441. // overwritten in ui: core_extend_op
  1442. };
  1443.  
  1444. // todo: remove
  1445. Op.prototype.setError = function (id, txt)
  1446. {
  1447. this._log.warn("old error message op.error() - use op.setUiError()");
  1448. };
  1449.  
  1450.  
  1451. /**
  1452. * enable/disable op
  1453. * @function
  1454. * @instance
  1455. * @memberof Op
  1456. * @param {boolean}
  1457. */
  1458. Op.prototype.setEnabled = function (b)
  1459. {
  1460. this.enabled = b;
  1461. this.emitEvent("onEnabledChange", b);
  1462. };
  1463.  
  1464. /**
  1465. * organize ports into a group
  1466. * @function
  1467. * @instance
  1468. * @memberof Op
  1469. * @param {String} name
  1470. * @param {Array} ports
  1471. */
  1472. Op.prototype.setPortGroup = function (name, ports)
  1473. {
  1474. for (let i = 0; i < ports.length; i++)
  1475. {
  1476. if (ports[i])
  1477. if (ports[i].setUiAttribs) ports[i].setUiAttribs({ "group": name });
  1478. else
  1479. {
  1480. this._log.error("setPortGroup: invalid port!");
  1481. }
  1482. }
  1483. };
  1484.  
  1485. /**
  1486. * visually indicate ports that they are coordinate inputs
  1487. * @function
  1488. * @instance
  1489. * @memberof Op
  1490. * @param {Port} portX
  1491. * @param {Port} portY
  1492. * @param {Port} portZ
  1493. */
  1494. Op.prototype.setUiAxisPorts = function (px, py, pz)
  1495. {
  1496. if (px) px.setUiAttribs({ "axis": "X" });
  1497. if (py) py.setUiAttribs({ "axis": "Y" });
  1498. if (pz) pz.setUiAttribs({ "axis": "Z" });
  1499. };
  1500.  
  1501. /**
  1502. * remove port from op
  1503. * @function removePort
  1504. * @instance
  1505. * @memberof Op
  1506. * @param {Port} port to remove
  1507. */
  1508. Op.prototype.removePort = function (port)
  1509. {
  1510. for (let ipi = 0; ipi < this.portsIn.length; ipi++)
  1511. {
  1512. if (this.portsIn[ipi] == port)
  1513. {
  1514. this.portsIn.splice(ipi, 1);
  1515. this.emitEvent("onUiAttribsChange", {});
  1516. this.emitEvent("onPortRemoved", {});
  1517. return;
  1518. }
  1519. }
  1520. for (let ipi = 0; ipi < this.portsOut.length; ipi++)
  1521. {
  1522. if (this.portsOut[ipi] == port)
  1523. {
  1524. this.portsOut.splice(ipi, 1);
  1525. this.emitEvent("onUiAttribsChange", {});
  1526. this.emitEvent("onPortRemoved", {});
  1527. return;
  1528. }
  1529. }
  1530. };
  1531.  
  1532. Op.prototype._checkLinksNeededToWork = function () {};
  1533.  
  1534. /**
  1535. * show a warning of this op is not a child of parentOpName
  1536. * @function
  1537. * @instance
  1538. * @memberof Op
  1539. * @param {String} parentOpName
  1540. */
  1541. Op.prototype.toWorkNeedsParent = function (parentOpName)
  1542. {
  1543. this._linkTimeRules.needsParentOp = parentOpName;
  1544. };
  1545.  
  1546. // /**
  1547. // * show a warning of this op is a child of parentOpName
  1548. // * @function
  1549. // * @instance
  1550. // * @memberof Op
  1551. // * @param {String} parentOpName
  1552. // */
  1553. Op.prototype.toWorkShouldNotBeChild = function (parentOpName, type)
  1554. {
  1555. if (!this.patch.isEditorMode()) return;
  1556. this._linkTimeRules.forbiddenParent = parentOpName;
  1557. if (type != undefined) this._linkTimeRules.forbiddenParentType = type;
  1558. };
  1559.  
  1560.  
  1561. /**
  1562. * show a small X to indicate op is not working when given ports are not linked
  1563. * @function
  1564. * @instance
  1565. * @memberof Op
  1566. * @param {Port} port1
  1567. * @param {Port} port2
  1568. * @param {Port} port3
  1569. */
  1570. Op.prototype.toWorkPortsNeedToBeLinked = function ()
  1571. {
  1572. if (!this.patch.isEditorMode()) return;
  1573. for (let i = 0; i < arguments.length; i++)
  1574. if (this._linkTimeRules.needsLinkedToWork.indexOf(arguments[i]) == -1) this._linkTimeRules.needsLinkedToWork.push(arguments[i]);
  1575. };
  1576. Op.prototype.toWorkPortsNeedToBeLinkedReset = function ()
  1577. {
  1578. if (!this.patch.isEditorMode()) return;
  1579. this._linkTimeRules.needsLinkedToWork.length = 0;
  1580. if (this.checkLinkTimeWarnings) this.checkLinkTimeWarnings();
  1581. };
  1582.  
  1583. Op.prototype.initVarPorts = function ()
  1584. {
  1585. for (let i = 0; i < this.portsIn.length; i++)
  1586. {
  1587. if (this.portsIn[i].getVariableName()) this.portsIn[i].setVariable(this.portsIn[i].getVariableName());
  1588. }
  1589. };
  1590.  
  1591. /**
  1592. * refresh op parameters, if current op is selected
  1593. * @function
  1594. * @instance
  1595. * @memberof Op
  1596. */
  1597. Op.prototype.refreshParams = function ()
  1598. {
  1599. if (this.patch && this.patch.isEditorMode() && this.isCurrentUiOp())
  1600. {
  1601. gui.opParams.show(this);
  1602. }
  1603. };
  1604.  
  1605. /**
  1606. * Returns true if op is selected and parameter are shown in the editor, can only return true if in editor/ui
  1607. * @function isCurrentUiOp
  1608. * @instance
  1609. * @memberof Op
  1610. * @returns {Boolean} - is current ui op
  1611. */
  1612. Op.prototype.isCurrentUiOp = function ()
  1613. {
  1614. if (this.patch.isEditorMode()) return gui.patchView.isCurrentOp(this);
  1615. };
  1616.  
  1617. /**
  1618. * Implement to render 2d canvas based graphics from in an op
  1619. * @function renderVizLayer
  1620. * @instance
  1621. * @memberof Op
  1622. * @param {ctx} context of canvas 2d
  1623. * @param {Object} layer info
  1624. * @param {number} layer.x x position on canvas
  1625. * @param {number} layer.y y position on canvas
  1626. * @param {number} layer.width width of canvas
  1627. * @param {number} layer.height height of canvas
  1628. * @param {number} layer.scale current scaling of patchfield view
  1629. */
  1630. Op.prototype.renderVizLayer = null; // optionaly defined in op instance
  1631. }
  1632.  
  1633. export { Op };