Strip stray BOM/hidden characters from multiple Python and web source files to normalize file encoding and avoid lint/parse issues. Also bump package version from 1.8.2 to 1.8.3 in pyproject.toml. No functional code changes were made.
218 lines
6.5 KiB
JavaScript
218 lines
6.5 KiB
JavaScript
import { app } from "../../scripts/app.js";
|
|
import { ComfyWidgets } from "../../scripts/widgets.js";
|
|
import { defineProperty, moveArrayItem } from "./mxd_shared_utils.js";
|
|
|
|
export class MxdBaseNode extends LGraphNode {
|
|
static title = "__NEED_CLASS_TITLE__";
|
|
static type = "__NEED_CLASS_TYPE__";
|
|
static category = "mxd";
|
|
static _category = "mxd";
|
|
static exposedActions = [];
|
|
|
|
constructor(title = MxdBaseNode.title) {
|
|
super(title);
|
|
this.comfyClass = "__NEED_COMFY_CLASS__";
|
|
this.isVirtualNode = false;
|
|
this.isDropEnabled = false;
|
|
this.removed = false;
|
|
this.configuring = false;
|
|
this._tempWidth = 0;
|
|
this.__constructed__ = false;
|
|
this.widgets = this.widgets || [];
|
|
this.properties = this.properties || {};
|
|
|
|
defineProperty(this, "mode", {
|
|
get: () => this._mxd_mode,
|
|
set: (mode) => {
|
|
if (this._mxd_mode !== mode) {
|
|
const oldMode = this._mxd_mode;
|
|
this._mxd_mode = mode;
|
|
this.onModeChange(oldMode, mode);
|
|
}
|
|
},
|
|
});
|
|
|
|
setTimeout(() => this.checkAndRunOnConstructed());
|
|
}
|
|
|
|
checkAndRunOnConstructed() {
|
|
if (!this.__constructed__) {
|
|
this.onConstructed();
|
|
}
|
|
return this.__constructed__;
|
|
}
|
|
|
|
onConstructed() {
|
|
if (this.__constructed__) return false;
|
|
this.type = this.type ?? undefined;
|
|
this.__constructed__ = true;
|
|
return true;
|
|
}
|
|
|
|
configure(info) {
|
|
this.configuring = true;
|
|
super.configure(info);
|
|
for (const w of this.widgets || []) {
|
|
w.last_y = w.last_y || 0;
|
|
}
|
|
this.configuring = false;
|
|
}
|
|
|
|
clone() {
|
|
const cloned = super.clone();
|
|
if (cloned?.properties && window.structuredClone) {
|
|
cloned.properties = structuredClone(cloned.properties);
|
|
}
|
|
return cloned;
|
|
}
|
|
|
|
onModeChange(from, to) {}
|
|
|
|
removeWidget(widget) {
|
|
if (typeof widget === "number") {
|
|
widget = this.widgets[widget];
|
|
}
|
|
if (!widget) return;
|
|
const index = this.widgets.indexOf(widget);
|
|
if (index > -1) {
|
|
this.widgets.splice(index, 1);
|
|
}
|
|
widget.onRemove?.();
|
|
}
|
|
|
|
replaceWidget(widgetOrSlot, newWidget) {
|
|
let index = null;
|
|
if (widgetOrSlot != null) {
|
|
index = typeof widgetOrSlot === "number" ? widgetOrSlot : this.widgets.indexOf(widgetOrSlot);
|
|
this.removeWidget(this.widgets[index]);
|
|
}
|
|
index = index != null ? index : this.widgets.length - 1;
|
|
if (this.widgets.includes(newWidget)) {
|
|
moveArrayItem(this.widgets, newWidget, index);
|
|
} else {
|
|
this.widgets.splice(index, 0, newWidget);
|
|
}
|
|
}
|
|
|
|
defaultGetSlotMenuOptions(slot) {
|
|
const menuInfo = [];
|
|
if (slot?.output?.links?.length) {
|
|
menuInfo.push({ content: "Disconnect Links", slot });
|
|
}
|
|
const inputOrOutput = slot.input || slot.output;
|
|
if (inputOrOutput) {
|
|
if (inputOrOutput.removable) {
|
|
menuInfo.push(inputOrOutput.locked ? { content: "Cannot remove" } : { content: "Remove Slot", slot });
|
|
}
|
|
if (!inputOrOutput.nameLocked) {
|
|
menuInfo.push({ content: "Rename Slot", slot });
|
|
}
|
|
}
|
|
return menuInfo;
|
|
}
|
|
|
|
onRemoved() {
|
|
super.onRemoved?.();
|
|
this.removed = true;
|
|
}
|
|
|
|
static setUp() {}
|
|
}
|
|
|
|
export class MxdBaseServerNode extends MxdBaseNode {
|
|
static nodeType = null;
|
|
static nodeData = null;
|
|
static __registeredForOverride__ = false;
|
|
|
|
constructor(title) {
|
|
super(title);
|
|
this.isDropEnabled = true;
|
|
this.serialize_widgets = true;
|
|
this.setupFromServerNodeData();
|
|
this.onConstructed();
|
|
}
|
|
|
|
getWidgets() {
|
|
return ComfyWidgets;
|
|
}
|
|
|
|
async setupFromServerNodeData() {
|
|
const nodeData = this.constructor.nodeData;
|
|
if (!nodeData) throw Error("No node data");
|
|
|
|
this.comfyClass = nodeData.name;
|
|
let inputs = nodeData.input.required;
|
|
if (nodeData.input.optional != undefined) {
|
|
inputs = Object.assign({}, inputs, nodeData.input.optional);
|
|
}
|
|
|
|
const WIDGETS = this.getWidgets();
|
|
const config = { minWidth: 1, minHeight: 1, widget: null };
|
|
|
|
for (const inputName in inputs) {
|
|
const inputData = inputs[inputName];
|
|
const type = inputData[0];
|
|
if (inputData[1]?.forceInput) {
|
|
this.addInput(inputName, type);
|
|
} else {
|
|
let widgetCreated = true;
|
|
if (Array.isArray(type)) {
|
|
Object.assign(config, WIDGETS.COMBO(this, inputName, inputData, app) || {});
|
|
} else if (`${type}:${inputName}` in WIDGETS) {
|
|
Object.assign(config, WIDGETS[`${type}:${inputName}`](this, inputName, inputData, app) || {});
|
|
} else if (type in WIDGETS) {
|
|
Object.assign(config, WIDGETS[type](this, inputName, inputData, app) || {});
|
|
} else {
|
|
this.addInput(inputName, type);
|
|
widgetCreated = false;
|
|
}
|
|
|
|
if (widgetCreated && inputData[1]?.forceInput && config?.widget) {
|
|
if (!config.widget.options) config.widget.options = {};
|
|
config.widget.options.forceInput = inputData[1].forceInput;
|
|
}
|
|
if (widgetCreated && inputData[1]?.defaultInput && config?.widget) {
|
|
if (!config.widget.options) config.widget.options = {};
|
|
config.widget.options.defaultInput = inputData[1].defaultInput;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (const o in nodeData.output) {
|
|
let output = nodeData.output[o];
|
|
if (output instanceof Array) output = "COMBO";
|
|
const outputName = nodeData.output_name[o] || output;
|
|
const outputShape = nodeData.output_is_list[o] ? LiteGraph.GRID_SHAPE : LiteGraph.CIRCLE_SHAPE;
|
|
this.addOutput(outputName, output, { shape: outputShape });
|
|
}
|
|
|
|
const s = this.computeSize();
|
|
s[0] = Math.max(config.minWidth ?? 1, s[0] * 1.5);
|
|
s[1] = Math.max(config.minHeight ?? 1, s[1]);
|
|
this.size = s;
|
|
this.serialize_widgets = true;
|
|
}
|
|
|
|
static registerForOverride(comfyClass, nodeData, mxdClass) {
|
|
if (OVERRIDDEN_SERVER_NODES.has(comfyClass)) {
|
|
throw Error(`Already have a class to override ${comfyClass.type || comfyClass.name || comfyClass.title}`);
|
|
}
|
|
OVERRIDDEN_SERVER_NODES.set(comfyClass, mxdClass);
|
|
if (!mxdClass.__registeredForOverride__) {
|
|
mxdClass.__registeredForOverride__ = true;
|
|
mxdClass.nodeType = comfyClass;
|
|
mxdClass.nodeData = nodeData;
|
|
mxdClass.onRegisteredForOverride(comfyClass, mxdClass);
|
|
}
|
|
}
|
|
|
|
static onRegisteredForOverride(comfyClass, mxdClass) {}
|
|
}
|
|
|
|
const OVERRIDDEN_SERVER_NODES = new Map();
|
|
const oldRegisterNodeType = LiteGraph.registerNodeType;
|
|
LiteGraph.registerNodeType = async function (nodeId, baseClass) {
|
|
const clazz = OVERRIDDEN_SERVER_NODES.get(baseClass) || baseClass;
|
|
return oldRegisterNodeType.call(LiteGraph, nodeId, clazz);
|
|
};
|