var w = /* @__PURE__ */ ((t) => (t[t.UP = 1] = "UP", t[t.DOWN = 2] = "DOWN", t[t.LEFT = 3] = "LEFT", t[t.RIGHT = 4] = "RIGHT", t[t.CENTER = 5] = "CENTER", t))(w || {}), Z = /* @__PURE__ */ ((t) => (t[t.ALWAYS = 0] = "ALWAYS", t[t.ON_EVENT = 1] = "ON_EVENT", t[t.NEVER = 2] = "NEVER", t[t.ON_TRIGGER = 3] = "ON_TRIGGER", t[t.ON_REQUEST = 4] = "ON_REQUEST", t))(Z || {}); const re = ["Always", "On Event", "Never", "On Trigger"], Oe = ["#666", "#422", "#333", "#224", "#626"]; var k = /* @__PURE__ */ ((t) => (t[t.DEFAULT = 0] = "DEFAULT", t[t.BOX_SHAPE = 1] = "BOX_SHAPE", t[t.ROUND_SHAPE = 2] = "ROUND_SHAPE", t[t.CIRCLE_SHAPE = 3] = "CIRCLE_SHAPE", t[t.CARD_SHAPE = 4] = "CARD_SHAPE", t[t.ARROW_SHAPE = 5] = "ARROW_SHAPE", t[t.GRID_SHAPE = 6] = "GRID_SHAPE", t))(k || {}); const Ie = ["default", "box", "round", "circle", "card", "arrow", "square"]; var W = /* @__PURE__ */ ((t) => (t[t.INPUT = 0] = "INPUT", t[t.OUTPUT = 1] = "OUTPUT", t))(W || {}), de = /* @__PURE__ */ ((t) => (t[t.STRAIGHT_LINK = 0] = "STRAIGHT_LINK", t[t.LINEAR_LINK = 1] = "LINEAR_LINK", t[t.SPLINE_LINK = 2] = "SPLINE_LINK", t))(de || {}); const Xe = ["Straight", "Linear", "Spline"]; var se = /* @__PURE__ */ ((t) => (t[t.NORMAL_TITLE = 0] = "NORMAL_TITLE", t[t.NO_TITLE = 1] = "NO_TITLE", t[t.TRANSPARENT_TITLE = 2] = "TRANSPARENT_TITLE", t[t.AUTOHIDE_TITLE = 3] = "AUTOHIDE_TITLE", t))(se || {}), I = /* @__PURE__ */ ((t) => (t[t.EVENT = -2] = "EVENT", t[t.ACTION = -1] = "ACTION", t[t.DEFAULT = 0] = "DEFAULT", t))(I || {}); const Ae = ["*", "array", "object", "number", "string", "enum", "boolean", "table"]; var ue = /* @__PURE__ */ ((t) => (t.VERTICAL_LAYOUT = "vertical", t.HORIZONTAL_LAYOUT = "horizontal", t))(ue || {}); function Te(t, e, i) { return e > t ? e : i < t ? i : t; } function ve(t, e) { return t.reduce((i, n) => { const s = e(n); return i[s] = n, i; }, {}); } function Ce(t, e) { return e in t ? t[e] : null; } function ye(t, e) { return e in t.constructor ? t.constructor[e] : null; } function Ge(t, e) { if (t.target !== e) return; let i = t.clientX - parseInt(window.getComputedStyle(e).left), n = t.clientY - parseInt(window.getComputedStyle(e).top); const s = (o) => { if (o.buttons === 0) { r(); return; } e.style.top = o.clientY - n + "px", e.style.left = o.clientX - i + "px"; }, r = () => { window.removeEventListener("mousemove", s), window.removeEventListener("mouseup", r); }; window.addEventListener("mousemove", s), window.addEventListener("mouseup", r); } function Ee(t) { return t.addEventListener("mousedown", (e) => Ge(e, t)), t.classList.add("draggable"), t; } function J(t) { return t === I.EVENT ? "Event" : t === I.ACTION ? "Action" : t === I.DEFAULT ? "Default" : t; } function Se(t) { return t === I.EVENT || t === I.ACTION || t === I.DEFAULT || typeof t == "string"; } const S = class { /** Register a node class so it can be listed when the user wants to create a new one */ static registerNodeType(t) { S.debug && console.log("Node registered: " + t.type); const e = t.name, i = t.type; if (!i) throw console.error(t), new Error("Config has no type: " + t); if (S.debug && console.debug(e, i), t.category == null || t.category === "") { const s = i.lastIndexOf("/"); t.category = i.substring(0, s); } t.title || (t.title = e); const n = S.registered_node_types[i]; if (n && console.warn("replacing node type: " + i), t.supported_extensions) for (let s in t.supported_extensions) { const r = t.supported_extensions[s]; r && r.constructor === String && (S.node_types_by_file_extension[r.toLowerCase()] = t); } t.class.__LITEGRAPH_TYPE__ = i, S.registered_node_types[i] = t, t.class.name && (S.Nodes[e] = t), S.onNodeTypeRegistered && S.onNodeTypeRegistered(i, t), n && S.onNodeTypeReplaced && S.onNodeTypeReplaced(i, t, n); } /** removes a node type from the system */ static unregisterNodeType(t) { let e; if (typeof t == "string" ? e = S.registered_node_types[t] : e = t, !e) throw "node type not found: " + t; delete S.registered_node_types[e.type], e.constructor.name && delete S.Nodes[e.constructor.name]; } /** * Save a slot type and his node * @method registerSlotType * @param {String|Object} type name of the node or the node constructor itself * @param {String} slot_type name of the slot type (variable type), eg. string, number, array, boolean, .. */ static registerNodeAndSlotType(t, e, i = !1) { let n; if (typeof t == "string" ? n = S.registered_node_types[t] : "type" in t ? n = S.registered_node_types[t.type] : n = t, !n) throw new Error("Node not registered!" + t); var s = n.class.__litegraph_type__; if (typeof e == "string") var r = e.split(","); else if (e == I.EVENT || e == I.ACTION) var r = ["_event_"]; else var r = ["*"]; for (var o = 0; o < r.length; ++o) { var a = r[o]; a === "" && (a = "*"); var l = i ? "registered_slot_out_types" : "registered_slot_in_types"; typeof this[l][a] > "u" && (this[l][a] = { nodes: [] }), this[l][a].nodes.push(s), a !== "_event_" && a !== "*" && (i ? S.slot_types_out.includes(a.toLowerCase()) || (S.slot_types_out.push(a.toLowerCase()), S.slot_types_out.sort()) : S.slot_types_in.includes(a.toLowerCase()) || (S.slot_types_in.push(a.toLowerCase()), S.slot_types_in.sort())); } } /** Removes all previously registered node's types. */ static clearRegisteredTypes() { S.registered_node_types = {}, S.node_types_by_file_extension = {}, S.Nodes = {}, S.searchbox_extras = {}; } /** * Create a new node type by passing a function, it wraps it with a proper class and generates inputs according to the parameters of the function. * Useful to wrap simple methods that do not require properties, and that only process some input to generate an output. * @param name node name with namespace (p.e.: 'math/sum') * @param func * @param param_types an array containing the type of every parameter, otherwise parameters will accept any type * @param return_type string with the return type, otherwise it will be generic * @param properties properties to be configurable */ // static wrapFunctionAsNode( // name: string, // func: (...args: any[]) => any, // param_types?: string[], // return_type?: string, // properties?: object // ): void { // var params = Array(func.length); // var code = ""; // var names = LiteGraph.getParameterNames(func); // for (var i = 0; i < names.length; ++i) { // code += // "this.addInput('" + // names[i] + // "'," + // (param_types && param_types[i] // ? "'" + param_types[i] + "'" // : "0") + // ");\n"; // } // code += // "this.addOutput('out'," + // (return_type ? "'" + return_type + "'" : 0) + // ");\n"; // if (properties) { // code += // "this.properties = " + JSON.stringify(properties) + ";\n"; // } // var classobj = Function(code) as any; // classobj.title = name.split("/").pop(); // classobj.desc = "Generated from " + func.name; // classobj.prototype.onExecute = function onExecute() { // for (var i = 0; i < params.length; ++i) { // params[i] = this.getInputData(i); // } // var r = func.apply(this, params); // this.setOutputData(0, r); // }; // LiteGraph.registerNodeType(name, classobj); // } /** * Adds this method to all node types, existing and to be created * (You can add it to LGraphNode.prototype but then existing node types wont have it) */ // static addNodeMethod(name: string, func: (...args: any[]) => any): void { // LGraphNode.prototype[name] = func; // for (var i in LiteGraph.registered_node_types) { // var type = LiteGraph.registered_node_types[i]; // if (type.prototype[name]) { // type.prototype["_" + name] = type.prototype[name]; // } //keep old in case of replacing // type.prototype[name] = func; // } // } /** * Create a node of a given type with a name. The node is not attached to any graph yet. * @param type full name of the node class. p.e. "math/sin" * @param name a name to distinguish from other nodes * @param options to set options */ static createNode(t, e, i = {}) { let n = null, s; if (typeof t == "string") s = t; else if (s = t.__LITEGRAPH_TYPE__, !s) throw console.error(t), "Node was not registered yet!"; if (n = S.registered_node_types[s], !n) return console.warn( 'GraphNode type "' + t + '" not registered.' ), null; e = e || n.title || s; var r = null; const o = i.constructorArgs || []; if (S.catch_exceptions) try { r = new n.class(e, ...o); } catch (p) { return console.error("Error creating node!", p), null; } else r = new n.class(e, ...o); if (r.class = n.class, r.type = s, !r.title && e && (r.title = e), r.properties || (r.properties = {}), r.properties_info || (r.properties_info = []), r.flags || (r.flags = {}), r.size || (r.size = r.computeSize()), r.pos || (r.pos = [S.DEFAULT_POSITION[0], S.DEFAULT_POSITION[1]]), r.mode || (r.mode = Z.ALWAYS), i.instanceProps) for (var a in i.instanceProps) r[a] = i.instanceProps[a]; const l = Ce(n.class, "propertyLayout"); if (l) { S.debug && console.debug("Found property layout!", l); for (const p of l) { const { name: f, defaultValue: c, type: v, options: g } = p; r.addProperty(f, c, v, g); } } const h = Ce(n.class, "slotLayout"); if (h) { if (S.debug && console.debug("Found slot layout!", h), h.inputs) for (const p of h.inputs) { const { name: f, type: c, options: v } = p; r.addInput(f, c, v); } if (h.outputs) for (const p of h.outputs) { const { name: f, type: c, options: v } = p; r.addOutput(f, c, v); } } return r.onNodeCreated && r.onNodeCreated(), r; } /** * Returns a registered node type with a given name * @param type full name of the node class. p.e. "math/sin" */ static getNodeType(t) { return S.registered_node_types[t]; } /** * Returns a list of node types matching one category * @method getNodeTypesInCategory * @param {String} category category name * @param {String} filter only nodes with ctor.filter equal can be shown * @return {Array} array with all the node classes */ static getNodeTypesInCategory(t, e) { var i = []; for (var n in S.registered_node_types) { var s = S.registered_node_types[n]; s.filter == e && (t == "" ? s.category == null && i.push(s) : s.category == t && i.push(s)); } return S.auto_sort_node_types && i.sort(function(r, o) { return r.title.localeCompare(o.title); }), i; } /** * Returns a list with all the node type categories * @method getNodeTypesCategories * @param {String} filter only nodes with ctor.filter equal can be shown * @return {Array} array with all the names of the categories */ static getNodeTypesCategories(t) { var e = { "": 1 }; for (var i in S.registered_node_types) { var n = S.registered_node_types[i]; if (n.category && !n.hide_in_node_lists) { if (n.filter != t) continue; e[n.category] = 1; } } var s = []; for (var i in e) s.push(i); return S.auto_sort_node_types ? s.sort() : s; } /** debug purposes: reloads all the js scripts that matches a wildcard */ static reloadNodes(t) { for (var e = document.getElementsByTagName("script"), i = [], n = 0; n < e.length; n++) i.push(e[n]); var s = document.getElementsByTagName("head")[0]; t = document.location.href + t; for (var n = 0; n < i.length; n++) { var r = i[n].src; if (!(!r || r.substr(0, t.length) != t)) try { S.debug && console.log("Reloading: " + r); var o = document.createElement("script"); o.type = "text/javascript", o.src = r, s.appendChild(o), s.removeChild(i[n]); } catch (l) { if (S.throw_errors) throw l; S.debug && console.log("Error while reloading " + r); } } S.debug && console.log("Nodes reloaded"); } // TODO move //separated just to improve if it doesn't work static cloneObject(t, e) { if (t == null) return null; var i = JSON.parse(JSON.stringify(t)); if (!e) return i; for (var n in i) e[n] = i[n]; return e; } /** * Returns if the types of two slots are compatible (taking into account wildcards, etc) * @method isValidConnection * @param {String} type_a * @param {String} type_b * @return {Boolean} true if they can be connected */ static isValidConnection(t, e) { if ((t == "" || t === "*") && (t = I.DEFAULT), (e == "" || e === "*") && (e = I.DEFAULT), !t || !e || t == e || t == I.EVENT && e == I.ACTION || t == I.ACTION && e == I.EVENT) return !0; if (t = String(t), e = String(e), t = t.toLowerCase(), e = e.toLowerCase(), t.indexOf(",") == -1 && e.indexOf(",") == -1) return t == e; for (var i = t.split(","), n = e.split(","), s = 0; s < i.length; ++s) for (var r = 0; r < n.length; ++r) if (this.isValidConnection(i[s], n[r])) return !0; return !1; } static getTime() { return Date.now(); } // static LLink: typeof LLink; // static LGraph: typeof LGraph; // static DragAndScale: typeof DragAndScale; static compareObjects(t, e) { for (var i in t) if (t[i] != e[i]) return !1; return !0; } static distance(t, e) { return Math.sqrt( (e[0] - t[0]) * (e[0] - t[0]) + (e[1] - t[1]) * (e[1] - t[1]) ); } static colorToString(t) { return "rgba(" + Math.round(t[0] * 255).toFixed() + "," + Math.round(t[1] * 255).toFixed() + "," + Math.round(t[2] * 255).toFixed() + "," + (t.length == 4 ? t[3].toFixed(2) : "1.0") + ")"; } static isInsideRectangle(t, e, i, n, s, r) { return i < t && i + s > t && n < e && n + r > e; } // [minx,miny,maxx,maxy] static growBounding(t, e, i) { return e < t[0] ? t[0] = e : e > t[2] && (t[2] = e), i < t[1] ? t[1] = i : i > t[3] && (t[3] = i), t; } static isInsideBounding(t, e) { return !(t[0] < e[0][0] || t[1] < e[0][1] || t[0] > e[1][0] || t[1] > e[1][1]); } // bounding overlap, format: [ startx, starty, width, height ] static overlapBounding(t, e) { var i = t[0] + t[2], n = t[1] + t[3], s = e[0] + e[2], r = e[1] + e[3]; return !(t[0] > s || t[1] > r || i < e[0] || n < e[1]); } // Convert a hex value to its decimal value - the inputted hex must be in the // format of a hex triplet - the kind we use for HTML colours. The function // will return an array with three values. static hex2num(t) { t.charAt(0) == "#" && (t = t.slice(1)), t = t.toUpperCase(); var e = "0123456789ABCDEF"; let i; for (var n = 0, s, r, o = 0; o < 6; o += 2) s = e.indexOf(t.charAt(o)), r = e.indexOf(t.charAt(o + 1)), i[n] = s * 16 + r, n++; return i; } //Give a array with three values as the argument and the function will return // the corresponding hex triplet. static num2hex(t) { for (var e = "0123456789ABCDEF", i = "#", n, s, r = 0; r < 3; r++) n = t[r] / 16, s = t[r] % 16, i += e.charAt(n) + e.charAt(s); return i; } // ContextMenu: typeof ContextMenu; // static extendClass(target: A, origin: B): A & B; // static getParameterNames(func: string | Function): string[]; /* helper for interaction: pointer, touch, mouse Listeners used by LGraphCanvas DragAndScale ContextMenu*/ static pointerListenerAdd(t, e, i, n = !1) { if (!(!t || !t.addEventListener || !e || typeof i != "function")) { var s = S.pointerevents_method, r = e; if (s == "pointer" && !window.PointerEvent) switch (console.warn("sMethod=='pointer' && !window.PointerEvent"), console.log("Converting pointer[" + r + "] : down move up cancel enter TO touchstart touchmove touchend, etc .."), r) { case "down": { s = "touch", r = "start"; break; } case "move": { s = "touch"; break; } case "up": { s = "touch", r = "end"; break; } case "cancel": { s = "touch"; break; } case "enter": { console.log("debug: Should I send a move event?"); break; } default: console.warn("PointerEvent not available in this browser ? The event " + r + " would not be called"); } switch (r) { case "down": case "up": case "move": case "over": case "out": case "enter": t.addEventListener(s + r, i, n); case "leave": case "cancel": case "gotpointercapture": case "lostpointercapture": if (s != "mouse") return t.addEventListener(s + r, i, n); default: return t.addEventListener(r, i, n); } } } static pointerListenerRemove(t, e, i, n = !1) { if (!(!t || !t.removeEventListener || !e || typeof i != "function")) switch (e) { case "down": case "up": case "move": case "over": case "out": case "enter": (S.pointerevents_method == "pointer" || S.pointerevents_method == "mouse") && t.removeEventListener(S.pointerevents_method + e, i, n); case "leave": case "cancel": case "gotpointercapture": case "lostpointercapture": if (S.pointerevents_method == "pointer") return t.removeEventListener(S.pointerevents_method + e, i, n); default: return t.removeEventListener(e, i, n); } } }; let u = S; u.VERSION = 10; u.CANVAS_GRID_SIZE = 10; u.NODE_TITLE_HEIGHT = 20; u.NODE_TITLE_TEXT_Y = 15; u.NODE_SLOT_HEIGHT = 20; u.NODE_WIDGET_HEIGHT = 20; u.NODE_WIDTH = 140; u.NODE_MIN_WIDTH = 50; u.NODE_COLLAPSED_RADIUS = 10; u.NODE_COLLAPSED_WIDTH = 80; u.NODE_TITLE_COLOR = "#999"; u.NODE_SELECTED_TITLE_COLOR = "#FFF"; u.NODE_TEXT_SIZE = 14; u.NODE_TEXT_COLOR = "#AAA"; u.NODE_SUBTEXT_SIZE = 12; u.NODE_DEFAULT_COLOR = "#333"; u.NODE_DEFAULT_BGCOLOR = "#353535"; u.NODE_DEFAULT_BOXCOLOR = "#666"; u.NODE_DEFAULT_SHAPE = "box"; u.NODE_BOX_OUTLINE_COLOR = "#FFF"; u.DEFAULT_SHADOW_COLOR = "rgba(0,0,0,0.5)"; u.DEFAULT_GROUP_FONT_SIZE = 24; u.WIDGET_BGCOLOR = "#222"; u.WIDGET_OUTLINE_COLOR = "#666"; u.WIDGET_TEXT_COLOR = "#DDD"; u.WIDGET_SECONDARY_TEXT_COLOR = "#999"; u.LINK_COLOR = "#9A9"; u.EVENT_LINK_COLOR = "#A86"; u.ACTION_LINK_COLOR = "#86A"; u.CONNECTING_LINK_COLOR = "#AFA"; u.MAX_NUMBER_OF_NODES = 1e3; u.DEFAULT_POSITION = [100, 100]; u.proxy = null; u.node_images_path = ""; u.debug = !1; u.catch_exceptions = !0; u.throw_errors = !0; u.allow_scripts = !1; u.registered_node_types = {}; u.node_types_by_file_extension = {}; u.Nodes = {}; u.Globals = {}; u.searchbox_extras = {}; u.auto_sort_node_types = !1; u.node_box_coloured_when_on = !1; u.node_box_coloured_by_mode = !1; u.dialog_close_on_mouse_leave = !0; u.dialog_close_on_mouse_leave_delay = 500; u.shift_click_do_break_link_from = !1; u.click_do_break_link_to = !1; u.search_hide_on_mouse_leave = !0; u.search_filter_enabled = !1; u.search_show_all_on_open = !0; u.auto_load_slot_types = !1; u.registered_slot_in_types = {}; u.registered_slot_out_types = {}; u.slot_types_in = []; u.slot_types_out = []; u.slot_types_default_in = {}; u.slot_types_default_out = {}; u.alt_drag_do_clone_nodes = !1; u.do_add_triggers_slots = !1; u.allow_multi_output_for_events = !0; u.middle_click_slot_add_default_node = !1; u.release_link_on_empty_shows_menu = !1; u.ignore_all_widget_events = !1; u.pointerevents_method = "mouse"; u.use_uuids = !1; u.search_box_refresh_interval_ms = 250; u.graph_inputs_outputs_use_combo_widget = !1; u.serialize_slot_data = !1; class Be { constructor(e, i = !1) { this.offset = [0, 0], this.scale = 1, this.max_scale = 10, this.min_scale = 0.1, this.onredraw = null, this.enabled = !0, this.last_mouse = [0, 0], this.element = null, this.visible_area = new Float32Array([0, 0, 0, 0]), this.viewport = null, this.dragging = !1, this._binded_mouse_callback = null, e && (this.element = e, i || this.bindEvents(e)); } bindEvents(e) { this.last_mouse = [0, 0], this._binded_mouse_callback = this.onMouse.bind(this), u.pointerListenerAdd(e, "down", this._binded_mouse_callback), u.pointerListenerAdd(e, "move", this._binded_mouse_callback), u.pointerListenerAdd(e, "up", this._binded_mouse_callback), e.addEventListener( "mousewheel", this._binded_mouse_callback, !1 ), e.addEventListener("wheel", this._binded_mouse_callback, !1); } computeVisibleArea(e) { if (!this.element) { this.visible_area[0] = this.visible_area[1] = this.visible_area[2] = this.visible_area[3] = 0; return; } var i = this.element.width, n = this.element.height, s = -this.offset[0], r = -this.offset[1]; e && (s += e[0] / this.scale, r += e[1] / this.scale, i = e[2], n = e[3]); var o = s + i / this.scale, a = r + n / this.scale; this.visible_area[0] = s, this.visible_area[1] = r, this.visible_area[2] = o - s, this.visible_area[3] = a - r; } onMouse(e) { if (!this.enabled) return; var i = this.element, n = i.getBoundingClientRect(); let s = e; var r = s.clientX - n.left, o = s.clientY - n.top; s.canvasX = r, s.canvasX = o, s.dragging = this.dragging; var a = !this.viewport || this.viewport && r >= this.viewport[0] && r < this.viewport[0] + this.viewport[2] && o >= this.viewport[1] && o < this.viewport[1] + this.viewport[3]; if (s.type == u.pointerevents_method + "down" && a) this.dragging = !0, u.pointerListenerRemove(i, "move", this._binded_mouse_callback), u.pointerListenerAdd(document, "move", this._binded_mouse_callback), u.pointerListenerAdd(document, "up", this._binded_mouse_callback); else if (s.type == u.pointerevents_method + "move") { var l = r - this.last_mouse[0], h = o - this.last_mouse[1]; this.dragging && this.mouseDrag(l, h); } else s.type == u.pointerevents_method + "up" ? (this.dragging = !1, u.pointerListenerRemove(document, "move", this._binded_mouse_callback), u.pointerListenerRemove(document, "up", this._binded_mouse_callback), u.pointerListenerAdd(i, "move", this._binded_mouse_callback)) : a && (s.type == "mousewheel" || s.type == "wheel" || s.type == "DOMMouseScroll") && (s.eventType = "mousewheel", s.type == "wheel" ? s.wheel = -s.deltaY : s.wheel = s.wheelDeltaY != null ? s.wheelDeltaY : s.detail * -60, s.delta = s.wheelDelta ? s.wheelDelta / 40 : s.deltaY ? -s.deltaY / 3 : 0, this.changeDeltaScale(1 + s.delta * 0.05, [s.clientX, s.clientY])); if (this.last_mouse[0] = r, this.last_mouse[1] = o, a) return s.preventDefault(), s.stopPropagation(), !1; } toCanvasContext(e) { e.scale(this.scale, this.scale), e.translate(this.offset[0], this.offset[1]); } convertOffsetToCanvas(e) { return [ (e[0] + this.offset[0]) * this.scale, (e[1] + this.offset[1]) * this.scale ]; } convertCanvasToOffset(e, i = [0, 0]) { return i[0] = e[0] / this.scale - this.offset[0], i[1] = e[1] / this.scale - this.offset[1], i; } mouseDrag(e, i) { this.offset[0] += e / this.scale, this.offset[1] += i / this.scale, this.onredraw && this.onredraw(this); } changeScale(e, i) { if (e < this.min_scale ? e = this.min_scale : e > this.max_scale && (e = this.max_scale), e != this.scale && this.element) { var n = this.element.getBoundingClientRect(); if (n) { i = i || [ n.width * 0.5, n.height * 0.5 ], i[0] -= n.left, i[1] -= n.top; var s = this.convertCanvasToOffset(i); this.scale = e, Math.abs(this.scale - 1) < 0.01 && (this.scale = 1); var r = this.convertCanvasToOffset(i), o = [ r[0] - s[0], r[1] - s[1] ]; this.offset[0] += o[0], this.offset[1] += o[1], this.onredraw && this.onredraw(this); } } } changeDeltaScale(e, i) { this.changeScale(this.scale * e, i); } reset() { this.scale = 1, this.offset[0] = 0, this.offset[1] = 0; } } class ge { processMouseDown(e) { if (this.set_canvas_dirty_on_mouse_event && (this.dirty_canvas = !0), !this.graph) return; let i = e; this.adjustMouseEvent(i); var n = this.getCanvasWindow(); n.document, N.active_canvas = this; var s = i.clientX, r = i.clientY; this.ds.viewport = this.viewport; var o = !this.viewport || this.viewport && s >= this.viewport[0] && s < this.viewport[0] + this.viewport[2] && r >= this.viewport[1] && r < this.viewport[1] + this.viewport[3]; if (this.skip_events || (u.pointerListenerRemove(this.canvas, "move", this._mousemove_callback), u.pointerListenerAdd(n.document, "move", this._mousemove_callback, !0), u.pointerListenerAdd(n.document, "up", this._mouseup_callback, !0)), !!o) { var a = this.graph.getNodeOnPos(i.canvasX, i.canvasY, this.visible_nodes, 5), l = !1, h = u.getTime(), p = !(i instanceof PointerEvent) || !i.isPrimary, f = h - this.last_mouseclick < 300 && p; if (this.mouse[0] = i.clientX, this.mouse[1] = i.clientY, this.offset_mouse[0] = i.offsetX, this.offset_mouse[1] = i.offsetY, this.graph_mouse[0] = i.canvasX, this.graph_mouse[1] = i.canvasY, this.last_click_position = [this.mouse[0], this.mouse[1]], this.last_click_position_offset = [this.offset_mouse[0], this.offset_mouse[1]], this.pointer_is_down && p ? this.pointer_is_double = !0 : this.pointer_is_double = !1, this.pointer_is_down = !0, this.canvas.focus(), X.closeAllContextMenus(n), this.search_box && this.search_box.close(), !(this.onMouse && this.onMouse(i) === !0)) { if (i.which == 1 && !this.pointer_is_double) { if (i.ctrlKey && this.allow_interaction && !this.read_only && (this.dragging_rectangle = new Float32Array(4), this.dragging_rectangle[0] = i.canvasX, this.dragging_rectangle[1] = i.canvasY, this.dragging_rectangle[2] = 1, this.dragging_rectangle[3] = 1, l = !0), u.alt_drag_do_clone_nodes && i.altKey && a && this.allow_interaction && !l && !this.read_only) { let P = a.clone(); P && (P.pos[0] += 5, P.pos[1] += 5, this.graph.add(P, { doCalcSize: !1 }), a = P, l = !0, m || (this.allow_dragnodes && (this.graph.beforeChange(), this.node_dragged = a), this.selected_nodes[a.id] || this.processNodeSelected(a, i))); } var c = !1; if (a && this.allow_interaction && !l && !this.read_only) { if (!this.live_mode && !a.flags.pinned && this.bringToFront(a), !this.connecting_node && !a.flags.collapsed && !this.live_mode) if (!l && a.resizable !== !1 && u.isInsideRectangle( i.canvasX, i.canvasY, a.pos[0] + a.size[0] - 5, a.pos[1] + a.size[1] - 5, 10, 10 )) this.graph.beforeChange(), this.resizing_node = a, this.canvas.style.cursor = "se-resize", l = !0; else { if (a.outputs) for (var v = 0, g = a.outputs.length; v < g; ++v) { var d = a.outputs[v], _ = a.getConnectionPos(!1, v); if (u.isInsideRectangle( i.canvasX, i.canvasY, _[0] - 15, _[1] - 10, 30, 20 )) { this.connecting_node = a, this.connecting_output = d, this.connecting_output.slot_index = v, this.connecting_pos = a.getConnectionPos(!1, v), this.connecting_slot = v, u.shift_click_do_break_link_from && i.shiftKey && a.disconnectOutput(v), f ? a.onOutputDblClick && a.onOutputDblClick(v, i) : a.onOutputClick && a.onOutputClick(v, i), l = !0; break; } } if (a.inputs) for (var v = 0, g = a.inputs.length; v < g; ++v) { var y = a.inputs[v], _ = a.getConnectionPos(!0, v); if (u.isInsideRectangle( i.canvasX, i.canvasY, _[0] - 15, _[1] - 10, 30, 20 )) { if (f ? a.onInputDblClick && a.onInputDblClick(v, i) : a.onInputClick && a.onInputClick(v, i), y.link !== null) { var b = this.graph.links[y.link]; u.click_do_break_link_to && (a.disconnectInput(v), this.dirty_bgcanvas = !0, l = !0), (this.allow_reconnect_links || //this.move_destination_link_without_shift || i.shiftKey) && (u.click_do_break_link_to || a.disconnectInput(v), this.connecting_node = this.graph._nodes_by_id[b.origin_id], this.connecting_slot = b.origin_slot, this.connecting_output = this.connecting_node.outputs[this.connecting_slot], this.connecting_pos = this.connecting_node.getConnectionPos(!1, this.connecting_slot), this.dirty_bgcanvas = !0, l = !0); } l || (this.connecting_node = a, this.connecting_input = y, this.connecting_input.slot_index = v, this.connecting_pos = a.getConnectionPos(!0, v), this.connecting_slot = v, this.dirty_bgcanvas = !0, l = !0); } } } if (!l) { var m = !1, E = [i.canvasX - a.pos[0], i.canvasY - a.pos[1]], T = this.processNodeWidgets(a, this.graph_mouse, i); T && (m = !0, this.node_widget = [a, T]), f && this.selected_nodes[a.id] && (a.onDblClick && a.onDblClick(i, E, this), this.processNodeDblClicked(a), m = !0), a.onMouseDown && a.onMouseDown(i, E, this) ? m = !0 : (a.subgraph && !a.skip_subgraph_button && !a.flags.collapsed && E[0] > a.size[0] - u.NODE_TITLE_HEIGHT && E[1] < 0 && setTimeout(() => { this.openSubgraph(a.subgraph); }, 10), this.live_mode && (c = !0, m = !0)), m || (this.allow_dragnodes && (this.graph.beforeChange(), this.node_dragged = a), this.selected_nodes[a.id] || this.processNodeSelected(a, i)), this.dirty_canvas = !0; } } else if (!l) { let P = !1; if (a && a.subgraph && !a.skip_subgraph_button) { var E = [i.canvasX - a.pos[0], i.canvasY - a.pos[1]]; !a.flags.collapsed && E[0] > a.size[0] - u.NODE_TITLE_HEIGHT && E[1] < 0 && (P = !0, setTimeout(() => { this.openSubgraph(a.subgraph); }, 10)); } if (!P) { if (this.allow_interaction && !this.read_only) { const F = this.findLinkCenterAtPos(i.canvasX, i.canvasY); F != null && (this.showLinkMenu(F, i), this.over_link_center = null); } if (this.selected_group = this.graph.getGroupOnPos(i.canvasX, i.canvasY), this.selected_group_resizing = !1, this.selected_group && !this.read_only && this.allow_interaction) { i.ctrlKey && (this.dragging_rectangle = null); var O = u.distance([i.canvasX, i.canvasY], [this.selected_group.pos[0] + this.selected_group.size[0], this.selected_group.pos[1] + this.selected_group.size[1]]); O * this.ds.scale < 10 ? this.selected_group_resizing = !0 : this.selected_group.recomputeInsideNodes(); } f && !this.read_only && this.allow_searchbox && this.allow_interaction && (this.showSearchBox(i), i.preventDefault(), i.stopPropagation()), c = !0; } } !l && c && this.allow_dragcanvas && (this.dragging_canvas = !0); } else if (i.which == 2) { if (u.middle_click_slot_add_default_node && a && this.allow_interaction && !l && !this.read_only && !this.connecting_node && !a.flags.collapsed && !this.live_mode) { var A = null, M = null, L = null; if (a.outputs) for (var v = 0, g = a.outputs.length; v < g; ++v) { var d = a.outputs[v], _ = a.getConnectionPos(!1, v); if (u.isInsideRectangle(i.canvasX, i.canvasY, _[0] - 15, _[1] - 10, 30, 20)) { A = d, M = v, L = !0; break; } } if (a.inputs) for (var v = 0, g = a.inputs.length; v < g; ++v) { var y = a.inputs[v], _ = a.getConnectionPos(!0, v); if (u.isInsideRectangle(i.canvasX, i.canvasY, _[0] - 15, _[1] - 10, 30, 20)) { A = y, M = v, L = !1; break; } } if (A && M !== !1) { var B = 0.5 - (M + 1) / (L ? a.outputs.length : a.inputs.length), G = a.getBounding(), z = [ L ? G[0] + G[2] : G[0], i.canvasY - 80 // + node_bounding[0]/this.canvas.width*66 // vertical "derive" ]; this.createDefaultNodeForSlot("AUTO", { nodeFrom: L ? a : null, slotFrom: L ? M : null, nodeTo: L ? null : a, slotTo: L ? null : M, position: z, posAdd: [L ? 30 : -30, -B * 130], posSizeFix: [L ? 0 : -1, 0] //-alphaPosY*2*/ }); } } } else if ((i.which == 3 || this.pointer_is_double) && this.allow_interaction && !l && !this.read_only) { let P = null; if (a) P = { type: "node", item: a }, Object.keys(this.selected_nodes).length && (this.selected_nodes[a.id] || i.shiftKey || i.ctrlKey || i.metaKey) ? this.selected_nodes[a.id] || this.selectNodes([a], !0) : this.selectNodes([a]); else { const F = this.findLinkCenterAtPos(i.canvasX, i.canvasY); F != null && (this.over_link_center = null, this.dirty_canvas = !0, P = { type: "link", item: F }); } this.processContextMenu(P, i); } if (this.selected_group_moving = !1, this.selected_group && !this.selected_group_resizing) { var pe = this.selected_group.fontSize || u.DEFAULT_GROUP_FONT_SIZE, D = pe * 1.4; u.isInsideRectangle(i.canvasX, i.canvasY, this.selected_group.pos[0], this.selected_group.pos[1], this.selected_group.size[0], D) && (this.selected_group_moving = !0); } return this.last_mouse[0] = i.clientX, this.last_mouse[1] = i.clientY, this.last_mouseclick = u.getTime(), this.last_mouse_dragging = !0, this.graph.change(), (!n.document.activeElement || n.document.activeElement.nodeName.toLowerCase() != "input" && n.document.activeElement.nodeName.toLowerCase() != "textarea") && i.preventDefault(), i.stopPropagation(), this.onMouseDown && this.onMouseDown(i), !1; } } } processMouseMove(e) { let i = e; if (this.autoresize && this.resize(), this.set_canvas_dirty_on_mouse_event && (this.dirty_canvas = !0), !this.graph) return; N.active_canvas = this, this.adjustMouseEvent(i); let n = [i.clientX, i.clientY]; this.mouse[0] = n[0], this.mouse[1] = n[1]; let s = [ n[0] - this.last_mouse[0], n[1] - this.last_mouse[1] ]; if (this.last_mouse = n, this.offset_mouse[0] = i.offsetX, this.offset_mouse[1] = i.offsetY, this.graph_mouse[0] = i.canvasX, this.graph_mouse[1] = i.canvasY, this.block_click) return i.preventDefault(), !1; i.dragging = this.last_mouse_dragging, this.node_widget && (this.processNodeWidgets( this.node_widget[0], this.graph_mouse, i, this.node_widget[1] ), this.dirty_canvas = !0); const r = this.selected_group; if (this.selected_group && !this.selected_group_resizing && !this.selected_group_moving && (this.selected_group = null), this.dragging_rectangle) this.dragging_rectangle[2] = i.canvasX - this.dragging_rectangle[0], this.dragging_rectangle[3] = i.canvasY - this.dragging_rectangle[1], this.dirty_canvas = !0; else if (this.selected_group && !this.read_only && this.allow_interaction) { if (this.selected_group_resizing) this.selected_group.size = [ i.canvasX - this.selected_group.pos[0], i.canvasY - this.selected_group.pos[1] ]; else { var o = s[0] / this.ds.scale, a = s[1] / this.ds.scale; this.selected_group.move(o, a, i.ctrlKey), this.selected_group._nodes.length && (this.dirty_canvas = !0); } this.dirty_bgcanvas = !0; } else if (this.dragging_canvas) this.ds.offset[0] += s[0] / this.ds.scale, this.ds.offset[1] += s[1] / this.ds.scale, this.dirty_canvas = !0, this.dirty_bgcanvas = !0; else { const b = this.allow_interaction && !this.read_only; this.connecting_node && (this.dirty_canvas = !0); var l = this.graph.getNodeOnPos(i.canvasX, i.canvasY, this.visible_nodes); if (b) for (var h = 0, p = this.graph._nodes.length; h < p; ++h) { let m = this.graph._nodes[h]; if (m.mouseOver && l != m) { m.mouseOver = !1, this.node_over && this.node_over.onMouseLeave && this.node_over.onMouseLeave(i, [i.canvasX - this.node_over.pos[0], i.canvasY - this.node_over.pos[1]], this); const E = this.node_over; this.node_over = null, this.dirty_canvas = !0, this.onHoverChange && E != this.node_over && this.onHoverChange(this.node_over, E); } } if (l) { if (l.redraw_on_mouse && (this.dirty_canvas = !0), b) { if (!l.mouseOver) { l.mouseOver = !0; const m = this.node_over; this.node_over = l, this.dirty_canvas = !0, this.onHoverChange && m != this.node_over && this.onHoverChange(this.node_over, m), l.onMouseEnter && l.onMouseEnter(i, [i.canvasX - l.pos[0], i.canvasY - l.pos[1]], this); } if (l.onMouseMove && l.onMouseMove(i, [i.canvasX - l.pos[0], i.canvasY - l.pos[1]], this), this.connecting_node) { if (this.connecting_output) { var f = this._highlight_input || [0, 0]; if (!this.isOverNodeBox(l, i.canvasX, i.canvasY)) { var c = this.isOverNodeInput(l, i.canvasX, i.canvasY, f); if (c != -1 && l.inputs[c]) { var v = l.inputs[c].type; u.isValidConnection(this.connecting_output.type, v) && (this._highlight_input = f, this._highlight_input_slot = l.inputs[c]); } else this._highlight_input = null, this._highlight_input_slot = null; } } else if (this.connecting_input) { var f = this._highlight_output || [0, 0]; if (!this.isOverNodeBox(l, i.canvasX, i.canvasY)) { var c = this.isOverNodeOutput(l, i.canvasX, i.canvasY, f); if (c != -1 && l.outputs[c]) { var v = l.outputs[c].type; u.isValidConnection(this.connecting_input.type, v) && (this._highlight_output = f); } else this._highlight_output = null; } } } this.canvas && (u.isInsideRectangle( i.canvasX, i.canvasY, l.pos[0] + l.size[0] - 5, l.pos[1] + l.size[1] - 5, 5, 5 ) ? this.canvas.style.cursor = "se-resize" : this.canvas.style.cursor = "crosshair"); } } else { var g = this.findLinkCenterAtPos(i.canvasX, i.canvasY); g != this.over_link_center && (this.over_link_center = g, this.dirty_canvas = !0), this.canvas && (this.canvas.style.cursor = ""); } if (b) { if (this.node_capturing_input && this.node_capturing_input != l && this.node_capturing_input.onMouseMove && this.node_capturing_input.onMouseMove(i, [i.canvasX - this.node_capturing_input.pos[0], i.canvasY - this.node_capturing_input.pos[1]], this), this.node_dragged && !this.live_mode) { for (const m in this.selected_nodes) { var d = this.selected_nodes[m]; d.pos[0] += s[0] / this.ds.scale, d.pos[1] += s[1] / this.ds.scale; } this.dirty_canvas = !0, this.dirty_bgcanvas = !0; } if (this.resizing_node && !this.live_mode) { var _ = [i.canvasX - this.resizing_node.pos[0], i.canvasY - this.resizing_node.pos[1]], y = this.resizing_node.computeSize(); _[0] = Math.max(y[0], _[0]), _[1] = Math.max(y[1], _[1]), this.resizing_node.setSize(_), this.canvas.style.cursor = "se-resize", this.dirty_canvas = !0, this.dirty_bgcanvas = !0; } } } return r && !this.selected_group_resizing && !this.selected_group_moving && (this.selected_group = r), i.preventDefault(), !1; } processMouseUp(e) { let i = e; var n = !(i instanceof PointerEvent) || !i.isPrimary; if (!n) return !1; if (this.set_canvas_dirty_on_mouse_event && (this.dirty_canvas = !0), !!this.graph) { var s = this.getCanvasWindow(), r = s.document; N.active_canvas = this, this.skip_events || (u.pointerListenerRemove(r, "move", this._mousemove_callback, !0), u.pointerListenerAdd(this.canvas, "move", this._mousemove_callback, !0), u.pointerListenerRemove(r, "up", this._mouseup_callback, !0)), this.adjustMouseEvent(i); var o = u.getTime(); if (i.click_time = o - this.last_mouseclick, this.last_mouse_dragging = !1, this.last_click_position = null, this.block_click && (this.block_click = !1), i.which == 1) { if (this.node_widget && this.processNodeWidgets(this.node_widget[0], this.graph_mouse, i), this.node_widget = null, this.selected_group) { var a = this.selected_group.pos[0] - Math.round(this.selected_group.pos[0]), l = this.selected_group.pos[1] - Math.round(this.selected_group.pos[1]); this.selected_group.move(a, l, i.ctrlKey), this.selected_group.pos[0] = Math.round( this.selected_group.pos[0] ), this.selected_group.pos[1] = Math.round( this.selected_group.pos[1] ), this.selected_group._nodes.length && (this.dirty_canvas = !0), this.selected_group = null; } this.selected_group_resizing = !1; var h = this.graph.getNodeOnPos( i.canvasX, i.canvasY, this.visible_nodes ); if (this.dragging_rectangle) { if (this.graph) { var p = this.graph._nodes, f = new Float32Array(4), c = Math.abs(this.dragging_rectangle[2]), v = Math.abs(this.dragging_rectangle[3]), g = this.dragging_rectangle[2] < 0 ? this.dragging_rectangle[0] - c : this.dragging_rectangle[0], d = this.dragging_rectangle[3] < 0 ? this.dragging_rectangle[1] - v : this.dragging_rectangle[1]; if (this.dragging_rectangle[0] = g, this.dragging_rectangle[1] = d, this.dragging_rectangle[2] = c, this.dragging_rectangle[3] = v, !h || c > 10 && v > 10) { for (var _ = [], y = 0; y < p.length; ++y) { var b = p[y]; b.getBounding(f), u.overlapBounding( this.dragging_rectangle, f ) && _.push(b); } _.length && this.selectNodes(_, i.shiftKey); } else this.selectNodes([h], i.shiftKey || i.ctrlKey); } this.dragging_rectangle = null; } else if (this.connecting_node) { this.dirty_canvas = !0, this.dirty_bgcanvas = !0; var m = this.connecting_output || this.connecting_input, E = m.type; if (h) { if (this.connecting_output) { var T = this.isOverNodeInput( h, i.canvasX, i.canvasY ); T != -1 ? this.connecting_node.connect(this.connecting_slot, h, T) : this.connecting_node.connectByTypeInput(this.connecting_slot, h, E); } else if (this.connecting_input) { var T = this.isOverNodeOutput( h, i.canvasX, i.canvasY ); T != -1 ? h.connect(T, this.connecting_node, this.connecting_slot) : this.connecting_node.connectByTypeOutput(this.connecting_slot, h, E); } } else u.release_link_on_empty_shows_menu && (i.shiftKey && this.allow_searchbox ? this.connecting_output ? this.showSearchBox(i, { node_from: this.connecting_node, slotFrom: this.connecting_output, type_filter_in: this.connecting_output.type }) : this.connecting_input && this.showSearchBox(i, { node_to: this.connecting_node, slotFrom: this.connecting_input, type_filter_out: this.connecting_input.type }) : this.connecting_output ? this.showConnectionMenu({ nodeFrom: this.connecting_node, slotFrom: this.connecting_output, e: i }) : this.connecting_input && this.showConnectionMenu({ nodeTo: this.connecting_node, slotTo: this.connecting_input, e: i })); this.connecting_output = null, this.connecting_input = null, this.connecting_pos = null, this.connecting_node = null, this.connecting_slot = -1; } else if (this.resizing_node) this.dirty_canvas = !0, this.dirty_bgcanvas = !0, this.graph.afterChange(this.resizing_node), this.resizing_node = null; else if (this.node_dragged) { var h = this.node_dragged; h && i.click_time < 300 && h.isShowingTitle(!0) && u.isInsideRectangle( i.canvasX, i.canvasY, h.pos[0], h.pos[1] - u.NODE_TITLE_HEIGHT, u.NODE_TITLE_HEIGHT, u.NODE_TITLE_HEIGHT ) && h.collapse(), this.dirty_canvas = !0, this.dirty_bgcanvas = !0, this.node_dragged.pos[0] = Math.round(this.node_dragged.pos[0]), this.node_dragged.pos[1] = Math.round(this.node_dragged.pos[1]), (this.graph.config.align_to_grid || this.align_to_grid) && this.node_dragged.alignToGrid(), this.onNodeMoved && this.onNodeMoved(this.node_dragged), this.graph.afterChange(this.node_dragged), this.node_dragged = null; } else { var h = this.graph.getNodeOnPos( i.canvasX, i.canvasY, this.visible_nodes ); !h && i.click_time < 300 && this.deselectAllNodes(), this.dirty_canvas = !0, this.dragging_canvas = !1, this.node_over && this.node_over.onMouseUp && this.node_over.onMouseUp(i, [i.canvasX - this.node_over.pos[0], i.canvasY - this.node_over.pos[1]], this), this.node_capturing_input && this.node_capturing_input.onMouseUp && this.node_capturing_input.onMouseUp(i, [ i.canvasX - this.node_capturing_input.pos[0], i.canvasY - this.node_capturing_input.pos[1] ], this); } } else i.which == 2 ? (this.dirty_canvas = !0, this.dragging_canvas = !1) : i.which == 3 && (this.dirty_canvas = !0, this.dragging_canvas = !1); return n && (this.pointer_is_down = !1, this.pointer_is_double = !1), this.graph.change(), i.stopPropagation(), i.preventDefault(), !1; } } processMouseWheel(e) { let i = e; if (!(!this.graph || !this.allow_dragcanvas)) { var n = i.wheelDeltaY != null ? i.wheelDeltaY : i.detail * -60; this.adjustMouseEvent(i); var s = i.clientX, r = i.clientY, o = !this.viewport || this.viewport && s >= this.viewport[0] && s < this.viewport[0] + this.viewport[2] && r >= this.viewport[1] && r < this.viewport[1] + this.viewport[3]; if (o) { var a = this.ds.scale; return n > 0 ? a *= 1.1 : n < 0 && (a *= 1 / 1.1), this.ds.changeScale(a, [i.clientX, i.clientY]), this.graph.change(), i.preventDefault(), !1; } } } } const ie = class { /** changes the zoom level of the graph (default is 1), you can pass also a place used to pivot the zoom */ setZoom(t, e) { this.ds.changeScale(t, e), this.maxZoom && this.ds.scale > this.maxZoom ? this.scale = this.maxZoom : this.minZoom && this.ds.scale < this.minZoom && (this.scale = this.minZoom); } /** brings a node to front (above all other nodes) */ bringToFront(t) { var e = this.graph._nodes.indexOf(t); e != -1 && (this.graph._nodes.splice(e, 1), this.graph._nodes.push(t)); } /** sends a node to the back (below all other nodes) */ sendToBack(t) { var e = this.graph._nodes.indexOf(t); e != -1 && (this.graph._nodes.splice(e, 1), this.graph._nodes.unshift(t)); } /** checks which nodes are visible (inside the camera area) */ computeVisibleNodes(t, e = []) { var i = e; i.length = 0, t = t || this.graph._nodes; for (var n = 0, s = t.length; n < s; ++n) { var r = t[n]; this.live_mode && !r.onDrawBackground && !r.onDrawForeground || u.overlapBounding(this.visible_area, r.getBounding(ie.temp)) && i.push(r); } return i; } /** renders the whole canvas content, by rendering in two separated canvas, one containing the background grid and the connections, and one containing the nodes) */ draw(t = !1, e = !1) { if (!(!this.canvas || this.canvas.width == 0 || this.canvas.height == 0)) { var i = u.getTime(); this.render_time = (i - this.last_draw_time) * 1e-3, this.last_draw_time = i, this.graph && this.ds.computeVisibleArea(this.viewport), (this.dirty_bgcanvas || e || this.always_render_background || this.graph && this.graph._last_trigger_time && i - this.graph._last_trigger_time < 1e3) && this.drawBackCanvas(), (this.dirty_canvas || t) && this.drawFrontCanvas(), this.fps = this.render_time ? 1 / this.render_time : 0, this.frame += 1; } } /** draws the front canvas (the one containing all the nodes) */ drawFrontCanvas() { this.dirty_canvas = !1, this.ctx || (this.ctx = this.canvas.getContext("2d")); var t = this.ctx; if (t) { var e = this.canvas, i = this.viewport || this.dirty_area; if (i && (t.save(), t.beginPath(), t.rect(i[0], i[1], i[2], i[3]), t.clip()), this.clear_background && (i ? t.clearRect(i[0], i[1], i[2], i[3]) : t.clearRect(0, 0, e.width, e.height)), this.bgcanvas == this.canvas ? this.drawBackCanvas() : t.drawImage(this.bgcanvas, 0, 0), this.onRender && this.onRender(e, t), this.show_info && this.renderInfo(t, i ? i[0] : 0, i ? i[1] : 0), this.graph) { t.save(), this.ds.toCanvasContext(t); for (var n = this.computeVisibleNodes( null, this.visible_nodes ), s = 0; s < n.length; ++s) { var r = n[s]; t.save(), t.translate(r.pos[0], r.pos[1]), this.drawNode(r, t), t.restore(); } if (this.render_execution_order && this.drawExecutionOrder(t), this.graph.config.links_ontop && (this.live_mode || this.drawConnections(t)), this.connecting_pos != null) { t.lineWidth = this.connections_width; var o = null, a = this.connecting_output || this.connecting_input, l = a.type, h = a.dir; h == null && (this.connecting_output ? h = this.connecting_node.horizontal ? w.DOWN : w.RIGHT : h = this.connecting_node.horizontal ? w.UP : w.LEFT); var p = a.shape; switch (l) { case I.EVENT: o = u.EVENT_LINK_COLOR; break; default: o = u.CONNECTING_LINK_COLOR; } if (this.renderLink( t, this.connecting_pos, [this.graph_mouse[0], this.graph_mouse[1]], null, !1, null, o, h, w.CENTER ), t.beginPath(), p === k.BOX_SHAPE ? (t.rect( this.connecting_pos[0] - 6 + 0.5, this.connecting_pos[1] - 5 + 0.5, 14, 10 ), t.fill(), t.beginPath(), t.rect( this.graph_mouse[0] - 6 + 0.5, this.graph_mouse[1] - 5 + 0.5, 14, 10 )) : p === k.ARROW_SHAPE ? (t.moveTo(this.connecting_pos[0] + 8, this.connecting_pos[1] + 0.5), t.lineTo(this.connecting_pos[0] - 4, this.connecting_pos[1] + 6 + 0.5), t.lineTo(this.connecting_pos[0] - 4, this.connecting_pos[1] - 6 + 0.5), t.closePath()) : (t.arc( this.connecting_pos[0], this.connecting_pos[1], 4, 0, Math.PI * 2 ), t.fill(), t.beginPath(), t.arc( this.graph_mouse[0], this.graph_mouse[1], 4, 0, Math.PI * 2 )), t.fill(), t.fillStyle = "#ffcc00", this._highlight_input) { t.beginPath(); var f = this._highlight_input_slot.shape; f === k.ARROW_SHAPE ? (t.moveTo(this._highlight_input[0] + 8, this._highlight_input[1] + 0.5), t.lineTo(this._highlight_input[0] - 4, this._highlight_input[1] + 6 + 0.5), t.lineTo(this._highlight_input[0] - 4, this._highlight_input[1] - 6 + 0.5), t.closePath()) : t.arc( this._highlight_input[0], this._highlight_input[1], 6, 0, Math.PI * 2 ), t.fill(); } this._highlight_output && (t.beginPath(), f === k.ARROW_SHAPE ? (t.moveTo(this._highlight_output[0] + 8, this._highlight_output[1] + 0.5), t.lineTo(this._highlight_output[0] - 4, this._highlight_output[1] + 6 + 0.5), t.lineTo(this._highlight_output[0] - 4, this._highlight_output[1] - 6 + 0.5), t.closePath()) : t.arc( this._highlight_output[0], this._highlight_output[1], 6, 0, Math.PI * 2 ), t.fill()); } this.dragging_rectangle && (t.strokeStyle = "#FFF", t.strokeRect( this.dragging_rectangle[0], this.dragging_rectangle[1], this.dragging_rectangle[2], this.dragging_rectangle[3] )), this.over_link_center && this.render_link_tooltip ? this.drawLinkTooltip(t, this.over_link_center) : this.onDrawLinkTooltip && this.onDrawLinkTooltip(t, null, this), this.onDrawForeground && this.onDrawForeground(t, this.visible_area), t.restore(); } this._graph_stack && this._graph_stack.length && this.render_subgraph_panels && this.drawSubgraphPanel(t), this.onDrawOverlay && this.onDrawOverlay(t), i && t.restore(); } } /** * draws the panel in the corner that shows subgraph properties * @method drawSubgraphPanel **/ drawSubgraphPanel(t) { var e = this.graph, i = e._subgraph_node; if (!i) { console.warn("subgraph without subnode"); return; } this.drawSubgraphPanelLeft(e, i, t), this.drawSubgraphPanelRight(e, i, t); } drawSubgraphPanelLeft(t, e, i) { var n = e.inputs ? e.inputs.length : 0, s = 200, r = Math.floor(u.NODE_SLOT_HEIGHT * 1.6); if (i.fillStyle = "#111", i.globalAlpha = 0.8, i.beginPath(), i.roundRect(10, 10, s, (n + 1) * r + 50, [8]), i.fill(), i.globalAlpha = 1, i.fillStyle = "#888", i.font = "14px Arial", i.textAlign = "left", i.fillText("Graph Inputs", 20, 34), this.drawButton(s - 20, 20, 20, 20, "X", "#151515", void 0, void 0, !0)) { this.closeSubgraph(); return; } var o = 50; if (i.font = "14px Arial", e.inputs) for (var a = 0; a < e.inputs.length; ++a) { var l = e.inputs[a]; l.not_subgraph_input || (i.fillStyle = "#9C9", i.beginPath(), i.arc(s - 16, o, 5, 0, 2 * Math.PI), i.fill(), i.fillStyle = "#AAA", i.fillText(l.name, 30, o + r * 0.75), i.fillStyle = "#777", i.fillText(J(l.type), 130, o + r * 0.75), o += r); } this.drawButton(20, o + 2, s - 20, r - 2, "+", "#151515", "#222") && this.showSubgraphPropertiesDialog(e); } drawSubgraphPanelRight(t, e, i) { var n = e.outputs ? e.outputs.length : 0, s = this.bgcanvas.width, r = 200, o = Math.floor(u.NODE_SLOT_HEIGHT * 1.6); i.fillStyle = "#111", i.globalAlpha = 0.8, i.beginPath(), i.roundRect(s - r - 10, 10, r, (n + 1) * o + 50, [8]), i.fill(), i.globalAlpha = 1, i.fillStyle = "#888", i.font = "14px Arial", i.textAlign = "left"; var a = "Graph Outputs", l = i.measureText(a).width; if (i.fillText(a, s - l - 20, 34), this.drawButton(s - r, 20, 20, 20, "X", "#151515", void 0, void 0, !0)) { this.closeSubgraph(); return; } var h = 50; if (i.font = "14px Arial", e.outputs) for (var p = 0; p < e.outputs.length; ++p) { var f = e.outputs[p]; f.not_subgraph_output || (i.fillStyle = "#9C9", i.beginPath(), i.arc(s - r + 16, h, 5, 0, 2 * Math.PI), i.fill(), i.fillStyle = "#AAA", i.fillText(f.name, s - r + 30, h + o * 0.75), i.fillStyle = "#777", i.fillText(J(f.type), s - r + 130, h + o * 0.75), h += o); } this.drawButton(s - r, h + 2, r - 20, o - 2, "+", "#151515", "#222") && this.showSubgraphPropertiesDialogRight(e); } //Draws a button into the canvas overlay and computes if it was clicked using the immediate gui paradigm drawButton(t, e, i, n, s, r = u.NODE_DEFAULT_COLOR, o = "#555", a = u.NODE_TEXT_COLOR, l = !1) { const h = !this.block_click && (l || this.allow_interaction && !this.read_only); var p = this.ctx, f = this.offset_mouse, c = h && u.isInsideRectangle(f[0], f[1], t, e, i, n); f = this.last_click_position_offset; var v = h && f && this.pointer_is_down && u.isInsideRectangle(f[0], f[1], t, e, i, n); p.fillStyle = c ? o : r, v && (p.fillStyle = "#AAA"), p.beginPath(), p.roundRect(t, e, i, n, [4]), p.fill(), s != null && s.constructor == String && (p.fillStyle = a, p.textAlign = "center", p.font = (n * 0.65 | 0) + "px Arial", p.fillText(s, t + i * 0.5, e + n * 0.75), p.textAlign = "left"); var g = v && h; return v && this.blockClick(), g; } /** draws every group area in the background */ drawGroups(t, e) { if (this.graph) { var i = this.graph._groups; e.save(), e.globalAlpha = 0.5 * this.editor_alpha; for (var n = 0; n < i.length; ++n) { var s = i[n]; if (u.overlapBounding(this.visible_area, s._bounding)) { e.fillStyle = s.color || "#335", e.strokeStyle = s.color || "#335"; var r = s._pos, o = s._size; e.globalAlpha = 0.25 * this.editor_alpha, e.beginPath(), e.rect(r[0] + 0.5, r[1] + 0.5, o[0], o[1]), e.fill(), e.globalAlpha = this.editor_alpha, e.stroke(), e.beginPath(), e.moveTo(r[0] + o[0], r[1] + o[1]), e.lineTo(r[0] + o[0] - 10, r[1] + o[1]), e.lineTo(r[0] + o[0], r[1] + o[1] - 10), e.fill(); var a = s.font_size || u.DEFAULT_GROUP_FONT_SIZE; e.font = a + "px Arial", e.textAlign = "left", e.fillText(s.title, r[0] + 4, r[1] + a); } } e.restore(); } } /** draws some useful stats in the corner of the canvas */ renderInfo(t, e = 10, i) { i = i || this.canvas.height - 80, t.save(), t.translate(e, i), t.font = "10px Arial", t.fillStyle = "#888", t.textAlign = "left", this.graph ? (t.fillText("T: " + this.graph.globaltime.toFixed(2) + "s", 5, 13 * 1), t.fillText("I: " + this.graph.iteration, 5, 13 * 2), t.fillText("N: " + this.graph._nodes.length + " [" + this.visible_nodes.length + "]", 5, 13 * 3), t.fillText("V: " + this.graph._version, 5, 13 * 4), t.fillText("FPS:" + this.fps.toFixed(2), 5, 13 * 5)) : t.fillText("No graph selected", 5, 13 * 1), t.restore(); } /** draws the back canvas (the one containing the background and the connections) */ drawBackCanvas() { var t = this.bgcanvas; (t.width != this.canvas.width || t.height != this.canvas.height) && (t.width = this.canvas.width, t.height = this.canvas.height), this.bgctx || (this.bgctx = this.bgcanvas.getContext("2d")); var e = this.bgctx; let i = this.viewport || [0, 0, e.canvas.width, e.canvas.height]; if (this.clear_background && e.clearRect(i[0], i[1], i[2], i[3]), this._graph_stack && this._graph_stack.length && this.render_subgraph_stack_header) { e.save(); const o = this._graph_stack[this._graph_stack.length - 1].graph, a = this.graph._subgraph_node; e.strokeStyle = a.bgcolor, e.lineWidth = 10, e.strokeRect(1, 1, t.width - 2, t.height - 2), e.lineWidth = 1, e.font = "40px Arial", e.textAlign = "center", e.fillStyle = a.bgcolor || "#AAA"; let l = ""; for (let h = 1; h < this._graph_stack.length; ++h) l += o._subgraph_node.getTitle() + " >> "; e.fillText( l + a.getTitle(), t.width * 0.5, 40 ), e.restore(); } let n = !1; if (this.onRenderBackground && this.onRenderBackground(t, e) && (n = !0), this.viewport || (e.restore(), e.setTransform(1, 0, 0, 1, 0, 0)), this.visible_links.length = 0, this.graph) { if (e.save(), this.ds.toCanvasContext(e), this.ds.scale < 1.5 && !n && this.clear_background_color && (e.fillStyle = this.clear_background_color, e.fillRect( this.visible_area[0], this.visible_area[1], this.visible_area[2], this.visible_area[3] )), this.background_image && this.ds.scale > 0.5 && !n) { this.zoom_modify_alpha ? e.globalAlpha = (1 - 0.5 / this.ds.scale) * this.editor_alpha : e.globalAlpha = this.editor_alpha, e.imageSmoothingEnabled = e.imageSmoothingEnabled = !1, (!this._bg_img || this._bg_img.name != this.background_image) && (this._bg_img = new Image(), this._bg_img.name = this.background_image, this._bg_img.src = this.background_image, this._bg_img.onload = () => { this.draw(!0, !0); }); var s = null; this._pattern == null && this._bg_img.width > 0 ? (s = e.createPattern(this._bg_img, "repeat"), this._pattern_img = this._bg_img, this._pattern = s) : s = this._pattern, s && (e.fillStyle = s, e.fillRect( this.visible_area[0], this.visible_area[1], this.visible_area[2], this.visible_area[3] ), e.fillStyle = "transparent"), e.globalAlpha = 1, e.imageSmoothingEnabled = e.imageSmoothingEnabled = !0; } this.graph._groups.length && !this.live_mode && this.drawGroups(t, e), this.onDrawBackground && this.onDrawBackground(e, this.visible_area), u.debug && (e.fillStyle = "red", e.fillRect(this.visible_area[0] + 10, this.visible_area[1] + 10, this.visible_area[2] - 20, this.visible_area[3] - 20)), this.render_canvas_border && (e.strokeStyle = "#235", e.strokeRect(0, 0, t.width, t.height)), this.render_connections_shadows ? (e.shadowColor = "#000", e.shadowOffsetX = 0, e.shadowOffsetY = 0, e.shadowBlur = 6) : e.shadowColor = "rgba(0,0,0,0)", !this.live_mode && this.render_connections && this.drawConnections(e), e.shadowColor = "rgba(0,0,0,0)", e.restore(); } this.dirty_bgcanvas = !1, this.dirty_canvas = !0; } /** draws the given node inside the canvas */ drawNode(t, e) { this.current_node = t; var i = t.color || t.constructor.color || u.NODE_DEFAULT_COLOR, n = t.bgcolor || t.constructor.bgcolor || u.NODE_DEFAULT_BGCOLOR; t.mouseOver; var s = this.ds.scale < 0.6; if (this.live_mode) { t.flags.collapsed || (e.shadowColor = "transparent", t.onDrawForeground && t.onDrawForeground(e, this, this.canvas)); return; } var r = this.editor_alpha; if (e.globalAlpha = r, this.render_shadows && !s ? (e.shadowColor = u.DEFAULT_SHADOW_COLOR, e.shadowOffsetX = 2 * this.ds.scale, e.shadowOffsetY = 2 * this.ds.scale, e.shadowBlur = 3 * this.ds.scale) : e.shadowColor = "transparent", !(t.flags.collapsed && t.onDrawCollapsed && t.onDrawCollapsed(e, this) == !0)) { var o = t.shape || k.BOX_SHAPE, a = ie.temp_vec2; ie.temp_vec2.set(t.size); var l = t.horizontal; if (t.flags.collapsed) { e.font = this.inner_text_font; var h = t.getTitle ? t.getTitle() : t.title; h != null && (t._collapsed_width = Math.min( t.size[0], e.measureText(h).width + u.NODE_TITLE_HEIGHT * 2 ), a[0] = t._collapsed_width, a[1] = 0); } t.clip_area && (e.save(), e.beginPath(), o == k.BOX_SHAPE ? e.rect(0, 0, a[0], a[1]) : o == k.ROUND_SHAPE ? e.roundRect(0, 0, a[0], a[1], [10]) : o == k.CIRCLE_SHAPE && e.arc( a[0] * 0.5, a[1] * 0.5, a[0] * 0.5, 0, Math.PI * 2 ), e.clip()), t.has_errors && (n = "red"), this.drawNodeShape( t, e, [a[0], a[1]], i, n, t.is_selected, t.mouseOver ), e.shadowColor = "transparent", t.onDrawForeground && t.onDrawForeground(e, this, this.canvas), e.textAlign = l ? "center" : "left", e.font = this.inner_text_font; var p = !s, f = this.connecting_output, c = this.connecting_input; e.lineWidth = 1; var v = 0, g = [0, 0]; if (t.flags.collapsed) { if (this.render_collapsed_slots) { var A = null, M = null; if (t.inputs) for (let G = 0; G < t.inputs.length; G++) { let z = t.inputs[G]; if (z.link != null) { A = z; break; } } if (t.outputs) for (let G = 0; G < t.outputs.length; G++) { let z = t.outputs[G]; !z.links || !z.links.length || (M = z); } if (A) { var L = 0, B = u.NODE_TITLE_HEIGHT * -0.5; l && (L = t._collapsed_width * 0.5, B = -u.NODE_TITLE_HEIGHT), e.fillStyle = "#686", e.beginPath(), A.shape === k.BOX_SHAPE ? e.rect(L - 7 + 0.5, B - 4, 14, 8) : A.shape === k.ARROW_SHAPE ? (e.moveTo(L + 8, B), e.lineTo(L + -4, B - 4), e.lineTo(L + -4, B + 4), e.closePath()) : e.arc(L, B, 4, 0, Math.PI * 2), e.fill(); } if (M) { var L = t._collapsed_width, B = u.NODE_TITLE_HEIGHT * -0.5; l && (L = t._collapsed_width * 0.5, B = 0), e.fillStyle = "#686", e.strokeStyle = "black", e.beginPath(), M.shape === k.BOX_SHAPE ? e.rect(L - 7 + 0.5, B - 4, 14, 8) : M.shape === k.ARROW_SHAPE ? (e.moveTo(L + 6, B), e.lineTo(L - 6, B - 4), e.lineTo(L - 6, B + 4), e.closePath()) : e.arc(L, B, 4, 0, Math.PI * 2), e.fill(); } } } else { if (t.inputs) for (var d = 0; d < t.inputs.length; d++) { var _ = t.inputs[d], y = _.type, b = _.shape; e.globalAlpha = r, this.connecting_output && !u.isValidConnection(_.type, f.type) ? e.globalAlpha = 0.4 * r : e.globalAlpha = r, e.fillStyle = _.link != null ? _.color_on || N.DEFAULT_CONNECTION_COLORS_BY_TYPE[y] || N.DEFAULT_CONNECTION_COLORS.input_on : _.color_off || N.DEFAULT_CONNECTION_COLORS_BY_TYPE_OFF[y] || N.DEFAULT_CONNECTION_COLORS_BY_TYPE[y] || N.DEFAULT_CONNECTION_COLORS.input_off; var m = t.getConnectionPos(!0, d, [g[0], g[1]]); m[0] -= t.pos[0], m[1] -= t.pos[1], v < m[1] + u.NODE_SLOT_HEIGHT * 0.5 && (v = m[1] + u.NODE_SLOT_HEIGHT * 0.5), e.beginPath(); var E = !0; if (_.shape === k.BOX_SHAPE ? l ? e.rect( m[0] - 5 + 0.5, m[1] - 8 + 0.5, 10, 14 ) : e.rect( m[0] - 6 + 0.5, m[1] - 5 + 0.5, 14, 10 ) : b === k.ARROW_SHAPE ? (e.moveTo(m[0] + 8, m[1] + 0.5), e.lineTo(m[0] - 4, m[1] + 6 + 0.5), e.lineTo(m[0] - 4, m[1] - 6 + 0.5), e.closePath()) : b === k.GRID_SHAPE ? (e.rect(m[0] - 4, m[1] - 4, 2, 2), e.rect(m[0] - 1, m[1] - 4, 2, 2), e.rect(m[0] + 2, m[1] - 4, 2, 2), e.rect(m[0] - 4, m[1] - 1, 2, 2), e.rect(m[0] - 1, m[1] - 1, 2, 2), e.rect(m[0] + 2, m[1] - 1, 2, 2), e.rect(m[0] - 4, m[1] + 2, 2, 2), e.rect(m[0] - 1, m[1] + 2, 2, 2), e.rect(m[0] + 2, m[1] + 2, 2, 2), E = !1) : s ? e.rect(m[0] - 4, m[1] - 4, 8, 8) : e.arc(m[0], m[1], 4, 0, Math.PI * 2), e.fill(), p) { var T = _.label != null ? _.label : _.name; T && (e.fillStyle = u.NODE_TEXT_COLOR, l || _.dir == w.UP ? e.fillText(T, m[0], m[1] - 10) : e.fillText(T, m[0] + 10, m[1] + 5)); } } if (e.textAlign = l ? "center" : "right", e.strokeStyle = "black", t.outputs) for (let G = 0; G < t.outputs.length; G++) { let z = t.outputs[G]; var y = z.type, b = z.shape; this.connecting_input && !u.isValidConnection(c.type, y) ? e.globalAlpha = 0.4 * r : e.globalAlpha = r; var m = t.getConnectionPos(!1, G, g); m[0] -= t.pos[0], m[1] -= t.pos[1], v < m[1] + u.NODE_SLOT_HEIGHT * 0.5 && (v = m[1] + u.NODE_SLOT_HEIGHT * 0.5), e.fillStyle = z.links && z.links.length ? z.color_on || N.DEFAULT_CONNECTION_COLORS_BY_TYPE[y] || N.DEFAULT_CONNECTION_COLORS.output_on : z.color_off || N.DEFAULT_CONNECTION_COLORS_BY_TYPE_OFF[y] || N.DEFAULT_CONNECTION_COLORS_BY_TYPE[y] || N.DEFAULT_CONNECTION_COLORS.output_off, e.beginPath(); var E = !0; if (b === k.BOX_SHAPE ? l ? e.rect( m[0] - 5 + 0.5, m[1] - 8 + 0.5, 10, 14 ) : e.rect( m[0] - 6 + 0.5, m[1] - 5 + 0.5, 14, 10 ) : b === k.ARROW_SHAPE ? (e.moveTo(m[0] + 8, m[1] + 0.5), e.lineTo(m[0] - 4, m[1] + 6 + 0.5), e.lineTo(m[0] - 4, m[1] - 6 + 0.5), e.closePath()) : b === k.GRID_SHAPE ? (e.rect(m[0] - 4, m[1] - 4, 2, 2), e.rect(m[0] - 1, m[1] - 4, 2, 2), e.rect(m[0] + 2, m[1] - 4, 2, 2), e.rect(m[0] - 4, m[1] - 1, 2, 2), e.rect(m[0] - 1, m[1] - 1, 2, 2), e.rect(m[0] + 2, m[1] - 1, 2, 2), e.rect(m[0] - 4, m[1] + 2, 2, 2), e.rect(m[0] - 1, m[1] + 2, 2, 2), e.rect(m[0] + 2, m[1] + 2, 2, 2), E = !1) : s ? e.rect(m[0] - 4, m[1] - 4, 8, 8) : e.arc(m[0], m[1], 4, 0, Math.PI * 2), e.fill(), !s && E && e.stroke(), p) { var T = z.label != null ? z.label : z.name; T && (e.fillStyle = u.NODE_TEXT_COLOR, l || z.dir == w.DOWN ? e.fillText(T, m[0], m[1] - 8) : e.fillText(T, m[0] - 10, m[1] + 5)); } } if (e.textAlign = "left", e.globalAlpha = 1, t.widgets) { var O = v; (l || t.widgets_up) && (O = 2), t.widgets_start_y != null && (O = t.widgets_start_y), this.drawNodeWidgets( t, O, e, this.node_widget && this.node_widget[0] == t ? this.node_widget[1] : null ); } } t.clip_area && e.restore(), e.globalAlpha = 1; } } /** used by this.over_link_center */ drawLinkTooltip(t, e) { var i = e._pos; if (this.allow_interaction && !this.read_only && (t.fillStyle = "black", t.beginPath(), t.arc(i[0], i[1], 3, 0, Math.PI * 2), t.fill()), e.data != null && !(this.onDrawLinkTooltip && this.onDrawLinkTooltip(t, e, this) == !0)) { var n = e.data, s = null; if (n.constructor === Number ? s = n.toFixed(2) : n.constructor === String ? s = '"' + n + '"' : n.constructor === Boolean ? s = String(n) : n.toToolTip ? s = n.toToolTip() : s = "[" + n.constructor.name + "]", s != null) { s = s.substr(0, 30), t.font = "14px Courier New"; var r = t.measureText(s), o = r.width + 20, a = 24; t.shadowColor = "black", t.shadowOffsetX = 2, t.shadowOffsetY = 2, t.shadowBlur = 3, t.fillStyle = "#454", t.beginPath(), t.roundRect(i[0] - o * 0.5, i[1] - 15 - a, o, a, [3]), t.moveTo(i[0] - 10, i[1] - 15), t.lineTo(i[0] + 10, i[1] - 15), t.lineTo(i[0], i[1] - 5), t.fill(), t.shadowColor = "transparent", t.textAlign = "center", t.fillStyle = "#CEC", t.fillText(s, i[0], i[1] - 15 - a * 0.3); } } } /** draws the shape of the given node in the canvas */ drawNodeShape(t, e, i, n, s, r, o) { e.strokeStyle = n, e.fillStyle = s; var a = u.NODE_TITLE_HEIGHT, l = this.ds.scale < 0.5, h = t.shape || t.constructor.shape || k.ROUND_SHAPE, p = t.titleMode, f = t.isShowingTitle(o), c = ie.tmp_area; c[0] = 0, c[1] = f ? -a : 0, c[2] = i[0] + 1, c[3] = f ? i[1] + a : i[1]; var v = e.globalAlpha; if (e.beginPath(), h == k.BOX_SHAPE || l ? e.fillRect(c[0], c[1], c[2], c[3]) : h == k.ROUND_SHAPE || h == k.CARD_SHAPE ? e.roundRect( c[0], c[1], c[2], c[3], h == k.CARD_SHAPE ? [this.round_radius, this.round_radius, 0, 0] : [this.round_radius] ) : h == k.CIRCLE_SHAPE && e.arc( i[0] * 0.5, i[1] * 0.5, i[0] * 0.5, 0, Math.PI * 2 ), e.fill(), !t.flags.collapsed && f && (e.shadowColor = "transparent", e.fillStyle = "rgba(0,0,0,0.2)", e.fillRect(0, -1, c[2], 2)), e.shadowColor = "transparent", t.onDrawBackground && t.onDrawBackground(e, this, this.canvas, this.graph_mouse), f || p == se.TRANSPARENT_TITLE) { if (t.onDrawTitleBar) t.onDrawTitleBar(e, this, a, i, this.ds.scale, n); else if (p != se.TRANSPARENT_TITLE && (t.constructor.title_color || this.render_title_colored)) { var g = t.constructor.title_color || n; if (t.flags.collapsed && (e.shadowColor = u.DEFAULT_SHADOW_COLOR), this.use_gradients) { var d = N.gradients[g]; d || (d = N.gradients[g] = e.createLinearGradient(0, 0, 400, 0), d.addColorStop(0, g), d.addColorStop(1, "#000")), e.fillStyle = d; } else e.fillStyle = g; e.beginPath(), h == k.BOX_SHAPE || l ? e.rect(0, -a, i[0] + 1, a) : (h == k.ROUND_SHAPE || h == k.CARD_SHAPE) && e.roundRect( 0, -a, i[0] + 1, a, t.flags.collapsed ? [this.round_radius] : [this.round_radius, this.round_radius, 0, 0] ), e.fill(), e.shadowColor = "transparent"; } var _ = null; u.node_box_coloured_by_mode && Oe[t.mode] && (_ = Oe[t.mode]), u.node_box_coloured_when_on && (_ = t.action_triggered ? "#FFF" : t.execute_triggered ? "#AAA" : _); var y = 10; if (t.onDrawTitleBox ? t.onDrawTitleBox(e, this, a, i, this.ds.scale) : h == k.ROUND_SHAPE || h == k.CIRCLE_SHAPE || h == k.CARD_SHAPE ? (l && (e.fillStyle = "black", e.beginPath(), e.arc( a * 0.5, a * -0.5, y * 0.5 + 1, 0, Math.PI * 2 ), e.fill()), e.fillStyle = t.boxcolor || _ || u.NODE_DEFAULT_BOXCOLOR, l ? e.fillRect(a * 0.5 - y * 0.5, a * -0.5 - y * 0.5, y, y) : (e.beginPath(), e.arc( a * 0.5, a * -0.5, y * 0.5, 0, Math.PI * 2 ), e.fill())) : (l && (e.fillStyle = "black", e.fillRect( (a - y) * 0.5 - 1, (a + y) * -0.5 - 1, y + 2, y + 2 )), e.fillStyle = t.boxcolor || _ || u.NODE_DEFAULT_BOXCOLOR, e.fillRect( (a - y) * 0.5, (a + y) * -0.5, y, y )), e.globalAlpha = v, t.onDrawTitleText && t.onDrawTitleText( e, this, a, i, this.ds.scale, this.title_text_font, r ), !l) { e.font = this.title_text_font; var b = String(t.getTitle()); b && (r ? e.fillStyle = u.NODE_SELECTED_TITLE_COLOR : e.fillStyle = t.constructor.title_text_color || this.node_title_color, t.flags.collapsed ? (e.textAlign = "left", e.fillText( b.substr(0, 20), //avoid urls too long a, // + measure.width * 0.5, u.NODE_TITLE_TEXT_Y - a ), e.textAlign = "left") : (e.textAlign = "left", e.fillText( b, a, u.NODE_TITLE_TEXT_Y - a ))); } if (!t.flags.collapsed && t.subgraph && !t.skip_subgraph_button) { var m = u.NODE_TITLE_HEIGHT, E = t.size[0] - m, T = u.isInsideRectangle(this.graph_mouse[0] - t.pos[0], this.graph_mouse[1] - t.pos[1], E + 2, -m + 2, m - 4, m - 4); e.fillStyle = T ? "#888" : "#555", h == k.BOX_SHAPE || l ? e.fillRect(E + 2, -m + 2, m - 4, m - 4) : (e.beginPath(), e.roundRect(E + 2, -m + 2, m - 4, m - 4, [4]), e.fill()), e.fillStyle = "#333", e.beginPath(), e.moveTo(E + m * 0.2, -m * 0.6), e.lineTo(E + m * 0.8, -m * 0.6), e.lineTo(E + m * 0.5, -m * 0.3), e.fill(); } t.onDrawTitle && t.onDrawTitle(e, this); } r && (t.onBounding && t.onBounding(c), p == se.TRANSPARENT_TITLE && (c[1] -= a, c[3] += a), e.lineWidth = 1, e.globalAlpha = 0.8, e.beginPath(), h == k.BOX_SHAPE ? e.rect( -6 + c[0], -6 + c[1], 12 + c[2], 12 + c[3] ) : h == k.ROUND_SHAPE || h == k.CARD_SHAPE && t.flags.collapsed ? e.roundRect( -6 + c[0], -6 + c[1], 12 + c[2], 12 + c[3], [this.round_radius * 2] ) : h == k.CARD_SHAPE ? e.roundRect( -6 + c[0], -6 + c[1], 12 + c[2], 12 + c[3], [this.round_radius * 2, 2, this.round_radius * 2, 2] ) : h == k.CIRCLE_SHAPE && e.arc( i[0] * 0.5, i[1] * 0.5, i[0] * 0.5 + 6, 0, Math.PI * 2 ), e.strokeStyle = u.NODE_BOX_OUTLINE_COLOR, e.stroke(), e.strokeStyle = n, e.globalAlpha = 1), t.execute_triggered > 0 && t.execute_triggered--, t.action_triggered > 0 && t.action_triggered--; } /** draws every connection visible in the canvas */ drawConnections(t) { var e = u.getTime(), i = this.visible_area; let n = ie.margin_area; n[0] = i[0] - 20, n[1] = i[1] - 20, n[2] = i[2] + 40, n[3] = i[3] + 40, t.lineWidth = this.connections_width, t.fillStyle = "#AAA", t.strokeStyle = "#AAA", t.globalAlpha = this.editor_alpha; for (var s = this.graph._nodes, r = 0, o = s.length; r < o; ++r) { var a = s[r]; if (!(!a.inputs || !a.inputs.length)) for (var l = 0; l < a.inputs.length; ++l) { var h = a.inputs[l]; if (!h || h.link == null) continue; var p = h.link, f = this.graph.links[p]; if (!f) continue; var c = this.graph.getNodeById(f.origin_id); if (c == null) continue; var v = f.origin_slot, g = null; v == -1 ? g = [ c.pos[0] + 10, c.pos[1] + 10 ] : g = c.getConnectionPos( !1, v, ie.tempA ); var d = a.getConnectionPos(!0, l, ie.tempB); let O = ie.link_bounding; if (O[0] = g[0], O[1] = g[1], O[2] = d[0] - g[0], O[3] = d[1] - g[1], O[2] < 0 && (O[0] += O[2], O[2] = Math.abs(O[2])), O[3] < 0 && (O[1] += O[3], O[3] = Math.abs(O[3])), !!u.overlapBounding(O, n)) { var _ = c.outputs[v], y = a.inputs[l]; if (!(!_ || !y)) { var b = _.dir || (c.horizontal ? w.DOWN : w.RIGHT), m = y.dir || (a.horizontal ? w.UP : w.LEFT); if (this.renderLink( t, g, d, f, !1, !1, null, b, m ), f && f._last_time && e - f._last_time < 1e3) { var E = 2 - (e - f._last_time) * 2e-3, T = t.globalAlpha; t.globalAlpha = T * E, this.renderLink( t, g, d, f, !0, !0, "white", b, m ), t.globalAlpha = T; } } } } } t.globalAlpha = 1; } /** * draws a link between two points * @param a start pos * @param b end pos * @param link the link object with all the link info * @param skipBorder ignore the shadow of the link * @param flow show flow animation (for events) * @param color the color for the link * @param startDir the direction enum * @param endDir the direction enum * @param numSublines number of sublines (useful to represent vec3 or rgb) **/ renderLink(t, e, i, n, s, r, o, a, l, h) { n && this.visible_links.push(n), !o && n && (o = n.color || this.link_type_colors[n.type]), o || (o = this.default_link_color), n != null && this.highlighted_links[n.id] && (o = "#FFF"), a = a || w.RIGHT, l = l || w.LEFT; var p = u.distance(e, i); this.render_connections_border && this.ds.scale > 0.6 && (t.lineWidth = this.connections_width + 4), t.lineJoin = "round", h = h || 1, h > 1 && (t.lineWidth = 0.5), t.beginPath(); for (var f = 0; f < h; f += 1) { var c = (f - (h - 1) * 0.5) * 5; if (this.links_render_mode == de.SPLINE_LINK) { t.moveTo(e[0], e[1] + c); var v = 0, g = 0, d = 0, _ = 0; switch (a) { case w.LEFT: v = p * -0.25; break; case w.RIGHT: v = p * 0.25; break; case w.UP: g = p * -0.25; break; case w.DOWN: g = p * 0.25; break; } switch (l) { case w.LEFT: d = p * -0.25; break; case w.RIGHT: d = p * 0.25; break; case w.UP: _ = p * -0.25; break; case w.DOWN: _ = p * 0.25; break; } t.bezierCurveTo( e[0] + v, e[1] + g + c, i[0] + d, i[1] + _ + c, i[0], i[1] + c ); } else if (this.links_render_mode == de.LINEAR_LINK) { t.moveTo(e[0], e[1] + c); var v = 0, g = 0, d = 0, _ = 0; switch (a) { case w.LEFT: v = -1; break; case w.RIGHT: v = 1; break; case w.UP: g = -1; break; case w.DOWN: g = 1; break; } switch (l) { case w.LEFT: d = -1; break; case w.RIGHT: d = 1; break; case w.UP: _ = -1; break; case w.DOWN: _ = 1; break; } var y = 15; t.lineTo( e[0] + v * y, e[1] + g * y + c ), t.lineTo( i[0] + d * y, i[1] + _ * y + c ), t.lineTo(i[0], i[1] + c); } else if (this.links_render_mode == de.STRAIGHT_LINK) { t.moveTo(e[0], e[1]); var b = e[0], m = e[1], E = i[0], T = i[1]; a == w.RIGHT ? b += 10 : m += 10, l == w.LEFT ? E -= 10 : T -= 10, t.lineTo(b, m), t.lineTo((b + E) * 0.5, m), t.lineTo((b + E) * 0.5, T), t.lineTo(E, T), t.lineTo(i[0], i[1]); } else return; } this.render_connections_border && this.ds.scale > 0.6 && !s && (t.strokeStyle = "rgba(0,0,0,0.5)", t.stroke()), t.lineWidth = this.connections_width, t.fillStyle = t.strokeStyle = o, t.stroke(); var O = this.computeConnectionPoint(e, i, 0.5, a, l); if (n && n._pos && (n._pos[0] = O[0], n._pos[1] = O[1]), this.ds.scale >= 0.6 && this.highquality_render && l != w.CENTER) { if (this.render_connection_arrows) { var A = this.computeConnectionPoint( e, i, 0.25, a, l ), M = this.computeConnectionPoint( e, i, 0.26, a, l ), L = this.computeConnectionPoint( e, i, 0.75, a, l ), B = this.computeConnectionPoint( e, i, 0.76, a, l ), G = 0, z = 0; this.render_curved_connections ? (G = -Math.atan2(M[0] - A[0], M[1] - A[1]), z = -Math.atan2(B[0] - L[0], B[1] - L[1])) : z = G = i[1] > e[1] ? 0 : Math.PI, t.save(), t.translate(A[0], A[1]), t.rotate(G), t.beginPath(), t.moveTo(-5, -3), t.lineTo(0, 7), t.lineTo(5, -3), t.fill(), t.restore(), t.save(), t.translate(L[0], L[1]), t.rotate(z), t.beginPath(), t.moveTo(-5, -3), t.lineTo(0, 7), t.lineTo(5, -3), t.fill(), t.restore(); } t.beginPath(), t.arc(O[0], O[1], 5, 0, Math.PI * 2), t.fill(); } if (r) { t.fillStyle = o; for (var f = 0; f < 5; ++f) { var pe = (u.getTime() * 1e-3 + f * 0.2) % 1, O = this.computeConnectionPoint( e, i, pe, a, l ); t.beginPath(), t.arc(O[0], O[1], 5, 0, 2 * Math.PI), t.fill(); } } } computeConnectionPoint(t, e, i, n = w.RIGHT, s = w.LEFT) { var r = u.distance(t, e), o = t, a = [t[0], t[1]], l = [e[0], e[1]], h = e; switch (n) { case w.LEFT: a[0] += r * -0.25; break; case w.RIGHT: a[0] += r * 0.25; break; case w.UP: a[1] += r * -0.25; break; case w.DOWN: a[1] += r * 0.25; break; } switch (s) { case w.LEFT: l[0] += r * -0.25; break; case w.RIGHT: l[0] += r * 0.25; break; case w.UP: l[1] += r * -0.25; break; case w.DOWN: l[1] += r * 0.25; break; } var p = (1 - i) * (1 - i) * (1 - i), f = 3 * ((1 - i) * (1 - i)) * i, c = 3 * (1 - i) * (i * i), v = i * i * i, g = p * o[0] + f * a[0] + c * l[0] + v * h[0], d = p * o[1] + f * a[1] + c * l[1] + v * h[1]; return [g, d]; } drawExecutionOrder(t) { t.shadowColor = "transparent", t.globalAlpha = 0.25, t.textAlign = "center", t.strokeStyle = "white", t.globalAlpha = 0.75; for (var e = this.visible_nodes, i = 0; i < e.length; ++i) { var n = e[i]; t.fillStyle = "black", t.fillRect( n.pos[0] - u.NODE_TITLE_HEIGHT, n.pos[1] - u.NODE_TITLE_HEIGHT, u.NODE_TITLE_HEIGHT, u.NODE_TITLE_HEIGHT ), n.order == 0 && t.strokeRect( n.pos[0] - u.NODE_TITLE_HEIGHT + 0.5, n.pos[1] - u.NODE_TITLE_HEIGHT + 0.5, u.NODE_TITLE_HEIGHT, u.NODE_TITLE_HEIGHT ), t.fillStyle = "#FFF", t.fillText( "" + n.order, n.pos[0] + u.NODE_TITLE_HEIGHT * -0.5, n.pos[1] - 6 ); } t.globalAlpha = 1; } /** draws the widgets stored inside a node */ drawNodeWidgets(t, e, i, n) { if (!(!t.widgets || !t.widgets.length)) { var s = t.size[0], r = t.widgets; e += 2; var o = u.NODE_WIDGET_HEIGHT, a = this.ds.scale > 0.5; i.save(), i.globalAlpha = this.editor_alpha; for (var l = u.WIDGET_OUTLINE_COLOR, h = u.WIDGET_BGCOLOR, p = u.WIDGET_TEXT_COLOR, f = u.WIDGET_SECONDARY_TEXT_COLOR, c = 15, v = 0; v < r.length; ++v) { var g = r[v]; if (!g.hidden) { var d = e; g.y && (d = g.y), g.last_y = d, i.strokeStyle = l, i.fillStyle = "#222", i.textAlign = "left", g.disabled && (i.globalAlpha *= 0.5); var _ = g.width || s; switch (g.type) { case "button": g.clicked && (i.fillStyle = "#AAA", g.clicked = !1, this.dirty_canvas = !0), i.fillRect(c, d, _ - c * 2, o), a && !g.disabled && !u.ignore_all_widget_events && i.strokeRect(c, d, _ - c * 2, o), a && (i.textAlign = "center", i.fillStyle = p, i.fillText(g.name, _ * 0.5, d + o * 0.7)); break; case "toggle": i.textAlign = "left", i.strokeStyle = l, i.fillStyle = h, i.beginPath(), a ? i.roundRect(c, d, _ - c * 2, o, [o * 0.5]) : i.rect(c, d, _ - c * 2, o), i.fill(), a && !g.disabled && !u.ignore_all_widget_events && i.stroke(), i.fillStyle = g.value ? "#89A" : "#333", i.beginPath(), i.arc(_ - c * 2, d + o * 0.5, o * 0.36, 0, Math.PI * 2), i.fill(), a && (i.fillStyle = f, g.name != null && i.fillText(g.name, c * 2, d + o * 0.7), i.fillStyle = g.value ? p : f, i.textAlign = "right", i.fillText( g.value ? g.options.on || "true" : g.options.off || "false", _ - 40, d + o * 0.7 )); break; case "slider": i.fillStyle = h, i.fillRect(c, d, _ - c * 2, o); var y = g.options.max - g.options.min, b = (g.value - g.options.min) / y; if (i.fillStyle = n == g ? "#89A" : "#678", i.fillRect(c, d, b * (_ - c * 2), o), a && !g.disabled && i.strokeRect(c, d, _ - c * 2, o), g.marker) { var m = (+g.marker - g.options.min) / y; i.fillStyle = "#AA9", i.fillRect(c + m * (_ - c * 2), d, 2, o); } a && (i.textAlign = "center", i.fillStyle = p, i.fillText( g.name + " " + Number(g.value).toFixed(3), _ * 0.5, d + o * 0.7 )); break; case "number": case "combo": if (i.textAlign = "left", i.strokeStyle = l, i.fillStyle = h, i.beginPath(), a ? i.roundRect(c, d, _ - c * 2, o, [o * 0.5]) : i.rect(c, d, _ - c * 2, o), i.fill(), a) if (!g.disabled && !u.ignore_all_widget_events && i.stroke(), i.fillStyle = p, !g.disabled && !u.ignore_all_widget_events && (i.beginPath(), i.moveTo(c + 16, d + 5), i.lineTo(c + 6, d + o * 0.5), i.lineTo(c + 16, d + o - 5), i.fill(), i.beginPath(), i.moveTo(_ - c - 16, d + 5), i.lineTo(_ - c - 6, d + o * 0.5), i.lineTo(_ - c - 16, d + o - 5), i.fill()), i.fillStyle = f, i.fillText(g.name, c * 2 + 5, d + o * 0.7), i.fillStyle = p, i.textAlign = "right", g.type == "number") i.fillText( Number(g.value).toFixed( g.options.precision !== void 0 ? g.options.precision : 3 ), _ - c * 2 - 20, d + o * 0.7 ); else { var E = g.value; if (g.options.values) { var T = g.options.values; T.constructor === Function && (T = T()), T && T.constructor !== Array && (E = T[g.value]); } i.fillText( E, _ - c * 2 - 20, d + o * 0.7 ); } break; case "string": case "text": i.textAlign = "left", i.strokeStyle = l, i.fillStyle = h, i.beginPath(), a ? i.roundRect(c, d, _ - c * 2, o, [o * 0.5]) : i.rect(c, d, _ - c * 2, o), i.fill(), a && (g.disabled || i.stroke(), i.save(), i.beginPath(), i.rect(c, d, _ - c * 2, o), i.clip(), i.fillStyle = f, g.name != null && i.fillText(g.name, c * 2, d + o * 0.7), i.fillStyle = p, i.textAlign = "right", i.fillText(String(g.value).substr(0, g.options.max_length || 30), _ - c * 2, d + o * 0.7), i.restore()); break; default: g.draw && g.draw(i, t, _, d, o); break; } e += (g.computeSize ? g.computeSize(_)[1] : o) + 4, i.globalAlpha = this.editor_alpha; } } i.restore(), i.textAlign = "left"; } } }; let U = ie; U.temp = new Float32Array(4); U.temp_vec2 = new Float32Array(2); U.tmp_area = new Float32Array(4); U.margin_area = new Float32Array(4); U.link_bounding = new Float32Array(4); U.tempA = [0, 0]; U.tempB = [0, 0]; class me { constructor(e = "Group") { this.fontSize = u.DEFAULT_GROUP_FONT_SIZE, this._nodes = [], this.graph = null, this._bounding = new Float32Array([10, 10, 140, 80]), this.title = e, this.color = N.node_colors.pale_blue ? N.node_colors.pale_blue.groupcolor : "#AAA", this._pos = this._bounding.subarray(0, 2), this._size = this._bounding.subarray(2, 4); } get bounding() { return this._bounding; } get pos() { return [this._pos[0], this._pos[1]]; } set pos(e) { !e || e.length < 2 || (this._pos[0] = e[0], this._pos[1] = e[1]); } get size() { return [this._size[0], this._size[1]]; } set size(e) { !e || e.length < 2 || (this._size[0] = Math.max(140, e[0]), this._size[1] = Math.max(80, e[1])); } configure(e) { e.bounding, this.title = e.title, this._bounding.set(e.bounding), this.color = e.color, this.font = e.font; } serialize() { const e = this._bounding; return { title: this.title, bounding: [ Math.round(e[0]), Math.round(e[1]), Math.round(e[2]), Math.round(e[3]) ], color: this.color, font: this.font }; } move(e, i, n) { if (this._pos[0] += e, this._pos[1] += i, !n) for (var s = 0; s < this._nodes.length; ++s) { var r = this._nodes[s]; r.pos[0] += e, r.pos[1] += i; } } recomputeInsideNodes() { this._nodes.length = 0; for (var e = this.graph._nodes, i = new Float32Array(4), n = 0; n < e.length; ++n) { var s = e[n]; s.getBounding(i), u.overlapBounding(this._bounding, i) && this._nodes.push(s); } } /** checks if a point is inside the shape of a node */ isPointInside(e, i, n = 0, s = !1) { var r = this.graph && this.graph.isLive() ? 0 : u.NODE_TITLE_HEIGHT; return s && (r = 0), this.pos[0] - 4 - n < e && this.pos[0] + this.size[0] + 4 + n > e && this.pos[1] - r - n < i && this.pos[1] + this.size[1] + n > i; } /** Forces to redraw or the main canvas (LGraphNode) or the bg canvas (links) */ setDirtyCanvas(e, i = !1) { this.graph && this.graph.sendActionToCanvas("setDirty", [e, i]); } } class he { constructor(e, i, n, s, r, o) { this.data = null, this._pos = [0, 0], this._last_time = 0, this.id = e, this.type = i, this.origin_id = n, this.origin_slot = s, this.target_id = r, this.target_slot = o; } static configure(e) { return e instanceof Array ? new he(e[0], e[5], e[1], e[2], e[3], e[4]) : new he(e.id, e.type, e.origin_id, e.origin_slot, e.target_id, e.target_slot); } serialize() { return [ this.id, this.origin_id, this.origin_slot, this.target_id, this.target_slot, this.type ]; } } let _e; const He = new Uint8Array(16); function Fe() { if (!_e && (_e = typeof crypto < "u" && crypto.getRandomValues && crypto.getRandomValues.bind(crypto), !_e)) throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported"); return _e(He); } const K = []; for (let t = 0; t < 256; ++t) K.push((t + 256).toString(16).slice(1)); function Ue(t, e = 0) { return (K[t[e + 0]] + K[t[e + 1]] + K[t[e + 2]] + K[t[e + 3]] + "-" + K[t[e + 4]] + K[t[e + 5]] + "-" + K[t[e + 6]] + K[t[e + 7]] + "-" + K[t[e + 8]] + K[t[e + 9]] + "-" + K[t[e + 10]] + K[t[e + 11]] + K[t[e + 12]] + K[t[e + 13]] + K[t[e + 14]] + K[t[e + 15]]).toLowerCase(); } const ze = typeof crypto < "u" && crypto.randomUUID && crypto.randomUUID.bind(crypto), ke = { randomUUID: ze }; function oe(t, e, i) { if (ke.randomUUID && !e && !t) return ke.randomUUID(); t = t || {}; const n = t.random || (t.rng || Fe)(); if (n[6] = n[6] & 15 | 64, n[8] = n[8] & 63 | 128, e) { i = i || 0; for (let s = 0; s < 16; ++s) e[i + s] = n[s]; return e; } return Ue(n); } const Ne = class { constructor(t) { this.desc = "", this.pos = [0, 0], this.subgraph = null, this.skip_subgraph_button = !1, this.priority = 0, this.removable = !0, this.clonable = !0, this.collapsable = !0, this.titleMode = se.NORMAL_TITLE, this.serialize_widgets = !1, this.hide_in_node_lists = !1, this.block_delete = !1, this.ignore_remove = !1, this.last_serialization = null, this._relative_id = null, this.exec_version = 0, this.action_call = null, this.execute_triggered = 0, this.action_triggered = 0, this.console = [], this.title = t || "Unnamed", this.size = [u.NODE_WIDTH, 60], this.graph = null, this.pos = [10, 10], u.use_uuids ? this.id = oe() : this.id = -1, this.type = null, this.inputs = [], this.outputs = [], this.connections = [], this.properties = {}, this.properties_info = [], this.flags = {}; } get slotLayout() { return "slotLayout" in this.constructor ? this.constructor.slotLayout : null; } /** configure a node from an object containing the serialized info */ configure(t) { this.graph && this.graph._version++; for (var e in t) { if (e == "properties") { for (var i in t.properties) this.properties[i] = t.properties[i], this.onPropertyChanged && this.onPropertyChanged(i, t.properties[i]); continue; } t[e] != null && (typeof t[e] == "object" ? this[e] && this[e].configure ? this[e].configure(t[e]) : this[e] = u.cloneObject(t[e], this[e]) : this[e] = t[e]); } t.title || (this.title = ye(this, "title") || this.title); const n = t.bgColor; if (n != null && (this.bgcolor || (this.bgcolor = n)), this.inputs) for (let o = 0; o < this.inputs.length; ++o) { let a = this.inputs[o], l = this.graph ? this.graph.links[a.link] : null; a.properties || (a.properties = {}), this.onConnectionsChange && this.onConnectionsChange(W.INPUT, o, !0, l, a), this.onInputAdded && this.onInputAdded(a); } if (this.outputs) for (var s = 0; s < this.outputs.length; ++s) { let o = this.outputs[s]; if (o.properties || (o.properties = {}), !!o.links) { for (let a = 0; a < o.links.length; ++a) { let l = this.graph ? this.graph.links[o.links[a]] : null; this.onConnectionsChange && this.onConnectionsChange(W.OUTPUT, s, !0, l, o); } this.onOutputAdded && this.onOutputAdded(o); } } if (this.widgets) { for (var s = 0; s < this.widgets.length; ++s) { var r = this.widgets[s]; r && r.options && r.options.property && this.properties[r.options.property] && (r.value = JSON.parse(JSON.stringify(this.properties[r.options.property]))); } if (t.widgets_values) for (var s = 0; s < t.widgets_values.length; ++s) this.widgets[s] && (this.widgets[s].value = t.widgets_values[s]); } this.onConfigure && this.onConfigure(t); } /** serialize the content */ serialize() { let t = { id: this.id, type: this.type, pos: this.pos, size: this.size, flags: u.cloneObject(this.flags), order: this.order, mode: this.mode }; if (this.constructor === Ne && this.last_serialization) return this.last_serialization; if (this.inputs && (t.inputs = this.inputs), this.outputs) { for (var e = 0; e < this.outputs.length; e++) delete this.outputs[e]._data; t.outputs = this.outputs; } if (this.title && this.title != this.constructor.title && (t.title = this.title), this.properties && (t.properties = u.cloneObject(this.properties)), this.widgets && this.serialize_widgets) { t.widgets_values = []; for (var e = 0; e < this.widgets.length; ++e) this.widgets[e] ? t.widgets_values[e] = this.widgets[e].value : t.widgets_values[e] = null; } return t.type || (t.type = this.constructor.type), this.color && (t.color = this.color), this.bgcolor && (t.bgcolor = this.bgcolor), this.boxcolor && (t.boxcolor = this.boxcolor), this.shape && (t.shape = this.shape), this.onSerialize && this.onSerialize(t), t; } /** Creates a clone of this node */ clone(t = { forNode: {} }) { var e = u.createNode(this.type); if (!e) return null; var i = u.cloneObject(this.serialize()); if (i.inputs) for (var n = 0; n < i.inputs.length; ++n) i.inputs[n].link = null; if (i.outputs) for (var n = 0; n < i.outputs.length; ++n) i.outputs[n].links && (i.outputs[n].links.length = 0); return delete i.id, u.use_uuids && (i.id = oe()), e.configure(i), e; } /** serialize and stringify */ toString() { return JSON.stringify(this.serialize()); } /** get the title string */ getTitle() { return this.title || this.constructor.title; } getRootGraph() { var e; let t = this.graph; for (; t && t._is_subgraph; ) t = (e = t._subgraph_node) == null ? void 0 : e.graph; return t == null || t._is_subgraph ? null : t; } *iterateParentSubgraphNodes() { var e; let t = this.graph._subgraph_node; for (; t; ) yield t, t = (e = t.graph) == null ? void 0 : e._subgraph_node; } /** sets the value of a property */ setProperty(t, e) { var r; if (this.properties || (this.properties = {}), e !== this.properties[t]) { var i = this.properties[t]; if (this.properties[t] = e, this.graph && this.graph._version++, this.onPropertyChanged && this.onPropertyChanged(t, e, i) === !1 && (this.properties[t] = i), this.widgets) for (var n = 0; n < this.widgets.length; ++n) { var s = this.widgets[n]; if (s && ((r = s.options) == null ? void 0 : r.property) == t) { s.value = e; break; } } } } getInputSlotProperty(t, e) { if (!(!this.inputs || !this.graph) && !(t == -1 || t >= this.inputs.length)) { var i = this.inputs[t]; if (i) return i.properties || (i.properties = {}), i.properties[e]; } } getOutputSlotProperty(t, e) { if (!(!this.outputs || !this.graph) && !(t == -1 || t >= this.outputs.length)) { var i = this.outputs[t]; if (i) return i.properties || (i.properties = {}), i.properties[e]; } } setInputSlotProperty(t, e, i) { if (!(!this.inputs || !this.graph) && !(t == -1 || t >= this.inputs.length)) { var n = this.inputs[t]; if (n && (n.properties || (n.properties = {}), i !== n.properties[e])) { var s = n.properties[e]; n.properties[e] = i, this.graph && this.graph._version++, this.onSlotPropertyChanged && this.onSlotPropertyChanged(W.INPUT, t, n, e, i, s) === !1 && (n.properties[e] = s); } } } setOutputSlotProperty(t, e, i) { if (!(!this.outputs || !this.graph) && !(t == -1 || t >= this.outputs.length)) { var n = this.outputs[t]; if (n && (n.properties || (n.properties = {}), i !== n.properties[e])) { var s = n.properties[e]; n.properties[e] = i, this.graph && this.graph._version++, this.onSlotPropertyChanged && this.onSlotPropertyChanged(W.OUTPUT, t, n, e, i, s) === !1 && (n.properties[e] = s); } } } /** sets the output data */ setOutputData(t, e) { if (!(!this.outputs || !this.graph) && !(t == -1 || t >= this.outputs.length)) { var i = this.outputs[t]; if (i && (u.serialize_slot_data ? i._data = e : i._data = void 0, this.outputs[t].links)) for (var n = 0; n < this.outputs[t].links.length; n++) { var s = this.outputs[t].links[n], r = this.graph.links[s]; r && (r.data = e); } } } /** sets the output data */ setOutputDataType(t, e) { if (this.outputs && !(t == -1 || t >= this.outputs.length)) { var i = this.outputs[t]; if (i && (i.type = e, this.outputs[t].links)) for (let n = this.outputs[t].links.length - 1; n >= 0; n--) { const s = this.outputs[t].links[n], r = this.graph.links[s]; if (r) { r.type = e; const o = this.graph.getNodeById(r.target_id); if (o) { const a = o.getInputInfo(r.target_slot); a && !u.isValidConnection(e, a.type) && o.disconnectInput(r.target_slot); } } } } } *iterateInputInfo() { for (let t = 0; t < this.inputs.length; t++) yield this.inputs[t]; } /** * Retrieves the input data (data traveling through the connection) from one slot * @param slot * @param force_update if set to true it will force the connected node of this slot to output data into this link * @return data or if it is not connected returns undefined */ getInputData(t, e) { if (!(!this.inputs || !this.graph) && !(t >= this.inputs.length || this.inputs[t].link == null)) { var i = this.inputs[t].link, n = this.graph.links[i]; if (!n) return u.debug && console.error(`Link not found in slot ${t}!`, this, this.inputs[t], i), null; if (!e) return n.data; var s = this.graph.getNodeById(n.origin_id); return s && (s.updateOutputData ? s.updateOutputData(n.origin_slot) : s.onExecute && s.onExecute(null, {})), n.data; } } /** * Retrieves the input data type (in case this supports multiple input types) * @param slot * @return datatype in string format */ getInputDataType(t) { if (!this.inputs || t >= this.inputs.length || this.inputs[t].link == null) return null; var e = this.inputs[t].link, i = this.graph.links[e]; if (!i) return u.debug && console.error(`Link not found in slot ${t}!`, this, this.inputs[t], e), null; var n = this.graph.getNodeById(i.origin_id); if (!n) return i.type; var s = n.outputs[i.origin_slot]; return s && s.type != -1 ? s.type : null; } /** * Retrieves the input data from one slot using its name instead of slot number * @param slot_name * @param force_update if set to true it will force the connected node of this slot to output data into this link * @return data or if it is not connected returns null */ getInputDataByName(t, e) { var i = this.findInputSlotIndexByName(t); return i == -1 ? null : this.getInputData(i, e); } /** tells you if there is a connection in one input slot */ isInputConnected(t) { return this.inputs ? t < this.inputs.length && this.inputs[t].link != null : !1; } /** tells you info about an input connection (which node, type, etc) */ getInputInfo(t) { return this.inputs && t < this.inputs.length ? this.inputs[t] : null; } /** * Returns the link info in the connection of an input slot * @param {number} slot * @return {LLink} object or null */ getInputLink(t) { if (!this.inputs || !this.graph) return null; if (t < this.inputs.length) { var e = this.inputs[t]; return this.graph.links[e.link]; } return null; } /** returns the node connected in the input slot */ getInputNode(t) { if (!this.inputs || !this.graph) return null; if (t < this.inputs.length) { const i = this.inputs[t].link, n = this.graph.links[i]; if (!n) return u.debug && console.error(`Link not found in slot ${t}!`, this, this.inputs[t], i), null; var e = this.graph.getNodeById(n.origin_id); if (e) return e; } return null; } /** returns the value of an input with this name, otherwise checks if there is a property with that name */ getInputOrProperty(t) { if (!this.inputs || !this.inputs.length || !this.graph) return this.properties ? this.properties[t] : null; for (var e = 0, i = this.inputs.length; e < i; ++e) { var n = this.inputs[e]; if (t == n.name && n.link != null) { var s = this.graph.links[n.link]; if (s) return s.data; } } return this.properties[t]; } /** sets the input data type */ setInputDataType(t, e) { if (!(!this.inputs || !this.graph) && !(t == -1 || t >= this.inputs.length)) { var i = this.inputs[t]; if (i && (i.type = e, i.link)) { const n = i.link, s = this.graph.links[n]; s.type = e; const r = this.graph.getNodeById(s.origin_id); if (r) { const o = r.getOutputInfo(s.origin_slot); o && !u.isValidConnection(o.type, e) && r.disconnectOutput(s.origin_slot); } } } } /** * Returns the output slot in another node that an input in this node is connected to. * @param {number} slot * @return {LLink} object or null */ getOutputSlotConnectedTo(t) { if (!this.outputs || !this.graph) return null; if (t >= 0 && t < this.outputs.length) { var e = this.inputs[t]; if (e.link) { const i = this.graph.links[e.link]; return this.graph.getNodeById(i.origin_id).outputs[i.origin_slot]; } } return null; } *iterateOutputInfo() { for (let t = 0; t < this.outputs.length; t++) yield this.outputs[t]; } /** tells you the last output data that went in that slot */ getOutputData(t) { if (!this.outputs || !this.graph || t >= this.outputs.length) return null; var e = this.outputs[t]; return e._data; } /** * Returns the link info in the connection of an output slot * @param {number} slot * @return {LLink} object or null */ getOutputLinks(t) { if (!this.outputs || !this.graph) return []; if (t >= 0 && t < this.outputs.length) { var e = this.outputs[t]; if (e.links) { var i = []; for (const n of e.links) i.push(this.graph.links[n]); return i; } } return []; } /** * Returns the input slots in other nodes that an output in this node is connected to. * @param {number} slot * @return {LLink} object or null */ getInputSlotsConnectedTo(t) { if (!this.outputs || !this.graph) return []; if (t >= 0 && t < this.outputs.length) { var e = this.outputs[t]; if (e.links) { var i = []; for (const n of e.links) { const s = this.graph.links[n], r = this.graph.getNodeById(s.target_id); i.push(r.inputs[s.target_slot]); } return i; } } return []; } /** tells you info about an output connection (which node, type, etc) */ getOutputInfo(t) { return this.outputs && t < this.outputs.length ? this.outputs[t] : null; } /** tells you if there is a connection in one output slot */ isOutputConnected(t) { return !this.outputs || !this.graph ? !1 : t < this.outputs.length && this.outputs[t].links && this.outputs[t].links.length > 0; } /** tells you if there is any connection in the output slots */ isAnyOutputConnected() { if (!this.outputs || !this.graph) return !1; for (var t = 0; t < this.outputs.length; ++t) if (this.outputs[t].links && this.outputs[t].links.length) return !0; return !1; } /** retrieves all the nodes connected to this output slot */ getOutputNodes(t) { if (!this.outputs || this.outputs.length == 0 || !this.graph || t >= this.outputs.length) return null; var e = this.outputs[t]; if (!e.links || e.links.length == 0) return null; for (var i = [], n = 0; n < e.links.length; n++) { var s = e.links[n], r = this.graph.links[s]; if (r) { var o = this.graph.getNodeById(r.target_id); o && i.push(o); } } return i; } *iterateAllLinks() { if (this.graph) { for (const t of this.iterateInputInfo()) if (t.link) { const e = this.graph.links[t.link]; e && (yield e); } for (const t of this.iterateOutputInfo()) if (t.links != null) for (const e of t.links) { const i = this.graph.links[e]; i && (yield i); } } } addOnTriggerInput() { var t = this.findInputSlotIndexByName("onTrigger"); if (t == -1) { //!trigS || return this.addInput("onTrigger", I.EVENT, { optional: !0, nameLocked: !0 }), this.findInputSlotIndexByName("onTrigger"); } return t; } addOnExecutedOutput() { var t = this.findOutputSlotIndexByName("onExecuted"); if (t == -1) { //!trigS || return this.addOutput("onExecuted", I.ACTION, { optional: !0, nameLocked: !0 }), this.findOutputSlotIndexByName("onExecuted"); } return t; } onAfterExecuteNode(t, e) { var i = this.findOutputSlotIndexByName("onExecuted"); i != -1 && this.triggerSlot(i, t, null, e); } changeMode(t) { switch (t) { case Z.ON_EVENT: break; case Z.ON_TRIGGER: this.addOnTriggerInput(), this.addOnExecutedOutput(); break; case Z.NEVER: break; case Z.ALWAYS: break; case Z.ON_REQUEST: break; default: return !1; } return this.mode = t, !0; } doExecute(t, e = {}) { this.onExecute && (e.action_call || (e.action_call = this.id + "_exec_" + Math.floor(Math.random() * 9999)), this.graph.nodes_executing[this.id] = !0, this.onExecute(t, e), this.graph.nodes_executing[this.id] = !1, this.exec_version = this.graph.iteration, e && e.action_call && (this.action_call = e.action_call, this.graph.nodes_executedAction[this.id] = e.action_call)), this.execute_triggered = 2, this.onAfterExecuteNode && this.onAfterExecuteNode(t, e); } /** * Triggers an action, wrapped by logics to control execution flow * @method actionDo * @param {String} action name * @param {*} param */ actionDo(t, e, i = {}) { this.onAction && (i.action_call || (i.action_call = this.id + "_" + (t || "action") + "_" + Math.floor(Math.random() * 9999)), this.graph.nodes_actioning[this.id] = t || "actioning", this.onAction(t, e, i), this.graph.nodes_actioning[this.id] = !1, i && i.action_call && (this.action_call = i.action_call, this.graph.nodes_executedAction[this.id] = i.action_call)), this.action_triggered = 2, this.onAfterExecuteNode && this.onAfterExecuteNode(e, i); } /** Triggers an event in this node, this will trigger any output with the same name */ trigger(t, e, i) { if (!(!this.outputs || !this.outputs.length)) { this.graph && (this.graph._last_trigger_time = u.getTime()); for (var n = 0; n < this.outputs.length; ++n) { var s = this.outputs[n]; !s || s.type !== I.EVENT || t && s.name != t || this.triggerSlot(n, e, null, i); } } } /** * Triggers an slot event in this node * @param slot the index of the output slot * @param param * @param link_id in case you want to trigger and specific output link in a slot */ triggerSlot(t, e, i, n = {}) { if (this.outputs) { if (t == null) { console.error("slot must be a number"); return; } typeof t != "number" && console.warn("slot must be a number, use node.trigger('name') if you want to use a string"); var s = this.outputs[t]; if (s) { var r = s.links; if (!(!r || !r.length)) { this.graph && (this.graph._last_trigger_time = u.getTime()); for (var o = 0; o < r.length; ++o) { var a = r[o]; if (!(i != null && i != a)) { var l = this.graph.links[r[o]]; if (l) { l._last_time = u.getTime(); var h = this.graph.getNodeById(l.target_id); if (h) { if (h.inputs[l.target_slot], n.link = l, n.originNode = this, h.mode === Z.ON_TRIGGER) n.action_call || (n.action_call = this.id + "_trigg_" + Math.floor(Math.random() * 9999)), h.onExecute && h.doExecute(e, n); else if (h.onAction) { n.action_call || (n.action_call = this.id + "_act_" + Math.floor(Math.random() * 9999)); const p = h.inputs[l.target_slot]; h.actionDo(p.name, e, n); } } } } } } } } } /** * clears the trigger slot animation * @param slot the index of the output slot * @param link_id in case you want to trigger and specific output link in a slot */ clearTriggeredSlot(t, e) { if (this.outputs) { var i = this.outputs[t]; if (i) { var n = i.links; if (!(!n || !n.length)) for (var s = 0; s < n.length; ++s) { var r = n[s]; if (!(e != null && e != r)) { var o = this.graph.links[n[s]]; o && (o._last_time = 0); } } } } } /** * changes node size and triggers callback * @method setSize * @param {vec2} size */ setSize(t) { this.size = t, this.onResize && this.onResize(this.size); } /** * add a new property to this node * @param name * @param default_value * @param type string defining the output type ("vec3","number",...) * @param extra_info this can be used to have special properties of the property (like values, etc) */ addProperty(t, e, i, n) { var s = { name: t, type: i, default_value: e }; if (n) for (var r in n) s[r] = n[r]; return this.properties_info || (this.properties_info = []), this.properties_info.push(s), this.properties || (this.properties = {}), this.properties[t] = e, s; } hasProperty(t) { return this.properties != null && t in this.properties; } /** * add a new output slot to use in this node * @param name * @param type string defining the output type ("vec3","number",...) * @param extra_info this can be used to have special properties of an output (label, special color, position, etc) */ addOutput(t, e = I.DEFAULT, i) { var n = { name: t, type: e, links: [], properties: {} }; if (i) for (var s in i) n[s] = i[s]; return (n.shape == null || n.shape == k.DEFAULT) && (e == "array" ? n.shape = k.GRID_SHAPE : (e === I.EVENT || e === I.ACTION) && (n.shape = k.BOX_SHAPE)), (e === I.EVENT || e === I.ACTION) && (n.shape = k.BOX_SHAPE), this.outputs || (this.outputs = []), this.outputs.push(n), this.onOutputAdded && this.onOutputAdded(n), u.auto_load_slot_types && u.registerNodeAndSlotType(this, e, !0), this.setSize(this.computeSize()), this.setDirtyCanvas(!0, !0), n; } /** remove an existing output slot */ removeOutput(t) { const e = this.outputs[t]; this.disconnectOutput(t), this.outputs.splice(t, 1); for (var i = t; i < this.outputs.length; ++i) if (!(!this.outputs[i] || !this.outputs[i].links)) for (var n = this.outputs[i].links, s = 0; s < n.length; ++s) { var r = this.graph.links[n[s]]; r && (r.origin_slot -= 1); } this.setSize(this.computeSize()), this.onOutputRemoved && this.onOutputRemoved(t, e), this.setDirtyCanvas(!0, !0); } moveOutput(t, e) { const i = this.outputs[t]; if (i == null || e < 0 || e > this.outputs.length - 1) return; const n = this.outputs[e]; if (i.links) for (const s of i.links) { const r = this.graph.links[s]; r.origin_slot = e; } if (n.links) for (const s of n.links) { const r = this.graph.links[s]; r.origin_slot = t; } this.outputs[e] = i, this.outputs[t] = n; } /** * add a new input slot to use in this node * @param name * @param type string defining the input type ("vec3","number",...), it its a generic one use 0 * @param extra_info this can be used to have special properties of an input (label, color, position, etc) */ addInput(t, e = I.DEFAULT, i) { var n = { name: t, type: e, link: null, properties: {} }; if (i) for (var s in i) n[s] = i[s]; return (n.shape == null || n.shape == k.DEFAULT) && (e == "array" ? n.shape = k.GRID_SHAPE : (e === I.EVENT || e === I.ACTION) && (n.shape = k.BOX_SHAPE)), this.inputs || (this.inputs = []), this.inputs.push(n), this.setSize(this.computeSize()), this.onInputAdded && this.onInputAdded(n), u.registerNodeAndSlotType(this, e), this.setDirtyCanvas(!0, !0), n; } /** remove an existing input slot */ removeInput(t) { this.disconnectInput(t); for (var e = this.inputs.splice(t, 1), i = t; i < this.inputs.length; ++i) if (this.inputs[i]) { var n = this.graph.links[this.inputs[i].link]; n && (n.target_slot -= 1); } this.setSize(this.computeSize()), this.onInputRemoved && this.onInputRemoved(t, e[0]), this.setDirtyCanvas(!0, !0); } moveInput(t, e) { const i = this.inputs[t]; if (i == null || e < 0 || e > this.inputs.length - 1) return; const n = this.inputs[e]; if (i.link != null) { const s = this.graph.links[i.link]; s.target_slot = e; } if (n.link != null) { const s = this.graph.links[n.link]; s.target_slot = t; } this.inputs[e] = i, this.inputs[t] = n; } /** * add an special connection to this node (used for special kinds of graphs) * @param name * @param type string defining the input type ("vec3","number",...) * @param pos position of the connection inside the node * @param direction if is input or output */ addConnection(t, e, i, n) { let s = { name: t, type: e, pos: i, direction: n, links: null }; return this.connections.push(s), s; } /** computes the size of a node according to its inputs and output slots */ computeSize(t = [0, 0]) { const e = ye(this, "overrideSize"); if (e) return e.concat(); var i = Math.max( this.inputs ? this.inputs.length : 1, this.outputs ? this.outputs.length : 1 ), n = t; i = Math.max(i, 1); var s = u.NODE_TEXT_SIZE, r = d(this.title), o = 0, a = 0; if (this.inputs) for (var l = 0, h = this.inputs.length; l < h; ++l) { var p = this.inputs[l], f = p.label || p.name || "", c = d(f); o < c && (o = c); } if (this.outputs) for (var l = 0, h = this.outputs.length; l < h; ++l) { var v = this.outputs[l], f = v.label || v.name || "", c = d(f); a < c && (a = c); } if (n[0] = Math.max(o + a + 10, r), n[0] = Math.max(n[0], u.NODE_WIDTH), this.widgets && this.widgets.length) for (const _ of this.widgets) n[0] = Math.max(n[0], _.width || u.NODE_WIDTH * 1.5); n[1] = (this.constructor.slot_start_y || 0) + i * u.NODE_SLOT_HEIGHT; var g = 0; if (this.widgets && this.widgets.length) { for (var l = 0, h = this.widgets.length; l < h; ++l) { const b = this.widgets[l]; b.hidden || (b.computeSize ? g += b.computeSize(n[0])[1] + 4 : g += u.NODE_WIDGET_HEIGHT + 4); } g += 8; } this.widgets_up ? n[1] = Math.max(n[1], g) : this.widgets_start_y != null ? n[1] = Math.max(n[1], g + this.widgets_start_y) : n[1] += g; function d(_) { return _ ? s * _.length * 0.6 : 0; } return this.constructor.min_height && n[1] < this.constructor.min_height && (n[1] = this.constructor.min_height), n[1] += 6, n; } /** * returns all the info available about a property of this node. * * @method getPropertyInfo * @param {String} property name of the property * @return {Object} the object with all the available info */ getPropertyInfo(t) { var e = null; if (this.properties_info) { for (var i = 0; i < this.properties_info.length; ++i) if (this.properties_info[i].name == t) { e = this.properties_info[i]; break; } } return this.constructor["@" + t] && (e = this.constructor["@" + t]), this.constructor.widgets_info && this.constructor.widgets_info[t] && (e = this.constructor.widgets_info[t]), !e && this.onGetPropertyInfo && (e = this.onGetPropertyInfo(t)), e || (e = {}), e.type || (e.type = typeof this.properties[t]), e.widget == "combo" && (e.type = "enum"), e; } /** * https://github.com/jagenjo/litegraph.js/blob/master/guides/README.md#node-widgets * @return created widget */ addWidget(t, e, i, n, s) { this.widgets || (this.widgets = []), !s && n && n.constructor === Object && (s = n, n = null), s && s.constructor === String && (s = { property: s }), n && n.constructor === String && (s || (s = {}), s.property = n, n = null), n && n.constructor !== Function && (console.warn("addWidget: callback must be a function"), n = null); var r = { type: t.toLowerCase(), name: e, value: i, callback: n, options: s || {} }; if (r.options.y !== void 0 && (r.y = r.options.y), !n && !r.options.callback && !r.options.property && console.warn("LiteGraph addWidget(...) without a callback or property assigned"), t == "combo" && !r.options.values) throw "LiteGraph addWidget('combo',...) requires to pass values in options: { values:['red','blue'] }"; return this.widgets.push(r), this.setSize(this.computeSize()), r; } addCustomWidget(t) { return this.widgets || (this.widgets = []), this.widgets.push(t), this.setSize(this.computeSize()), t; } setWidgetHidden(t, e) { t.hidden = e, this.setSize(this.computeSize()); } /** * returns the bounding of the object, used for rendering purposes * @return [x, y, width, height] */ getBounding(t) { return t = t || new Float32Array(4), t[0] = this.pos[0] - 4, t[1] = this.pos[1] - u.NODE_TITLE_HEIGHT, t[2] = this.size[0] + 4, t[3] = this.flags.collapsed ? u.NODE_TITLE_HEIGHT : this.size[1] + u.NODE_TITLE_HEIGHT, this.onBounding && this.onBounding(t), t; } /** checks if a point is inside the shape of a node */ isPointInside(t, e, i = 0, n = !1) { var s = this.graph && this.graph.isLive() ? 0 : u.NODE_TITLE_HEIGHT; if (n && (s = 0), this.flags && this.flags.collapsed) { if (u.isInsideRectangle( t, e, this.pos[0] - i, this.pos[1] - u.NODE_TITLE_HEIGHT - i, (this._collapsed_width || u.NODE_COLLAPSED_WIDTH) + 2 * i, u.NODE_TITLE_HEIGHT + 2 * i )) return !0; } else if (this.pos[0] - 4 - i < t && this.pos[0] + this.size[0] + 4 + i > t && this.pos[1] - s - i < e && this.pos[1] + this.size[1] + i > e) return !0; return !1; } /** checks if a point is inside a node slot, and returns info about which slot */ getSlotInPosition(t, e) { var i = [0, 0]; if (this.inputs) for (var n = 0, s = this.inputs.length; n < s; ++n) { var r = this.inputs[n]; if (this.getConnectionPos(!0, n, i), u.isInsideRectangle( t, e, i[0] - 10, i[1] - 5, 20, 10 )) return { input: r, slot: n, link_pos: i }; } if (this.outputs) for (var n = 0, s = this.outputs.length; n < s; ++n) { var o = this.outputs[n]; if (this.getConnectionPos(!1, n, i), u.isInsideRectangle( t, e, i[0] - 10, i[1] - 5, 20, 10 )) return { output: o, slot: n, link_pos: i }; } return null; } is(t) { const e = t.__LITEGRAPH_TYPE__; return e != null && this.type === e; } /** * returns the input slot with a given name (used for dynamic slots), -1 if not found * @param name the name of the slot * @return the slot (-1 if not found) */ findInputSlotIndexByName(t, e = !1, i) { if (!this.inputs) return -1; for (var n = 0, s = this.inputs.length; n < s; ++n) if (!(e && this.inputs[n].link && this.inputs[n].link != null) && !(i && i.includes(this.inputs[n].type)) && (!t || t == this.inputs[n].name)) return n; return -1; } findInputSlotByName(t, e = !1, i) { if (!this.inputs) return null; for (var n = 0, s = this.inputs.length; n < s; ++n) if (!(e && this.inputs[n].link && this.inputs[n].link != null) && !(i && i.includes(this.inputs[n].type)) && (!t || t == this.inputs[n].name)) return this.inputs[n]; return null; } /** * returns the output slot with a given name (used for dynamic slots), -1 if not found * @param name the name of the slot * @return the slot (-1 if not found) */ findOutputSlotIndexByName(t, e = !1, i) { if (!this.outputs) return -1; for (var n = 0, s = this.outputs.length; n < s; ++n) if (!(e && this.outputs[n].links && this.outputs[n].links != null) && !(i && i.includes(this.outputs[n].type)) && (!t || t == this.outputs[n].name)) return n; return -1; } findOutputSlotByName(t, e = !1, i) { if (!this.outputs) return null; for (var n = 0, s = this.outputs.length; n < s; ++n) if (!(e && this.outputs[n].links && this.outputs[n].links != null) && !(i && i.includes(this.outputs[n].type)) && (!t || t == this.outputs[n].name)) return this.outputs[n]; return null; } /** * findSlotByType for INPUTS */ findInputSlotIndexByType(t, e = !1, i = !1) { return this.findSlotByType(!0, t, !1, e, i); } /** * findSlotByType for OUTPUTS */ findOutputSlotIndexByType(t, e = !1, i = !1) { return this.findSlotByType(!1, t, !1, e, i); } /** * findSlotByType for INPUTS */ findInputSlotByType(t, e = !1, i = !1) { return this.findSlotByType(!0, t, !1, e, i); } /** * findSlotByType for OUTPUTS */ findOutputSlotByType(t, e = !1, i = !1) { return this.findSlotByType(!1, t, !1, e, i); } /** * returns the output (or input) slot with a given type, -1 if not found * @method findSlotByType * @param {boolean} input uise inputs instead of outputs * @param {string} type the type of the slot * @param {boolean} preferFreeSlot if we want a free slot (if not found, will return the first of the type anyway) * @return {number_or_object} the slot (-1 if not found) */ findSlotByType(t, e, i, n = !1, s = !1) { n = n || !1, s = s || !1; var r = t ? this.inputs : this.outputs; if (!r) return i ? null : -1; (e == "" || e == "*") && (e = 0); for (var o = 0, a = r.length; o < a; ++o) { var l = (e + "").toLowerCase().split(","), h = r[o].type == "0" || r[o].type == "*" ? "0" : r[o].type; let p = (h + "").toLowerCase().split(","); for (let f = 0; f < l.length; f++) for (let c = 0; c < p.length; c++) if (l[f] == "_event_" && (l[f] = I.EVENT), p[f] == "_event_" && (p[f] = I.EVENT), l[f] == "*" && (l[f] = I.DEFAULT), p[f] == "*" && (p[f] = I.DEFAULT), l[f] == p[c]) { let v = r[o]; if (n && v.links && v.links !== null || v.link && v.link !== null) continue; return i ? v : o; } } if (n && !s) for (var o = 0, a = r.length; o < a; ++o) { var l = (e + "").toLowerCase().split(","), h = r[o].type == "0" || r[o].type == "*" ? "0" : r[o].type; let g = (h + "").toLowerCase().split(","); for (let d = 0; d < l.length; d++) for (let _ = 0; _ < g.length; _++) if (l[d] == "*" && (l[d] = I.DEFAULT), g[d] == "*" && (g[d] = I.DEFAULT), l[d] == g[_]) return i ? r[o] : o; } return i ? null : -1; } /** * connect this node output to the input of another node BY TYPE * @method connectByType * @param {number_or_string} slot (could be the number of the slot or the string with the name of the slot) * @param {LGraphNode} node the target node * @param {string} target_type the input slot type of the target node * @return {Object} the link_info is created, otherwise null */ connectByTypeInput(t, e, i, n = {}) { var s = { createEventInCase: !0, firstFreeIfOutputGeneralInCase: !0, generalTypeInCase: !0 }, r = Object.assign(s, n); e && e.constructor === Number && (e = this.graph.getNodeById(e)); let o = i; i === I.EVENT ? o = I.ACTION : i === I.ACTION && (o = I.EVENT); let a = e.findInputSlotIndexByType(o, !0); if (a >= 0 && a !== null) return u.debug && console.debug("CONNbyTYPE type " + i + " for " + a), this.connect(t, e, a); if (u.debug && console.log("type " + i + " not found or not free?"), r.createEventInCase && i == I.EVENT) return u.debug && console.debug("connect WILL CREATE THE onTrigger " + i + " to " + e), this.connect(t, e, -1); if (r.generalTypeInCase) { let l = e.findInputSlotIndexByType(I.DEFAULT, !0, !0); if (u.debug && console.debug("connect TO a general type (*, 0), if not found the specific type ", i, " to ", e, "RES_SLOT:", l), l >= 0) return this.connect(t, e, l); } if (r.firstFreeIfOutputGeneralInCase && (i == 0 || i == "*" || i == "")) { let l = e.findInputSlotIndexByName(null, !0, [I.EVENT]); if (u.debug && console.debug("connect TO TheFirstFREE ", i, " to ", e, "RES_SLOT:", l), l >= 0) return this.connect(t, e, l); } return u.debug && console.error("no way to connect type: ", i, " to targetNODE ", e), null; } /** * connect this node input to the output of another node BY TYPE * @method connectByType * @param {number_or_string} slot (could be the number of the slot or the string with the name of the slot) * @param {LGraphNode} node the target node * @param {string} target_type the output slot type of the target node * @return {Object} the link_info is created, otherwise null */ connectByTypeOutput(t, e, i, n = {}) { var s = { createEventInCase: !0, firstFreeIfInputGeneralInCase: !0, generalTypeInCase: !0 }, r = Object.assign(s, n); e && e.constructor === Number && (e = this.graph.getNodeById(e)); let o = i; if (i === I.EVENT ? o = I.ACTION : i === I.ACTION && (o = I.EVENT), a = e.findOutputSlotIndexByType(o, !0), a >= 0 && a !== null) return console.debug("CONNbyTYPE OUT! type " + i + " for " + a + " to " + o), e.connect(a, this, t); if (r.generalTypeInCase) { var a = e.findOutputSlotIndexByType(0, !0, !0); if (a >= 0) return e.connect(a, this, t); } if ((r.createEventInCase && i == I.EVENT || i == I.ACTION) && u.do_add_triggers_slots) { var a = e.addOnExecutedOutput(); return e.connect(a, this, t); } if (r.firstFreeIfInputGeneralInCase && (i == 0 || i == "*" || i == "")) { let l = e.findOutputSlotIndexByName(null, !0, [I.EVENT, I.ACTION]); if (l >= 0) return e.connect(l, this, t); } return console.error("no way to connect byOUT type: ", i, " to sourceNODE ", e), console.error("type OUT! " + i + " not found or not free?"), null; } /** * connect this node output to the input of another node * @param slot (could be the number of the slot or the string with the name of the slot) * @param targetNode the target node * @param targetSlot the input slot of the target node (could be the number of the slot or the string with the name of the slot, or -1 to connect a trigger) * @return {Object} the linkInfo is created, otherwise null */ connect(t, e, i) { if (i = i || 0, !this.graph) throw new Error("Connect: Error, node doesn't belong to any graph. Nodes must be added first to a graph before connecting them."); if (typeof t == "string") { if (t = this.findOutputSlotIndexByName(t), t == -1) return u.debug && console.error("Connect: Error, no slot of name " + t), null; } else if (!this.outputs || t >= this.outputs.length) return u.debug && console.error("Connect: Error, slot number not found"), null; if (e && e.constructor === Number && (e = this.graph.getNodeById(e)), !e) throw "target node is null"; if (e == this) return u.debug && console.error("Connect: Error, can't connect node to itself!"), null; if (!e.graph) throw new Error("Connect: Error, target node doesn't belong to any graph. Nodes must be added first to a graph before connecting them."); if (typeof i == "string") { if (i = e.findInputSlotIndexByName(i), i == -1) return u.debug && console.error( "Connect: Error, no slot of name " + i ), null; } else if (i === I.EVENT) if (u.do_add_triggers_slots) e.changeMode(Z.ON_TRIGGER), i = e.findInputSlotIndexByName("onTrigger"); else return u.debug && console.error("Connect: Error, can't connect event target slot"), null; else if (!e.inputs || i >= e.inputs.length) return u.debug && console.error("Connect: Error, slot number not found"), null; var n = !1, s = e.inputs[i], r = null, o = this.outputs[t]; if (!this.outputs[t]) return u.debug && (console.warn("Connect: Invalid slot passed: " + t), console.warn(this.outputs)), null; if (e.onBeforeConnectInput && (i = e.onBeforeConnectInput(i)), i === -1 || i === null || !u.isValidConnection(o.type, s.type)) return this.setDirtyCanvas(!1, !0), n && this.graph.connectionChange(this, r), console.warn("Connect: Invalid connection: ", i, o.type, s.type), null; if (u.debug && console.debug("valid connection", o.type, s.type), e.onConnectInput && e.onConnectInput(i, o.type, o, this, t) === !1) return u.debug && console.debug("onConnectInput blocked", o.type, s.type), null; if (this.onConnectOutput && this.onConnectOutput(t, s.type, s, e, i) === !1) return u.debug && console.debug("onConnectOutput blocked", o.type, s.type), null; if (e.inputs[i] && e.inputs[i].link != null && (this.graph.beforeChange(), e.disconnectInput(i, { doProcessChange: !1 }), n = !0), o.links !== null && o.links.length) switch (o.type) { case I.EVENT: u.allow_multi_output_for_events || (this.graph.beforeChange(), this.disconnectOutput(t, null, { doProcessChange: !1 }), n = !0); break; } let a; return u.use_uuids ? a = oe() : a = ++this.graph.last_link_id, r = new he( a, s.type || o.type, this.id, t, e.id, i ), this.graph.links[r.id] && console.error("Link already exists in graph!", r.id, r, this.graph.links[r.id]), this.graph.links[r.id] = r, o.links == null && (o.links = []), o.links.push(r.id), e.inputs[i].link = r.id, this.graph && this.graph._version++, this.onConnectionsChange && this.onConnectionsChange( W.OUTPUT, t, !0, r, o ), e.onConnectionsChange && e.onConnectionsChange( W.INPUT, i, !0, r, s ), this.graph && this.graph.onNodeConnectionChange && (this.graph.onNodeConnectionChange( W.INPUT, e, i, this, t ), this.graph.onNodeConnectionChange( W.OUTPUT, this, t, e, i )), this.setDirtyCanvas(!1, !0), this.graph.afterChange(), this.graph.connectionChange(this, r), r; } /** * disconnect one output to an specific node * @param slot (could be the number of the slot or the string with the name of the slot) * @param targetNode the target node to which this slot is connected [Optional, if not targetNode is specified all nodes will be disconnected] * @return if it was disconnected successfully */ disconnectOutput(t, e, i) { if (typeof t == "string") { if (t = this.findOutputSlotIndexByName(t), t == -1) return u.debug && console.error("Connect: Error, no slot of name " + t), !1; } else if (!this.outputs || t >= this.outputs.length) return u.debug && console.error("Connect: Error, slot number not found"), !1; var n = this.outputs[t]; if (!n || !n.links || n.links.length == 0) return !1; if (e) { if (e.constructor === Number && (e = this.graph.getNodeById(e)), !e) throw "Target Node not found"; for (var s = 0, r = n.links.length; s < r; s++) { var o = n.links[s], a = this.graph.links[o]; if (a.target_id == e.id) { n.links.splice(s, 1); var l = e.inputs[a.target_slot]; l.link = null, delete this.graph.links[o], this.graph && this.graph._version++, e.onConnectionsChange && e.onConnectionsChange( W.INPUT, a.target_slot, !1, a, l ), this.onConnectionsChange && this.onConnectionsChange( W.OUTPUT, t, !1, a, n ), this.graph && this.graph.onNodeConnectionChange && this.graph.onNodeConnectionChange( W.OUTPUT, this, t ), this.graph && this.graph.onNodeConnectionChange && (this.graph.onNodeConnectionChange( W.OUTPUT, this, t ), this.graph.onNodeConnectionChange( W.INPUT, e, a.target_slot )); break; } } } else { for (var s = 0, r = n.links.length; s < r; s++) { var o = n.links[s], a = this.graph.links[o]; if (a) { var e = this.graph.getNodeById(a.target_id), l = null; this.graph && this.graph._version++, e && (l = e.inputs[a.target_slot], l.link = null, e.onConnectionsChange && e.onConnectionsChange( W.INPUT, a.target_slot, !1, a, l ), this.graph && this.graph.onNodeConnectionChange && this.graph.onNodeConnectionChange( W.INPUT, e, a.target_slot )), delete this.graph.links[o], this.onConnectionsChange && this.onConnectionsChange( W.OUTPUT, t, !1, a, n ), this.graph && this.graph.onNodeConnectionChange && (this.graph.onNodeConnectionChange( W.OUTPUT, this, t ), this.graph.onNodeConnectionChange( W.INPUT, e, a.target_slot )); } } n.links = null; } return this.setDirtyCanvas(!1, !0), this.graph.connectionChange(this), !0; } /** * disconnect one input * @param slot (could be the number of the slot or the string with the name of the slot) * @return if it was disconnected successfully */ disconnectInput(t, e = {}) { if (typeof t == "string") { if (t = this.findInputSlotIndexByName(t), t == -1) return u.debug && console.error("Connect: Error, no slot of name " + t), !1; } else if (!this.inputs || t >= this.inputs.length) return u.debug && console.error("Connect: Error, slot number not found"), !1; var i = this.inputs[t]; if (!i) return !1; var n = this.inputs[t].link; if (n != null) { this.inputs[t].link = null; var s = this.graph.links[n]; if (s) { var r = this.graph.getNodeById(s.origin_id); if (!r) return !1; var o = r.outputs[s.origin_slot]; if (!o || !o.links || o.links.length == 0) return !1; for (var a = 0, l = o.links.length; a < l; a++) if (o.links[a] == n) { o.links.splice(a, 1); break; } delete this.graph.links[n], this.graph && this.graph._version++, this.onConnectionsChange && this.onConnectionsChange( W.INPUT, t, !1, s, i ), r.onConnectionsChange && r.onConnectionsChange( W.OUTPUT, a, !1, s, o ), this.graph && this.graph.onNodeConnectionChange && (this.graph.onNodeConnectionChange( W.OUTPUT, r, a ), this.graph.onNodeConnectionChange(W.INPUT, this, t)); } } return this.setDirtyCanvas(!1, !0), this.graph && this.graph.connectionChange(this), !0; } /** * returns the center of a connection point in canvas coords * @param is_input true if if a input slot, false if it is an output * @param slot (could be the number of the slot or the string with the name of the slot) * @param out a place to store the output, to free garbage * @return the position **/ getConnectionPos(t, e, i = [0, 0], n = !1) { var s = 0; t && this.inputs && (s = this.inputs.length), !t && this.outputs && (s = this.outputs.length); var r = u.NODE_SLOT_HEIGHT * 0.5; if (this.flags.collapsed && !n) { var o = this._collapsed_width || u.NODE_COLLAPSED_WIDTH; return this.horizontal ? (i[0] = this.pos[0] + o * 0.5, t ? i[1] = this.pos[1] - u.NODE_TITLE_HEIGHT : i[1] = this.pos[1]) : (t ? i[0] = this.pos[0] : i[0] = this.pos[0] + o, i[1] = this.pos[1] - u.NODE_TITLE_HEIGHT * 0.5), i; } return t && e == -1 ? (i[0] = this.pos[0] + u.NODE_TITLE_HEIGHT * 0.5, i[1] = this.pos[1] + u.NODE_TITLE_HEIGHT * 0.5, i) : t && s > e && this.inputs[e].pos ? (i[0] = this.pos[0] + this.inputs[e].pos[0], i[1] = this.pos[1] + this.inputs[e].pos[1], i) : !t && s > e && this.outputs[e].pos ? (i[0] = this.pos[0] + this.outputs[e].pos[0], i[1] = this.pos[1] + this.outputs[e].pos[1], i) : this.horizontal ? (i[0] = this.pos[0] + (e + 0.5) * (this.size[0] / s), t ? i[1] = this.pos[1] - u.NODE_TITLE_HEIGHT : i[1] = this.pos[1] + this.size[1], i) : (t ? i[0] = this.pos[0] + r : i[0] = this.pos[0] + this.size[0] + 1 - r, i[1] = this.pos[1] + (e + 0.7) * u.NODE_SLOT_HEIGHT + (this.constructor.slot_start_y || 0), i); } /** Force align to grid */ alignToGrid() { this.pos[0] = u.CANVAS_GRID_SIZE * Math.round(this.pos[0] / u.CANVAS_GRID_SIZE), this.pos[1] = u.CANVAS_GRID_SIZE * Math.round(this.pos[1] / u.CANVAS_GRID_SIZE); } /** Console output */ trace(t) { this.console || (this.console = []), this.console.push(t), this.console.length > Ne.MAX_CONSOLE && this.console.shift(), this.graph.onNodeTrace && this.graph.onNodeTrace(this, t); } /** Forces to redraw or the main canvas (LGraphNode) or the bg canvas (links) */ setDirtyCanvas(t, e = !1) { this.graph && this.graph.sendActionToCanvas("setDirty", [t, e]); } loadImage(t) { var e = new Image(); e.src = u.node_images_path + t; var i = this; return e.onload = function() { i.setDirtyCanvas(!0); }, e; } /** Allows to get onMouseMove and onMouseUp events even if the mouse is out of focus */ captureInput(t) { if (!(!this.graph || !this.graph.list_of_graphcanvas)) for (var e = this.graph.list_of_graphcanvas, i = 0; i < e.length; ++i) { var n = e[i]; !t && n.node_capturing_input != this || (n.node_capturing_input = t ? this : null); } } isShowingTitle(t) { return this.titleMode == se.TRANSPARENT_TITLE || this.titleMode == se.NO_TITLE ? !1 : (this.titleMode == se.AUTOHIDE_TITLE && t, !0); } /** Collapse the node to make it smaller on the canvas */ collapse(t = !1) { this.graph._version++, !(this.collapsable === !1 && !t) && (this.flags.collapsed ? this.flags.collapsed = !1 : this.flags.collapsed = !0, this.setDirtyCanvas(!0, !0)); } /** Forces the node to do not move or realign on Z */ pin(t) { this.graph._version++, t === void 0 ? this.flags.pinned = !this.flags.pinned : this.flags.pinned = t; } localToScreen(t, e, i) { return [ (t + this.pos[0]) * i.ds.scale + i.ds.offset[0], (e + this.pos[1]) * i.ds.scale + i.ds.offset[1] ]; } getOptionalSlots() { return ye(this, "optionalSlots"); } }; let ae = Ne; ae.MAX_CONSOLE = 100; function we() { let t = []; return t = t.concat(Ae), t = t.concat([I.ACTION]), t = t.concat(u.slot_types_in.map((e) => e.toUpperCase())), t; } function We() { return we().map(J); } class $ extends ae { constructor(e) { super(e), this.properties = { name: "", type: "number", value: 0, subgraphID: null }, this.nameInGraph = "", this.clonable = !1, this.size = [180, 90]; let i = this; this.nameWidget = this.addWidget( "text", "Name", this.properties.name, this.setName.bind(this) ), u.graph_inputs_outputs_use_combo_widget ? this.typeWidget = this.addWidget( "combo", "Type", J(this.properties.type), this.setType.bind(this), { values: We } ) : this.typeWidget = this.addWidget( "text", "Type", J(this.properties.type), this.setType.bind(this) ), this.valueWidget = this.addWidget( "number", "Value", this.properties.value, function(n) { i.setProperty("value", n); } ), this.widgets_up = !0; } setName(e) { if (e == null || e === this.properties.name) return; const i = this.getParentSubgraph(); i && (e = i.getValidGraphInputName(e), this.setProperty("name", e)); } setType(e) { e || (e = "*"); let i = e; e === "-1" || e === "Action" ? i = I.ACTION : e === "-2" || e === "Event" ? i = I.EVENT : e === "0" && (i = "*"), this.setProperty("type", i); } onConfigure() { this.updateType(); } getParentSubgraph() { var e, i; return (i = (e = this.graph._subgraph_node) == null ? void 0 : e.graph) == null ? void 0 : i.getNodeById(this.properties.subgraphID); } /** ensures the type in the node output and the type in the associated graph input are the same */ updateType() { var e = this.properties.type; this.typeWidget.value = J(e); const i = this.outputs[0]; i.type != e && (u.isValidConnection(i.type, e) || this.disconnectOutput(0), i.type = e), e == "array" ? i.shape = k.GRID_SHAPE : e === I.EVENT || e === I.ACTION ? i.shape = k.BOX_SHAPE : i.shape = k.DEFAULT, e == "number" ? (this.valueWidget.type = "number", this.valueWidget.value = 0) : e == "boolean" ? (this.valueWidget.type = "toggle", this.valueWidget.value = !0) : e == "string" ? (this.valueWidget.type = "text", this.valueWidget.value = "") : (this.valueWidget.type = null, this.valueWidget.value = null), this.properties.value = this.valueWidget.value, this.graph && this.nameInGraph && Se(e) ? (this.graph.changeInputType(this.nameInGraph, e), i.type !== e && this.setOutputDataType(0, e)) : console.error("[GraphInput] Can't change output to type", e, this.graph, this.nameInGraph); } /** this is executed AFTER the property has changed */ onPropertyChanged(e, i) { if (e == "name") { if (i == "" || i == this.nameInGraph || i == "enabled") return !1; this.graph && (this.nameInGraph ? this.graph.renameInput(this.nameInGraph, i) : this.graph.addInput(i, "" + this.properties.type, null)), this.nameWidget.value = i, this.nameInGraph = i; } else e == "type" && this.updateType(); } getTitle() { return this.flags.collapsed ? this.properties.name : this.title; } onAction(e, i) { this.properties.type == I.EVENT && this.triggerSlot(0, i); } onExecute() { var e = this.properties.name, i = this.graph.inputs[e]; if (!i) { this.setOutputData(0, this.properties.value); return; } this.setOutputData(0, i.value !== void 0 ? i.value : this.properties.value); } onRemoved() { this.nameInGraph && this.graph.removeInput(this.nameInGraph); } } $.slotLayout = { inputs: [], outputs: [ { name: "", type: "number" } ] }; u.registerNodeType({ class: $, title: "Input", desc: "Input of the graph", type: "graph/input", hide_in_node_lists: !0 }); function Le() { let t = []; return t = t.concat(Ae), t = t.concat([I.EVENT]), t = t.concat(u.slot_types_out), t; } function Ye() { return Le().map(J); } class Q extends ae { constructor(e) { super(e), this.properties = { name: "", type: "number", subgraphID: null }, this.nameInGraph = "", this.clonable = !1, this.size = [180, 60], this.nameWidget = this.addWidget( "text", "Name", this.properties.name, this.setName.bind(this) ), u.graph_inputs_outputs_use_combo_widget ? this.typeWidget = this.addWidget( "combo", "Type", J(this.properties.type), this.setType.bind(this), { values: Ye } ) : this.typeWidget = this.addWidget( "text", "Type", J(this.properties.type), this.setType.bind(this) ), this.widgets_up = !0; } setName(e) { if (e == null || e === this.properties.name) return; const i = this.getParentSubgraph(); i && (e = i.getValidGraphOutputName(e), this.setProperty("name", e)); } setType(e) { e || (e = "*"); let i = e; e === "-1" || e === "Action" ? i = I.ACTION : e === "-2" || e === "Event" ? i = I.EVENT : e === "0" && (i = "*"), this.setProperty("type", i); } onConfigure() { this.updateType(); } getParentSubgraph() { var e, i; return (i = (e = this.graph._subgraph_node) == null ? void 0 : e.graph) == null ? void 0 : i.getNodeById(this.properties.subgraphID); } updateType() { var e = this.properties.type; const i = this.inputs[0]; this.typeWidget && (this.typeWidget.value = J(e)), e == "array" ? i.shape = k.GRID_SHAPE : e === I.EVENT || e === I.ACTION ? i.shape = k.BOX_SHAPE : i.shape = k.DEFAULT, i.type != e && ((e == "action" || e == "event") && (e = I.EVENT), u.isValidConnection(i.type, e) || this.disconnectInput(0), i.type = e), this.graph && this.nameInGraph && Se(e) ? (this.graph.changeOutputType(this.nameInGraph, e), i.type !== e && this.setInputDataType(0, e)) : console.error("Can't change GraphOutput to type", e, this.graph, this.nameInGraph); } /** this is executed AFTER the property has changed */ onPropertyChanged(e, i) { if (e == "name") { if (i == "" || i == this.nameInGraph || i == "enabled") return !1; this.graph ? this.nameInGraph ? this.graph.renameOutput(this.nameInGraph, i) : this.graph.addOutput(i, "" + this.properties.type, null) : console.error("[GraphOutput] missing graph!", e, i), this.nameWidget.value = i, this.nameInGraph = i; } else e == "type" && this.updateType(); } getTitle() { return this.flags.collapsed ? this.properties.name : this.title; } onAction(e, i, n) { const s = this.getParentSubgraph(); if (!s) return; const r = s.findOutputSlotIndexByName(this.properties.name); r == null || s.outputs[r] == null || s.triggerSlot(r, i); } onExecute() { const e = this.getInputData(0); this.graph.setOutputData(this.properties.name, e); } onRemoved() { this.nameInGraph && this.graph.removeOutput(this.nameInGraph); } } Q.slotLayout = { inputs: [ { name: "", type: "" } ], outputs: [] }; u.registerNodeType({ class: Q, title: "Output", desc: "Output of the graph", type: "graph/output", hide_in_node_lists: !0 }); var xe = /* @__PURE__ */ ((t) => (t[t.STATUS_STOPPED = 1] = "STATUS_STOPPED", t[t.STATUS_RUNNING = 2] = "STATUS_RUNNING", t))(xe || {}); const De = class { constructor(t) { this.supported_types = null, this.vars = {}, this.extra = {}, this.inputs = {}, this.outputs = {}, this.links = {}, this.list_of_graphcanvas = [], this._nodes = [], this._groups = [], this._nodes_by_id = {}, this._nodes_executable = null, this._nodes_in_order = [], this._version = -1, this._last_trigger_time = 0, this._is_subgraph = !1, this._subgraph_node = null, this.nodes_executing = [], this.nodes_actioning = [], this.nodes_executedAction = [], this.execution_timer_id = -1, this.execution_time = 0, this.errors_in_execution = !1, u.debug && console.log("Graph created"), this.list_of_graphcanvas = null, this.clear(), t && this.configure(t); } getSupportedTypes() { return this.supported_types || De.DEFAULT_SUPPORTED_TYPES; } /* * Gets the root graph above any subgraphs. */ getRootGraph() { const t = Array.from(this.iterateParentGraphs()), e = t[t.length - 1]; return e._is_subgraph ? null : e; } *iterateParentGraphs() { var e; let t = this; for (; t; ) yield t, t = (e = t._subgraph_node) == null ? void 0 : e.graph; } /** Removes all nodes from this graph */ clear() { if (this.stop(), this.status = 1, this.last_node_id = 0, this.last_link_id = 0, this._version = -1, this._nodes) for (var t = 0; t < this._nodes.length; ++t) { var e = this._nodes[t]; e.onRemoved && e.onRemoved(); } this._nodes = [], this._nodes_by_id = {}, this._nodes_in_order = [], this._nodes_executable = null, this._groups = [], this.links = {}, this.iteration = 0, this.config = {}, this.vars = {}, this.extra = {}, this.globaltime = 0, this.runningtime = 0, this.fixedtime = 0, this.fixedtime_lapse = 0.01, this.elapsed_time = 0.01, this.last_update_time = 0, this.starttime = 0, this.catch_errors = !0, this.nodes_executing = [], this.nodes_actioning = [], this.nodes_executedAction = [], this.inputs = {}, this.outputs = {}, this.change(), this.sendActionToCanvas("clear"); } /** Attach Canvas to this graph */ attachCanvas(t) { if (!(t instanceof N)) throw "attachCanvas expects a LGraphCanvas instance"; t.graph && t.graph != this && t.graph.detachCanvas(t), t.graph = this, this.list_of_graphcanvas || (this.list_of_graphcanvas = []), this.list_of_graphcanvas.push(t); } /** Detach Canvas to this graph */ detachCanvas(t) { if (this.list_of_graphcanvas) { var e = this.list_of_graphcanvas.indexOf(t); e != -1 && (t.graph = null, this.list_of_graphcanvas.splice(e, 1)); } } /** * Starts running this graph every interval milliseconds. * @param interval amount of milliseconds between executions, if 0 then it renders to the monitor refresh rate */ start(t) { if (this.status != 2) { this.status = 2, this.onPlayEvent && this.onPlayEvent(), this.sendEventToAllNodes("onStart"), this.starttime = u.getTime(), this.last_update_time = this.starttime, t = t || 0; var e = this; if (t == 0 && typeof window < "u" && window.requestAnimationFrame) { let i = function() { e.execution_timer_id == -1 && (window.requestAnimationFrame(i), e.onBeforeStep && e.onBeforeStep(), e.runStep(1, !e.catch_errors), e.onAfterStep && e.onAfterStep()); }; this.execution_timer_id = -1, i(); } else this.execution_timer_id = setInterval(function() { e.onBeforeStep && e.onBeforeStep(), e.runStep(1, !e.catch_errors), e.onAfterStep && e.onAfterStep(); }, t); } } /** Stops the execution loop of the graph */ stop() { this.status != 1 && (this.status = 1, this.onStopEvent && this.onStopEvent(), this.execution_timer_id != null && (this.execution_timer_id != -1 && clearInterval(this.execution_timer_id), this.execution_timer_id = null), this.sendEventToAllNodes("onStop")); } /** * Run N steps (cycles) of the graph * @param num number of steps to run, default is 1 * @param do_not_catch_errors if you want to try/catch errors */ runStep(t = 1, e = !1, i) { var n = u.getTime(); this.globaltime = 1e-3 * (n - this.starttime); let s = this._nodes_executable ? this._nodes_executable : this._nodes; if (s) { if (i = i || s.length, e) { for (var r = 0; r < t; r++) { for (var o = 0; o < i; ++o) { var a = s[o]; a.mode == Z.ALWAYS && a.onExecute && a.doExecute(); } this.fixedtime += this.fixedtime_lapse, this.onExecuteStep && this.onExecuteStep(); } this.onAfterExecute && this.onAfterExecute(); } else try { for (var r = 0; r < t; r++) { for (var o = 0; o < i; ++o) { var a = s[o]; a.mode == Z.ALWAYS && a.onExecute && a.onExecute(null, {}); } this.fixedtime += this.fixedtime_lapse, this.onExecuteStep && this.onExecuteStep(); } this.onAfterExecute && this.onAfterExecute(), this.errors_in_execution = !1; } catch (p) { if (this.errors_in_execution = !0, u.throw_errors) throw p; u.debug && console.log("Error during execution: " + p), this.stop(); } var l = u.getTime(), h = l - n; h == 0 && (h = 1), this.execution_time = 1e-3 * h, this.globaltime += 1e-3 * h, this.iteration += 1, this.elapsed_time = (l - this.last_update_time) * 1e-3, this.last_update_time = l, this.nodes_executing = [], this.nodes_actioning = [], this.nodes_executedAction = []; } } /** * Updates the graph execution order according to relevance of the nodes (nodes with only outputs have more relevance than * nodes with only inputs. */ updateExecutionOrder() { this._nodes_in_order = this.computeExecutionOrder(!1), this._nodes_executable = []; for (var t = 0; t < this._nodes_in_order.length; ++t) if (this._nodes_in_order[t].onExecute) { let e = this._nodes_in_order[t]; this._nodes_executable.push(e); } } *computeExecutionOrderRecursive(t = !1, e) { for (const i of this.computeExecutionOrder(t, e)) if (yield i, i.is(ne)) for (const n of i.subgraph.computeExecutionOrderRecursive(t, e)) yield n; } /** This is more internal, it computes the executable nodes in order and returns it */ computeExecutionOrder(t = !1, e) { for (var i = [], n = [], s = {}, r = {}, o = {}, a = 0, _ = this._nodes.length; a < _; ++a) { var l = this._nodes[a]; if (!(t && !l.onExecute)) { s[l.id] = l; var h = 0; if (l.inputs) for (var p = 0, f = l.inputs.length; p < f; p++) l.inputs[p] && l.inputs[p].link != null && (h += 1); h == 0 ? (n.push(l), e && (l._level = 1)) : (e && (l._level = 0), o[l.id] = h); } } for (; n.length != 0; ) { let y = n.shift(); if (i.push(y), delete s[y.id], !!y.outputs) for (var a = 0; a < y.outputs.length; a++) { var c = y.outputs[a]; if (!(c == null || c.links == null || c.links.length == 0)) for (var p = 0; p < c.links.length; p++) { var v = c.links[p], g = this.links[v]; if (g && !r[g.id]) { var d = this.getNodeById(g.target_id); if (d == null) { r[g.id] = !0; continue; } e && (!d._level || d._level <= y._level) && (d._level = y._level + 1), r[g.id] = !0, o[d.id] -= 1, o[d.id] == 0 && n.push(d); } } } } for (let y of Object.keys(s).sort()) i.push(s[y]); i.length != this._nodes.length && u.debug && console.warn("something went wrong, nodes missing"); for (var _ = i.length, a = 0; a < _; ++a) i[a].order = a; i = i.sort(function(y, b) { var m = y.constructor.priority || y.priority || 0, E = b.constructor.priority || b.priority || 0; return m == E ? y.order - b.order : m - E; }); for (var a = 0; a < _; ++a) i[a].order = a; return i; } /** * Returns all the nodes that could affect this one (ancestors) by crawling all the inputs recursively. * It doesn't include the node itself * @return an array with all the LGraphNodes that affect this node, in order of execution */ getAncestors(t) { for (var e = [], i = [t], n = {}; i.length; ) { var s = i.shift(); if (s.inputs) { !n[s.id] && s != t && (n[s.id] = !0, e.push(s)); for (var r = 0; r < s.inputs.length; ++r) { var o = s.getInputNode(r); o && e.indexOf(o) == -1 && i.push(o); } } } return e.sort(function(a, l) { return a.order - l.order; }), e; } /** * Positions every node in a more readable manner */ arrange(t = 100, e = ue.HORIZONTAL_LAYOUT) { const i = this.computeExecutionOrder(!1, !0), n = []; for (let r = 0; r < i.length; ++r) { const o = i[r], a = o._level || 1; n[a] || (n[a] = []), n[a].push(o); } let s = t; for (let r = 0; r < n.length; ++r) { const o = n[r]; if (!o) continue; let a = 100, l = t + u.NODE_TITLE_HEIGHT; for (let h = 0; h < o.length; ++h) { const p = o[h]; p.pos[0] = e == ue.VERTICAL_LAYOUT ? l : s, p.pos[1] = e == ue.VERTICAL_LAYOUT ? s : l; const f = e == ue.VERTICAL_LAYOUT ? 1 : 0; p.size[f] > a && (a = p.size[f]); const c = e == ue.VERTICAL_LAYOUT ? 0 : 1; l += p.size[c] + t + u.NODE_TITLE_HEIGHT; } s += a + t; } this.setDirtyCanvas(!0, !0); } /** * Returns the amount of time the graph has been running in milliseconds * @return number of milliseconds the graph has been running */ getTime() { return this.globaltime; } /** * Returns the amount of time accumulated using the fixedtime_lapse var. This is used in context where the time increments should be constant * @return number of milliseconds the graph has been running */ getFixedTime() { return this.fixedtime; } /** * Returns the amount of time it took to compute the latest iteration. Take into account that this number could be not correct * if the nodes are using graphical actions * @return number of milliseconds it took the last cycle */ getElapsedTime() { return this.elapsed_time; } /** * Iterates all nodes in this graph *excluding* subgraphs. */ *iterateNodesInOrder() { const t = this._nodes_in_order ? this._nodes_in_order : this._nodes || []; for (const e of t) yield e; } /** * Iterates all nodes in this graph and subgraphs. */ *iterateNodesInOrderRecursive() { const t = this._nodes_in_order ? this._nodes_in_order : this._nodes || []; for (const e of t) if (yield e, e.subgraph != null) for (const i of e.subgraph.iterateNodesInOrderRecursive()) yield i; } /** * Iterates all nodes in this graph *excluding* subgraphs. */ *iterateNodesOfClass(t) { const e = t.__LITEGRAPH_TYPE__; if (e != null) for (const i of this.iterateNodesInOrder()) i.type === e && (yield i); } /** * Iterates all nodes in this graph *excluding* subgraphs. */ *iterateNodesOfClassRecursive(t) { const e = t.__LITEGRAPH_TYPE__; if (e != null) for (const i of this.iterateNodesInOrderRecursive()) i.type === e && (yield i); } /** * Iterates all nodes in this graph *excluding* subgraphs. */ *iterateNodesOfTypeRecursive(t) { for (const e of this.iterateNodesInOrderRecursive()) e.type === t && (yield e); } /** * Sends an event to all the nodes, useful to trigger stuff * @param eventName the name of the event (function to be called) * @param params parameters in array format */ sendEventToAllNodes(t, e = [], i = Z.ALWAYS) { var n = this._nodes_in_order ? this._nodes_in_order : this._nodes; if (n) for (const s of this.iterateNodesInOrder()) { if (s.type === "basic/subgraph" && t != "onExecute") { s.mode == i && s.sendEventToAllNodes(t, e, i); continue; } !s[t] || s.mode != i || (e === void 0 ? s[t]() : e && e.constructor === Array ? s[t].apply(s, e) : s[t](e)); } } sendActionToCanvas(t, e = []) { if (this.list_of_graphcanvas) for (var i = 0; i < this.list_of_graphcanvas.length; ++i) { var n = this.list_of_graphcanvas[i]; n[t] && n[t].apply(n, e); } } addGroup(t) { return this._groups.push(t), this.setDirtyCanvas(!0), this.change(), t.graph = this, this._version++, t; } /** * Adds a new node instance to this graph * @param node the instance of the node */ add(t, e = {}) { if (t.id != -1 && this._nodes_by_id[t.id] != null && (console.warn( "LiteGraph: there is already a node with this ID, changing it", t.id ), u.use_uuids ? t.id = oe() : t.id = ++this.last_node_id), e.pos && (isNaN(e.pos[0]) || isNaN(e.pos[1]))) throw "LiteGraph: Node position contained NaN(s)!"; if (this._nodes.length >= u.MAX_NUMBER_OF_NODES) throw "LiteGraph: max number of nodes in a graph reached"; return u.use_uuids ? t.id || (t.id = oe()) : t.id == null || t.id == -1 ? t.id = ++this.last_node_id : this.last_node_id < t.id && (this.last_node_id = t.id), t.graph = this, this._version++, this._nodes.push(t), this._nodes_by_id[t.id] = t, e.pos && (t.pos = e.pos), t.onAdded && t.onAdded(this), this.config.align_to_grid && t.alignToGrid(), e.skipComputeOrder || this.updateExecutionOrder(), this.onNodeAdded && this.onNodeAdded(t, e), this.setDirtyCanvas(!0), this.change(), t; } /** Removes a node from the graph */ remove(t, e = {}) { if (t instanceof me) { var i = this._groups.indexOf(t); i != -1 && this._groups.splice(i, 1), t.graph = null, this._version++, this.setDirtyCanvas(!0, !0), this.change(); return; } if (this._nodes_by_id[t.id] != null && !t.ignore_remove) { if (this.beforeChange(), t.inputs) for (var n = 0; n < t.inputs.length; n++) { var s = t.inputs[n]; s.link != null && t.disconnectInput(n); } if (t.outputs) for (var n = 0; n < t.outputs.length; n++) { let l = t.outputs[n]; l.links != null && l.links.length && t.disconnectOutput(n); } if (t.onRemoved && t.onRemoved(e), t.graph = null, this._version++, this.list_of_graphcanvas) for (var n = 0; n < this.list_of_graphcanvas.length; ++n) { var r = this.list_of_graphcanvas[n]; r.selected_nodes[t.id] && delete r.selected_nodes[t.id], r.node_dragged == t && (r.node_dragged = null); } var o = this._nodes.indexOf(t); o != -1 && this._nodes.splice(o, 1), delete this._nodes_by_id[t.id], this.onNodeRemoved && this.onNodeRemoved(t, e), this.sendActionToCanvas("checkPanels"), this.setDirtyCanvas(!0, !0), this.afterChange(), this.change(), this.updateExecutionOrder(); } } /** Returns a node by its id. */ getNodeById(t) { return t == null ? null : this._nodes_by_id[t]; } /** Returns a node by its id. */ getNodeByIdRecursive(t) { const e = this.getNodeById(t); if (e != null) return e; for (const i of this.iterateNodesOfClass(ne)) { const n = i.subgraph.getNodeByIdRecursive(t); if (n) return n; } return null; } /** * Returns a list of nodes that matches a class * @param classObject the class itself (not an string) * @return a list with all the nodes of this type */ findNodesByClass(t, e = []) { e.length = 0; for (const i of this.iterateNodesOfClass(t)) e.push(i); return e; } /** * Returns a list of nodes that matches a type * @param type the name of the node type * @return a list with all the nodes of this type */ findNodesByType(i, e = []) { var i = i.toLowerCase(); e.length = 0; for (var n = 0, s = this._nodes.length; n < s; ++n) this._nodes[n].type.toLowerCase() == i && e.push(this._nodes[n]); return e; } /** * Returns a list of nodes that matches a class * @param classObject the class itself (not an string) * @return a list with all the nodes of this type */ findNodesByClassRecursive(t, e = []) { e.length = 0; for (const i of this.iterateNodesOfClassRecursive(t)) e.push(i); return e; } /** * Returns a list of nodes that matches a type * @param type the name of the node type * @return a list with all the nodes of this type */ findNodesByTypeRecursive(i, e = []) { var i = i.toLowerCase(); e.length = 0; for (const n of this.iterateNodesOfTypeRecursive(i)) e.push(n); return e; } /** * Returns the first node that matches a name in its title * @param title the name of the node to search * @return the node or null */ findNodeByTitle(t) { for (var e = 0, i = this._nodes.length; e < i; ++e) if (this._nodes[e].title == t) return this._nodes[e]; return null; } /** * Returns a list of nodes that matches a name * @param title the name of the node to search * @return a list with all the nodes with this name */ findNodesByTitle(t) { for (var e = [], i = 0, n = this._nodes.length; i < n; ++i) this._nodes[i].title == t && e.push(this._nodes[i]); return e; } /** * Returns the top-most node in this position of the canvas * @param x the x coordinate in canvas space * @param y the y coordinate in canvas space * @param nodesList a list with all the nodes to search from, by default is all the nodes in the graph * @return the node at this position or null */ getNodeOnPos(t, e, i, n) { i = i || this._nodes; for (var s = null, r = i.length - 1; r >= 0; r--) { var o = i[r], a = o.titleMode == se.NO_TITLE; if (o.isPointInside(t, e, n, a)) return o; } return s; } /** * Returns the top-most group in that position * @param x the x coordinate in canvas space * @param y the y coordinate in canvas space * @return the group or null */ getGroupOnPos(t, e) { for (var i = this._groups.length - 1; i >= 0; i--) { var n = this._groups[i]; if (n.isPointInside(t, e, 2, !0)) return n; } return null; } /** * Checks that the node type matches the node type registered, used when replacing a nodetype by a newer version during execution * this replaces the ones using the old version with the new version * @method checkNodeTypes */ checkNodeTypes() { for (var t = !1, e = 0; e < this._nodes.length; e++) { var i = this._nodes[e], n = u.registered_node_types[i.type]; if (i.constructor != n.class) { console.log("node being replaced by newer version: " + i.type); var s = u.createNode(i.type); t = !0, this._nodes[e] = s, s.configure(i.serialize()), s.graph = this, this._nodes_by_id[s.id] = s, i.inputs && (s.inputs = i.inputs.concat()), i.outputs && (s.outputs = i.outputs.concat()); } } return this.updateExecutionOrder(), t; } // ********** GLOBALS ***************** onAction(t, e, i = {}) { for (const n of this.iterateNodesOfClass($)) if (n.properties.name == t) { n.actionDo(t, e, i); break; } } trigger(t, e) { this.onTrigger && this.onTrigger(t, e); } triggerSlot(t, e) { this.onTrigger && this.onTrigger(t, e); } /** Tell this graph it has a global graph input of this type */ addInput(t, e, i) { var n = this.inputs[t]; n || (this.beforeChange(), this.inputs[t] = { name: t, type: e, value: i }, this._version++, this.afterChange(), this.onInputAdded && this.onInputAdded(t, e, i), this.onInputsOutputsChange && this.onInputsOutputsChange()); } /** Assign a data to the global graph input */ setInputData(t, e) { var i = this.inputs[t]; i && (i.value = e); } /** Returns the current value of a global graph input */ getInputData(t) { var e = this.inputs[t]; return e ? e.value : null; } /** Changes the name of a global graph input */ renameInput(t, e) { if (e != t) return this.inputs[t] ? this.inputs[e] ? (console.error("there is already one input with that name"), !1) : (this.inputs[e] = this.inputs[t], delete this.inputs[t], this._version++, this.onInputRenamed && this.onInputRenamed(t, e), this.onInputsOutputsChange && this.onInputsOutputsChange(), !0) : !1; } /** Changes the type of a global graph input */ changeInputType(t, e) { if (!this.inputs[t]) return !1; if (this.inputs[t].type && String(this.inputs[t].type).toLowerCase() == String(e).toLowerCase()) return; const i = this.inputs[t].type; return this.inputs[t].type = e, this._version++, this.onInputTypeChanged && this.onInputTypeChanged(t, i, e), !0; } /** Removes a global graph input */ removeInput(t) { return this.inputs[t] ? (delete this.inputs[t], this._version++, this.onInputRemoved && this.onInputRemoved(t), this.onInputsOutputsChange && this.onInputsOutputsChange(), !0) : !1; } /** Creates a global graph output */ addOutput(t, e, i) { this.outputs[t] = { name: t, type: e, value: i }, this._version++, this.onOutputAdded && this.onOutputAdded(t, e, i), this.onInputsOutputsChange && this.onInputsOutputsChange(); } /** Assign a data to the global output */ setOutputData(t, e) { var i = this.outputs[t]; i && (i.value = e); } /** Returns the current value of a global graph output */ getOutputData(t) { var e = this.outputs[t]; return e ? e.value : null; } /** Renames a global graph output */ renameOutput(t, e) { return this.outputs[t] ? this.outputs[e] ? (console.error("there is already one output with that name"), !1) : (this.outputs[e] = this.outputs[t], delete this.outputs[t], this._version++, this.onOutputRenamed && this.onOutputRenamed(t, e), this.onInputsOutputsChange && this.onInputsOutputsChange(), !0) : !1; } /** Changes the type of a global graph output */ changeOutputType(t, e) { if (!this.outputs[t]) return !1; if (this.outputs[t].type && String(this.outputs[t].type).toLowerCase() == String(e).toLowerCase()) return; const i = this.outputs[t].type; return this.outputs[t].type = e, this._version++, this.onOutputTypeChanged && this.onOutputTypeChanged(t, i, e), !0; } /** Removes a global graph output */ removeOutput(t) { return this.outputs[t] ? (delete this.outputs[t], this._version++, this.onOutputRemoved && this.onOutputRemoved(t), this.onInputsOutputsChange && this.onInputsOutputsChange(), !0) : !1; } /* TODO implement triggerInput(name: string, value: any): void { var nodes = this.findNodesByTitle(name); for (var i = 0; i < nodes.length; ++i) { nodes[i].onTrigger(value); } } setCallback(name: string, func: (...args: any[]) => any): void { var nodes = this.findNodesByTitle(name); for (var i = 0; i < nodes.length; ++i) { nodes[i].setTrigger(func); } } */ /** used for undo, called before any change is made to the graph */ beforeChange(t) { this.onBeforeChange && this.onBeforeChange(this, t), this.sendActionToCanvas("onBeforeChange", [this]); } /** used to resend actions, called after any change is made to the graph */ afterChange(t) { this.onAfterChange && this.onAfterChange(this, t), this.sendActionToCanvas("onAfterChange", [this]); } connectionChange(t, e) { this.updateExecutionOrder(), this.onConnectionChange && this.onConnectionChange(t), this._version++, this.sendActionToCanvas("onConnectionChange"); } /** returns if the graph is in live mode */ isLive() { if (!this.list_of_graphcanvas) return !1; for (var t = 0; t < this.list_of_graphcanvas.length; ++t) { var e = this.list_of_graphcanvas[t]; if (e.live_mode) return !0; } return !1; } /** clears the triggered slot animation in all links (stop visual animation) */ clearTriggeredSlots() { for (var t in this.links) { var e = this.links[t]; e && e._last_time && (e._last_time = 0); } } /* Called when something visually changed (not the graph!) */ change() { u.debug && console.log("Graph changed"), this.sendActionToCanvas("setDirty", [!0, !0]), this.onChange && this.onChange(this); } setDirtyCanvas(t = !1, e = !1) { this.sendActionToCanvas("setDirty", [t, e]); } /** Destroys a link */ removeLink(t) { var e = this.links[t]; if (e) { var i = this.getNodeById(e.target_id); i && i.disconnectInput(e.target_slot); } } /** Creates a Object containing all the info about this graph, it can be serialized */ serialize() { for (var t = [], e = 0, i = this._nodes.length; e < i; ++e) t.push(this._nodes[e].serialize()); var n = []; for (const h in this.links) { var s = this.links[h]; if (!s.serialize) { console.error( "weird LLink bug, link info is not a LLink but a regular object", s ); var r = he.configure(s); for (var o in s) r[o] = s[o]; this.links[h] = r, s = r; } n.push(s.serialize()); } for (var a = [], e = 0; e < this._groups.length; ++e) a.push(this._groups[e].serialize()); var l = { last_node_id: this.last_node_id, last_link_id: this.last_link_id, nodes: t, links: n, groups: a, config: this.config, extra: this.extra, version: u.VERSION }; return this.onSerialize && this.onSerialize(l), l; } /** * Configure a graph from a JSON string * @param data configure a graph from a JSON string * @returns if there was any error parsing */ configure(t, e) { if (t) { e || this.clear(); var i = t.nodes; if (t.links && t.links.constructor === Array) { for (var n = [], s = 0; s < t.links.length; ++s) { var r = t.links[s]; if (!r) { console.warn("serialized graph link data contains errors, skipping."); continue; } var o = he.configure(r); n[o.id] = o; } t.links = n; } for (const c in t) c == "nodes" || c == "groups" || (this[c] = t[c]); var a = !1; if (this._nodes = [], i) { for (var s = 0, l = i.length; s < l; ++s) { var h = i[s], p = u.createNode(h.type, h.title); p || (console.error( "Node not found or has errors: " + h.type ), p = new ae(), p.last_serialization = h, p.has_errors = !0, a = !0), p.id = h.id, this.add(p, { addedBy: "configure", skipComputeOrder: !0 }); } for (var s = 0, l = i.length; s < l; ++s) { var h = i[s], p = this.getNodeById(h.id); p && p.configure(h); } } if (this._groups.length = 0, t.groups) for (var s = 0; s < t.groups.length; ++s) { var f = new me(); f.configure(t.groups[s]), this.addGroup(f); } return this.updateExecutionOrder(), this.extra = t.extra || {}, this.onConfigure && this.onConfigure(t), this._version++, this.setDirtyCanvas(!0, !0), a; } } load(t, e) { var i = this; if (t.constructor === File || t.constructor === Blob) { var n = new FileReader(); n.addEventListener("load", function(r) { var o = JSON.parse(n.result); i.configure(o), e && e(o); }), n.readAsText(t); return; } var s = new XMLHttpRequest(); s.open("GET", t, !0), s.send(null), s.onload = function(r) { if (s.status !== 200) { console.error("Error loading graph:", s.status, s.response); return; } var o = JSON.parse(s.response); i.configure(o), e && e(o); }, s.onerror = function(r) { console.error("Error loading graph:", r); }; } }; let Pe = De; Pe.DEFAULT_SUPPORTED_TYPES = ["number", "string", "boolean"]; function Re(t) { const e = { nodeIDs: {}, linkIDs: {} }; for (const i of t.nodes) { const n = i.id, s = oe(); if (i.id = s, e.nodeIDs[n] || e.nodeIDs[s]) throw new Error( `New/old node UUID wasn't unique in changed map! ${n} ${s}` ); e.nodeIDs[n] = s, e.nodeIDs[s] = n; } for (const i of t.links) { const n = i[0], s = oe(); if (i[0] = s, e.linkIDs[n] || e.linkIDs[s]) throw new Error( `New/old link UUID wasn't unique in changed map! ${n} ${s}` ); e.linkIDs[n] = s, e.linkIDs[s] = n; const r = i[1], o = i[3]; if (!e.nodeIDs[r]) throw new Error(`Old node UUID not found in mapping! ${r}`); if (i[1] = e.nodeIDs[r], !e.nodeIDs[o]) throw new Error(`Old node UUID not found in mapping! ${o}`); i[3] = e.nodeIDs[o]; } for (const i of t.nodes) { for (const n of i.inputs) n.link && (n.link = e.linkIDs[n.link]); for (const n of i.outputs) n.links && (n.links = n.links.map((s) => e.linkIDs[s])); } for (const i of t.nodes) if (i.type === "graph/subgraph") { const n = Re( i.subgraph ); e.nodeIDs = { ...e.nodeIDs, ...n.nodeIDs }, e.linkIDs = { ...e.linkIDs, ...n.linkIDs }; } return e; } function Ve(t, e) { for (const i of t.iterateNodesInOrderRecursive()) i.onReassignID && i.onReassignID(e); } const Me = class extends ae { constructor(t, e) { super(t), this.properties = { enabled: !0 }, this.size = [140, 80], this.enabled = !0, this.subgraph = (e || Me.default_lgraph_factory)(), this.subgraph._subgraph_node = this, this.subgraph._is_subgraph = !0; const i = (n, s) => { const r = s.bind(this); return function(...o) { n == null || n.apply(this, o), r(...o); }; }; this.subgraph.onTrigger = i( this.subgraph.onTrigger, this.onSubgraphTrigger ), this.subgraph.onNodeAdded = i( this.subgraph.onNodeAdded, this.onSubgraphNodeAdded ), this.subgraph.onNodeRemoved = i( this.subgraph.onNodeRemoved, this.onSubgraphNodeRemoved ), this.subgraph.onInputAdded = i( this.subgraph.onInputAdded, this.onSubgraphNewInput ), this.subgraph.onInputRenamed = i( this.subgraph.onInputRenamed, this.onSubgraphRenamedInput ), this.subgraph.onInputTypeChanged = i( this.subgraph.onInputTypeChanged, this.onSubgraphTypeChangeInput ), this.subgraph.onInputRemoved = i( this.subgraph.onInputRemoved, this.onSubgraphRemovedInput ), this.subgraph.onOutputAdded = i( this.subgraph.onOutputAdded, this.onSubgraphNewOutput ), this.subgraph.onOutputRenamed = i( this.subgraph.onOutputRenamed, this.onSubgraphRenamedOutput ), this.subgraph.onOutputTypeChanged = i( this.subgraph.onOutputTypeChanged, this.onSubgraphTypeChangeOutput ), this.subgraph.onOutputRemoved = i( this.subgraph.onOutputRemoved, this.onSubgraphRemovedOutput ); } // getRootGraph(): LGraph | null { // const graphs = Array.from(this.iterateParentGraphs()); // const graph = graphs[graphs.length - 1] // // console.warn(graph._is_subgraph) // if (graph._is_subgraph) // return null; // return graph; // } *iterateParentGraphs() { var e; let t = this.graph; for (; t; ) yield t, t = (e = t._subgraph_node) == null ? void 0 : e.graph; } onDblClick(t, e, i) { var n = this; setTimeout(function() { i.openSubgraph(n.subgraph); }, 10); } onAction(t, e, i) { const { originNode: n, link: s } = i; if (!n || !s) return; const r = s.target_slot; this.getInnerGraphInputByIndex(r).triggerSlot(0, e); } onExecute() { if (this.enabled = this.getInputOrProperty("enabled"), !!this.enabled) { if (this.inputs) for (var t = 0; t < this.inputs.length; t++) { var e = this.inputs[t], i = this.getInputData(t); this.subgraph.setInputData(e.name, i); } if (this.subgraph.runStep(), this.outputs) for (var t = 0; t < this.outputs.length; t++) { var n = this.outputs[t], i = this.subgraph.getOutputData(n.name); this.setOutputData(t, i); } } } sendEventToAllNodes(t, e, i) { this.enabled && this.subgraph.sendEventToAllNodes(t, e, i); } onDrawBackground(t, e, i, n) { } // override onMouseDown(e, localpos, graphcanvas) // { // var y = this.size[1] - LiteGraph.NODE_TITLE_HEIGHT + 0.5; // if(localpos[1] > y) // { // graphcanvas.showSubgraphPropertiesDialog(this); // } // } // override onMouseDown(e: MouseEventExt, localpos: Vector2, graphcanvas: LGraphCanvas): boolean | undefined { // var y = this.size[1] - LiteGraph.NODE_TITLE_HEIGHT + 0.5; // console.log(0) // if (localpos[1] > y) { // if (localpos[0] < this.size[0] / 2) { // console.log(1) // graphcanvas.showSubgraphPropertiesDialog(this); // } else { // console.log(2) // graphcanvas.showSubgraphPropertiesDialogRight(this); // } // } // return false; // } computeSize() { var t = this.inputs ? this.inputs.length : 0, e = this.outputs ? this.outputs.length : 0; return [ 200, Math.max(t, e) * u.NODE_SLOT_HEIGHT + u.NODE_SLOT_HEIGHT * 0.5 ]; } //**** INPUTS *********************************** onSubgraphTrigger(t, e) { } onSubgraphNodeAdded(t, e) { var i, n; (i = this.graph) != null && i.onNodeAdded && (e.subgraphs || (e.subgraphs = []), e.subgraphs.push(this), (n = this.graph) == null || n.onNodeAdded(t, e)); } onSubgraphNodeRemoved(t, e) { var i, n; (i = this.graph) != null && i.onNodeRemoved && (e.subgraphs || (e.subgraphs = []), e.subgraphs.push(this), (n = this.graph) == null || n.onNodeRemoved(t, e)); } onSubgraphNewInput(t, e) { var i = this.findInputSlotIndexByName(t); i == -1 && this.addInput(t, e); } onSubgraphRenamedInput(t, e) { var i = this.findInputSlotIndexByName(t); if (i != -1) { var n = this.getInputInfo(i); n.name = e; } } onSubgraphTypeChangeInput(t, e, i) { var n = this.findInputSlotIndexByName(t); if (n != -1) { var s = this.getInputInfo(n); s.type = i; } } onSubgraphRemovedInput(t) { var e = this.findInputSlotIndexByName(t); e != -1 && this.removeInput(e); } //**** OUTPUTS *********************************** onSubgraphNewOutput(t, e) { var i = this.findOutputSlotIndexByName(t); i == -1 && this.addOutput(t, e); } onSubgraphRenamedOutput(t, e) { var i = this.findOutputSlotIndexByName(t); if (i != -1) { var n = this.getOutputInfo(i); n.name = e; } } onSubgraphTypeChangeOutput(t, e, i) { var n = this.findOutputSlotIndexByName(t); if (n != -1) { var s = this.getOutputInfo(n); s.type = i; } } onSubgraphRemovedOutput(t) { var e = this.findOutputSlotIndexByName(t); e != -1 && this.removeOutput(e); } // ***************************************************** getExtraMenuOptions(t, e) { var i = this; return [ { content: "Open", callback: function() { t.openSubgraph(i.subgraph); } } ]; } onResize(t) { console.error("TEST subgraph resize"); } serialize() { var t = ae.prototype.serialize.call(this); return t.subgraph = this.subgraph.serialize(), t; } //no need to define node.configure, the default method detects node.subgraph and passes the object to node.subgraph.configure() onConfigure(t) { super.onConfigure && super.onConfigure(t), this.subgraph._is_subgraph = !0, this.subgraph._subgraph_node = this; for (const e of this.subgraph.iterateNodesInOrder()) (e.is($) || e.is(Q)) && (e.properties.subgraphID = this.id); } onReassignID() { for (const t of this.subgraph.iterateNodesInOrder()) (t.is($) || t.is(Q)) && (t.properties.subgraphID = this.id); } clone(t = { forNode: {} }) { var s, r, o, a; var e = u.createNode(this.type), i = this.serialize(); let n = null; if (u.use_uuids) { const l = u.cloneObject(i.subgraph); n = Re(l), i.subgraph = l; } return delete i.id, delete i.inputs, delete i.outputs, e.configure(i), u.use_uuids && Ve(e.subgraph, n), (s = t.forNode)[r = this.id] || (s[r] = {}), t.forNode[this.id].subgraphNewIDMapping = n, (o = t.forNode)[a = e.id] || (o[a] = {}), t.forNode[e.id].subgraphNewIDMapping = n, e; } buildFromNodes(t) { var _, y; if (t = t.filter((b) => !b.is($) && !b.is(Q)), t.length === 0) return; const e = {}, i = {}, n = {}, s = t.reduce((b, m) => (b[m.id] = m, b), {}); let r = Number.MAX_SAFE_INTEGER, o = 0, a = Number.MAX_SAFE_INTEGER, l = 0; for (const b of Object.values(t)) r = Math.min(b.pos[0], r), o = Math.max(b.pos[0] + b.size[0], o), a = Math.min(b.pos[1], a), l = Math.max(b.pos[1] + b.size[1], l); const h = {}; for (const b of t) { h[b.id] = b; for (let m = 0; m < b.inputs.length; m++) { const E = b.getInputLink(m); if (E) { const T = b.getConnectionPos(!0, m), O = b.getInputInfo(m), A = b.getInputNode(m); A && (h[A.id] = A), s[E.origin_id] != null ? n[E.id] = [E, T] : e[E.id] = [E, T, O.name]; } } for (let m = 0; m < b.outputs.length; m++) { const E = b.getOutputLinks(m); for (const T of E) { const O = b.getConnectionPos(!1, m), A = b.getOutputInfo(m), M = b.graph.getNodeById(T.target_id); M && (h[M.id] = M), s[T.target_id] != null ? n[T.id] = [T, O] : i[T.id] = [T, O, A.name]; } } } const p = Object.values(e), f = Object.values(i); p.sort((b, m) => b[1][1] - m[1][1]), f.sort((b, m) => b[1][1] - m[1][1]), u.debug && (console.debug("NODES", Object.keys(t)), console.debug("IN", Object.keys(e)), console.debug("OUT", Object.keys(i)), console.debug("INNER", Object.keys(n))); const c = {}, v = {}; for (const b of t) { const m = [b.pos[0] - r, b.pos[1] - a], E = b.id; b.graph.remove(b, { removedBy: "moveIntoSubgraph" }), this.subgraph.add(b, { addedBy: "moveIntoSubgraph", prevNodeID: E }), b.pos = m, h[E] = b, h[b.id] = b; } let g = 0, d = 0; for (const [b, m, E] of p) { let T = null; if (c[b.origin_id] && (T = c[b.origin_id][b.origin_slot]), !T && (T = this.addGraphInput(E, b.type, [ -200, g ]), g += T.innerNode.size[1] + u.NODE_SLOT_HEIGHT, !T)) { console.error( "Failed creating subgraph output pair!", b ); continue; } const O = h[b.origin_id], A = h[b.target_id]; O.connect(b.origin_slot, this, T.outerInputIndex), T.innerNode.connect(0, A, b.target_slot), c[_ = b.origin_id] || (c[_] = {}), c[b.origin_id][b.origin_slot] = T; } for (const [b, m, E] of f) { let T = null; if (v[b.target_id] && (T = v[b.target_id][b.target_slot]), !T && (T = this.addGraphOutput(E, b.type, [ o - r + 200, d ]), d += T.innerNode.size[1] + u.NODE_SLOT_HEIGHT, !T)) { console.error( "Failed creating subgraph output pair!", b ); continue; } const O = h[b.origin_id], A = h[b.target_id]; O.connect(b.origin_slot, T.innerNode, 0), this.connect(T.outerOutputIndex, A, b.target_slot), v[y = b.target_id] || (v[y] = {}), v[b.target_id][b.origin_slot] = T; } for (const [b, m] of Object.values(n)) { const E = h[b.origin_id], T = h[b.target_id]; E.connect( b.origin_slot, T, b.target_slot ); } } addGraphInput(t, e, i) { t = this.getValidGraphInputName(t); const n = u.createNode($); if (n == null) return null; let s = e; e === I.EVENT ? s = I.ACTION : e === I.ACTION && (e = I.EVENT), console.warn("[Subgraph] addGraphInput", t, e, s, i), n.setProperty("name", t), n.setProperty("type", e), n.properties.subgraphID = this.id, this.subgraph.add(n); const r = n.computeSize(); i && (n.pos = [ i[0] - r[0] * 0.5, i[1] - r[1] * 0.5 ]), this.subgraph.addInput(t, s, null); const o = this.inputs.length - 1, a = this.inputs[o]; return { innerNode: n, outerInput: a, outerInputIndex: o }; } addGraphOutput(t, e, i) { t = this.getValidGraphOutputName(t); const n = u.createNode(Q); if (n == null) return null; let s = e; e === I.EVENT ? e = I.ACTION : e === I.ACTION && (s = I.EVENT), console.warn("[Subgraph] addGraphOutput", t, e, s, i), n.setProperty("name", t), n.setProperty("type", e), n.properties.subgraphID = this.id, this.subgraph.add(n); const r = n.computeSize(); i && (n.pos = [i[0], i[1] - r[1] * 0.5]), this.subgraph.addOutput(t, s, null); const o = this.outputs.length - 1, a = this.outputs[o]; return { innerNode: n, outerOutput: a, outerOutputIndex: o }; } removeGraphInput(t) { if (this.findInputSlotIndexByName(t) == null) { console.error("[Subgraph] No input in slot!", t); return; } const i = this.subgraph.findNodesByClass($).filter((n) => n.properties.name === t); if (i.length > 0) for (const n of i) this.subgraph.remove(n); else { console.warn( "[Subgraph] No GraphInputs found on input removal", t ); const n = this.findInputSlotIndexByName(t); n !== -1 && this.removeInput(n); } } removeGraphOutput(t) { if (this.findOutputSlotIndexByName(t) == null) { console.error("[Subgraph] No output in slot!", t); return; } const i = this.subgraph.findNodesByClass(Q).filter((n) => n.properties.name === t); if (i.length > 0) for (const n of i) this.subgraph.remove(n); else { console.warn( "[Subgraph] No GraphOutputs found on output removal", t ); const n = this.findOutputSlotIndexByName(t); n !== -1 && this.removeOutput(n); } } getValidGraphInputName(t) { t || (t = "newInput"); let e = t, i = this.getInnerGraphInput(e), n = 1; for (; i != null; ) e = `${t}_${n++}`, i = this.getInnerGraphInput(e); return e; } getValidGraphOutputName(t) { t || (t = "newOutput"); let e = t, i = this.getInnerGraphOutput(e), n = 1; for (; i != null; ) e = `${t}_${n++}`, i = this.getInnerGraphOutput(e); return e; } getInnerGraphOutput(t) { return this.subgraph._nodes.find((i) => i.is(Q) && i.properties.name === t) || null; } getInnerGraphInput(t) { return this.subgraph._nodes.find((i) => i.is($) && i.properties.name === t) || null; } getInnerGraphOutputByIndex(t) { const e = this.getOutputInfo(t); return e ? this.getInnerGraphOutput(e.name) : null; } getInnerGraphInputByIndex(t) { const e = this.getInputInfo(t); return e ? this.getInnerGraphInput(e.name) : null; } moveNodesToParentGraph(t) { if (t = t.filter((g) => !g.is($) && !g.is(Q)), t.length === 0) return; const e = this, i = e.graph; let n = Number.MAX_SAFE_INTEGER, s = 0, r = Number.MAX_SAFE_INTEGER, o = 0; for (const g of Object.values(t)) n = Math.min(g.pos[0], n), s = Math.max(g.pos[0] + g.size[0], s), r = Math.min(g.pos[1], r), o = Math.max(g.pos[1] + g.size[1], o); const a = s - n, l = o - r, h = e.pos[0] + e.size[0] / 2 - a / 2, p = e.pos[1] + e.size[1] / 2 - l / 2, f = {}, c = {}; for (const [g, d] of t.entries()) c[d.id] = d; for (const g of t) for (const d of g.iterateAllLinks()) { const _ = d.target_id === g.id, y = g.getConnectionPos( _, _ ? d.target_slot : d.origin_slot ); c[d.origin_id] != null && c[d.target_id] != null && (f[d.id] = [d, y]); } const v = {}; for (const [g, d] of t.entries()) { const _ = [ d.pos[0] - n + h, d.pos[1] - r + p ], y = d.id; d.graph.remove(d, { removedBy: "moveOutOfSubgraph" }), i.add(d, { addedBy: "moveOutOfSubgraph", prevNodeID: y }), d.pos = _, v[y] = d; } for (const [g, d] of Object.values(f)) { const _ = c[g.origin_id], y = c[g.target_id]; _.connect(g.origin_slot, y, g.target_slot); } return v; } convertNodesToSubgraphInputs(t) { var a; if (t = t.filter((l) => !l.is($) && !l.is(Q)), t.length === 0) return; const e = ve(t, (l) => l.id), i = [], n = {}, s = this.subgraph; for (const l of t) for (const h of l.iterateAllLinks()) { if (e[h.origin_id] == null) throw new Error( "Can't convert to input with an origin link outward" ); if (e[h.target_id] == null) { i.push(h); const p = [0, 0]; l.getConnectionPos(!1, h.target_slot, p), n[l.id] = [ [l.pos[0], l.pos[1]], p ]; } } const r = this.moveNodesToParentGraph(t), o = {}; for (const l of i) { const h = s.getNodeById(l.target_id), p = h.getInputInfo(l.target_slot); o[a = l.origin_id] || (o[a] = {}); let f = o[l.origin_id][l.origin_slot]; if (f == null) { const v = this.getValidGraphInputName(p.name); f = this.addGraphInput(v, p.type), o[l.origin_id][l.origin_slot] = f; const [g, d] = n[l.origin_id], _ = f.innerNode.pos, y = f.innerNode.computeSize(), b = f.innerNode.getConnectionPos(!0, 0), m = [ f.innerNode.pos[0] - b[0], f.innerNode.pos[1] - b[1] ], E = [ d[0] + m[0] - y[0], d[1] + m[1] ]; console.warn( "newPos", _, "size", f.innerNode.size, "connPos", d, "newConPos", b, "offset", m ), f.innerNode.pos = E; } r[l.origin_id].connect(l.origin_slot, this, f.outerInputIndex), f.innerNode.connect(0, h, l.target_slot); } } convertNodesToSubgraphOutputs(t) { var a; if (t = t.filter((l) => !l.is($) && !l.is(Q)), t.length === 0) return; const e = ve(t, (l) => l.id), i = [], n = {}, s = this.subgraph; for (const l of t) for (const h of l.iterateAllLinks()) if (e[h.origin_id] == null) { i.push(h); const p = [0, 0]; l.getConnectionPos(!0, h.origin_slot, p), n[l.id] = [ [l.pos[0], l.pos[1]], p ]; } else if (e[h.target_id] == null) throw new Error( "Can't convert to input with an origin link outward" ); const r = this.moveNodesToParentGraph(t), o = {}; for (const l of i) { const h = s.getNodeById(l.origin_id), p = h.getOutputInfo(l.origin_slot); o[a = l.target_id] || (o[a] = {}); let f = o[l.target_id][l.target_slot]; if (f == null) { const v = this.getValidGraphOutputName(p.name); f = this.addGraphOutput(v, p.type), o[l.target_id][l.target_slot] = f; const [g, d] = n[l.target_id], _ = f.innerNode.getConnectionPos(!0, 0), y = [ f.innerNode.pos[0] - _[0], f.innerNode.pos[1] - _[1] ], b = [ d[0] + y[0], d[1] + y[1] ]; f.innerNode.pos = b; } const c = r[l.target_id]; h.connect(l.origin_slot, f.innerNode, 0), this.connect(f.outerOutputIndex, c, l.target_slot); } } }; let ne = Me; ne.default_lgraph_factory = () => new Pe(); ne.slotLayout = { inputs: [], outputs: [] }; ne.propertyLayout = [ { name: "enabled", defaultValue: !0 } ]; ne.optionalSlots = { outputs: [{ name: "enabled", type: "boolean" }] }; u.registerNodeType({ class: ne, title: "Subgraph", desc: "Graph inside a node", title_color: "#334", type: "graph/subgraph" }); class C { static onMenuCollapseAll() { } static onMenuNodeEdit() { } // refactor: there are different dialogs, some uses createDialog some dont prompt(e = "", i, n, s, r = !1, o = null) { var a = this, l = document.createElement("div"); if (l.is_modified = !1, l.className = "graphdialog rounded", r) { let T = 5; typeof i != "string" && (i = JSON.stringify(i, null, 2)); const O = (i.match(/\n/g) || "").length + 1; T = Te(O, 5, 10), l.innerHTML = ` `; } else l.innerHTML = ` `; l.close = function() { a.prompt_box = null, l.parentNode && l.parentNode.removeChild(l); }; var h = N.active_canvas, p = h.canvas; p.parentNode.appendChild(l), this.ds.scale > 1 && (l.style.transform = "scale(" + this.ds.scale + ")"); var f = null, c = 0; u.pointerListenerAdd(l, "leave", function(T) { c || u.dialog_close_on_mouse_leave && !l.is_modified && u.dialog_close_on_mouse_leave && T.buttons === 0 && (f = setTimeout(l.close, u.dialog_close_on_mouse_leave_delay)); }), u.pointerListenerAdd(l, "enter", function(T) { u.dialog_close_on_mouse_leave && f && clearTimeout(f); }); var v = l.querySelectorAll("select"); v && v.forEach(function(T) { T.addEventListener("click", function(O) { c++; }), T.addEventListener("blur", function(O) { c = 0; }), T.addEventListener("change", function(O) { c = -1; }); }), a.prompt_box && a.prompt_box.close(), a.prompt_box = l; var g = l.querySelector(".name"); g.innerText = e; let d = l.querySelector(".value"); d.value = i; var _ = d; if (_.addEventListener("keydown", function(T) { if (l.is_modified = !0, T.keyCode == 27) l.close(); else if (T.keyCode == 13 && T.target instanceof Element && T.target.localName != "textarea") n && n(this.value), l.close(); else return; T.preventDefault(), T.stopPropagation(); }), o) for (const [T, O] of Object.entries(o)) _.style[T] = O; var y = l.querySelector("button"); y.addEventListener("click", function(T) { n && n(_.value), a.setDirty(!0), l.close(); }); var b = p.getBoundingClientRect(), m = -20, E = -20; return b && (m -= b.left, E -= b.top), s ? (l.style.left = s.clientX + "px", l.style.top = s.clientY + "px") : (l.style.left = p.width * 0.5 + m + "px", l.style.top = p.height * 0.5 + E + "px"), console.warn(l.style.left, l.style.top), console.warn(s), setTimeout(function() { _.focus(); }, 10), Ee(l), l; } showSearchBox(e, i = {}) { var n = { slotFrom: null, node_from: null, node_to: null, do_type_filter: u.search_filter_enabled, type_filter_in: null, type_filter_out: null, show_general_if_none_on_typefilter: !0, show_general_after_typefiltered: !0, hide_on_mouse_leave: u.search_hide_on_mouse_leave, show_all_if_empty: !0, show_all_on_open: u.search_show_all_on_open }; i = Object.assign(n, i); var s = this, r = N.active_canvas, o = r.canvas, a = o.ownerDocument || document; let l = e; var h = document.createElement("div"); h.className = "litegraph litesearchbox graphdialog rounded", h.innerHTML = "Search ", i.do_type_filter && (h.innerHTML += "", h.innerHTML += ""), h.innerHTML += "
", a.fullscreenElement ? a.fullscreenElement.appendChild(h) : (a.body.appendChild(h), a.body.style.overflow = "hidden"); let p = null, f = null; if (i.do_type_filter && (p = h.querySelector(".slot_in_type_filter"), f = h.querySelector(".slot_out_type_filter")), h.close = function() { s.search_box = null, this.blur(), o.focus(), a.body.style.overflow = "", setTimeout(function() { s.canvas.focus(); }, 20), h.parentNode && h.parentNode.removeChild(h); }, this.ds.scale > 1 && (h.style.transform = "scale(" + this.ds.scale + ")"), i.hide_on_mouse_leave) { var c = 0, v = null; u.pointerListenerAdd(h, "enter", function(D) { v && (clearTimeout(v), v = null); }), u.pointerListenerAdd(h, "leave", function(D) { c || (v = setTimeout(function() { h.close(); }, 500)); }), i.do_type_filter && (p.addEventListener("click", function(D) { c++; }), p.addEventListener("blur", function(D) { c = 0; }), p.addEventListener("change", function(D) { c = -1; }), f.addEventListener("click", function(D) { c++; }), f.addEventListener("blur", function(D) { c = 0; }), f.addEventListener("change", function(D) { c = -1; })); } s.search_box && s.search_box.close(), s.search_box = h; var g = h.querySelector(".helper"), d = null, _ = null, y = null; const b = (D) => { if (D) if (s.onSearchBoxSelection) s.onSearchBoxSelection(D, l, r); else { var P = u.searchbox_extras[D.toLowerCase()]; P && (D = P.type), r.graph.beforeChange(); var F = u.createNode(D); if (F && (F.pos = r.convertEventToCanvasOffset( l ), r.graph.add(F)), P && P.data) { if (P.data.properties) for (var V in P.data.properties) F.addProperty("" + V, P.data.properties[V]); if (P.data.inputs) { F.inputs = []; for (var V in P.data.inputs) F.addInput( P.data.inputs[V][0], P.data.inputs[V][1] ); } if (P.data.outputs) { F.outputs = []; for (var V in P.data.outputs) F.addOutput( P.data.outputs[V][0], P.data.outputs[V][1] ); } P.data.title && (F.title = P.data.title), P.data.json && F.configure(P.data.json); } if (i.node_from) { var R = null; switch (typeof i.slotFrom) { case "string": R = i.node_from.findOutputSlotIndexByName(i.slotFrom); break; case "object": i.slotFrom.name ? R = i.node_from.findOutputSlotIndexByName(i.slotFrom.name) : R = -1, R == -1 && typeof i.slotFrom.slot_index < "u" && (R = i.slotFrom.slot_index); break; case "number": R = i.slotFrom; break; default: R = 0; } R = R, typeof i.node_from.outputs[R] !== void 0 && R !== null && R > -1 && i.node_from.connectByTypeInput(R, F, i.node_from.outputs[R].type); } if (i.node_to) { var R = null; switch (typeof i.slotFrom) { case "string": R = i.node_to.findInputSlotIndexByName(i.slotFrom); break; case "number": R = i.slotFrom; break; default: R = 0; } typeof i.node_to.inputs[R] !== void 0 && R !== null && R > -1 && i.node_to.connectByTypeOutput(R, F, i.node_to.inputs[R].type); } r.graph.afterChange(); } h.close(); }, m = (D) => { var P = y; y && y.classList.remove("selected"), y ? (y = D ? y.nextSibling : y.previousSibling, y || (y = P)) : y = D ? g.childNodes[0] : g.childNodes[g.childNodes.length], y && (y.classList.add("selected"), y.scrollIntoView({ block: "end", behavior: "smooth" })); }, E = (D, P, F, V, R, le = {}) => { const ee = Object.assign({ skipFilter: !1, inTypeOverride: null, outTypeOverride: null }, le), fe = u.registered_node_types[D]; if (fe.hide_in_node_lists || P && fe.filter != P || (!i.show_all_if_empty || F) && D.toLowerCase().indexOf(F) === -1) return !1; if (i.do_type_filter && !ee.skipFilter) { const Y = D; let H = V == null ? void 0 : V.value; if (ee.inTypeOverride != null && (H = ee.inTypeOverride), V && H && u.registered_slot_in_types[H] && u.registered_slot_in_types[H].nodes) { var te = u.registered_slot_in_types[H].nodes.includes(Y); if (te === !1) return !1; } if (H = R == null ? void 0 : R.value, ee.outTypeOverride != null && (H = ee.outTypeOverride), R && H && u.registered_slot_out_types[H] && u.registered_slot_out_types[H].nodes) { var te = u.registered_slot_out_types[H].nodes.includes(Y); if (te === !1) return !1; } } return !0; }, T = () => { _ = null; var D = O.value; if (d = null, g.innerHTML = "", !D && !i.show_all_if_empty) return; if (s.onSearchBox) { var P = s.onSearchBox(g, D, r); if (P) for (var F = 0; F < P.length; ++F) te(P[F]); } else { var V = 0; D = D.toLowerCase(); var R = r.filter || r.graph.filter; let Y, H; i.do_type_filter && s.search_box ? (Y = s.search_box.querySelector(".slot_in_type_filter"), H = s.search_box.querySelector(".slot_out_type_filter")) : (Y = null, H = null); for (const x in u.searchbox_extras) { var le = u.searchbox_extras[x]; if (!((!i.show_all_if_empty || D) && le.desc.toLowerCase().indexOf(D) === -1)) { var be = u.registered_node_types[le.type]; if (!(be && be.filter != R) && E(le.type, R, D, Y, H) && (te(le.desc, "searchbox_extra"), N.search_limit !== -1 && V++ > N.search_limit)) break; } } var ee = null; if (Array.prototype.filter) var fe = Object.keys(u.registered_node_types), ee = fe.filter((q) => E(q, R, D, Y, H)); else { ee = []; for (const x in u.registered_node_types) E(x, R, D, Y, H) && ee.push(x); } for (var F = 0; F < ee.length && (te(ee[F]), !(N.search_limit !== -1 && V++ > N.search_limit)); F++) ; if (i.show_general_after_typefiltered && (Y != null && Y.value || H != null && H.value)) { let x = []; for (const q in u.registered_node_types) E(q, R, D, Y, H, { inTypeOverride: Y && Y.value ? "*" : null, outTypeOverride: H && H.value ? "*" : null }) && x.push(q); for (let q = 0; q < x.length && (te(x[q], "generic_type"), !(N.search_limit !== -1 && V++ > N.search_limit)); q++) ; } if ((Y != null && Y.value || H != null && H.value) && (g == null ? void 0 : g.childNodes.length) == 0 && i.show_general_if_none_on_typefilter) { let x = []; for (const q in u.registered_node_types) E(q, R, D, Y, H, { skipFilter: !0 }) && x.push(q); for (let q = 0; q < x.length && (te(x[q], "not_in_filter"), !(N.search_limit !== -1 && V++ > N.search_limit)); q++) ; } } function te(Y, H) { var x = document.createElement("div"); d || (d = Y), x.innerText = Y, x.dataset.type = escape(Y), x.className = "litegraph lite-search-item", H && (x.className += " " + H), x.addEventListener("click", function(q) { b(unescape(this.dataset.type)); }), g.appendChild(x); } }; var O = h.querySelector("input"); if (O && (O.addEventListener("blur", function(D) { this.focus(); }), O.addEventListener("keydown", function(D) { if (D.keyCode == 38) m(!1); else if (D.keyCode == 40) m(!0); else if (D.keyCode == 27) h.close(); else if (D.keyCode == 13) y ? b(y.innerHTML) : d ? b(d) : h.close(); else { _ && clearInterval(_), _ = setTimeout(T, u.search_box_refresh_interval_ms); return; } return D.preventDefault(), D.stopPropagation(), D.stopImmediatePropagation(), !0; })), i.do_type_filter) { if (p) { var A = u.slot_types_in, M = A.length; (i.type_filter_in == I.EVENT || i.type_filter_in == I.ACTION) && (i.type_filter_in = "_event_"); for (var L = 0; L < M; L++) { var B = document.createElement("option"); B.value = A[L], B.innerHTML = A[L], p.appendChild(B), i.type_filter_in !== null && (i.type_filter_in + "").toLowerCase() == (A[L] + "").toLowerCase() && (B.selected = !0); } p.addEventListener("change", T); } if (f) { var A = u.slot_types_out, M = A.length; (i.type_filter_out == I.EVENT || i.type_filter_out == I.ACTION) && (i.type_filter_out = "_event_"); for (var L = 0; L < M; L++) { var B = document.createElement("option"); B.value = A[L], B.innerHTML = A[L], f.appendChild(B), i.type_filter_out !== null && (i.type_filter_out + "").toLowerCase() == (A[L] + "").toLowerCase() && (B.selected = !0); } f.addEventListener("change", T); } } var G = o.getBoundingClientRect(), z = (l ? l.clientX : G.left + G.width * 0.5) - 80, pe = (l ? l.clientY : G.top + G.height * 0.5) - 20; return h.style.left = z + "px", h.style.top = pe + "px", l.layerY > G.height - 200 && (g.style.maxHeight = G.height - l.layerY - 20 + "px"), O.focus(), i.show_all_on_open && T(), h; } showShowNodePanel(e) { this.closePanels(); var i = this.getCanvasWindow(), n = this, s = this.createPanel(e.title || "", { closable: !0, window: i, onOpen: function() { }, onClose: function() { n.node_panel = null; } }); n.node_panel = s, s.id = "node-panel", s.node = e, s.classList.add("settings"); function r() { s.content.innerHTML = "", s.addHTML("" + e.type + "" + (e.constructor.desc || "") + ""), s.addHTML("

Properties

"); var o = function(f, c) { switch (n.graph.beforeChange(e), f) { case "Title": e.title = c; break; case "Mode": var v = Object.values(re).indexOf(c); v >= Z.ALWAYS && re[v] ? e.changeMode(v) : console.warn("unexpected mode: " + c); break; case "Color": N.node_colors[c] ? (e.color = N.node_colors[c].color, e.bgcolor = N.node_colors[c].bgcolor) : console.warn("unexpected color: " + c); break; default: e.setProperty(f, c); break; } n.graph.afterChange(), n.dirty_canvas = !0; }; s.addWidget("string", "Title", e.title, {}, o), s.addWidget("combo", "Mode", re[e.mode], { values: re }, o); var a = ""; e.color !== void 0 && (a = Object.keys(N.node_colors).filter(function(f) { return N.node_colors[f].color == e.color; })[0]), s.addWidget("combo", "Color", a, { values: Object.keys(N.node_colors) }, o); for (var l in e.properties) { var h = e.properties[l], p = e.getPropertyInfo(l); p.type, !(e.onAddPropertyToPanel && e.onAddPropertyToPanel(l, s)) && s.addWidget(p.widget || p.type, l, h, p, o); } s.addSeparator(), e.onShowCustomPanelInfo && e.onShowCustomPanelInfo(s), s.footer.innerHTML = "", s.addButton("Delete", function() { e.block_delete || (e.graph.remove(e), s.close()); }).classList.add("delete"); } s.inner_showCodePad = function(o) { s.classList.remove("settings"), s.classList.add("centered"), s.alt_content.innerHTML = ""; var a = s.alt_content.querySelector("textarea"), l = function() { s.toggleAltContent(!1), s.toggleFooterVisibility(!0), a.parentNode.removeChild(a), s.classList.add("settings"), s.classList.remove("centered"), r(); }; a.value = e.properties[o], a.addEventListener("keydown", function(f) { f.code == "Enter" && f.ctrlKey && (e.setProperty(o, a.value), l()); }), s.toggleAltContent(!0), s.toggleFooterVisibility(!1), a.style.height = "calc(100% - 40px)"; var h = s.addButton("Assign", function() { e.setProperty(o, a.value), l(); }); s.alt_content.appendChild(h); var p = s.addButton("Close", l); p.style.float = "right", s.alt_content.appendChild(p); }, r(), this.canvas.parentNode.appendChild(s); } showSubgraphPropertiesDialog(e) { console.log("showing subgraph properties dialog"); var i = this.canvas.parentNode.querySelector(".subgraph_dialog"); i && i.close(); var n = this.createPanel("Subgraph Inputs", { closable: !0, width: 500 }); n.node = e, n.classList.add("subgraph_dialog"); const s = e; var r = s.subgraph; if (!r) { console.warn("subnode without subgraph!"); return; } function o() { if (n.clear(), e.inputs) for (var d = 0; d < e.inputs.length; ++d) { var _ = e.inputs[d]; if (_.not_subgraph_input) continue; var y = ` `, b = n.addHTML(y, "subgraph_property"); b.dataset.name = _.name, b.dataset.slot = "" + d, b.querySelector(".name").innerText = _.name, b.querySelector(".type").innerText = J(_.type), b.querySelector(".delete").addEventListener("click", function(T) { const O = this.parentNode.dataset.name; s.removeGraphInput(O), o(); }); const m = b.querySelector(".move_up"); m.disabled = d <= 0, m.addEventListener("click", function(T) { const O = +this.parentNode.dataset.slot; O < 0 || (s.moveInput(O, O - 1), o()); }); const E = b.querySelector(".move_down"); E.disabled = d >= e.inputs.length - 1, E.addEventListener("click", function(T) { const O = +this.parentNode.dataset.slot; O > e.inputs.length - 1 || (s.moveInput(O, O + 1), o()); }); } } var a = ` + Name Type `, l = n.addHTML(a, "subgraph_property extra", !0); const h = l.querySelector(".name"), p = l.querySelector(".type"), f = l.querySelector("button"); for (const d of we()) { var c = document.createElement("option"); c.value = d, c.innerHTML = J(d), p.appendChild(c), d === "*" && (c.selected = !0); } const v = () => { const d = h.value; let _ = p.value; _ === "-1" ? _ = I.ACTION : _ === "-2" && (_ = I.EVENT), !(!d || e.findInputSlotIndexByName(d) != -1) && (this.addGraphInputNode(e, d, _), h.value = "", p.value = "", o(), h.focus()); }, g = (d) => { d.keyCode == 13 ? (v(), d.preventDefault()) : d.keyCode == 27 && (n.close(), d.preventDefault()); }; return f.addEventListener("click", v), h.addEventListener("keydown", g), p.addEventListener("keydown", g), o(), this.canvas.parentNode.appendChild(n), h.focus(), n; } showSubgraphPropertiesDialogRight(e) { var i = this.canvas.parentNode.querySelector(".subgraph_dialog"); i && i.close(); var n = this.createPanel("Subgraph Outputs", { closable: !0, width: 500 }); n.node = e, n.classList.add("subgraph_dialog"); const s = e; if (!s.subgraph) { console.warn("subnode without subgraph!"); return; } function o() { if (n.clear(), e.outputs) for (var d = 0; d < e.outputs.length; ++d) { var _ = e.outputs[d]; if (_.not_subgraph_output) continue; var y = ` `, b = n.addHTML(y, "subgraph_property"); b.dataset.name = _.name, b.dataset.slot = "" + d, b.querySelector(".name").innerText = _.name, b.querySelector(".type").innerText = J(_.type), b.querySelector("button").addEventListener("click", function(T) { const O = this.parentNode.dataset.name; s.removeGraphOutput(O), o(); }); const m = b.querySelector(".move_up"); m.disabled = d <= 0, m.addEventListener("click", function(T) { const O = +this.parentNode.dataset.slot; O < 0 || (s.moveOutput(O, O - 1), o()); }); const E = b.querySelector(".move_down"); E.disabled = d >= e.outputs.length - 1, E.addEventListener("click", function(T) { const O = +this.parentNode.dataset.slot; O > e.outputs.length - 1 || (s.moveOutput(O, O + 1), o()); }); } } var a = ` + Name Type `, l = n.addHTML(a, "subgraph_property extra", !0); const h = l.querySelector(".name"), p = l.querySelector(".type"), f = l.querySelector("button"); for (const d of Le()) { var c = document.createElement("option"); c.value = d, c.innerHTML = J(d), p.appendChild(c), d === "*" && (c.selected = !0); } const v = () => { const d = h.value; let _ = p.value; _ === "-1" ? _ = I.ACTION : _ === "-2" && (_ = I.EVENT), !(!d || e.findOutputSlotIndexByName(d) != -1) && (this.addGraphOutputNode(e, d, _), h.value = "", p.value = "", o(), h.focus()); }, g = (d) => { d.keyCode == 13 ? (v(), d.preventDefault()) : d.keyCode == 27 && (n.close(), d.preventDefault()); }; return f.addEventListener("click", v), h.addEventListener("keydown", g), p.addEventListener("keydown", g), o(), this.canvas.parentNode.appendChild(n), h.focus(), n; } showConnectionMenu(e = {}) { var i = e.nodeFrom && e.slotFrom, n = !i && e.nodeTo && e.slotTo; if (!i && !n) return console.warn("No data passed to showConnectionMenu"), !1; var s = i ? e.nodeFrom : e.nodeTo; const r = i ? e.slotFrom : e.slotTo; let o; var a = null; switch (typeof r) { case "string": a = i ? s.findOutputSlotIndexByName(r) : s.findInputSlotIndexByName(r), o = i ? s.outputs[r] : s.inputs[r]; break; case "object": o = r, a = i ? s.findOutputSlotIndexByName(o.name) : s.findInputSlotIndexByName(o.name); break; case "number": a = r, o = i ? s.outputs[a] : s.inputs[a]; break; default: return console.error("Can't get slot information", r), !1; } var l = [{ content: "Add Node" }, j.SEPARATOR]; s.graph._is_subgraph && (i ? l.push({ content: "Add Subgraph Output" }) : l.push({ content: "Add Subgraph Input" }), l.push(j.SEPARATOR)), this.allow_searchbox && (l.push({ content: "Search" }), l.push(j.SEPARATOR)); var h = o.type == I.EVENT ? "_event_" : o.type, p = i ? u.slot_types_default_out : u.slot_types_default_in; const f = p[h]; if (console.warn("FROMSL", p, f), p && p[h]) if (Array.isArray(f)) for (var c of f) { const b = typeof c == "string" ? c : (c == null ? void 0 : c.title) || (c == null ? void 0 : c.node); l.push({ content: b, value: c }); } else throw new Error(`Invalid default slot specifier, must be an array: ${f}`); const v = (b) => { const m = s.graph._subgraph_node, E = [b.canvasX, b.canvasY]; m.addGraphInput(o.name, o.type, E).innerNode.connect(0, s, a); }, g = (b) => { const m = s.graph._subgraph_node, E = [b.canvasX, b.canvasY], T = m.addGraphOutput(o.name, o.type, E); s.connect(a, T.innerNode, 0); }, d = (b) => { const m = Object.assign(e, { position: [e.e.canvasX, e.e.canvasY] }); var E = this.createDefaultNodeForSlot(b, m); E ? console.log("node created", b) : console.error("node not in defaults", b); }, _ = (b, m, E) => { switch (b.content) { case "Add Node": N.onMenuAdd(b, m, E, y, function(T) { i ? e.nodeFrom.connectByTypeInput(a, T, h) : e.nodeTo.connectByTypeOutput(a, T, h); }); break; case "Add Subgraph Input": v(this.adjustMouseEvent(E)); break; case "Add Subgraph Output": g(this.adjustMouseEvent(E)); break; case "Search": i ? this.showSearchBox(E, { node_from: e.nodeFrom, slotFrom: o, type_filter_in: h }) : this.showSearchBox(E, { node_to: e.nodeTo, slotFrom: o, type_filter_out: h }); break; default: d(b.value); break; } }; var y = new X(l, { event: e.e, title: (o && o.name != "" ? o.name + (h ? " | " : "") : "") + (o && h ? h : ""), callback: _ }); return !1; } getLinkMenuOptions(e) { const i = this.graph.getNodeById(e.origin_id), n = this.graph.getNodeById(e.target_id); let s = null; i && i.outputs && i.outputs[e.origin_slot] && (s = i.outputs[e.origin_slot].type); let r = null; n && n.outputs && n.outputs[e.target_slot] && (r = n.inputs[e.target_slot].type); const o = (p) => { console.debug("node autoconnect"), !(!p.inputs || !p.inputs.length || !p.outputs || !p.outputs.length) && i.connectByTypeInput(e.origin_slot, p, s) && (p.connectByTypeInput(e.target_slot, n, r), p.pos[0] -= p.size[0] * 0.5); }, a = (p, f, c, v, g) => { N.onMenuAdd(p, f, c, v, o); }, l = () => { this.graph.removeLink(e.id); }; let h = [ { content: "Add Node", has_submenu: !0, callback: a }, j.SEPARATOR, { content: "Delete", has_submenu: !0, callback: l }, j.SEPARATOR ]; return this.graph.onGetLinkMenuOptions && (h = this.graph.onGetLinkMenuOptions(h, e)), i.getExtraLinkOptions && (h = i.getExtraLinkOptions(this, e, W.OUTPUT, h)), n.getExtraLinkOptions && (h = n.getExtraLinkOptions(this, e, W.INPUT, h)), h; } showLinkMenu(e, i) { const n = this.getLinkMenuOptions(e); return new X(n, { event: i, title: e.data != null ? e.data.constructor.name : null, extra: e }), !1; } /* * Shows a popup for editing one of the LGraphNode.properties. */ showEditPropertyValue(e, i, n = {}) { if (!e || e.properties[i] === void 0 || u.ignore_all_widget_events) return; var s = e.getPropertyInfo(i), r = s.type, o = ""; if (r == "string" || r == "number" || r == "array" || r == "object") if (s.multiline) { let d = e.properties[i], _ = 5; if (r !== "string") { d = JSON.stringify(d, null, 2); const y = (d.match(/\n/g) || "").length + 1; _ = Te(y, 5, 10); } o = ""; } else o = ""; else if ((r == "enum" || r == "combo") && s.values) { o = ""; } else if (r == "boolean" || r == "toggle") o = ""; else { console.warn("unknown type: " + r); return; } var h = this.createDialog( "" + (s.label ? s.label : i) + "" + o + "", n ), p = null; if ((r == "enum" || r == "combo") && s.values) p = h.querySelector("select"), p.addEventListener("change", function(d) { h.modified(), v(d.target.value); }); else if (r == "boolean" || r == "toggle") p = h.querySelector("input"), p && p.addEventListener("click", function(d) { h.modified(), v(!!p.checked); }); else if (s.multiline ? p = h.querySelector("textarea") : p = h.querySelector("input"), p) { p.addEventListener("blur", function(_) { this.focus(); }); let d = e.properties[i] !== void 0 ? e.properties[i] : ""; if (r !== "string") { let _ = null; s.multiline && (_ = 2), d = JSON.stringify(d, null, _); } if (p.value = d, p.addEventListener("keydown", function(_) { let y = !1; _.keyCode == 27 ? (h.close(), y = !0) : _.keyCode == 13 && !s.multiline ? (c(), y = !0) : _.keyCode != 13 && h.modified(), y && (_.preventDefault(), _.stopPropagation()); }), s.inputStyle) for (const [_, y] of Object.entries(s.inputStyle)) p.style[_] = y; } p && p.focus(); const f = () => { n.onclose && n.onclose(), h.close(), e.setDirtyCanvas(!0, !0); }, c = () => { r != "boolean" && r != "toggle" ? v(p.value) : f(); }, v = (d) => { s && s.values && s.values.constructor === Object && s.values[d] != null && (d = s.values[d]), typeof e.properties[i] == "number" && (d = Number(d)), (r == "array" || r == "object") && (d = JSON.parse(d)), e.setProperty(i, d), f(); }; var g = h.querySelector("button"); return g.addEventListener("click", c), Ee(h), h; } // TODO refactor, theer are different dialog, some uses createDialog, some dont createDialog(e, i = { checkForInput: !1, closeOnLeave: !0, closeOnLeave_checkModified: !0 }) { var n = document.createElement("div"); n.className = "graphdialog", n.innerHTML = e, n.is_modified = !1; var s = this.canvas.getBoundingClientRect(), r = -20, o = -20; if (s && (r -= s.left, o -= s.top), i.position ? (r = i.position[0], o = i.position[1]) : i.event ? (r = i.event.clientX, o = i.event.clientY) : (r += this.canvas.width * 0.5, o += this.canvas.height * 0.5), n.style.left = r + "px", n.style.top = o + "px", this.canvas.parentNode.appendChild(n), i.checkForInput) { var a = n.querySelectorAll("input"), l = !1; a && a.forEach(function(c) { c.addEventListener("keydown", function(v) { if (n.modified(), v.keyCode == 27) n.close(); else if (v.keyCode != 13) return; v.preventDefault(), v.stopPropagation(); }), l || c.focus(); }); } n.modified = function() { n.is_modified = !0; }, n.close = function() { n.parentNode && n.parentNode.removeChild(n); }; var h = null, p = 0; n.addEventListener("mouseleave", function(c) { p || (i.closeOnLeave || u.dialog_close_on_mouse_leave) && !n.is_modified && u.dialog_close_on_mouse_leave && c.buttons === 0 && (h = setTimeout(n.close, u.dialog_close_on_mouse_leave_delay)); }), n.addEventListener("mouseenter", function(c) { (i.closeOnLeave || u.dialog_close_on_mouse_leave) && h && clearTimeout(h); }); var f = n.querySelectorAll("select"); return f && f.forEach(function(c) { c.addEventListener("click", function(v) { p++; }), c.addEventListener("blur", function(v) { p = 0; }), c.addEventListener("change", function(v) { p = -1; }); }), n; } getCanvasMenuOptions() { var e = null; if (this.getMenuOptions ? e = this.getMenuOptions(this) : (e = [ { content: "Add Node", has_submenu: !0, callback: N.onMenuAdd }, { content: "Add Group", callback: N.onGroupAdd } //{ content: "Arrange", callback: that.graph.arrange }, //{content:"Collapse All", callback: LGraphCanvas.onMenuCollapseAll } ], this._graph_stack && this._graph_stack.length > 0 && e.push(j.SEPARATOR, { content: "Close subgraph", callback: this.closeSubgraph.bind(this) })), this.getExtraMenuOptions) { var i = this.getExtraMenuOptions(this, e); i && (e = e.concat(i)); } return e; } getNodeMenuOptions(e) { let i = []; e.getMenuOptions ? i = e.getMenuOptions(this) : (i = [ { content: "Inputs", has_submenu: !0, disabled: !0, callback: N.showMenuNodeOptionalInputs }, { content: "Outputs", has_submenu: !0, disabled: !0, callback: N.showMenuNodeOptionalOutputs }, j.SEPARATOR, { content: "Properties", has_submenu: !0, disabled: u.ignore_all_widget_events, callback: N.onShowMenuNodeProperties }, j.SEPARATOR, { content: "Title", value: { name: "title", type: "string" }, callback: N.onShowPropertyEditor }, { content: "Mode", has_submenu: !0, callback: N.onMenuNodeMode } ], e.resizable !== !1 && i.push({ content: "Resize", callback: N.onMenuResizeNode }), i.push( { content: "Collapse", callback: N.onMenuNodeCollapse }, { content: "Pin", callback: N.onMenuNodePin }, { content: "Colors", has_submenu: !0, callback: N.onMenuNodeColors }, { content: "Shapes", has_submenu: !0, callback: N.onMenuNodeShapes }, j.SEPARATOR )); const n = e.getOptionalSlots(); if (n && (n.inputs && n.inputs.length > 0 && typeof i[0] == "object" && (i[0].disabled = !1), n.outputs && n.outputs.length && typeof i[1] == "object" && (i[1].disabled = !1)), e.getExtraMenuOptions) { var s = e.getExtraMenuOptions(this, i); s && (s.push(j.SEPARATOR), i = s.concat(i)); } e.clonable !== !1 && i.push({ content: "Clone", callback: N.onMenuNodeClone }), i.push({ content: "To Subgraph", callback: N.onMenuNodeToSubgraph }); let r = Object.values(this.selected_nodes || {}); if (r.length || (r = [e]), r = r.filter((o) => !o.is($) && !o.is(Q)), i.push({ content: "To Parent Graph", disabled: !e.graph._is_subgraph || r.length === 0, callback: N.onMenuNodeToParentGraph }), e.graph._is_subgraph) { const o = (p) => { let f = 0; const c = ve(p, (v) => v.id); for (const v of p) for (const g of v.iterateAllLinks()) { if (c[g.origin_id] == null) return 0; c[g.target_id] == null && (f += 1); } return f; }, a = (p) => { let f = 0; const c = ve(p, (v) => v.id); for (const v of p) for (const g of v.iterateAllLinks()) if (c[g.origin_id] == null) f += 1; else if (c[g.target_id] == null) return 0; return f; }, l = o(r); i.push({ content: "To Subgraph Input" + (l > 1 ? "s" : ""), disabled: l === 0, callback: N.onMenuNodeToSubgraphInputs }); const h = a(r); i.push({ content: "To Subgraph Output" + (h > 1 ? "s" : ""), disabled: h === 0, callback: N.onMenuNodeToSubgraphOutputs }); } return i.push(j.SEPARATOR, { content: "Remove", disabled: !(e.removable !== !1 && !e.block_delete), callback: N.onMenuNodeRemove }), e.graph && e.graph.onGetNodeMenuOptions && (i = e.graph.onGetNodeMenuOptions(i, e)), i; } getGroupMenuOptions(e) { var i = [ { content: "Title", value: { name: "title", type: "string" }, callback: N.onShowPropertyEditor }, { content: "Color", has_submenu: !0, callback: N.onMenuNodeColors }, { content: "Font size", value: { name: "fontSize", type: "number" }, callback: N.onShowPropertyEditor }, j.SEPARATOR, { content: "Remove", callback: N.onMenuNodeRemove } ]; return i; } /** Called when mouse right click */ processContextMenu(e, i) { var n = N.active_canvas, s = n.getCanvasWindow(); let r = i, o = null, a = null, l = null; e != null && (l = e.item, e.type === "node" && (o = e.item), e.type === "link" && (a = e.item)); let h = null; var p = { event: r, extra: l }; o != null && (p.title = o.type); let f = null; o != null && (f = o.getSlotInPosition(r.canvasX, r.canvasY), N.active_node = o); const c = (y) => { const b = y.slot; o.graph.beforeChange(), b.input ? o.removeInput(b.slot) : b.output && o.removeOutput(b.slot), o.graph.afterChange(); }, v = (y) => { var b = y.slot; o.graph.beforeChange(), b.output ? o.disconnectOutput(b.slot) : b.input && o.disconnectInput(b.slot), o.graph.afterChange(); }, g = (y) => { var b = y.slot, m = b.input ? o.getInputInfo(b.slot) : o.getOutputInfo(b.slot), E = this.createDialog( "Name", p ), T = E.querySelector("input"); T && m && (T.value = m.label || ""); var O = () => { o.graph.beforeChange(), T.value && (m && (m.label = T.value), this.setDirty(!0)), E.close(), o.graph.afterChange(); }; E.querySelector("button").addEventListener("click", O), T.addEventListener("keydown", function(A) { if (E.is_modified = !0, A.keyCode == 27) E.close(); else if (A.keyCode == 13) O(); else if (A.keyCode != 13 && A.target instanceof Element && A.target.localName != "textarea") return; A.preventDefault(), A.stopPropagation(); }), T.focus(); }; if (f) { if (h = [], o.getSlotMenuOptions) h = o.getSlotMenuOptions(f); else { f && f.output && f.output.links && f.output.links.length && h.push({ content: "Disconnect Links", slot: f, callback: v }); var d = f.input || f.output; d.removable && h.push( d.locked ? "Cannot remove" : { content: "Remove Slot", slot: f, callback: c } ), d.nameLocked || h.push({ content: "Rename Slot", slot: f, callback: g }); } const y = (f.input ? f.input.type : f.output.type) || "*"; p.title = J(y); } else if (o) h = this.getNodeMenuOptions(o); else if (a) h = this.getLinkMenuOptions(a); else { h = this.getCanvasMenuOptions(); var _ = this.graph.getGroupOnPos( r.canvasX, r.canvasY ); _ && h.push(j.SEPARATOR, { content: "Edit Group", has_submenu: !0, submenu: { title: "Group", extra: _, options: this.getGroupMenuOptions(_) } }); } h && new X(h, p, s); } createPanel(e, i = {}) { var n = i.window || window, s = document.createElement("div"); if (s.className = "litegraph dialog", s.innerHTML = `
`, s.header = s.querySelector(".dialog-header"), i.width && (s.style.width = i.width + (i.width.constructor === Number ? "px" : "")), i.height && (s.style.height = i.height + (i.height.constructor === Number ? "px" : "")), i.closable) { var r = document.createElement("span"); r.innerHTML = "✕", r.classList.add("close"), r.addEventListener("click", function() { s.close(); }), s.header.appendChild(r); } return i.onOpen && (s.onOpen = i.onOpen), i.onClose && (s.onClose = i.onClose), s.title_element = s.querySelector(".dialog-title"), s.title_element.innerText = e, s.content = s.querySelector(".dialog-content"), s.alt_content = s.querySelector(".dialog-alt-content"), s.footer = s.querySelector(".dialog-footer"), s.close = function() { s.onClose && typeof s.onClose == "function" && s.onClose(), s.parentNode && s.parentNode.removeChild(s), this.parentNode && this.parentNode.removeChild(this); }, s.toggleAltContent = function(o = !1) { if (typeof o < "u") var a = o ? "block" : "none", l = o ? "none" : "block"; else var a = s.alt_content.style.display != "block" ? "block" : "none", l = s.alt_content.style.display != "block" ? "none" : "block"; s.alt_content.style.display = a, s.content.style.display = l; }, s.toggleFooterVisibility = function(o = !1) { if (typeof o < "u") var a = o ? "block" : "none"; else var a = s.footer.style.display != "block" ? "block" : "none"; s.footer.style.display = a; }, s.clear = function() { this.content.innerHTML = ""; }, s.addHTML = function(o, a, l) { var h = document.createElement("div"); return a && (h.className = a), h.innerHTML = o, l ? s.footer.appendChild(h) : s.content.appendChild(h), h; }, s.addButton = function(o, a, l) { var h = document.createElement("button"); return h.innerText = o, h.options = l, h.classList.add("btn"), h.addEventListener("click", a), s.footer.appendChild(h), h; }, s.addSeparator = function() { var o = document.createElement("div"); return o.className = "separator", s.content.appendChild(o), o; }, s.addWidget = function(o, a, l, h = {}, p) { var f = String(l); o = o.toLowerCase(), o == "number" && (f = l.toFixed(3)); var c = document.createElement("div"); c.className = "property", c.innerHTML = ""; let v = c.querySelector(".property_name"); v.innerText = h.label || a; var g = c.querySelector(".property_value"); if (g.innerText = f, c.dataset.property = a, c.dataset.type = h.type || o, c.options = h, c.value = l, o == "code") c.addEventListener("click", function(_) { s.inner_showCodePad(this.dataset.property); }); else if (o == "boolean") c.classList.add("boolean"), l && c.classList.add("bool-on"), c.addEventListener("click", function() { var _ = this.dataset.property; this.value = !this.value, this.classList.toggle("bool-on"); const y = this.querySelector(".property_value"); y.innerText = this.value ? "true" : "false", d(_, this.value); }); else if (o == "string" || o == "number") g.setAttribute("contenteditable", "true"), g.addEventListener("keydown", function(_) { _.code == "Enter" && (o != "string" || !_.shiftKey) && (_.preventDefault(), this.blur()); }), g.addEventListener("blur", function() { let _ = this.innerText; const y = this.parentNode; var b = y.dataset.property, m = y.dataset.type; m == "number" && (_ = Number(_)), d(b, _); }); else if ((o == "enum" || o == "combo") && "values" in h) { var f = N.getPropertyPrintableValue(l, h.values); g.innerText = f, g.addEventListener("click", function(y) { let b = h.values || []; typeof b == "function" && (console.error("Values by callback not supported in panel.addWidget!", b), b = []); var E = this.parentNode.dataset.property, T = this; let O = Array.from(b).map((M) => ({ content: M })); new X(O, { event: y, className: "dark", callback: A }, n); function A(M, L, B) { return T.innerText = M.content, d(E, M.content), !1; } }); } s.content.appendChild(c); function d(_, y) { h.callback && h.callback(_, y, h), p && p(_, y, h); } return c; }, s.onOpen && typeof s.onOpen == "function" && s.onOpen(), s; } checkPanels() { if (this.canvas) for (var e = this.canvas.parentNode.querySelectorAll(".litegraph.dialog"), i = 0; i < e.length; ++i) { var n = e[i]; if (n.node && (n.node.graph || n.close(), n.node.graph != this.graph)) { if (n.node.is(ne) && this.graph._is_subgraph && this.graph === n.node.subgraph) continue; n.close(); } } } closePanels() { var e = document.querySelector("#node-panel"); e && e.close(); var e = document.querySelector("#option-panel"); e && e.close(); } } C.onShowPropertyEditor = function(t, e, i, n, s) { var r = t.value, o = r.name, a = s[o], l = document.createElement("div"); l.is_modified = !1, l.className = "graphdialog", l.innerHTML = "", l.close = function() { l.parentNode && l.parentNode.removeChild(l); }; var h = l.querySelector(".name"); h.innerText = o; var p = l.querySelector(".value"); if (p && (p.value = a, p.addEventListener("blur", function(E) { this.focus(); }), p.addEventListener("keydown", function(E) { if (l.is_modified = !0, E.keyCode == 27) l.close(); else if (E.keyCode == 13) _(); else if (E.keyCode != 13 && E.target instanceof Element && E.target.localName != "textarea") return; E.preventDefault(), E.stopPropagation(); }), r.inputStyle)) for (const [E, T] of Object.entries(r.inputStyle)) p.style[E] = T; var f = N.active_canvas, c = f.canvas, v = c.getBoundingClientRect(), g = -20, d = -20; v && (g -= v.left, d -= v.top), i ? (l.style.left = i.clientX + g + "px", l.style.top = i.clientY + d + "px") : (l.style.left = c.width * 0.5 + g + "px", l.style.top = c.height * 0.5 + d + "px"); const _ = () => { p && y(p.value); }, y = (E) => { r.type == "number" ? E = Number(E) : r.type == "boolean" && (E = !!E); const T = s[o]; s[o] = E, s.onJSPropertyChanged && s.onJSPropertyChanged(o, E, T) === !1 && (s[o] = T), l.parentNode && l.parentNode.removeChild(l), s.setDirtyCanvas(!0, !0); }; var b = l.querySelector("button"); b.addEventListener("click", _), c.parentNode.appendChild(l), p && p.focus(); var m = null; l.addEventListener("mouseleave", function(E) { u.dialog_close_on_mouse_leave && !l.is_modified && u.dialog_close_on_mouse_leave && E.buttons === 0 && (m = setTimeout(l.close, u.dialog_close_on_mouse_leave_delay)); }), l.addEventListener("mouseenter", function(E) { u.dialog_close_on_mouse_leave && m && clearTimeout(m); }), Ee(l); }; C.onGroupAdd = function(t, e, i, n) { var s = N.active_canvas; s.getCanvasWindow(); var r = new me(); r.pos = s.convertEventToCanvasOffset(i), s.graph.addGroup(r); }; C.onMenuAdd = function(t, e, i, n, s) { var r = N.active_canvas, o = r.getCanvasWindow(), a = r.graph; if (!a) return; function l(h, p) { var f = u.getNodeTypesCategories(r.filter || a.filter).filter(function(g) { return g.startsWith(h); }), c = []; f.map(function(g) { if (g) { var d = new RegExp("^(" + h + ")"), _ = g.replace(d, "").split("/")[0], y = h === "" ? _ + "/" : h + _ + "/", b = _; b.indexOf("::") != -1 && (b = b.split("::")[1]); var m = c.findIndex(function(E) { return E.value === y; }); m === -1 && c.push( { value: y, content: b, has_submenu: !0, callback: function(E, T, O, A) { l(E.value, A); } } ); } }); var v = u.getNodeTypesInCategory(h.slice(0, -1), r.filter || a.filter); v.map(function(g) { if (!g.hide_in_node_lists) { var d = { value: g.class, content: g.title, has_submenu: !1, callback: function(_, y, b, m) { var E = m.getFirstEvent(); r.graph.beforeChange(); var T = u.createNode(_.value); T && (T.pos = r.convertEventToCanvasOffset(E), r.graph.add(T)), s && s(T), r.graph.afterChange(); } }; c.push(d); } }), new X(c, { event: i, parentMenu: p }, o); } return l("", n), !1; }; C.showMenuNodeOptionalInputs = function(t, e, i, n, s) { if (!s) return; var r = this, o = N.active_canvas, a = o.getCanvasWindow(); let l = s.getOptionalSlots().inputs, h = []; if (l) for (let v = 0; v < l.length; v++) { let g = l[v]; if (!g) { h.push(j.SEPARATOR); continue; } let { name: d, type: _, options: y } = g; y || (y = {}), y.label && (d = y.label), y.removable = !0; var p = { content: d, value: g }; _ == I.ACTION && (p.className = "event"), h.push(p); } if (s.onMenuNodeInputs) { var f = s.onMenuNodeInputs(h); f && (h = f); } if (!h.length) { console.log("no input entries"); return; } new X( h, { event: i, callback: c, parentMenu: n, node: s }, a ); function c(v, g, d, _) { if (s && (v.callback && v.callback.call(r, s, v, d, _), v.value)) { let y = v.value; s.graph.beforeChange(), s.addInput(y.name, y.type, y.options), s.onNodeOptionalInputAdd && s.onNodeOptionalInputAdd(v.value), s.setDirtyCanvas(!0, !0), s.graph.afterChange(); } } return !1; }; C.showMenuNodeOptionalOutputs = function(t, e, i, n, s) { if (!s) return; var r = this, o = N.active_canvas, a = o.getCanvasWindow(), l = s.getOptionalSlots().outputs, h = []; if (l) for (var p = 0; p < l.length; p++) { var f = l[p]; if (!f) { h.push(j.SEPARATOR); continue; } let { name: d, type: _, options: y } = f; if (!(s.flags && s.flags.skip_repeated_outputs && s.findOutputSlotIndexByName(f[0]) != -1)) { y || (y = {}), y.label && (d = y.label), y.removable = !0; var c = { content: d, value: [d, _, y] }; _ == I.EVENT && (c.className = "event"), h.push(c); } } if (this.onMenuNodeOutputs && (h = this.onMenuNodeOutputs(h)), u.do_add_triggers_slots && s.findOutputSlotIndexByName("onExecuted") == -1 && h.push({ content: "On Executed", value: ["onExecuted", I.EVENT, { nameLocked: !0 }], className: "event" }), s.onMenuNodeOutputs) { var v = s.onMenuNodeOutputs(h); v && (h = v); } if (!h.length) return; let g = function(d, _, y, b) { if (s && (d.callback && d.callback.call(r, s, d, y, b), !!d.value)) { var m = d.value[1]; if (m && (m.constructor === Object || m.constructor === Array)) { var E = []; for (var T in m) E.push({ content: T, value: m[T] }); return new X(E, { event: y, callback: g, parentMenu: n, node: s }), !1; } else { const O = d.value; s.graph.beforeChange(), s.addOutput(O.name, O.type, O.options), s.onNodeOptionalOutputAdd && s.onNodeOptionalOutputAdd(d.value), s.setDirtyCanvas(!0, !0), s.graph.afterChange(); } } }; return new X( h, { event: i, callback: g, parentMenu: n, node: s }, a ), !1; }; C.onMenuResizeNode = function(t, e, i, n, s) { if (s) { var r = function(l) { l.size = l.computeSize(), l.onResize && l.onResize(l.size); }, o = N.active_canvas; if (!o.selected_nodes || Object.keys(o.selected_nodes).length <= 1) r(s); else for (var a in o.selected_nodes) r(o.selected_nodes[a]); s.setDirtyCanvas(!0, !0); } }; C.onShowMenuNodeProperties = function(t, e, i, n, s) { if (!s || !s.properties) return; var r = N.active_canvas, o = r.getCanvasWindow(), a = []; for (var l in s.properties) { var h = s.properties[l] !== void 0 ? s.properties[l] : " "; typeof h == "object" && (h = JSON.stringify(h)); var p = s.getPropertyInfo(l); (p.type == "enum" || p.type == "combo") && (h = N.getPropertyPrintableValue(h, p.values)), h = N.decodeHTML(h), a.push({ content: "" + (p.label ? p.label : l) + "" + h + "", value: l }); } if (!a.length) return; new X( a, { event: i, callback: f, parentMenu: n, allow_html: !0, node: s }, o ); function f(c, v, g, d) { if (s) { var _ = this.getBoundingClientRect(); r.showEditPropertyValue(s, c.value, { position: [_.left, _.top] }); } } return !1; }; C.onResizeNode = function(t, e, i, n, s) { s && (s.size = s.computeSize(), s.setDirtyCanvas(!0, !0)); }; C.onMenuNodeCollapse = function(t, e, i, n, s) { s.graph.beforeChange( /*?*/ ); var r = function(l) { l.collapse(); }, o = N.active_canvas; if (!o.selected_nodes || Object.keys(o.selected_nodes).length <= 1) r(s); else for (var a in o.selected_nodes) r(o.selected_nodes[a]); s.graph.afterChange( /*?*/ ); }; C.onMenuNodePin = function(t, e, i, n, s) { s.pin(); }; C.onMenuNodeMode = function(t, e, i, n, s) { let r = Array.from(re).map((a) => ({ content: a })); new X( r, { event: i, callback: o, parentMenu: n, node: s } ); function o(a) { if (s) { var l = Object.values(re).indexOf(a.content), h = function(c) { l >= Z.ALWAYS && re[l] ? c.changeMode(l) : (console.warn("unexpected mode: " + a), c.changeMode(Z.ALWAYS)); }, p = N.active_canvas; if (!p.selected_nodes || Object.keys(p.selected_nodes).length <= 1) h(s); else for (var f in p.selected_nodes) h(p.selected_nodes[f]); } } return !1; }; C.onMenuNodeColors = function(t, e, i, n, s) { if (!s) throw "no node for color"; var r = []; r.push({ value: null, content: "No color" }); for (let l in N.node_colors) { var o = N.node_colors[l]; let h = { value: l, content: "" + l + "" }; r.push(h); } new X(r, { event: i, callback: a, parentMenu: n, node: s, allow_html: !0 }); function a(l) { if (s) { var h = l.value ? N.node_colors[l.value] : null, p = function(v) { h ? v instanceof me ? v.color = h.groupcolor : (v.color = h.color, v.bgcolor = h.bgcolor) : (delete v.color, v instanceof ae && delete v.bgcolor); }, f = N.active_canvas; if (!f.selected_nodes || Object.keys(f.selected_nodes).length <= 1) p(s); else for (var c in f.selected_nodes) p(f.selected_nodes[c]); s.setDirtyCanvas(!0, !0); } } return !1; }; C.onMenuNodeShapes = function(t, e, i, n, s) { if (!s) throw "no node passed"; const r = Array.from(Ie).map((a) => ({ content: a })); new X(r, { event: i, callback: o, parentMenu: n, node: s }); function o(a) { if (s) { s.graph.beforeChange( /*?*/ ); var l = function(f) { f.shape = Ie.indexOf(a.content); }, h = N.active_canvas; if (!h.selected_nodes || Object.keys(h.selected_nodes).length <= 1) l(s); else for (var p in h.selected_nodes) l(h.selected_nodes[p]); s.graph.afterChange( /*?*/ ), s.setDirtyCanvas(!0); } } return !1; }; C.onMenuNodeRemove = function(t, e, i, n, s) { if (!s) throw "no node passed"; var r = s.graph; r.beforeChange(); var o = function(h) { h.removable !== !1 && r.remove(h); }, a = N.active_canvas; if (!a.selected_nodes || Object.keys(a.selected_nodes).length <= 1) o(s); else for (var l in a.selected_nodes) o(a.selected_nodes[l]); r.afterChange(), s.setDirtyCanvas(!0, !0); }; C.onMenuNodeToSubgraph = function(t, e, i, n, s) { var r = s.graph, o = N.active_canvas; if (o) { var a = Object.values(o.selected_nodes || {}); a.length || (a = [s]); var l = u.createNode("graph/subgraph", null, { constructorArgs: [null] }); l.pos = s.pos.concat(), r.add(l), l.buildFromNodes(a), o.deselectAllNodes(), s.setDirtyCanvas(!0, !0); } }; C.onMenuNodeToSubgraphInputs = function(t, e, i, n, s) { var r = N.active_canvas; if (!r) return; const o = s.graph._subgraph_node; if (!s.graph._is_subgraph || !o) { console.error("[To Subgraph Inputs] Current graph is not a subgraph!", s.graph); return; } let a = Object.values(r.selected_nodes || {}); a.length || (a = [s]), o.convertNodesToSubgraphInputs(a), r.deselectAllNodes(), s.setDirtyCanvas(!0, !0); }; C.onMenuNodeToSubgraphOutputs = function(t, e, i, n, s) { var r = N.active_canvas; if (!r) return; const o = s.graph._subgraph_node; if (!s.graph._is_subgraph || !o) { console.error("[To Subgraph Outputs] Current graph is not a subgraph!", s.graph); return; } let a = Object.values(r.selected_nodes || {}); a.length || (a = [s]), o.convertNodesToSubgraphOutputs(a), r.deselectAllNodes(), s.setDirtyCanvas(!0, !0); }; C.onMenuNodeToParentGraph = function(t, e, i, n, s) { var r = N.active_canvas; if (!r) return; const o = s.graph._subgraph_node; if (!s.graph._is_subgraph || !o) { console.error("[To Parent Graph] Current graph is not a subgraph!", s.graph); return; } let a = Object.values(r.selected_nodes || {}); a.length || (a = [s]), o.moveNodesToParentGraph(a), r.deselectAllNodes(), s.setDirtyCanvas(!0, !0); }; C.onMenuNodeClone = function(t, e, i, n, s) { var r = N.active_canvas; (!r.selected_nodes || Object.keys(r.selected_nodes).length <= 1) && r.selectNode(s), r.cloneSelection(); }; const ce = class { constructor(t, e, i = {}) { this.link_type_colors = {}, this.node_panel = null, this.options_panel = null, this.render_time = 0, this.allow_dragcanvas = !0, this.allow_dragnodes = !0, this.allow_interaction = !0, this.allow_reconnect_links = !0, this.allow_searchbox = !0, this.always_render_background = !1, this.background_image = ce.DEFAULT_BACKGROUND_IMAGE, this.block_click = !1, this.clear_background = !0, this.clear_background_color = "#222", this.connecting_pos = null, this.connecting_slot = null, this.connecting_input = null, this.connecting_output = null, this.connections_width = 3, this.current_node = null, this.drag_mode = !1, this.dragging_rectangle = null, this.ds = new Be(), this.editor_alpha = 1, this.filter = null, this.highquality_render = !0, this.skip_events = !1, this.last_mouse_position = [0, 0], this.last_click_position = [0, 0], this.last_click_position_offset = [0, 0], this.last_mouse_dragging = !1, this.links_render_mode = de.SPLINE_LINK, this.live_mode = !1, this.mouse = [0, 0], this.offset_mouse = [0, 0], this.graph_mouse = [0, 0], this.node_widget = null, this.maxZoom = null, this.minZoom = null, this.multi_select = !1, this.over_link_center = null, this.pause_rendering = !1, this.read_only = !1, this.render_canvas_border = !0, this.render_collapsed_slots = !0, this.render_connection_arrows = !1, this.render_connections_border = !0, this.render_connections_shadows = !1, this.render_connections = !0, this.render_curved_connections = !1, this.render_execution_order = !1, this.render_link_tooltip = !0, this.render_only_selected = !0, this.render_shadows = !0, this.render_title_colored = !0, this.render_subgraph_panels = !0, this.render_subgraph_stack_header = !0, this.round_radius = 8, this.set_canvas_dirty_on_mouse_event = !0, this.show_info = !0, this.use_gradients = !1, this.visible_links = [], this.zoom_modify_alpha = !0, this.pointer_is_down = !1, this.pointer_is_double = !1, this._highlight_input = null, this._highlight_input_slot = null, this._highlight_output = null, this._graph_stack = [], this._bg_img = null, this._pattern = null, this._pattern_img = null, this.search_box = null, this.prompt_box = null, this._events_binded = !1, this.resizing_node = null, typeof t == "string" && (t = document.querySelector(t)), this.skip_events = i.skip_events || !1, this.title_text_font = "" + u.NODE_TEXT_SIZE + "px Arial", this.inner_text_font = "normal " + u.NODE_SUBTEXT_SIZE + "px Arial", this.node_title_color = u.NODE_TITLE_COLOR, this.default_link_color = u.LINK_COLOR, this.link_type_colors = u.cloneObject(ce.DEFAULT_LINK_TYPE_COLORS), this.canvas_mouse = this.graph_mouse, this.visible_area = this.ds.visible_area, this.viewport = i.viewport || null, e && e.attachCanvas(this), this.setCanvas(t, i.skip_events), this.clear(), i.skip_render || this.startRendering(), this.autoresize = i.autoresize; } static getFileExtension(t) { var e = t.indexOf("?"); e != -1 && (t = t.substr(0, e)); var i = t.lastIndexOf("."); return i == -1 ? "" : t.substr(i + 1).toLowerCase(); } static decodeHTML(t) { var e = document.createElement("div"); return e.innerText = t, e.innerHTML; } static getPropertyPrintableValue(t, e) { if (!e || e.constructor === Array) return String(t); if (e.constructor === Object) { var i = ""; for (var n in e) if (e[n] == t) { i = n; break; } return String(t) + " (" + i + ")"; } } get scale() { return this.ds.scale; } set scale(t) { this.ds.scale = t; } /** clears all the data inside */ clear() { this.frame = 0, this.last_draw_time = 0, this.render_time = 0, this.fps = 0, this.dragging_rectangle = null, this.selected_nodes = {}, this.selected_group = null, this.visible_nodes = [], this.node_dragged = null, this.node_over = null, this.node_capturing_input = null, this.connecting_node = null, this.highlighted_links = {}, this.dragging_canvas = !1, this.dirty_canvas = !0, this.dirty_bgcanvas = !0, this.dirty_area = null, this.node_in_panel = null, this.node_widget = null, this.last_mouse = [0, 0], this.last_mouseclick = 0, this.pointer_is_down = !1, this.pointer_is_double = !1, this.onClear && this.onClear(); } /** assigns a graph, you can reassign graphs to the same canvas */ setGraph(t, e = !1) { if (this.graph != t) { if (e || this.clear(), !t && this.graph) { this.graph.detachCanvas(this); return; } t.attachCanvas(this), this._graph_stack && (this._graph_stack = null), this.setDirty(!0, !0); } } /** opens a graph contained inside a node in the current graph */ openSubgraph(t) { if (!t) throw "graph cannot be null"; if (this.graph == t) throw "graph cannot be the same"; if (this.clear(), this.graph) { this._graph_stack || (this._graph_stack = []); const i = [this.ds.offset[0], this.ds.offset[1]]; this._graph_stack.push({ graph: this.graph, offset: i, scale: this.ds.scale }); } u.debug && (console.warn("SubGraph opened", t), console.warn("Graph inputs", t.inputs), console.warn("Graph outputs", t.outputs)), t.attachCanvas(this); const e = [0, 0]; if (t._nodes.length > 0) { let i = Number.MAX_SAFE_INTEGER, n = 0, s = Number.MAX_SAFE_INTEGER, r = 0; for (const o of t.iterateNodesInOrder()) i = Math.min(o.pos[0], i), n = Math.max(o.pos[0] + o.size[0], n), s = Math.min(o.pos[1], s), r = Math.max(o.pos[1] + o.size[1], r); e[0] = -(i + (n - i) / 2) + this.canvas.width / 2, e[1] = -(s + (r - s) / 2) + this.canvas.height / 2; } this.ds.offset = e, this.ds.scale = 1, this.checkPanels(), this.setDirty(!0, !0); } closeAllSubgraphs() { for (; this._graph_stack && this._graph_stack.length > 0; ) this.closeSubgraph(); } /** closes a subgraph contained inside a node */ closeSubgraph() { if (!(!this._graph_stack || this._graph_stack.length == 0)) { var t = this.graph._subgraph_node, { graph: e, offset: i, scale: n } = this._graph_stack.pop(); this.selected_nodes = {}, this.highlighted_links = {}, e.attachCanvas(this), this.setDirty(!0, !0), t && (this.centerOnNode(t), this.selectNodes([t])), this.ds.offset = i, this.ds.scale = n; } } /** assigns a canvas */ setCanvas(t, e = !1) { if (t && typeof t == "string" && (t = document.getElementById(t), !t)) throw "Error creating LiteGraph canvas: Canvas not found"; if (t = t, t !== this.canvas && (!t && this.canvas && (e || this.unbindEvents()), this.canvas = t, this.ds.element = t, !!t)) { if (t.className += " lgraphcanvas", t.data = this, t.tabIndex = 1, this.bgcanvas = null, this.bgcanvas || (this.bgcanvas = document.createElement("canvas"), this.bgcanvas.width = this.canvas.width, this.bgcanvas.height = this.canvas.height), t.getContext == null) throw t.localName != "canvas" ? "Element supplied for LGraphCanvas must be a element, you passed a " + t.localName : "This browser doesn't support Canvas"; e || this.bindEvents(), this.adjustCanvasForHiDPI(); } } //used in some events to capture them _doNothing(t) { return t.preventDefault(), !1; } _doReturnTrue(t) { return t.preventDefault(), !0; } /** binds mouse, keyboard, touch and drag events to the canvas */ bindEvents() { if (this._events_binded) { console.warn("LGraphCanvas: events already binded"); return; } var t = this.canvas, e = this.getCanvasWindow(), i = e.document; this._mousedown_callback = this.processMouseDown.bind(this), this._mousewheel_callback = this.processMouseWheel.bind(this), this._mousemove_callback = this.processMouseMove.bind(this), this._mouseup_callback = this.processMouseUp.bind(this), u.pointerListenerAdd(t, "down", this._mousedown_callback, !0), t.addEventListener("mousewheel", this._mousewheel_callback, !1), u.pointerListenerAdd(t, "up", this._mouseup_callback, !0), u.pointerListenerAdd(t, "move", this._mousemove_callback), t.addEventListener("contextmenu", this._doNothing), t.addEventListener( "DOMMouseScroll", this._mousewheel_callback, !1 ), this._key_callback = this.processKey.bind(this), t.addEventListener("keydown", this._key_callback, !0), i.addEventListener("keyup", this._key_callback, !0), this._ondrop_callback = this.processDrop.bind(this), t.addEventListener("dragover", this._doNothing, !1), t.addEventListener("dragend", this._doNothing, !1), t.addEventListener("drop", this._ondrop_callback, !1), t.addEventListener("dragenter", this._doReturnTrue, !1), this._events_binded = !0; } /** unbinds mouse events from the canvas */ unbindEvents() { if (!this._events_binded) { console.warn("LGraphCanvas: no events binded"); return; } u.debug && console.log("pointerevents: unbindEvents"); var t = this.getCanvasWindow(), e = t.document; u.pointerListenerRemove(this.canvas, "move", this._mousedown_callback), u.pointerListenerRemove(this.canvas, "up", this._mousedown_callback), u.pointerListenerRemove(this.canvas, "down", this._mousedown_callback), this.canvas.removeEventListener( "mousewheel", this._mousewheel_callback ), this.canvas.removeEventListener( "DOMMouseScroll", this._mousewheel_callback ), this.canvas.removeEventListener("keydown", this._key_callback), e.removeEventListener("keyup", this._key_callback), this.canvas.removeEventListener("contextmenu", this._doNothing), this.canvas.removeEventListener("drop", this._ondrop_callback), this.canvas.removeEventListener("dragenter", this._doReturnTrue), this._mousedown_callback = null, this._mousewheel_callback = null, this._key_callback = null, this._ondrop_callback = null, this._events_binded = !1; } /** * this function allows to render the canvas using WebGL instead of Canvas2D * this is useful if you plant to render 3D objects inside your nodes, it uses litegl.js for webgl and canvas2DtoWebGL to emulate the Canvas2D calls in webGL **/ enableWebGL() { } /** * marks as dirty the canvas, this way it will be rendered again * @param fg if the foreground canvas is dirty (the one containing the nodes) * @param bg if the background canvas is dirty (the one containing the wires) */ setDirty(t = !1, e = !1) { t && (this.dirty_canvas = !0), e && (this.dirty_bgcanvas = !0); } /** * Used to attach the canvas in a popup * @return the window where the canvas is attached (the DOM root node) */ getCanvasWindow() { if (!this.canvas) return window; var t = this.canvas.ownerDocument; return t.defaultView; } adjustCanvasForHiDPI(t) { if (t || (t = window.devicePixelRatio), t == 1 || !this.canvas.parentNode) return; const e = this.canvas.parentNode.getBoundingClientRect(), { width: i, height: n } = e; this.canvas.width = i * t, this.canvas.height = n * t, this.canvas.style.width = i + "px", this.canvas.style.height = n + "px", this.canvas.getContext("2d").scale(t, t); } /** starts rendering the content of the canvas when needed */ startRendering() { if (this.is_rendering) return; this.is_rendering = !0, t.call(this); function t() { this.pause_rendering || this.draw(); var e = this.getCanvasWindow(); this.is_rendering && e.requestAnimationFrame(t.bind(this)); } } /** stops rendering the content of the canvas (to save resources) */ stopRendering() { this.is_rendering = !1; } //used to block future mouse events (because of im gui) blockClick() { this.block_click = !0, this.last_mouseclick = 0; } createDefaultNodeForSlot(t, e = {}) { var i = this, n = e.nodeFrom && e.slotFrom !== null, s = !n && e.nodeTo && e.slotTo !== null; if (e = { ...{ position: [0, 0], posAdd: [0, 0], posSizeFix: [0, 0] }, ...e }, !n && !s) return console.warn("No data passed to createDefaultNodeForSlot " + e.nodeFrom + " " + e.slotFrom + " " + e.nodeTo + " " + e.slotTo), !1; if (!t) return console.warn("No type to createDefaultNodeForSlot"), !1; var o = n ? e.nodeFrom : e.nodeTo, a = n ? e.slotFrom : e.slotTo, l = null; switch (typeof a) { case "string": l = n ? o.findOutputSlotIndexByName(a) : o.findInputSlotIndexByName(a), a = n ? o.outputs[a] : o.inputs[a]; break; case "object": l = n ? o.findOutputSlotIndexByName(a.name) : o.findInputSlotIndexByName(a.name); break; case "number": l = a, a = n ? o.outputs[a] : o.inputs[a]; break; case "undefined": default: return console.warn("Cant get slot information " + a), !1; } a = a, (!a || !l) && console.warn("createDefaultNodeForSlot bad slotX " + a + " " + l); var h = a.type == I.EVENT ? "_event_" : a.type, p = n ? u.slot_types_default_out : u.slot_types_default_in; const f = p[h]; if (p && f) { a.link !== null || a.links && a.links.length > 0; let _ = null; if (Array.isArray(f)) { for (var c in f) if (t == p[h][c] || t == "AUTO") { _ = p[h][c], u.debug && console.log("opts.nodeType == slotTypesDefault[fromSlotType][typeX] :: " + t); break; } } else throw new Error(`Invalid default slot specifier, must be an array: ${f}`); if (_) { var v = null; typeof _ == "object" && _.node && (v = _, _ = _.node); var g = u.createNode(_); if (g) { if (v) { if (v.properties) for (var d in v.properties) g.addProperty(d, v.properties[d]); if (v.inputs) { g.inputs = []; for (var d in v.inputs) g.addOutput( v.inputs[d][0], v.inputs[d][1] ); } if (v.outputs) { g.outputs = []; for (var d in v.outputs) g.addOutput( v.outputs[d][0], v.outputs[d][1] ); } v.title && (g.title = v.title), v.json && g.configure(v.json); } console.warn("PLACING", g.type, e); const y = e.position[0] + e.posAdd[0] + (e.posSizeFix[0] ? e.posSizeFix[0] * g.size[0] : 0), b = e.position[1] + e.posAdd[1] + (e.posSizeFix[1] ? e.posSizeFix[1] * g.size[1] : 0), m = [y, b]; return i.graph.add(g, { pos: m }), n ? e.nodeFrom.connectByTypeInput(l, g, h) : e.nodeTo.connectByTypeOutput(l, g, h), n && s && console.debug("connecting in between"), !0; } else console.log("failed creating " + _); } } return !1; } /** returns true if a position (in graph space) is on top of a node little corner box */ isOverNodeBox(t, e, i) { var n = u.NODE_TITLE_HEIGHT; return !!u.isInsideRectangle( e, i, t.pos[0] + 2, t.pos[1] + 2 - n, n - 4, n - 4 ); } /** returns slot index if a position (in graph space) is on top of a node input slot */ isOverNodeInput(t, e, i, n) { if (t.inputs) for (var s = 0, r = t.inputs.length; s < r; ++s) { var o = t.getConnectionPos(!0, s), a = !1; if (t.horizontal ? a = u.isInsideRectangle( e, i, o[0] - 5, o[1] - 10, 10, 20 ) : a = u.isInsideRectangle( e, i, o[0] - 10, o[1] - 5, 40, 10 ), a) return n && (n[0] = o[0], n[1] = o[1]), s; } return -1; } /** * returns the INDEX if a position (in graph space) is on top of a node output slot * @method isOverNodeOuput **/ isOverNodeOutput(t, e, i, n) { if (t.outputs) for (var s = 0, r = t.outputs.length; s < r; ++s) { t.outputs[s]; var o = t.getConnectionPos(!1, s), a = !1; if (t.horizontal ? a = u.isInsideRectangle( e, i, o[0] - 5, o[1] - 10, 10, 20 ) : a = u.isInsideRectangle( e, i, o[0] - 10, o[1] - 5, 40, 10 ), a) return n && (n[0] = o[0], n[1] = o[1]), s; } return -1; } findLinkCenterAtPos(t, e) { for (let i = 0; i < this.visible_links.length; ++i) { const n = this.visible_links[i]; if (this.graph && this.graph.links[n.id] == null) continue; const s = n._pos; if (!(!s || t < s[0] - 4 || t > s[0] + 4 || e < s[1] - 4 || e > s[1] + 4)) return n; } return null; } /** process a key event */ processKey(t) { if (!this.graph) return; var e = !1; if (u.debug && console.log("processKey", t), t.target instanceof Element && t.target.localName == "input") return; const i = this.allow_interaction && !this.read_only; if (t.type == "keydown") { if (t.keyCode == 32 && !(t.metaKey || t.ctrlKey || t.shiftKey) && (this.dragging_canvas = !0, e = !0), t.keyCode == 27 && !(t.metaKey || t.ctrlKey || t.shiftKey) && (this.node_panel && this.node_panel.close(), this.options_panel && this.options_panel.close(), e = !0), i && (t.keyCode == 65 && t.ctrlKey && (this.selectNodes(), e = !0), t.code == "KeyX" && (t.metaKey || t.ctrlKey) && !t.shiftKey && this.selected_nodes && (this.cutToClipboard(), e = !0), t.code == "KeyC" && (t.metaKey || t.ctrlKey) && !t.shiftKey && this.selected_nodes && (this.copyToClipboard(), e = !0), t.code == "KeyV" && (t.metaKey || t.ctrlKey) && !t.shiftKey && this.pasteFromClipboard(), t.code == "KeyD" && (t.metaKey || t.ctrlKey) && !t.shiftKey && (this.cloneSelection(), e = !0), (t.keyCode == 46 || t.keyCode == 8) && t.target instanceof Element && t.target.localName != "input" && t.target.localName != "textarea" && (this.deleteSelectedNodes(), e = !0), this.selected_nodes)) for (var n in this.selected_nodes) this.selected_nodes[n].onKeyDown && this.selected_nodes[n].onKeyDown(t); } else if (t.type == "keyup" && (t.keyCode == 32 && (this.dragging_canvas = !1), i && this.selected_nodes)) for (var n in this.selected_nodes) this.selected_nodes[n].onKeyUp && this.selected_nodes[n].onKeyUp(t); if (this.graph.change(), e) return t.preventDefault(), t.stopImmediatePropagation(), !1; } cutToClipboard() { this.copyToClipboard(), this.deleteSelectedNodes(); } copyToClipboard() { var t = { nodes: [], nodeCloneData: {}, links: [] }, e = 0, i = []; for (var n in this.selected_nodes) { var s = this.selected_nodes[n]; s._relative_id = e, i.push(s), e += 1; } for (let h = 0; h < i.length; ++h) { let p = i[h]; if (!p.clonable) continue; const f = { forNode: {} }; let c = p.clone(f); if (!c) { console.warn("node type not found: " + p.type); continue; } if (t.nodes.push(c.serialize()), t.nodeCloneData[c.id] = { prevNodeID: p.id, cloneData: f }, p.inputs && p.inputs.length) for (var r = 0; r < p.inputs.length; ++r) { var o = p.inputs[r]; if (!(!o || o.link == null)) { var a = this.graph.links[o.link]; if (a) { var l = this.graph.getNodeById( a.origin_id ); !l || !this.selected_nodes[l.id] || !this.selected_nodes[l.id].clonable || t.links.push([ l._relative_id, a.origin_slot, //j, p._relative_id, a.target_slot ]); } } } } localStorage.setItem( "litegrapheditor_clipboard", JSON.stringify(t) ); } pasteFromClipboard() { var t = localStorage.getItem("litegrapheditor_clipboard"); if (t) { this.graph.beforeChange(); for (var e = JSON.parse(t), i = null, n = null, s = 0; s < e.nodes.length; ++s) i ? (i[0] > e.nodes[s].pos[0] && (i[0] = e.nodes[s].pos[0], n[0] = s), i[1] > e.nodes[s].pos[1] && (i[1] = e.nodes[s].pos[1], n[1] = s)) : (i = [e.nodes[s].pos[0], e.nodes[s].pos[1]], n = [s, s]); for (var r = [], s = 0; s < e.nodes.length; ++s) { var o = e.nodes[s], a = u.createNode(o.type); if (a) { a.configure(o), a.pos[0] += this.graph_mouse[0] - i[0], a.pos[1] += this.graph_mouse[1] - i[1]; const { cloneData: c, prevNodeID: v } = e.nodeCloneData[a.id]; this.graph.add(a, { doProcessChange: !1, addedBy: "paste", prevNodeID: v, cloneData: c }), r.push(a); } } for (var s = 0; s < e.links.length; ++s) { var l = e.links[s], h = r[l[0]], p = r[l[2]]; h && p ? h.connect(l[1], p, l[3]) : console.warn("Warning, nodes missing on pasting"); } this.selectNodes(r), this.graph.afterChange(); } } cloneSelection() { if (!this.selected_nodes || Object.keys(this.selected_nodes).length === 0) return; this.graph.beforeChange(); const t = {}, e = [], i = {}; for (const r of Object.values(this.selected_nodes)) for (const o of r.iterateAllLinks()) this.selected_nodes[o.origin_id] && this.selected_nodes[o.target_id] && e.push(o); const n = function(r) { if (r.clonable == !1) return; const o = r.id, a = { forNode: {} }, l = r.clone(a); l && (i[o] = l, l.pos = [r.pos[0] + 5, r.pos[1] + 5], r.graph.add(l, { addedBy: "cloneSelection", prevNodeID: o, prevNode: r, cloneData: a }), t[l.id] = l); }; for (var s in this.selected_nodes) n(this.selected_nodes[s]); for (const r of e) { const o = i[r.origin_id], a = i[r.target_id]; o && a && o.connect(r.origin_slot, a, r.target_slot); } Object.keys(t).length && this.selectNodes(Object.values(t)), this.graph.afterChange(), this.setDirty(!0, !0); } processDrop(t) { let e = t; e.preventDefault(), this.adjustMouseEvent(e); var i = e.clientX, n = e.clientY, s = !this.viewport || this.viewport && i >= this.viewport[0] && i < this.viewport[0] + this.viewport[2] && n >= this.viewport[1] && n < this.viewport[1] + this.viewport[3]; if (s) { var r = [e.canvasX, e.canvasY], o = this.graph ? this.graph.getNodeOnPos(r[0], r[1]) : null; if (!o) { var a = null; this.onDropItem && (a = this.onDropItem(e)), a || this.checkDropItem(e); return; } if (o.onDropFile || o.onDropData) { var l = e.dataTransfer.files; if (l && l.length) for (var h = 0; h < l.length; h++) { var p = e.dataTransfer.files[0], f = p.name; if (ce.getFileExtension(f), o.onDropFile && o.onDropFile(p), o.onDropData) { var c = new FileReader(); c.onload = function(g) { var d = g.target.result; o.onDropData(d, f, p); }; var v = p.type.split("/")[0]; v == "text" || v == "" ? c.readAsText(p) : v == "image" ? c.readAsDataURL(p) : c.readAsArrayBuffer(p); } } } return !!(o.onDropItem && o.onDropItem(e) || this.onDropItem && this.onDropItem(e)); } } checkDropItem(t) { let e = t; if (e.dataTransfer.files.length) { var i = e.dataTransfer.files[0], n = ce.getFileExtension(i.name).toLowerCase(), s = u.node_types_by_file_extension[n]; if (s) { this.graph.beforeChange(); var r = u.createNode(s.type); r.pos = [e.canvasX, e.canvasY], this.graph.add(r), r.onDropFile && r.onDropFile(i), this.graph.afterChange(); } } } processNodeDblClicked(t) { this.onShowNodePanel ? this.onShowNodePanel(t) : this.showShowNodePanel(t), this.onNodeDblClicked && this.onNodeDblClicked(t), this.setDirty(!0); } processNodeSelected(t, e) { this.selectNode(t, e && (e.shiftKey || e.ctrlKey || this.multi_select)), this.onNodeSelected && this.onNodeSelected(t); } /** selects a given node (or adds it to the current selection) */ selectNode(t, e = !1) { t == null ? this.deselectAllNodes() : this.selectNodes([t], e); } /** selects several nodes (or adds them to the current selection) */ selectNodes(t, e = !1) { e || this.deselectAllNodes(), t = t || this.graph._nodes, typeof t == "string" && (t = [t]); for (var i in t) { var n = t[i]; if (n.is_selected) { this.deselectNode(n); continue; } if (!n.is_selected && n.onSelected && n.onSelected(), n.is_selected = !0, this.selected_nodes[n.id] = n, n.inputs) for (var s = 0; s < n.inputs.length; ++s) this.highlighted_links[n.inputs[s].link] = !0; if (n.outputs) for (var s = 0; s < n.outputs.length; ++s) { var r = n.outputs[s]; if (r.links) for (var o = 0; o < r.links.length; ++o) this.highlighted_links[r.links[o]] = !0; } } this.onSelectionChange && this.onSelectionChange(this.selected_nodes), this.setDirty(!0); } /** removes a node from the current selection */ deselectNode(t) { if (t.is_selected) { if (t.onDeselected && t.onDeselected(), t.is_selected = !1, this.onNodeDeselected && this.onNodeDeselected(t), t.inputs) for (var e = 0; e < t.inputs.length; ++e) delete this.highlighted_links[t.inputs[e].link]; if (t.outputs) for (var e = 0; e < t.outputs.length; ++e) { var i = t.outputs[e]; if (i.links) for (var n = 0; n < i.links.length; ++n) delete this.highlighted_links[i.links[n]]; } } } /** removes all nodes from the current selection */ deselectAllNodes() { if (this.graph) { for (var t = this.graph._nodes, e = 0, i = t.length; e < i; ++e) { var n = t[e]; n.is_selected && (n.onDeselected && n.onDeselected(), n.is_selected = !1, this.onNodeDeselected && this.onNodeDeselected(n)); } this.selected_nodes = {}, this.current_node = null, this.highlighted_links = {}, this.onSelectionChange && this.onSelectionChange(this.selected_nodes), this.setDirty(!0); } } /** deletes all nodes in the current selection from the graph */ deleteSelectedNodes() { this.graph.beforeChange(); for (var t in this.selected_nodes) { var e = this.selected_nodes[t]; if (!e.block_delete) { if (e.inputs && e.inputs.length && e.outputs && e.outputs.length && u.isValidConnection(e.inputs[0].type, e.outputs[0].type) && e.inputs[0].link && e.outputs[0].links && e.outputs[0].links.length) { var i = e.graph.links[e.inputs[0].link], n = e.graph.links[e.outputs[0].links[0]], s = e.getInputNode(0), r = e.getOutputNodes(0)[0]; s && r && s.connect(i.origin_slot, r, n.target_slot); } this.graph.remove(e), this.onNodeDeselected && this.onNodeDeselected(e); } } this.selected_nodes = {}, this.current_node = null, this.highlighted_links = {}, this.setDirty(!0), this.graph.afterChange(); } /** centers the camera on a given node */ centerOnNode(t) { this.ds.offset[0] = -t.pos[0] - t.size[0] * 0.5 + this.canvas.width * 0.5 / this.ds.scale, this.ds.offset[1] = -t.pos[1] - t.size[1] * 0.5 + this.canvas.height * 0.5 / this.ds.scale, this.setDirty(!0, !0); } /** * adds some useful properties to a mouse event, like the position in graph coordinates * @method adjustMouseEvent **/ adjustMouseEvent(t) { let e = t; var i = 0, n = 0; if (this.canvas) { var s = this.canvas.getBoundingClientRect(); i = e.clientX - s.left, n = e.clientY - s.top; } else i = e.clientX, n = e.clientY; return this.last_mouse_position[0] = i, this.last_mouse_position[1] = n, e.canvasX = i / this.ds.scale - this.ds.offset[0], e.canvasY = n / this.ds.scale - this.ds.offset[1], e; } /** process an event on widgets */ processNodeWidgets(t, e, i, n) { if (!t.widgets || !t.widgets.length || u.ignore_all_widget_events) return null; for (var s = e[0] - t.pos[0], r = e[1] - t.pos[1], o = t.size[0], a = this, l = this.getCanvasWindow(), h = 0; h < t.widgets.length; ++h) { var p = t.widgets[h]; if (!(!p || p.disabled)) { var f = p.computeSize ? p.computeSize(o)[1] : u.NODE_WIDGET_HEIGHT, c = p.width || o; if (!(p != n && (s < 6 || s > c - 12 || r < p.last_y || r > p.last_y + f || p.last_y === void 0))) { var v = p.value; switch (p.type) { case "button": i.type === u.pointerevents_method + "down" && (p.callback && setTimeout(function() { p.callback(p, a, t, e, i); }, 20), p.clicked = !0, this.dirty_canvas = !0); break; case "slider": p.options.max - p.options.min; var g = Te((s - 15) / (c - 30), 0, 1); p.value = p.options.min + (p.options.max - p.options.min) * g, p.callback && setTimeout(function() { E(p, p.value); }, 20), this.dirty_canvas = !0; break; case "number": case "combo": var v = p.value; if (i.type == u.pointerevents_method + "move" && p.type == "number") i.deltaX && (p.value += i.deltaX * (p.options.step || 0.1)), p.options.min != null && p.value < p.options.min && (p.value = p.options.min), p.options.max != null && p.value > p.options.max && (p.value = p.options.max); else if (i.type == u.pointerevents_method + "down") { var d = p.options.values; if (d && typeof d == "function") { let O = p.options.values; d = O(p, t); } var _ = null; p.type != "number" && (_ = Array.isArray(d) ? d : Object.keys(d)); var y = s < 40 ? -1 : s > c - 40 ? 1 : 0; if (p.type == "number") p.value += y * (p.options.step || 0.1), p.options.min != null && p.value < p.options.min && (p.value = p.options.min), p.options.max != null && p.value > p.options.max && (p.value = p.options.max); else if (y) { var b = -1; this.last_mouseclick = 0, d.constructor === Object ? b = _.indexOf(String(p.value)) + y : b = _.indexOf(p.value) + y, b >= _.length && (b = _.length - 1), b < 0 && (b = 0), Array.isArray(d) ? p.value = d[b] : p.value = b; } else { let O = function(M, L, B) { let G = M.content; return d != _ && (G = m.indexOf(G)), this.value = G, E(this, G), a.dirty_canvas = !0, !1; }; var m = d != _ ? Object.values(d) : d; let A = Array.from(m).map((M) => ({ content: M })); new X( A, { scale: Math.max(1, this.ds.scale), event: i, className: "dark", callback: O.bind(p) }, l ); } } else if (i.type == u.pointerevents_method + "up" && p.type == "number") { var y = s < 40 ? -1 : s > c - 40 ? 1 : 0; i.click_time < 200 && y == 0 && this.prompt( "Value", p.value, function(A) { this.value = Number(A), E(this, this.value); }.bind(p), i ); } v != p.value && setTimeout( function() { E(this, this.value); }.bind(p), 20 ), this.dirty_canvas = !0; break; case "toggle": i.type == u.pointerevents_method + "down" && (p.value = !p.value, setTimeout(function() { E(p, p.value); }, 20)); break; case "string": case "text": i.type == u.pointerevents_method + "down" && this.prompt( "Value", p.value, function(O) { this.value = O, E(this, O); }.bind(p), i, p.options ? p.options.multiline : !1, p.options.inputStyle ); break; default: p.mouse && (this.dirty_canvas = p.mouse(i, [s, r], t)); break; } return v != p.value && (t.onWidgetChanged && t.onWidgetChanged(p, v), t.graph._version++), p; } } } function E(T, O) { T.value = O, T.options && T.options.property && t.properties[T.options.property] !== void 0 && t.setProperty(T.options.property, O), T.callback && T.callback(T.value, a, t, e, i); } return null; } adjustNodesSize() { for (var t = this.graph._nodes, e = 0; e < t.length; ++e) t[e].size = t[e].computeSize(); this.setDirty(!0, !0); } /** resizes the canvas to a given size, if no size is passed, then it tries to fill the parentNode */ resize(t, e) { if (!t && !e) { var i = this.canvas.parentNode; t = i.offsetWidth, e = i.offsetHeight; } this.canvas.width == t && this.canvas.height == e || (this.canvas.width = t, this.canvas.height = e, this.bgcanvas.width = this.canvas.width, this.bgcanvas.height = this.canvas.height, this.adjustCanvasForHiDPI(), this.setDirty(!0, !0)); } isAreaClicked(t, e, i, n, s) { var r = this.offset_mouse; u.isInsideRectangle(r[0], r[1], t, e, i, n), r = this.last_click_position; var o = r && u.isInsideRectangle(r[0], r[1], t, e, i, n), a = o && !this.block_click; return o && s && this.blockClick(), a; } /** * switches to live mode (node shapes are not rendered, only the content) * this feature was designed when graphs where meant to create user interfaces **/ switchLiveMode(t) { if (!t) { this.live_mode = !this.live_mode, this.dirty_canvas = !0, this.dirty_bgcanvas = !0; return; } var e = this, i = this.live_mode ? 1.1 : 0.9; this.live_mode && (this.live_mode = !1, this.editor_alpha = 0.1); var n = setInterval(function() { e.editor_alpha *= i, e.dirty_canvas = !0, e.dirty_bgcanvas = !0, i < 1 && e.editor_alpha < 0.01 && (clearInterval(n), i < 1 && (e.live_mode = !0)), i > 1 && e.editor_alpha > 0.99 && (clearInterval(n), e.editor_alpha = 1); }, 1); } onNodeSelectionChange() { } touchHandler(t) { } convertOffsetToCanvas(t) { return this.ds.convertOffsetToCanvas(t); } convertCanvasToOffset(t, e = [0, 0]) { return this.ds.convertCanvasToOffset(t, e); } /** converts event coordinates from canvas2D to graph coordinates */ convertEventToCanvasOffset(t) { var e = this.canvas.getBoundingClientRect(); return this.convertCanvasToOffset([ t.clientX - e.left, t.clientY - e.top ]); } addGraphInputNode(t, e, i) { const n = this.graph.findNodesByClass($).find((o) => o.properties.name === e); if (n) { this.selectNodes([n]); return; } (!i || i === "") && (i = "*"); const s = [ this.canvas.width * 0.25 / this.ds.scale - this.ds.offset[0], this.canvas.height * 0.5 / this.ds.scale - this.ds.offset[1] ]; this.graph.beforeChange(); const r = t.addGraphInput(e, i, s); if (r) { const o = r.innerNode; this.selectNodes([o]), this.graph.afterChange(); } else console.error("graph input node not found:", i); } addGraphOutputNode(t, e, i) { const n = this.graph.findNodesByClass(Q).find((o) => o.properties.name === e); if (n) { this.selectNodes([n]); return; } (!i || i === "") && (i = "*"); const s = [ this.canvas.width * 0.75 / this.ds.scale - this.ds.offset[0], this.canvas.height * 0.5 / this.ds.scale - this.ds.offset[1] ]; this.graph.beforeChange(); const r = t.addGraphOutput(e, i, s); if (r) { const o = r.innerNode; this.selectNodes([o]), this.graph.afterChange(); } else console.error("graph output node not found:", i); } getCanvasMenuOptions() { return C.prototype.getCanvasMenuOptions.apply(this, arguments); } getNodeMenuOptions(t) { return C.prototype.getNodeMenuOptions.apply(this, arguments); } getLinkMenuOptions(t) { return C.prototype.getLinkMenuOptions.apply(this, arguments); } getGroupMenuOptions(t) { return C.prototype.getGroupMenuOptions.apply(this, arguments); } checkPanels() { C.prototype.checkPanels.apply(this, arguments); } closePanels() { C.prototype.closePanels.apply(this, arguments); } createDialog(t, e) { return C.prototype.createDialog.apply(this, arguments); } createPanel(t, e = {}) { return C.prototype.createPanel.apply(this, arguments); } showSearchBox(t, e = {}) { return C.prototype.showSearchBox.apply(this, arguments); } prompt(t = "", e, i, n, s = !1, r = null) { return C.prototype.prompt.apply(this, arguments); } showConnectionMenu(t = {}) { return C.prototype.showConnectionMenu.apply(this, arguments); } showLinkMenu(t, e) { return C.prototype.showLinkMenu.apply(this, arguments); } showEditPropertyValue(t, e, i) { return C.prototype.showEditPropertyValue.apply(this, arguments); } showShowNodePanel(t) { C.prototype.showShowNodePanel.apply(this, arguments); } showSubgraphPropertiesDialog(t) { return C.prototype.showSubgraphPropertiesDialog.apply(this, arguments); } showSubgraphPropertiesDialogRight(t) { return C.prototype.showSubgraphPropertiesDialogRight.apply(this, arguments); } processContextMenu(t, e) { C.prototype.processContextMenu.apply(this, arguments); } /* * Events */ processMouseMove(t) { return ge.prototype.processMouseMove.apply(this, arguments); } processMouseDown(t) { return ge.prototype.processMouseDown.apply(this, arguments); } processMouseUp(t) { return ge.prototype.processMouseUp.apply(this, arguments); } processMouseWheel(t) { return ge.prototype.processMouseWheel.apply(this, arguments); } /* * Rendering */ setZoom(t, e) { U.prototype.setZoom.apply(this, arguments); } bringToFront(t) { U.prototype.bringToFront.apply(this, arguments); } sendToBack(t) { U.prototype.sendToBack.apply(this, arguments); } computeVisibleNodes(t, e = []) { return U.prototype.computeVisibleNodes.apply(this, arguments); } draw(t = !1, e = !1) { U.prototype.draw.apply(this, arguments); } drawFrontCanvas() { U.prototype.drawFrontCanvas.apply(this, arguments); } drawSubgraphPanel(t) { U.prototype.drawSubgraphPanel.apply(this, arguments); } drawSubgraphPanelLeft(t, e, i) { U.prototype.drawSubgraphPanelLeft.apply(this, arguments); } drawSubgraphPanelRight(t, e, i) { U.prototype.drawSubgraphPanelRight.apply(this, arguments); } drawButton(t, e, i, n, s, r = u.NODE_DEFAULT_COLOR, o = "#555", a = u.NODE_TEXT_COLOR, l = !0) { return U.prototype.drawButton.apply(this, arguments); } drawBackCanvas() { U.prototype.drawBackCanvas.apply(this, arguments); } renderInfo(t, e = 10, i) { U.prototype.renderInfo.apply(this, arguments); } drawNode(t, e) { U.prototype.drawNode.apply(this, arguments); } drawLinkTooltip(t, e) { U.prototype.drawLinkTooltip.apply(this, arguments); } drawNodeShape(t, e, i, n, s, r, o) { U.prototype.drawNodeShape.apply(this, arguments); } drawConnections(t) { U.prototype.drawConnections.apply(this, arguments); } renderLink(t, e, i, n, s, r, o, a, l, h) { U.prototype.renderLink.apply(this, arguments); } computeConnectionPoint(t, e, i, n = w.RIGHT, s = w.LEFT) { return U.prototype.computeConnectionPoint.apply(this, arguments); } drawExecutionOrder(t) { U.prototype.drawExecutionOrder.apply(this, arguments); } drawNodeWidgets(t, e, i, n) { U.prototype.drawNodeWidgets.apply(this, arguments); } drawGroups(t, e) { U.prototype.drawGroups.apply(this, arguments); } /* * ComfyUI Extension */ updateBackground(t, e) { this._bg_img = new Image(), this._bg_img.name = t, this._bg_img.src = t, this._bg_img.onload = () => { this.draw(!0, !0); }, this.background_image = t, this.clear_background = !0, this.clear_background_color = e, this._pattern = null; } }; let N = ce; N.DEFAULT_BACKGROUND_IMAGE = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAIAAAD/gAIDAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQBJREFUeNrs1rEKwjAUhlETUkj3vP9rdmr1Ysammk2w5wdxuLgcMHyptfawuZX4pJSWZTnfnu/lnIe/jNNxHHGNn//HNbbv+4dr6V+11uF527arU7+u63qfa/bnmh8sWLBgwYJlqRf8MEptXPBXJXa37BSl3ixYsGDBMliwFLyCV/DeLIMFCxYsWLBMwSt4Be/NggXLYMGCBUvBK3iNruC9WbBgwYJlsGApeAWv4L1ZBgsWLFiwYJmCV/AK3psFC5bBggULloJX8BpdwXuzYMGCBctgwVLwCl7Be7MMFixYsGDBsu8FH1FaSmExVfAxBa/gvVmwYMGCZbBg/W4vAQYA5tRF9QYlv/QAAAAASUVORK5CYII="; N.node_colors = { red: { color: "#322", bgcolor: "#533", groupcolor: "#A88" }, brown: { color: "#332922", bgcolor: "#593930", groupcolor: "#b06634" }, green: { color: "#232", bgcolor: "#353", groupcolor: "#8A8" }, blue: { color: "#223", bgcolor: "#335", groupcolor: "#88A" }, pale_blue: { color: "#2a363b", bgcolor: "#3f5159", groupcolor: "#3f789e" }, cyan: { color: "#233", bgcolor: "#355", groupcolor: "#8AA" }, purple: { color: "#323", bgcolor: "#535", groupcolor: "#a1309b" }, yellow: { color: "#432", bgcolor: "#653", groupcolor: "#b58b2a" }, black: { color: "#222", bgcolor: "#000", groupcolor: "#444" } }; N.DEFAULT_LINK_TYPE_COLORS = { [I.ACTION]: u.ACTION_LINK_COLOR, [I.EVENT]: u.EVENT_LINK_COLOR, number: "#AAA", node: "#DCA" }; N.DEFAULT_CONNECTION_COLORS = { input_off: "#778", input_on: "#7F7", //"#BBD" output_off: "#778", output_on: "#7F7" //"#BBD" }; N.DEFAULT_CONNECTION_COLORS_BY_TYPE = { number: "#7F7", string: "#77F", boolean: "#F77" }; N.DEFAULT_CONNECTION_COLORS_BY_TYPE_OFF = { number: "#474", string: "#447", boolean: "#744" }; N.active_canvas = null; N.active_node = null; N.onMenuCollapseAll = C.onMenuCollapseAll; N.onMenuNodeEdit = C.onMenuNodeEdit; N.onShowPropertyEditor = C.onShowPropertyEditor; N.onGroupAdd = C.onGroupAdd; N.onMenuAdd = C.onMenuAdd; N.showMenuNodeOptionalInputs = C.showMenuNodeOptionalInputs; N.showMenuNodeOptionalOutputs = C.showMenuNodeOptionalOutputs; N.onShowMenuNodeProperties = C.onShowMenuNodeProperties; N.onResizeNode = C.onResizeNode; N.onMenuResizeNode = C.onMenuResizeNode; N.onMenuNodeCollapse = C.onMenuNodeCollapse; N.onMenuNodePin = C.onMenuNodePin; N.onMenuNodeMode = C.onMenuNodeMode; N.onMenuNodeColors = C.onMenuNodeColors; N.onMenuNodeShapes = C.onMenuNodeShapes; N.onMenuNodeRemove = C.onMenuNodeRemove; N.onMenuNodeClone = C.onMenuNodeClone; N.onMenuNodeToSubgraph = C.onMenuNodeToSubgraph; N.onMenuNodeToSubgraphInputs = C.onMenuNodeToSubgraphInputs; N.onMenuNodeToSubgraphOutputs = C.onMenuNodeToSubgraphOutputs; N.onMenuNodeToParentGraph = C.onMenuNodeToParentGraph; var j = /* @__PURE__ */ ((t) => (t[t.SEPARATOR = 0] = "SEPARATOR", t))(j || {}); class X { static trigger(e, i, n, s) { var r = document.createEvent("CustomEvent"); return r.initCustomEvent(i, !0, !0, n), r.target = s, e.dispatchEvent && e.dispatchEvent(r), r; } static isCursorOverElement(e, i) { var n = e.clientX, s = e.clientY, r = i.getBoundingClientRect(); return r ? s > r.top && s < r.top + r.height && n > r.left && n < r.left + r.width : !1; } static closeAllContextMenus(e) { e = e || window; var i = e.document.querySelectorAll(".litecontextmenu"); if (i.length) { var n = Array.from(i); for (const s of n) s.close(); } } constructor(e, i = {}, n) { var g; this.options = i; var s = this; i.parentMenu && (i.parentMenu.constructor !== this.constructor ? (console.error( "parentMenu must be of class ContextMenu, ignoring it" ), i.parentMenu = null) : (this.parentMenu = i.parentMenu, this.parentMenu.lock = !0, this.parentMenu.current_submenu = this)); var r = null; i.event && (r = i.event.constructor.name), r !== "MouseEvent" && r !== "CustomEvent" && r !== "PointerEvent" && (console.error( "Event passed to ContextMenu is not of type MouseEvent or CustomEvent. Ignoring it. (" + r + ")" ), i.event = null); var o = document.createElement("div"); if (o.className = "litegraph litecontextmenu litemenubar-panel", i.className && (o.className += " " + i.className), o.style.pointerEvents = "none", setTimeout(function() { o.style.pointerEvents = "auto"; }, 100), u.pointerListenerAdd( o, "up", function(d) { return d.preventDefault(), !0; }, !0 ), o.addEventListener( "contextmenu", function(d) { return d.button != 2 || d.preventDefault(), !1; }, !0 ), o.close = () => { o.parentNode.removeChild(o); }, u.pointerListenerAdd( o, "down", function(d) { if (d.button == 2) return s.close(), d.preventDefault(), !0; }, !0 ), i.scroll_speed || (i.scroll_speed = 0.1), o.addEventListener("wheel", this.onMouseWheel.bind(this), !0), o.addEventListener("mousewheel", this.onMouseWheel.bind(this), !0), this.root = o, i.title) { var a = document.createElement("div"); a.className = "litemenu-title", a.innerHTML = i.title, o.appendChild(a); } this.values = []; for (let d = 0; d < e.length; d++) { let _ = e[d], y = ""; _ === 0 || _ == null ? y = "" : typeof _ == "string" ? y = _ : y = _.content, this.addItem(y, _, i); } u.pointerListenerAdd(o, "enter", function(d) { o.closing_timer && clearTimeout(o.closing_timer); }); var l = document; i.event && i.event.target instanceof Node && (l = i.event.target.ownerDocument), l || (l = document), l.fullscreenElement ? l.fullscreenElement.appendChild(o) : l.body.appendChild(o); var h = i.left || 0, p = i.top || 0; if (i.event) { if (h = i.event.clientX - 10, p = i.event.clientY - 10, i.title && (p -= 20), i.parentMenu) { var f = i.parentMenu.root.getBoundingClientRect(); h = f.left + f.width; } var c = document.body.getBoundingClientRect(), v = o.getBoundingClientRect(); c.height == 0 && console.error("document.body height is 0. That is dangerous, set html,body { height: 100%; }"), c.width && h > c.width - v.width - 10 && (h = c.width - v.width - 10), c.height && p > c.height - v.height - 10 && (p = c.height - v.height - 10); } o.style.left = h + "px", o.style.top = p + "px", i.scale && (o.style.transform = "scale(" + i.scale + ")"), (g = u.onContextMenuCreated) == null || g.call(u, this); } addItem(e, i, n = {}) { var s = this, r = document.createElement("div"); r.className = "litemenu-entry submenu"; var o = !1; typeof i == "string" && (i = { content: i }), i === 0 || i == null ? r.classList.add("separator") : (r.innerHTML = i.title ? i.title : e, i.disabled && (o = !0, r.classList.add("disabled")), (i.submenu || i.has_submenu) && r.classList.add("has_submenu"), typeof i == "function" ? r.dataset.value = e : r.dataset.value = "" + this.values.length, i.className && (r.className += " " + i.className)), this.values.push(i), this.root.appendChild(r), o || r.addEventListener("click", h), n.autoopen && u.pointerListenerAdd(r, "enter", l); let a = this; function l(p) { var f = this.value; !f || !f.has_submenu || h.call(this, p); } function h(p) { let f = parseInt(this.dataset.value); var c = a.values[f]; u.debug && console.debug("ContextMenu inner_onclick", f, c); const v = N.active_canvas; if (!v) return; const g = v.adjustMouseEvent(p); var d = !0; if (s.current_submenu && s.current_submenu.close(g), n.callback) { var _ = n.callback.call( this, c, n, g, s, n.node ); _ === !0 && (d = !1); } if (c && typeof c == "object") { if (c.callback && !n.ignore_item_callbacks && c.disabled !== !0) { var _ = c.callback.call( this, c, n, g, s, n.extra ); _ === !0 && (d = !1); } if (c.submenu) { if (!c.submenu.options) throw "ContextMenu submenu needs options"; new X(c.submenu.options, { callback: c.submenu.callback, event: g, parentMenu: s, ignore_item_callbacks: c.submenu.ignore_item_callbacks, title: c.submenu.title, extra: c.submenu.extra, autoopen: n.autoopen }), d = !1; } } d && !s.lock && s.close(); } return r; } close(e, i) { this.root.parentNode && this.root.parentNode.removeChild(this.root), this.parentMenu && !i && (this.parentMenu.lock = !1, this.parentMenu.current_submenu = null, e === void 0 ? this.parentMenu.close() : e && !X.isCursorOverElement(e, this.parentMenu.root) && X.trigger(this.parentMenu.root, u.pointerevents_method + "leave", e)), this.current_submenu && this.current_submenu.close(e, !0), this.root.closing_timer && clearTimeout(this.root.closing_timer); } getTopMenu() { return this.options.parentMenu ? this.options.parentMenu.getTopMenu() : this; } getFirstEvent() { return this.options.parentMenu ? this.options.parentMenu.getFirstEvent() : this.options.event; } onMouseWheel(e) { var i = parseInt(this.root.style.top); return this.root.style.top = (i + e.deltaY * this.options.scroll_speed * (this.options.invert_scrolling ? -1 : 1)).toFixed() + "px", e.preventDefault(), !0; } } export { Ae as BASE_SLOT_TYPES, k as BuiltInSlotShape, I as BuiltInSlotType, X as ContextMenu, j as ContextMenuSpecialItem, w as Dir, Be as DragAndScale, $ as GraphInput, Q as GraphOutput, W as LConnectionKind, Pe as LGraph, N as LGraphCanvas, ge as LGraphCanvas_Events, U as LGraphCanvas_Rendering, C as LGraphCanvas_UI, me as LGraphGroup, ae as LGraphNode, xe as LGraphStatus, Xe as LINK_RENDER_MODE_NAMES, he as LLink, ue as LayoutDirection, de as LinkRenderMode, u as LiteGraph, Oe as NODE_MODE_COLORS, re as NODE_MODE_NAMES, Z as NodeMode, Ie as SLOT_SHAPE_NAMES, ne as Subgraph, se as TitleMode, Te as clamp, J as getLitegraphTypeName, we as getSlotTypesIn, We as getSlotTypesInFormatted, Le as getSlotTypesOut, Ye as getSlotTypesOutFormatted, Ce as getStaticProperty, ye as getStaticPropertyOnInstance, Se as isValidLitegraphType, Ee as makeDraggable, Re as reassignGraphIDs, ve as toHashMap };