From bd94f51526512f9a58fa2e458f8f11d93ab95e86 Mon Sep 17 00:00:00 2001 From: ribawaja Date: Mon, 6 Feb 2023 23:26:55 -0500 Subject: [PATCH 1/4] Add ability to mark images --- js/ui/tool/dream.js | 136 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 116 insertions(+), 20 deletions(-) diff --git a/js/ui/tool/dream.js b/js/ui/tool/dream.js index 154193c..30b18fe 100644 --- a/js/ui/tool/dream.js +++ b/js/ui/tool/dream.js @@ -343,6 +343,7 @@ const _generate = async (endpoint, request, bb, options = {}) => { /** @type {Array} */ const images = [null]; const seeds = [-1]; + const markedImages=[null]; //A sparse array of booleans indicating which images have been marked, by index /** @type {HTMLDivElement} */ let imageSelectMenu = null; // Layer for the images @@ -467,28 +468,47 @@ const _generate = async (endpoint, request, bb, options = {}) => { at--; if (at < 0) at = images.length - 1; - imageindextxt.textContent = `${at}/${images.length - 1}`; - var seed = seeds[at]; - seedbtn.title = "Use seed " + seed; - redraw(); + activateImgAt(at); }; + const prevImgEvent = (evn) => { + if (evn.shiftKey) { + prevMarkedImg(); + } else { + prevImg(); + } + } + const nextImg = () => { at++; if (at >= images.length) at = 0; highestNavigatedImageIndex = Math.max(at, highestNavigatedImageIndex); - imageindextxt.textContent = `${at}/${images.length - 1}`; - var seed = seeds[at]; - seedbtn.title = "Use seed " + seed; - redraw(); - + activateImgAt(at); + if (needMoreGenerations() && !isGenerationPending()) { makeMore(); } }; + const nextImgEvent = (evn) => { + if (evn.shiftKey) { + nextMarkedImg(); + } else { + nextImg(); + } + } + + const activateImgAt = (at) => { + updateImageIndexText(); + var seed = seeds[at]; + seedbtn.title = "Use seed " + seed; + redraw(); + } + + + const applyImg = async () => { if (!images[at]) return; @@ -551,14 +571,79 @@ const _generate = async (endpoint, request, bb, options = {}) => { if (!images[at]) return; images.splice(at, 1); seeds.splice(at, 1); + markedImages.splice(at,1); if (at > images.length - 1) prevImg(); if (images.length - 1 === 0) discardImg(); - imageindextxt.textContent = `${at}/${images.length - 1}`; + updateImageIndexText(); var seed = seeds[at]; seedbtn.title = "Use seed " + seed; redraw(); }; + const toggleMarkedImg = async () => { + markedImages[at] = markedImages[at] == true ? null : true; + activateImgAt(at); //redraw just to update caption + }; + + const nextMarkedImg = () => { + var nextIndex = getNextMarkedImage(at); + if (nextIndex == null) { + //If no next marked image, and we're not currently on a marked image, then return the last marked image in the list, if any, rather than doing nothing + if (markedImages[at] == true) { + return; + } else { + nextIndex = getPrevMarkedImage(at); + if (nextIndex == null) { + return; + } + } + } + at = nextIndex; + activateImgAt(at); + } + + const prevMarkedImg = () => { + var nextIndex = getPrevMarkedImage(at); + if (nextIndex == null) { + //If no previous marked image, and we're not currently on a marked image, then return the next image in the list, if any, rather than doing nothing + if (markedImages[at] == true) { + return; + } else { + nextIndex = getNextMarkedImage(at); + if (nextIndex == null) { + return; + } + } + } + at = nextIndex; + activateImgAt(at); + } + + const getNextMarkedImage = (at) => { + for (let i = at+1; i < markedImages.length; i++) { + if (markedImages[i] != null) { + return i; + } + } + return null; + + }; + + const getPrevMarkedImage = (at) => { + for (let i = at-1; i >= 0; --i) { + if (markedImages[i] != null) { + return i; + } + } + return null; + }; + + const updateImageIndexText = () => { + var markedImageIndicator = markedImages[at] == true ? "*" : ""; + imageindextxt.textContent = `${markedImageIndicator}${at}/${images.length - 1}`; + } + + const makeMore = async () => { const moreQ = await waitQueue(); try { @@ -573,7 +658,7 @@ const _generate = async (endpoint, request, bb, options = {}) => { dreamData = await _dream(endpoint, requestCopy); images.push(...dreamData.images); seeds.push(...dreamData.seeds); - imageindextxt.textContent = `${at}/${images.length - 1}`; + updateImageIndexText(); } catch (e) { if (alertCount < 2) { alert( @@ -641,13 +726,16 @@ const _generate = async (endpoint, request, bb, options = {}) => { case "-": removeImg(); break; + case "*": + toggleMarkedImg(); + default: switch (evn.code) { case "ArrowRight": - nextImg(); + nextImgEvent(evn.evn); break; case "ArrowLeft": - prevImg(); + prevImgEvent(evn.evn); break; case "Enter": applyImg(); @@ -729,8 +817,10 @@ const _generate = async (endpoint, request, bb, options = {}) => { const onwheelhandler = mouse.listen.world.onwheel.on( (evn, state) => { if (!state.dream_processed && bb.contains(evn.x, evn.y)) { - if (evn.delta < 0) nextImg(); - else prevImg(); + + if (evn.delta < 0) { + nextImgEvent(evn.evn); + } else prevImgEvent(evn.evn); state.dream_processed = true; } }, @@ -765,25 +855,25 @@ const _generate = async (endpoint, request, bb, options = {}) => { imageSelectMenu = makeElement("div", bb.x, bb.y + bb.h); const imageindextxt = document.createElement("button"); - imageindextxt.textContent = `${at}/${images.length - 1}`; + updateImageIndexText(); + imageindextxt.addEventListener("click", () => { at = 0; - - imageindextxt.textContent = `${at}/${images.length - 1}`; + updateImageIndexText(); redraw(); }); const backbtn = document.createElement("button"); backbtn.textContent = "<"; backbtn.title = "Previous Image"; - backbtn.addEventListener("click", prevImg); + backbtn.addEventListener("click", prevImgEvent); imageSelectMenu.appendChild(backbtn); imageSelectMenu.appendChild(imageindextxt); const nextbtn = document.createElement("button"); nextbtn.textContent = ">"; nextbtn.title = "Next Image"; - nextbtn.addEventListener("click", nextImg); + nextbtn.addEventListener("click", nextImgEvent); imageSelectMenu.appendChild(nextbtn); const morebtn = document.createElement("button"); @@ -846,6 +936,12 @@ const _generate = async (endpoint, request, bb, options = {}) => { }); imageSelectMenu.appendChild(seedbtn); + const toggleMarkedButton = document.createElement("button"); + toggleMarkedButton.textContent = "*"; + toggleMarkedButton.title = "Mark/Unmark"; + toggleMarkedButton.addEventListener("click", toggleMarkedImg); + imageSelectMenu.appendChild(toggleMarkedButton); + nextQueue(initialQ); //Start the next batch after the initial generation From fe0095421adfd6c6513638c1c3288dad25392116 Mon Sep 17 00:00:00 2001 From: Victor Seiji Hariki Date: Sun, 19 Feb 2023 10:14:38 -0300 Subject: [PATCH 2/4] fixes #195 Signed-off-by: Victor Seiji Hariki --- js/lib/toolbar.js | 26 ++++++++++++++++++++++++-- js/ui/tool/colorbrush.js | 4 ++++ js/ui/tool/dream.js | 21 +++++++++++++++++++++ js/ui/tool/interrogate.js | 2 ++ js/ui/tool/maskbrush.js | 3 +++ js/ui/tool/select.js | 4 ++++ js/ui/tool/stamp.js | 19 +++++++++++++------ 7 files changed, 71 insertions(+), 8 deletions(-) diff --git a/js/lib/toolbar.js b/js/lib/toolbar.js index 32d1f56..7569192 100644 --- a/js/lib/toolbar.js +++ b/js/lib/toolbar.js @@ -151,18 +151,24 @@ const toolbar = { * Premade inputs for populating the context menus */ const _toolbar_input = { - checkbox: (state, dataKey, text, classes, cb = null) => { + checkbox: (state, lsKey, dataKey, text, classes, cb = null) => { if (state[dataKey] === undefined) state[dataKey] = false; + const savedValueStr = lsKey && localStorage.getItem(lsKey); + const savedValue = savedValueStr && JSON.parse(savedValueStr); + const checkbox = document.createElement("input"); checkbox.type = "checkbox"; checkbox.classList.add("oo-checkbox", "ui", "inline-icon"); + if (savedValue !== null) state[dataKey] = checkbox.checked = savedValue; + if (typeof classes === "string") classes = [classes]; if (classes) checkbox.classList.add(...classes); checkbox.checked = state[dataKey]; checkbox.onchange = () => { + if (lsKey) localStorage.setItem(lsKey, JSON.stringify(checkbox.checked)); state[dataKey] = checkbox.checked; cb && cb(); }; @@ -185,15 +191,19 @@ const _toolbar_input = { }; }, - slider: (state, dataKey, text, options = {}) => { + slider: (state, lsKey, dataKey, text, options = {}) => { defaultOpt(options, {min: 0, max: 1, step: 0.1, textStep: null, cb: null}); const slider = document.createElement("div"); + const savedValueStr = lsKey && localStorage.getItem(lsKey); + const savedValue = savedValueStr && JSON.parse(savedValueStr); + const value = createSlider(text, slider, { min: options.min, max: options.max, step: options.step, valuecb: (v) => { + if (lsKey) localStorage.setItem(lsKey, JSON.stringify(v)); state[dataKey] = v; options.cb && options.cb(v); }, @@ -201,6 +211,8 @@ const _toolbar_input = { textStep: options.textStep, }); + if (savedValue !== null) value.value = savedValue; + return { slider, rawSlider: value, @@ -213,12 +225,16 @@ const _toolbar_input = { selectlist: ( state, + lsKey, dataKey, text, options = {value, text}, defaultOptionValue, cb = null ) => { + const savedValueStr = lsKey && localStorage.getItem(lsKey); + const savedValue = savedValueStr && JSON.parse(savedValueStr); + const selectlist = document.createElement("select"); selectlist.classList.add("bareselector"); Object.entries(options).forEach((opt) => { @@ -228,7 +244,13 @@ const _toolbar_input = { selectlist.options.add(option); }); selectlist.selectedIndex = defaultOptionValue; + + if (savedValue !== null) + state[dataKey] = selectlist.selectedIndex = savedValue; + selectlist.onchange = () => { + if (lsKey) + localStorage.setItem(lsKey, JSON.stringify(selectlist.selectedIndex)); state[dataKey] = selectlist.selectedIndex; cb && cb(); }; diff --git a/js/ui/tool/colorbrush.js b/js/ui/tool/colorbrush.js index 6855a9e..fb147d1 100644 --- a/js/ui/tool/colorbrush.js +++ b/js/ui/tool/colorbrush.js @@ -373,6 +373,7 @@ const colorBrushTool = () => const array = document.createElement("div"); const affectMaskCheckbox = _toolbar_input.checkbox( state, + "openoutpaint/colorbrush-affectmask", "affectMask", "Affect Mask", "icon-venetian-mask" @@ -384,6 +385,7 @@ const colorBrushTool = () => // Brush size slider const brushSizeSlider = _toolbar_input.slider( state, + "openoutpaint/colorbrush-brushsize", "brushSize", "Brush Size", { @@ -399,6 +401,7 @@ const colorBrushTool = () => // Brush opacity slider const brushOpacitySlider = _toolbar_input.slider( state, + "openoutpaint/colorbrush-brushopacity", "brushOpacity", "Brush Opacity", { @@ -413,6 +416,7 @@ const colorBrushTool = () => // Brush blur slider const brushBlurSlider = _toolbar_input.slider( state, + "openoutpaint/colorbrush-brushblur", "brushBlur", "Brush Blur", { diff --git a/js/ui/tool/dream.js b/js/ui/tool/dream.js index 41c02b0..5547c98 100644 --- a/js/ui/tool/dream.js +++ b/js/ui/tool/dream.js @@ -1600,6 +1600,7 @@ const dreamTool = () => // Cursor Size Slider const cursorSizeSlider = _toolbar_input.slider( state, + "openoutpaint/dream-cursorsize", "cursorSize", "Cursor Size", { @@ -1632,6 +1633,7 @@ const dreamTool = () => // Snap to Grid Checkbox state.ctxmenu.snapToGridLabel = _toolbar_input.checkbox( state, + "openoutpaint/dream-snaptogrid", "snapToGrid", "Snap To Grid", "icon-grid" @@ -1640,6 +1642,7 @@ const dreamTool = () => // Invert Mask Checkbox state.ctxmenu.invertMaskLabel = _toolbar_input.checkbox( state, + "openoutpaint/dream-invertmask", "invertMask", "Invert Mask", ["icon-venetian-mask", "invert-mask-checkbox"], @@ -1651,6 +1654,7 @@ const dreamTool = () => // Keep Masked Content Checkbox state.ctxmenu.keepUnmaskedLabel = _toolbar_input.checkbox( state, + "openoutpaint/dream-keepunmasked", "keepUnmasked", "Keep Unmasked", "icon-pin", @@ -1674,6 +1678,7 @@ const dreamTool = () => // Keep Masked Content Blur Slider state.ctxmenu.keepUnmaskedBlurSlider = _toolbar_input.slider( state, + "openoutpaint/dream-keepunmaskedblur", "keepUnmaskedBlur", "Keep Unmasked Blur", { @@ -1693,6 +1698,7 @@ const dreamTool = () => // outpaint fill type select list state.ctxmenu.outpaintTypeSelect = _toolbar_input.selectlist( state, + "openoutpaint/dream-outpainttype", "outpainting_fill", "Outpaint Type", { @@ -1710,6 +1716,7 @@ const dreamTool = () => // Preserve Brushed Masks Checkbox state.ctxmenu.preserveMasksLabel = _toolbar_input.checkbox( state, + "openoutpaint/dream-preservemasks", "preserveMasks", "Preserve Brushed Masks", "icon-paintbrush" @@ -1718,6 +1725,7 @@ const dreamTool = () => // Overmasking Slider state.ctxmenu.overMaskPxLabel = _toolbar_input.slider( state, + "openoutpaint/dream-overmaskpx", "overMaskPx", "Overmask px", { @@ -1731,6 +1739,7 @@ const dreamTool = () => // Eager generation Slider state.ctxmenu.eagerGenerateCountLabel = _toolbar_input.slider( state, + "openoutpaint/dream-eagergeneratecount", "eagerGenerateCount", "Generate-ahead count", { @@ -2148,6 +2157,7 @@ const img2imgTool = () => // Cursor Size Slider const cursorSizeSlider = _toolbar_input.slider( state, + "openoutpaint/img2img-cursorsize", "cursorSize", "Cursor Size", { @@ -2177,6 +2187,7 @@ const img2imgTool = () => // Snap To Grid Checkbox state.ctxmenu.snapToGridLabel = _toolbar_input.checkbox( state, + "openoutpaint/img2img-snaptogrid", "snapToGrid", "Snap To Grid", "icon-grid" @@ -2185,6 +2196,7 @@ const img2imgTool = () => // Invert Mask Checkbox state.ctxmenu.invertMaskLabel = _toolbar_input.checkbox( state, + "openoutpaint/img2img-invertmask", "invertMask", "Invert Mask", ["icon-venetian-mask", "invert-mask-checkbox"], @@ -2196,6 +2208,7 @@ const img2imgTool = () => // Keep Masked Content Checkbox state.ctxmenu.keepUnmaskedLabel = _toolbar_input.checkbox( state, + "openoutpaint/img2img-keepunmasked", "keepUnmasked", "Keep Unmasked", "icon-pin", @@ -2219,6 +2232,7 @@ const img2imgTool = () => // Keep Masked Content Blur Slider state.ctxmenu.keepUnmaskedBlurSlider = _toolbar_input.slider( state, + "openoutpaint/img2img-unmaskedblur", "keepUnmaskedBlur", "Keep Unmasked Blur", { @@ -2238,6 +2252,7 @@ const img2imgTool = () => // Preserve Brushed Masks Checkbox state.ctxmenu.preserveMasksLabel = _toolbar_input.checkbox( state, + "openoutpaint/img2img-preservemasks", "preserveMasks", "Preserve Brushed Masks", "icon-paintbrush" @@ -2246,6 +2261,7 @@ const img2imgTool = () => // Inpaint Full Resolution Checkbox state.ctxmenu.fullResolutionLabel = _toolbar_input.checkbox( state, + "openoutpaint/img2img-fullresolution", "fullResolution", "Inpaint Full Resolution", "icon-expand" @@ -2254,6 +2270,7 @@ const img2imgTool = () => // Denoising Strength Slider state.ctxmenu.denoisingStrengthSlider = _toolbar_input.slider( state, + "openoutpaint/img2img-denoisingstrength", "denoisingStrength", "Denoising Strength", { @@ -2267,6 +2284,7 @@ const img2imgTool = () => // Border Mask Gradient Checkbox state.ctxmenu.borderMaskGradientCheckbox = _toolbar_input.checkbox( state, + "openoutpaint/img2img-gradient", "gradient", "Border Mask Gradient", "icon-box-select" @@ -2275,6 +2293,7 @@ const img2imgTool = () => // Border Mask Size Slider state.ctxmenu.borderMaskSlider = _toolbar_input.slider( state, + "openoutpaint/img2img-keepbordersize", "keepBorderSize", "Keep Border Size", { @@ -2288,6 +2307,7 @@ const img2imgTool = () => // inpaint fill type select list state.ctxmenu.inpaintTypeSelect = _toolbar_input.selectlist( state, + "openoutpaint/img2img-inpaintingtype", "inpainting_fill", "Inpaint Type", { @@ -2305,6 +2325,7 @@ const img2imgTool = () => // Eager generation Slider state.ctxmenu.eagerGenerateCountLabel = _toolbar_input.slider( state, + "openoutpaint/img2img-eagergeneratecount", "eagerGenerateCount", "Generate-ahead count", { diff --git a/js/ui/tool/interrogate.js b/js/ui/tool/interrogate.js index b7fc403..889d34e 100644 --- a/js/ui/tool/interrogate.js +++ b/js/ui/tool/interrogate.js @@ -80,6 +80,7 @@ const interrogateTool = () => // Cursor Size Slider const cursorSizeSlider = _toolbar_input.slider( state, + "openoutpaint/interrogate-cursorsize", "cursorSize", "Cursor Size", { @@ -96,6 +97,7 @@ const interrogateTool = () => // Snap to Grid Checkbox state.ctxmenu.snapToGridLabel = _toolbar_input.checkbox( state, + "openoutpaint/interrogate-snaptogrid", "snapToGrid", "Snap To Grid", "icon-grid" diff --git a/js/ui/tool/maskbrush.js b/js/ui/tool/maskbrush.js index 3eaef41..080fe76 100644 --- a/js/ui/tool/maskbrush.js +++ b/js/ui/tool/maskbrush.js @@ -186,6 +186,7 @@ const maskBrushTool = () => // Brush size slider const brushSizeSlider = _toolbar_input.slider( state, + "openoutpaint/maskbrush-brushsize", "brushSize", "Brush Size", { @@ -206,6 +207,7 @@ const maskBrushTool = () => // Brush opacity slider const brushOpacitySlider = _toolbar_input.slider( state, + "openoutpaint/maskbrush-brushopacity", "brushOpacity", "Brush Opacity", { @@ -220,6 +222,7 @@ const maskBrushTool = () => // Brush blur slider const brushBlurSlider = _toolbar_input.slider( state, + "openoutpaint/maskbrush-brushblur", "brushBlur", "Brush Blur", { diff --git a/js/ui/tool/select.js b/js/ui/tool/select.js index a86cbd9..401a0ad 100644 --- a/js/ui/tool/select.js +++ b/js/ui/tool/select.js @@ -652,6 +652,7 @@ const selectTransformTool = () => // Snap To Grid Checkbox state.ctxmenu.snapToGridLabel = _toolbar_input.checkbox( state, + "openoutpaint/select-snaptogrid", "snapToGrid", "Snap To Grid", "icon-grid" @@ -660,6 +661,7 @@ const selectTransformTool = () => // Keep Aspect Ratio state.ctxmenu.keepAspectRatioLabel = _toolbar_input.checkbox( state, + "openoutpaint/select-keepaspectratio", "keepAspectRatio", "Keep Aspect Ratio", "icon-maximize" @@ -668,6 +670,7 @@ const selectTransformTool = () => // Use Clipboard const clipboardCheckbox = _toolbar_input.checkbox( state, + "openoutpaint/select-useclipboard", "useClipboard", "Use clipboard", "icon-clipboard-list" @@ -679,6 +682,7 @@ const selectTransformTool = () => // Selection Peek Opacity state.ctxmenu.selectionPeekOpacitySlider = _toolbar_input.slider( state, + "openoutpaint/select-peekopacity", "selectionPeekOpacity", "Peek Opacity", { diff --git a/js/ui/tool/stamp.js b/js/ui/tool/stamp.js index 3e8c40a..13f42ce 100644 --- a/js/ui/tool/stamp.js +++ b/js/ui/tool/stamp.js @@ -495,6 +495,7 @@ const stampTool = () => array.appendChild( _toolbar_input.checkbox( state, + "openoutpaint/stamp-snaptogrid", "snapToGrid", "Snap To Grid", "icon-grid" @@ -515,12 +516,18 @@ const stampTool = () => state.ctxmenu.buttonArray = array; // Scale Slider - const scaleSlider = _toolbar_input.slider(state, "scale", "Scale", { - min: 0.01, - max: 10, - step: 0.1, - textStep: 0.001, - }); + const scaleSlider = _toolbar_input.slider( + state, + null, + "scale", + "Scale", + { + min: 0.01, + max: 10, + step: 0.1, + textStep: 0.001, + } + ); state.ctxmenu.scaleSlider = scaleSlider.slider; state.setScale = scaleSlider.setValue; From 6ec9907d8e5979f42e41738711b10af83c96a770 Mon Sep 17 00:00:00 2001 From: seijihariki Date: Sun, 19 Feb 2023 13:16:34 +0000 Subject: [PATCH 3/4] Fixed resource hashes --- index.html | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/index.html b/index.html index 9cd7461..d393077 100644 --- a/index.html +++ b/index.html @@ -410,7 +410,7 @@ - + - + - + From 0343eeb45242d4520cbbfc7995d90cedeca28f49 Mon Sep 17 00:00:00 2001 From: zero01101 Date: Sat, 25 Feb 2023 14:50:22 +0000 Subject: [PATCH 4/4] Fixed resource hashes --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index d393077..2f8f918 100644 --- a/index.html +++ b/index.html @@ -437,7 +437,7 @@ src="js/ui/tool/generic.js?v=3e678e0" type="text/javascript"> - +