From 12e371a48170d30eaab6f4c40969d9dfb45df854 Mon Sep 17 00:00:00 2001 From: Victor Seiji Hariki Date: Mon, 26 Dec 2022 22:24:26 -0300 Subject: [PATCH 1/7] Unused variable cleanup and new overmask px default Signed-off-by: Victor Seiji Hariki --- js/config.js | 3 +++ js/index.js | 26 -------------------------- js/ui/tool/dream.js | 25 +++++++++++++------------ js/ui/tool/interrogate.js | 3 +-- 4 files changed, 17 insertions(+), 40 deletions(-) diff --git a/js/config.js b/js/config.js index 6120e78..a6f7ba6 100644 --- a/js/config.js +++ b/js/config.js @@ -7,6 +7,9 @@ const config = makeReadOnly( { // Scroll Tick Limit (How much must scroll to reach next tick) wheelTickSize: 50, + + // Endpoint + api: makeReadOnly({path: "/sdapi/v1/"}), }, "config" ); diff --git a/js/index.js b/js/index.js index ace7a55..8c9505d 100644 --- a/js/index.js +++ b/js/index.js @@ -132,35 +132,9 @@ var stableDiffusionData = { }; // stuff things use -let debug = false; -var returnedImages; -var imageIndex = 0; -var tmpImgXYWH = {}; var host = ""; var url = "/sdapi/v1/"; -var endpoint = "txt2img"; -var frameX = 512; -var frameY = 512; -var drawThis = {}; const basePixelCount = 64; //64 px - ALWAYS 64 PX -var snapToGrid = true; -var backupMaskPaintCanvas; //??? -var backupMaskPaintCtx; //...? look i am bad at this -var backupMaskChunk = null; -var backupMaskX = null; -var backupMaskY = null; -var totalImagesReturned; -var overMaskPx = 0; -var drawTargets = []; // is this needed? i only draw the last one anyway... -var dropTargets = []; // uhhh yeah similar to the above but for arbitrary dropped images -var arbitraryImage; -var arbitraryImageData; -var arbitraryImageBitmap; -var arbitraryImageBase64; // seriously js cmon work with me here -var placingArbitraryImage = false; // for when the user has loaded an existing image from their computer -var marchOffset = 0; -var inProgress = false; -var marchCoords = {}; // function startup() { diff --git a/js/ui/tool/dream.js b/js/ui/tool/dream.js index bb3f2dc..4c2ee47 100644 --- a/js/ui/tool/dream.js +++ b/js/ui/tool/dream.js @@ -13,7 +13,7 @@ let generating = false; const _monitorProgress = (bb, oncheck = null) => { const minDelay = 1000; - const apiURL = `${host}${url}progress?skip_current_image=true`; + const apiURL = `${host}${config.api.path}progress?skip_current_image=true`; const expanded = {...bb}; expanded.x--; @@ -84,7 +84,7 @@ const _monitorProgress = (bb, oncheck = null) => { * @returns {Promise} */ const _dream = async (endpoint, request) => { - const apiURL = `${host}${url}${endpoint}`; + const apiURL = `${host}${config.api.path}${endpoint}`; // Debugging is enabled if (global.debug) { @@ -380,7 +380,7 @@ const _generate = async (endpoint, request, bb, options = {}) => { interruptButton.classList.add("dream-stop-btn"); interruptButton.textContent = "Interrupt"; interruptButton.addEventListener("click", () => { - fetch(`${host}${url}interrupt`, {method: "POST"}); + fetch(`${host}${config.api.path}interrupt`, {method: "POST"}); interruptButton.disabled = true; }); const marchingOptions = {}; @@ -400,13 +400,13 @@ const _generate = async (endpoint, request, bb, options = {}) => { if (lastProgress < nextCP && data.progress >= nextCP) { nextCP += options.drawEvery; - fetch(`${host}${url}progress?skip_current_image=false`).then( - async (response) => { - if (stopDrawingStatus) return; - const imagedata = await response.json(); - redraw(imagedata.current_image); - } - ); + fetch( + `${host}${config.api.path}progress?skip_current_image=false` + ).then(async (response) => { + if (stopDrawingStatus) return; + const imagedata = await response.json(); + redraw(imagedata.current_image); + }); } lastProgress = data.progress; }); @@ -1191,7 +1191,7 @@ const dreamTool = () => state.invertMask = false; state.keepUnmasked = true; state.keepUnmaskedBlur = 8; - state.overMaskPx = 0; + state.overMaskPx = 20; state.preserveMasks = false; state.erasePrevCursor = () => @@ -2022,7 +2022,8 @@ const img2imgTool = () => window.onbeforeunload = async () => { // Stop current generation on page close - if (generating) await fetch(`${host}${url}interrupt`, {method: "POST"}); + if (generating) + await fetch(`${host}${config.api.path}interrupt`, {method: "POST"}); }; const sendSeed = (seed) => { diff --git a/js/ui/tool/interrogate.js b/js/ui/tool/interrogate.js index 4224645..2090c03 100644 --- a/js/ui/tool/interrogate.js +++ b/js/ui/tool/interrogate.js @@ -33,7 +33,6 @@ const interrogateTool = () => state.snapToGrid = true; state.invertMask = false; - state.overMaskPx = 0; state.block_res_change = true; state.erasePrevReticle = () => ovLayer.clear(); @@ -163,7 +162,7 @@ const interrogate_callback = async (evn, state) => { * @returns {Promise} */ const _interrogate = async (request) => { - const apiURL = `${host}${url}` + "interrogate"; + const apiURL = `${host}${config.api.path}interrogate`; /** @type {StableDiffusionResponse} */ let data = null; From 84ba327706d757a47a2ffa91671559c898e4ed1b Mon Sep 17 00:00:00 2001 From: Victor Seiji Hariki Date: Tue, 27 Dec 2022 01:04:56 -0300 Subject: [PATCH 2/7] allow pan via LMB drag Signed-off-by: Victor Seiji Hariki --- js/initalize/layers.populate.js | 75 ++++++++++++++++++++++----------- js/ui/tool/colorbrush.js | 14 +++--- js/ui/tool/dream.js | 37 +++++++--------- js/ui/tool/maskbrush.js | 12 +++--- 4 files changed, 76 insertions(+), 62 deletions(-) diff --git a/js/initalize/layers.populate.js b/js/initalize/layers.populate.js index 744b15d..026a2a7 100644 --- a/js/initalize/layers.populate.js +++ b/js/initalize/layers.populate.js @@ -245,12 +245,30 @@ mouse.registerContext( { target: imageCollection.inputElement, validate: (evn) => { - if (!global.hasActiveInput || evn.type === "mousemove") return true; + if ((!global.hasActiveInput && !evn.ctrlKey) || evn.type === "mousemove") + return true; return false; }, } ); +mouse.registerContext( + "camera", + (evn, ctx) => { + ctx.coords.prev.x = ctx.coords.pos.x; + ctx.coords.prev.y = ctx.coords.pos.y; + + // Set coords + ctx.coords.pos.x = evn.x; + ctx.coords.pos.y = evn.y; + }, + { + validate: (evn) => { + return !!evn.ctrlKey; + }, + } +); + // Redraw on active input state change (() => { mouse.listen.window.onany.on((evn) => { @@ -264,32 +282,30 @@ mouse.registerContext( }); })(); -mouse.listen.window.onwheel.on((evn) => { - if (evn.evn.ctrlKey) { - evn.evn.preventDefault(); +mouse.listen.camera.onwheel.on((evn) => { + evn.evn.preventDefault(); - const pcx = viewport.cx; - const pcy = viewport.cy; - if (evn.delta < 0) { - viewport.zoom *= 1 + Math.abs(evn.delta * 0.0002); - } else { - viewport.zoom *= 1 - Math.abs(evn.delta * 0.0002); - } - - viewport.cx = pcx; - viewport.cy = pcy; - - viewport.transform(imageCollection.element); - - toolbar.currentTool.redraw(); + const pcx = viewport.cx; + const pcy = viewport.cy; + if (evn.delta < 0) { + viewport.zoom *= 1 + Math.abs(evn.delta * 0.0002); + } else { + viewport.zoom *= 1 - Math.abs(evn.delta * 0.0002); } + + viewport.cx = pcx; + viewport.cy = pcy; + + viewport.transform(imageCollection.element); + + toolbar.currentTool.redraw(); }); -mouse.listen.window.btn.middle.onpaintstart.on((evn) => { - if (evn.evn.ctrlKey) worldInit = {x: viewport.cx, y: viewport.cy}; -}); +const cameraPaintStart = (evn) => { + worldInit = {x: viewport.cx, y: viewport.cy}; +}; -mouse.listen.window.btn.middle.onpaint.on((evn) => { +const cameraPaint = (evn) => { if (worldInit) { viewport.cx = worldInit.x + (evn.ix - evn.x) / viewport.zoom; viewport.cy = worldInit.y + (evn.iy - evn.y) / viewport.zoom; @@ -315,11 +331,20 @@ mouse.listen.window.btn.middle.onpaint.on((evn) => { debugCtx.arc(viewport.cx, viewport.cy, 5, 0, Math.PI * 2); debugCtx.fill(); } -}); +}; -mouse.listen.window.btn.middle.onpaintend.on((evn) => { +const cameraPaintEnd = (evn) => { worldInit = null; -}); +}; + +mouse.listen.camera.btn.middle.onpaintstart.on(cameraPaintStart); +mouse.listen.camera.btn.left.onpaintstart.on(cameraPaintStart); + +mouse.listen.camera.btn.middle.onpaint.on(cameraPaint); +mouse.listen.camera.btn.left.onpaint.on(cameraPaint); + +mouse.listen.window.btn.middle.onpaintend.on(cameraPaintEnd); +mouse.listen.window.btn.left.onpaintend.on(cameraPaintEnd); window.addEventListener("resize", () => { viewport.transform(imageCollection.element); diff --git a/js/ui/tool/colorbrush.js b/js/ui/tool/colorbrush.js index 32701b3..5786307 100644 --- a/js/ui/tool/colorbrush.js +++ b/js/ui/tool/colorbrush.js @@ -208,14 +208,12 @@ const colorBrushTool = () => }; state.wheelcb = (evn) => { - if (!evn.evn.ctrlKey) { - state.brushSize = state.setBrushSize( - state.brushSize - - Math.floor(state.config.brushScrollSpeed * evn.delta) - ); - uiCtx.clearRect(0, 0, uiCanvas.width, uiCanvas.height); - state.movecb(evn); - } + state.brushSize = state.setBrushSize( + state.brushSize - + Math.floor(state.config.brushScrollSpeed * evn.delta) + ); + uiCtx.clearRect(0, 0, uiCanvas.width, uiCanvas.height); + state.movecb(evn); }; /** diff --git a/js/ui/tool/dream.js b/js/ui/tool/dream.js index 4c2ee47..ada341f 100644 --- a/js/ui/tool/dream.js +++ b/js/ui/tool/dream.js @@ -619,11 +619,7 @@ const _generate = async (endpoint, request, bb, options = {}) => { ); const onmorehandler = mouse.listen.world.btn.middle.onclick.on( (evn, state) => { - if ( - !state.dream_processed && - bb.contains(evn.x, evn.y) && - !evn.evn.ctrlKey - ) { + if (!state.dream_processed && bb.contains(evn.x, evn.y)) { makeMore(); state.dream_processed = true; } @@ -633,7 +629,6 @@ const _generate = async (endpoint, request, bb, options = {}) => { ); const onwheelhandler = mouse.listen.world.onwheel.on( (evn, state) => { - if (evn.evn.ctrlKey) return; if (!state.dream_processed && bb.contains(evn.x, evn.y)) { if (evn.delta < 0) nextImg(); else prevImg(); @@ -1086,26 +1081,24 @@ const dream_img2img_callback = (bb, resolution, state) => { let _dream_wheel_accum = 0; const _dream_onwheel = (evn, state) => { - if (!evn.evn.ctrlKey) { - if (evn.mode !== WheelEvent.DOM_DELTA_PIXEL) { - // We don't really handle non-pixel scrolling - return; - } + if (evn.mode !== WheelEvent.DOM_DELTA_PIXEL) { + // We don't really handle non-pixel scrolling + return; + } - // A simple but (I hope) effective fix for mouse wheel behavior - _dream_wheel_accum += evn.delta; + // A simple but (I hope) effective fix for mouse wheel behavior + _dream_wheel_accum += evn.delta; - if (Math.abs(_dream_wheel_accum) > config.wheelTickSize) { - // Snap to next or previous position - const v = - state.cursorSize - - 128 * (_dream_wheel_accum / Math.abs(_dream_wheel_accum)); + if (Math.abs(_dream_wheel_accum) > config.wheelTickSize) { + // Snap to next or previous position + const v = + state.cursorSize - + 128 * (_dream_wheel_accum / Math.abs(_dream_wheel_accum)); - state.cursorSize = state.setCursorSize(v + snap(v, 0, 128)); - state.mousemovecb(evn); + state.cursorSize = state.setCursorSize(v + snap(v, 0, 128)); + state.mousemovecb(evn); - _dream_wheel_accum = 0; // Zero accumulation - } + _dream_wheel_accum = 0; // Zero accumulation } }; diff --git a/js/ui/tool/maskbrush.js b/js/ui/tool/maskbrush.js index 9649cde..0b68c4b 100644 --- a/js/ui/tool/maskbrush.js +++ b/js/ui/tool/maskbrush.js @@ -167,13 +167,11 @@ const maskBrushTool = () => }; state.wheelcb = (evn) => { - if (!evn.evn.ctrlKey) { - state.brushSize = state.setBrushSize( - state.brushSize - - Math.floor(state.config.brushScrollSpeed * evn.delta) - ); - state.redraw(); - } + state.brushSize = state.setBrushSize( + state.brushSize - + Math.floor(state.config.brushScrollSpeed * evn.delta) + ); + state.redraw(); }; state.drawcb = (evn) => From a47fc3ee2573744f69f1f2368aafe74bf7b0ef51 Mon Sep 17 00:00:00 2001 From: Victor Seiji Hariki Date: Tue, 27 Dec 2022 17:59:45 -0300 Subject: [PATCH 3/7] fix wheel validate() handling Signed-off-by: Victor Seiji Hariki --- js/lib/input.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/lib/input.js b/js/lib/input.js index bf67dfd..aab00b3 100644 --- a/js/lib/input.js +++ b/js/lib/input.js @@ -447,7 +447,7 @@ window.addEventListener( _discard = evn.deltaMode; mouse._contexts.forEach(({name, target, validate}) => { - if (!target || (target === evn.target && (!validate || validate(evn)))) { + if ((!target || target === evn.target) && (!validate || validate(evn))) { mouse.listen[name].onwheel.emit({ target: evn.target, delta: evn.deltaY, From 61da4b9d58d16dc8e7026a4297a860878808fa3f Mon Sep 17 00:00:00 2001 From: Victor Seiji Hariki Date: Tue, 27 Dec 2022 18:05:09 -0300 Subject: [PATCH 4/7] fix some errors/better dragging + evaluate Signed-off-by: Victor Seiji Hariki --- index.html | 8 ++++---- js/lib/input.js | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/index.html b/index.html index d49bd4c..b4d3f43 100644 --- a/index.html +++ b/index.html @@ -306,6 +306,10 @@ + + + + @@ -320,11 +324,7 @@ src="js/initalize/layers.populate.js" type="text/javascript"> - - - - diff --git a/js/lib/input.js b/js/lib/input.js index aab00b3..4a385a1 100644 --- a/js/lib/input.js +++ b/js/lib/input.js @@ -220,6 +220,7 @@ window.addEventListener( const key = buttons[evn.button]; if ( (!target || target === evn.target) && + mouse.coords[name].dragging[key] && !mouse.coords[name].dragging[key].drag && key ) { @@ -273,13 +274,12 @@ window.addEventListener( (evn) => { const time = performance.now(); - mouse._contexts.forEach(({target, name, buttons, validate}) => { + mouse._contexts.forEach(({target, name, buttons}) => { const key = buttons[evn.button]; if ( (!target || target === evn.target) && key && - mouse.coords[name].dragging[key] && - (!validate || validate(evn)) + mouse.coords[name].dragging[key] ) { const start = { x: mouse.coords[name].dragging[key].x, From 44e760f37d5953d56e17d3c16db77f18536c6f08 Mon Sep 17 00:00:00 2001 From: Victor Seiji Hariki Date: Tue, 27 Dec 2022 18:08:06 -0300 Subject: [PATCH 5/7] fix config setup order Signed-off-by: Victor Seiji Hariki --- index.html | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index b4d3f43..34dce50 100644 --- a/index.html +++ b/index.html @@ -306,9 +306,8 @@ - + - @@ -324,6 +323,9 @@ src="js/initalize/layers.populate.js" type="text/javascript"> + + + From 7e6df6819fb9b1f67ca39867da335efe6ae7455b Mon Sep 17 00:00:00 2001 From: Victor Seiji Hariki Date: Tue, 27 Dec 2022 18:38:36 -0300 Subject: [PATCH 6/7] rework zoom to zoom into mouse location Signed-off-by: Victor Seiji Hariki --- js/initalize/layers.populate.js | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/js/initalize/layers.populate.js b/js/initalize/layers.populate.js index 026a2a7..99810e9 100644 --- a/js/initalize/layers.populate.js +++ b/js/initalize/layers.populate.js @@ -285,19 +285,30 @@ mouse.registerContext( mouse.listen.camera.onwheel.on((evn) => { evn.evn.preventDefault(); + // Get cursor world position + const cursorPosition = viewport.viewToCanvas(evn.x, evn.y); + console.debug(cursorPosition); + + // Get viewport center const pcx = viewport.cx; const pcy = viewport.cy; - if (evn.delta < 0) { - viewport.zoom *= 1 + Math.abs(evn.delta * 0.0002); - } else { - viewport.zoom *= 1 - Math.abs(evn.delta * 0.0002); - } + // Apply zoom + viewport.zoom *= 1 - evn.delta * 0.0002; + + // Apply normal zoom (center of viewport) viewport.cx = pcx; viewport.cy = pcy; viewport.transform(imageCollection.element); + // Calculate new viewport center and move + const newCursorPosition = viewport.viewToCanvas(evn.x, evn.y); + viewport.cx = pcx - (newCursorPosition.x - cursorPosition.x); + viewport.cy = pcy - (newCursorPosition.y - cursorPosition.y); + + viewport.transform(imageCollection.element); + toolbar.currentTool.redraw(); }); From b23a9183ea354d1b774b562cadf1d45c271a26b6 Mon Sep 17 00:00:00 2001 From: Victor Seiji Hariki Date: Tue, 27 Dec 2022 18:50:00 -0300 Subject: [PATCH 7/7] Make bg always pixelated Signed-off-by: Victor Seiji Hariki --- css/layers.css | 5 +++++ js/initalize/layers.populate.js | 3 +++ 2 files changed, 8 insertions(+) diff --git a/css/layers.css b/css/layers.css index 6d426c0..a4f2ee7 100644 --- a/css/layers.css +++ b/css/layers.css @@ -63,3 +63,8 @@ image-rendering: pixelated; image-rendering: crisp-edges; } + +canvas.pixelated { + image-rendering: pixelated; + image-rendering: crisp-edges; +} diff --git a/js/initalize/layers.populate.js b/js/initalize/layers.populate.js index 99810e9..0496848 100644 --- a/js/initalize/layers.populate.js +++ b/js/initalize/layers.populate.js @@ -22,6 +22,9 @@ const bgLayer = imageCollection.registerLayer("bg", { name: "Background", category: "background", }); + +bgLayer.canvas.classList.add("pixelated"); + const imgLayer = imageCollection.registerLayer("image", { name: "Image", category: "image",