Merge pull request #43 from seijihariki/input-rework-2

non-broken version on input-rework

Former-commit-id: 44ae64a42f7bb11520e4e29180be4a67f2814b50
This commit is contained in:
tim h 2022-11-23 23:54:07 -06:00 committed by GitHub
commit da95542c34
8 changed files with 548 additions and 376 deletions

View file

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

View file

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

View file

@ -68,66 +68,19 @@ people, person, humans, human, divers, diver, glitch, error, text, watermark, ba
value="-1"
step="1" />
<br />
<label for="steps">
Steps:
<input type="number" id="stepsTxt" />
</label>
<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 id="steps"></div>
<div id="cfgScale"></div>
<div id="batchSize"></div>
<div id="batchCount"></div>
</div>
<!-- Unsectioned -->
<label for="scaleFactor">
Scale factor:
<input type="number" id="scaleFactorTxt" />
</label>
<br />
<div id="scaleFactor"></div>
<label for="cbxSnap">Snap to grid?</label>
<input
type="range"
id="scaleFactor"
name="scaleFactor"
min="1"
max="16" />
type="checkbox"
id="cbxSnap"
onchange="changeSnapMode()"
checked="checked" />
<br />
<input type="checkbox" id="cbxHRFix" onchange="changeHiResFix()" />
<label for="cbxHRFix">Auto txt2img HRfix</label>

View file

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

View file

@ -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 {
const mouse = {
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(),
onmousemove: new Observer(),
left: _mouse_observers(),
middle: _mouse_observers(),
right: _mouse_observers(),
};
}
const mouse = {
buttons: {
right: null,
left: null,
middle: null,
},
// 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();
});
// Mouse Actions in Window Coordinates
window: _context_coords(),
// Add to context
context.coords = mouse.coords[name];
context.listen = mouse.listen[name];
// Mouse Actions in Canvas Coordinates
canvas: _context_coords(),
// Add to list
mouse.contexts.push(context);
// Mouse Actions in World Coordinates
world: _context_coords(),
listen: {
window: _context_observers(),
canvas: _context_observers(),
world: _context_observers(),
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]) {
if (_double_click_timeout[evn.button]) {
// ondclick event
["window", "canvas", "world"].forEach((ctx) =>
mouse.listen[ctx][key].ondclick.emit({
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(),
})
);
x: mouse.coords[name].pos.x,
y: mouse.coords[name].pos.y,
evn,
timestamp: time,
});
});
} else {
// Start timer
_double_click_timeout[key] = setTimeout(
() => delete _double_click_timeout[key],
_double_click_timeout[evn.button] = setTimeout(
() => delete _double_click_timeout[evn.button],
inputConfig.dClickTiming
);
}
// Set drag start timeout
_drag_start_timeout[key] = setTimeout(() => {
["window", "canvas", "world"].forEach((ctx) => {
mouse.listen[ctx][key].ondragstart.emit({
_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[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;
delete _drag_start_timeout[key];
mouse.coords[name].dragging[key].drag = true;
}
});
delete _drag_start_timeout[evn.button];
}, inputConfig.clickTiming);
["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.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};
}
["window", "canvas", "world"].forEach((ctx) => {
mouse.listen[ctx].onmousemove.emit({
mouse.listen[name].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(),
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(),
});
["left", "middle", "right"].forEach((key) => {
// ondrag event
if (mouse[ctx].dragging[key] && mouse[ctx].dragging[key].drag)
mouse.listen[ctx][key].ondrag.emit({
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,
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(),
buttonId: evn.button,
x: mouse.coords[name].pos.x,
y: mouse.coords[name].pos.y,
evn,
timestamp: performance.now(),
});
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[ctx].dragging[key])
mouse.listen[ctx][key].onpaint.emit({
if (mouse.coords[name].dragging[key]) {
mouse.listen[name][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(),
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,

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) => {
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);
@ -261,7 +244,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);
@ -337,17 +323,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"
@ -360,16 +346,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",
}
@ -389,7 +375,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);
@ -454,11 +440,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",
}

View file

@ -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
*/