2021-12-27 21:11:59 +03:00
|
|
|
class LassoSelectionTool extends SelectionTool {
|
2021-12-30 01:16:16 +03:00
|
|
|
currentPixels = [];
|
|
|
|
currSelection = {};
|
2022-01-02 23:57:35 +03:00
|
|
|
boundingBox = {minX: 9999999, maxX: -1, minY: 9999999, maxY: -1};
|
2021-12-29 00:51:18 +03:00
|
|
|
|
2021-12-27 21:11:59 +03:00
|
|
|
constructor (name, options, switchFunc, moveTool) {
|
2021-12-27 21:40:23 +03:00
|
|
|
super(name, options, switchFunc, moveTool);
|
2021-12-29 00:51:18 +03:00
|
|
|
Events.on('click', this.mainButton, switchFunc, this);
|
2021-12-27 21:11:59 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
onStart(mousePos) {
|
|
|
|
super.onStart(mousePos);
|
2021-12-29 00:51:18 +03:00
|
|
|
|
|
|
|
// Putting the vfx layer on top of everything
|
|
|
|
currFile.VFXLayer.canvas.style.zIndex = MAX_Z_INDEX;
|
|
|
|
// clearSelection();
|
2022-01-05 14:02:35 +03:00
|
|
|
this.boundingBox = {minX: 9999999, maxX: -1, minY: 9999999, maxY: -1};
|
2021-12-29 00:51:18 +03:00
|
|
|
this.currentPixels = [];
|
|
|
|
this.drawSelection();
|
2022-01-02 23:57:35 +03:00
|
|
|
this.currentPixels.push([mousePos[0] / currFile.zoom, mousePos[1] / currFile.zoom]);
|
2021-12-27 21:11:59 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
onDrag(mousePos) {
|
|
|
|
super.onDrag(mousePos);
|
2021-12-29 00:51:18 +03:00
|
|
|
|
2022-01-02 23:57:35 +03:00
|
|
|
let mouseX = mousePos[0] / currFile.zoom;
|
|
|
|
let mouseY = mousePos[1] / currFile.zoom;
|
2021-12-30 01:16:16 +03:00
|
|
|
|
2021-12-29 00:51:18 +03:00
|
|
|
if (this.currentPixels[this.currentPixels.length - 1] != mousePos)
|
2022-01-02 23:57:35 +03:00
|
|
|
this.currentPixels.push([mousePos[0] / currFile.zoom, mousePos[1] / currFile.zoom]);
|
2021-12-29 00:51:18 +03:00
|
|
|
this.drawSelection();
|
2022-01-02 23:57:35 +03:00
|
|
|
|
|
|
|
if (mouseX > this.boundingBox.maxX)
|
|
|
|
this.boundingBox.maxX = Math.floor(mouseX);
|
|
|
|
if (mouseX < this.boundingBox.minX)
|
|
|
|
this.boundingBox.minX = Math.floor(mouseX);
|
|
|
|
if (mouseY < this.boundingBox.minY)
|
|
|
|
this.boundingBox.minY = Math.floor(mouseY);
|
|
|
|
if (mouseY > this.boundingBox.maxY)
|
|
|
|
this.boundingBox.maxY = Math.floor(mouseY);
|
2021-12-27 21:11:59 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
onEnd(mousePos) {
|
|
|
|
super.onEnd(mousePos);
|
2021-12-29 01:14:37 +03:00
|
|
|
new HistoryState().EditCanvas();
|
|
|
|
|
2022-01-02 23:57:35 +03:00
|
|
|
this.currentPixels.push([this.startMousePos[0] / currFile.zoom, this.startMousePos[1] / currFile.zoom]);
|
2021-12-29 01:14:37 +03:00
|
|
|
this.getSelection();
|
|
|
|
|
|
|
|
// Switch to the move tool so that the user can move the selection
|
|
|
|
this.switchFunc(this.moveTool);
|
2021-12-30 01:16:16 +03:00
|
|
|
this.moveTool.setSelectionData(null, this);
|
2021-12-27 21:11:59 +03:00
|
|
|
}
|
|
|
|
|
2021-12-29 00:51:18 +03:00
|
|
|
onSelect() {
|
|
|
|
super.onSelect();
|
2021-12-27 21:11:59 +03:00
|
|
|
}
|
|
|
|
|
2021-12-29 00:51:18 +03:00
|
|
|
onDeselect() {
|
|
|
|
super.onDeselect();
|
2021-12-27 21:11:59 +03:00
|
|
|
}
|
|
|
|
|
2021-12-29 00:51:18 +03:00
|
|
|
drawSelection() {
|
|
|
|
if (this.currentPixels.length <= 1)
|
|
|
|
return;
|
|
|
|
let point = [];
|
2022-01-02 23:57:35 +03:00
|
|
|
let prevPoint = [];
|
2021-12-29 00:51:18 +03:00
|
|
|
|
|
|
|
currFile.VFXLayer.context.clearRect(0, 0, currFile.canvasSize[0], currFile.canvasSize[1]);
|
|
|
|
currFile.VFXLayer.context.strokeStyle = 'rgba(0,0,0,1)';
|
|
|
|
currFile.VFXLayer.context.fillStyle = 'rgba(0,0,0,1)';
|
|
|
|
currFile.VFXLayer.context.lineWidth = 1;
|
|
|
|
currFile.VFXLayer.context.beginPath();
|
2021-12-27 21:11:59 +03:00
|
|
|
|
2021-12-29 00:51:18 +03:00
|
|
|
for (var index = 0; index < this.currentPixels.length; index ++) {
|
|
|
|
point = this.currentPixels[index];
|
|
|
|
|
|
|
|
if (index == 0)
|
|
|
|
currFile.VFXLayer.context.moveTo(point[0], point[1]);
|
|
|
|
else {
|
2022-01-02 23:57:35 +03:00
|
|
|
prevPoint = this.currentPixels[index- 1];
|
2021-12-29 00:51:18 +03:00
|
|
|
currFile.VFXLayer.context.lineTo(point[0], point[1]);
|
2022-01-02 23:57:35 +03:00
|
|
|
currFile.VFXLayer.drawLine(Math.floor(prevPoint[0]), Math.floor(prevPoint[1]),
|
|
|
|
Math.floor(point[0]), Math.floor(point[1]), 1);
|
2021-12-29 00:51:18 +03:00
|
|
|
}
|
|
|
|
}
|
2022-01-02 23:57:35 +03:00
|
|
|
|
|
|
|
currFile.VFXLayer.drawLine(Math.floor(prevPoint[0]), Math.floor(prevPoint[1]),
|
|
|
|
Math.floor(this.startMousePos[0] / currFile.zoom), Math.floor(this.startMousePos[1] / currFile.zoom), 1);
|
|
|
|
currFile.VFXLayer.context.lineTo(this.startMousePos[0] / currFile.zoom, this.startMousePos[1] / currFile.zoom);
|
|
|
|
|
2021-12-29 00:51:18 +03:00
|
|
|
currFile.VFXLayer.context.fillStyle = 'rgba(0,0,0,0.3)';
|
|
|
|
currFile.VFXLayer.context.fill();
|
|
|
|
currFile.VFXLayer.context.closePath();
|
2021-12-27 21:11:59 +03:00
|
|
|
}
|
2021-12-29 01:38:28 +03:00
|
|
|
|
2021-12-30 01:16:16 +03:00
|
|
|
cursorInSelectedArea(mousePos) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-01-05 02:10:02 +03:00
|
|
|
isBorderOfBox(pixel) {
|
|
|
|
return pixel[0] == this.boundingBox.minX || pixel[0] == this.boundingBox.maxX ||
|
|
|
|
pixel[1] == this.boundingBox.minY || pixel[1] == this.boundingBox.maxY;
|
|
|
|
}
|
|
|
|
|
|
|
|
visit(pixel, visited) {
|
|
|
|
let toVisit = [pixel];
|
|
|
|
let selected = [];
|
2022-01-05 14:02:35 +03:00
|
|
|
let currVisited = {};
|
2022-01-05 02:10:02 +03:00
|
|
|
|
|
|
|
while (toVisit.length > 0) {
|
|
|
|
pixel = toVisit.pop();
|
|
|
|
selected.push(pixel);
|
2022-01-05 14:02:35 +03:00
|
|
|
|
|
|
|
visited[pixel] = true;
|
|
|
|
currVisited[pixel] = true;
|
2022-01-05 02:10:02 +03:00
|
|
|
|
|
|
|
let col = currFile.VFXLayer.context.getImageData(pixel[0], pixel[1], 1, 1).data;
|
|
|
|
if (col[3] == 255)
|
|
|
|
continue;
|
2022-01-05 14:02:35 +03:00
|
|
|
if (this.isBorderOfBox(pixel))
|
|
|
|
return [];
|
2022-01-05 02:10:02 +03:00
|
|
|
|
|
|
|
let top, bottom, left, right;
|
|
|
|
if (pixel[1] > 0)
|
|
|
|
top = [pixel[0], pixel[1] - 1];
|
|
|
|
else
|
|
|
|
top = undefined;
|
|
|
|
|
|
|
|
if (pixel[0] > 0)
|
|
|
|
left = [pixel[0] - 1, pixel[1]];
|
|
|
|
else
|
|
|
|
left = undefined;
|
|
|
|
|
|
|
|
if (pixel[1] < currFile.canvasSize[1])
|
|
|
|
bottom = [pixel[0], pixel[1] + 1];
|
|
|
|
else
|
|
|
|
bottom = undefined;
|
|
|
|
|
|
|
|
if (pixel[0] < currFile.canvasSize[0])
|
|
|
|
right = [pixel[0] + 1, pixel[1]];
|
|
|
|
else
|
|
|
|
right = undefined;
|
|
|
|
|
|
|
|
// The include problem: https://stackoverflow.com/questions/19543514/check-whether-an-array-exists-in-an-array-of-arrays
|
2022-01-05 14:02:35 +03:00
|
|
|
if (right != undefined && currVisited[right] == undefined)
|
2022-01-05 02:10:02 +03:00
|
|
|
toVisit.push(right);
|
2022-01-05 14:02:35 +03:00
|
|
|
if (left != undefined && currVisited[left] == undefined)
|
2022-01-05 02:10:02 +03:00
|
|
|
toVisit.push(left);
|
2022-01-05 14:02:35 +03:00
|
|
|
if (top != undefined && currVisited[top] == undefined)
|
2022-01-05 02:10:02 +03:00
|
|
|
toVisit.push(top);
|
2022-01-05 14:02:35 +03:00
|
|
|
if (bottom != undefined && currVisited[bottom] == undefined)
|
2022-01-05 02:10:02 +03:00
|
|
|
toVisit.push(bottom);
|
|
|
|
}
|
|
|
|
|
|
|
|
return selected;
|
|
|
|
}
|
|
|
|
|
2021-12-29 01:38:28 +03:00
|
|
|
getSelection() {
|
2021-12-30 01:16:16 +03:00
|
|
|
let selected = [];
|
2022-01-05 14:02:35 +03:00
|
|
|
let visited = {};
|
2021-12-30 01:16:16 +03:00
|
|
|
if (this.currentPixels.length <= 1){
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-01-05 02:10:02 +03:00
|
|
|
/** I'm once again asking you to make a BFS
|
|
|
|
* - This time since I'm dumb check all pixels in the bounding box
|
|
|
|
* - Start a BFS: stop when you reach the border of the bounding box:
|
|
|
|
* - In that case all the pixels you visited aren't part of the selection
|
|
|
|
* - Also stop when you touch black:
|
|
|
|
* - If you haven't found the border of the bounding box, then all the pixels you visited
|
|
|
|
* are inside the selection
|
|
|
|
*/
|
|
|
|
|
2022-01-05 14:02:35 +03:00
|
|
|
for (let x=this.boundingBox.minX; x<=this.boundingBox.maxX; x++) {
|
|
|
|
for (let y=this.boundingBox.minY; y<=this.boundingBox.maxY; y++) {
|
|
|
|
if (visited[x, y] == undefined) {
|
2022-01-05 02:10:02 +03:00
|
|
|
let insidePixels = this.visit([x,y], visited);
|
2021-12-30 01:16:16 +03:00
|
|
|
|
2022-01-05 14:02:35 +03:00
|
|
|
for (let i=0; i<insidePixels.length; i++) {
|
2022-01-05 02:10:02 +03:00
|
|
|
selected.push(insidePixels[i]);
|
|
|
|
}
|
2021-12-30 01:16:16 +03:00
|
|
|
}
|
|
|
|
}
|
2022-01-02 23:57:35 +03:00
|
|
|
}
|
2021-12-29 01:38:28 +03:00
|
|
|
|
2021-12-30 01:16:16 +03:00
|
|
|
for (let i=0; i<selected.length; i++) {
|
|
|
|
currFile.VFXLayer.context.fillStyle = "red";
|
|
|
|
currFile.VFXLayer.context.fillRect(selected[i][0], selected[i][1], 1, 1);
|
|
|
|
}
|
2021-12-29 01:38:28 +03:00
|
|
|
}
|
2021-12-27 21:11:59 +03:00
|
|
|
}
|