diff --git a/css/colors.css b/css/colors.css index 1dba78a..984592d 100644 --- a/css/colors.css +++ b/css/colors.css @@ -2,6 +2,7 @@ --c-primary: #2c3333; --c-hover: hsl(180, 7%, 30%); --c-active: hsl(180, 7%, 25%); + --c-primary-accent: hsl(180, 7%, 40%); --c-secondary: #395b64; --c-accent: #a5c9ca; --c-text: #e7f6f2; diff --git a/css/ui/generic.css b/css/ui/generic.css index b8c4556..deed60d 100644 --- a/css/ui/generic.css +++ b/css/ui/generic.css @@ -30,3 +30,68 @@ .draggable { cursor: move; } + +/* Slider Input */ +div.slider-wrapper { + margin: 5px; +} + +div.slider-wrapper { + position: relative; + height: 20px; + border-radius: 5px; +} + +div.slider-wrapper * { + height: 20px; + border-radius: 5px; + margin: 0; +} + +div.slider-wrapper > * { + position: absolute; + padding: inherit; + width: 100%; + + left: 0; + right: 0; + top: 0; + bottom: 0; + + overflow: hidden; +} + +div.slider-wrapper > div.under { + display: flex; + background-color: var(--c-primary-accent); +} +div.slider-wrapper > div.under > div:first-child { + background-color: var(--c-primary); + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +div.slider-wrapper > div.under > div:last-child { + flex: 1; + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +div.slider-wrapper > div.under > * { + height: 100%; +} + +div.slider-wrapper > div.over { + cursor: pointer; +} + +div.slider-wrapper > input.text { + color: var(--c-text); + + flex: 1; + appearance: textfield; + border: 0px; + + padding-top: 5px; + height: 15px; + text-align: center; + background-color: transparent; +} diff --git a/index.html b/index.html index e3b3ec3..6028b75 100644 --- a/index.html +++ b/index.html @@ -68,66 +68,19 @@ people, person, humans, human, divers, diver, glitch, error, text, watermark, ba value="-1" step="1" />
- -
- -
- -
- -
- -
- -
- -
- -
-
+
+
+
+
- -
+
+ + type="checkbox" + id="cbxSnap" + onchange="changeSnapMode()" + checked="checked" />
diff --git a/js/index.js b/js/index.js index 55b4d97..1c858e1 100644 --- a/js/index.js +++ b/js/index.js @@ -47,62 +47,6 @@ var stableDiffusionData = { // "include_init_images": false // ?????? }; -/** - * Some Utility Functions - */ -function sliderChangeHandlerFactory( - sliderId, - textBoxId, - dataKey, - defaultV, - save = true, - setter = (k, v) => (stableDiffusionData[k] = v), - getter = (k) => stableDiffusionData[k] -) { - return sliderChangeHandlerFactoryEl( - document.getElementById(sliderId), - document.getElementById(textBoxId), - dataKey, - defaultV, - save, - setter, - getter - ); -} - -function sliderChangeHandlerFactoryEl( - sliderEl, - textBoxEl, - dataKey, - defaultV, - save = true, - setter = (k, v) => (stableDiffusionData[k] = v), - getter = (k) => stableDiffusionData[k] -) { - const savedValue = save && localStorage.getItem(dataKey); - - if (savedValue) setter(dataKey, savedValue || defaultV); - - function changeHandler(evn) { - const eventSource = evn && evn.srcElement; - const value = eventSource && Number(eventSource.value); - - if (value) setter(dataKey, value); - - if (!eventSource || eventSource === textBoxEl) - sliderEl.value = getter(dataKey); - setter(dataKey, Number(sliderEl.value)); - textBoxEl.value = getter(dataKey); - - if (save) localStorage.setItem(dataKey, getter(dataKey)); - } - - textBoxEl.onchange = changeHandler; - sliderEl.oninput = changeHandler; - - return changeHandler; -} - // stuff things use var blockNewImages = false; var returnedImages; @@ -175,12 +119,8 @@ function startup() { getUpscalers(); getModels(); drawBackground(); - changeScaleFactor(); changeSampler(); - changeSteps(); - changeCfgScale(); - changeBatchCount(); - changeBatchSize(); + changeSnapMode(); changeMaskBlur(); changeSeed(); changeOverMaskPx(); @@ -542,39 +482,77 @@ function changeSampler() { } } -const changeCfgScale = sliderChangeHandlerFactory( - "cfgScale", - "cfgScaleTxt", +const makeSlider = ( + label, + el, + lsKey, + min, + max, + step, + defaultValue, + valuecb = null +) => { + const local = localStorage.getItem(lsKey); + const def = parseFloat(local === null ? defaultValue : local); + return createSlider(label, el, { + valuecb: + valuecb || + ((v) => { + stableDiffusionData[lsKey] = v; + localStorage.setItem(lsKey, v); + }), + min, + max, + step, + defaultValue: def, + }); +}; + +makeSlider( + "CFG Scale", + document.getElementById("cfgScale"), "cfg_scale", + -1, + 25, + 0.5, 7.0 ); -const changeBatchSize = sliderChangeHandlerFactory( - "batchSize", - "batchSizeText", +makeSlider( + "Batch Size", + document.getElementById("batchSize"), "batch_size", - 2 -); -const changeBatchCount = sliderChangeHandlerFactory( - "batchCount", - "batchCountText", - "n_iter", - 2 -); -const changeScaleFactor = sliderChangeHandlerFactory( - "scaleFactor", - "scaleFactorTxt", - "scaleFactor", + 1, 8, - true, - (k, v) => (scaleFactor = v), - (k) => scaleFactor + 1, + 2 ); -const changeSteps = sliderChangeHandlerFactory( - "steps", - "stepsTxt", - "steps", - 30 +makeSlider( + "Iterations", + document.getElementById("batchCount"), + "n_iter", + 1, + 8, + 1, + 2 ); +makeSlider( + "Scale Factor", + document.getElementById("scaleFactor"), + "scale_factor", + 1, + 16, + 1, + 8, + (v) => { + scaleFactor = v; + } +); + +makeSlider("Steps", document.getElementById("steps"), "steps", 1, 70, 1, 30); + +function changeSnapMode() { + snapToGrid = document.getElementById("cbxSnap").checked; +} function changeMaskBlur() { stableDiffusionData.mask_blur = document.getElementById("maskBlur").value; diff --git a/js/input.js b/js/input.js index 20d4888..ba1ed32 100644 --- a/js/input.js +++ b/js/input.js @@ -3,32 +3,13 @@ const inputConfig = { clickTiming: 500, // Timing window to be considered a click (ms). If longer, turns into a drag dClickTiming: 500, // Timing window to be considered a double click (ms). - keyboardHoldTiming: 100, // Timing window after which to consider holding a key (ms) + keyboardHoldTiming: 1000, // Timing window after which to consider holding a key (ms) }; /** * Mouse input processing */ // Base object generator functions -function _context_coords() { - return { - dragging: { - left: null, - middle: null, - right: null, - }, - - prev: { - x: 0, - y: 0, - }, - - pos: { - x: 0, - y: 0, - }, - }; -} function _mouse_observers() { return { // Simple click handler @@ -46,229 +27,286 @@ function _mouse_observers() { }; } -function _context_observers() { - return { - onwheel: new Observer(), - onmousemove: new Observer(), - left: _mouse_observers(), - middle: _mouse_observers(), - right: _mouse_observers(), - }; -} - const mouse = { - buttons: { - right: null, - left: null, - middle: null, - }, + contexts: [], + buttons: {}, + coords: {}, - // Mouse Actions in Window Coordinates - window: _context_coords(), + listen: {}, - // Mouse Actions in Canvas Coordinates - canvas: _context_coords(), + // Register Context + registerContext: (name, onmove, options = {}) => { + // Options + defaultOpt(options, { + target: null, + buttons: {0: "left", 1: "middle", 2: "right"}, + }); - // Mouse Actions in World Coordinates - world: _context_coords(), + // Context information + const context = { + id: guid(), + name, + onmove, + target: options.target, + buttons: options.buttons, + }; - listen: { - window: _context_observers(), - canvas: _context_observers(), - world: _context_observers(), + // Coordinate information + mouse.coords[name] = { + dragging: {}, + + prev: { + x: 0, + y: 0, + }, + + pos: { + x: 0, + y: 0, + }, + }; + + // Listeners + mouse.listen[name] = { + onwheel: new Observer(), + onmousemove: new Observer(), + }; + + // Button specific items + Object.keys(options.buttons).forEach((index) => { + const button = options.buttons[index]; + mouse.coords[name].dragging[button] = null; + mouse.listen[name][button] = _mouse_observers(); + }); + + // Add to context + context.coords = mouse.coords[name]; + context.listen = mouse.listen[name]; + + // Add to list + mouse.contexts.push(context); + + return context; }, }; -function _mouse_state_snapshot() { - return { - buttons: window.structuredClone(mouse.buttons), - window: window.structuredClone(mouse.window), - canvas: window.structuredClone(mouse.canvas), - world: window.structuredClone(mouse.world), - }; -} - const _double_click_timeout = {}; const _drag_start_timeout = {}; window.onmousedown = (evn) => { - const time = new Date(); + const time = performance.now(); - // Processes for a named button - const onhold = (key) => () => { - if (_double_click_timeout[key]) { - // ondclick event - ["window", "canvas", "world"].forEach((ctx) => - mouse.listen[ctx][key].ondclick.emit({ + if (_double_click_timeout[evn.button]) { + // ondclick event + mouse.contexts.forEach(({target, name, buttons}) => { + if ((!target || target === evn.target) && buttons[evn.button]) + mouse.listen[name][buttons[evn.button]].ondclick.emit({ target: evn.target, buttonId: evn.button, - x: mouse[ctx].pos.x, - y: mouse[ctx].pos.y, - timestamp: new Date(), - }) - ); - } else { - // Start timer - _double_click_timeout[key] = setTimeout( - () => delete _double_click_timeout[key], - inputConfig.dClickTiming - ); - } - - // Set drag start timeout - _drag_start_timeout[key] = setTimeout(() => { - ["window", "canvas", "world"].forEach((ctx) => { - mouse.listen[ctx][key].ondragstart.emit({ - target: evn.target, - buttonId: evn.button, - x: mouse[ctx].pos.x, - y: mouse[ctx].pos.y, - timestamp: new Date(), + x: mouse.coords[name].pos.x, + y: mouse.coords[name].pos.y, + evn, + timestamp: time, }); - if (mouse[ctx].dragging[key]) mouse[ctx].dragging[key].drag = true; + }); + } else { + // Start timer + _double_click_timeout[evn.button] = setTimeout( + () => delete _double_click_timeout[evn.button], + inputConfig.dClickTiming + ); + } - delete _drag_start_timeout[key]; - }); - }, inputConfig.clickTiming); + // Set drag start timeout + _drag_start_timeout[evn.button] = setTimeout(() => { + mouse.contexts.forEach(({target, name, buttons}) => { + const key = buttons[evn.button]; + if ( + (!target || target === evn.target) && + !mouse.coords[name].dragging[key].drag && + key + ) { + mouse.listen[name][key].ondragstart.emit({ + target: evn.target, + buttonId: evn.button, + x: mouse.coords[name].pos.x, + y: mouse.coords[name].pos.y, + evn, + timestamp: time, + }); - ["window", "canvas", "world"].forEach((ctx) => { - mouse.buttons[key] = time; - mouse[ctx].dragging[key] = {target: evn.target}; - Object.assign(mouse[ctx].dragging[key], mouse[ctx].pos); + mouse.coords[name].dragging[key].drag = true; + } + }); + delete _drag_start_timeout[evn.button]; + }, inputConfig.clickTiming); + + mouse.buttons[evn.button] = time; + + mouse.contexts.forEach(({target, name, buttons}) => { + const key = buttons[evn.button]; + if ((!target || target === evn.target) && key) { + mouse.coords[name].dragging[key] = {}; + mouse.coords[name].dragging[key].target = evn.target; + Object.assign(mouse.coords[name].dragging[key], mouse.coords[name].pos); // onpaintstart event - mouse.listen[ctx][key].onpaintstart.emit({ + mouse.listen[name][key].onpaintstart.emit({ target: evn.target, buttonId: evn.button, - x: mouse[ctx].pos.x, - y: mouse[ctx].pos.y, - timestamp: new Date(), + x: mouse.coords[name].pos.x, + y: mouse.coords[name].pos.y, + evn, + timestamp: performance.now(), }); - }); - }; - - // Runs the correct handler - const buttons = [onhold("left"), onhold("middle"), onhold("right")]; - - buttons[evn.button] && buttons[evn.button](); + } + }); }; window.onmouseup = (evn) => { - const time = new Date(); + const time = performance.now(); - // Processes for a named button - const onrelease = (key) => () => { - ["window", "canvas", "world"].forEach((ctx) => { + mouse.contexts.forEach(({target, name, buttons}) => { + const key = buttons[evn.button]; + if ( + (!target || target === evn.target) && + key && + mouse.coords[name].dragging[key] + ) { const start = { - x: mouse[ctx].dragging[key].x, - y: mouse[ctx].dragging[key].y, + x: mouse.coords[name].dragging[key].x, + y: mouse.coords[name].dragging[key].y, }; // onclick event - const dx = mouse[ctx].pos.x - start.x; - const dy = mouse[ctx].pos.y - start.y; + const dx = mouse.coords[name].pos.x - start.x; + const dy = mouse.coords[name].pos.y - start.y; if ( - time.getTime() - mouse.buttons[key].getTime() < - inputConfig.clickTiming && + mouse.buttons[evn.button] && + time - mouse.buttons[evn.button] < inputConfig.clickTiming && dx * dx + dy * dy < inputConfig.clickRadius * inputConfig.clickRadius ) - mouse.listen[ctx][key].onclick.emit({ + mouse.listen[name][key].onclick.emit({ target: evn.target, buttonId: evn.button, - x: mouse[ctx].pos.x, - y: mouse[ctx].pos.y, - timestamp: new Date(), + x: mouse.coords[name].pos.x, + y: mouse.coords[name].pos.y, + evn, + timestamp: performance.now(), }); // onpaintend event - mouse.listen[ctx][key].onpaintend.emit({ + mouse.listen[name][key].onpaintend.emit({ target: evn.target, - initialTarget: mouse[ctx].dragging[key].target, + initialTarget: mouse.coords[name].dragging[key].target, buttonId: evn.button, - x: mouse[ctx].pos.x, - y: mouse[ctx].pos.y, - timestamp: new Date(), + x: mouse.coords[name].pos.x, + y: mouse.coords[name].pos.y, + evn, + timestamp: performance.now(), }); // ondragend event - if (mouse[ctx].dragging[key].drag) - mouse.listen[ctx][key].ondragend.emit({ + if (mouse.coords[name].dragging[key].drag) + mouse.listen[name][key].ondragend.emit({ target: evn.target, - initialTarget: mouse[ctx].dragging[key].target, + initialTarget: mouse.coords[name].dragging[key].target, buttonId: evn.button, - x: mouse[ctx].pos.x, - y: mouse[ctx].pos.y, - timestamp: new Date(), + x: mouse.coords[name].pos.x, + y: mouse.coords[name].pos.y, + evn, + timestamp: performance.now(), }); - mouse[ctx].dragging[key] = null; - }); - - if (_drag_start_timeout[key] !== undefined) { - clearTimeout(_drag_start_timeout[key]); - delete _drag_start_timeout[key]; + mouse.coords[name].dragging[key] = null; } - mouse.buttons[key] = null; - }; + }); - // Runs the correct handler - const buttons = [onrelease("left"), onrelease("middle"), onrelease("right")]; - - buttons[evn.button] && buttons[evn.button](); + if (_drag_start_timeout[evn.button] !== undefined) { + clearTimeout(_drag_start_timeout[evn.button]); + delete _drag_start_timeout[evn.button]; + } + mouse.buttons[evn.button] = null; }; window.onmousemove = (evn) => { - // Set Window Coordinates - Object.assign(mouse.window.prev, mouse.window.pos); - mouse.window.pos = {x: evn.clientX, y: evn.clientY}; + mouse.contexts.forEach((context) => { + const target = context.target; + const name = context.name; - // Set Canvas Coordinates (using overlay canvas as reference) - if (evn.target.id === "overlayCanvas") { - Object.assign(mouse.canvas.prev, mouse.canvas.pos); - mouse.canvas.pos = {x: evn.layerX, y: evn.layerY}; - } + if (!target || target === evn.target) { + context.onmove(evn, context); - // Set World Coordinates (For now the same as canvas coords; Will be useful with infinite canvas) - if (evn.target.id === "overlayCanvas") { - Object.assign(mouse.world.prev, mouse.world.pos); - mouse.world.pos = {x: evn.layerX, y: evn.layerY}; - } + mouse.listen[name].onmousemove.emit({ + target: evn.target, + px: mouse.coords[name].prev.x, + py: mouse.coords[name].prev.y, + x: mouse.coords[name].pos.x, + y: mouse.coords[name].pos.y, + evn, + timestamp: performance.now(), + }); - ["window", "canvas", "world"].forEach((ctx) => { - mouse.listen[ctx].onmousemove.emit({ - target: evn.target, - px: mouse[ctx].prev.x, - py: mouse[ctx].prev.y, - x: mouse[ctx].pos.x, - y: mouse[ctx].pos.y, - timestamp: new Date(), - }); - ["left", "middle", "right"].forEach((key) => { - // ondrag event - if (mouse[ctx].dragging[key] && mouse[ctx].dragging[key].drag) - mouse.listen[ctx][key].ondrag.emit({ - target: evn.target, - initialTarget: mouse[ctx].dragging[key].target, - px: mouse[ctx].prev.x, - py: mouse[ctx].prev.y, - x: mouse[ctx].pos.x, - y: mouse[ctx].pos.y, - timestamp: new Date(), - }); + Object.keys(context.buttons).forEach((index) => { + const key = context.buttons[index]; + // ondragstart event (2) + if (mouse.coords[name].dragging[key]) { + const dx = + mouse.coords[name].pos.x - mouse.coords[name].dragging[key].x; + const dy = + mouse.coords[name].pos.y - mouse.coords[name].dragging[key].y; + if ( + !mouse.coords[name].dragging[key].drag && + dx * dx + dy * dy >= + inputConfig.clickRadius * inputConfig.clickRadius + ) { + mouse.listen[name][key].ondragstart.emit({ + target: evn.target, + buttonId: evn.button, + x: mouse.coords[name].pos.x, + y: mouse.coords[name].pos.y, + evn, + timestamp: performance.now(), + }); - // onpaint event - if (mouse[ctx].dragging[key]) - mouse.listen[ctx][key].onpaint.emit({ - target: evn.target, - initialTarget: mouse[ctx].dragging[key].target, - px: mouse[ctx].prev.x, - py: mouse[ctx].prev.y, - x: mouse[ctx].pos.x, - y: mouse[ctx].pos.y, - timestamp: new Date(), - }); - }); + mouse.coords[name].dragging[key].drag = true; + } + } + + // ondrag event + if ( + mouse.coords[name].dragging[key] && + mouse.coords[name].dragging[key].drag + ) + mouse.listen[name][key].ondrag.emit({ + target: evn.target, + initialTarget: mouse.coords[name].dragging[key].target, + button: index, + px: mouse.coords[name].prev.x, + py: mouse.coords[name].prev.y, + x: mouse.coords[name].pos.x, + y: mouse.coords[name].pos.y, + evn, + timestamp: performance.now(), + }); + + // onpaint event + if (mouse.coords[name].dragging[key]) { + mouse.listen[name][key].onpaint.emit({ + target: evn.target, + initialTarget: mouse.coords[name].dragging[key].target, + button: index, + px: mouse.coords[name].prev.x, + py: mouse.coords[name].prev.y, + x: mouse.coords[name].pos.x, + y: mouse.coords[name].pos.y, + evn, + timestamp: performance.now(), + }); + } + }); + } }); }; @@ -276,22 +314,41 @@ window.addEventListener( "wheel", (evn) => { evn.preventDefault(); - ["window", "canvas", "world"].forEach((ctx) => { - mouse.listen[ctx].onwheel.emit({ + mouse.contexts.forEach(({name}) => { + mouse.listen[name].onwheel.emit({ target: evn.target, delta: evn.deltaY, deltaX: evn.deltaX, deltaY: evn.deltaY, deltaZ: evn.deltaZ, mode: evn.deltaMode, - x: mouse[ctx].pos.x, - y: mouse[ctx].pos.y, - timestamp: new Date(), + x: mouse.coords[name].pos.x, + y: mouse.coords[name].pos.y, + evn, + timestamp: performance.now(), }); }); }, {passive: false} ); + +mouse.registerContext("window", (evn, ctx) => { + ctx.coords.prev.x = ctx.coords.pos.x; + ctx.coords.prev.y = ctx.coords.pos.y; + ctx.coords.pos.x = evn.clientX; + ctx.coords.pos.y = evn.clientY; +}); + +mouse.registerContext( + "canvas", + (evn, ctx) => { + ctx.coords.prev.x = ctx.coords.pos.x; + ctx.coords.prev.y = ctx.coords.pos.y; + ctx.coords.pos.x = evn.layerX; + ctx.coords.pos.y = evn.layerY; + }, + document.getElementById("overlayCanvas") +); /** * Keyboard input processing */ @@ -342,7 +399,9 @@ const keyboard = { }; window.onkeydown = (evn) => { + // onkeydown event keyboard.listen.onkeydown.emit({ + target: evn.target, code: evn.code, key: evn.key, evn, @@ -354,7 +413,9 @@ window.onkeydown = (evn) => { _hold_to: setTimeout(() => { keyboard.keys[evn.code].held = true; delete keyboard.keys[evn.code]._hold_to; + // onkeyholdstart event keyboard.listen.onkeyholdstart.emit({ + target: evn.target, code: evn.code, key: evn.key, evn, @@ -383,7 +444,9 @@ window.onkeydown = (evn) => { !!callback.alt === evn.altKey && !!callback.shift === evn.shiftKey ) { + // onshortcut event keyboard.listen.onshortcut.emit({ + target: evn.target, code: evn.code, key: evn.key, id: callback.id, @@ -395,19 +458,25 @@ window.onkeydown = (evn) => { }; window.onkeyup = (evn) => { + // onkeyup event keyboard.listen.onkeyup.emit({ + target: evn.target, code: evn.code, key: evn.key, evn, }); if (keyboard.keys[evn.code] && keyboard.keys[evn.code].held) { + // onkeyholdend event keyboard.listen.onkeyholdend.emit({ + target: evn.target, code: evn.code, key: evn.key, evn, }); } else { + // onkeyclick event keyboard.listen.onkeyclick.emit({ + target: evn.target, code: evn.code, key: evn.key, evn, diff --git a/js/settingsbar.js b/js/settingsbar.js index bfb60c3..895eaae 100644 --- a/js/settingsbar.js +++ b/js/settingsbar.js @@ -46,3 +46,113 @@ for (var i = 0; i < coll.length; i++) { } }); } + +/** + * Slider Inputs + */ +function createSlider(name, wrapper, options = {}) { + defaultOpt(options, { + valuecb: null, + min: 0, + max: 1, + step: 0.1, + defaultValue: 0.7, + }); + + let value = options.defaultValue; + + // Use phantom range element for rounding + const phantomRange = document.createElement("input"); + phantomRange.type = "range"; + phantomRange.min = options.min; + phantomRange.max = options.max; + phantomRange.step = options.step; + + // Build slider element + const underEl = document.createElement("div"); + underEl.classList.add("under"); + const textEl = document.createElement("input"); + textEl.type = "text"; + textEl.classList.add("text"); + + const overEl = document.createElement("div"); + overEl.classList.add("over"); + + wrapper.classList.add("slider-wrapper"); + wrapper.appendChild(underEl); + wrapper.appendChild(textEl); + wrapper.appendChild(overEl); + + const bar = document.createElement("div"); + bar.classList.add("slider-bar"); + underEl.appendChild(bar); + underEl.appendChild(document.createElement("div")); + + // Set value + const setValue = (val) => { + phantomRange.value = val; + value = parseFloat(phantomRange.value); + bar.style.width = `${ + wrapper.offsetWidth * + ((value - options.min) / (options.max - options.min)) + }px`; + textEl.value = `${name}: ${value}`; + options.valuecb && options.valuecb(value); + }; + + setValue(options.defaultValue); + + // Events + textEl.addEventListener("blur", () => { + overEl.style.pointerEvents = "auto"; + textEl.value = `${name}: ${value}`; + }); + textEl.addEventListener("focus", () => { + textEl.value = value; + }); + + textEl.addEventListener("change", () => { + try { + if (Number.isNaN(parseFloat(textEl.value))) setValue(value); + else setValue(parseFloat(textEl.value)); + } catch (e) {} + }); + + keyboard.listen.onkeyclick.on((evn) => { + if (evn.target === textEl && evn.code === "Enter") { + textEl.blur(); + } + }); + + mouse.listen.window.left.onclick.on((evn) => { + if (evn.target === overEl) { + overEl.style.pointerEvents = "none"; + textEl.select(); + } + }); + + mouse.listen.window.left.ondrag.on((evn) => { + if (evn.target === overEl) { + setValue( + Math.max( + options.min, + Math.min( + options.max, + (evn.evn.layerX / wrapper.offsetWidth) * + (options.max - options.min) + + options.min + ) + ) + ); + } + }); + + return { + set value(val) { + setValue(val); + }, + get value() { + return value; + }, + }; +} diff --git a/js/ui/toolbar.js b/js/ui/toolbar.js index 59a3621..d2817f5 100644 --- a/js/ui/toolbar.js +++ b/js/ui/toolbar.js @@ -135,42 +135,22 @@ const _toolbar_input = { }, slider: (state, dataKey, text, min = 0, max = 1, step = 0.1) => { - const slider = document.createElement("input"); - slider.type = "range"; - slider.max = max; - slider.step = step; - slider.min = min; - slider.value = state[dataKey]; + const slider = document.createElement("div"); - const textEl = document.createElement("input"); - textEl.type = "number"; - textEl.value = state[dataKey]; - - console.log(state[dataKey]); - - sliderChangeHandlerFactoryEl( - slider, - textEl, - dataKey, - state[dataKey], - false, - (k, v) => (state[dataKey] = v), - (k) => state[dataKey] - ); - - const label = document.createElement("label"); - label.appendChild(new Text(text)); - label.appendChild(textEl); - label.appendChild(slider); + const value = createSlider(text, slider, { + min, + max, + step, + valuecb: (v) => { + state[dataKey] = v; + }, + }); return { slider, - text: textEl, - label, setValue(v) { - slider.value = v; - textEl.value = slider.value; - return parseInt(slider.value); + value.value = v; + return value.value; }, }; }, @@ -206,7 +186,10 @@ tools.dream = toolbar.registerTool( (state, opt) => { // Draw new cursor immediately ovCtx.clearRect(0, 0, ovCanvas.width, ovCanvas.height); - state.mousemovecb({...mouse.canvas.pos, target: {id: "overlayCanvas"}}); + state.mousemovecb({ + ...mouse.coords.canvas.pos, + target: {id: "overlayCanvas"}, + }); // Start Listeners mouse.listen.canvas.onmousemove.on(state.mousemovecb); @@ -250,7 +233,10 @@ tools.img2img = toolbar.registerTool( (state, opt) => { // Draw new cursor immediately ovCtx.clearRect(0, 0, ovCanvas.width, ovCanvas.height); - state.mousemovecb({...mouse.canvas.pos, target: {id: "overlayCanvas"}}); + state.mousemovecb({ + ...mouse.coords.canvas.pos, + target: {id: "overlayCanvas"}, + }); // Start Listeners mouse.listen.canvas.onmousemove.on(state.mousemovecb); @@ -326,17 +312,17 @@ tools.img2img = toolbar.registerTool( ).label; // Denoising Strength Slider - state.ctxmenu.denoisingStrengthLabel = _toolbar_input.slider( + state.ctxmenu.denoisingStrengthSlider = _toolbar_input.slider( state, "denoisingStrength", "Denoising Strength", 0, 1, 0.05 - ).label; + ).slider; // Use Border Mask Checkbox - state.ctxmenu.useBorderMaskLabel = _toolbar_input.checkbox( + state.ctxmenu.useBorderMaskSlider = _toolbar_input.checkbox( state, "useBorderMask", "Use Border Mask" @@ -349,16 +335,16 @@ tools.img2img = toolbar.registerTool( 0, 128, 1 - ).label; + ).slider; } menu.appendChild(state.ctxmenu.snapToGridLabel); menu.appendChild(document.createElement("br")); - menu.appendChild(state.ctxmenu.denoisingStrengthLabel); + menu.appendChild(state.ctxmenu.denoisingStrengthSlider); menu.appendChild(document.createElement("br")); menu.appendChild(state.ctxmenu.useBorderMaskLabel); menu.appendChild(document.createElement("br")); - menu.appendChild(state.ctxmenu.borderMaskSize); + menu.appendChild(state.ctxmenu.borderMaskSlider); }, shortcut: "I", } @@ -378,7 +364,7 @@ tools.maskbrush = toolbar.registerTool( (state, opt) => { // Draw new cursor immediately ovCtx.clearRect(0, 0, ovCanvas.width, ovCanvas.height); - state.movecb({...mouse.canvas.pos, target: {id: "overlayCanvas"}}); + state.movecb({...mouse.coords.canvas.pos, target: {id: "overlayCanvas"}}); // Start Listeners mouse.listen.canvas.onmousemove.on(state.movecb); @@ -443,11 +429,11 @@ tools.maskbrush = toolbar.registerTool( state.config.maxBrushSize, 1 ); - state.ctxmenu.brushSizeLabel = brushSizeSlider.label; + state.ctxmenu.brushSizeSlider = brushSizeSlider.slider; state.setBrushSize = brushSizeSlider.setValue; } - menu.appendChild(state.ctxmenu.brushSizeLabel); + menu.appendChild(state.ctxmenu.brushSizeSlider); }, shortcut: "M", } diff --git a/js/util.js b/js/util.js index d16e67c..0de261b 100644 --- a/js/util.js +++ b/js/util.js @@ -42,6 +42,16 @@ const guid = (size = 3) => { return id; }; +/** + * Default option set + */ + +function defaultOpt(options, defaults) { + Object.keys(defaults).forEach((key) => { + if (options[key] === undefined) options[key] = defaults[key]; + }); +} + /** * Bounding box Calculation */