| import { api } from "../../scripts/api.js"; | |
| import { app } from "../../scripts/app.js"; | |
| let original_show = app.ui.dialog.show; | |
| export function customAlert(message) { | |
| try { | |
| app.extensionManager.toast.addAlert(message); | |
| } | |
| catch { | |
| alert(message); | |
| } | |
| } | |
| export function isBeforeFrontendVersion(compareVersion) { | |
| try { | |
| const frontendVersion = window['__COMFYUI_FRONTEND_VERSION__']; | |
| if (typeof frontendVersion !== 'string') { | |
| return false; | |
| } | |
| function parseVersion(versionString) { | |
| const parts = versionString.split('.').map(Number); | |
| return parts.length === 3 && parts.every(part => !isNaN(part)) ? parts : null; | |
| } | |
| const currentVersion = parseVersion(frontendVersion); | |
| const comparisonVersion = parseVersion(compareVersion); | |
| if (!currentVersion || !comparisonVersion) { | |
| return false; | |
| } | |
| for (let i = 0; i < 3; i++) { | |
| if (currentVersion[i] > comparisonVersion[i]) { | |
| return false; | |
| } else if (currentVersion[i] < comparisonVersion[i]) { | |
| return true; | |
| } | |
| } | |
| return false; | |
| } catch { | |
| return true; | |
| } | |
| } | |
| function dialog_show_wrapper(html) { | |
| if (typeof html === "string") { | |
| if(html.includes("IMPACT-PACK-SIGNAL: STOP CONTROL BRIDGE")) { | |
| return; | |
| } | |
| this.textElement.innerHTML = html; | |
| } else { | |
| this.textElement.replaceChildren(html); | |
| } | |
| this.element.style.display = "flex"; | |
| } | |
| app.ui.dialog.show = dialog_show_wrapper; | |
| function nodeFeedbackHandler(event) { | |
| let nodes = app.graph._nodes_by_id; | |
| let node = nodes[event.detail.node_id]; | |
| if(node) { | |
| const w = node.widgets.find((w) => event.detail.widget_name === w.name); | |
| if(w) { | |
| w.value = event.detail.value; | |
| } | |
| } | |
| } | |
| api.addEventListener("impact-node-feedback", nodeFeedbackHandler); | |
| function setMuteState(event) { | |
| let nodes = app.graph._nodes_by_id; | |
| let node = nodes[event.detail.node_id]; | |
| if(node) { | |
| if(event.detail.is_active) | |
| node.mode = 0; | |
| else | |
| node.mode = 2; | |
| } | |
| } | |
| api.addEventListener("impact-node-mute-state", setMuteState); | |
| async function bridgeContinue(event) { | |
| let nodes = app.graph._nodes_by_id; | |
| let node = nodes[event.detail.node_id]; | |
| if(node) { | |
| const mutes = new Set(event.detail.mutes); | |
| const actives = new Set(event.detail.actives); | |
| const bypasses = new Set(event.detail.bypasses); | |
| for(let i in app.graph._nodes_by_id) { | |
| let this_node = app.graph._nodes_by_id[i]; | |
| if(mutes.has(i)) { | |
| this_node.mode = 2; | |
| } | |
| else if(actives.has(i)) { | |
| this_node.mode = 0; | |
| } | |
| else if(bypasses.has(i)) { | |
| this_node.mode = 4; | |
| } | |
| } | |
| await app.queuePrompt(0, 1); | |
| } | |
| } | |
| api.addEventListener("impact-bridge-continue", bridgeContinue); | |
| function addQueue(event) { | |
| app.queuePrompt(0, 1); | |
| } | |
| api.addEventListener("impact-add-queue", addQueue); | |
| function refreshPreview(event) { | |
| let node_id = event.detail.node_id; | |
| let item = event.detail.item; | |
| let img = new Image(); | |
| img.src = `/view?filename=${item.filename}&subfolder=${item.subfolder}&type=${item.type}&no-cache=${Date.now()}`; | |
| let node = app.graph._nodes_by_id[node_id]; | |
| if(node) | |
| node.imgs = [img]; | |
| } | |
| api.addEventListener("impact-preview", refreshPreview); | |
| // ============================================================================ | |
| // MaskRectArea Shared Utilities | |
| // ============================================================================ | |
| /** | |
| * Reads a numeric value from a connected link by inspecting the origin node widget. | |
| * More reliable than getInputData() in ComfyUI's frontend execution model. | |
| * | |
| * @param {LGraphNode} node - LiteGraph node instance | |
| * @param {string} inputName - Name of the input to read | |
| * @returns {number|null} The numeric value or null if not available | |
| */ | |
| export function readLinkedNumber(node, inputName) { | |
| try { | |
| if (!node || !node.graph || !Array.isArray(node.inputs)) { | |
| return null; | |
| } | |
| const inp = node.inputs.find(i => i && i.name === inputName); | |
| if (!inp || inp.link == null) { | |
| return null; | |
| } | |
| const link = node.graph.links && node.graph.links[inp.link]; | |
| if (!link) { | |
| return null; | |
| } | |
| const originNode = node.graph.getNodeById | |
| ? node.graph.getNodeById(link.origin_id) | |
| : null; | |
| if (!originNode || !Array.isArray(originNode.widgets) || originNode.widgets.length === 0) { | |
| return null; | |
| } | |
| const w = originNode.widgets.find(ww => ww && ww.name === "value") | |
| || originNode.widgets[0]; | |
| const v = w ? w.value : null; | |
| return (typeof v === "number") ? v : null; | |
| } catch (e) { | |
| return null; | |
| } | |
| } | |
| /** | |
| * Generates a color based on percentage using HSL color space. | |
| * | |
| * @param {number} percent - Value between 0 and 1 | |
| * @param {string} alpha - Hex alpha value (e.g., "ff", "80") | |
| * @returns {string} Hex color string with alpha (e.g., "#ff8040ff") | |
| */ | |
| export function getDrawColor(percent, alpha) { | |
| let h = 360 * percent; | |
| let s = 50; | |
| let l = 50; | |
| l /= 100; | |
| const a = s * Math.min(l, 1 - l) / 100; | |
| const f = n => { | |
| const k = (n + h / 30) % 12; | |
| const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1); | |
| return Math.round(255 * color).toString(16).padStart(2, '0'); | |
| }; | |
| return `#${f(0)}${f(8)}${f(4)}${alpha}`; | |
| } | |
| /** | |
| * Computes and adjusts canvas size for preview widgets. | |
| * | |
| * @param {LGraphNode} node - LiteGraph node instance | |
| * @param {[number, number]} size - [width, height] array | |
| * @param {number} minHeight - Minimum canvas height (REQUIRED) | |
| * @param {number} minWidth - Minimum canvas width (REQUIRED) | |
| * @returns {void} | |
| */ | |
| export function computeCanvasSize(node, size, minHeight, minWidth) { | |
| // Validate required parameters | |
| if (typeof minHeight !== 'number' || typeof minWidth !== 'number') { | |
| console.warn('[computeCanvasSize] minHeight and minWidth are required parameters'); | |
| return; | |
| } | |
| // Null safety check for widgets array | |
| if (!node.widgets?.length || node.widgets[0].last_y == null) { | |
| return; | |
| } | |
| // LiteGraph global availability check | |
| const NODE_WIDGET_HEIGHT = (typeof LiteGraph !== 'undefined' && LiteGraph.NODE_WIDGET_HEIGHT) | |
| ? LiteGraph.NODE_WIDGET_HEIGHT | |
| : 20; | |
| let y = node.widgets[0].last_y + 5; | |
| let freeSpace = size[1] - y; | |
| // Compute the height of all non-customCanvas widgets | |
| let widgetHeight = 0; | |
| for (let i = 0; i < node.widgets.length; i++) { | |
| const w = node.widgets[i]; | |
| if (w.type !== "customCanvas") { | |
| if (w.computeSize) { | |
| widgetHeight += w.computeSize()[1] + 4; | |
| } else { | |
| widgetHeight += NODE_WIDGET_HEIGHT + 5; | |
| } | |
| } | |
| } | |
| // Ensure there is enough vertical space | |
| freeSpace -= widgetHeight; | |
| // Clamp minimum canvas height | |
| if (freeSpace < minHeight) { | |
| freeSpace = minHeight; | |
| } | |
| // Allow both grow and shrink to fit content | |
| const targetHeight = y + widgetHeight + freeSpace; | |
| if (node.size[1] !== targetHeight) { | |
| node.size[1] = targetHeight; | |
| node.graph.setDirtyCanvas(true); | |
| } | |
| // Ensure the node width meets the minimum width requirement | |
| if (node.size[0] < minWidth) { | |
| node.size[0] = minWidth; | |
| node.graph.setDirtyCanvas(true); | |
| } | |
| // Position each of the widgets | |
| for (const w of node.widgets) { | |
| w.y = y; | |
| if (w.type === "customCanvas") { | |
| y += freeSpace; | |
| } else if (w.computeSize) { | |
| y += w.computeSize()[1] + 4; | |
| } else { | |
| y += NODE_WIDGET_HEIGHT + 4; | |
| } | |
| } | |
| node.canvasHeight = freeSpace; | |
| } | |
Xet Storage Details
- Size:
- 7.81 kB
- Xet hash:
- 975934996caa38104d8e6f7e7816b999f242e0a3254d47af9a9d3252ee482a4e
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.