| | import { app } from "../../../scripts/app.js"; |
| | app.registerExtension({ |
| | name: "pysssss.ContextMenuHook", |
| | init() { |
| | const getOrSet = (target, name, create) => { |
| | if (name in target) return target[name]; |
| | return (target[name] = create()); |
| | }; |
| | const symbol = getOrSet(window, "__pysssss__", () => Symbol("__pysssss__")); |
| | const store = getOrSet(window, symbol, () => ({})); |
| | const contextMenuHook = getOrSet(store, "contextMenuHook", () => ({})); |
| | for (const e of ["ctor", "preAddItem", "addItem"]) { |
| | if (!contextMenuHook[e]) { |
| | contextMenuHook[e] = []; |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | const ctorProxy = new Proxy(LiteGraph.ContextMenu, { |
| | construct(target, args) { |
| | return new LiteGraph.ContextMenu(...args); |
| | }, |
| | }); |
| |
|
| | function triggerCallbacks(name, getArgs, handler) { |
| | const callbacks = contextMenuHook[name]; |
| | if (callbacks && callbacks instanceof Array) { |
| | for (const cb of callbacks) { |
| | const r = cb(...getArgs()); |
| | handler?.call(this, r); |
| | } |
| | } else { |
| | console.warn("[pysssss 🐍]", `invalid ${name} callbacks`, callbacks, name in contextMenuHook); |
| | } |
| | } |
| |
|
| | const addItem = LiteGraph.ContextMenu.prototype.addItem; |
| | LiteGraph.ContextMenu.prototype.addItem = function () { |
| | const proxy = new Proxy(this, { |
| | get(target, prop) { |
| | if (prop === "constructor") { |
| | return ctorProxy; |
| | } |
| | return target[prop]; |
| | }, |
| | }); |
| | proxy.__target__ = this; |
| |
|
| | let el; |
| | let args = arguments; |
| | triggerCallbacks( |
| | "preAddItem", |
| | () => [el, this, args], |
| | (r) => { |
| | if (r !== undefined) el = r; |
| | } |
| | ); |
| |
|
| | if (el === undefined) { |
| | el = addItem.apply(proxy, arguments); |
| | } |
| |
|
| | triggerCallbacks( |
| | "addItem", |
| | () => [el, this, args], |
| | (r) => { |
| | if (r !== undefined) el = r; |
| | } |
| | ); |
| | return el; |
| | }; |
| |
|
| | |
| | const ctxMenu = LiteGraph.ContextMenu; |
| | LiteGraph.ContextMenu = function (values, options) { |
| | if (options?.parentMenu) { |
| | if (options.parentMenu.__target__) { |
| | options.parentMenu = options.parentMenu.__target__; |
| | } |
| | } |
| |
|
| | triggerCallbacks("ctor", () => [values, options]); |
| | ctxMenu.call(this, values, options); |
| | }; |
| | LiteGraph.ContextMenu.prototype = ctxMenu.prototype; |
| | }, |
| | }); |
| |
|