2021-12-13 00:50:21 +03:00
|
|
|
class FillTool extends DrawingTool {
|
2021-10-31 20:31:45 +03:00
|
|
|
constructor(name, options, switchFunction) {
|
|
|
|
super(name, options);
|
|
|
|
|
|
|
|
Events.on('click', this.mainButton, switchFunction, this);
|
2022-01-30 02:09:43 +03:00
|
|
|
|
|
|
|
this.resetTutorial();
|
|
|
|
this.addTutorialTitle("Fill tool");
|
|
|
|
this.addTutorialKey("F", " to select the fill tool");
|
|
|
|
this.addTutorialKey("Left click", " to fill a contiguous area");
|
|
|
|
this.addTutorialImg("fill-tutorial.gif");
|
2021-10-31 20:31:45 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
onStart(mousePos, target) {
|
|
|
|
super.onStart(mousePos);
|
|
|
|
|
|
|
|
if (target.className != 'drawingCanvas')
|
|
|
|
return;
|
2022-01-26 01:47:01 +03:00
|
|
|
new HistoryState().EditCanvas();
|
2022-01-23 18:07:04 +03:00
|
|
|
FillTool.fill(mousePos);
|
2021-12-06 19:37:43 +03:00
|
|
|
currFile.currentLayer.updateLayerPreview();
|
2021-10-31 20:31:45 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-01-23 15:32:23 +03:00
|
|
|
static fill(cursorLocation, context) {
|
2021-10-31 20:31:45 +03:00
|
|
|
//changes a pixels color
|
|
|
|
function colorPixel(tempImage, pixelPos, fillColor) {
|
|
|
|
//console.log('colorPixel:',pixelPos);
|
|
|
|
tempImage.data[pixelPos] = fillColor.r;
|
|
|
|
tempImage.data[pixelPos + 1] = fillColor.g;
|
|
|
|
tempImage.data[pixelPos + 2] = fillColor.b;
|
|
|
|
tempImage.data[pixelPos + 3] = 255;
|
|
|
|
}
|
|
|
|
|
|
|
|
//change x y to color value passed from the function and use that as the original color
|
|
|
|
function matchStartColor(tempImage, pixelPos, color) {
|
|
|
|
//console.log('matchPixel:',x,y)
|
|
|
|
|
|
|
|
let r = tempImage.data[pixelPos];
|
|
|
|
let g = tempImage.data[pixelPos + 1];
|
|
|
|
let b = tempImage.data[pixelPos + 2];
|
|
|
|
let a = tempImage.data[pixelPos + 3];
|
|
|
|
//console.log(r == color[0] && g == color[1] && b == color[2]);
|
|
|
|
return (r == color[0] && g == color[1] && b == color[2] && a == color[3]);
|
|
|
|
}
|
|
|
|
|
2022-01-23 15:32:23 +03:00
|
|
|
if (context == undefined)
|
|
|
|
context = currFile.currentLayer.context;
|
|
|
|
|
2021-10-31 20:31:45 +03:00
|
|
|
//temporary image holds the data while we change it
|
2022-01-23 15:32:23 +03:00
|
|
|
let tempImage = context.getImageData(0, 0, currFile.canvasSize[0], currFile.canvasSize[1]);
|
2021-10-31 20:31:45 +03:00
|
|
|
|
|
|
|
//this is an array that holds all of the pixels at the top of the cluster
|
2021-12-06 19:37:43 +03:00
|
|
|
let topmostPixelsArray = [[Math.floor(cursorLocation[0]/currFile.zoom), Math.floor(cursorLocation[1]/currFile.zoom)]];
|
2021-10-31 20:31:45 +03:00
|
|
|
//console.log('topmostPixelsArray:',topmostPixelsArray)
|
|
|
|
|
|
|
|
//the offset of the pixel in the temp image data to start with
|
2021-12-06 19:37:43 +03:00
|
|
|
let startingPosition = (topmostPixelsArray[0][1] * currFile.canvasSize[0] + topmostPixelsArray[0][0]) * 4;
|
2021-10-31 20:31:45 +03:00
|
|
|
|
|
|
|
//the color of the cluster that is being filled
|
|
|
|
let clusterColor = [tempImage.data[startingPosition],tempImage.data[startingPosition+1],tempImage.data[startingPosition+2], tempImage.data[startingPosition+3]];
|
|
|
|
|
2021-11-09 00:25:30 +03:00
|
|
|
//the color to fill with
|
2022-01-23 15:32:23 +03:00
|
|
|
let fillColor = Color.hexToRgb(context.fillStyle);
|
2021-10-31 20:31:45 +03:00
|
|
|
|
|
|
|
//if you try to fill with the same color that's already there, exit the function
|
|
|
|
if (clusterColor[0] == fillColor.r &&
|
|
|
|
clusterColor[1] == fillColor.g &&
|
|
|
|
clusterColor[2] == fillColor.b &&
|
|
|
|
clusterColor[3] != 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//loop until there are no more values left in this array
|
|
|
|
while (topmostPixelsArray.length) {
|
|
|
|
let reachLeft, reachRight;
|
|
|
|
|
|
|
|
//move the most recent pixel from the array and set it as our current working pixels
|
|
|
|
let currentPixel = topmostPixelsArray.pop();
|
|
|
|
|
|
|
|
//set the values of this pixel to x/y variables just for readability
|
|
|
|
let x = currentPixel[0];
|
|
|
|
let y = currentPixel[1];
|
|
|
|
|
|
|
|
//this variable holds the index of where the starting values for the current pixel are in the data array
|
|
|
|
//we multiply the number of rows down (y) times the width of each row, then add x. at the end we multiply by 4 because
|
|
|
|
//each pixel has 4 values, rgba
|
2021-12-06 19:37:43 +03:00
|
|
|
let pixelPos = (y * currFile.canvasSize[0] + x) * 4;
|
2021-10-31 20:31:45 +03:00
|
|
|
|
|
|
|
//move up in the image until you reach the top or the pixel you hit was not the right color
|
|
|
|
while (y-- >= 0 && matchStartColor(tempImage, pixelPos, clusterColor)) {
|
2021-12-06 19:37:43 +03:00
|
|
|
pixelPos -= currFile.canvasSize[0] * 4;
|
2021-10-31 20:31:45 +03:00
|
|
|
}
|
2021-12-06 19:37:43 +03:00
|
|
|
pixelPos += currFile.canvasSize[0] * 4;
|
2021-10-31 20:31:45 +03:00
|
|
|
++y;
|
|
|
|
reachLeft = false;
|
|
|
|
reachRight = false;
|
2021-11-09 00:25:30 +03:00
|
|
|
|
2021-12-06 19:37:43 +03:00
|
|
|
while (y++ < currFile.canvasSize[1] - 1 && matchStartColor(tempImage, pixelPos, clusterColor)) {
|
2021-10-31 20:31:45 +03:00
|
|
|
colorPixel(tempImage, pixelPos, fillColor);
|
|
|
|
if (x > 0) {
|
|
|
|
if (matchStartColor(tempImage, pixelPos - 4, clusterColor)) {
|
|
|
|
if (!reachLeft) {
|
|
|
|
topmostPixelsArray.push([x - 1, y]);
|
|
|
|
reachLeft = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (reachLeft) {
|
|
|
|
reachLeft = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-06 19:37:43 +03:00
|
|
|
if (x < currFile.canvasSize[0] - 1) {
|
2021-10-31 20:31:45 +03:00
|
|
|
if (matchStartColor(tempImage, pixelPos + 4, clusterColor)) {
|
|
|
|
if (!reachRight) {
|
|
|
|
topmostPixelsArray.push([x + 1, y]);
|
|
|
|
reachRight = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (reachRight) {
|
|
|
|
reachRight = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-06 19:37:43 +03:00
|
|
|
pixelPos += currFile.canvasSize[0] * 4;
|
2021-10-31 20:31:45 +03:00
|
|
|
}
|
|
|
|
}
|
2022-01-23 15:32:23 +03:00
|
|
|
context.putImageData(tempImage, 0, 0);
|
2021-10-31 20:31:45 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
onDrag(mousePos, cursorTarget) {
|
|
|
|
}
|
|
|
|
|
|
|
|
onEnd(mousePos) {
|
|
|
|
super.onEnd(mousePos);
|
|
|
|
}
|
|
|
|
|
|
|
|
onSelect() {
|
|
|
|
super.onSelect();
|
|
|
|
}
|
|
|
|
|
|
|
|
onDeselect() {
|
|
|
|
super.onDeselect();
|
|
|
|
}
|
|
|
|
}
|