mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-02-10 13:32:36 +08:00
Initial changes for litegraph.ts compat
This commit is contained in:
parent
d7b3b0f8c1
commit
c13f148df9
@ -1,5 +1,6 @@
|
||||
import {app} from "../../scripts/app.js";
|
||||
import {$el} from "../../scripts/ui.js";
|
||||
import { LiteGraph, LGraphCanvas } from "../../lib/litegraph.core.js"
|
||||
|
||||
// Manage color palettes
|
||||
|
||||
@ -341,8 +342,8 @@ app.registerExtension({
|
||||
if (colorPalette.colors) {
|
||||
// Sets the colors of node slots and links
|
||||
if (colorPalette.colors.node_slot) {
|
||||
Object.assign(app.canvas.default_connection_color_byType, colorPalette.colors.node_slot);
|
||||
Object.assign(LGraphCanvas.link_type_colors, colorPalette.colors.node_slot);
|
||||
Object.assign(LGraphCanvas.DEFAULT_CONNECTION_COLORS_BY_TYPE, colorPalette.colors.node_slot);
|
||||
Object.assign(app.canvas.link_type_colors, colorPalette.colors.node_slot);
|
||||
}
|
||||
// Sets the colors of the LiteGraph objects
|
||||
if (colorPalette.colors.litegraph_base) {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import {app} from "../../scripts/app.js";
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { LiteGraph } from "../../lib/litegraph.core.js"
|
||||
|
||||
// Adds filtering to combo context menus
|
||||
|
||||
@ -141,7 +142,7 @@ const ext = {
|
||||
return ctx;
|
||||
};
|
||||
|
||||
LiteGraph.ContextMenu.prototype = ctxMenu.prototype;
|
||||
// LiteGraph.ContextMenu.prototype = ctxMenu.prototype;
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { LiteGraph } from "../../lib/litegraph.core.js"
|
||||
|
||||
// Inverts the scrolling of context menus
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { LiteGraph, LINK_RENDER_MODE_NAMES } from "../../lib/litegraph.core.js"
|
||||
|
||||
const id = "Comfy.LinkRenderMode";
|
||||
const ext = {
|
||||
@ -9,7 +10,7 @@ const ext = {
|
||||
name: "Link Render Mode",
|
||||
defaultValue: 2,
|
||||
type: "combo",
|
||||
options: LiteGraph.LINK_RENDER_MODES.map((m, i) => ({
|
||||
options: LINK_RENDER_MODE_NAMES.map((m, i) => ({
|
||||
value: i,
|
||||
text: m,
|
||||
selected: i == app.canvas.links_render_mode,
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { ComfyDialog, $el } from "../../scripts/ui.js";
|
||||
import { LGraphCanvas } from "../../lib/litegraph.core.js"
|
||||
|
||||
// Adds the ability to save and add multiple nodes as a template
|
||||
// To save:
|
||||
|
||||
@ -1,11 +1,14 @@
|
||||
import {app} from "../../scripts/app.js";
|
||||
import {ComfyWidgets} from "../../scripts/widgets.js";
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { ComfyWidgets } from "../../scripts/widgets.js";
|
||||
import { ComfyGraphNode } from "../../scripts/graphNode.js";
|
||||
import { LiteGraph } from "../../lib/litegraph.core.js"
|
||||
|
||||
// Node that add notes to your project
|
||||
|
||||
app.registerExtension({
|
||||
name: "Comfy.NoteNode",
|
||||
registerCustomNodes() {
|
||||
class NoteNode {
|
||||
class NoteNode extends ComfyGraphNode {
|
||||
color=LGraphCanvas.node_colors.yellow.color;
|
||||
bgcolor=LGraphCanvas.node_colors.yellow.bgcolor;
|
||||
groupcolor = LGraphCanvas.node_colors.yellow.groupcolor;
|
||||
@ -19,22 +22,18 @@ app.registerExtension({
|
||||
|
||||
this.serialize_widgets = true;
|
||||
this.isVirtualNode = true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Load default visibility
|
||||
|
||||
LiteGraph.registerNodeType(
|
||||
"Note",
|
||||
Object.assign(NoteNode, {
|
||||
title_mode: LiteGraph.NORMAL_TITLE,
|
||||
title: "Note",
|
||||
collapsable: true,
|
||||
})
|
||||
);
|
||||
LiteGraph.registerNodeType({
|
||||
class: NoteNode,
|
||||
title_mode: LiteGraph.NORMAL_TITLE,
|
||||
type: "Note",
|
||||
title: "Note",
|
||||
collapsable: true,
|
||||
});
|
||||
|
||||
NoteNode.category = "utils";
|
||||
},
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { ComfyGraphNode } from "../../scripts/graphNode.js";
|
||||
import { LiteGraph } from "../../lib/litegraph.core.js"
|
||||
|
||||
// Node that allows you to redirect connections for cleaner graphs
|
||||
|
||||
app.registerExtension({
|
||||
name: "Comfy.RerouteNode",
|
||||
registerCustomNodes() {
|
||||
class RerouteNode {
|
||||
class RerouteNode extends ComfyGraphNode {
|
||||
constructor() {
|
||||
if (!this.properties) {
|
||||
this.properties = {};
|
||||
@ -109,7 +111,7 @@ app.registerExtension({
|
||||
}
|
||||
|
||||
const displayType = inputType || outputType || "*";
|
||||
const color = LGraphCanvas.link_type_colors[displayType];
|
||||
const color = app.canvas.link_type_colors[displayType];
|
||||
|
||||
// Update the types of each node
|
||||
for (const node of updateNodes) {
|
||||
@ -219,14 +221,13 @@ app.registerExtension({
|
||||
// Load default visibility
|
||||
RerouteNode.setDefaultTextVisibility(!!localStorage["Comfy.RerouteNode.DefaultVisibility"]);
|
||||
|
||||
LiteGraph.registerNodeType(
|
||||
"Reroute",
|
||||
Object.assign(RerouteNode, {
|
||||
title_mode: LiteGraph.NO_TITLE,
|
||||
title: "Reroute",
|
||||
collapsable: false,
|
||||
})
|
||||
);
|
||||
LiteGraph.registerNodeType({
|
||||
class: RerouteNode,
|
||||
title_mode: LiteGraph.NO_TITLE,
|
||||
type: "Reroute",
|
||||
title: "Reroute",
|
||||
collapsable: false,
|
||||
});
|
||||
|
||||
RerouteNode.category = "utils";
|
||||
},
|
||||
|
||||
@ -2,6 +2,7 @@ import { app } from "../../scripts/app.js";
|
||||
|
||||
// Use widget values and dates in output filenames
|
||||
|
||||
/*
|
||||
app.registerExtension({
|
||||
name: "Comfy.SaveImageExtraOutput",
|
||||
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
||||
@ -98,3 +99,4 @@ app.registerExtension({
|
||||
}
|
||||
},
|
||||
});
|
||||
*/
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { ComfyWidgets } from "../../scripts/widgets.js";
|
||||
import { LiteGraph } from "../../lib/litegraph.core.js"
|
||||
|
||||
// Adds defaults for quickly adding nodes with middle click on the input/output
|
||||
|
||||
app.registerExtension({
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { LiteGraph } from "../../lib/litegraph.core.js"
|
||||
|
||||
// Shift + drag/resize to snap to grid
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { ComfyWidgets, addValueControlWidget } from "../../scripts/widgets.js";
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { LiteGraph } from "../../lib/litegraph.core.js"
|
||||
|
||||
const CONVERTED_TYPE = "converted-widget";
|
||||
const VALID_TYPES = ["STRING", "combo", "number", "BOOLEAN"];
|
||||
@ -95,8 +96,8 @@ app.registerExtension({
|
||||
name: "Comfy.WidgetInputs",
|
||||
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
||||
// Add menu options to conver to/from widgets
|
||||
const origGetExtraMenuOptions = nodeType.prototype.getExtraMenuOptions;
|
||||
nodeType.prototype.getExtraMenuOptions = function (_, options) {
|
||||
const origGetExtraMenuOptions = nodeType.class.prototype.getExtraMenuOptions;
|
||||
nodeType.class.prototype.getExtraMenuOptions = function (_, options) {
|
||||
const r = origGetExtraMenuOptions ? origGetExtraMenuOptions.apply(this, arguments) : undefined;
|
||||
|
||||
if (this.widgets) {
|
||||
@ -131,8 +132,8 @@ app.registerExtension({
|
||||
};
|
||||
|
||||
// On initial configure of nodes hide all converted widgets
|
||||
const origOnConfigure = nodeType.prototype.onConfigure;
|
||||
nodeType.prototype.onConfigure = function () {
|
||||
const origOnConfigure = nodeType.class.prototype.onConfigure;
|
||||
nodeType.class.prototype.onConfigure = function () {
|
||||
const r = origOnConfigure ? origOnConfigure.apply(this, arguments) : undefined;
|
||||
|
||||
if (this.inputs) {
|
||||
@ -161,9 +162,9 @@ app.registerExtension({
|
||||
}
|
||||
|
||||
// Double click a widget input to automatically attach a primitive
|
||||
const origOnInputDblClick = nodeType.prototype.onInputDblClick;
|
||||
const origOnInputDblClick = nodeType.class.prototype.onInputDblClick;
|
||||
const ignoreDblClick = Symbol();
|
||||
nodeType.prototype.onInputDblClick = function (slot) {
|
||||
nodeType.class.prototype.onInputDblClick = function (slot) {
|
||||
const r = origOnInputDblClick ? origOnInputDblClick.apply(this, arguments) : undefined;
|
||||
|
||||
const input = this.inputs[slot];
|
||||
@ -403,12 +404,11 @@ app.registerExtension({
|
||||
}
|
||||
}
|
||||
|
||||
LiteGraph.registerNodeType(
|
||||
"PrimitiveNode",
|
||||
Object.assign(PrimitiveNode, {
|
||||
title: "Primitive",
|
||||
})
|
||||
);
|
||||
LiteGraph.registerNodeType({
|
||||
class: PrimitiveNode,
|
||||
type: "PrimitiveNode",
|
||||
title: "Primitive",
|
||||
});
|
||||
PrimitiveNode.category = "utils";
|
||||
},
|
||||
});
|
||||
|
||||
@ -7,12 +7,10 @@
|
||||
<link rel="stylesheet" type="text/css" href="./lib/litegraph.css" />
|
||||
<link rel="stylesheet" type="text/css" href="./style.css" />
|
||||
<link rel="stylesheet" type="text/css" href="./user.css" />
|
||||
<script type="text/javascript" src="./lib/litegraph.core.js"></script>
|
||||
<script type="text/javascript" src="./lib/litegraph.extensions.js" defer></script>
|
||||
<script type="module">
|
||||
import { app } from "./scripts/app.js";
|
||||
await app.setup();
|
||||
window.app = app;
|
||||
await app.setup();
|
||||
window.graph = app.graph;
|
||||
</script>
|
||||
</head>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,21 +0,0 @@
|
||||
/**
|
||||
* Changes the background color of the canvas.
|
||||
*
|
||||
* @method updateBackground
|
||||
* @param {image} String
|
||||
* @param {clearBackgroundColor} String
|
||||
* @
|
||||
*/
|
||||
LGraphCanvas.prototype.updateBackground = function (image, clearBackgroundColor) {
|
||||
this._bg_img = new Image();
|
||||
this._bg_img.name = image;
|
||||
this._bg_img.src = image;
|
||||
this._bg_img.onload = () => {
|
||||
this.draw(true, true);
|
||||
};
|
||||
this.background_image = image;
|
||||
|
||||
this.clear_background = true;
|
||||
this.clear_background_color = clearBackgroundColor;
|
||||
this._pattern = null
|
||||
}
|
||||
@ -4,6 +4,10 @@ import { ComfyUI, $el } from "./ui.js";
|
||||
import { api } from "./api.js";
|
||||
import { defaultGraph } from "./defaultGraph.js";
|
||||
import { getPngMetadata, importA1111, getLatentMetadata } from "./pnginfo.js";
|
||||
import { LiteGraph } from "../lib/litegraph.core.js"
|
||||
import ComfyGraph from "./graph.js";
|
||||
import ComfyGraphCanvas from "./graphCanvas.js";
|
||||
import { ComfyBackendNode } from "./graphNode.js";
|
||||
|
||||
/**
|
||||
* @typedef {import("types/comfy").ComfyExtension} ComfyExtension
|
||||
@ -690,270 +694,6 @@ export class ComfyApp {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle mouse
|
||||
*
|
||||
* Move group by header
|
||||
*/
|
||||
#addProcessMouseHandler() {
|
||||
const self = this;
|
||||
|
||||
const origProcessMouseDown = LGraphCanvas.prototype.processMouseDown;
|
||||
LGraphCanvas.prototype.processMouseDown = function(e) {
|
||||
const res = origProcessMouseDown.apply(this, arguments);
|
||||
|
||||
this.selected_group_moving = false;
|
||||
|
||||
if (this.selected_group && !this.selected_group_resizing) {
|
||||
var font_size =
|
||||
this.selected_group.font_size || LiteGraph.DEFAULT_GROUP_FONT_SIZE;
|
||||
var height = font_size * 1.4;
|
||||
|
||||
// Move group by header
|
||||
if (LiteGraph.isInsideRectangle(e.canvasX, e.canvasY, this.selected_group.pos[0], this.selected_group.pos[1], this.selected_group.size[0], height)) {
|
||||
this.selected_group_moving = true;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
const origProcessMouseMove = LGraphCanvas.prototype.processMouseMove;
|
||||
LGraphCanvas.prototype.processMouseMove = function(e) {
|
||||
const orig_selected_group = this.selected_group;
|
||||
|
||||
if (this.selected_group && !this.selected_group_resizing && !this.selected_group_moving) {
|
||||
this.selected_group = null;
|
||||
}
|
||||
|
||||
const res = origProcessMouseMove.apply(this, arguments);
|
||||
|
||||
if (orig_selected_group && !this.selected_group_resizing && !this.selected_group_moving) {
|
||||
this.selected_group = orig_selected_group;
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle keypress
|
||||
*
|
||||
* Ctrl + M mute/unmute selected nodes
|
||||
*/
|
||||
#addProcessKeyHandler() {
|
||||
const self = this;
|
||||
const origProcessKey = LGraphCanvas.prototype.processKey;
|
||||
LGraphCanvas.prototype.processKey = function(e) {
|
||||
const res = origProcessKey.apply(this, arguments);
|
||||
|
||||
if (res === false) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (!this.graph) {
|
||||
return;
|
||||
}
|
||||
|
||||
var block_default = false;
|
||||
|
||||
if (e.target.localName == "input") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.type == "keydown") {
|
||||
// Ctrl + M mute/unmute
|
||||
if (e.keyCode == 77 && e.ctrlKey) {
|
||||
if (this.selected_nodes) {
|
||||
for (var i in this.selected_nodes) {
|
||||
if (this.selected_nodes[i].mode === 2) { // never
|
||||
this.selected_nodes[i].mode = 0; // always
|
||||
} else {
|
||||
this.selected_nodes[i].mode = 2; // never
|
||||
}
|
||||
}
|
||||
}
|
||||
block_default = true;
|
||||
}
|
||||
|
||||
if (e.keyCode == 66 && e.ctrlKey) {
|
||||
if (this.selected_nodes) {
|
||||
for (var i in this.selected_nodes) {
|
||||
if (this.selected_nodes[i].mode === 4) { // never
|
||||
this.selected_nodes[i].mode = 0; // always
|
||||
} else {
|
||||
this.selected_nodes[i].mode = 4; // never
|
||||
}
|
||||
}
|
||||
}
|
||||
block_default = true;
|
||||
}
|
||||
}
|
||||
|
||||
this.graph.change();
|
||||
|
||||
if (block_default) {
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
return false;
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws group header bar
|
||||
*/
|
||||
#addDrawGroupsHandler() {
|
||||
const self = this;
|
||||
|
||||
const origDrawGroups = LGraphCanvas.prototype.drawGroups;
|
||||
LGraphCanvas.prototype.drawGroups = function(canvas, ctx) {
|
||||
if (!this.graph) {
|
||||
return;
|
||||
}
|
||||
|
||||
var groups = this.graph._groups;
|
||||
|
||||
ctx.save();
|
||||
ctx.globalAlpha = 0.7 * this.editor_alpha;
|
||||
|
||||
for (var i = 0; i < groups.length; ++i) {
|
||||
var group = groups[i];
|
||||
|
||||
if (!LiteGraph.overlapBounding(this.visible_area, group._bounding)) {
|
||||
continue;
|
||||
} //out of the visible area
|
||||
|
||||
ctx.fillStyle = group.color || "#335";
|
||||
ctx.strokeStyle = group.color || "#335";
|
||||
var pos = group._pos;
|
||||
var size = group._size;
|
||||
ctx.globalAlpha = 0.25 * this.editor_alpha;
|
||||
ctx.beginPath();
|
||||
var font_size =
|
||||
group.font_size || LiteGraph.DEFAULT_GROUP_FONT_SIZE;
|
||||
ctx.rect(pos[0] + 0.5, pos[1] + 0.5, size[0], font_size * 1.4);
|
||||
ctx.fill();
|
||||
ctx.globalAlpha = this.editor_alpha;
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
|
||||
const res = origDrawGroups.apply(this, arguments);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws node highlights (executing, drag drop) and progress bar
|
||||
*/
|
||||
#addDrawNodeHandler() {
|
||||
const origDrawNodeShape = LGraphCanvas.prototype.drawNodeShape;
|
||||
const self = this;
|
||||
|
||||
LGraphCanvas.prototype.drawNodeShape = function (node, ctx, size, fgcolor, bgcolor, selected, mouse_over) {
|
||||
const res = origDrawNodeShape.apply(this, arguments);
|
||||
|
||||
const nodeErrors = self.lastNodeErrors?.[node.id];
|
||||
|
||||
let color = null;
|
||||
let lineWidth = 1;
|
||||
if (node.id === +self.runningNodeId) {
|
||||
color = "#0f0";
|
||||
} else if (self.dragOverNode && node.id === self.dragOverNode.id) {
|
||||
color = "dodgerblue";
|
||||
}
|
||||
else if (nodeErrors?.errors) {
|
||||
color = "red";
|
||||
lineWidth = 2;
|
||||
}
|
||||
else if (self.lastExecutionError && +self.lastExecutionError.node_id === node.id) {
|
||||
color = "#f0f";
|
||||
lineWidth = 2;
|
||||
}
|
||||
|
||||
if (color) {
|
||||
const shape = node._shape || node.constructor.shape || LiteGraph.ROUND_SHAPE;
|
||||
ctx.lineWidth = lineWidth;
|
||||
ctx.globalAlpha = 0.8;
|
||||
ctx.beginPath();
|
||||
if (shape == LiteGraph.BOX_SHAPE)
|
||||
ctx.rect(-6, -6 - LiteGraph.NODE_TITLE_HEIGHT, 12 + size[0] + 1, 12 + size[1] + LiteGraph.NODE_TITLE_HEIGHT);
|
||||
else if (shape == LiteGraph.ROUND_SHAPE || (shape == LiteGraph.CARD_SHAPE && node.flags.collapsed))
|
||||
ctx.roundRect(
|
||||
-6,
|
||||
-6 - LiteGraph.NODE_TITLE_HEIGHT,
|
||||
12 + size[0] + 1,
|
||||
12 + size[1] + LiteGraph.NODE_TITLE_HEIGHT,
|
||||
this.round_radius * 2
|
||||
);
|
||||
else if (shape == LiteGraph.CARD_SHAPE)
|
||||
ctx.roundRect(
|
||||
-6,
|
||||
-6 - LiteGraph.NODE_TITLE_HEIGHT,
|
||||
12 + size[0] + 1,
|
||||
12 + size[1] + LiteGraph.NODE_TITLE_HEIGHT,
|
||||
[this.round_radius * 2, this.round_radius * 2, 2, 2]
|
||||
);
|
||||
else if (shape == LiteGraph.CIRCLE_SHAPE)
|
||||
ctx.arc(size[0] * 0.5, size[1] * 0.5, size[0] * 0.5 + 6, 0, Math.PI * 2);
|
||||
ctx.strokeStyle = color;
|
||||
ctx.stroke();
|
||||
ctx.strokeStyle = fgcolor;
|
||||
ctx.globalAlpha = 1;
|
||||
}
|
||||
|
||||
if (self.progress && node.id === +self.runningNodeId) {
|
||||
ctx.fillStyle = "green";
|
||||
ctx.fillRect(0, 0, size[0] * (self.progress.value / self.progress.max), 6);
|
||||
ctx.fillStyle = bgcolor;
|
||||
}
|
||||
|
||||
// Highlight inputs that failed validation
|
||||
if (nodeErrors) {
|
||||
ctx.lineWidth = 2;
|
||||
ctx.strokeStyle = "red";
|
||||
for (const error of nodeErrors.errors) {
|
||||
if (error.extra_info && error.extra_info.input_name) {
|
||||
const inputIndex = node.findInputSlot(error.extra_info.input_name)
|
||||
if (inputIndex !== -1) {
|
||||
let pos = node.getConnectionPos(true, inputIndex);
|
||||
ctx.beginPath();
|
||||
ctx.arc(pos[0] - node.pos[0], pos[1] - node.pos[1], 12, 0, 2 * Math.PI, false)
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
const origDrawNode = LGraphCanvas.prototype.drawNode;
|
||||
LGraphCanvas.prototype.drawNode = function (node, ctx) {
|
||||
var editor_alpha = this.editor_alpha;
|
||||
var old_color = node.bgcolor;
|
||||
|
||||
if (node.mode === 2) { // never
|
||||
this.editor_alpha = 0.4;
|
||||
}
|
||||
|
||||
if (node.mode === 4) { // never
|
||||
node.bgcolor = "#FF00FF";
|
||||
this.editor_alpha = 0.2;
|
||||
}
|
||||
|
||||
const res = origDrawNode.apply(this, arguments);
|
||||
|
||||
this.editor_alpha = editor_alpha;
|
||||
node.bgcolor = old_color;
|
||||
|
||||
return res;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles updates from the API socket
|
||||
*/
|
||||
@ -1056,11 +796,8 @@ export class ComfyApp {
|
||||
canvasEl.tabIndex = "1";
|
||||
document.body.prepend(canvasEl);
|
||||
|
||||
this.#addProcessMouseHandler();
|
||||
this.#addProcessKeyHandler();
|
||||
|
||||
this.graph = new LGraph();
|
||||
const canvas = (this.canvas = new LGraphCanvas(canvasEl, this.graph));
|
||||
this.graph = new ComfyGraph();
|
||||
const canvas = (this.canvas = new ComfyGraphCanvas(canvasEl, this.graph));
|
||||
this.ctx = canvasEl.getContext("2d");
|
||||
|
||||
LiteGraph.release_link_on_empty_shows_menu = true;
|
||||
@ -1106,8 +843,6 @@ export class ComfyApp {
|
||||
// Save current workflow automatically
|
||||
setInterval(() => localStorage.setItem("workflow", JSON.stringify(this.graph.serialize())), 1000);
|
||||
|
||||
this.#addDrawNodeHandler();
|
||||
this.#addDrawGroupsHandler();
|
||||
this.#addApiUpdateHandlers();
|
||||
this.#addDropHandler();
|
||||
this.#addPasteHandler();
|
||||
@ -1130,74 +865,92 @@ export class ComfyApp {
|
||||
async registerNodesFromDefs(defs) {
|
||||
await this.#invokeExtensionsAsync("addCustomNodeDefs", defs);
|
||||
|
||||
// // Generate list of known widgets
|
||||
// const widgets = Object.assign(
|
||||
// {},
|
||||
// ComfyWidgets,
|
||||
// ...(await this.#invokeExtensionsAsync("getCustomWidgets")).filter(Boolean)
|
||||
// );
|
||||
|
||||
// Generate list of known widgets
|
||||
const widgets = Object.assign(
|
||||
{},
|
||||
ComfyWidgets,
|
||||
...(await this.#invokeExtensionsAsync("getCustomWidgets")).filter(Boolean)
|
||||
);
|
||||
const customWidgets = (await app.#invokeExtensionsAsync("getCustomWidgets")).filter(Boolean);
|
||||
ComfyWidgets.customWidgets = customWidgets;
|
||||
|
||||
// Register a node for each definition
|
||||
for (const nodeId in defs) {
|
||||
const nodeData = defs[nodeId];
|
||||
const node = Object.assign(
|
||||
function ComfyNode() {
|
||||
var inputs = nodeData["input"]["required"];
|
||||
if (nodeData["input"]["optional"] != undefined){
|
||||
inputs = Object.assign({}, nodeData["input"]["required"], nodeData["input"]["optional"])
|
||||
}
|
||||
const config = { minWidth: 1, minHeight: 1 };
|
||||
for (const inputName in inputs) {
|
||||
const inputData = inputs[inputName];
|
||||
const type = inputData[0];
|
||||
|
||||
if(inputData[1]?.forceInput) {
|
||||
this.addInput(inputName, type);
|
||||
} else {
|
||||
if (Array.isArray(type)) {
|
||||
// Enums
|
||||
Object.assign(config, widgets.COMBO(this, inputName, inputData, app) || {});
|
||||
} else if (`${type}:${inputName}` in widgets) {
|
||||
// Support custom widgets by Type:Name
|
||||
Object.assign(config, widgets[`${type}:${inputName}`](this, inputName, inputData, app) || {});
|
||||
} else if (type in widgets) {
|
||||
// Standard type widgets
|
||||
Object.assign(config, widgets[type](this, inputName, inputData, app) || {});
|
||||
} else {
|
||||
// Node connection inputs
|
||||
this.addInput(inputName, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
const ctor = class extends ComfyBackendNode {
|
||||
constructor(title) {
|
||||
super(title, nodeId, nodeData);
|
||||
}
|
||||
}
|
||||
|
||||
for (const o in nodeData["output"]) {
|
||||
const output = nodeData["output"][o];
|
||||
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 node = {
|
||||
class: ctor,
|
||||
title: nodeData.display_name || nodeData.name,
|
||||
desc: `ComfyNode: ${nodeId}`
|
||||
}
|
||||
|
||||
const s = this.computeSize();
|
||||
s[0] = Math.max(config.minWidth, s[0] * 1.5);
|
||||
s[1] = Math.max(config.minHeight, s[1]);
|
||||
this.size = s;
|
||||
this.serialize_widgets = true;
|
||||
// const node = Object.assign(
|
||||
// function ComfyNode() {
|
||||
// var inputs = nodeData["input"]["required"];
|
||||
// if (nodeData["input"]["optional"] != undefined){
|
||||
// inputs = Object.assign({}, nodeData["input"]["required"], nodeData["input"]["optional"])
|
||||
// }
|
||||
// const config = { minWidth: 1, minHeight: 1 };
|
||||
// for (const inputName in inputs) {
|
||||
// const inputData = inputs[inputName];
|
||||
// const type = inputData[0];
|
||||
|
||||
app.#invokeExtensionsAsync("nodeCreated", this);
|
||||
},
|
||||
{
|
||||
title: nodeData.display_name || nodeData.name,
|
||||
comfyClass: nodeData.name,
|
||||
}
|
||||
);
|
||||
node.prototype.comfyClass = nodeData.name;
|
||||
// if(inputData[1]?.forceInput) {
|
||||
// this.addInput(inputName, type);
|
||||
// } else {
|
||||
// if (Array.isArray(type)) {
|
||||
// // Enums
|
||||
// Object.assign(config, widgets.COMBO(this, inputName, inputData, app) || {});
|
||||
// } else if (`${type}:${inputName}` in widgets) {
|
||||
// // Support custom widgets by Type:Name
|
||||
// Object.assign(config, widgets[`${type}:${inputName}`](this, inputName, inputData, app) || {});
|
||||
// } else if (type in widgets) {
|
||||
// // Standard type widgets
|
||||
// Object.assign(config, widgets[type](this, inputName, inputData, app) || {});
|
||||
// } else {
|
||||
// // Node connection inputs
|
||||
// this.addInput(inputName, type);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
this.#addNodeContextMenuHandler(node);
|
||||
this.#addDrawBackgroundHandler(node, app);
|
||||
this.#addNodeKeyHandler(node);
|
||||
// for (const o in nodeData["output"]) {
|
||||
// const output = nodeData["output"][o];
|
||||
// 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, s[0] * 1.5);
|
||||
// s[1] = Math.max(config.minHeight, s[1]);
|
||||
// this.size = s;
|
||||
// this.serialize_widgets = true;
|
||||
|
||||
// app.#invokeExtensionsAsync("nodeCreated", this);
|
||||
// },
|
||||
// {
|
||||
// title: nodeData.display_name || nodeData.name,
|
||||
// comfyClass: nodeData.name,
|
||||
// }
|
||||
// );
|
||||
// node.prototype.comfyClass = nodeData.name;
|
||||
node.type = nodeId;
|
||||
|
||||
// this.#addNodeContextMenuHandler(node);
|
||||
// this.#addDrawBackgroundHandler(node, app);
|
||||
// this.#addNodeKeyHandler(node);
|
||||
|
||||
await this.#invokeExtensionsAsync("beforeRegisterNodeDef", node, nodeData);
|
||||
LiteGraph.registerNodeType(nodeId, node);
|
||||
LiteGraph.registerNodeType(node);
|
||||
node.category = nodeData.category;
|
||||
}
|
||||
}
|
||||
|
||||
5
web/scripts/graph.js
Normal file
5
web/scripts/graph.js
Normal file
@ -0,0 +1,5 @@
|
||||
import { LGraph } from "../lib/litegraph.core.js"
|
||||
|
||||
export default class ComfyGraph extends LGraph {
|
||||
|
||||
}
|
||||
236
web/scripts/graphCanvas.js
Normal file
236
web/scripts/graphCanvas.js
Normal file
@ -0,0 +1,236 @@
|
||||
import { LGraphCanvas } from "../lib/litegraph.core.js"
|
||||
|
||||
export default class ComfyGraphCanvas extends LGraphCanvas {
|
||||
processKey(e) {
|
||||
const res = super.processKey(e);
|
||||
|
||||
if (res === false) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (!this.graph) {
|
||||
return;
|
||||
}
|
||||
|
||||
var block_default = false;
|
||||
|
||||
if (e.target.localName == "input") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.type == "keydown") {
|
||||
// Ctrl + M mute/unmute
|
||||
if (e.keyCode == 77 && e.ctrlKey) {
|
||||
if (this.selected_nodes) {
|
||||
for (var i in this.selected_nodes) {
|
||||
if (this.selected_nodes[i].mode === 2) { // never
|
||||
this.selected_nodes[i].mode = 0; // always
|
||||
} else {
|
||||
this.selected_nodes[i].mode = 2; // never
|
||||
}
|
||||
}
|
||||
}
|
||||
block_default = true;
|
||||
}
|
||||
|
||||
if (e.keyCode == 66 && e.ctrlKey) {
|
||||
if (this.selected_nodes) {
|
||||
for (var i in this.selected_nodes) {
|
||||
if (this.selected_nodes[i].mode === 4) { // never
|
||||
this.selected_nodes[i].mode = 0; // always
|
||||
} else {
|
||||
this.selected_nodes[i].mode = 4; // never
|
||||
}
|
||||
}
|
||||
}
|
||||
block_default = true;
|
||||
}
|
||||
}
|
||||
|
||||
this.graph.change();
|
||||
|
||||
if (block_default) {
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
return false;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
processMouseDown(e) {
|
||||
const res = super.processMouseDown(e);
|
||||
|
||||
this.selected_group_moving = false;
|
||||
|
||||
if (this.selected_group && !this.selected_group_resizing) {
|
||||
var font_size =
|
||||
this.selected_group.font_size || LiteGraph.DEFAULT_GROUP_FONT_SIZE;
|
||||
var height = font_size * 1.4;
|
||||
|
||||
// Move group by header
|
||||
if (LiteGraph.isInsideRectangle(e.canvasX, e.canvasY, this.selected_group.pos[0], this.selected_group.pos[1], this.selected_group.size[0], height)) {
|
||||
this.selected_group_moving = true;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
processMouseMove(e) {
|
||||
const orig_selected_group = this.selected_group;
|
||||
|
||||
if (this.selected_group && !this.selected_group_resizing && !this.selected_group_moving) {
|
||||
this.selected_group = null;
|
||||
}
|
||||
|
||||
const res = super.processMouseMove(e);
|
||||
|
||||
if (orig_selected_group && !this.selected_group_resizing && !this.selected_group_moving) {
|
||||
this.selected_group = orig_selected_group;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws group header bar
|
||||
*/
|
||||
drawGroups(canvas, ctx) {
|
||||
if (!this.graph) {
|
||||
return;
|
||||
}
|
||||
|
||||
var groups = this.graph._groups;
|
||||
|
||||
ctx.save();
|
||||
ctx.globalAlpha = 0.7 * this.editor_alpha;
|
||||
|
||||
for (var i = 0; i < groups.length; ++i) {
|
||||
var group = groups[i];
|
||||
|
||||
if (!LiteGraph.overlapBounding(this.visible_area, group._bounding)) {
|
||||
continue;
|
||||
} //out of the visible area
|
||||
|
||||
ctx.fillStyle = group.color || "#335";
|
||||
ctx.strokeStyle = group.color || "#335";
|
||||
var pos = group._pos;
|
||||
var size = group._size;
|
||||
ctx.globalAlpha = 0.25 * this.editor_alpha;
|
||||
ctx.beginPath();
|
||||
var font_size =
|
||||
group.font_size || LiteGraph.DEFAULT_GROUP_FONT_SIZE;
|
||||
ctx.rect(pos[0] + 0.5, pos[1] + 0.5, size[0], font_size * 1.4);
|
||||
ctx.fill();
|
||||
ctx.globalAlpha = this.editor_alpha;
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
|
||||
const res = super.drawGroups(canvas, ctx);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws node highlights (executing, drag drop) and progress bar
|
||||
*/
|
||||
drawNodeShape(node, ctx, size, fgcolor, bgcolor, selected, mouse_over) {
|
||||
const res = super.drawNodeShape(node, ctx, size, fgcolor, bgcolor, selected, mouse_over);
|
||||
|
||||
const nodeErrors = self.lastNodeErrors?.[node.id];
|
||||
|
||||
let color = null;
|
||||
let lineWidth = 1;
|
||||
if (node.id === +self.runningNodeId) {
|
||||
color = "#0f0";
|
||||
} else if (self.dragOverNode && node.id === self.dragOverNode.id) {
|
||||
color = "dodgerblue";
|
||||
}
|
||||
else if (nodeErrors?.errors) {
|
||||
color = "red";
|
||||
lineWidth = 2;
|
||||
}
|
||||
else if (self.lastExecutionError && +self.lastExecutionError.node_id === node.id) {
|
||||
color = "#f0f";
|
||||
lineWidth = 2;
|
||||
}
|
||||
|
||||
if (color) {
|
||||
const shape = node._shape || node.constructor.shape || LiteGraph.ROUND_SHAPE;
|
||||
ctx.lineWidth = lineWidth;
|
||||
ctx.globalAlpha = 0.8;
|
||||
ctx.beginPath();
|
||||
if (shape == LiteGraph.BOX_SHAPE)
|
||||
ctx.rect(-6, -6 - LiteGraph.NODE_TITLE_HEIGHT, 12 + size[0] + 1, 12 + size[1] + LiteGraph.NODE_TITLE_HEIGHT);
|
||||
else if (shape == LiteGraph.ROUND_SHAPE || (shape == LiteGraph.CARD_SHAPE && node.flags.collapsed))
|
||||
ctx.roundRect(
|
||||
-6,
|
||||
-6 - LiteGraph.NODE_TITLE_HEIGHT,
|
||||
12 + size[0] + 1,
|
||||
12 + size[1] + LiteGraph.NODE_TITLE_HEIGHT,
|
||||
this.round_radius * 2
|
||||
);
|
||||
else if (shape == LiteGraph.CARD_SHAPE)
|
||||
ctx.roundRect(
|
||||
-6,
|
||||
-6 - LiteGraph.NODE_TITLE_HEIGHT,
|
||||
12 + size[0] + 1,
|
||||
12 + size[1] + LiteGraph.NODE_TITLE_HEIGHT,
|
||||
[this.round_radius * 2, this.round_radius * 2, 2, 2]
|
||||
);
|
||||
else if (shape == LiteGraph.CIRCLE_SHAPE)
|
||||
ctx.arc(size[0] * 0.5, size[1] * 0.5, size[0] * 0.5 + 6, 0, Math.PI * 2);
|
||||
ctx.strokeStyle = color;
|
||||
ctx.stroke();
|
||||
ctx.strokeStyle = fgcolor;
|
||||
ctx.globalAlpha = 1;
|
||||
}
|
||||
|
||||
if (self.progress && node.id === +self.runningNodeId) {
|
||||
ctx.fillStyle = "green";
|
||||
ctx.fillRect(0, 0, size[0] * (self.progress.value / self.progress.max), 6);
|
||||
ctx.fillStyle = bgcolor;
|
||||
}
|
||||
|
||||
// Highlight inputs that failed validation
|
||||
if (nodeErrors) {
|
||||
ctx.lineWidth = 2;
|
||||
ctx.strokeStyle = "red";
|
||||
for (const error of nodeErrors.errors) {
|
||||
if (error.extra_info && error.extra_info.input_name) {
|
||||
const inputIndex = node.findInputSlot(error.extra_info.input_name)
|
||||
if (inputIndex !== -1) {
|
||||
let pos = node.getConnectionPos(true, inputIndex);
|
||||
ctx.beginPath();
|
||||
ctx.arc(pos[0] - node.pos[0], pos[1] - node.pos[1], 12, 0, 2 * Math.PI, false)
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
drawNode(node, ctx) {
|
||||
var editor_alpha = this.editor_alpha;
|
||||
var old_color = node.bgcolor;
|
||||
|
||||
if (node.mode === 2) { // never
|
||||
this.editor_alpha = 0.4;
|
||||
}
|
||||
|
||||
if (node.mode === 4) { // never
|
||||
node.bgcolor = "#FF00FF";
|
||||
this.editor_alpha = 0.2;
|
||||
}
|
||||
|
||||
const res = super.drawNode(node, ctx);
|
||||
|
||||
this.editor_alpha = editor_alpha;
|
||||
node.bgcolor = old_color;
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
86
web/scripts/graphNode.js
Normal file
86
web/scripts/graphNode.js
Normal file
@ -0,0 +1,86 @@
|
||||
import { LGraphNode, LGraphCanvas, BuiltInSlotType, BuiltInSlotShape } from "../lib/litegraph.core.js"
|
||||
import { ComfyWidgets } from "./widgets.js";
|
||||
import { iterateNodeDefOutputs, iterateNodeDefInputs } from "./nodeDef.js";
|
||||
|
||||
export class ComfyGraphNode extends LGraphNode {
|
||||
|
||||
}
|
||||
|
||||
// comfy class -> input name -> input config
|
||||
const defaultInputConfigs = {}
|
||||
|
||||
export class ComfyBackendNode extends ComfyGraphNode {
|
||||
constructor(title, comfyClass, nodeDef) {
|
||||
super(title)
|
||||
this.type = comfyClass; // XXX: workaround dependency in LGraphNode.addInput()
|
||||
this.displayName = nodeDef.display_name;
|
||||
this.comfyNodeDef = nodeDef;
|
||||
this.comfyClass = comfyClass;
|
||||
this.isBackendNode = true;
|
||||
|
||||
const color = LGraphCanvas.node_colors["yellow"];
|
||||
if (this.color == null)
|
||||
this.color = color.color
|
||||
if (this.bgColor == null)
|
||||
this.bgColor = color.bgColor
|
||||
|
||||
this.#setup(nodeDef)
|
||||
|
||||
// if (nodeDef.output_node) {
|
||||
// this.addOutput("OUTPUT", BuiltInSlotType.EVENT, { color_off: "rebeccapurple", color_on: "rebeccapurple" });
|
||||
// }
|
||||
}
|
||||
|
||||
get isOutputNode() {
|
||||
return this.comfyNodeDef.output_node;
|
||||
}
|
||||
|
||||
#setup(nodeDef) {
|
||||
defaultInputConfigs[this.type] = {}
|
||||
|
||||
const widgets = Object.assign({}, ComfyWidgets, ComfyWidgets.customWidgets);
|
||||
|
||||
for (const [inputName, inputData] of iterateNodeDefInputs(nodeDef)) {
|
||||
const config = {};
|
||||
|
||||
const [type, opts] = inputData;
|
||||
|
||||
if (opts?.forceInput) {
|
||||
if (Array.isArray(type)) {
|
||||
throw new Error(`Can't have forceInput set to true for an enum type! ${type}`)
|
||||
}
|
||||
this.addInput(inputName, type);
|
||||
} else {
|
||||
if (Array.isArray(type)) {
|
||||
// Enums
|
||||
Object.assign(config, widgets.COMBO(this, inputName, inputData) || {});
|
||||
} else if (`${type}:${inputName}` in widgets) {
|
||||
// Support custom ComfyWidgets by Type:Name
|
||||
Object.assign(config, widgets[`${type}:${inputName}`](this, inputName, inputData) || {});
|
||||
} else if (type in widgets) {
|
||||
// Standard type ComfyWidgets
|
||||
Object.assign(config, widgets[type](this, inputName, inputData) || {});
|
||||
} else {
|
||||
// Node connection inputs (backend)
|
||||
this.addInput(inputName, type);
|
||||
}
|
||||
}
|
||||
|
||||
if ("widgetNodeType" in config)
|
||||
ComfyBackendNode.defaultInputConfigs[this.type][inputName] = config.config
|
||||
}
|
||||
|
||||
for (const output of iterateNodeDefOutputs(nodeDef)) {
|
||||
const outputShape = output.is_list ? BuiltInSlotShape.GRID_SHAPE : BuiltInSlotShape.CIRCLE_SHAPE;
|
||||
this.addOutput(output.name, output.type, { shape: outputShape });
|
||||
}
|
||||
|
||||
this.serialize_widgets = false;
|
||||
// app.#invokeExtensionsAsync("nodeCreated", this);
|
||||
}
|
||||
|
||||
// onExecuted(outputData) {
|
||||
// console.warn("onExecuted outputs", outputData)
|
||||
// this.triggerSlot(0, outputData)
|
||||
// }
|
||||
}
|
||||
26
web/scripts/nodeDef.js
Normal file
26
web/scripts/nodeDef.js
Normal file
@ -0,0 +1,26 @@
|
||||
import { ComfyWidgets } from "./widgets.js"
|
||||
import { range } from "./utils.js"
|
||||
|
||||
export function isBackendNodeDefInputType(inputName, type) {
|
||||
const widgets = Object.assign({}, ComfyWidgets, ComfyWidgets.customWidgets);
|
||||
return !Array.isArray(type) && !(type in ComfyWidgets) && !(`${type}:${inputName}` in ComfyWidgets);
|
||||
}
|
||||
|
||||
export function iterateNodeDefInputs(def) {
|
||||
var inputs = def.input.required || {}
|
||||
if (def.input.optional != null) {
|
||||
inputs = Object.assign({}, def.input.required, def.input.optional)
|
||||
}
|
||||
return Object.entries(inputs);
|
||||
}
|
||||
|
||||
export function iterateNodeDefOutputs(def) {
|
||||
const outputCount = def.output ? def.output.length : 0;
|
||||
return range(outputCount).map(i => {
|
||||
return {
|
||||
type: def.output[i],
|
||||
name: def.output_name[i] || def.output[i],
|
||||
is_list: def.output_is_list[i],
|
||||
}
|
||||
})
|
||||
}
|
||||
3
web/scripts/utils.js
Normal file
3
web/scripts/utils.js
Normal file
@ -0,0 +1,3 @@
|
||||
export function range(size, startAt = 0) {
|
||||
return [...Array(size).keys()].map(i => i + startAt);
|
||||
}
|
||||
@ -157,7 +157,7 @@ function addMultilineWidget(node, name, opts, app) {
|
||||
// Calculate it here instead
|
||||
computeSize(node.size);
|
||||
}
|
||||
const visible = app.canvas.ds.scale > 0.5 && this.type === "customtext";
|
||||
const visible = window.app.canvas.ds.scale > 0.5 && this.type === "customtext";
|
||||
const margin = 10;
|
||||
const elRect = ctx.canvas.getBoundingClientRect();
|
||||
const transform = new DOMMatrix()
|
||||
@ -176,7 +176,7 @@ function addMultilineWidget(node, name, opts, app) {
|
||||
position: "absolute",
|
||||
background: (!node.color)?'':node.color,
|
||||
color: (!node.color)?'':'white',
|
||||
zIndex: app.graph._nodes.indexOf(node),
|
||||
zIndex: window.app.graph._nodes.indexOf(node),
|
||||
});
|
||||
this.inputEl.hidden = !visible;
|
||||
},
|
||||
@ -195,11 +195,11 @@ function addMultilineWidget(node, name, opts, app) {
|
||||
|
||||
node.addCustomWidget(widget);
|
||||
|
||||
app.canvas.onDrawBackground = function () {
|
||||
window.app.canvas.onDrawBackground = function () {
|
||||
// Draw node isnt fired once the node is off the screen
|
||||
// if it goes off screen quickly, the input may not be removed
|
||||
// this shifts it off screen so it can be moved back if the node is visible.
|
||||
for (let n in app.graph._nodes) {
|
||||
for (let n in window.app.graph._nodes) {
|
||||
n = graph._nodes[n];
|
||||
for (let w in n.widgets) {
|
||||
let wid = n.widgets[w];
|
||||
@ -251,7 +251,7 @@ function addMultilineWidget(node, name, opts, app) {
|
||||
}
|
||||
|
||||
function isSlider(display, app) {
|
||||
if (app.ui.settings.getSettingValue("Comfy.DisableSliders")) {
|
||||
if (window.app.ui.settings.getSettingValue("Comfy.DisableSliders")) {
|
||||
return "number"
|
||||
}
|
||||
|
||||
@ -321,7 +321,7 @@ export const ComfyWidgets = {
|
||||
const img = new Image();
|
||||
img.onload = () => {
|
||||
node.imgs = [img];
|
||||
app.graph.setDirtyCanvas(true);
|
||||
window.app.graph.setDirtyCanvas(true);
|
||||
};
|
||||
let folder_separator = name.lastIndexOf("/");
|
||||
let subfolder = "";
|
||||
@ -329,7 +329,7 @@ export const ComfyWidgets = {
|
||||
subfolder = name.substring(0, folder_separator);
|
||||
name = name.substring(folder_separator + 1);
|
||||
}
|
||||
img.src = api.apiURL(`/view?filename=${name}&type=input&subfolder=${subfolder}${app.getPreviewFormatParam()}`);
|
||||
img.src = api.apiURL(`/view?filename=${name}&type=input&subfolder=${subfolder}${window.app.getPreviewFormatParam()}`);
|
||||
node.setSizeForImage?.();
|
||||
}
|
||||
|
||||
@ -457,3 +457,5 @@ export const ComfyWidgets = {
|
||||
return { widget: uploadWidget };
|
||||
},
|
||||
};
|
||||
|
||||
export const customWidgets = []
|
||||
|
||||
Loading…
Reference in New Issue
Block a user