non-broken version on input-rework

Signed-off-by: Victor Seiji Hariki <victorseijih@gmail.com>

Former-commit-id: 3c337c8cf8d4a65cb2fe0845f6eaf9315eb21ae7
This commit is contained in:
Victor Seiji Hariki 2022-11-24 01:53:14 -03:00
parent 45b267737c
commit 951fbacd6c
8 changed files with 548 additions and 376 deletions

View file

@ -2,6 +2,7 @@
--c-primary: #2c3333; --c-primary: #2c3333;
--c-hover: hsl(180, 7%, 30%); --c-hover: hsl(180, 7%, 30%);
--c-active: hsl(180, 7%, 25%); --c-active: hsl(180, 7%, 25%);
--c-primary-accent: hsl(180, 7%, 40%);
--c-secondary: #395b64; --c-secondary: #395b64;
--c-accent: #a5c9ca; --c-accent: #a5c9ca;
--c-text: #e7f6f2; --c-text: #e7f6f2;

View file

@ -30,3 +30,68 @@
.draggable { .draggable {
cursor: move; 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;
}

View file

@ -68,66 +68,19 @@ people, person, humans, human, divers, diver, glitch, error, text, watermark, ba
value="-1" value="-1"
step="1" /> step="1" />
<br /> <br />
<label for="steps"> <div id="steps"></div>
Steps: <div id="cfgScale"></div>
<input type="number" id="stepsTxt" /> <div id="batchSize"></div>
</label> <div id="batchCount"></div>
<br />
<input type="range" id="steps" name="steps" min="1" max="50" />
<br />
<label for="cfgScale">
CFG scale:
<input type="number" id="cfgScaleTxt" />
</label>
<br />
<input
type="range"
id="cfgScale"
name="cfgScale"
min="-1"
max="25"
step="0.5" />
<br />
<label for="batchSize">
Batch size:
<input type="number" id="batchSizeText" />
</label>
<br />
<input
type="range"
id="batchSize"
name="batchSize"
min="1"
max="8"
step="1" />
<br />
<label for="batchCount">
Batch count:
<input type="number" id="batchCountText" />
</label>
<br />
<input
type="range"
id="batchCount"
name="batchCount"
min="1"
max="8"
step="1" />
<br />
<hr />
</div> </div>
<!-- Unsectioned --> <!-- Unsectioned -->
<label for="scaleFactor"> <div id="scaleFactor"></div>
Scale factor: <label for="cbxSnap">Snap to grid?</label>
<input type="number" id="scaleFactorTxt" />
</label>
<br />
<input <input
type="range" type="checkbox"
id="scaleFactor" id="cbxSnap"
name="scaleFactor" onchange="changeSnapMode()"
min="1" checked="checked" />
max="16" />
<br /> <br />
<label for="cbxHRFix">Auto txt2img HRfix?</label> <label for="cbxHRFix">Auto txt2img HRfix?</label>
<input type="checkbox" id="cbxHRFix" onchange="changeHiResFix()" /> <input type="checkbox" id="cbxHRFix" onchange="changeHiResFix()" />

View file

@ -47,62 +47,6 @@ var stableDiffusionData = {
// "include_init_images": false // ?????? // "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 // stuff things use
var blockNewImages = false; var blockNewImages = false;
var returnedImages; var returnedImages;
@ -175,12 +119,8 @@ function startup() {
getUpscalers(); getUpscalers();
getModels(); getModels();
drawBackground(); drawBackground();
changeScaleFactor();
changeSampler(); changeSampler();
changeSteps(); changeSnapMode();
changeCfgScale();
changeBatchCount();
changeBatchSize();
changeMaskBlur(); changeMaskBlur();
changeSeed(); changeSeed();
changeOverMaskPx(); changeOverMaskPx();
@ -542,39 +482,77 @@ function changeSampler() {
} }
} }
const changeCfgScale = sliderChangeHandlerFactory( const makeSlider = (
"cfgScale", label,
"cfgScaleTxt", 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", "cfg_scale",
-1,
25,
0.5,
7.0 7.0
); );
const changeBatchSize = sliderChangeHandlerFactory( makeSlider(
"batchSize", "Batch Size",
"batchSizeText", document.getElementById("batchSize"),
"batch_size", "batch_size",
2 1,
);
const changeBatchCount = sliderChangeHandlerFactory(
"batchCount",
"batchCountText",
"n_iter",
2
);
const changeScaleFactor = sliderChangeHandlerFactory(
"scaleFactor",
"scaleFactorTxt",
"scaleFactor",
8, 8,
true, 1,
(k, v) => (scaleFactor = v), 2
(k) => scaleFactor
); );
const changeSteps = sliderChangeHandlerFactory( makeSlider(
"steps", "Iterations",
"stepsTxt", document.getElementById("batchCount"),
"steps", "n_iter",
30 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() { function changeMaskBlur() {
stableDiffusionData.mask_blur = document.getElementById("maskBlur").value; stableDiffusionData.mask_blur = document.getElementById("maskBlur").value;

View file

@ -3,32 +3,13 @@ const inputConfig = {
clickTiming: 500, // Timing window to be considered a click (ms). If longer, turns into a drag 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). 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 * Mouse input processing
*/ */
// Base object generator functions // 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() { function _mouse_observers() {
return { return {
// Simple click handler // Simple click handler
@ -46,229 +27,286 @@ function _mouse_observers() {
}; };
} }
function _context_observers() { const mouse = {
return { contexts: [],
buttons: {},
coords: {},
listen: {},
// Register Context
registerContext: (name, onmove, options = {}) => {
// Options
defaultOpt(options, {
target: null,
buttons: {0: "left", 1: "middle", 2: "right"},
});
// Context information
const context = {
id: guid(),
name,
onmove,
target: options.target,
buttons: options.buttons,
};
// Coordinate information
mouse.coords[name] = {
dragging: {},
prev: {
x: 0,
y: 0,
},
pos: {
x: 0,
y: 0,
},
};
// Listeners
mouse.listen[name] = {
onwheel: new Observer(), onwheel: new Observer(),
onmousemove: new Observer(), onmousemove: new Observer(),
left: _mouse_observers(),
middle: _mouse_observers(),
right: _mouse_observers(),
}; };
}
const mouse = { // Button specific items
buttons: { Object.keys(options.buttons).forEach((index) => {
right: null, const button = options.buttons[index];
left: null, mouse.coords[name].dragging[button] = null;
middle: null, mouse.listen[name][button] = _mouse_observers();
}, });
// Mouse Actions in Window Coordinates // Add to context
window: _context_coords(), context.coords = mouse.coords[name];
context.listen = mouse.listen[name];
// Mouse Actions in Canvas Coordinates // Add to list
canvas: _context_coords(), mouse.contexts.push(context);
// Mouse Actions in World Coordinates return context;
world: _context_coords(),
listen: {
window: _context_observers(),
canvas: _context_observers(),
world: _context_observers(),
}, },
}; };
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 _double_click_timeout = {};
const _drag_start_timeout = {}; const _drag_start_timeout = {};
window.onmousedown = (evn) => { window.onmousedown = (evn) => {
const time = new Date(); const time = performance.now();
// Processes for a named button if (_double_click_timeout[evn.button]) {
const onhold = (key) => () => {
if (_double_click_timeout[key]) {
// ondclick event // ondclick event
["window", "canvas", "world"].forEach((ctx) => mouse.contexts.forEach(({target, name, buttons}) => {
mouse.listen[ctx][key].ondclick.emit({ if ((!target || target === evn.target) && buttons[evn.button])
mouse.listen[name][buttons[evn.button]].ondclick.emit({
target: evn.target, target: evn.target,
buttonId: evn.button, buttonId: evn.button,
x: mouse[ctx].pos.x, x: mouse.coords[name].pos.x,
y: mouse[ctx].pos.y, y: mouse.coords[name].pos.y,
timestamp: new Date(), evn,
}) timestamp: time,
); });
});
} else { } else {
// Start timer // Start timer
_double_click_timeout[key] = setTimeout( _double_click_timeout[evn.button] = setTimeout(
() => delete _double_click_timeout[key], () => delete _double_click_timeout[evn.button],
inputConfig.dClickTiming inputConfig.dClickTiming
); );
} }
// Set drag start timeout // Set drag start timeout
_drag_start_timeout[key] = setTimeout(() => { _drag_start_timeout[evn.button] = setTimeout(() => {
["window", "canvas", "world"].forEach((ctx) => { mouse.contexts.forEach(({target, name, buttons}) => {
mouse.listen[ctx][key].ondragstart.emit({ 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, target: evn.target,
buttonId: evn.button, buttonId: evn.button,
x: mouse[ctx].pos.x, x: mouse.coords[name].pos.x,
y: mouse[ctx].pos.y, y: mouse.coords[name].pos.y,
timestamp: new Date(), evn,
timestamp: time,
}); });
if (mouse[ctx].dragging[key]) mouse[ctx].dragging[key].drag = true;
delete _drag_start_timeout[key]; mouse.coords[name].dragging[key].drag = true;
}
}); });
delete _drag_start_timeout[evn.button];
}, inputConfig.clickTiming); }, inputConfig.clickTiming);
["window", "canvas", "world"].forEach((ctx) => { mouse.buttons[evn.button] = time;
mouse.buttons[key] = time;
mouse[ctx].dragging[key] = {target: evn.target}; mouse.contexts.forEach(({target, name, buttons}) => {
Object.assign(mouse[ctx].dragging[key], mouse[ctx].pos); 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 // onpaintstart event
mouse.listen[ctx][key].onpaintstart.emit({ mouse.listen[name][key].onpaintstart.emit({
target: evn.target, target: evn.target,
buttonId: evn.button, buttonId: evn.button,
x: mouse[ctx].pos.x, x: mouse.coords[name].pos.x,
y: mouse[ctx].pos.y, y: mouse.coords[name].pos.y,
timestamp: new Date(), 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) => { window.onmouseup = (evn) => {
const time = new Date(); const time = performance.now();
// Processes for a named button mouse.contexts.forEach(({target, name, buttons}) => {
const onrelease = (key) => () => { const key = buttons[evn.button];
["window", "canvas", "world"].forEach((ctx) => { if (
(!target || target === evn.target) &&
key &&
mouse.coords[name].dragging[key]
) {
const start = { const start = {
x: mouse[ctx].dragging[key].x, x: mouse.coords[name].dragging[key].x,
y: mouse[ctx].dragging[key].y, y: mouse.coords[name].dragging[key].y,
}; };
// onclick event // onclick event
const dx = mouse[ctx].pos.x - start.x; const dx = mouse.coords[name].pos.x - start.x;
const dy = mouse[ctx].pos.y - start.y; const dy = mouse.coords[name].pos.y - start.y;
if ( if (
time.getTime() - mouse.buttons[key].getTime() < mouse.buttons[evn.button] &&
inputConfig.clickTiming && time - mouse.buttons[evn.button] < inputConfig.clickTiming &&
dx * dx + dy * dy < inputConfig.clickRadius * inputConfig.clickRadius dx * dx + dy * dy < inputConfig.clickRadius * inputConfig.clickRadius
) )
mouse.listen[ctx][key].onclick.emit({ mouse.listen[name][key].onclick.emit({
target: evn.target, target: evn.target,
buttonId: evn.button, buttonId: evn.button,
x: mouse[ctx].pos.x, x: mouse.coords[name].pos.x,
y: mouse[ctx].pos.y, y: mouse.coords[name].pos.y,
timestamp: new Date(), evn,
timestamp: performance.now(),
}); });
// onpaintend event // onpaintend event
mouse.listen[ctx][key].onpaintend.emit({ mouse.listen[name][key].onpaintend.emit({
target: evn.target, target: evn.target,
initialTarget: mouse[ctx].dragging[key].target, initialTarget: mouse.coords[name].dragging[key].target,
buttonId: evn.button, buttonId: evn.button,
x: mouse[ctx].pos.x, x: mouse.coords[name].pos.x,
y: mouse[ctx].pos.y, y: mouse.coords[name].pos.y,
timestamp: new Date(), evn,
timestamp: performance.now(),
}); });
// ondragend event // ondragend event
if (mouse[ctx].dragging[key].drag) if (mouse.coords[name].dragging[key].drag)
mouse.listen[ctx][key].ondragend.emit({ mouse.listen[name][key].ondragend.emit({
target: evn.target, target: evn.target,
initialTarget: mouse[ctx].dragging[key].target, initialTarget: mouse.coords[name].dragging[key].target,
buttonId: evn.button, buttonId: evn.button,
x: mouse[ctx].pos.x, x: mouse.coords[name].pos.x,
y: mouse[ctx].pos.y, y: mouse.coords[name].pos.y,
timestamp: new Date(), evn,
timestamp: performance.now(),
}); });
mouse[ctx].dragging[key] = null; mouse.coords[name].dragging[key] = null;
});
if (_drag_start_timeout[key] !== undefined) {
clearTimeout(_drag_start_timeout[key]);
delete _drag_start_timeout[key];
} }
mouse.buttons[key] = null; });
};
// Runs the correct handler if (_drag_start_timeout[evn.button] !== undefined) {
const buttons = [onrelease("left"), onrelease("middle"), onrelease("right")]; clearTimeout(_drag_start_timeout[evn.button]);
delete _drag_start_timeout[evn.button];
buttons[evn.button] && buttons[evn.button](); }
mouse.buttons[evn.button] = null;
}; };
window.onmousemove = (evn) => { window.onmousemove = (evn) => {
// Set Window Coordinates mouse.contexts.forEach((context) => {
Object.assign(mouse.window.prev, mouse.window.pos); const target = context.target;
mouse.window.pos = {x: evn.clientX, y: evn.clientY}; const name = context.name;
// Set Canvas Coordinates (using overlay canvas as reference) if (!target || target === evn.target) {
if (evn.target.id === "overlayCanvas") { context.onmove(evn, context);
Object.assign(mouse.canvas.prev, mouse.canvas.pos);
mouse.canvas.pos = {x: evn.layerX, y: evn.layerY};
}
// Set World Coordinates (For now the same as canvas coords; Will be useful with infinite canvas) mouse.listen[name].onmousemove.emit({
if (evn.target.id === "overlayCanvas") {
Object.assign(mouse.world.prev, mouse.world.pos);
mouse.world.pos = {x: evn.layerX, y: evn.layerY};
}
["window", "canvas", "world"].forEach((ctx) => {
mouse.listen[ctx].onmousemove.emit({
target: evn.target, target: evn.target,
px: mouse[ctx].prev.x, px: mouse.coords[name].prev.x,
py: mouse[ctx].prev.y, py: mouse.coords[name].prev.y,
x: mouse[ctx].pos.x, x: mouse.coords[name].pos.x,
y: mouse[ctx].pos.y, y: mouse.coords[name].pos.y,
timestamp: new Date(), evn,
timestamp: performance.now(),
}); });
["left", "middle", "right"].forEach((key) => {
// ondrag event Object.keys(context.buttons).forEach((index) => {
if (mouse[ctx].dragging[key] && mouse[ctx].dragging[key].drag) const key = context.buttons[index];
mouse.listen[ctx][key].ondrag.emit({ // 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, target: evn.target,
initialTarget: mouse[ctx].dragging[key].target, buttonId: evn.button,
px: mouse[ctx].prev.x, x: mouse.coords[name].pos.x,
py: mouse[ctx].prev.y, y: mouse.coords[name].pos.y,
x: mouse[ctx].pos.x, evn,
y: mouse[ctx].pos.y, timestamp: performance.now(),
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 // onpaint event
if (mouse[ctx].dragging[key]) if (mouse.coords[name].dragging[key]) {
mouse.listen[ctx][key].onpaint.emit({ mouse.listen[name][key].onpaint.emit({
target: evn.target, target: evn.target,
initialTarget: mouse[ctx].dragging[key].target, initialTarget: mouse.coords[name].dragging[key].target,
px: mouse[ctx].prev.x, button: index,
py: mouse[ctx].prev.y, px: mouse.coords[name].prev.x,
x: mouse[ctx].pos.x, py: mouse.coords[name].prev.y,
y: mouse[ctx].pos.y, x: mouse.coords[name].pos.x,
timestamp: new Date(), y: mouse.coords[name].pos.y,
evn,
timestamp: performance.now(),
}); });
}
}); });
}
}); });
}; };
@ -276,22 +314,41 @@ window.addEventListener(
"wheel", "wheel",
(evn) => { (evn) => {
evn.preventDefault(); evn.preventDefault();
["window", "canvas", "world"].forEach((ctx) => { mouse.contexts.forEach(({name}) => {
mouse.listen[ctx].onwheel.emit({ mouse.listen[name].onwheel.emit({
target: evn.target, target: evn.target,
delta: evn.deltaY, delta: evn.deltaY,
deltaX: evn.deltaX, deltaX: evn.deltaX,
deltaY: evn.deltaY, deltaY: evn.deltaY,
deltaZ: evn.deltaZ, deltaZ: evn.deltaZ,
mode: evn.deltaMode, mode: evn.deltaMode,
x: mouse[ctx].pos.x, x: mouse.coords[name].pos.x,
y: mouse[ctx].pos.y, y: mouse.coords[name].pos.y,
timestamp: new Date(), evn,
timestamp: performance.now(),
}); });
}); });
}, },
{passive: false} {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 * Keyboard input processing
*/ */
@ -342,7 +399,9 @@ const keyboard = {
}; };
window.onkeydown = (evn) => { window.onkeydown = (evn) => {
// onkeydown event
keyboard.listen.onkeydown.emit({ keyboard.listen.onkeydown.emit({
target: evn.target,
code: evn.code, code: evn.code,
key: evn.key, key: evn.key,
evn, evn,
@ -354,7 +413,9 @@ window.onkeydown = (evn) => {
_hold_to: setTimeout(() => { _hold_to: setTimeout(() => {
keyboard.keys[evn.code].held = true; keyboard.keys[evn.code].held = true;
delete keyboard.keys[evn.code]._hold_to; delete keyboard.keys[evn.code]._hold_to;
// onkeyholdstart event
keyboard.listen.onkeyholdstart.emit({ keyboard.listen.onkeyholdstart.emit({
target: evn.target,
code: evn.code, code: evn.code,
key: evn.key, key: evn.key,
evn, evn,
@ -383,7 +444,9 @@ window.onkeydown = (evn) => {
!!callback.alt === evn.altKey && !!callback.alt === evn.altKey &&
!!callback.shift === evn.shiftKey !!callback.shift === evn.shiftKey
) { ) {
// onshortcut event
keyboard.listen.onshortcut.emit({ keyboard.listen.onshortcut.emit({
target: evn.target,
code: evn.code, code: evn.code,
key: evn.key, key: evn.key,
id: callback.id, id: callback.id,
@ -395,19 +458,25 @@ window.onkeydown = (evn) => {
}; };
window.onkeyup = (evn) => { window.onkeyup = (evn) => {
// onkeyup event
keyboard.listen.onkeyup.emit({ keyboard.listen.onkeyup.emit({
target: evn.target,
code: evn.code, code: evn.code,
key: evn.key, key: evn.key,
evn, evn,
}); });
if (keyboard.keys[evn.code] && keyboard.keys[evn.code].held) { if (keyboard.keys[evn.code] && keyboard.keys[evn.code].held) {
// onkeyholdend event
keyboard.listen.onkeyholdend.emit({ keyboard.listen.onkeyholdend.emit({
target: evn.target,
code: evn.code, code: evn.code,
key: evn.key, key: evn.key,
evn, evn,
}); });
} else { } else {
// onkeyclick event
keyboard.listen.onkeyclick.emit({ keyboard.listen.onkeyclick.emit({
target: evn.target,
code: evn.code, code: evn.code,
key: evn.key, key: evn.key,
evn, evn,

View file

@ -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;
},
};
}

View file

@ -135,42 +135,22 @@ const _toolbar_input = {
}, },
slider: (state, dataKey, text, min = 0, max = 1, step = 0.1) => { slider: (state, dataKey, text, min = 0, max = 1, step = 0.1) => {
const slider = document.createElement("input"); const slider = document.createElement("div");
slider.type = "range";
slider.max = max;
slider.step = step;
slider.min = min;
slider.value = state[dataKey];
const textEl = document.createElement("input"); const value = createSlider(text, slider, {
textEl.type = "number"; min,
textEl.value = state[dataKey]; max,
step,
console.log(state[dataKey]); valuecb: (v) => {
state[dataKey] = v;
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);
return { return {
slider, slider,
text: textEl,
label,
setValue(v) { setValue(v) {
slider.value = v; value.value = v;
textEl.value = slider.value; return value.value;
return parseInt(slider.value);
}, },
}; };
}, },
@ -206,7 +186,10 @@ tools.dream = toolbar.registerTool(
(state, opt) => { (state, opt) => {
// Draw new cursor immediately // Draw new cursor immediately
ovCtx.clearRect(0, 0, ovCanvas.width, ovCanvas.height); 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 // Start Listeners
mouse.listen.canvas.onmousemove.on(state.mousemovecb); mouse.listen.canvas.onmousemove.on(state.mousemovecb);
@ -250,7 +233,10 @@ tools.img2img = toolbar.registerTool(
(state, opt) => { (state, opt) => {
// Draw new cursor immediately // Draw new cursor immediately
ovCtx.clearRect(0, 0, ovCanvas.width, ovCanvas.height); 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 // Start Listeners
mouse.listen.canvas.onmousemove.on(state.mousemovecb); mouse.listen.canvas.onmousemove.on(state.mousemovecb);
@ -326,17 +312,17 @@ tools.img2img = toolbar.registerTool(
).label; ).label;
// Denoising Strength Slider // Denoising Strength Slider
state.ctxmenu.denoisingStrengthLabel = _toolbar_input.slider( state.ctxmenu.denoisingStrengthSlider = _toolbar_input.slider(
state, state,
"denoisingStrength", "denoisingStrength",
"Denoising Strength", "Denoising Strength",
0, 0,
1, 1,
0.05 0.05
).label; ).slider;
// Use Border Mask Checkbox // Use Border Mask Checkbox
state.ctxmenu.useBorderMaskLabel = _toolbar_input.checkbox( state.ctxmenu.useBorderMaskSlider = _toolbar_input.checkbox(
state, state,
"useBorderMask", "useBorderMask",
"Use Border Mask" "Use Border Mask"
@ -349,16 +335,16 @@ tools.img2img = toolbar.registerTool(
0, 0,
128, 128,
1 1
).label; ).slider;
} }
menu.appendChild(state.ctxmenu.snapToGridLabel); menu.appendChild(state.ctxmenu.snapToGridLabel);
menu.appendChild(document.createElement("br")); menu.appendChild(document.createElement("br"));
menu.appendChild(state.ctxmenu.denoisingStrengthLabel); menu.appendChild(state.ctxmenu.denoisingStrengthSlider);
menu.appendChild(document.createElement("br")); menu.appendChild(document.createElement("br"));
menu.appendChild(state.ctxmenu.useBorderMaskLabel); menu.appendChild(state.ctxmenu.useBorderMaskLabel);
menu.appendChild(document.createElement("br")); menu.appendChild(document.createElement("br"));
menu.appendChild(state.ctxmenu.borderMaskSize); menu.appendChild(state.ctxmenu.borderMaskSlider);
}, },
shortcut: "I", shortcut: "I",
} }
@ -378,7 +364,7 @@ tools.maskbrush = toolbar.registerTool(
(state, opt) => { (state, opt) => {
// Draw new cursor immediately // Draw new cursor immediately
ovCtx.clearRect(0, 0, ovCanvas.width, ovCanvas.height); 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 // Start Listeners
mouse.listen.canvas.onmousemove.on(state.movecb); mouse.listen.canvas.onmousemove.on(state.movecb);
@ -443,11 +429,11 @@ tools.maskbrush = toolbar.registerTool(
state.config.maxBrushSize, state.config.maxBrushSize,
1 1
); );
state.ctxmenu.brushSizeLabel = brushSizeSlider.label; state.ctxmenu.brushSizeSlider = brushSizeSlider.slider;
state.setBrushSize = brushSizeSlider.setValue; state.setBrushSize = brushSizeSlider.setValue;
} }
menu.appendChild(state.ctxmenu.brushSizeLabel); menu.appendChild(state.ctxmenu.brushSizeSlider);
}, },
shortcut: "M", shortcut: "M",
} }

View file

@ -42,6 +42,16 @@ const guid = (size = 3) => {
return id; 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 * Bounding box Calculation
*/ */