Multi target support

This commit is contained in:
Neil Graham
2024-01-24 18:24:33 +13:00
parent 8be3a82289
commit 45579aa7a1
4 changed files with 42 additions and 21 deletions
+7 -1
View File
@@ -2,6 +2,8 @@
ComfyUI canvas editor page
## Updates
- 2024-1-24 Added multi canvas node support.
- 2024-1-11 Added CSS for prefers-color-scheme:dark
- 2023-12-23 Added tool to scale and rotate layers (Hotkey is T, doubleClick on image to toggle between Rotate and Scale mode)
- 2023-12-4 Added hotkeys for Brush Radius, Added Duplicate Layer button. Ctrl-Click duplicates the target layer.
- 2023-12-2 Added Trigger Queue on change toggle.
@@ -26,6 +28,9 @@ Drag images around with the middle mouse button and scale them with the mouse wh
There is a green Tab on the side of images in the editor, click on that tab to highlight it.
The image with the highlighted tab is sent through to the comfyUI node.
Multiple Canvas Tab nodes are supported, If the title of the node and the title of the image in the editor are set to the same name
The output of the canvas editor will be sent to that node.
You can have multiple image layers and you can select generated images to be
added as a new layer, replace an existing layers, or as a new image.
@@ -52,7 +57,8 @@ send images directly to the editor.
- CTRL_SHIFT_Z redo
##Why would you do such a thing?
## Why would you do such a thing?
My main motivation for making this was to develop an inpainting workflow,
but I have also found it quite useful for scribble based images,
+12 -6
View File
@@ -41,7 +41,7 @@ function checkAndClear(key) {
function handleStatusUpdate(e) {
const detail = e.detail;
if (detail?.exec_info?.queue_remaining === 0) {
console.log({anotherQueueWaiting,autoQueueInProgress})
//console.log({anotherQueueWaiting,autoQueueInProgress})
if (anotherQueueWaiting) {
app.queuePrompt();
anotherQueueWaiting=false;
@@ -99,7 +99,7 @@ function initEditorNode(node)
node.collected_images = [];
node.addWidget("button","Edit","bingo", (widget,graphCanvas, node, {x,y}, event) => focusEditor(node));
node.triggerQueue=node.addWidget("toggle","Queue on change",false,_=>{});
node.widgets.reverse();// because auto created widget get put in first
node.widgets.reverse();// because auto created widgets get put in first
node.canvasWidget=node.widgets[2];
node.maskWidget=node.widgets[3];
@@ -138,7 +138,6 @@ function addDragDropSupport(node) {
}
function transmitImages(images) {
console.log("transmit",editor)
if (!editor.window || editor.window.closed) openEditor();
if(editor.channel) {
@@ -274,8 +273,7 @@ function addCanvasWidget(node,name,inputData,app) {
widget.uploadedBlobName = result.name;
widget.sendBlobRequired=false;
}
}
console.log(widget)
}
return widget.uploadedBlobName;
}
}
@@ -324,8 +322,16 @@ function handleWindowMessage(e) {
}
async function messageFromEditor(event) {
const nodes = app.graph.findNodesByType("Canvas_Tab");
let nodes = app.graph.findNodesByType("Canvas_Tab");
//send same thing to all of the Canvas_Tab nodes
const {title, selected} = event.data;
console.log({title,selected});
if (title) {
let targetNodes = nodes.filter(node=>node.title==title || (node.title=="Edit In Another Tab" && selected));
nodes=targetNodes;
}
let queue = false;
if (event.data.image instanceof Blob) {
for (const node of nodes) {
+18 -10
View File
@@ -89,7 +89,8 @@ function setExportPic(pic) {
button.classList.add("output");
pic.updateVisualRepresentation(true);
transmitMask(pic.mask.canvas);
transmitMask(pic.mask.canvas,pic.title,true);
}
function closePic(pic) {
@@ -322,6 +323,7 @@ function createDrawArea(canvas = blankCanvas(),initialTitle="Image") {
set mask(m) {mask=m},
get width() {return canvas.width},
get height() {return canvas.height},
get title() {return title.textContent},
scale:1,
scalefactor:0,
offsetX:0,
@@ -388,15 +390,14 @@ function createDrawArea(canvas = blankCanvas(),initialTitle="Image") {
this.activeLayer.transform= [1,0 ,0,1, 0,0];
this.isDrawing = false;
if (selectedExport===this) {
//if (selectedExport===this) {
if (this.activeLayer===this.mask) {
transmitMask(this.mask.canvas);
transmitMask(this.mask.canvas,this.title,selectedExport===this);
} else {
this.composite(true);
transmitCanvas(canvas);
}
}
transmitCanvas(canvas,this.title,selectedExport===this);
}
//}
if (activePic===this) {
updateLayerList(); //inefficient to remake all controls on edit, fix this
}
@@ -413,9 +414,9 @@ function createDrawArea(canvas = blankCanvas(),initialTitle="Image") {
this.commit();
},
updateVisualRepresentation(transmit=true) {
if (transmit && this===selectedExport) {
if (transmit) {
this.composite(true); //suppress mask for transmitted canvas
transmitCanvas(canvas);
transmitCanvas(canvas,this.title,this===selectedExport);
}
this.composite(false);
if (typeof tool?.drawUI === "function") tool.drawUI();
@@ -864,7 +865,6 @@ function addNewImage(image) {
let result =createDrawArea(target);
$("#workspace").append(result.element);
//transmitCanvas(target);
return(result)
}
@@ -919,7 +919,15 @@ function handleMouseDown(e) {
setActivePic(pic);
const maskLayer = activePic.activeLayer.mask
if (e.altKey) {
switch (e.button) {
case 0:
break;
}
return;
}
switch (e.button) {
case 0:
+5 -4
View File
@@ -31,23 +31,24 @@ if (location.pathname.includes("/page/")) {
let portToMain; // variable to hold the MessageChannel port
function transmitCanvas(canvas) {
function transmitCanvas(canvas,title="",selected=true) {
if (portToMain) {
canvas.toBlob( blob=>{
portToMain.postMessage( {"image": blob} );
portToMain.postMessage( {"image": blob,title,selected} );
});
}
}
function transmitMask(canvas) {
function transmitMask(canvas,title="",selected=true) {
if (portToMain) {
canvas.toBlob( blob=>{
portToMain.postMessage( {"mask": blob} );
portToMain.postMessage( {"mask": blob,title,selected} );
});
}
}
function loadImagefromURL(url) {
var img = new Image();
img.onload = function() {