|
import { app } from "/scripts/app.js"; |
|
|
|
|
|
|
|
const ids1 = new Set(["smZ CLIPTextEncode"]) |
|
const ids2 = new Set(["smZ Settings"]) |
|
const widgets = ['mean_normalization', 'multi_conditioning', 'use_old_emphasis_implementation', 'with_SDXL'] |
|
const widgets_sdxl = ['ascore', 'width', 'height', 'crop_w', 'crop_h', 'target_width', 'target_height', 'text_g', 'text_l'] |
|
const getSetWidgets = new Set(['parser', 'with_SDXL']) |
|
|
|
let origProps = {}; |
|
const HIDDEN_TAG = "smZhidden" |
|
|
|
const findWidgetByName = (node, name) => node.widgets.find((w) => w.name === name); |
|
const findWidgetsByName = (node, name) => node.widgets.filter((w) => w.name.endsWith(name)); |
|
|
|
const doesInputWithNameExist = (node, name) => node.inputs ? node.inputs.some((input) => input.name === name) : false; |
|
|
|
|
|
function round(number, increment = 10, offset = 0) { |
|
return Math.ceil((number - offset) / increment ) * increment + offset; |
|
} |
|
|
|
function toggleWidget(node, widget, show = false, suffix = "") { |
|
if (!widget || doesInputWithNameExist(node, widget.name)) return; |
|
if (!origProps[widget.name]) { |
|
origProps[widget.name] = { origType: widget.type, origComputeSize: widget.computeSize}; |
|
} |
|
const origSize = node.size; |
|
|
|
widget.type = show ? origProps[widget.name].origType : HIDDEN_TAG + suffix; |
|
widget.computeSize = show ? origProps[widget.name].origComputeSize : () => [0, -3.3]; |
|
|
|
widget.linkedWidgets?.forEach(w => toggleWidget(node, w, ":" + widget.name, show)); |
|
|
|
const height = show ? Math.max(node.computeSize()[1], origSize[1]) : node.size[1]; |
|
node.setSize([node.size[0], height]); |
|
if (show) |
|
delete widget.computedHeight; |
|
else |
|
widget.computedHeight = 0; |
|
} |
|
|
|
function widgetLogic(node, widget) { |
|
const wname = widget.name |
|
if (wname.endsWith("parser")) { |
|
const in_comfy = widget.value.includes("comfy") |
|
toggleMenuOption(node, ['multi_conditioning', wname], !in_comfy) |
|
toggleMenuOption(node, ['mean_normalization', wname], widget.value !== "comfy") |
|
if (in_comfy) { |
|
toggleMenuOption(node, ['use_old_emphasis_implementation', wname], false) |
|
} |
|
} else if (wname.endsWith("with_SDXL")) { |
|
toggleMenuOption(node, ['text', wname], !widget.value) |
|
|
|
|
|
if (!widget.value) { |
|
|
|
if(widget.init === false) { |
|
|
|
node.setSize([node.size[0], Math.max(100, round(node.size[1]/1.5))]) |
|
} |
|
} else { |
|
|
|
widget.init = false |
|
} |
|
|
|
|
|
for (const w of widgets_sdxl) { |
|
toggleMenuOption(node, [w, wname], widget.value) |
|
} |
|
|
|
|
|
if (widget.value && widget.type === HIDDEN_TAG) { |
|
toggleMenuOption(node, [widget.name, wname], true) |
|
} |
|
} |
|
} |
|
|
|
function getGroupNodeConfig(node) { |
|
let ls = [] |
|
let nodeData = node.constructor?.nodeData |
|
if (nodeData) { |
|
for(let sym of Object.getOwnPropertySymbols(nodeData) ) { |
|
const o = nodeData[sym]; |
|
if (!o) continue; |
|
ls.push(o) |
|
} |
|
} |
|
return ls |
|
} |
|
|
|
function getSetters(node) { |
|
if (node.widgets) { |
|
let gncl = getGroupNodeConfig(node) |
|
for (const w of node.widgets) { |
|
for (const gsw of [...getSetWidgets]) { |
|
if (!w.name.endsWith(gsw)) continue; |
|
let shouldBreak = false |
|
for (const gnc of gncl) { |
|
const nwmap = gnc.newToOldWidgetMap[w.name] |
|
if (nwmap && !(nwmap.node.type === [...ids1][0] && nwmap.inputName === gsw)) |
|
shouldBreak = true |
|
} |
|
if (shouldBreak) break; |
|
widgetLogic(node, w); |
|
w._value = w.value |
|
|
|
Object.defineProperty(w, 'value', { |
|
get() { |
|
return w._value; |
|
}, |
|
set(newVal) { |
|
w._value = newVal |
|
widgetLogic(node, w); |
|
} |
|
}); |
|
|
|
|
|
|
|
if (w.name.endsWith('with_SDXL')) { |
|
toggleMenuOption(node, ['with_SDXL', w.name]) |
|
w.init = true |
|
|
|
|
|
toggleMenuOption(node, ['smZ_steps', w.name] , false) |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
function toggleMenuOption(node, widget_arr, _show = null, perform_action = true) { |
|
const gncl = getGroupNodeConfig(node) |
|
const [widget_name, companion_widget_name] = Array.isArray(widget_arr) ? widget_arr : [widget_arr] |
|
let nwname = widget_name |
|
|
|
if (companion_widget_name) { |
|
for (const gnc of gncl) { |
|
const omap = Object.values(gnc.oldToNewWidgetMap).find(x => Object.values(x).find(z => z === companion_widget_name)) |
|
const tmp2 = omap[widget_name] |
|
if (tmp2) nwname = tmp2; |
|
} |
|
} |
|
const widgets = companion_widget_name ? [findWidgetByName(node, nwname)] : findWidgetsByName(node, nwname) |
|
for (const widget of widgets) |
|
toggleMenuOption0(node, widget, _show, perform_action) |
|
} |
|
|
|
function toggleMenuOption0(node, widget, _show = null, perform_action = true) { |
|
if (!widget || doesInputWithNameExist(node, widget.name)) return; |
|
if (!origProps[widget.name]) { |
|
origProps[widget.name] = { origType: widget.type, origComputeSize: widget.computeSize}; |
|
} |
|
const show = (widget.type === origProps[widget.name].origType) |
|
if (perform_action) { |
|
toggleWidget(node, widget, _show !== null ? _show : !show) |
|
node.setDirtyCanvas(true); |
|
} |
|
} |
|
|
|
function toggle_all_settings_desc_widgets(node, _show = null) { |
|
let found_widgets = node.widgets.filter((w) => w.name.includes('info')); |
|
let is_showing = _show !== null ? _show : null |
|
found_widgets.forEach(w => { |
|
toggleMenuOption(node, [w.name, w.name], _show) |
|
is_showing = _show !== null ? _show : w.type === origProps[w.name].origType |
|
}); |
|
|
|
let w = node.widgets.find((w) => w.name === 'extra'); |
|
if (w) { |
|
let value = null; |
|
try { |
|
value =JSON.parse(w.value); |
|
} catch (error) { |
|
|
|
value = {"show":true} |
|
} |
|
value.show = is_showing; |
|
w.value = JSON.stringify(value); |
|
} |
|
|
|
|
|
if (!is_showing) { |
|
node.setSize([node.size[0], node.computeSize()[1]]) |
|
} |
|
} |
|
|
|
function create_custom_option(content, _callback) { |
|
return { |
|
content: content, |
|
callback: () => _callback(), |
|
} |
|
}; |
|
|
|
app.registerExtension({ |
|
name: "comfy.smZ.dynamicWidgets", |
|
|
|
|
|
|
|
|
|
|
|
|
|
nodeCreated(node) { |
|
const nodeType = node.type || node.constructor?.type |
|
let inGroupNode = false |
|
let inGroupNode2 = false |
|
let innerNodes = node.getInnerNodes?.() |
|
if (innerNodes) { |
|
for (const inode of innerNodes) { |
|
const _nodeType = inode.type || inode.constructor?.type |
|
if (ids1.has(_nodeType)) |
|
inGroupNode = ids1.has(_nodeType) |
|
if (inGroupNode) |
|
ids1.add(nodeType) |
|
if (ids2.has(_nodeType)) |
|
inGroupNode2 = ids2.has(_nodeType) |
|
if (inGroupNode2) |
|
ids2.add(nodeType) |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (ids1.has(nodeType) || inGroupNode) { |
|
node.widgets.forEach(w => w._name = w.name) |
|
|
|
getSetters(node) |
|
|
|
|
|
|
|
node.setSize([node.size[0], 220]) |
|
} |
|
|
|
if (ids2.has(nodeType) || inGroupNode2) { |
|
node.serialize_widgets = true |
|
|
|
const onConfigure = node.onConfigure; |
|
node.onConfigure = function(o) { |
|
const r = onConfigure ? onConfigure.apply(this, arguments) : undefined; |
|
const w = this.widgets.find(w => w.name === 'extra') |
|
let value = null |
|
try { |
|
value = JSON.parse(w.value); |
|
} catch (error) { |
|
|
|
value = {"show":true} |
|
} |
|
toggle_all_settings_desc_widgets(this, value.show) |
|
return r; |
|
} |
|
|
|
|
|
node.widgets.forEach(function(w) { |
|
w._name = w.name |
|
if (w.name.includes('ㅤ')) { |
|
w.heading = true |
|
} else if (w.name.includes('info')) { |
|
w.info = true |
|
w.inputEl.disabled = true; |
|
w.inputEl.readOnly = true; |
|
w.inputEl.style.opacity = 0.75; |
|
w.inputEl.style.alignContent = 'center'; |
|
w.inputEl.style.textAlign = 'center'; |
|
} |
|
}) |
|
|
|
toggleMenuOption(node, 'extra', false) |
|
} |
|
|
|
|
|
if (ids1.has(nodeType) || inGroupNode || ids2.has(nodeType) || inGroupNode2) { |
|
|
|
const getExtraMenuOptions = node.getExtraMenuOptions; |
|
|
|
node.getExtraMenuOptions = function (_, options) { |
|
|
|
const r = getExtraMenuOptions ? getExtraMenuOptions.apply(this, arguments) : undefined; |
|
let customOptions = [] |
|
node.setDirtyCanvas(true, true); |
|
|
|
|
|
if (ids2.has(nodeType) || inGroupNode2) { |
|
const content_hide_show = "Hide/show all descriptions"; |
|
customOptions.push(null) |
|
customOptions.push(create_custom_option(content_hide_show, toggle_all_settings_desc_widgets.bind(this, node))) |
|
|
|
|
|
const toHideWidgets = node.widgets.filter(w => w.name.includes('ㅤ') || w.name.includes('info') || w.name.includes('extra')) |
|
const wo = options.filter(o => o === null || (o && !toHideWidgets.some(w => o.content.includes(`Convert ${w.name} to input`)))) |
|
options.splice(0, options.length, ...wo); |
|
} |
|
|
|
if (ids1.has(nodeType) || inGroupNode) { |
|
|
|
const content_hide_show = "Hide/show "; |
|
|
|
const hiddenWidgets = node.widgets.filter(w => w.type === HIDDEN_TAG) |
|
|
|
const with_SDXL = node.widgets.find(w => w.name === 'with_SDXL') |
|
const parser = node.widgets.find(w => w.name === 'parser') |
|
const in_comfy = parser.value.includes("comfy") |
|
let ws = widgets.map(widget_name => create_custom_option(content_hide_show + widget_name, toggleMenuOption.bind(this, node, widget_name))) |
|
ws = ws.filter((w) => (in_comfy && parser.value !== 'comfy' && w.content.includes('mean_normalization')) || (in_comfy && w.content.includes('with_SDXL')) || !in_comfy ) |
|
|
|
customOptions.push(...ws) |
|
|
|
let wo = options.filter(o => o === null || (o && !hiddenWidgets.some(w => o.content.includes(`Convert ${w.name} to input`)))) |
|
const width = node.widgets.find(w => w.name === 'width') |
|
const height = node.widgets.find(w => w.name === 'height') |
|
if (width && height) { |
|
const width_type = width.type.toLowerCase() |
|
const height_type = height.type.toLowerCase() |
|
if (!(width_type.includes('number') || width_type.includes('int') || width_type.includes('float') || |
|
height_type.includes('number') || height_type.includes('int') || height_type.includes('float'))) |
|
wo = wo.filter(o => o === null || (o && !o.content.includes('Swap width/height'))) |
|
} |
|
options.splice(0, options.length, ...wo); |
|
} |
|
|
|
options.splice(options.length - 1, 0, ...customOptions) |
|
|
|
} |
|
} |
|
} |
|
}); |
|
|