mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2025-03-14 13:17:32 +00:00
Merge remote-tracking branch 'origin/master' into combo_filter_input
This commit is contained in:
commit
de2894ac2c
21
web/extensions/core/slotDefaults.js
Normal file
21
web/extensions/core/slotDefaults.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { app } from "/scripts/app.js";
|
||||||
|
|
||||||
|
// Adds defaults for quickly adding nodes with middle click on the input/output
|
||||||
|
|
||||||
|
app.registerExtension({
|
||||||
|
name: "Comfy.SlotDefaults",
|
||||||
|
init() {
|
||||||
|
LiteGraph.middle_click_slot_add_default_node = true;
|
||||||
|
LiteGraph.slot_types_default_in = {
|
||||||
|
MODEL: "CheckpointLoaderSimple",
|
||||||
|
LATENT: "EmptyLatentImage",
|
||||||
|
VAE: "VAELoader",
|
||||||
|
};
|
||||||
|
|
||||||
|
LiteGraph.slot_types_default_out = {
|
||||||
|
LATENT: "VAEDecode",
|
||||||
|
IMAGE: "SaveImage",
|
||||||
|
CLIP: "CLIPTextEncode",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
89
web/extensions/core/snapToGrid.js
Normal file
89
web/extensions/core/snapToGrid.js
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
import { app } from "/scripts/app.js";
|
||||||
|
|
||||||
|
// Shift + drag/resize to snap to grid
|
||||||
|
|
||||||
|
app.registerExtension({
|
||||||
|
name: "Comfy.SnapToGrid",
|
||||||
|
init() {
|
||||||
|
// Add setting to control grid size
|
||||||
|
app.ui.settings.addSetting({
|
||||||
|
id: "Comfy.SnapToGrid.GridSize",
|
||||||
|
name: "Grid Size",
|
||||||
|
type: "number",
|
||||||
|
attrs: {
|
||||||
|
min: 1,
|
||||||
|
max: 500,
|
||||||
|
},
|
||||||
|
tooltip:
|
||||||
|
"When dragging and resizing nodes while holding shift they will be aligned to the grid, this controls the size of that grid.",
|
||||||
|
defaultValue: LiteGraph.CANVAS_GRID_SIZE,
|
||||||
|
onChange(value) {
|
||||||
|
LiteGraph.CANVAS_GRID_SIZE = +value;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// After moving a node, if the shift key is down align it to grid
|
||||||
|
const onNodeMoved = app.canvas.onNodeMoved;
|
||||||
|
app.canvas.onNodeMoved = function (node) {
|
||||||
|
const r = onNodeMoved?.apply(this, arguments);
|
||||||
|
|
||||||
|
if (app.shiftDown) {
|
||||||
|
// Ensure all selected nodes are realigned
|
||||||
|
for (const id in this.selected_nodes) {
|
||||||
|
this.selected_nodes[id].alignToGrid();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
};
|
||||||
|
|
||||||
|
// When a node is added, add a resize handler to it so we can fix align the size with the grid
|
||||||
|
const onNodeAdded = app.graph.onNodeAdded;
|
||||||
|
app.graph.onNodeAdded = function (node) {
|
||||||
|
const onResize = node.onResize;
|
||||||
|
node.onResize = function () {
|
||||||
|
if (app.shiftDown) {
|
||||||
|
const w = LiteGraph.CANVAS_GRID_SIZE * Math.round(node.size[0] / LiteGraph.CANVAS_GRID_SIZE);
|
||||||
|
const h = LiteGraph.CANVAS_GRID_SIZE * Math.round(node.size[1] / LiteGraph.CANVAS_GRID_SIZE);
|
||||||
|
node.size[0] = w;
|
||||||
|
node.size[1] = h;
|
||||||
|
}
|
||||||
|
return onResize?.apply(this, arguments);
|
||||||
|
};
|
||||||
|
return onNodeAdded?.apply(this, arguments);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Draw a preview of where the node will go if holding shift and the node is selected
|
||||||
|
const origDrawNode = LGraphCanvas.prototype.drawNode;
|
||||||
|
LGraphCanvas.prototype.drawNode = function (node, ctx) {
|
||||||
|
if (app.shiftDown && this.node_dragged && node.id in this.selected_nodes) {
|
||||||
|
const x = LiteGraph.CANVAS_GRID_SIZE * Math.round(node.pos[0] / LiteGraph.CANVAS_GRID_SIZE);
|
||||||
|
const y = LiteGraph.CANVAS_GRID_SIZE * Math.round(node.pos[1] / LiteGraph.CANVAS_GRID_SIZE);
|
||||||
|
|
||||||
|
const shiftX = x - node.pos[0];
|
||||||
|
let shiftY = y - node.pos[1];
|
||||||
|
|
||||||
|
let w, h;
|
||||||
|
if (node.flags.collapsed) {
|
||||||
|
w = node._collapsed_width;
|
||||||
|
h = LiteGraph.NODE_TITLE_HEIGHT;
|
||||||
|
shiftY -= LiteGraph.NODE_TITLE_HEIGHT;
|
||||||
|
} else {
|
||||||
|
w = node.size[0];
|
||||||
|
h = node.size[1];
|
||||||
|
let titleMode = node.constructor.title_mode;
|
||||||
|
if (titleMode !== LiteGraph.TRANSPARENT_TITLE && titleMode !== LiteGraph.NO_TITLE) {
|
||||||
|
h += LiteGraph.NODE_TITLE_HEIGHT;
|
||||||
|
shiftY -= LiteGraph.NODE_TITLE_HEIGHT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const f = ctx.fillStyle;
|
||||||
|
ctx.fillStyle = "rgba(100, 100, 100, 0.5)";
|
||||||
|
ctx.fillRect(shiftX, shiftY, w, h);
|
||||||
|
ctx.fillStyle = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return origDrawNode.apply(this, arguments);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
@ -20,7 +20,7 @@ function hideWidget(node, widget, suffix = "") {
|
|||||||
if (link == null) {
|
if (link == null) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
return widget.value;
|
return widget.origSerializeValue ? widget.origSerializeValue() : widget.value;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Hide any linked widgets, e.g. seed+randomize
|
// Hide any linked widgets, e.g. seed+randomize
|
||||||
|
@ -18,6 +18,7 @@ class ComfyApp {
|
|||||||
this.ui = new ComfyUI(this);
|
this.ui = new ComfyUI(this);
|
||||||
this.extensions = [];
|
this.extensions = [];
|
||||||
this.nodeOutputs = {};
|
this.nodeOutputs = {};
|
||||||
|
this.shiftDown = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -637,11 +638,16 @@ class ComfyApp {
|
|||||||
|
|
||||||
#addKeyboardHandler() {
|
#addKeyboardHandler() {
|
||||||
window.addEventListener("keydown", (e) => {
|
window.addEventListener("keydown", (e) => {
|
||||||
|
this.shiftDown = e.shiftKey;
|
||||||
|
|
||||||
// Queue prompt using ctrl or command + enter
|
// Queue prompt using ctrl or command + enter
|
||||||
if ((e.ctrlKey || e.metaKey) && (e.key === "Enter" || e.keyCode === 13 || e.keyCode === 10)) {
|
if ((e.ctrlKey || e.metaKey) && (e.key === "Enter" || e.keyCode === 13 || e.keyCode === 10)) {
|
||||||
this.queuePrompt(e.shiftKey ? -1 : 0);
|
this.queuePrompt(e.shiftKey ? -1 : 0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
window.addEventListener("keyup", (e) => {
|
||||||
|
this.shiftDown = e.shiftKey;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -676,6 +682,9 @@ class ComfyApp {
|
|||||||
const canvas = (this.canvas = new LGraphCanvas(canvasEl, this.graph));
|
const canvas = (this.canvas = new LGraphCanvas(canvasEl, this.graph));
|
||||||
this.ctx = canvasEl.getContext("2d");
|
this.ctx = canvasEl.getContext("2d");
|
||||||
|
|
||||||
|
LiteGraph.release_link_on_empty_shows_menu = true;
|
||||||
|
LiteGraph.alt_drag_do_clone_nodes = true;
|
||||||
|
|
||||||
this.graph.start();
|
this.graph.start();
|
||||||
|
|
||||||
function resizeCanvas() {
|
function resizeCanvas() {
|
||||||
|
@ -198,7 +198,7 @@ class ComfySettingsDialog extends ComfyDialog {
|
|||||||
localStorage[settingId] = JSON.stringify(value);
|
localStorage[settingId] = JSON.stringify(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
addSetting({ id, name, type, defaultValue, onChange }) {
|
addSetting({ id, name, type, defaultValue, onChange, attrs = {}, tooltip = "", }) {
|
||||||
if (!id) {
|
if (!id) {
|
||||||
throw new Error("Settings must have an ID");
|
throw new Error("Settings must have an ID");
|
||||||
}
|
}
|
||||||
@ -225,13 +225,14 @@ class ComfySettingsDialog extends ComfyDialog {
|
|||||||
value = v;
|
value = v;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (typeof type === "function") {
|
let element;
|
||||||
return type(name, setter, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (typeof type === "function") {
|
||||||
|
element = type(name, setter, value, attrs);
|
||||||
|
} else {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "boolean":
|
case "boolean":
|
||||||
return $el("div", [
|
element = $el("div", [
|
||||||
$el("label", { textContent: name || id }, [
|
$el("label", { textContent: name || id }, [
|
||||||
$el("input", {
|
$el("input", {
|
||||||
type: "checkbox",
|
type: "checkbox",
|
||||||
@ -239,28 +240,57 @@ class ComfySettingsDialog extends ComfyDialog {
|
|||||||
oninput: (e) => {
|
oninput: (e) => {
|
||||||
setter(e.target.checked);
|
setter(e.target.checked);
|
||||||
},
|
},
|
||||||
|
...attrs
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
]);
|
]);
|
||||||
|
break;
|
||||||
|
case "number":
|
||||||
|
element = $el("div", [
|
||||||
|
$el("label", { textContent: name || id }, [
|
||||||
|
$el("input", {
|
||||||
|
type,
|
||||||
|
value,
|
||||||
|
oninput: (e) => {
|
||||||
|
setter(e.target.value);
|
||||||
|
},
|
||||||
|
...attrs
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
console.warn("Unsupported setting type, defaulting to text");
|
console.warn("Unsupported setting type, defaulting to text");
|
||||||
return $el("div", [
|
element = $el("div", [
|
||||||
$el("label", { textContent: name || id }, [
|
$el("label", { textContent: name || id }, [
|
||||||
$el("input", {
|
$el("input", {
|
||||||
value,
|
value,
|
||||||
oninput: (e) => {
|
oninput: (e) => {
|
||||||
setter(e.target.value);
|
setter(e.target.value);
|
||||||
},
|
},
|
||||||
|
...attrs
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
]);
|
]);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if(tooltip) {
|
||||||
|
element.title = tooltip;
|
||||||
|
}
|
||||||
|
|
||||||
|
return element;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
show() {
|
show() {
|
||||||
super.show();
|
super.show();
|
||||||
|
Object.assign(this.textElement.style, {
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
gap: "10px"
|
||||||
|
});
|
||||||
this.textElement.replaceChildren(...this.settings.map((s) => s.render()));
|
this.textElement.replaceChildren(...this.settings.map((s) => s.render()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user