supports drag and drop for non-square resolutions
Has a lot of duplicate code... will try refactoring someday. Adding mouse wheel on selection to scale generation resolution is also a possibility. Signed-off-by: Victor Seiji Hariki <victorseijih@gmail.com>
This commit is contained in:
parent
58b5805bd7
commit
fb83b126c7
2 changed files with 348 additions and 111 deletions
|
@ -311,3 +311,31 @@ function downloadCanvas(options = {}) {
|
||||||
link.click();
|
link.click();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes an element in a location
|
||||||
|
* @param {string} type Element Tag
|
||||||
|
* @param {number} x X coordinate of the element
|
||||||
|
* @param {number} y Y coordinate of the element
|
||||||
|
* @param {{x: number y: offset}} offset Offset to apply to the element
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
const makeElement = (
|
||||||
|
type,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
offset = {
|
||||||
|
x: -imageCollection.inputOffset.x,
|
||||||
|
y: -imageCollection.inputOffset.y,
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
const el = document.createElement(type);
|
||||||
|
el.style.position = "absolute";
|
||||||
|
el.style.left = `${x + offset.x}px`;
|
||||||
|
el.style.top = `${y + offset.y}px`;
|
||||||
|
|
||||||
|
// We can use the input element to add interactible html elements in the world
|
||||||
|
imageCollection.inputElement.appendChild(el);
|
||||||
|
|
||||||
|
return el;
|
||||||
|
};
|
||||||
|
|
|
@ -129,19 +129,6 @@ const _generate = async (
|
||||||
if (generationAreas.has(areaid)) return;
|
if (generationAreas.has(areaid)) return;
|
||||||
generationAreas.add(areaid);
|
generationAreas.add(areaid);
|
||||||
|
|
||||||
// Makes an element in a location
|
|
||||||
const makeElement = (type, x, y) => {
|
|
||||||
const el = document.createElement(type);
|
|
||||||
el.style.position = "absolute";
|
|
||||||
el.style.left = `${x - imageCollection.inputOffset.x}px`;
|
|
||||||
el.style.top = `${y - imageCollection.inputOffset.y}px`;
|
|
||||||
|
|
||||||
// We can use the input element to add interactible html elements in the world
|
|
||||||
imageCollection.inputElement.appendChild(el);
|
|
||||||
|
|
||||||
return el;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Await for queue
|
// Await for queue
|
||||||
let cancelled = false;
|
let cancelled = false;
|
||||||
const waitQueue = async () => {
|
const waitQueue = async () => {
|
||||||
|
@ -494,19 +481,14 @@ const _generate = async (
|
||||||
* @param {*} evn
|
* @param {*} evn
|
||||||
* @param {*} state
|
* @param {*} state
|
||||||
*/
|
*/
|
||||||
const dream_generate_callback = async (evn, state) => {
|
const dream_generate_callback = async (bb, state) => {
|
||||||
const bb = getBoundingBox(
|
|
||||||
evn.x,
|
|
||||||
evn.y,
|
|
||||||
state.cursorSize,
|
|
||||||
state.cursorSize,
|
|
||||||
state.snapToGrid && basePixelCount
|
|
||||||
);
|
|
||||||
|
|
||||||
// Build request to the API
|
// Build request to the API
|
||||||
const request = {};
|
const request = {};
|
||||||
Object.assign(request, stableDiffusionData);
|
Object.assign(request, stableDiffusionData);
|
||||||
|
|
||||||
|
request.width = bb.w;
|
||||||
|
request.height = bb.h;
|
||||||
|
|
||||||
// Load prompt (maybe we should add some events so we don't have to do this)
|
// Load prompt (maybe we should add some events so we don't have to do this)
|
||||||
request.prompt = document.getElementById("prompt").value;
|
request.prompt = document.getElementById("prompt").value;
|
||||||
request.negative_prompt = document.getElementById("negPrompt").value;
|
request.negative_prompt = document.getElementById("negPrompt").value;
|
||||||
|
@ -619,14 +601,7 @@ const dream_generate_callback = async (evn, state) => {
|
||||||
_generate("img2img", request, bb);
|
_generate("img2img", request, bb);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const dream_erase_callback = (evn, state) => {
|
const dream_erase_callback = (bb) => {
|
||||||
const bb = getBoundingBox(
|
|
||||||
evn.x,
|
|
||||||
evn.y,
|
|
||||||
state.cursorSize,
|
|
||||||
state.cursorSize,
|
|
||||||
state.snapToGrid && basePixelCount
|
|
||||||
);
|
|
||||||
commands.runCommand("eraseImage", "Erase Area", bb);
|
commands.runCommand("eraseImage", "Erase Area", bb);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -672,15 +647,7 @@ function applyOvermask(canvas, ctx, px) {
|
||||||
/**
|
/**
|
||||||
* Image to Image
|
* Image to Image
|
||||||
*/
|
*/
|
||||||
const dream_img2img_callback = (evn, state) => {
|
const dream_img2img_callback = (bb, state) => {
|
||||||
const bb = getBoundingBox(
|
|
||||||
evn.x,
|
|
||||||
evn.y,
|
|
||||||
state.cursorSize,
|
|
||||||
state.cursorSize,
|
|
||||||
state.snapToGrid && basePixelCount
|
|
||||||
);
|
|
||||||
|
|
||||||
// Get visible pixels
|
// Get visible pixels
|
||||||
const visibleCanvas = uil.getVisible(bb);
|
const visibleCanvas = uil.getVisible(bb);
|
||||||
|
|
||||||
|
@ -691,6 +658,9 @@ const dream_img2img_callback = (evn, state) => {
|
||||||
const request = {};
|
const request = {};
|
||||||
Object.assign(request, stableDiffusionData);
|
Object.assign(request, stableDiffusionData);
|
||||||
|
|
||||||
|
request.width = bb.w;
|
||||||
|
request.height = bb.h;
|
||||||
|
|
||||||
request.denoising_strength = state.denoisingStrength;
|
request.denoising_strength = state.denoisingStrength;
|
||||||
request.inpainting_fill = 1; // For img2img use original
|
request.inpainting_fill = 1; // For img2img use original
|
||||||
|
|
||||||
|
@ -807,21 +777,15 @@ const dream_img2img_callback = (evn, state) => {
|
||||||
/**
|
/**
|
||||||
* Dream and img2img tools
|
* Dream and img2img tools
|
||||||
*/
|
*/
|
||||||
const _reticle_draw = (evn, state, tool, style = {}) => {
|
const _reticle_draw = (bb, state, tool, resolution, style = {}) => {
|
||||||
defaultOpt(style, {
|
defaultOpt(style, {
|
||||||
sizeTextStyle: "#FFF5",
|
sizeTextStyle: "#FFF5",
|
||||||
|
genSizeTextStyle: "#FFF5",
|
||||||
toolTextStyle: "#FFF5",
|
toolTextStyle: "#FFF5",
|
||||||
reticleWidth: 1,
|
reticleWidth: 1,
|
||||||
reticleStyle: "#FFF",
|
reticleStyle: "#FFF",
|
||||||
});
|
});
|
||||||
|
|
||||||
const bb = getBoundingBox(
|
|
||||||
evn.x,
|
|
||||||
evn.y,
|
|
||||||
state.cursorSize,
|
|
||||||
state.cursorSize,
|
|
||||||
state.snapToGrid && basePixelCount
|
|
||||||
);
|
|
||||||
const bbvp = {
|
const bbvp = {
|
||||||
...viewport.canvasToView(bb.x, bb.y),
|
...viewport.canvasToView(bb.x, bb.y),
|
||||||
w: viewport.zoom * bb.w,
|
w: viewport.zoom * bb.w,
|
||||||
|
@ -838,19 +802,14 @@ const _reticle_draw = (evn, state, tool, style = {}) => {
|
||||||
uiCtx.font = `bold 20px Open Sans`;
|
uiCtx.font = `bold 20px Open Sans`;
|
||||||
|
|
||||||
// Draw Tool Name
|
// Draw Tool Name
|
||||||
{
|
if (bb.h > 40) {
|
||||||
const xshrink = Math.min(1, (bbvp.w - 20) / uiCtx.measureText(tool).width);
|
const xshrink = Math.min(1, (bbvp.w - 20) / uiCtx.measureText(tool).width);
|
||||||
|
|
||||||
uiCtx.font = `bold ${20 * xshrink}px Open Sans`;
|
uiCtx.font = `bold ${20 * xshrink}px Open Sans`;
|
||||||
|
|
||||||
uiCtx.textAlign = "left";
|
uiCtx.textAlign = "left";
|
||||||
uiCtx.fillStyle = style.toolTextStyle;
|
uiCtx.fillStyle = style.toolTextStyle;
|
||||||
uiCtx.fillText(
|
uiCtx.fillText(tool, bbvp.x + 10, bbvp.y + 10 + 20 * xshrink, bb.w);
|
||||||
tool,
|
|
||||||
bbvp.x + 10,
|
|
||||||
bbvp.y + 10 + 20 * xshrink,
|
|
||||||
state.cursorSize
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw width and height
|
// Draw width and height
|
||||||
|
@ -861,49 +820,32 @@ const _reticle_draw = (evn, state, tool, style = {}) => {
|
||||||
uiCtx.translate(bbvp.x + bbvp.w / 2, bbvp.y + bbvp.h / 2);
|
uiCtx.translate(bbvp.x + bbvp.w / 2, bbvp.y + bbvp.h / 2);
|
||||||
const xshrink = Math.min(
|
const xshrink = Math.min(
|
||||||
1,
|
1,
|
||||||
(bbvp.w - 30) / uiCtx.measureText(`${state.cursorSize}px`).width
|
(bbvp.w - 30) / uiCtx.measureText(`${bb.w}px`).width
|
||||||
);
|
);
|
||||||
const yshrink = Math.min(
|
const yshrink = Math.min(
|
||||||
1,
|
1,
|
||||||
(bbvp.h - 30) / uiCtx.measureText(`${state.cursorSize}px`).width
|
(bbvp.h - 30) / uiCtx.measureText(`${bb.h}px`).width
|
||||||
);
|
);
|
||||||
uiCtx.font = `bold ${20 * xshrink}px Open Sans`;
|
uiCtx.font = `bold ${20 * xshrink}px Open Sans`;
|
||||||
uiCtx.fillText(
|
uiCtx.fillText(`${bb.w}px`, 0, bbvp.h / 2 - 10 * xshrink, bb.w);
|
||||||
`${state.cursorSize}px`,
|
|
||||||
0,
|
|
||||||
bbvp.h / 2 - 10 * xshrink,
|
|
||||||
state.cursorSize
|
|
||||||
);
|
|
||||||
|
|
||||||
// Render Generation Width
|
// Render Generation Width
|
||||||
|
uiCtx.fillStyle = style.genSizeTextStyle;
|
||||||
uiCtx.font = `bold ${10 * xshrink}px Open Sans`;
|
uiCtx.font = `bold ${10 * xshrink}px Open Sans`;
|
||||||
if (state.cursorSize !== stableDiffusionData.width)
|
if (bb.w !== resolution.w)
|
||||||
uiCtx.fillText(
|
uiCtx.fillText(`${resolution.w}px`, 0, bbvp.h / 2 - 30 * xshrink, bb.h);
|
||||||
`${stableDiffusionData.width}px`,
|
|
||||||
0,
|
|
||||||
bbvp.h / 2 - 30 * xshrink,
|
|
||||||
state.cursorSize
|
|
||||||
);
|
|
||||||
|
|
||||||
// Render Cursor Height
|
// Render Cursor Height
|
||||||
uiCtx.rotate(-Math.PI / 2);
|
uiCtx.rotate(-Math.PI / 2);
|
||||||
|
uiCtx.fillStyle = style.sizeTextStyle;
|
||||||
uiCtx.font = `bold ${20 * yshrink}px Open Sans`;
|
uiCtx.font = `bold ${20 * yshrink}px Open Sans`;
|
||||||
uiCtx.fillText(
|
uiCtx.fillText(`${bb.h}px`, 0, bbvp.w / 2 - 10 * yshrink, bb.h);
|
||||||
`${state.cursorSize}px`,
|
|
||||||
0,
|
|
||||||
bbvp.w / 2 - 10 * yshrink,
|
|
||||||
state.cursorSize
|
|
||||||
);
|
|
||||||
|
|
||||||
// Render Generation Width
|
// Render Generation Height
|
||||||
|
uiCtx.fillStyle = style.genSizeTextStyle;
|
||||||
uiCtx.font = `bold ${10 * yshrink}px Open Sans`;
|
uiCtx.font = `bold ${10 * yshrink}px Open Sans`;
|
||||||
if (state.cursorSize !== stableDiffusionData.height)
|
if (bb.h !== resolution.h)
|
||||||
uiCtx.fillText(
|
uiCtx.fillText(`${resolution.h}px`, 0, bbvp.w / 2 - 30 * xshrink, bb.h);
|
||||||
`${stableDiffusionData.height}px`,
|
|
||||||
0,
|
|
||||||
bbvp.w / 2 - 30 * xshrink,
|
|
||||||
state.cursorSize
|
|
||||||
);
|
|
||||||
|
|
||||||
uiCtx.restore();
|
uiCtx.restore();
|
||||||
}
|
}
|
||||||
|
@ -911,7 +853,7 @@ const _reticle_draw = (evn, state, tool, style = {}) => {
|
||||||
return () => {
|
return () => {
|
||||||
uiCtx.save();
|
uiCtx.save();
|
||||||
|
|
||||||
uiCtx.clearRect(bbvp.x - 10, bbvp.y - 10, bbvp.w + 20, bbvp.h + 20);
|
uiCtx.clearRect(bbvp.x - 64, bbvp.y - 64, bbvp.w + 128, bbvp.h + 128);
|
||||||
|
|
||||||
uiCtx.restore();
|
uiCtx.restore();
|
||||||
};
|
};
|
||||||
|
@ -953,9 +895,17 @@ const dreamTool = () =>
|
||||||
// Start Listeners
|
// Start Listeners
|
||||||
mouse.listen.world.onmousemove.on(state.mousemovecb);
|
mouse.listen.world.onmousemove.on(state.mousemovecb);
|
||||||
mouse.listen.world.onwheel.on(state.wheelcb);
|
mouse.listen.world.onwheel.on(state.wheelcb);
|
||||||
|
|
||||||
|
mouse.listen.world.btn.left.ondragstart.on(state.dragstartcb);
|
||||||
|
mouse.listen.world.btn.left.ondrag.on(state.dragcb);
|
||||||
|
mouse.listen.world.btn.left.ondragend.on(state.dragendcb);
|
||||||
|
|
||||||
mouse.listen.world.btn.left.onclick.on(state.dreamcb);
|
mouse.listen.world.btn.left.onclick.on(state.dreamcb);
|
||||||
mouse.listen.world.btn.right.onclick.on(state.erasecb);
|
mouse.listen.world.btn.right.onclick.on(state.erasecb);
|
||||||
|
|
||||||
|
// Clear Selection
|
||||||
|
state.selected = null;
|
||||||
|
|
||||||
// Display Mask
|
// Display Mask
|
||||||
setMask(state.invertMask ? "hold" : "clear");
|
setMask(state.invertMask ? "hold" : "clear");
|
||||||
|
|
||||||
|
@ -968,9 +918,17 @@ const dreamTool = () =>
|
||||||
// Clear Listeners
|
// Clear Listeners
|
||||||
mouse.listen.world.onmousemove.clear(state.mousemovecb);
|
mouse.listen.world.onmousemove.clear(state.mousemovecb);
|
||||||
mouse.listen.world.onwheel.clear(state.wheelcb);
|
mouse.listen.world.onwheel.clear(state.wheelcb);
|
||||||
|
|
||||||
|
mouse.listen.world.btn.left.ondragstart.clear(state.dragstartcb);
|
||||||
|
mouse.listen.world.btn.left.ondrag.clear(state.dragcb);
|
||||||
|
mouse.listen.world.btn.left.ondragend.clear(state.dragendcb);
|
||||||
|
|
||||||
mouse.listen.world.btn.left.onclick.clear(state.dreamcb);
|
mouse.listen.world.btn.left.onclick.clear(state.dreamcb);
|
||||||
mouse.listen.world.btn.right.onclick.clear(state.erasecb);
|
mouse.listen.world.btn.right.onclick.clear(state.erasecb);
|
||||||
|
|
||||||
|
// Clear Selection
|
||||||
|
state.selected = null;
|
||||||
|
|
||||||
// Hide Mask
|
// Hide Mask
|
||||||
setMask("none");
|
setMask("none");
|
||||||
|
|
||||||
|
@ -987,6 +945,8 @@ const dreamTool = () =>
|
||||||
state.invertMask = false;
|
state.invertMask = false;
|
||||||
state.overMaskPx = 0;
|
state.overMaskPx = 0;
|
||||||
|
|
||||||
|
state.erasePrevCursor = () =>
|
||||||
|
uiCtx.clearRect(0, 0, uiCanvas.width, uiCanvas.height);
|
||||||
state.erasePrevReticle = () =>
|
state.erasePrevReticle = () =>
|
||||||
uiCtx.clearRect(0, 0, uiCanvas.width, uiCanvas.height);
|
uiCtx.clearRect(0, 0, uiCanvas.width, uiCanvas.height);
|
||||||
|
|
||||||
|
@ -994,18 +954,107 @@ const dreamTool = () =>
|
||||||
...mouse.coords.world.pos,
|
...mouse.coords.world.pos,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
state.dragstartcb = (evn) => {
|
||||||
|
const x = state.snapToGrid ? evn.x + snap(evn.x, 0, 64) : evn.x;
|
||||||
|
const y = state.snapToGrid ? evn.y + snap(evn.y, 0, 64) : evn.y;
|
||||||
|
state.selected = {start: {x, y}, now: {x, y}};
|
||||||
|
};
|
||||||
|
state.dragcb = (evn) => {
|
||||||
|
const x = state.snapToGrid ? evn.x + snap(evn.x, 0, 64) : evn.x;
|
||||||
|
const y = state.snapToGrid ? evn.y + snap(evn.y, 0, 64) : evn.y;
|
||||||
|
|
||||||
|
state.selected.now = {x, y};
|
||||||
|
};
|
||||||
|
state.dragendcb = (evn) => {
|
||||||
|
const x = state.snapToGrid ? evn.x + snap(evn.x, 0, 64) : evn.x;
|
||||||
|
const y = state.snapToGrid ? evn.y + snap(evn.y, 0, 64) : evn.y;
|
||||||
|
|
||||||
|
state.selected.now = {x, y};
|
||||||
|
|
||||||
|
if (
|
||||||
|
state.selected.start.x === state.selected.now.x ||
|
||||||
|
state.selected.start.y === state.selected.now.y
|
||||||
|
) {
|
||||||
|
state.selected = null;
|
||||||
|
state.redraw();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
state.mousemovecb = (evn) => {
|
state.mousemovecb = (evn) => {
|
||||||
state.lastMouseMove = evn;
|
state.lastMouseMove = evn;
|
||||||
|
|
||||||
|
state.erasePrevCursor();
|
||||||
state.erasePrevReticle();
|
state.erasePrevReticle();
|
||||||
|
|
||||||
|
let x = evn.x;
|
||||||
|
let y = evn.y;
|
||||||
|
if (state.snapToGrid) {
|
||||||
|
x += snap(evn.x, 0, 64);
|
||||||
|
y += snap(evn.y, 0, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
const vpc = viewport.canvasToView(x, y);
|
||||||
|
|
||||||
|
// Draw current cursor location
|
||||||
|
uiCtx.lineWidth = 3;
|
||||||
|
uiCtx.strokeStyle = "#FFF5";
|
||||||
|
|
||||||
|
uiCtx.beginPath();
|
||||||
|
uiCtx.moveTo(vpc.x, vpc.y + 10);
|
||||||
|
uiCtx.lineTo(vpc.x, vpc.y - 10);
|
||||||
|
uiCtx.moveTo(vpc.x + 10, vpc.y);
|
||||||
|
uiCtx.lineTo(vpc.x - 10, vpc.y);
|
||||||
|
uiCtx.stroke();
|
||||||
|
state.eraseCursor = () => {
|
||||||
|
uiCtx.clearRect(vpc.x - 15, vpc.y - 15, vpc.x + 30, vpc.y + 30);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (state.selected) {
|
||||||
|
const bb = {x: 0, y: 0, w: 0, h: 0};
|
||||||
|
|
||||||
|
const minx = Math.min(state.selected.now.x, state.selected.start.x);
|
||||||
|
const miny = Math.min(state.selected.now.y, state.selected.start.y);
|
||||||
|
const maxx = Math.max(state.selected.now.x, state.selected.start.x);
|
||||||
|
const maxy = Math.max(state.selected.now.y, state.selected.start.y);
|
||||||
|
|
||||||
|
bb.x = minx;
|
||||||
|
bb.y = miny;
|
||||||
|
bb.w = maxx - minx;
|
||||||
|
bb.h = maxy - miny;
|
||||||
|
|
||||||
|
state.selected.bb = bb;
|
||||||
|
|
||||||
|
state.erasePrevReticle = _reticle_draw(bb, state, "Dream", {
|
||||||
|
w: bb.w,
|
||||||
|
h: bb.h,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const style =
|
const style =
|
||||||
state.cursorSize > stableDiffusionData.width
|
state.cursorSize > stableDiffusionData.width
|
||||||
? "#FBB5"
|
? "#FBB5"
|
||||||
: state.cursorSize < stableDiffusionData.width
|
: state.cursorSize < stableDiffusionData.width
|
||||||
? "#BFB5"
|
? "#BFB5"
|
||||||
: "#FFF5";
|
: "#FFF5";
|
||||||
state.erasePrevReticle = _reticle_draw(evn, state, "Dream", {
|
state.erasePrevReticle = _reticle_draw(
|
||||||
sizeTextStyle: style,
|
getBoundingBox(
|
||||||
});
|
evn.x,
|
||||||
|
evn.y,
|
||||||
|
state.cursorSize,
|
||||||
|
state.cursorSize,
|
||||||
|
state.snapToGrid && basePixelCount
|
||||||
|
),
|
||||||
|
state,
|
||||||
|
"Dream",
|
||||||
|
{
|
||||||
|
w: stableDiffusionData.width,
|
||||||
|
h: stableDiffusionData.height,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sizeTextStyle: style,
|
||||||
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
state.redraw = () => {
|
state.redraw = () => {
|
||||||
|
@ -1016,9 +1065,33 @@ const dreamTool = () =>
|
||||||
_dream_onwheel(evn, state);
|
_dream_onwheel(evn, state);
|
||||||
};
|
};
|
||||||
state.dreamcb = (evn) => {
|
state.dreamcb = (evn) => {
|
||||||
dream_generate_callback(evn, state);
|
const bb =
|
||||||
|
(state.selected && state.selected.bb) ||
|
||||||
|
getBoundingBox(
|
||||||
|
evn.x,
|
||||||
|
evn.y,
|
||||||
|
state.cursorSize,
|
||||||
|
state.cursorSize,
|
||||||
|
state.snapToGrid && basePixelCount
|
||||||
|
);
|
||||||
|
dream_generate_callback(bb, state);
|
||||||
|
state.selected = null;
|
||||||
|
};
|
||||||
|
state.erasecb = (evn) => {
|
||||||
|
if (state.selected) {
|
||||||
|
state.selected = null;
|
||||||
|
state.redraw();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const bb = getBoundingBox(
|
||||||
|
evn.x,
|
||||||
|
evn.y,
|
||||||
|
state.cursorSize,
|
||||||
|
state.cursorSize,
|
||||||
|
state.snapToGrid && basePixelCount
|
||||||
|
);
|
||||||
|
dream_erase_callback(bb, state);
|
||||||
};
|
};
|
||||||
state.erasecb = (evn) => dream_erase_callback(evn, state);
|
|
||||||
},
|
},
|
||||||
populateContextMenu: (menu, state) => {
|
populateContextMenu: (menu, state) => {
|
||||||
if (!state.ctxmenu) {
|
if (!state.ctxmenu) {
|
||||||
|
@ -1102,9 +1175,17 @@ const img2imgTool = () =>
|
||||||
// Start Listeners
|
// Start Listeners
|
||||||
mouse.listen.world.onmousemove.on(state.mousemovecb);
|
mouse.listen.world.onmousemove.on(state.mousemovecb);
|
||||||
mouse.listen.world.onwheel.on(state.wheelcb);
|
mouse.listen.world.onwheel.on(state.wheelcb);
|
||||||
|
|
||||||
|
mouse.listen.world.btn.left.ondragstart.on(state.dragstartcb);
|
||||||
|
mouse.listen.world.btn.left.ondrag.on(state.dragcb);
|
||||||
|
mouse.listen.world.btn.left.ondragend.on(state.dragendcb);
|
||||||
|
|
||||||
mouse.listen.world.btn.left.onclick.on(state.dreamcb);
|
mouse.listen.world.btn.left.onclick.on(state.dreamcb);
|
||||||
mouse.listen.world.btn.right.onclick.on(state.erasecb);
|
mouse.listen.world.btn.right.onclick.on(state.erasecb);
|
||||||
|
|
||||||
|
// Clear Selection
|
||||||
|
state.selected = null;
|
||||||
|
|
||||||
// Display Mask
|
// Display Mask
|
||||||
setMask(state.invertMask ? "hold" : "clear");
|
setMask(state.invertMask ? "hold" : "clear");
|
||||||
|
|
||||||
|
@ -1117,9 +1198,17 @@ const img2imgTool = () =>
|
||||||
// Clear Listeners
|
// Clear Listeners
|
||||||
mouse.listen.world.onmousemove.clear(state.mousemovecb);
|
mouse.listen.world.onmousemove.clear(state.mousemovecb);
|
||||||
mouse.listen.world.onwheel.clear(state.wheelcb);
|
mouse.listen.world.onwheel.clear(state.wheelcb);
|
||||||
|
|
||||||
|
mouse.listen.world.btn.left.ondragstart.clear(state.dragstartcb);
|
||||||
|
mouse.listen.world.btn.left.ondrag.clear(state.dragcb);
|
||||||
|
mouse.listen.world.btn.left.ondragend.clear(state.dragendcb);
|
||||||
|
|
||||||
mouse.listen.world.btn.left.onclick.clear(state.dreamcb);
|
mouse.listen.world.btn.left.onclick.clear(state.dreamcb);
|
||||||
mouse.listen.world.btn.right.onclick.clear(state.erasecb);
|
mouse.listen.world.btn.right.onclick.clear(state.erasecb);
|
||||||
|
|
||||||
|
// Clear Selection
|
||||||
|
state.selected = null;
|
||||||
|
|
||||||
// Hide mask
|
// Hide mask
|
||||||
setMask("none");
|
setMask("none");
|
||||||
uiCtx.clearRect(0, 0, uiCanvas.width, uiCanvas.height);
|
uiCtx.clearRect(0, 0, uiCanvas.width, uiCanvas.height);
|
||||||
|
@ -1140,39 +1229,134 @@ const img2imgTool = () =>
|
||||||
state.keepBorderSize = 64;
|
state.keepBorderSize = 64;
|
||||||
state.gradient = true;
|
state.gradient = true;
|
||||||
|
|
||||||
|
state.erasePrevCursor = () =>
|
||||||
|
uiCtx.clearRect(0, 0, uiCanvas.width, uiCanvas.height);
|
||||||
state.erasePrevReticle = () =>
|
state.erasePrevReticle = () =>
|
||||||
uiCtx.clearRect(0, 0, uiCanvas.width, uiCanvas.height);
|
uiCtx.clearRect(0, 0, uiCanvas.width, uiCanvas.height);
|
||||||
|
|
||||||
state.lastMouseMove = {
|
state.lastMouseMove = {
|
||||||
...mouse.coords.world.pos,
|
...mouse.coords.world.pos,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
state.dragstartcb = (evn) => {
|
||||||
|
const x = state.snapToGrid ? evn.x + snap(evn.x, 0, 64) : evn.x;
|
||||||
|
const y = state.snapToGrid ? evn.y + snap(evn.y, 0, 64) : evn.y;
|
||||||
|
state.selected = {start: {x, y}, now: {x, y}};
|
||||||
|
};
|
||||||
|
state.dragcb = (evn) => {
|
||||||
|
const x = state.snapToGrid ? evn.x + snap(evn.x, 0, 64) : evn.x;
|
||||||
|
const y = state.snapToGrid ? evn.y + snap(evn.y, 0, 64) : evn.y;
|
||||||
|
|
||||||
|
state.selected.now = {x, y};
|
||||||
|
};
|
||||||
|
|
||||||
|
state.dragendcb = (evn) => {
|
||||||
|
const x = state.snapToGrid ? evn.x + snap(evn.x, 0, 64) : evn.x;
|
||||||
|
const y = state.snapToGrid ? evn.y + snap(evn.y, 0, 64) : evn.y;
|
||||||
|
|
||||||
|
state.selected.now = {x, y};
|
||||||
|
|
||||||
|
if (
|
||||||
|
state.selected.start.x === state.selected.now.x ||
|
||||||
|
state.selected.start.y === state.selected.now.y
|
||||||
|
) {
|
||||||
|
state.selected = null;
|
||||||
|
state.redraw();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
state.mousemovecb = (evn) => {
|
state.mousemovecb = (evn) => {
|
||||||
state.lastMouseMove = evn;
|
state.lastMouseMove = evn;
|
||||||
|
|
||||||
|
state.erasePrevCursor();
|
||||||
state.erasePrevReticle();
|
state.erasePrevReticle();
|
||||||
|
|
||||||
const style =
|
let x = evn.x;
|
||||||
state.cursorSize > stableDiffusionData.width
|
let y = evn.y;
|
||||||
? "#FBB5"
|
if (state.snapToGrid) {
|
||||||
: state.cursorSize < stableDiffusionData.width
|
x += snap(evn.x, 0, 64);
|
||||||
? "#BFB5"
|
y += snap(evn.y, 0, 64);
|
||||||
: "#FFF5";
|
}
|
||||||
state.erasePrevReticle = _reticle_draw(evn, state, "Img2Img", {
|
|
||||||
sizeTextStyle: style,
|
|
||||||
});
|
|
||||||
|
|
||||||
const bb = getBoundingBox(
|
const vpc = viewport.canvasToView(x, y);
|
||||||
evn.x,
|
|
||||||
evn.y,
|
// Draw current cursor location
|
||||||
state.cursorSize,
|
uiCtx.lineWidth = 3;
|
||||||
state.cursorSize,
|
uiCtx.strokeStyle = "#FFF5";
|
||||||
state.snapToGrid && basePixelCount
|
|
||||||
);
|
uiCtx.beginPath();
|
||||||
|
uiCtx.moveTo(vpc.x, vpc.y + 10);
|
||||||
|
uiCtx.lineTo(vpc.x, vpc.y - 10);
|
||||||
|
uiCtx.moveTo(vpc.x + 10, vpc.y);
|
||||||
|
uiCtx.lineTo(vpc.x - 10, vpc.y);
|
||||||
|
uiCtx.stroke();
|
||||||
|
state.eraseCursor = () => {
|
||||||
|
uiCtx.clearRect(vpc.x - 15, vpc.y - 15, vpc.x + 30, vpc.y + 30);
|
||||||
|
};
|
||||||
|
|
||||||
// Resolution
|
// Resolution
|
||||||
const request = {
|
let bb = null;
|
||||||
width: stableDiffusionData.width,
|
let request = null;
|
||||||
height: stableDiffusionData.height,
|
|
||||||
};
|
if (state.selected) {
|
||||||
|
bb = {x: 0, y: 0, w: 0, h: 0};
|
||||||
|
|
||||||
|
const minx = Math.min(state.selected.now.x, state.selected.start.x);
|
||||||
|
const miny = Math.min(state.selected.now.y, state.selected.start.y);
|
||||||
|
const maxx = Math.max(state.selected.now.x, state.selected.start.x);
|
||||||
|
const maxy = Math.max(state.selected.now.y, state.selected.start.y);
|
||||||
|
|
||||||
|
bb.x = minx;
|
||||||
|
bb.y = miny;
|
||||||
|
bb.w = maxx - minx;
|
||||||
|
bb.h = maxy - miny;
|
||||||
|
|
||||||
|
state.selected.bb = bb;
|
||||||
|
|
||||||
|
request = {width: bb.w, height: bb.h};
|
||||||
|
|
||||||
|
state.erasePrevReticle = _reticle_draw(bb, state, "Img2Img", {
|
||||||
|
w: bb.w,
|
||||||
|
h: bb.h,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
bb = getBoundingBox(
|
||||||
|
evn.x,
|
||||||
|
evn.y,
|
||||||
|
state.cursorSize,
|
||||||
|
state.cursorSize,
|
||||||
|
state.snapToGrid && basePixelCount
|
||||||
|
);
|
||||||
|
|
||||||
|
request = {
|
||||||
|
width: stableDiffusionData.width,
|
||||||
|
height: stableDiffusionData.height,
|
||||||
|
};
|
||||||
|
|
||||||
|
const style =
|
||||||
|
state.cursorSize > stableDiffusionData.width
|
||||||
|
? "#FBB5"
|
||||||
|
: state.cursorSize < stableDiffusionData.width
|
||||||
|
? "#BFB5"
|
||||||
|
: "#FFF5";
|
||||||
|
state.erasePrevReticle = _reticle_draw(
|
||||||
|
bb,
|
||||||
|
state,
|
||||||
|
"Img2Img",
|
||||||
|
{w: request.width, h: request.height},
|
||||||
|
{
|
||||||
|
sizeTextStyle: style,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
state.selected &&
|
||||||
|
(state.selected.now.x === state.selected.start.x ||
|
||||||
|
state.selected.now.y === state.selected.start.y)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const bbvp = {
|
const bbvp = {
|
||||||
...viewport.canvasToView(bb.x, bb.y),
|
...viewport.canvasToView(bb.x, bb.y),
|
||||||
|
@ -1268,9 +1452,34 @@ const img2imgTool = () =>
|
||||||
_dream_onwheel(evn, state);
|
_dream_onwheel(evn, state);
|
||||||
};
|
};
|
||||||
state.dreamcb = (evn) => {
|
state.dreamcb = (evn) => {
|
||||||
dream_img2img_callback(evn, state);
|
const bb =
|
||||||
|
(state.selected && state.selected.bb) ||
|
||||||
|
getBoundingBox(
|
||||||
|
evn.x,
|
||||||
|
evn.y,
|
||||||
|
state.cursorSize,
|
||||||
|
state.cursorSize,
|
||||||
|
state.snapToGrid && basePixelCount
|
||||||
|
);
|
||||||
|
dream_img2img_callback(bb, state);
|
||||||
|
state.selected = null;
|
||||||
|
state.redraw();
|
||||||
|
};
|
||||||
|
state.erasecb = (evn) => {
|
||||||
|
if (state.selected) {
|
||||||
|
state.selected = null;
|
||||||
|
state.redraw();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const bb = getBoundingBox(
|
||||||
|
evn.x,
|
||||||
|
evn.y,
|
||||||
|
state.cursorSize,
|
||||||
|
state.cursorSize,
|
||||||
|
state.snapToGrid && basePixelCount
|
||||||
|
);
|
||||||
|
dream_erase_callback(bb, state);
|
||||||
};
|
};
|
||||||
state.erasecb = (evn) => dream_erase_callback(evn, state);
|
|
||||||
},
|
},
|
||||||
populateContextMenu: (menu, state) => {
|
populateContextMenu: (menu, state) => {
|
||||||
if (!state.ctxmenu) {
|
if (!state.ctxmenu) {
|
||||||
|
|
Loading…
Reference in a new issue