Fixed bugs in new selection system

This commit is contained in:
Nicola
2022-01-22 12:18:10 +01:00
parent 86ab2e08e6
commit fd688a3e86
9 changed files with 123 additions and 37 deletions

View File

@ -96,14 +96,14 @@ class Tool {
currFile.canvasView.style.cursor = 'default'; currFile.canvasView.style.cursor = 'default';
} }
onStart(mousePos) { onStart(mousePos, mouseTarget) {
this.startMousePos = mousePos; this.startMousePos = mousePos;
} }
onDrag(mousePos) { onDrag(mousePos, mouseTarget) {
} }
onEnd(mousePos) { onEnd(mousePos, mouseTarget) {
this.endMousePos = mousePos; this.endMousePos = mousePos;
} }

View File

@ -30,6 +30,9 @@ const ToolManager = (() => {
Events.on("mousedown", window, onMouseDown); Events.on("mousedown", window, onMouseDown);
Events.on("wheel", window, onMouseWheel); Events.on("wheel", window, onMouseWheel);
// Assign a selection tool to the move tool
tools["moveselection"].selectionTool = tools["lassoselect"];
// Bind tool shortcuts // Bind tool shortcuts
Events.onCustom("tool-shortcut", onShortcut); Events.onCustom("tool-shortcut", onShortcut);
@ -145,10 +148,13 @@ const ToolManager = (() => {
return currTool; return currTool;
} }
function switchTool(newTool) { function switchTool(newTool, event) {
currTool.onDeselect(); currTool.onDeselect();
currTool = newTool; currTool = newTool;
currTool.onSelect(); currTool.onSelect();
if (event != undefined)
event.stopPropagation();
} }
return { return {

View File

@ -18,6 +18,7 @@ const TopMenuModule = (() => {
closeMenu(); closeMenu();
// Select the item // Select the item
Util.select(e.target.parentElement); Util.select(e.target.parentElement);
e.stopPropagation();
}); });
const subMenu = menuItem.children[1]; const subMenu = menuItem.children[1];
@ -53,18 +54,29 @@ const TopMenuModule = (() => {
e.preventDefault(); e.preventDefault();
} }
break; break;
// REFACTOR: move the binding to the Selection IIFE or something like that once it's done
case 'Paste': case 'Paste':
Events.on('click', currSubmenuButton, function(){Events.emit("ctrl+v");}); Events.on('click', currSubmenuButton, function(e){
Events.emit("ctrl+v");
e.stopPropagation();
});
break; break;
case 'Copy': case 'Copy':
Events.on('click', currSubmenuButton, function(){Events.emit("ctrl+c");}); Events.on('click', currSubmenuButton, function(e){
Events.emit("ctrl+c");
e.stopPropagation();
});
break; break;
case 'Cut': case 'Cut':
Events.on('click', currSubmenuButton, function(){Events.emit("ctrl+x");}); Events.on('click', currSubmenuButton, function(e){
Events.emit("ctrl+x");
e.stopPropagation();
});
break; break;
case 'Cancel': case 'Cancel':
Events.on('click', currSubmenuButton, function(){Events.emit("esc-pressed")}); Events.on('click', currSubmenuButton, function(e){
Events.emit("esc-pressed");
e.stopPropagation();
});
break; break;
//Help Menu //Help Menu
case 'Settings': case 'Settings':

View File

@ -95,4 +95,8 @@ class Util {
static isPixelTransparent(data, x, y, dataWidth) { static isPixelTransparent(data, x, y, dataWidth) {
return this.getPixelColor(data, x, y, dataWidth)[3] == 255; return this.getPixelColor(data, x, y, dataWidth)[3] == 255;
} }
static cursorInCanvas(canvasSize, mousePos) {
return mousePos[0] >= 0 && mousePos[1] >= 0 && canvasSize[0] > mousePos[0] && canvasSize[1] > mousePos[1];
}
} }

View File

@ -6,17 +6,24 @@ class LassoSelectionTool extends SelectionTool {
Events.on('click', this.mainButton, switchFunc, this); Events.on('click', this.mainButton, switchFunc, this);
} }
onStart(mousePos) { onStart(mousePos, mouseTarget) {
super.onStart(mousePos); super.onStart(mousePos, mouseTarget);
// clearSelection();
if (Util.isChildOfByClass(mouseTarget, "editor-top-menu") ||
!Util.cursorInCanvas(currFile.canvasSize, [mousePos[0]/currFile.zoom, mousePos[1]/currFile.zoom]))
return;
this.currentPixels = []; this.currentPixels = [];
this.drawSelection(); this.drawSelection();
this.currentPixels.push([mousePos[0] / currFile.zoom, mousePos[1] / currFile.zoom]); this.currentPixels.push([mousePos[0] / currFile.zoom, mousePos[1] / currFile.zoom]);
} }
onDrag(mousePos) { onDrag(mousePos, mouseTarget) {
super.onDrag(mousePos); super.onDrag(mousePos, mouseTarget);
if (Util.isChildOfByClass(mouseTarget, "editor-top-menu") ||
!Util.cursorInCanvas(currFile.canvasSize, [mousePos[0]/currFile.zoom, mousePos[1]/currFile.zoom]))
return;
if (this.currentPixels[this.currentPixels.length - 1] != mousePos) if (this.currentPixels[this.currentPixels.length - 1] != mousePos)
this.currentPixels.push([mousePos[0] / currFile.zoom, mousePos[1] / currFile.zoom]); this.currentPixels.push([mousePos[0] / currFile.zoom, mousePos[1] / currFile.zoom]);
@ -24,10 +31,14 @@ class LassoSelectionTool extends SelectionTool {
this.drawSelection(); this.drawSelection();
} }
onEnd(mousePos) { onEnd(mousePos, mouseTarget) {
super.onEnd(mousePos); super.onEnd(mousePos, mouseTarget);
new HistoryState().EditCanvas(); new HistoryState().EditCanvas();
if (Util.isChildOfByClass(mouseTarget, "editor-top-menu") ||
!Util.cursorInCanvas(currFile.canvasSize, [mousePos[0]/currFile.zoom, mousePos[1]/currFile.zoom]))
return;
this.currentPixels.push([this.startMousePos[0] / currFile.zoom, this.startMousePos[1] / currFile.zoom]); this.currentPixels.push([this.startMousePos[0] / currFile.zoom, this.startMousePos[1] / currFile.zoom]);
// Include extreme borders // Include extreme borders

View File

@ -5,8 +5,12 @@ class MagicWandTool extends SelectionTool {
Events.on('click', this.mainButton, switchFunc, this); Events.on('click', this.mainButton, switchFunc, this);
} }
onEnd(mousePos) { onEnd(mousePos, mouseTarget) {
super.onStart(mousePos); super.onStart(mousePos, mouseTarget);
if (Util.isChildOfByClass(mouseTarget, "editor-top-menu") ||
!Util.cursorInCanvas(currFile.canvasSize, [mousePos[0]/currFile.zoom, mousePos[1]/currFile.zoom]))
return;
this.switchFunc(this.moveTool); this.switchFunc(this.moveTool);
this.moveTool.setSelectionData(this.getSelection(), this); this.moveTool.setSelectionData(this.getSelection(), this);
@ -45,6 +49,9 @@ class MagicWandTool extends SelectionTool {
// Put it on the TMP layer // Put it on the TMP layer
currFile.TMPLayer.context.putImageData(this.previewData, 0, 0); currFile.TMPLayer.context.putImageData(this.previewData, 0, 0);
// Draw the bounding box
this.drawBoundingBox();
return selectedData; return selectedData;
} }

View File

@ -1,7 +1,3 @@
/** TODO:
* - Test with lasso
*/
class MoveSelectionTool extends DrawingTool { class MoveSelectionTool extends DrawingTool {
currSelection = undefined; currSelection = undefined;
selectionTool = undefined; selectionTool = undefined;
@ -18,17 +14,20 @@ class MoveSelectionTool extends DrawingTool {
Events.onCustom("esc-pressed", this.endSelection.bind(this)); Events.onCustom("esc-pressed", this.endSelection.bind(this));
Events.onCustom("ctrl+c", this.copySelection.bind(this)); Events.onCustom("ctrl+c", this.copySelection.bind(this), true);
Events.onCustom("ctrl+x", this.cutSelection.bind(this)); Events.onCustom("ctrl+x", this.cutSelection.bind(this), true);
Events.onCustom("ctrl+v", this.pasteSelection.bind(this)); Events.onCustom("ctrl+v", this.pasteSelection.bind(this));
} }
copySelection() { copySelection(event) {
this.lastCopiedSelection = this.currSelection; this.lastCopiedSelection = this.currSelection;
this.cutting = false; this.cutting = false;
if (event)
this.switchFunc(this.selectionTool);
} }
cutSelection() { cutSelection(event) {
if (currFile.currentLayer.isLocked) if (currFile.currentLayer.isLocked)
return; return;
this.cutting = true; this.cutting = true;
@ -37,6 +36,11 @@ class MoveSelectionTool extends DrawingTool {
this.currSelection = this.lastCopiedSelection; this.currSelection = this.lastCopiedSelection;
// Cut the data // Cut the data
this.selectionTool.cutSelection(); this.selectionTool.cutSelection();
if (event)
this.switchFunc(this.selectionTool);
new HistoryState().EditCanvas();
} }
pasteSelection() { pasteSelection() {
@ -56,6 +60,7 @@ class MoveSelectionTool extends DrawingTool {
this.switchFunc(this); this.switchFunc(this);
this.currSelection = this.lastCopiedSelection; this.currSelection = this.lastCopiedSelection;
this.selectionTool.drawSelectedArea();
// Putting the vfx layer on top of everything // Putting the vfx layer on top of everything
currFile.VFXLayer.canvas.style.zIndex = MAX_Z_INDEX; currFile.VFXLayer.canvas.style.zIndex = MAX_Z_INDEX;
@ -83,13 +88,15 @@ class MoveSelectionTool extends DrawingTool {
// Draw the selection area and outline // Draw the selection area and outline
this.selectionTool.drawOutline(); this.selectionTool.drawOutline();
this.selectionTool.drawSelectedArea(); this.selectionTool.drawSelectedArea();
this.selectionTool.drawBoundingBox();
} }
onEnd(mousePos, mouseTarget) { onEnd(mousePos, mouseTarget) {
super.onEnd(mousePos, mouseTarget); super.onEnd(mousePos, mouseTarget);
if (!this.selectionTool.cursorInSelectedArea(mousePos) && if (!this.selectionTool.cursorInSelectedArea(mousePos) &&
!Util.isChildOfByClass(mouseTarget, "editor-top-menu")) { !Util.isChildOfByClass(mouseTarget, "editor-top-menu") &&
Util.cursorInCanvas(currFile.canvasSize, [mousePos[0]/currFile.zoom, mousePos[1]/currFile.zoom])) {
this.endSelection(); this.endSelection();
// Switch to selection tool // Switch to selection tool
this.switchFunc(this.selectionTool); this.switchFunc(this.selectionTool);
@ -102,6 +109,7 @@ class MoveSelectionTool extends DrawingTool {
onDeselect() { onDeselect() {
super.onDeselect(); super.onDeselect();
this.endSelection();
} }
setSelectionData(data, tool) { setSelectionData(data, tool) {
@ -121,10 +129,13 @@ class MoveSelectionTool extends DrawingTool {
} }
} }
endSelection() { endSelection(event) {
if (this.currSelection == undefined) if (this.currSelection == undefined)
return; return;
this.currSelection = undefined; this.currSelection = undefined;
this.selectionTool.pasteSelection(); this.selectionTool.pasteSelection();
if (event)
this.switchFunc(this.selectionTool);
} }
} }

View File

@ -5,8 +5,12 @@ class RectangularSelectionTool extends SelectionTool {
Events.on('click', this.mainButton, switchFunc, this); Events.on('click', this.mainButton, switchFunc, this);
} }
onStart(mousePos) { onStart(mousePos, mouseTarget) {
super.onStart(mousePos); super.onStart(mousePos, mouseTarget);
if (Util.isChildOfByClass(mouseTarget, "editor-top-menu") ||
!Util.cursorInCanvas(currFile.canvasSize, [mousePos[0]/currFile.zoom, mousePos[1]/currFile.zoom]))
return;
// Avoiding external selections // Avoiding external selections
if (this.startMousePos[0] < 0) { if (this.startMousePos[0] < 0) {
@ -27,17 +31,25 @@ class RectangularSelectionTool extends SelectionTool {
this.drawSelection(this.startMousePos[0], this.startMousePos[1]); this.drawSelection(this.startMousePos[0], this.startMousePos[1]);
} }
onDrag(mousePos) { onDrag(mousePos, mouseTarget) {
super.onDrag(mousePos); super.onDrag(mousePos, mouseTarget);
if (Util.isChildOfByClass(mouseTarget, "editor-top-menu") ||
!Util.cursorInCanvas(currFile.canvasSize, [mousePos[0]/currFile.zoom, mousePos[1]/currFile.zoom]))
return;
// Drawing the rect // Drawing the rect
this.endMousePos = [Math.floor(mousePos[0] / currFile.zoom), Math.floor(mousePos[1] / currFile.zoom)]; this.endMousePos = [Math.floor(mousePos[0] / currFile.zoom), Math.floor(mousePos[1] / currFile.zoom)];
this.drawSelection(Math.floor(mousePos[0] / currFile.zoom), Math.floor(mousePos[1] / currFile.zoom)); this.drawSelection(Math.floor(mousePos[0] / currFile.zoom), Math.floor(mousePos[1] / currFile.zoom));
} }
onEnd(mousePos) { onEnd(mousePos, mouseTarget) {
super.onEnd(mousePos); super.onEnd(mousePos, mouseTarget);
if (Util.isChildOfByClass(mouseTarget, "editor-top-menu") ||
!Util.cursorInCanvas(currFile.canvasSize, [mousePos[0]/currFile.zoom, mousePos[1]/currFile.zoom]))
return;
new HistoryState().EditCanvas(); new HistoryState().EditCanvas();
// Getting the end position // Getting the end position

View File

@ -20,9 +20,13 @@ class SelectionTool extends Tool {
this.switchFunc = switchFunc; this.switchFunc = switchFunc;
} }
onStart(mousePos) { onStart(mousePos, mouseTarget) {
super.onStart(mousePos); super.onStart(mousePos);
if (mouseTarget == undefined || Util.isChildOfByClass(mouseTarget, "editor-top-menu") ||
!Util.cursorInCanvas(currFile.canvasSize, [mousePos[0]/currFile.zoom, mousePos[1]/currFile.zoom]))
return;
// Putting the vfx layer on top of everything // Putting the vfx layer on top of everything
currFile.VFXLayer.canvas.style.zIndex = MAX_Z_INDEX; currFile.VFXLayer.canvas.style.zIndex = MAX_Z_INDEX;
currFile.VFXLayer.context.fillStyle = "rgba(0,0,0,1)"; currFile.VFXLayer.context.fillStyle = "rgba(0,0,0,1)";
@ -47,6 +51,7 @@ class SelectionTool extends Tool {
onDrag(mousePos) { onDrag(mousePos) {
super.onDrag(mousePos); super.onDrag(mousePos);
console.log("drag");
let mouseX = mousePos[0] / currFile.zoom; let mouseX = mousePos[0] / currFile.zoom;
let mouseY = mousePos[1] / currFile.zoom; let mouseY = mousePos[1] / currFile.zoom;
@ -65,9 +70,13 @@ class SelectionTool extends Tool {
Math.min(Math.max(mouseY, 0), currFile.canvasSize[1]-1)); Math.min(Math.max(mouseY, 0), currFile.canvasSize[1]-1));
} }
onEnd(mousePos) { onEnd(mousePos, mouseTarget) {
super.onEnd(mousePos); super.onEnd(mousePos);
if (mouseTarget == undefined || Util.isChildOfByClass(mouseTarget, "editor-top-menu") ||
!Util.cursorInCanvas(currFile.canvasSize, [mousePos[0]/currFile.zoom, mousePos[1]/currFile.zoom]))
return;
let mouseX = mousePos[0] / currFile.zoom; let mouseX = mousePos[0] / currFile.zoom;
let mouseY = mousePos[1] / currFile.zoom; let mouseY = mousePos[1] / currFile.zoom;
@ -232,10 +241,12 @@ class SelectionTool extends Tool {
this.previewData = new ImageData(currFile.canvasSize[0], currFile.canvasSize[1]); this.previewData = new ImageData(currFile.canvasSize[0], currFile.canvasSize[1]);
// Cut the selection // Cut the selection
this.cutSelection(); this.cutSelection();
// Put it on the TMP layer // Put it on the TMP layer
currFile.TMPLayer.context.putImageData(this.previewData, 0, 0); currFile.TMPLayer.context.putImageData(this.previewData, 0, 0);
// Draw the selected area and the bounding box
this.drawSelectedArea(); this.drawSelectedArea();
this.drawBoundingBox();
return this.previewData; return this.previewData;
} }
@ -359,6 +370,18 @@ class SelectionTool extends Tool {
this.boundingBox.minY + this.moveOffset[1]); this.boundingBox.minY + this.moveOffset[1]);
} }
drawBoundingBox() {
currFile.VFXLayer.context.fillStyle = "red";
currFile.VFXLayer.context.fillRect(this.boundingBox.minX + this.moveOffset[0],
this.boundingBox.minY + this.moveOffset[1], 1, 1);
currFile.VFXLayer.context.fillRect(this.boundingBox.minX+ this.moveOffset[0],
this.boundingBox.maxY + this.moveOffset[1], 1, 1);
currFile.VFXLayer.context.fillRect(this.boundingBox.maxX+ this.moveOffset[0],
this.boundingBox.minY + this.moveOffset[1], 1, 1);
currFile.VFXLayer.context.fillRect(this.boundingBox.maxX+ this.moveOffset[0],
this.boundingBox.maxY + this.moveOffset[1], 1, 1);
}
isBorderOfBox(pixel) { isBorderOfBox(pixel) {
return pixel[0] == this.boundingBox.minX || pixel[0] == this.boundingBox.maxX || return pixel[0] == this.boundingBox.minX || pixel[0] == this.boundingBox.maxX ||
pixel[1] == this.boundingBox.minY || pixel[1] == this.boundingBox.maxY; pixel[1] == this.boundingBox.minY || pixel[1] == this.boundingBox.maxY;