diff --git a/README.md b/README.md index 0085e7f..d74ec4f 100644 --- a/README.md +++ b/README.md @@ -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, diff --git a/web/main.js b/web/main.js index 8a50c60..b5196bd 100644 --- a/web/main.js +++ b/web/main.js @@ -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) { diff --git a/web/page/bspaint.js b/web/page/bspaint.js index 3f1f61d..224060b 100644 --- a/web/page/bspaint.js +++ b/web/page/bspaint.js @@ -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: diff --git a/web/page/main.js b/web/page/main.js index 8409ec4..59f0201 100644 --- a/web/page/main.js +++ b/web/page/main.js @@ -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() {