Files
MajoorWaldi-ComfyUI-Majoor-…/js/preview/shared/widgets.js
T

253 lines
8.2 KiB
JavaScript

import { isNode as isAppendNode } from "../nodes/append.js";
import { isNode as isFrameRangeNode } from "../nodes/frame-range.js";
import { isImageOpsNativeUiClass } from "./classes.js";
import { markCanvasDirty } from "./canvas.js";
function syncWidgetElement(widget, value) {
const element = widget?.element;
if (!element) return;
if (typeof value === "boolean") {
if ("checked" in element) {
element.checked = value;
}
if ("value" in element) {
element.value = value ? "true" : "false";
}
return;
}
if ("value" in element) {
element.value = String(value);
}
}
function notifyWidgetChanged(widget, value) {
if (!widget) return;
try {
widget.callback?.(value);
} catch {
}
}
function findWidget(node, name) {
return node?.widgets?.find((w) => w?.name === name) ?? null;
}
function widgetNumber(node, name, fallback = 0) {
const value = findWidget(node, name)?.value;
const parsed = parseFloat(String(value ?? ""));
return Number.isFinite(parsed) ? parsed : fallback;
}
function widgetString(node, name, fallback = "") {
const value = findWidget(node, name)?.value;
return typeof value === "string" ? value : fallback;
}
function widgetBoolean(node, name, fallback = false) {
const value = findWidget(node, name)?.value;
if (typeof value === "boolean") return value;
if (typeof value === "number") return !!value;
if (typeof value === "string") return value.toLowerCase() === "true";
return fallback;
}
function hideWidgetForGood(node, widget, suffix = "") {
if (!widget) return;
widget.origType = widget.origType ?? widget.type;
widget.origComputeSize = widget.origComputeSize ?? widget.computeSize;
widget.origSerializeValue ?? (widget.origSerializeValue = widget.serializeValue);
widget.origHidden ?? (widget.origHidden = widget.hidden);
widget.hidden = true;
widget.visible = false;
widget.last_y = -4096;
widget.draw = () => {
};
widget.serialize = true;
widget.serializeValue = function() {
const original = widget.origSerializeValue;
if (typeof original === "function") {
try {
return original.call(widget);
} catch {
}
}
return widget.value;
};
try {
widget.options = {
...widget.options ?? {},
hidden: true,
canvasOnly: true,
serialize: true
};
} catch {
}
widget.computeSize = () => [0, -4];
const element = widget.element;
if (element) {
element.hidden = true;
element.style.display = "none";
}
if (widget.linkedWidgets) {
for (const linked of widget.linkedWidgets) {
hideWidgetForGood(node, linked, `:${widget.name}${suffix}`);
}
}
}
function hideWidgetsByName(node, name) {
if (!node?.widgets) return;
for (const widget of node.widgets) {
if (widget?.name && widget.name.toLowerCase() === name.toLowerCase()) {
hideWidgetForGood(node, widget);
}
}
}
function deduplicateColorWidgets(node) {
if (!node?.widgets) return;
const seen = /* @__PURE__ */ new Set();
for (const widget of node.widgets) {
if (!widget?.name) continue;
if (seen.has(widget.name)) {
hideWidgetForGood(node, widget);
} else {
seen.add(widget.name);
}
}
}
function setWidgetValue(widget, value, options = {}) {
if (!widget) return;
const notify = options.notify !== false;
const dirty = options.dirty !== false;
const changed = Number(widget.value) !== Number(value);
widget.value = value;
syncWidgetElement(widget, value);
if (changed) {
if (notify) notifyWidgetChanged(widget, value);
if (dirty) markCanvasDirty();
}
}
function setWidgetStringValue(widget, value, options = {}) {
if (!widget) return;
const notify = options.notify !== false;
const dirty = options.dirty !== false;
const changed = String(widget.value ?? "") !== String(value);
widget.value = value;
syncWidgetElement(widget, value);
if (changed) {
if (notify) notifyWidgetChanged(widget, value);
if (dirty) markCanvasDirty();
}
}
function setWidgetStringValuesByName(node, name, value, options = {}) {
for (const widget of node.widgets ?? []) {
if (widget?.name === name) setWidgetStringValue(widget, value, options);
}
}
function setWidgetBooleanValue(widget, value, options = {}) {
if (!widget) return;
const notify = options.notify !== false;
const dirty = options.dirty !== false;
const current = typeof widget.value === "boolean" ? widget.value : String(widget.value ?? "false").toLowerCase() === "true";
const changed = current !== value;
widget.value = value;
syncWidgetElement(widget, value);
if (changed) {
if (notify) notifyWidgetChanged(widget, value);
if (dirty) markCanvasDirty();
}
}
function setWidgetMixedValue(widget, value, options = {}) {
if (!widget) return;
const notify = options.notify !== false;
const dirty = options.dirty !== false;
const changed = typeof value === "number" ? Number(widget.value) !== Number(value) : typeof value === "boolean" ? (typeof widget.value === "boolean" ? widget.value : String(widget.value ?? "false").toLowerCase() === "true") !== value : String(widget.value ?? "") !== String(value);
widget.value = value;
syncWidgetElement(widget, value);
if (changed) {
if (notify) notifyWidgetChanged(widget, value);
if (dirty) markCanvasDirty();
}
}
function getWidgetInputSpec(node, name) {
const nodeData = node?.constructor?.nodeData;
const entry = nodeData?.input?.required?.[name] ?? nodeData?.input?.optional?.[name];
if (!Array.isArray(entry) || entry.length === 0) return null;
const options = entry[1];
return {
typeSpec: entry[0],
options: options && typeof options === "object" ? options : null
};
}
function isWidgetHidden(widget) {
if (!widget) return true;
if (widget.hidden === true) return true;
return Boolean(widget.options?.hidden);
}
function isCompNode(node) {
return String(node?.comfyClass ?? "") === "ImageOpsComp";
}
function shouldUseCompactIntWidget(node) {
return isFrameRangeNode(node) || isAppendNode(node) || isCompNode(node) || isImageOpsNativeUiClass(node.comfyClass);
}
function supportsCompactUi(node, widget) {
if (!widget?.name || widget.name === "preview" || isWidgetHidden(widget)) return false;
const spec = getWidgetInputSpec(node, widget.name);
if (!spec) return false;
if (Array.isArray(spec.typeSpec)) return true;
const kind = String(spec.typeSpec ?? "").trim().toUpperCase();
if (kind === "INT" && !shouldUseCompactIntWidget(node)) return false;
return kind === "BOOLEAN" || kind === "INT" || kind === "FLOAT" || kind === "STRING" || kind === "COLOR" || kind === "COMBO";
}
function listCompactUiWidgets(node) {
return (node?.widgets ?? []).filter((widget) => supportsCompactUi(node, widget));
}
function hideCompactUiWidgets(node) {
}
function cloneDefaultValue(value) {
if (value == null || typeof value !== "object") return value;
try {
return structuredClone(value);
} catch {
return JSON.parse(JSON.stringify(value));
}
}
function getWidgetDefaultValue(node, name) {
const nodeData = node?.constructor?.nodeData;
const entry = nodeData?.input?.required?.[name] ?? nodeData?.input?.optional?.[name];
if (!Array.isArray(entry)) return void 0;
const options = entry[1];
return options && typeof options === "object" ? cloneDefaultValue(options.default) : void 0;
}
function resetNodeWidgetsToDefaults(node) {
const resetNames = [];
for (const widget of node?.widgets ?? []) {
const name = widget?.name;
if (!name) continue;
const defaultValue = getWidgetDefaultValue(node, name);
if (defaultValue === void 0) continue;
if (typeof defaultValue === "boolean") {
setWidgetBooleanValue(widget, defaultValue);
} else if (typeof defaultValue === "number") {
setWidgetValue(widget, defaultValue);
} else if (typeof defaultValue === "string") {
setWidgetStringValue(widget, defaultValue);
} else {
widget.value = cloneDefaultValue(defaultValue);
}
resetNames.push(name);
}
return resetNames;
}
export {
deduplicateColorWidgets,
findWidget,
getWidgetDefaultValue,
getWidgetInputSpec,
hideCompactUiWidgets,
hideWidgetForGood,
hideWidgetsByName,
listCompactUiWidgets,
resetNodeWidgetsToDefaults,
setWidgetBooleanValue,
setWidgetMixedValue,
setWidgetStringValue,
setWidgetStringValuesByName,
setWidgetValue,
widgetBoolean,
widgetNumber,
widgetString
};