| | import { app } from "../../../scripts/app.js"; |
| |
|
| | |
| |
|
| | const LOCKED = Symbol(); |
| |
|
| | function lockArray(arr, isLocked) { |
| | const v = []; |
| |
|
| | for (let i = 0; i < 2; i++) { |
| | v[i] = arr[i]; |
| |
|
| | Object.defineProperty(arr, i, { |
| | get() { |
| | return v[i]; |
| | }, |
| | set(value) { |
| | if (!isLocked()) { |
| | v[i] = value; |
| | } |
| | }, |
| | }); |
| | } |
| | } |
| |
|
| | app.registerExtension({ |
| | name: "pysssss.Locking", |
| | init() { |
| | function lockGroup(node) { |
| | node[LOCKED] = true; |
| | } |
| |
|
| | |
| | const serialize = LGraphGroup.prototype.serialize; |
| | LGraphGroup.prototype.serialize = function () { |
| | const o = serialize.apply(this, arguments); |
| | o.locked = !!this[LOCKED]; |
| | return o; |
| | }; |
| |
|
| | |
| | const configure = LGraphGroup.prototype.configure; |
| | LGraphGroup.prototype.configure = function (o) { |
| | configure.apply(this, arguments); |
| | if (o.locked) { |
| | lockGroup(this); |
| | } |
| | }; |
| |
|
| | |
| | const getGroupOnPos = LGraph.prototype.getGroupOnPos; |
| | LGraph.prototype.getGroupOnPos = function () { |
| | const r = getGroupOnPos.apply(this, arguments); |
| | if (r && r[LOCKED] && !new Error().stack.includes("processContextMenu")) return null; |
| | return r; |
| | }; |
| |
|
| | |
| | const getGroupMenuOptions = LGraphCanvas.prototype.getGroupMenuOptions; |
| | LGraphCanvas.prototype.getGroupMenuOptions = function (node) { |
| | const opts = getGroupMenuOptions.apply(this, arguments); |
| |
|
| | opts.unshift( |
| | node[LOCKED] |
| | ? { |
| | content: "Unlock", |
| | callback: () => { |
| | delete node[LOCKED]; |
| | }, |
| | } |
| | : { |
| | content: "Lock", |
| | callback: () => lockGroup(node), |
| | }, |
| | null |
| | ); |
| |
|
| | return opts; |
| | }; |
| | }, |
| | setup() { |
| | const drawNodeShape = LGraphCanvas.prototype.drawNodeShape; |
| | LGraphCanvas.prototype.drawNodeShape = function (node, ctx, size, fgcolor, bgcolor, selected, mouse_over) { |
| | const res = drawNodeShape.apply(this, arguments); |
| |
|
| | if (node[LOCKED]) { |
| | ctx.fillText("🔒", node.size[0] - 20, -10); |
| | } |
| |
|
| | return res; |
| | }; |
| | }, |
| | async beforeRegisterNodeDef(nodeType) { |
| | const nodesArray = (nodes) => { |
| | if (nodes) { |
| | if (nodes instanceof Array) { |
| | return nodes; |
| | } |
| | return [nodes]; |
| | } |
| | return Object.values(app.canvas.selected_nodes); |
| | }; |
| | function unlockNode(nodes) { |
| | nodes = nodesArray(nodes); |
| | for (const node of nodes) { |
| | delete node[LOCKED]; |
| | } |
| | app.graph.setDirtyCanvas(true, false); |
| | } |
| | function lockNode(nodes) { |
| | nodes = nodesArray(nodes); |
| | for (const node of nodes) { |
| | if (node[LOCKED]) continue; |
| |
|
| | node[LOCKED] = true; |
| | |
| | lockArray(node.pos, () => !!node[LOCKED]); |
| |
|
| | |
| | |
| | const sz = [node.size[0], node.size[1]]; |
| | Object.defineProperty(node, "size", { |
| | get() { |
| | return sz; |
| | }, |
| | set(value) { |
| | if (!node[LOCKED]) { |
| | sz[0] = value[0]; |
| | sz[1] = value[1]; |
| | } |
| | }, |
| | }); |
| | |
| | lockArray(sz, () => !!node[LOCKED]); |
| | } |
| |
|
| | app.graph.setDirtyCanvas(true, false); |
| | } |
| |
|
| | |
| | const getExtraMenuOptions = nodeType.prototype.getExtraMenuOptions; |
| | nodeType.prototype.getExtraMenuOptions = function (_, options) { |
| | const r = getExtraMenuOptions ? getExtraMenuOptions.apply(this, arguments) : undefined; |
| |
|
| | options.splice( |
| | options.findIndex((o) => o?.content === "Properties") + 1, |
| | 0, |
| | null, |
| | this[LOCKED] |
| | ? { |
| | content: "Unlock", |
| | callback: () => { |
| | unlockNode(); |
| | }, |
| | } |
| | : { |
| | content: "Lock", |
| | callback: () => lockNode(), |
| | } |
| | ); |
| |
|
| | return r; |
| | }; |
| |
|
| | |
| | const onSerialize = nodeType.prototype.onSerialize; |
| | nodeType.prototype.onSerialize = function (o) { |
| | if (onSerialize) { |
| | onSerialize.apply(this, arguments); |
| | } |
| | o.locked = this[LOCKED]; |
| | }; |
| |
|
| | |
| | const onConfigure = nodeType.prototype.onConfigure; |
| | nodeType.prototype.onConfigure = function (o) { |
| | if (onConfigure) { |
| | onConfigure.apply(this, arguments); |
| | } |
| | if (o.locked) { |
| | lockNode(this); |
| | } |
| | }; |
| | }, |
| | }); |
| |
|