diff --git a/mtb/comfy_shared.js b/mtb/comfy_shared.js deleted file mode 100644 index b8a1332..0000000 --- a/mtb/comfy_shared.js +++ /dev/null @@ -1,342 +0,0 @@ -/** - * File: comfy_shared.js - * Project: comfy_mtb - * Author: Mel Massadian - * - * Copyright (c) 2023 Mel Massadian - * - */ - -import { app } from '../../scripts/app.js' - -export const log = (...args) => { - if (window.MTB?.DEBUG) { - console.debug(...args) - } -} - -//- WIDGET UTILS -export const CONVERTED_TYPE = 'converted-widget' - -export const hasWidgets = (node) => { - if (!node.widgets || !node.widgets?.[Symbol.iterator]) { - return false - } - return true -} - -export const cleanupNode = (node) => { - if (!hasWidgets(node)) { - return - } - - for (const w of node.widgets) { - if (w.canvas) { - w.canvas.remove() - } - if (w.inputEl) { - w.inputEl.remove() - } - // calls the widget remove callback - w.onRemoved?.() - } -} - -export function offsetDOMWidget( - widget, - ctx, - node, - widgetWidth, - widgetY, - height -) { - const margin = 10 - const elRect = ctx.canvas.getBoundingClientRect() - const transform = new DOMMatrix() - .scaleSelf( - elRect.width / ctx.canvas.width, - elRect.height / ctx.canvas.height - ) - .multiplySelf(ctx.getTransform()) - .translateSelf(margin, margin + widgetY) - - const scale = new DOMMatrix().scaleSelf(transform.a, transform.d) - Object.assign(widget.inputEl.style, { - transformOrigin: '0 0', - transform: scale, - left: `${transform.a + transform.e}px`, - top: `${transform.d + transform.f}px`, - width: `${widgetWidth - margin * 2}px`, - // height: `${(widget.parent?.inputHeight || 32) - (margin * 2)}px`, - height: `${(height || widget.parent?.inputHeight || 32) - margin * 2}px`, - - position: 'absolute', - background: !node.color ? '' : node.color, - color: !node.color ? '' : 'white', - zIndex: 5, //app.graph._nodes.indexOf(node), - }) -} - -/** - * Extracts the type and link type from a widget config object. - * @param {*} config - * @returns - */ -export function getWidgetType(config) { - // Special handling for COMBO so we restrict links based on the entries - let type = config?.[0] - let linkType = type - if (type instanceof Array) { - type = 'COMBO' - linkType = linkType.join(',') - } - return { type, linkType } -} - -export const dynamic_connection = ( - node, - index, - connected, - connectionPrefix = 'input_', - connectionType = 'PSDLAYER' -) => { - // remove all non connected inputs - if (!connected && node.inputs.length > 1) { - log(`Removing input ${index} (${node.inputs[index].name})`) - if (node.widgets) { - const w = node.widgets.find((w) => w.name === node.inputs[index].name) - if (w) { - w.onRemoved?.() - node.widgets.length = node.widgets.length - 1 - } - } - node.removeInput(index) - - // make inputs sequential again - for (let i = 0; i < node.inputs.length; i++) { - node.inputs[i].label = `${connectionPrefix}${i + 1}` - } - } - - // add an extra input - if (node.inputs[node.inputs.length - 1].link != undefined) { - log( - `Adding input ${node.inputs.length + 1} (${connectionPrefix}${ - node.inputs.length + 1 - })` - ) - - node.addInput( - `${connectionPrefix}${node.inputs.length + 1}`, - connectionType - ) - } -} - -/** - * Appends a callback to the extra menu options of a given node type. - * @param {*} nodeType - * @param {*} cb - */ -export function addMenuHandler(nodeType, cb) { - const getOpts = nodeType.prototype.getExtraMenuOptions - nodeType.prototype.getExtraMenuOptions = function () { - const r = getOpts.apply(this, arguments) - cb.apply(this, arguments) - return r - } -} - -export function hideWidget(node, widget, suffix = '') { - widget.origType = widget.type - widget.hidden = true - widget.origComputeSize = widget.computeSize - widget.origSerializeValue = widget.serializeValue - widget.computeSize = () => [0, -4] // -4 is due to the gap litegraph adds between widgets automatically - widget.type = CONVERTED_TYPE + suffix - widget.serializeValue = () => { - // Prevent serializing the widget if we have no input linked - const { link } = node.inputs.find((i) => i.widget?.name === widget.name) - if (link == null) { - return undefined - } - return widget.origSerializeValue - ? widget.origSerializeValue() - : widget.value - } - - // Hide any linked widgets, e.g. seed+seedControl - if (widget.linkedWidgets) { - for (const w of widget.linkedWidgets) { - hideWidget(node, w, ':' + widget.name) - } - } -} - -export function showWidget(widget) { - widget.type = widget.origType - widget.computeSize = widget.origComputeSize - widget.serializeValue = widget.origSerializeValue - - delete widget.origType - delete widget.origComputeSize - delete widget.origSerializeValue - - // Hide any linked widgets, e.g. seed+seedControl - if (widget.linkedWidgets) { - for (const w of widget.linkedWidgets) { - showWidget(w) - } - } -} - -export function convertToWidget(node, widget) { - showWidget(widget) - const sz = node.size - node.removeInput(node.inputs.findIndex((i) => i.widget?.name === widget.name)) - - for (const widget of node.widgets) { - widget.last_y -= LiteGraph.NODE_SLOT_HEIGHT - } - - // Restore original size but grow if needed - node.setSize([Math.max(sz[0], node.size[0]), Math.max(sz[1], node.size[1])]) -} - -export function convertToInput(node, widget, config) { - hideWidget(node, widget) - - const { linkType } = getWidgetType(config) - - // Add input and store widget config for creating on primitive node - const sz = node.size - node.addInput(widget.name, linkType, { - widget: { name: widget.name, config }, - }) - - for (const widget of node.widgets) { - widget.last_y += LiteGraph.NODE_SLOT_HEIGHT - } - - // Restore original size but grow if needed - node.setSize([Math.max(sz[0], node.size[0]), Math.max(sz[1], node.size[1])]) -} - -export function hideWidgetForGood(node, widget, suffix = '') { - widget.origType = widget.type - widget.origComputeSize = widget.computeSize - widget.origSerializeValue = widget.serializeValue - widget.computeSize = () => [0, -4] // -4 is due to the gap litegraph adds between widgets automatically - widget.type = CONVERTED_TYPE + suffix - // widget.serializeValue = () => { - // // Prevent serializing the widget if we have no input linked - // const w = node.inputs?.find((i) => i.widget?.name === widget.name); - // if (w?.link == null) { - // return undefined; - // } - // return widget.origSerializeValue ? widget.origSerializeValue() : widget.value; - // }; - - // Hide any linked widgets, e.g. seed+seedControl - if (widget.linkedWidgets) { - for (const w of widget.linkedWidgets) { - hideWidgetForGood(node, w, ':' + widget.name) - } - } -} - -export function fixWidgets(node) { - if (node.inputs) { - for (const input of node.inputs) { - log(input) - if (input.widget || node.widgets) { - // if (newTypes.includes(input.type)) { - const matching_widget = node.widgets.find((w) => w.name === input.name) - if (matching_widget) { - // if (matching_widget.hidden) { - // log(`Already hidden skipping ${matching_widget.name}`) - // continue - // } - const w = node.widgets.find((w) => w.name === matching_widget.name) - if (w && w.type != CONVERTED_TYPE) { - log(w) - log(`hidding ${w.name}(${w.type}) from ${node.type}`) - log(node) - hideWidget(node, w) - } else { - log(`converting to widget ${w}`) - - convertToWidget(node, input) - } - } - } - } - } -} -export function inner_value_change(widget, value, event = undefined) { - if (widget.type == 'number' || widget.type == 'BBOX') { - value = Number(value) - } else if (widget.type == 'BOOL') { - value = Boolean(value) - } - widget.value = value - if ( - widget.options && - widget.options.property && - node.properties[widget.options.property] !== undefined - ) { - node.setProperty(widget.options.property, value) - } - if (widget.callback) { - widget.callback(widget.value, app.canvas, node, pos, event) - } -} - -//- COLOR UTILS -export function isColorBright(rgb, threshold = 240) { - const brightess = getBrightness(rgb) - return brightess > threshold -} - -function getBrightness(rgbObj) { - return Math.round( - (parseInt(rgbObj[0]) * 299 + - parseInt(rgbObj[1]) * 587 + - parseInt(rgbObj[2]) * 114) / - 1000 - ) -} - -//- HTML / CSS UTILS -export function defineClass(className, classStyles) { - const styleSheets = document.styleSheets - - // Helper function to check if the class exists in a style sheet - function classExistsInStyleSheet(styleSheet) { - const rules = styleSheet.rules || styleSheet.cssRules - for (const rule of rules) { - if (rule.selectorText === `.${className}`) { - return true - } - } - return false - } - - // Check if the class is already defined in any of the style sheets - let classExists = false - for (const styleSheet of styleSheets) { - if (classExistsInStyleSheet(styleSheet)) { - classExists = true - break - } - } - - // If the class doesn't exist, add the new class definition to the first style sheet - if (!classExists) { - if (styleSheets[0].insertRule) { - styleSheets[0].insertRule(`.${className} { ${classStyles} }`, 0) - } else if (styleSheets[0].addRule) { - styleSheets[0].addRule(`.${className}`, classStyles, 0) - } - } -}