diff --git a/js/index.js b/js/index.js index 2d579c7..28d1acd 100644 --- a/js/index.js +++ b/js/index.js @@ -264,6 +264,7 @@ async function testHostConnection() { setConnectionStatus("online"); // Load data as soon as connection is first stablished if (firstTimeOnline) { + getConfig(); getStyles(); getSamplers(); getUpscalers(); @@ -688,6 +689,65 @@ function changeModel() { }); } +async function getConfig() { + var url = document.getElementById("host").value + "/sdapi/v1/options"; + + let message = + "The following options for the AUTOMATIC1111's webui are not recommended to use with this software:"; + + try { + const response = await fetch(url); + + const data = await response.json(); + + let wrong = false; + + // Check if img2img color correction is disabled and inpainting mask weight is set to one + // TODO: API Seems bugged for retrieving inpainting mask weight - returning 0 for all values different than 1.0 + if (data.img2img_color_correction) { + message += "\n - Image to Image Color Correction: false recommended"; + wrong = true; + } + + if (data.inpainting_mask_weight < 1.0) { + message += `\n - Inpainting Conditioning Mask Strength: 1.0 recommended`; + wrong = true; + } + + message += "\n\nShould these values be changed to the recommended ones?"; + + if (!wrong) { + console.info("[index] WebUI Settings set as recommended."); + return; + } + + console.info( + "[index] WebUI Settings not set as recommended. Prompting for changing settings automatically." + ); + + if (!confirm(message)) return; + + try { + await fetch(url, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + img2img_color_correction: false, + inpainting_mask_weight: 1.0, + }), + }); + } catch (e) { + console.warn("[index] Failed to fetch WebUI Configuration"); + console.warn(e); + } + } catch (e) { + console.warn("[index] Failed to fetch WebUI Configuration"); + console.warn(e); + } +} + async function getStyles() { /** @type {HTMLSelectElement} */ var styleSelect = document.getElementById("styleSelect"); diff --git a/js/initalize/layers.populate.js b/js/initalize/layers.populate.js index 9263dfe..b867f0f 100644 --- a/js/initalize/layers.populate.js +++ b/js/initalize/layers.populate.js @@ -59,8 +59,14 @@ mouse.registerContext( "world", (evn, ctx) => { // Fix because in chrome layerX and layerY simply doesnt work - /** @type {HTMLDivElement} */ - const target = evn.target; + ctx.coords.prev.x = ctx.coords.pos.x; + ctx.coords.prev.y = ctx.coords.pos.y; + + if (evn.layerX !== evn.clientX || evn.layerY !== evn.clientY) { + ctx.coords.pos.x = evn.layerX; + ctx.coords.pos.y = evn.layerY; + return; + } // Get element bounding rect const bb = imageCollection.element.getBoundingClientRect(); @@ -78,10 +84,8 @@ mouse.registerContext( const layerY = ((y - bb.top) / bb.height) * h; // - ctx.coords.prev.x = ctx.coords.pos.x; - ctx.coords.prev.y = ctx.coords.pos.y; - ctx.coords.pos.x = layerX; - ctx.coords.pos.y = layerY; + ctx.coords.pos.x = Math.round(layerX); + ctx.coords.pos.y = Math.round(layerY); }, {target: imageCollection.inputElement} ); diff --git a/js/initalize/ui.populate.js b/js/initalize/ui.populate.js index eed8070..ba8b43c 100644 --- a/js/initalize/ui.populate.js +++ b/js/initalize/ui.populate.js @@ -1,6 +1,28 @@ -document.querySelectorAll(".floating-window").forEach((w) => { - makeDraggable(w); -}); +document.querySelectorAll(".floating-window").forEach( + /** + * Runs for each floating window + * + * @param {HTMLDivElement} w + */ + (w) => { + makeDraggable(w); + w.addEventListener( + "wheel", + (e) => { + e.stopPropagation(); + }, + {passive: false} + ); + + w.addEventListener( + "click", + (e) => { + e.stopPropagation(); + }, + {passive: false} + ); + } +); var coll = document.getElementsByClassName("collapsible"); for (var i = 0; i < coll.length; i++) { diff --git a/js/lib/ui.js b/js/lib/ui.js index 485f319..0fb0373 100644 --- a/js/lib/ui.js +++ b/js/lib/ui.js @@ -168,14 +168,17 @@ function createSlider(name, wrapper, options = {}) { mouse.listen.window.btn.left.ondrag.on((evn) => { if (evn.initialTarget === overEl) { - phantomRange.value = Math.max( + const newv = Math.max( options.min, Math.min( options.max, - (evn.evn.layerX / wrapper.offsetWidth) * (options.max - options.min) + + ((evn.evn.clientX - evn.initialTarget.getBoundingClientRect().left) / + wrapper.offsetWidth) * + (options.max - options.min) + options.min ) ); + phantomRange.value = newv; setValue(parseFloat(phantomRange.value)); } }); diff --git a/js/lib/util.js b/js/lib/util.js index bdd0a63..0f80380 100644 --- a/js/lib/util.js +++ b/js/lib/util.js @@ -180,14 +180,15 @@ function getBoundingBox(cx, cy, w, h, gridSnap = null, offset = 0) { offs.x = snap(cx, offset, gridSnap); offs.y = snap(cy, offset, gridSnap); } - box.x = offs.x + cx; - box.y = offs.y + cy; + + box.x = Math.round(offs.x + cx); + box.y = Math.round(offs.y + cy); return { x: Math.floor(box.x - w / 2), y: Math.floor(box.y - h / 2), - w, - h, + w: Math.round(w), + h: Math.round(h), }; } diff --git a/js/ui/tool/colorbrush.js b/js/ui/tool/colorbrush.js index 2cbdfd7..dfaa640 100644 --- a/js/ui/tool/colorbrush.js +++ b/js/ui/tool/colorbrush.js @@ -37,7 +37,7 @@ const _color_brush_erase_callback = (evn, state, ctx) => { const colorBrushTool = () => toolbar.registerTool( - "res/icons/brush.svg", + "/res/icons/brush.svg", "Color Brush", (state, opt) => { // Draw new cursor immediately diff --git a/js/ui/tool/dream.js b/js/ui/tool/dream.js index e19fecd..b466e33 100644 --- a/js/ui/tool/dream.js +++ b/js/ui/tool/dream.js @@ -806,9 +806,13 @@ const _reticle_draw = (evn, state, tool, style = {}) => { const _dream_onwheel = (evn, state) => { if (!evn.evn.ctrlKey) { - const v = - state.cursorSize - - Math.floor(state.config.cursorSizeScrollSpeed * evn.delta); + // Seems mouse wheel scroll is very different between different browsers. + // Will use scroll as just an event to go to the next cursor snap position instead. + // + // TODO: Someone that has a smooth scrolling mouse should verify if this works with them. + + const v = state.cursorSize - 128 * (evn.delta / Math.abs(evn.delta)); + state.cursorSize = state.setCursorSize(v + snap(v, 0, 128)); state.mousemovecb(evn); } @@ -819,7 +823,7 @@ const _dream_onwheel = (evn, state) => { */ const dreamTool = () => toolbar.registerTool( - "res/icons/image-plus.svg", + "/res/icons/image-plus.svg", "Dream", (state, opt) => { // Draw new cursor immediately @@ -940,7 +944,7 @@ const dreamTool = () => { min: 0, max: 64, - step: 5, + step: 4, textStep: 1, } ).slider; @@ -959,7 +963,7 @@ const dreamTool = () => const img2imgTool = () => toolbar.registerTool( - "res/icons/image.svg", + "/res/icons/image.svg", "Img2Img", (state, opt) => { // Draw new cursor immediately diff --git a/js/ui/tool/interrogate.js b/js/ui/tool/interrogate.js index 10c8e98..5e97375 100644 --- a/js/ui/tool/interrogate.js +++ b/js/ui/tool/interrogate.js @@ -1,6 +1,6 @@ const interrogateTool = () => toolbar.registerTool( - "res/icons/microscope.svg", + "/res/icons/microscope.svg", "Interrogate", (state, opt) => { // Draw new cursor immediately @@ -48,8 +48,16 @@ const interrogateTool = () => reticleStyle: "#AFAF", }); }; + + state.redraw = () => { + state.mousemovecb({ + x: mouse.coords.world.pos.x, + y: mouse.coords.world.pos.y, + }); + }; + state.wheelcb = (evn) => { - _interrogate_onwheel(evn, state); + _dream_onwheel(evn, state); }; state.interrogatecb = (evn) => { @@ -91,20 +99,6 @@ const interrogateTool = () => } ); -/** - * Generic wheel handler - */ - -const _interrogate_onwheel = (evn, state) => { - if (!evn.evn.ctrlKey) { - const v = - state.cursorSize - - Math.floor(state.config.cursorSizeScrollSpeed * evn.delta); - state.cursorSize = state.setCursorSize(v + snap(v, 0, 128)); - state.mousemovecb(evn); - } -}; - const interrogate_callback = async (evn, state) => { const bb = getBoundingBox( evn.x, diff --git a/js/ui/tool/maskbrush.js b/js/ui/tool/maskbrush.js index 90dad73..bf71cfa 100644 --- a/js/ui/tool/maskbrush.js +++ b/js/ui/tool/maskbrush.js @@ -61,7 +61,7 @@ const _mask_brush_erase_callback = (evn, state, opacity = 100) => { const maskBrushTool = () => toolbar.registerTool( - "res/icons/paintbrush.svg", + "/res/icons/paintbrush.svg", "Mask Brush", (state, opt) => { // Draw new cursor immediately diff --git a/js/ui/tool/select.js b/js/ui/tool/select.js index 1ad41fd..97dd684 100644 --- a/js/ui/tool/select.js +++ b/js/ui/tool/select.js @@ -1,6 +1,6 @@ const selectTransformTool = () => toolbar.registerTool( - "res/icons/box-select.svg", + "/res/icons/box-select.svg", "Select Image", (state, opt) => { // Draw new cursor immediately @@ -101,6 +101,10 @@ const selectTransformTool = () => // Selection bounding box object. Has some witchery to deal with handles. const selectionBB = (x1, y1, x2, y2) => { + x1 = Math.round(x1); + y1 = Math.round(y1); + x2 = Math.round(x2); + y2 = Math.round(y2); return { original: { x: Math.min(x1, x2), @@ -213,8 +217,8 @@ const selectTransformTool = () => // Update position if (state.moving) { - state.selected.x = x - state.moving.offset.x; - state.selected.y = y - state.moving.offset.y; + state.selected.x = Math.round(x - state.moving.offset.x); + state.selected.y = Math.round(y - state.moving.offset.y); state.selected.updateOriginal(); } @@ -350,11 +354,13 @@ const selectTransformTool = () => "Image Transform Erase", state.original ); - commands.runCommand( - "drawImage", - "Image Transform Draw", - state.selected - ); + commands.runCommand("drawImage", "Image Transform Draw", { + image: state.selected.image, + x: Math.round(state.selected.x), + y: Math.round(state.selected.y), + w: Math.round(state.selected.w), + h: Math.round(state.selected.h), + }); state.original = null; state.selected = null; diff --git a/js/ui/tool/stamp.js b/js/ui/tool/stamp.js index faf0611..8cf3bc7 100644 --- a/js/ui/tool/stamp.js +++ b/js/ui/tool/stamp.js @@ -1,6 +1,6 @@ const stampTool = () => toolbar.registerTool( - "res/icons/file-up.svg", + "/res/icons/file-up.svg", "Stamp Image", (state, opt) => { state.loaded = true;