some fixes and comments
Signed-off-by: Victor Seiji Hariki <victorseijih@gmail.com> (cherry picked from commit 6299b561f196a7c78c66a8d21b2e1b27cecdee77)
This commit is contained in:
parent
e19f7af581
commit
72ebe5ba21
4 changed files with 103 additions and 26 deletions
|
@ -44,7 +44,7 @@ const maskBrushTool = () =>
|
|||
(state, opt) => {
|
||||
// Clear Listeners
|
||||
mouse.listen.canvas.onmousemove.clear(state.movecb);
|
||||
mouse.listen.canvas.onwheel.on(state.wheelcb);
|
||||
mouse.listen.canvas.onwheel.clear(state.wheelcb);
|
||||
mouse.listen.canvas.left.onpaint.clear(state.drawcb);
|
||||
mouse.listen.canvas.right.onpaint.clear(state.erasecb);
|
||||
},
|
||||
|
|
|
@ -7,23 +7,28 @@ const selectTransformTool = () =>
|
|||
ovCtx.clearRect(0, 0, ovCanvas.width, ovCanvas.height);
|
||||
state.movecb({...mouse.coords.canvas.pos, target: {id: "overlayCanvas"}});
|
||||
|
||||
// Canvas left mouse handlers
|
||||
mouse.listen.canvas.onmousemove.on(state.movecb);
|
||||
mouse.listen.canvas.left.onclick.on(state.clickcb);
|
||||
mouse.listen.canvas.left.ondragstart.on(state.dragstartcb);
|
||||
mouse.listen.canvas.left.ondragend.on(state.dragendcb);
|
||||
|
||||
// Canvas right mouse handler
|
||||
mouse.listen.canvas.right.onclick.on(state.cancelcb);
|
||||
|
||||
// Keyboard click handlers
|
||||
keyboard.listen.onkeyclick.on(state.keyclickcb);
|
||||
keyboard.listen.onkeydown.on(state.keydowncb);
|
||||
|
||||
// Registers keyboard shortcuts
|
||||
keyboard.onShortcut({ctrl: true, key: "KeyC"}, state.ctrlccb);
|
||||
keyboard.onShortcut({ctrl: true, key: "KeyV"}, state.ctrlvcb);
|
||||
keyboard.onShortcut({ctrl: true, key: "KeyX"}, state.ctrlxcb);
|
||||
keyboard.onShortcut({ctrl: true, key: "KeyS"}, state.ctrlscb);
|
||||
|
||||
state.selected = null;
|
||||
},
|
||||
(state, opt) => {
|
||||
// Clear all those listeners and shortcuts we set up
|
||||
mouse.listen.canvas.onmousemove.clear(state.movecb);
|
||||
mouse.listen.canvas.left.onclick.clear(state.clickcb);
|
||||
mouse.listen.canvas.left.ondragstart.clear(state.dragstartcb);
|
||||
|
@ -36,10 +41,11 @@ const selectTransformTool = () =>
|
|||
keyboard.deleteShortcut(state.ctrlccb, "KeyC");
|
||||
keyboard.deleteShortcut(state.ctrlvcb, "KeyV");
|
||||
keyboard.deleteShortcut(state.ctrlxcb, "KeyX");
|
||||
keyboard.deleteShortcut(state.ctrlscb, "KeyS");
|
||||
|
||||
// Clear any selections
|
||||
state.reset();
|
||||
|
||||
// Resets cursor
|
||||
ovCanvas.style.cursor = "auto";
|
||||
},
|
||||
{
|
||||
|
@ -64,6 +70,7 @@ const selectTransformTool = () =>
|
|||
});
|
||||
state.moving = null;
|
||||
|
||||
// Some things to easy request for a redraw
|
||||
state.lastMouseTarget = null;
|
||||
state.lastMouseMove = null;
|
||||
|
||||
|
@ -72,12 +79,13 @@ const selectTransformTool = () =>
|
|||
state.movecb(state.lastMouseMove);
|
||||
};
|
||||
|
||||
// Clears selection and make things right
|
||||
state.reset = () => {
|
||||
if (state.selected)
|
||||
imgCtx.drawImage(
|
||||
state.selected.image,
|
||||
state.selected.original.x,
|
||||
state.selected.original.y
|
||||
state.original.image,
|
||||
state.original.x,
|
||||
state.original.y
|
||||
);
|
||||
|
||||
if (state.dragging) state.dragging = null;
|
||||
|
@ -86,6 +94,7 @@ const selectTransformTool = () =>
|
|||
redraw();
|
||||
};
|
||||
|
||||
// Selection bounding box object. Has some witchery to deal with handles.
|
||||
const selectionBB = (x1, y1, x2, y2) => {
|
||||
return {
|
||||
original: {
|
||||
|
@ -174,6 +183,7 @@ const selectTransformTool = () =>
|
|||
};
|
||||
};
|
||||
|
||||
// Mouse move handelr. As always, also renders cursor
|
||||
state.movecb = (evn) => {
|
||||
ovCanvas.style.cursor = "auto";
|
||||
state.lastMouseTarget = evn.target;
|
||||
|
@ -287,8 +297,10 @@ const selectTransformTool = () =>
|
|||
}
|
||||
};
|
||||
|
||||
// Handles left mouse clicks
|
||||
state.clickcb = (evn) => {
|
||||
if (evn.target.id === "overlayCanvas") {
|
||||
// If something is selected, commit changes to the canvas
|
||||
if (state.selected) {
|
||||
imgCtx.drawImage(
|
||||
state.selected.image,
|
||||
|
@ -312,6 +324,8 @@ const selectTransformTool = () =>
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Handles left mouse drag events
|
||||
state.dragstartcb = (evn) => {
|
||||
if (evn.target.id === "overlayCanvas") {
|
||||
let ix = evn.ix;
|
||||
|
@ -321,6 +335,7 @@ const selectTransformTool = () =>
|
|||
iy += snap(evn.iy, true, 64);
|
||||
}
|
||||
|
||||
// If is selected, check if drag is in handles/body and act accordingly
|
||||
if (state.selected) {
|
||||
const handles = state.selected.handles();
|
||||
|
||||
|
@ -329,17 +344,21 @@ const selectTransformTool = () =>
|
|||
);
|
||||
if (activeHandle) {
|
||||
state.scaling = activeHandle;
|
||||
return;
|
||||
} else if (state.selected.contains(ix, iy)) {
|
||||
state.moving = {
|
||||
offset: {x: ix - state.selected.x, y: iy - state.selected.y},
|
||||
};
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
state.dragging = {ix, iy};
|
||||
}
|
||||
// If it is not, just create new selection
|
||||
state.reset();
|
||||
state.dragging = {ix, iy};
|
||||
}
|
||||
};
|
||||
|
||||
// Handles left mouse drag end events
|
||||
state.dragendcb = (evn) => {
|
||||
if (evn.target.id === "overlayCanvas") {
|
||||
let x = evn.x;
|
||||
|
@ -349,11 +368,17 @@ const selectTransformTool = () =>
|
|||
y += snap(evn.y, true, 64);
|
||||
}
|
||||
|
||||
// If we are scaling, stop scaling and do some handler magic
|
||||
if (state.scaling) {
|
||||
state.selected.updateOriginal();
|
||||
state.scaling = null;
|
||||
// If we are moving the selection, just... stop
|
||||
} else if (state.moving) {
|
||||
state.moving = null;
|
||||
/**
|
||||
* If we are dragging, create a cutout selection area and save to an auxiliar image
|
||||
* We will be rendering the image to the overlay, so it will not be noticeable
|
||||
*/
|
||||
} else if (state.dragging) {
|
||||
state.original = selectionBB(
|
||||
state.dragging.ix,
|
||||
|
@ -404,19 +429,21 @@ const selectTransformTool = () =>
|
|||
}
|
||||
};
|
||||
|
||||
// Handler for right clicks. Basically resets everything
|
||||
state.cancelcb = (evn) => {
|
||||
if (evn.target.id === "overlayCanvas") {
|
||||
state.reset();
|
||||
}
|
||||
};
|
||||
|
||||
// Keyboard callbacks
|
||||
// Keyboard callbacks (For now, they just handle the "delete" key)
|
||||
state.keydowncb = (evn) => {};
|
||||
|
||||
state.keyclickcb = (evn) => {
|
||||
if (state.lastMouseTarget.id === "overlayCanvas") {
|
||||
switch (evn.code) {
|
||||
case "Delete":
|
||||
// Deletes selected area
|
||||
state.selected &&
|
||||
commands.runCommand(
|
||||
"eraseImage",
|
||||
|
@ -430,8 +457,11 @@ const selectTransformTool = () =>
|
|||
};
|
||||
|
||||
// Register Ctrl-C/V Shortcut
|
||||
state.ctrlccb = (evn) => {
|
||||
|
||||
// Handles copying
|
||||
state.ctrlccb = (evn, cut = false) => {
|
||||
if (state.selected && state.lastMouseTarget.id === "overlayCanvas") {
|
||||
// We create a new canvas to store the data
|
||||
state.clipboard.copy = document.createElement("canvas");
|
||||
|
||||
state.clipboard.copy.width = state.selected.w;
|
||||
|
@ -440,10 +470,29 @@ const selectTransformTool = () =>
|
|||
const ctx = state.clipboard.copy.getContext("2d");
|
||||
|
||||
ctx.clearRect(0, 0, state.selected.w, state.selected.h);
|
||||
ctx.drawImage(state.selected.image, 0, 0);
|
||||
ctx.drawImage(
|
||||
state.selected.image,
|
||||
0,
|
||||
0,
|
||||
state.selected.image.width,
|
||||
state.selected.image.height,
|
||||
0,
|
||||
0,
|
||||
state.selected.w,
|
||||
state.selected.h
|
||||
);
|
||||
|
||||
// If cutting, we reverse the selection and erase the selection area
|
||||
if (cut) {
|
||||
const aux = state.original;
|
||||
state.reset();
|
||||
|
||||
commands.runCommand("eraseImage", "Cut Image", aux);
|
||||
}
|
||||
|
||||
// Because firefox needs manual activation of the feature
|
||||
if (state.useClipboard) {
|
||||
// Send to clipboard
|
||||
state.clipboard.copy.toBlob((blob) => {
|
||||
const item = new ClipboardItem({"image/png": blob});
|
||||
navigator.clipboard.write([item]).catch((e) => {
|
||||
|
@ -454,8 +503,11 @@ const selectTransformTool = () =>
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Handles pasting
|
||||
state.ctrlvcb = (evn) => {
|
||||
if (state.useClipboard) {
|
||||
// If we use the clipboard, do some proccessing of clipboard data (ugly but kind of minimum required)
|
||||
navigator.clipboard.read().then((items) => {
|
||||
console.info(items[0]);
|
||||
for (const item of items) {
|
||||
|
@ -476,35 +528,41 @@ const selectTransformTool = () =>
|
|||
}
|
||||
});
|
||||
} else if (state.clipboard.copy) {
|
||||
// Use internal clipboard
|
||||
const image = document.createElement("img");
|
||||
image.src = state.clipboard.copy.toDataURL();
|
||||
|
||||
// Send to stamp, as clipboard temporary data
|
||||
tools.stamp.enable({
|
||||
image,
|
||||
back: tools.selecttransform.enable,
|
||||
});
|
||||
}
|
||||
};
|
||||
state.ctrlxcb = (evn) => {};
|
||||
state.ctrlscb = (evn) => {
|
||||
evn.evn.preventDefault();
|
||||
|
||||
// Cut shortcut. Basically, send to copy handler
|
||||
state.ctrlxcb = (evn) => {
|
||||
state.ctrlccb(evn, true);
|
||||
};
|
||||
},
|
||||
populateContextMenu: (menu, state) => {
|
||||
if (!state.ctxmenu) {
|
||||
state.ctxmenu = {};
|
||||
|
||||
// Snap To Grid Checkbox
|
||||
state.ctxmenu.snapToGridLabel = _toolbar_input.checkbox(
|
||||
state,
|
||||
"snapToGrid",
|
||||
"Snap To Grid"
|
||||
).label;
|
||||
|
||||
// Keep Aspect Ratio
|
||||
state.ctxmenu.keepAspectRatioLabel = _toolbar_input.checkbox(
|
||||
state,
|
||||
"keepAspectRatio",
|
||||
"Keep Aspect Ratio"
|
||||
).label;
|
||||
|
||||
// Use Clipboard
|
||||
const clipboardCheckbox = _toolbar_input.checkbox(
|
||||
state,
|
||||
|
@ -519,6 +577,7 @@ const selectTransformTool = () =>
|
|||
const actionArray = document.createElement("div");
|
||||
actionArray.classList.add("button-array");
|
||||
|
||||
// Save button
|
||||
const saveSelectionButton = document.createElement("button");
|
||||
saveSelectionButton.classList.add("button", "tool");
|
||||
saveSelectionButton.textContent = "Save";
|
||||
|
@ -530,6 +589,7 @@ const selectTransformTool = () =>
|
|||
});
|
||||
};
|
||||
|
||||
// Save as Resource Button
|
||||
const createResourceButton = document.createElement("button");
|
||||
createResourceButton.classList.add("button", "tool");
|
||||
createResourceButton.textContent = "Resource";
|
||||
|
@ -544,10 +604,13 @@ const selectTransformTool = () =>
|
|||
actionArray.appendChild(saveSelectionButton);
|
||||
actionArray.appendChild(createResourceButton);
|
||||
|
||||
// Disable buttons (if nothing is selected)
|
||||
state.ctxmenu.disableButtons = () => {
|
||||
saveSelectionButton.disabled = true;
|
||||
createResourceButton.disabled = true;
|
||||
};
|
||||
|
||||
// Disable buttons (if something is selected)
|
||||
state.ctxmenu.enableButtons = () => {
|
||||
saveSelectionButton.disabled = "";
|
||||
createResourceButton.disabled = "";
|
||||
|
|
|
@ -10,16 +10,15 @@ const stampTool = () =>
|
|||
// Start Listeners
|
||||
mouse.listen.canvas.onmousemove.on(state.movecb);
|
||||
mouse.listen.canvas.left.onclick.on(state.drawcb);
|
||||
mouse.listen.canvas.right.onclick.on(state.cancelcb);
|
||||
|
||||
// For calls from other tools to paste image
|
||||
if (opt && opt.image) {
|
||||
const resource = state.addResource(
|
||||
state.addResource(
|
||||
opt.name || "Clipboard",
|
||||
opt.image,
|
||||
opt.temporary === undefined ? true : opt.temporary
|
||||
);
|
||||
state.selected = resource;
|
||||
document.getElementById(`resource-${resource.id}`).click();
|
||||
state.ctxmenu.uploadButton.disabled = true;
|
||||
state.back = opt.back || null;
|
||||
toolbar.lock();
|
||||
|
@ -35,6 +34,7 @@ const stampTool = () =>
|
|||
// Clear Listeners
|
||||
mouse.listen.canvas.onmousemove.clear(state.movecb);
|
||||
mouse.listen.canvas.left.onclick.clear(state.drawcb);
|
||||
mouse.listen.canvas.right.onclick.clear(state.cancelcb);
|
||||
|
||||
// Deselect
|
||||
state.selected = null;
|
||||
|
@ -49,12 +49,15 @@ const stampTool = () =>
|
|||
state.selected = null;
|
||||
state.back = null;
|
||||
|
||||
const selectResource = (resource) => {
|
||||
state.lastMouseMove = {x: 0, y: 0};
|
||||
|
||||
state.selectResource = (resource) => {
|
||||
if (state.ctxmenu.uploadButton.disabled) return;
|
||||
|
||||
const resourceWrapper = resource.dom.wrapper;
|
||||
const resourceWrapper = resource && resource.dom.wrapper;
|
||||
|
||||
const wasSelected = resourceWrapper.classList.contains("selected");
|
||||
const wasSelected =
|
||||
resourceWrapper && resourceWrapper.classList.contains("selected");
|
||||
|
||||
Array.from(state.ctxmenu.resourceList.children).forEach((child) => {
|
||||
child.classList.remove("selected");
|
||||
|
@ -62,7 +65,7 @@ const stampTool = () =>
|
|||
|
||||
// Select
|
||||
if (!wasSelected) {
|
||||
resourceWrapper.classList.add("selected");
|
||||
resourceWrapper && resourceWrapper.classList.add("selected");
|
||||
state.selected = resource;
|
||||
}
|
||||
// If already selected, clear selection
|
||||
|
@ -70,6 +73,9 @@ const stampTool = () =>
|
|||
resourceWrapper.classList.remove("selected");
|
||||
state.selected = null;
|
||||
}
|
||||
|
||||
ovCtx.clearRect(0, 0, ovCanvas.width, ovCanvas.height);
|
||||
state.movecb(state.lastMouseMove);
|
||||
};
|
||||
|
||||
// Synchronizes resources array with the DOM
|
||||
|
@ -90,7 +96,7 @@ const stampTool = () =>
|
|||
resourceWrapper.classList.add("resource");
|
||||
|
||||
resourceWrapper.addEventListener("click", () =>
|
||||
selectResource(resource)
|
||||
state.selectResource(resource)
|
||||
);
|
||||
|
||||
resourceWrapper.addEventListener("mouseover", () => {
|
||||
|
@ -133,7 +139,7 @@ const stampTool = () =>
|
|||
syncResources();
|
||||
|
||||
// Select this resource
|
||||
selectResource(resource);
|
||||
state.selectResource(resource);
|
||||
|
||||
return resource;
|
||||
};
|
||||
|
@ -155,6 +161,8 @@ const stampTool = () =>
|
|||
y += snap(evn.y, true, 64);
|
||||
}
|
||||
|
||||
state.lastMouseMove = evn;
|
||||
|
||||
// Draw selected image
|
||||
if (state.selected) {
|
||||
ovCtx.drawImage(state.selected.image, x, y);
|
||||
|
@ -196,15 +204,21 @@ const stampTool = () =>
|
|||
|
||||
if (state.back) {
|
||||
toolbar.unlock();
|
||||
state.back({message: "Returning from stamp", pasted: true});
|
||||
const backfn = state.back;
|
||||
state.back = null;
|
||||
backfn({message: "Returning from stamp", pasted: true});
|
||||
}
|
||||
}
|
||||
};
|
||||
state.cancelcb = (evn) => {
|
||||
if (evn.target.id === "overlayCanvas") {
|
||||
state.selectResource(null);
|
||||
|
||||
if (state.back) {
|
||||
toolbar.unlock();
|
||||
state.back({message: "Returning from stamp", pasted: false});
|
||||
const backfn = state.back;
|
||||
state.back = null;
|
||||
backfn({message: "Returning from stamp", pasted: false});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -143,7 +143,7 @@ function cropCanvas(sourceCanvas) {
|
|||
return cutCanvas;
|
||||
}
|
||||
|
||||
function downloadCanvas(options) {
|
||||
function downloadCanvas(options = {}) {
|
||||
defaultOpt(options, {
|
||||
cropToContent: true,
|
||||
canvas: imgCanvas,
|
||||
|
|
Loading…
Reference in a new issue