More region widget fixes
This commit is contained in:
Submodule litegraph updated: 34b0f0c220...d8fa87185a
@@ -11,7 +11,7 @@ import type { ComfyComboNode, ComfyWidgetNode } from "./nodes/widgets";
|
|||||||
import selectionState from "./stores/selectionState";
|
import selectionState from "./stores/selectionState";
|
||||||
import type { WritableLayoutStateStore } from "./stores/layoutStates";
|
import type { WritableLayoutStateStore } from "./stores/layoutStates";
|
||||||
import layoutStates from "./stores/layoutStates";
|
import layoutStates from "./stores/layoutStates";
|
||||||
import type { ComfyWorkflow } from "./stores/workflowState";
|
import type { ComfyWorkflow, WorkflowInstID } from "./stores/workflowState";
|
||||||
import workflowState from "./stores/workflowState";
|
import workflowState from "./stores/workflowState";
|
||||||
|
|
||||||
type ComfyGraphEvents = {
|
type ComfyGraphEvents = {
|
||||||
@@ -163,7 +163,7 @@ export default class ComfyGraph extends LGraph {
|
|||||||
// case node was cloned
|
// case node was cloned
|
||||||
const reg = LiteGraph.registered_node_types[node.type]
|
const reg = LiteGraph.registered_node_types[node.type]
|
||||||
|
|
||||||
layoutState.groupItems(dragItemIDs, { title: reg.title })
|
layoutState.groupItems(dragItemIDs, { title: reg.title, variant: "accordion", openOnStartup: true })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -356,6 +356,24 @@ export default class ComfyApp {
|
|||||||
|
|
||||||
ComfyApp.registerDefaultSlotHandlers(nodeId, nodeDef)
|
ComfyApp.registerDefaultSlotHandlers(nodeId, nodeDef)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ComfyApp.registerComfyBoxSlotTypes()
|
||||||
|
}
|
||||||
|
|
||||||
|
static registerComfyBoxSlotTypes() {
|
||||||
|
const reg = (type: string) => {
|
||||||
|
const lowerType = type.toLowerCase();
|
||||||
|
if (!LiteGraph.slot_types_in.includes(lowerType)) {
|
||||||
|
LiteGraph.slot_types_in.push(lowerType);
|
||||||
|
}
|
||||||
|
if (!LiteGraph.slot_types_out.includes(type)) {
|
||||||
|
LiteGraph.slot_types_out.push(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reg("COMFYBOX_IMAGE")
|
||||||
|
reg("COMFYBOX_IMAGES")
|
||||||
|
reg("COMFYBOX_REGION")
|
||||||
}
|
}
|
||||||
|
|
||||||
static registerDefaultSlotHandlers(nodeId: string, nodeDef: ComfyNodeDef) {
|
static registerDefaultSlotHandlers(nodeId: string, nodeDef: ComfyNodeDef) {
|
||||||
@@ -771,7 +789,9 @@ export default class ComfyApp {
|
|||||||
|
|
||||||
const promptFilename = get(configState).promptForWorkflowName;
|
const promptFilename = get(configState).promptForWorkflowName;
|
||||||
|
|
||||||
let filename = "workflow.json";
|
const title = workflow.attrs.title.trim() || "workflow"
|
||||||
|
|
||||||
|
let filename = `${title}.json`;
|
||||||
if (promptFilename) {
|
if (promptFilename) {
|
||||||
filename = prompt("Save workflow as:", filename);
|
filename = prompt("Save workflow as:", filename);
|
||||||
if (!filename) return;
|
if (!filename) return;
|
||||||
@@ -782,7 +802,7 @@ export default class ComfyApp {
|
|||||||
else {
|
else {
|
||||||
const date = new Date();
|
const date = new Date();
|
||||||
const formattedDate = date.toISOString().replace(/:/g, '-').replace(/\.\d{3}/g, '').replace('T', '_').replace("Z", "");
|
const formattedDate = date.toISOString().replace(/:/g, '-').replace(/\.\d{3}/g, '').replace('T', '_').replace("Z", "");
|
||||||
filename = `workflow - ${formattedDate}.json`
|
filename = `${title} - ${formattedDate}.json`
|
||||||
}
|
}
|
||||||
|
|
||||||
const indent = 2
|
const indent = 2
|
||||||
|
|||||||
@@ -150,7 +150,7 @@
|
|||||||
let submessage = `Nodes: ${Object.keys(entry.prompt).length}`
|
let submessage = `Nodes: ${Object.keys(entry.prompt).length}`
|
||||||
|
|
||||||
if (Object.keys(entry.outputs).length > 0) {
|
if (Object.keys(entry.outputs).length > 0) {
|
||||||
const imageCount = Object.values(entry.outputs).flatMap(o => o.images).length
|
const imageCount = Object.values(entry.outputs).filter(o => o.images).flatMap(o => o.images).length
|
||||||
submessage = `Images: ${imageCount}`
|
submessage = `Images: ${imageCount}`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,13 +172,23 @@
|
|||||||
result.images = thumbnails.map(convertComfyOutputToComfyURL);
|
result.images = thumbnails.map(convertComfyOutputToComfyURL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const outputs = Object.values(entry.outputs)
|
||||||
|
.filter(o => o.images)
|
||||||
|
.flatMap(o => o.images)
|
||||||
|
.map(convertComfyOutputToComfyURL);
|
||||||
|
if (outputs) {
|
||||||
|
result.images = result.images.concat(outputs)
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertCompletedEntry(entry: CompletedQueueEntry): QueueUIEntry {
|
function convertCompletedEntry(entry: CompletedQueueEntry): QueueUIEntry {
|
||||||
const result = convertEntry(entry.entry, entry.status);
|
const result = convertEntry(entry.entry, entry.status);
|
||||||
|
|
||||||
const images = Object.values(entry.entry.outputs).flatMap(o => o.images)
|
const images = Object.values(entry.entry.outputs)
|
||||||
|
.filter(o => o.images)
|
||||||
|
.flatMap(o => o.images)
|
||||||
.map(convertComfyOutputToComfyURL);
|
.map(convertComfyOutputToComfyURL);
|
||||||
result.images = images
|
result.images = images
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
export let label: string;
|
export let label: string;
|
||||||
export let root: string = "";
|
export let root: string = "";
|
||||||
export let root_url: null | string = null;
|
export let root_url: null | string = null;
|
||||||
|
export let scrollOnUpdate = false;
|
||||||
export let value: Array<string> | Array<FileData> | null = null;
|
export let value: Array<string> | Array<FileData> | null = null;
|
||||||
export let style: Styles = {
|
export let style: Styles = {
|
||||||
grid_cols: [2],
|
grid_cols: [2],
|
||||||
@@ -120,6 +121,7 @@
|
|||||||
let container: HTMLDivElement;
|
let container: HTMLDivElement;
|
||||||
|
|
||||||
async function scroll_to_img(index: number | null) {
|
async function scroll_to_img(index: number | null) {
|
||||||
|
if (!scrollOnUpdate) return;
|
||||||
if (typeof index !== "number") return;
|
if (typeof index !== "number") return;
|
||||||
await tick();
|
await tick();
|
||||||
|
|
||||||
|
|||||||
@@ -7,10 +7,11 @@ export default class ComfyRegionToCoordsNode extends ComfyGraphNode {
|
|||||||
{ name: "in", type: "COMFYBOX_REGION" },
|
{ name: "in", type: "COMFYBOX_REGION" },
|
||||||
],
|
],
|
||||||
outputs: [
|
outputs: [
|
||||||
{ name: "x", type: "number" },
|
// same order as conditioning nodes
|
||||||
{ name: "y", type: "number" },
|
|
||||||
{ name: "width", type: "number" },
|
{ name: "width", type: "number" },
|
||||||
{ name: "height", type: "number" },
|
{ name: "height", type: "number" },
|
||||||
|
{ name: "x", type: "number" },
|
||||||
|
{ name: "y", type: "number" },
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,16 +20,16 @@ export default class ComfyRegionToCoordsNode extends ComfyGraphNode {
|
|||||||
if (!Array.isArray(value))
|
if (!Array.isArray(value))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.setOutputData(0, value[0])
|
this.setOutputData(0, value[2])
|
||||||
this.setOutputData(1, value[1])
|
this.setOutputData(1, value[3])
|
||||||
this.setOutputData(2, value[2])
|
this.setOutputData(2, value[0])
|
||||||
this.setOutputData(3, value[3])
|
this.setOutputData(3, value[1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LiteGraph.registerNodeType({
|
LiteGraph.registerNodeType({
|
||||||
class: ComfyRegionToCoordsNode,
|
class: ComfyRegionToCoordsNode,
|
||||||
title: "Comfy.RegionToCoords",
|
title: "Comfy.RegionToCoords",
|
||||||
desc: "Converts a COMFYBOX_REGION to four outputs of [x, y, width, height]",
|
desc: "Converts a COMFYBOX_REGION to four outputs of [width, height, x, y]",
|
||||||
type: "utils/region_to_coords"
|
type: "utils/region_to_coords"
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export default class ComfyMultiRegionNode extends ComfyWidgetNode<BoundingBox[]>
|
|||||||
{ name: "changed", type: BuiltInSlotType.EVENT },
|
{ name: "changed", type: BuiltInSlotType.EVENT },
|
||||||
|
|
||||||
// dynamic outputs, may be removed later
|
// dynamic outputs, may be removed later
|
||||||
{ name: "region1", type: "COMFYBOX_REGION" },
|
{ name: "region_1", type: "COMFYBOX_REGION" },
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,7 +145,7 @@ export default class ComfyMultiRegionNode extends ComfyWidgetNode<BoundingBox[]>
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (let index = this.outputs.length - 1; index < this.properties.regionCount; index++) {
|
for (let index = this.outputs.length - 1; index < this.properties.regionCount; index++) {
|
||||||
this.addOutput(`region${index + 1}`, "COMFYBOX_REGION")
|
this.addOutput(`region_${index + 1}`, "COMFYBOX_REGION")
|
||||||
}
|
}
|
||||||
|
|
||||||
this.regionsChanged.set(true);
|
this.regionsChanged.set(true);
|
||||||
@@ -165,10 +165,10 @@ export default class ComfyMultiRegionNode extends ComfyWidgetNode<BoundingBox[]>
|
|||||||
value ||= this.getValue();
|
value ||= this.getValue();
|
||||||
|
|
||||||
for (const bbox of value) {
|
for (const bbox of value) {
|
||||||
bbox[0] = clamp(bbox[0], 0, 1 - bbox[2]);
|
bbox[0] = clamp(bbox[0], 0, 1);
|
||||||
bbox[1] = clamp(bbox[1], 0, 1 - bbox[3]);
|
bbox[1] = clamp(bbox[1], 0, 1);
|
||||||
bbox[2] = clamp(bbox[2], 0, 1 - bbox[1])
|
bbox[2] = clamp(bbox[2], 0, 1)
|
||||||
bbox[3] = clamp(bbox[3], 0, 1 - bbox[2])
|
bbox[3] = clamp(bbox[3], 0, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
const sizeChanged = this.properties.canvasWidth != this._prevWidth
|
const sizeChanged = this.properties.canvasWidth != this._prevWidth
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
import { generateBlankCanvas, generateImageCanvas, loadImage } from "./utils";
|
import { generateBlankCanvas, generateImageCanvas, loadImage } from "./utils";
|
||||||
import { clamp } from "$lib/utils";
|
import { clamp } from "$lib/utils";
|
||||||
import Row from "$lib/components/gradio/app/Row.svelte";
|
import Row from "$lib/components/gradio/app/Row.svelte";
|
||||||
import Column from "$lib/components/gradio/app/Column.svelte";
|
|
||||||
|
|
||||||
// ref: https://html-color.codes/
|
// ref: https://html-color.codes/
|
||||||
const COLOR_MAP: [string, string][] = [
|
const COLOR_MAP: [string, string][] = [
|
||||||
@@ -400,6 +399,10 @@ const COLOR_MAP: [string, string][] = [
|
|||||||
displayBoxes = await recreateDisplayBoxes();
|
displayBoxes = await recreateDisplayBoxes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateSelectedIndex(newIndexPlusOne: number) {
|
||||||
|
selectedIndex = clamp(newIndexPlusOne - 1, 0, $nodeValue.length - 1);
|
||||||
|
}
|
||||||
|
|
||||||
function updateX(newX: number) {
|
function updateX(newX: number) {
|
||||||
const bbox = $nodeValue[selectedIndex]
|
const bbox = $nodeValue[selectedIndex]
|
||||||
const dbox = displayBoxes[selectedIndex]
|
const dbox = displayBoxes[selectedIndex]
|
||||||
@@ -440,7 +443,7 @@ const COLOR_MAP: [string, string][] = [
|
|||||||
displayBoxes[selectedIndex] = displayBoundingBox(bbox, selectedIndex, imageElem, dbox);
|
displayBoxes[selectedIndex] = displayBoundingBox(bbox, selectedIndex, imageElem, dbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateValue() {
|
async function updateValue() {
|
||||||
// Clamp regions
|
// Clamp regions
|
||||||
const bbox = $nodeValue[selectedIndex]
|
const bbox = $nodeValue[selectedIndex]
|
||||||
const dbox = displayBoxes[selectedIndex]
|
const dbox = displayBoxes[selectedIndex]
|
||||||
@@ -452,6 +455,8 @@ const COLOR_MAP: [string, string][] = [
|
|||||||
displayBoxes[selectedIndex] = displayBoundingBox(bbox, selectedIndex, imageElem, dbox);
|
displayBoxes[selectedIndex] = displayBoundingBox(bbox, selectedIndex, imageElem, dbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await updateImageAndDBoxes();
|
||||||
|
|
||||||
// Force reactivity after changing a bbox's internal values
|
// Force reactivity after changing a bbox's internal values
|
||||||
$nodeValue = $nodeValue
|
$nodeValue = $nodeValue
|
||||||
}
|
}
|
||||||
@@ -504,6 +509,13 @@ const COLOR_MAP: [string, string][] = [
|
|||||||
</div>
|
</div>
|
||||||
{#if selectedBBox}
|
{#if selectedBBox}
|
||||||
<Block>
|
<Block>
|
||||||
|
<Row>
|
||||||
|
<Range label="Region #" value={selectedIndex+1}
|
||||||
|
show_label={true} minimum={1} maximum={$nodeValue.length} step={1}
|
||||||
|
on:change={(e) => updateSelectedIndex(e.detail)}
|
||||||
|
on:release={updateValue}
|
||||||
|
/>
|
||||||
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<Range label="X" value={selectedBBox[0]}
|
<Range label="X" value={selectedBBox[0]}
|
||||||
show_label={true} minimum={0.0} maximum={1.0} step={0.01}
|
show_label={true} minimum={0.0} maximum={1.0} step={0.01}
|
||||||
|
|||||||
Reference in New Issue
Block a user