diff --git a/__init__.py b/__init__.py index fda422a..4338d45 100644 --- a/__init__.py +++ b/__init__.py @@ -14,13 +14,51 @@ def image_to_data_url(image): img_base64 = base64.b64encode(buffered.getvalue()) return f"data:image/png;base64,{img_base64.decode()}" +class Send_To_Editor: + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return { + "required": { + }, + "hidden": { + "unique_id":"UNIQUE_ID", + }, + "optional": { + "images": ("IMAGE",), + }, + + } + + RETURN_TYPES = () + + FUNCTION = "collect_images" + + OUTPUT_NODE = True + + CATEGORY = "image" + + def collect_images(self, unique_id, images=None): + + collected_images = list() + if images is not None: + for image in images: + i = 255. * image.cpu().numpy() + img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8)) + collected_images.append(image_to_data_url(img)) + + + return { "ui": {"collected_images":collected_images}} + + class Canvas_Tab: """ A Image Buffer for handling an editor in another tab. """ def __init__(self): - self.testState = {} pass @classmethod @@ -33,9 +71,9 @@ class Canvas_Tab: "hidden": { "unique_id":"UNIQUE_ID", }, - "optional": { - "images": ("IMAGE",), - }, +# "optional": { +# "images": ("IMAGE",), +# }, } @@ -49,14 +87,14 @@ class Canvas_Tab: def image_buffer(self, unique_id, mask, canvas, images=None): - collected_images = list() - if images is not None: - for image in images: - i = 255. * image.cpu().numpy() - img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8)) - collected_images.append(image_to_data_url(img)) - - +# collected_images = list() +# if images is not None: +# for image in images: +# i = 255. * image.cpu().numpy() +# img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8)) +# collected_images.append(image_to_data_url(img)) +# +# print(f"Node {unique_id}: images: {images}") image_path = folder_paths.get_annotated_filepath(canvas) i = Image.open(image_path) @@ -80,15 +118,17 @@ class Canvas_Tab: - return { "ui": {"collected_images":collected_images}, "result": (rgb_image, mask_data) } + return (rgb_image, mask_data) WEB_DIRECTORY = "web" NODE_CLASS_MAPPINGS = { - "Canvas_Tab": Canvas_Tab + "Canvas_Tab": Canvas_Tab, + "Send_To_Editor": Send_To_Editor } NODE_DISPLAY_NAME_MAPPINGS = { - "Canvas_Tab": "Edit In Another Tab" + "Canvas_Tab": "Edit In Another Tab", + "Send_To_Editor": "Send to Editor Tab" } diff --git a/web/main.js b/web/main.js index f8a35a8..2a8c642 100644 --- a/web/main.js +++ b/web/main.js @@ -64,11 +64,17 @@ app.registerExtension({ if (title==="Edit In Another Tab") { initEditorNode(node) } + else if (title==="Send to Editor Tab") { + initTransmitNode(node) + } + + } }); + function initEditorNode(node) { node.collected_images = []; @@ -81,15 +87,31 @@ function initEditorNode(node) node.maskWidget.onTopOf = node.canvasWidget; + /* node.onExecuted = (output)=> { if (output?.collected_images && editor.channel) { editor.channel.port1.postMessage( {images:output.collected_images}) - } - + } } + */ return; } +function initTransmitNode(node) +{ + node.collected_images = []; + + node.onExecuted = (output)=> { + if (output?.collected_images && editor.channel) { + editor.channel.port1.postMessage( {images:output.collected_images}) + } + } + + return; +} + + + function openOrFocusEditor() { if (!editor.window || editor.window.closed) { if (getSignal('clientPage')) { diff --git a/web/page/bspaint.js b/web/page/bspaint.js index a91923d..23bbd32 100644 --- a/web/page/bspaint.js +++ b/web/page/bspaint.js @@ -47,8 +47,9 @@ var activePic; function setActivePic(newValue) { activePic=newValue; - activePic.bringToFront(); updateLayerList() + if (!activePic) return; + activePic.bringToFront(); } @@ -71,6 +72,15 @@ function setExportPic(pic) { transmitMask(pic.mask.canvas); } +function closePic(pic) { + + pic.element.parentElement.removeChild(pic.element); + if (pic === activePic) { + const newActive = document.querySelector("#workspace .pic"); + setActivePic(newActive.pic); + } +} + var lastUsedMaskColor = "#402040"; class Layer { @@ -121,13 +131,18 @@ function createDrawArea(canvas = blankCanvas()) { const ctx=canvas.getContext("2d"); const eventOverlay = document.createElement("div"); const sidebar = document.createElement("div"); + const closeButton = document.createElement("div"); + sidebar.className = "sidebutton"; + closeButton.className = "closebutton"; + element.className="pic"; eventOverlay.className="eventoverlay fillparent"; element.appendChild(sidebar); element.appendChild(canvas); element.appendChild(eventOverlay); + element.appendChild(closeButton); canvas.ctx=ctx; const activeOperationCanvas = document.createElement("canvas"); @@ -272,6 +287,7 @@ function createDrawArea(canvas = blankCanvas()) { } eventOverlay.pic = result; sidebar.addEventListener("mousedown",_=> setExportPic(result)) + closeButton.addEventListener("click",_=> closePic(result)) result.setTransform(); setActivePic(result) @@ -361,6 +377,7 @@ function addNewLayer(image) { console.log("new layer", layer) console.log(layer.canvas.width, layer.canvas.height) pic.layers.push(layer); + pic.activeLayer=layer; updateLayerList(); pic.updateVisualRepresentation(); } @@ -683,7 +700,7 @@ function poulateLayerControl() { const content = $(`
- @@ -780,10 +797,12 @@ function updateLayerList() { const layer_control=document.querySelector("#layer_control") const layer_list =layer_control.querySelector(".layer_list") - const newControls = activePic.layers.map(makeLayerWidget); - while(layer_list.firstChild) layer_list.removeChild(layer_list.firstChild) + if (!activePic) return; + + const newControls = activePic.layers.map(makeLayerWidget); + newControls.reverse().forEach(element=>layer_list.appendChild(element)) $(".layer-attributes").toggleClass("mask", activePic.activeLayer.mask) diff --git a/web/page/main.js b/web/page/main.js index 62fb956..86d4d3f 100644 --- a/web/page/main.js +++ b/web/page/main.js @@ -146,7 +146,10 @@ window.addEventListener('message', (event) => { portToMain.onmessage = (messageEvent) => { console.log(messageEvent) if (messageEvent.data instanceof Object) { - loadImagefromURL(messageEvent.data.images[0]); + const images=messageEvent.data.images[0]; + if (images?.length > 0) { + loadImagefromURL(messageEvent.data.images[0]); + } } else console.log('Message received from main page:', messageEvent.data); }; } diff --git a/web/page/style.css b/web/page/style.css index 9bb1a17..dddb424 100644 --- a/web/page/style.css +++ b/web/page/style.css @@ -6,7 +6,7 @@ body { --left-panel-width : 80px; --right-panel-width : 210px; background:#f8fcff; - + --label : "image"; } canvas { display: block; @@ -114,6 +114,29 @@ canvas { transform: translate(var(--translateX),var(--translateY)) scale(var(--scalefactor) ) } +.pic .closebutton { + position: absolute; + top: -20px; + left: 3px; + width: 16px; + height: 16px; + background: #8008; + border-radius: 16px; + box-sizing: border-box; + border: 1px solid black; + cursor: default; +} + +.pic .closebutton:hover { + background: #f33f; +} + +.pic .closebutton:active { + background: #f00f; + border: 3px solid black; + +} + input[type="color"] { width:48px; height:32px; @@ -155,7 +178,7 @@ input[type="color"] { } .pic>.eventoverlay::before { - content: "label"; + content: var(--label); position: absolute; height: 19px; display: inline-block; @@ -163,7 +186,7 @@ input[type="color"] { transform-origin: left; background-color: palegoldenrod; border-radius: 0 11px 0 0; - padding-left: 8px; + padding-left: 32px; padding-right: 17px; box-shadow: 0px 0px 0px 2px; font-family: sans-serif;