cables_dev/cables/src/core/core_op.js
- import { Logger } from "cables-shared-client";
- import { EventTarget } from "./eventtarget.js";
- import { UTILS, cleanJson, shortId } from "./utils.js";
- import { CONSTANTS } from "./constants.js";
- import { Port } from "./core_port.js";
- import { SwitchPort } from "./core_port_switch.js";
- import { ValueSelectPort } from "./core_port_select.js";
- import { MultiPort } from "./core_port_multi.js";
-
- /**
- * op the class of all operators
- * @namespace external:CABLES#Op
- * @hideconstructor
- */
-
- /**
- * @type {Object}
- * @name attachments
- * @instance
- * @memberof Op
- * @description access file attachments as String values
- * @example
- * // set shader source to attached files (files are called shader.vert / shader.frag)
- * shader.setSource(attachments.shader_vert,attachments.shader_frag);
- */
-
- const Ops = {};
-
- const Op = function ()
- {
- EventTarget.apply(this);
-
- this._log = new Logger("core_op");
- this.data = {}; // UNUSED, DEPRECATED, only left in for backwards compatibility with userops
- this.storage = {}; // op-specific data to be included in export
- this.__objName = "";
- this.portsOut = [];
- this.portsIn = [];
- this.portsInData = []; // original loaded patch data
- this.opId = ""; // unique op id
- this.uiAttribs = {};
- this.enabled = true;
- this.patch = arguments[0];
- this._name = arguments[1];
- this.preservedPortTitles = {};
- this.preservedPortValues = {};
- this.preservedPortLinks = {};
-
- this._linkTimeRules = {
- "needsLinkedToWork": [],
- "needsParentOp": null
- };
-
- this.shouldWork = {};
- this.hasUiErrors = false;
- this._uiErrors = {};
- this._hasAnimPort = false;
-
- if (arguments[1])
- {
- this._shortOpName = CABLES.getShortOpName(arguments[1]);
- this.getTitle();
- }
-
- this.id = arguments[2] || shortId(); // instance id
- this.onAddPort = null;
- this.onCreate = null;
- this.onResize = null;
- this.onLoaded = null;
- this.onDelete = null;
- this.onError = null;
-
- this._instances = null;
-
- /**
- * overwrite this to prerender shader and meshes / will be called by op `loadingStatus`
- * @function preRender
- * @memberof Op
- * @instance
- */
- this.preRender = null;
-
- /**
- * overwrite this to initialize your op
- * @function init
- * @memberof Op
- * @instance
- */
- this.init = null;
-
- Object.defineProperty(this, "name", {
- get() { return this.getTitle(); },
- set(v)
- {
- this.setTitle(v);
- }
- });
-
- Object.defineProperty(this, "_objName", { set(on)
- {
- this.__objName = on; this._log = new Logger("op " + on);
- } });
-
- Object.defineProperty(this, "objName", { get() { return this.__objName; } });
- Object.defineProperty(this, "shortName", { get() { return this._shortOpName; } });
-
- if (this.initUi) this.initUi();
- };
-
- {
- Op.prototype.clearUiAttrib = function (name)
- {
- const obj = {};
- // obj.name = null;
- this.uiAttrib(obj);
- };
-
- Op.prototype.require = function (name)
- {
- if (CABLES.platform && CABLES.StandaloneElectron && !CABLES.platform.frontendOptions.isStandalone)
- this.setUiError("notstandalone", "This op will only work in cables standalone version", 3);
-
- return null;
- };
-
-
- Op.prototype.checkMainloopExists = function ()
- {
- if (!CABLES.UI) return;
- if (!this.patch.tempData.mainloopOp) this.setUiError("nomainloop", "patch should have a mainloop to use this op");
- else this.setUiError("nomainloop", null);
- };
-
- Op.prototype.getTitle = function ()
- {
- if (!this.uiAttribs) return "nouiattribs" + this._name;
-
- // if ((this.uiAttribs.title === undefined || this.uiAttribs.title === "") && this.objName.indexOf("Ops.Ui.") == -1)
- // this.uiAttribs.title = this._shortOpName;
-
- return this.uiAttribs.title || this._shortOpName;
- };
-
- Op.prototype.setTitle = function (title)
- {
- // this._log.log("settitle", title);
- // this._log.log(
- // (new Error()).stack
- // );
-
- if (title != this.getTitle()) this.uiAttr({ "title": title });
- };
-
- Op.prototype.setStorage = function (newAttribs)
- {
- if (!newAttribs) return;
- this.storage = this.storage || {};
-
- let changed = false;
- for (const p in newAttribs)
- {
- if (this.storage[p] != newAttribs[p]) changed = true;
- this.storage[p] = newAttribs[p];
- }
-
- if (changed) this.emitEvent("onStorageChange", newAttribs);
- };
-
- Op.prototype.isSubPatchOp = function ()
- {
- if (this.patchId && this.storage) return (this.storage.subPatchVer || this.storage.blueprintVer || 0);
- return false;
- };
-
- const _setUiAttrib = function (newAttribs)
- {
- if (!newAttribs) return;
-
- if (newAttribs.error || newAttribs.warning || newAttribs.hint)
- {
- this._log.warn("old ui error/warning attribute in " + this._name + ", use op.setUiError !", newAttribs);
- }
-
-
- if (typeof newAttribs != "object") this._log.error("op.uiAttrib attribs are not of type object");
- if (!this.uiAttribs) this.uiAttribs = {};
-
- let changed = false;
- let emitMove = false;
- if (
- CABLES.UI &&
- newAttribs.hasOwnProperty("translate") &&
- (
- !this.uiAttribs.translate ||
- this.uiAttribs.translate.x != newAttribs.translate.x ||
- this.uiAttribs.translate.y != newAttribs.translate.y
- )) emitMove = true;
-
-
- if (newAttribs.hasOwnProperty("title") && newAttribs.title != this.uiAttribs.title)
- {
- // const doEmitEvent = newAttribs.title != this.getTitle();
- this.uiAttribs.title = newAttribs.title;
- // if (doEmitEvent) this.emitEvent("onTitleChange", newAttribs.title);
- changed = true;
- // this.setTitle(newAttribs.title);
- }
-
- if (newAttribs.hasOwnProperty("disabled")) this.setEnabled(!newAttribs.disabled);
-
- for (const p in newAttribs)
- {
- if (this.uiAttribs[p] != newAttribs[p]) changed = true;
- this.uiAttribs[p] = newAttribs[p];
- }
-
-
- if (this.uiAttribs.hasOwnProperty("selected") && this.uiAttribs.selected == false) delete this.uiAttribs.selected;
-
-
- if (changed)
- {
- this.emitEvent("onUiAttribsChange", newAttribs);
- this.patch.emitEvent("onUiAttribsChange", this, newAttribs);
- }
-
-
- if (emitMove) this.emitEvent("move");
- };
- /**
- * setUiAttrib
- * possible values:
- * <pre>
- * warning - warning message - showing up in op parameter panel
- * error - error message - showing up in op parameter panel
- * extendTitle - op title extension, e.g. [ + ]
- * </pre>
- * @function setUiAttrib
- * @param {Object} newAttribs, e.g. {"attrib":value}
- * @memberof Op
- * @instance
- * @example
- * op.setUiAttrib({"extendTitle":str});
- */
- Op.prototype.setUiAttribs = Op.prototype.setUiAttrib = Op.prototype.uiAttr = _setUiAttrib;
-
- Op.prototype.getName = function ()
- {
- if (this.uiAttribs.name) return this.uiAttribs.name;
- return this._name;
- };
-
- Op.prototype.addOutPort = function (p)
- {
- p.direction = CONSTANTS.PORT.PORT_DIR_OUT;
- p._op = this;
- this.portsOut.push(p);
- this.emitEvent("onPortAdd", p);
- return p;
- };
-
- Op.prototype.hasDynamicPort = function ()
- {
- let i = 0;
- for (i = 0; i < this.portsIn.length; i++)
- {
- if (this.portsIn[i].type == CONSTANTS.OP.OP_PORT_TYPE_DYNAMIC) return true;
- if (this.portsIn[i].getName() == "dyn") return true;
- }
- for (i = 0; i < this.portsOut.length; i++)
- {
- if (this.portsOut[i].type == CONSTANTS.OP.OP_PORT_TYPE_DYNAMIC) return true;
- if (this.portsOut[i].getName() == "dyn") return true;
- }
-
- return false;
- };
-
- Op.prototype.addInPort = function (p)
- {
- if (!(p instanceof Port)) throw new Error("parameter is not a port!");
-
- p.direction = CONSTANTS.PORT.PORT_DIR_IN;
- p._op = this;
-
- this.portsIn.push(p);
- this.emitEvent("onPortAdd", p);
-
- return p;
- };
-
- /**
- * create a trigger input port
- * @function inTrigger
- * @instance
- * @memberof Op
- * @param {String} name
- * @return {Port} created port
- *
- */
- Op.prototype.inFunction = Op.prototype.inTrigger = function (name, v)
- {
- const p = this.addInPort(new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_FUNCTION));
- if (v !== undefined) p.set(v);
- return p;
- };
-
- /**
- * create multiple UI trigger buttons
- * @function inTriggerButton
- * @memberof Op
- * @instance
- * @param {String} name
- * @param {Array} names
- * @return {Port} created port
- */
- Op.prototype.inFunctionButton = Op.prototype.inTriggerButton = function (name, v)
- {
- const p = this.addInPort(
- new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_FUNCTION, {
- "display": "button"
- })
- );
- if (v !== undefined) p.set(v);
- return p;
- };
-
- Op.prototype.inFunctionButton = Op.prototype.inUiTriggerButtons = function (name, v)
- {
- const p = this.addInPort(
- new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_FUNCTION, {
- "display": "buttons"
- })
- );
- if (v !== undefined) p.set(v);
- return p;
- };
-
-
-
- /**
- * create a number value input port
- * @function inFloat
- * @memberof Op
- * @instance
- * @param {String} name
- * @param {Number} value
- * @return {Port} created port
- */
- Op.prototype.inValueFloat = Op.prototype.inValue = Op.prototype.inFloat = function (name, v)
- {
- const p = this.addInPort(new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE));
-
- p.setInitialValue(v);
-
- return p;
- };
-
- /**
- * create a boolean input port, displayed as a checkbox
- * @function inBool
- * @instance
- * @memberof Op
- * @param {String} name
- * @param {Boolean} value
- * @return {Port} created port
- */
- Op.prototype.inValueBool = Op.prototype.inBool = function (name, v)
- {
- const p = this.addInPort(
- new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_NUMBER, {
- "display": "bool"
- })
- );
-
- if (v === true)v = 1;
- if (v === false)v = 0;
- p.setInitialValue(v);
-
- return p;
- };
-
-
- Op.prototype.inMultiPort = function (name, type)
- {
- const p = new MultiPort(
- this,
- name,
- type,
- CONSTANTS.PORT.PORT_DIR_IN,
- {
- "addPort": true,
- "hidePort": true
- }
- );
- p.ignoreValueSerialize = true;
-
- this.addInPort(p);
- p.initPorts();
-
- return p;
- };
-
- Op.prototype.outMultiPort = function (name, type, uiAttribsPort = {})
- {
- const p = new MultiPort(
- this,
- name,
- type,
- CONSTANTS.PORT.PORT_DIR_OUT,
- {
- "display": "multiport",
- "hidePort": true
- },
- uiAttribsPort
- );
- p.ignoreValueSerialize = true;
-
- this.addOutPort(p);
- p.initPorts();
-
- return p;
- };
-
-
-
- Op.prototype.inValueString = function (name, v)
- {
- const p = this.addInPort(
- new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
- "type": "string"
- })
- );
- p.value = "";
-
- p.setInitialValue(v);
- return p;
- };
-
- /**
- * create a String value input port
- * @function inString
- * @instance
- * @memberof Op
- * @param {String} name
- * @param {String} value default value
- * @return {Port} created port
- */
- Op.prototype.inString = function (name, v)
- {
- const p = this.addInPort(
- new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_STRING, {
- "type": "string"
- })
- );
- v = v || "";
- // p.value = v;
-
- p.setInitialValue(v);
- return p;
- };
-
- /**
- * create a String value input port displayed as TextArea
- * @function inValueText
- * @instance
- * @memberof Op
- * @param {String} name
- * @param {String} value default value
- * @return {Port} created port
- */
- Op.prototype.inValueText = function (name, v)
- {
- const p = this.addInPort(
- new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
- "type": "string",
- "display": "text"
- })
- );
- p.value = "";
-
- p.setInitialValue(v);
- // if (v !== undefined)
- // {
- // p.set(v);
- // p.defaultValue = v;
- // }
- return p;
- };
-
- Op.prototype.inTextarea = function (name, v)
- {
- const p = this.addInPort(
- new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_STRING, {
- "type": "string",
- "display": "text"
- })
- );
- p.value = "";
- if (v !== undefined)
- {
- p.set(v);
- p.defaultValue = v;
- }
- return p;
- };
-
- /**
- * create a String value input port displayed as editor
- * @function inStringEditor
- * @instance
- * @memberof Op
- * @param {String} name
- * @param {String} value default value
- * @return {Port} created port
- */
- // new string
- Op.prototype.inStringEditor = function (name, v, syntax, hideFormatButton = true)
- {
- const p = this.addInPort(
- new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_STRING, {
- "type": "string",
- "display": "editor",
- "editShortcut": true,
- "editorSyntax": syntax,
- "hideFormatButton": hideFormatButton
- }));
-
- p.value = "";
- if (v !== undefined)
- {
- p.set(v);
- p.defaultValue = v;
- }
- return p;
- };
-
- // old
- Op.prototype.inValueEditor = function (name, v, syntax, hideFormatButton = true)
- {
- const p = this.addInPort(
- new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_NUMBER, {
- "type": "string",
- "display": "editor",
- "editorSyntax": syntax,
- "hideFormatButton": hideFormatButton
- })
- );
- p.value = "";
- if (v !== undefined)
- {
- p.set(v);
- p.defaultValue = v;
- }
- return p;
- };
-
- /**
- * create a string select box
- * @function inDropDown
- * @instance
- * @memberof Op
- * @param {String} name
- * @param {Array} values
- * @param {String} value default value
- * @return {Port} created port
- */
- Op.prototype.inValueSelect = Op.prototype.inDropDown = function (name, values, v, noindex)
- {
- let p = null;
- if (!noindex)
- {
- const indexPort = new Port(this, name + " index", CONSTANTS.OP.OP_PORT_TYPE_NUMBER, {
- "increment": "integer",
- "hideParam": true
- });
- const n = this.addInPort(indexPort);
-
- if (values) for (let i = 0; i < values.length; i++) values[i] = String(values[i]);
-
- const valuePort = new ValueSelectPort(
- this,
- name,
- CONSTANTS.OP.OP_PORT_TYPE_NUMBER,
- {
- "display": "dropdown",
- "hidePort": true,
- "type": "string",
- "values": values
- },
- n
- );
-
- valuePort.indexPort = indexPort;
-
- valuePort.on("change", (val, thePort) =>
- {
- if (!thePort.indexPort.isLinked() && thePort.uiAttribs.values)
- {
- const idx = thePort.uiAttribs.values.indexOf(val);
- if (idx > -1) thePort.indexPort.set(idx);
- }
- });
-
- indexPort.onLinkChanged = function ()
- {
- valuePort.setUiAttribs({ "greyout": indexPort.isLinked() });
- };
-
- p = this.addInPort(valuePort);
-
- if (v !== undefined)
- {
- p.set(v);
- const index = values.findIndex((item) => { return item == v; });
- n.setValue(index);
- p.defaultValue = v;
- n.defaultValue = index;
- }
- }
- else
- {
- const valuePort = new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
- "display": "dropdown",
- "hidePort": true,
- "type": "string",
- values
- });
-
- p = this.addInPort(valuePort);
- }
-
- return p;
- };
-
- /**
- * create a string switch box
- * @function inSwitch
- * @instance
- * @memberof Op
- * @param {String} name
- * @param {Array} values
- * @param {String} value default value
- * @return {Port} created port
- */
- Op.prototype.inSwitch = function (name, values, v, noindex)
- {
- let p = null;
- if (!noindex)
- {
- if (!v)v = values[0];
- const indexPort = new Port(this, name + " index", CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
- "increment": "integer",
- "values": values,
- "hideParam": true
- });
- const n = this.addInPort(indexPort);
-
- if (values) for (let i = 0; i < values.length; i++) values[i] = String(values[i]);
-
- const switchPort = new SwitchPort(
- this,
- name,
- CONSTANTS.OP.OP_PORT_TYPE_STRING,
- {
- "display": "switch",
- "hidePort": true,
- "type": "string",
- "values": values
- },
- n
- );
-
- switchPort.indexPort = indexPort;
-
- switchPort.on("change", (val, thePort) =>
- {
- if (!thePort.indexPort.isLinked() && thePort.uiAttribs.values)
- {
- const idx = thePort.uiAttribs.values.indexOf(val);
- if (idx > -1) thePort.indexPort.set(idx);
- }
- });
-
- indexPort.onLinkChanged = function ()
- {
- switchPort.setUiAttribs({ "greyout": indexPort.isLinked() });
- };
- p = this.addInPort(switchPort);
-
- if (v !== undefined)
- {
- p.set(v);
- const index = values.findIndex((item) => { return item == v; });
- n.setValue(index);
- p.defaultValue = v;
- n.defaultValue = index;
- }
- }
- else
- {
- const switchPort = new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_STRING, {
- "display": "switch",
- "hidePort": true,
- "type": "string",
- "values": values
- });
- p = this.addInPort(switchPort);
- }
-
- return p;
- };
-
- /**
- * create a integer input port
- * @function inInt
- * @instance
- * @memberof Op
- * @param {String} name
- * @param {number} value default value
- * @return {Port} created port
- */
- Op.prototype.inValueInt = Op.prototype.inInt = function (name, v)
- {
- // old
- const p = this.addInPort(
- new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
- "increment": "integer"
- })
- );
- if (v !== undefined)
- {
- p.set(v);
- p.defaultValue = v;
- }
- return p;
- };
-
- /**
- * create a file/URL input port
- * @function inURL
- * @instance
- * @memberof Op
- * @param {String} name
- * @return {Port} created port
- */
- Op.prototype.inFile = function (name, filter, v)
- {
- const p = this.addInPort(
- new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
- "display": "file",
- "type": "string",
- "filter": filter
- })
- );
- if (v !== undefined)
- {
- p.set(v);
- p.defaultValue = v;
- }
- return p;
- };
-
- Op.prototype.inUrl = function (name, filter, v)
- {
- const p = this.addInPort(
- new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_STRING, {
- "display": "file",
- "type": "string",
- "filter": filter
- })
- );
- if (v !== undefined)
- {
- p.set(v);
- p.defaultValue = v;
- }
- return p;
- };
-
- /**
- * create a texture input port
- * @function inTexture
- * @instance
- * @memberof Op
- * @param {String} name
- * @return {Port} created port
- */
- Op.prototype.inTexture = function (name, v)
- {
- const p = this.addInPort(
- new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_OBJECT, {
- "display": "texture",
- "objType": "texture",
- "preview": true
- })
- );
- p.ignoreValueSerialize = true;
- if (v !== undefined) p.set(v);
- return p;
- };
-
-
- /**
- * create a object input port
- * @function inObject
- * @instance
- * @memberof Op
- * @param {String} name
- * @return {Port} created port
- */
- Op.prototype.inObject = function (name, v, objType)
- {
- const p = this.addInPort(new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_OBJECT, { "objType": objType }));
- p.ignoreValueSerialize = true;
-
- if (v !== undefined) p.set(v);
- return p;
- };
-
- Op.prototype.inGradient = function (name, v)
- {
- const p = this.addInPort(
- new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
- "display": "gradient"
- // "hidePort": true
- })
- );
- if (v !== undefined) p.set(v);
- return p;
- };
-
-
- Op.prototype.getPortVisibleIndex = function (p)
- {
- let ports = this.portsIn;
- if (p.direction == CONSTANTS.PORT_DIR_OUT)ports = this.portsOut;
-
- let index = 0;
- for (let i = 0; i < ports.length; i++)
- {
- if (ports[i].uiAttribs.hidePort) continue;
- index++;
- if (ports[i] == p) return index;
- }
- };
-
- /**
- * create a array input port
- * @function inArray
- * @instance
- * @memberof Op
- * @param {String} name
- * @return {Port} created port
- */
- Op.prototype.inArray = function (name, v, stride)
- {
- if (!stride && CABLES.UTILS.isNumeric(v))stride = v;
-
- const p = this.addInPort(new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_ARRAY, { "stride": stride }));
-
- if (v !== undefined && (Array.isArray(v) || v == null)) p.set(v);
-
- // if (v !== undefined) p.set(v);
- return p;
- };
-
- /**
- * create a value slider input port
- * @function inFloatSlider
- * @instance
- * @memberof Op
- * @param {String} name
- * @param {number} defaultvalue
- * @param {number} min
- * @param {number} max
- * @return {Port} created port
- */
- Op.prototype.inValueSlider = Op.prototype.inFloatSlider = function (name, v, min, max)
- {
- const uiattribs = { "display": "range" };
-
- if (min != undefined && max != undefined)
- {
- uiattribs.min = min;
- uiattribs.max = max;
- }
-
- const p = this.addInPort(new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, uiattribs));
- if (v !== undefined)
- {
- p.set(v);
- p.defaultValue = v;
- }
- return p;
- };
-
- /**
- * create output trigger port
- * @function outTrigger
- * @instance
- * @memberof Op
- * @param {String} name
- * @return {Port} created port
- */
- Op.prototype.outFunction = Op.prototype.outTrigger = function (name, v)
- {
- // old
- const p = this.addOutPort(new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_FUNCTION));
- if (v !== undefined) p.set(v);
- return p;
- };
-
- /**
- * create output value port
- * @function outNumber
- * @instance
- * @memberof Op
- * @param {String} name
- * @param {number} default value
- * @return {Port} created port
- */
- Op.prototype.outValue = Op.prototype.outNumber = function (name, v)
- {
- // old
- const p = this.addOutPort(new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE));
- if (v !== undefined) p.set(v);
- return p;
- };
-
- /**
- * deprecated create output boolean port
- * @deprecated
- * @function outBool
- * @instance
- * @memberof Op
- * @param {String} name
- * @return {Port} created port
- */
- Op.prototype.outValueBool = Op.prototype.outBool = function (name, v)
- {
- // old: use outBoolNum
- const p = this.addOutPort(
- new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
- "display": "bool"
- })
- );
- if (v !== undefined) p.set(v);
- else p.set(0);
- return p;
- };
-
- /**
- * create output boolean port,value will be converted to 0 or 1
- * @function outBoolNum
- * @instance
- * @memberof Op
- * @param {String} name
- * @return {Port} created port
- */
- Op.prototype.outBoolNum = function (name, v)
- {
- const p = this.addOutPort(
- new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
- "display": "boolnum"
- })
- );
-
- p.set = function (b)
- {
- this.setValue(b ? 1 : 0);
- // this._log.log("bool set", b, this.get());
- }.bind(p);
-
- if (v !== undefined) p.set(v);
- else p.set(0);
- return p;
- };
-
- /**
- * create output string port
- * @function outString
- * @instance
- * @memberof Op
- * @param {String} name
- * @return {Port} created port
- */
- Op.prototype.outValueString = function (name, v)
- {
- const p = this.addOutPort(
- new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_VALUE, {
- "type": "string"
- })
- );
- if (v !== undefined) p.set(v);
- return p;
- };
- Op.prototype.outString = function (name, v)
- {
- const p = this.addOutPort(
- new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_STRING, {
- "type": "string"
- })
- );
- if (v !== undefined) p.set(v);
- else p.set("");
- return p;
- };
-
- /**
- * create output object port
- * @function outObject
- * @instance
- * @memberof Op
- * @param {String} name
- * @return {Port} created port
- */
- Op.prototype.outObject = function (name, v, objType)
- {
- const p = this.addOutPort(new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_OBJECT, { "objType": objType || null }));
- p.set(v || null);
- p.ignoreValueSerialize = true;
- return p;
- };
-
- /**
- * create output array port
- * @function outArray
- * @instance
- * @memberof Op
- * @param {String} name
- * @return {Port} created port
- */
- Op.prototype.outArray = function (name, v, stride)
- {
- if (!stride && CABLES.UTILS.isNumeric(v))stride = v;
- const p = this.addOutPort(new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_ARRAY, { "stride": stride }));
- if (v !== undefined && (Array.isArray(v) || v == null)) p.set(v);
-
- p.ignoreValueSerialize = true;
- return p;
- };
-
- /**
- * create output texture port
- * @function outTexture
- * @instance
- * @memberof Op
- * @param {String} name
- * @return {Port} created port
- */
- Op.prototype.outTexture = function (name, v)
- {
- const p = this.addOutPort(
- new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_OBJECT, {
- "preview": true,
- "objType": "texture",
- "display": "texture"
- })
- );
- if (v !== undefined) p.setRef(v || CGL.Texture.getEmptyTexture(this.patch.cgl));
-
- p.ignoreValueSerialize = true;
- return p;
- };
-
- Op.prototype.inDynamic = function (name, filter, options, v)
- {
- const p = new Port(this, name, CONSTANTS.OP.OP_PORT_TYPE_DYNAMIC, options);
-
- p.shouldLink = function (p1, p2)
- {
- if (filter && UTILS.isArray(filter))
- {
- for (let i = 0; i < filter.length; i++)
- {
- if (p1 == this && p2.type === filter[i]) return true;
- if (p2 == this && p1.type === filter[i]) return true;
- }
- return false; // types do not match
- }
- return true; // no filter set
- };
-
- this.addInPort(p);
- if (v !== undefined)
- {
- p.set(v);
- p.defaultValue = v;
- }
- return p;
- };
-
- Op.prototype.removeLinks = function ()
- {
- for (let i = 0; i < this.portsIn.length; i++) this.portsIn[i].removeLinks();
- for (let i = 0; i < this.portsOut.length; i++) this.portsOut[i].removeLinks();
- };
-
- Op.prototype.getSerialized = function ()
- {
- const opObj = {};
-
- if (this.opId) opObj.opId = this.opId;
- if (this.patch.storeObjNames) opObj.objName = this.objName;
-
- opObj.id = this.id;
- opObj.uiAttribs = JSON.parse(JSON.stringify(this.uiAttribs)) || {};
-
- if (this.storage && Object.keys(this.storage).length > 0) opObj.storage = JSON.parse(JSON.stringify(this.storage));
- if (this.uiAttribs.hasOwnProperty("working") && this.uiAttribs.working == true) delete this.uiAttribs.working;
- if (opObj.uiAttribs.hasOwnProperty("uierrors")) delete opObj.uiAttribs.uierrors;
-
- if (opObj.uiAttribs.title === "") delete opObj.uiAttribs.title;
- if (opObj.uiAttribs.color === null) delete opObj.uiAttribs.color;
- if (opObj.uiAttribs.comment === null) delete opObj.uiAttribs.comment;
-
- if (opObj.uiAttribs.title == this._shortOpName ||
- (this.uiAttribs.title || "").toLowerCase() == this._shortOpName.toLowerCase()) delete opObj.uiAttribs.title;
-
- opObj.portsIn = [];
- opObj.portsOut = [];
-
- for (let i = 0; i < this.portsIn.length; i++)
- {
- const s = this.portsIn[i].getSerialized();
- if (s) opObj.portsIn.push(s);
- }
-
- for (let i = 0; i < this.portsOut.length; i++)
- {
- const s = this.portsOut[i].getSerialized();
- if (s) opObj.portsOut.push(s);
- }
-
- if (opObj.portsIn.length == 0) delete opObj.portsIn;
- if (opObj.portsOut.length == 0) delete opObj.portsOut;
- cleanJson(opObj);
-
- return opObj;
- };
-
- Op.prototype.getFirstOutPortByType = function (type)
- {
- for (const ipo in this.portsOut) if (this.portsOut[ipo].type == type) return this.portsOut[ipo];
- };
-
- Op.prototype.getFirstInPortByType = function (type)
- {
- for (const ipo in this.portsIn) if (this.portsIn[ipo].type == type) return this.portsIn[ipo];
- };
-
- /**
- * return port by the name portName
- * @function getPort
- * @instance
- * @memberof Op
- * @param {String} portName
- * @return {Port}
- */
- Op.prototype.getPort = Op.prototype.getPortByName = function (name, lowerCase)
- {
- if (lowerCase)
- {
- for (let ipi = 0; ipi < this.portsIn.length; ipi++)
- if (this.portsIn[ipi].getName().toLowerCase() == name || this.portsIn[ipi].id.toLowerCase() == name)
- return this.portsIn[ipi];
-
- for (let ipo = 0; ipo < this.portsOut.length; ipo++)
- if (this.portsOut[ipo].getName().toLowerCase() == name || this.portsOut[ipo].id.toLowerCase() == name)
- return this.portsOut[ipo];
- }
- else
- {
- for (let ipi = 0; ipi < this.portsIn.length; ipi++)
- if (this.portsIn[ipi].getName() == name || this.portsIn[ipi].id == name)
- return this.portsIn[ipi];
-
- for (let ipo = 0; ipo < this.portsOut.length; ipo++)
- if (this.portsOut[ipo].getName() == name || this.portsOut[ipo].id == name)
- return this.portsOut[ipo];
- }
- };
-
-
- /**
- * return port by the name id
- * @function getPortById
- * @instance
- * @memberof Op
- * @param {String} id
- * @return {Port}
- */
- Op.prototype.getPortById = function (id)
- {
- for (let ipi = 0; ipi < this.portsIn.length; ipi++) if (this.portsIn[ipi].id == id) return this.portsIn[ipi];
- for (let ipo = 0; ipo < this.portsOut.length; ipo++) if (this.portsOut[ipo].id == id) return this.portsOut[ipo];
- };
-
- Op.prototype.updateAnims = function ()
- {
- if (this._hasAnimPort)
- for (let i = 0; i < this.portsIn.length; i++) this.portsIn[i].updateAnim();
- };
-
- Op.prototype.log = function ()
- {
- this._log.log(...arguments);
- };
-
- Op.prototype.error = Op.prototype.logError = function ()
- {
- // if (!this)
- // {
- // this._log.error("no this...!!!");
- // debugger;
- // return;
- // }
- // const initiator = "op " + this.objName;
- // if (CABLES.UI && !CABLES.UI.logFilter.filterLog({ "initiator": initiator, "opInstId": this.id, "level": 2 }, ...arguments)) return;
-
- // // if (this.patch.silent) return;
- // const args = ["[op " + CABLES.getShortOpName(this.objName) + "]"];
- // args.push.apply(args, arguments);
- // Function.prototype.apply.apply(this._log.error, [console, args]);// eslint-disable-line
- // if (window.gui) window.gui.emitEvent("opLogEvent", this.objName, "error", arguments);
- this._log.error(...arguments);
- };
-
- Op.prototype.warn = Op.prototype.logWarn = function ()
- {
- this._log.warn(...arguments);
-
- // const initiator = "op " + this.objName;
- // if (CABLES.UI && !CABLES.UI.logFilter.filterLog({ "initiator": initiator, "opInstId": this.id, "level": 1 }, ...arguments)) return;
-
- // // if (this.patch.silent) return;
- // const args = ["[op " + CABLES.getShortOpName(this.objName) + "]"];
- // args.push.apply(args, arguments);
- // Function.prototype.apply.apply(this._log.warn, [console, args]);// eslint-disable-line
- };
-
- Op.prototype.verbose = Op.prototype.logVerbose = function ()
- {
- // const initiator = "op " + CABLES.getShortOpName(this.objName);
- // if (CABLES.UI && !CABLES.UI.logFilter.filterLog({ "initiator": initiator, "opInstId": this.id, "level": 0 }, ...arguments)) return;
-
- // if (!CABLES.UI && this.patch.silent) return;
-
- // const args = ["[" + initiator + "]"];
- // args.push.apply(args, arguments);
- // Function.prototype.apply.apply(this._log.info, [console, args]);// eslint-disable-line
- this._log.verbose(...arguments);
- };
-
-
- Op.prototype.profile = function (enable)
- {
- for (let ipi = 0; ipi < this.portsIn.length; ipi++)
- {
- this.portsIn[ipi]._onTriggered = this.portsIn[ipi]._onTriggeredProfiling;
- this.portsIn[ipi].set = this.portsIn[ipi]._onSetProfiling;
- }
- };
-
- Op.prototype.findParent = function (objName)
- {
- for (let ipi = 0; ipi < this.portsIn.length; ipi++)
- {
- if (this.portsIn[ipi].isLinked())
- {
- if (this.portsIn[ipi].links[0].portOut.parent.objName == objName)
- return this.portsIn[ipi].links[0].portOut.parent;
-
- let found = null;
- found = this.portsIn[ipi].links[0].portOut.parent.findParent(objName);
- if (found) return found;
- }
- }
- return null;
- };
-
-
- // todo: check instancing stuff?
- Op.prototype.cleanUp = function ()
- {
- if (this._instances)
- {
- for (let i = 0; i < this._instances.length; i++)
- {
- if (this._instances[i].onDelete) this._instances[i].onDelete();
- }
-
-
- this._instances.length = 0;
- }
- for (let i = 0; i < this.portsIn.length; i++)
- {
- this.portsIn[i].setAnimated(false);
- }
-
- if (this.onAnimFrame) this.patch.removeOnAnimFrame(this);
- };
-
- // todo: check instancing stuff?
- Op.prototype.instanced = function (triggerPort)
- {
- return false;
- // this._log.log("instanced", this.patch.instancing.numCycles());
- // if (this.patch.instancing.numCycles() === 0) return false;
-
-
- // let i = 0;
- // let ipi = 0;
- // if (!this._instances || this._instances.length != this.patch.instancing.numCycles())
- // {
- // if (!this._instances) this._instances = [];
- // this._.log("creating instances of ", this.objName, this.patch.instancing.numCycles(), this._instances.length);
- // this._instances.length = this.patch.instancing.numCycles();
-
- // for (i = 0; i < this._instances.length; i++)
- // {
- // this._instances[i] = this.patch.createOp(this.objName, true);
- // this._instances[i].instanced = function ()
- // {
- // return false;
- // };
- // this._instances[i].uiAttr(this.uiAttribs);
-
- // for (let ipo = 0; ipo < this.portsOut.length; ipo++)
- // {
- // if (this.portsOut[ipo].type == CONSTANTS.OP.OP_PORT_TYPE_FUNCTION)
- // {
- // this._instances[i].getPortByName(this.portsOut[ipo].name).trigger = this.portsOut[ipo].trigger.bind(this.portsOut[ipo]);
- // }
- // }
- // }
-
- // for (ipi = 0; ipi < this.portsIn.length; ipi++)
- // {
- // this.portsIn[ipi].onChange = null;
- // this.portsIn[ipi].onValueChanged = null;
- // }
- // }
-
- // const theTriggerPort = null;
- // for (ipi = 0; ipi < this.portsIn.length; ipi++)
- // {
- // if (
- // this.portsIn[ipi].type == CONSTANTS.OP.OP_PORT_TYPE_VALUE ||
- // this.portsIn[ipi].type == CONSTANTS.OP.OP_PORT_TYPE_ARRAY
- // )
- // {
- // this._instances[this.patch.instancing.index()].portsIn[ipi].set(this.portsIn[ipi].get());
- // }
- // if (this.portsIn[ipi].type == CONSTANTS.OP.OP_PORT_TYPE_FUNCTION)
- // {
- // // if(this._instances[ this.patch.instancing.index() ].portsIn[ipi].name==triggerPort.name)
- // // theTriggerPort=this._instances[ this.patch.instancing.index() ].portsIn[ipi];
- // }
- // }
-
- // if (theTriggerPort) theTriggerPort.onTriggered();
-
- // for (ipi = 0; ipi < this.portsOut.length; ipi++)
- // {
- // if (this.portsOut[ipi].type == CONSTANTS.OP.OP_PORT_TYPE_VALUE)
- // {
- // this.portsOut[ipi].set(this._instances[this.patch.instancing.index()].portsOut[ipi].get());
- // }
- // }
-
- // return true;
- };
-
- // todo: check instancing stuff?
- Op.prototype.initInstancable = function ()
- {
- // if(this.isInstanced)
- // {
- // this._log.log('cancel instancing');
- // return;
- // }
- // this._instances=[];
- // for(var ipi=0;ipi<this.portsIn.length;ipi++)
- // {
- // if(this.portsIn[ipi].type==CONSTANTS.OP.OP_PORT_TYPE_VALUE)
- // {
- //
- // }
- // if(this.portsIn[ipi].type==CONSTANTS.OP.OP_PORT_TYPE_FUNCTION)
- // {
- // // var piIndex=ipi;
- // this.portsIn[ipi].onTriggered=function(piIndex)
- // {
- //
- // var i=0;
- // // this._log.log('trigger',this._instances.length);
- //
- // }.bind(this,ipi );
- //
- // }
- // };
- // this._instances=null;
- };
-
- Op.prototype.setValues = function (obj)
- {
- for (const i in obj)
- {
- const port = this.getPortByName(i);
- if (port) port.set(obj[i]);
- else this._log.warn("op.setValues: port not found:", i);
- }
- };
-
- /**
- * return true if op has this error message id
- * @function hasUiError
- * @instance
- * @memberof Op
- * @param {id} error id
- * @returns {Boolean} - has id
- */
- Op.prototype.hasUiError = function (id)
- {
- return this._uiErrors.hasOwnProperty(id) && this._uiErrors[id];
- };
-
- /**
- * show op error message - set message to null to remove error message
- * @function setUiError
- * @instance
- * @memberof Op
- * @param {id} error id
- * @param {txt} text message
- * @param {level} level
- */
- Op.prototype.setUiError = function (id, txt, level)
- {
- // overwritten in ui: core_extend_op
- };
-
- // todo: remove
- Op.prototype.setError = function (id, txt)
- {
- this._log.warn("old error message op.error() - use op.setUiError()");
- };
-
-
- /**
- * enable/disable op
- * @function
- * @instance
- * @memberof Op
- * @param {boolean}
- */
- Op.prototype.setEnabled = function (b)
- {
- this.enabled = b;
- this.emitEvent("onEnabledChange", b);
- };
-
- /**
- * organize ports into a group
- * @function
- * @instance
- * @memberof Op
- * @param {String} name
- * @param {Array} ports
- */
- Op.prototype.setPortGroup = function (name, ports)
- {
- for (let i = 0; i < ports.length; i++)
- {
- if (ports[i])
- if (ports[i].setUiAttribs) ports[i].setUiAttribs({ "group": name });
- else
- {
- this._log.error("setPortGroup: invalid port!");
- }
- }
- };
-
- /**
- * visually indicate ports that they are coordinate inputs
- * @function
- * @instance
- * @memberof Op
- * @param {Port} portX
- * @param {Port} portY
- * @param {Port} portZ
- */
- Op.prototype.setUiAxisPorts = function (px, py, pz)
- {
- if (px) px.setUiAttribs({ "axis": "X" });
- if (py) py.setUiAttribs({ "axis": "Y" });
- if (pz) pz.setUiAttribs({ "axis": "Z" });
- };
-
- /**
- * remove port from op
- * @function removePort
- * @instance
- * @memberof Op
- * @param {Port} port to remove
- */
- Op.prototype.removePort = function (port)
- {
- for (let ipi = 0; ipi < this.portsIn.length; ipi++)
- {
- if (this.portsIn[ipi] == port)
- {
- this.portsIn.splice(ipi, 1);
- this.emitEvent("onUiAttribsChange", {});
- this.emitEvent("onPortRemoved", {});
- return;
- }
- }
- for (let ipi = 0; ipi < this.portsOut.length; ipi++)
- {
- if (this.portsOut[ipi] == port)
- {
- this.portsOut.splice(ipi, 1);
- this.emitEvent("onUiAttribsChange", {});
- this.emitEvent("onPortRemoved", {});
- return;
- }
- }
- };
-
- Op.prototype._checkLinksNeededToWork = function () {};
-
- /**
- * show a warning of this op is not a child of parentOpName
- * @function
- * @instance
- * @memberof Op
- * @param {String} parentOpName
- */
- Op.prototype.toWorkNeedsParent = function (parentOpName)
- {
- this._linkTimeRules.needsParentOp = parentOpName;
- };
-
- // /**
- // * show a warning of this op is a child of parentOpName
- // * @function
- // * @instance
- // * @memberof Op
- // * @param {String} parentOpName
- // */
- Op.prototype.toWorkShouldNotBeChild = function (parentOpName, type)
- {
- if (!this.patch.isEditorMode()) return;
- this._linkTimeRules.forbiddenParent = parentOpName;
- if (type != undefined) this._linkTimeRules.forbiddenParentType = type;
- };
-
-
- /**
- * show a small X to indicate op is not working when given ports are not linked
- * @function
- * @instance
- * @memberof Op
- * @param {Port} port1
- * @param {Port} port2
- * @param {Port} port3
- */
- Op.prototype.toWorkPortsNeedToBeLinked = function ()
- {
- if (!this.patch.isEditorMode()) return;
- for (let i = 0; i < arguments.length; i++)
- if (this._linkTimeRules.needsLinkedToWork.indexOf(arguments[i]) == -1) this._linkTimeRules.needsLinkedToWork.push(arguments[i]);
- };
- Op.prototype.toWorkPortsNeedToBeLinkedReset = function ()
- {
- if (!this.patch.isEditorMode()) return;
- this._linkTimeRules.needsLinkedToWork.length = 0;
- if (this.checkLinkTimeWarnings) this.checkLinkTimeWarnings();
- };
-
- Op.prototype.initVarPorts = function ()
- {
- for (let i = 0; i < this.portsIn.length; i++)
- {
- if (this.portsIn[i].getVariableName()) this.portsIn[i].setVariable(this.portsIn[i].getVariableName());
- }
- };
-
- /**
- * refresh op parameters, if current op is selected
- * @function
- * @instance
- * @memberof Op
- */
- Op.prototype.refreshParams = function ()
- {
- if (this.patch && this.patch.isEditorMode() && this.isCurrentUiOp())
- {
- gui.opParams.show(this);
- }
- };
-
- /**
- * Returns true if op is selected and parameter are shown in the editor, can only return true if in editor/ui
- * @function isCurrentUiOp
- * @instance
- * @memberof Op
- * @returns {Boolean} - is current ui op
- */
- Op.prototype.isCurrentUiOp = function ()
- {
- if (this.patch.isEditorMode()) return gui.patchView.isCurrentOp(this);
- };
-
- /**
- * Implement to render 2d canvas based graphics from in an op
- * @function renderVizLayer
- * @instance
- * @memberof Op
- * @param {ctx} context of canvas 2d
- * @param {Object} layer info
- * @param {number} layer.x x position on canvas
- * @param {number} layer.y y position on canvas
- * @param {number} layer.width width of canvas
- * @param {number} layer.height height of canvas
- * @param {number} layer.scale current scaling of patchfield view
- */
- Op.prototype.renderVizLayer = null; // optionaly defined in op instance
- }
-
- export { Op };