From d034bbc659e252fa95876cc6ffc331b90dc07281 Mon Sep 17 00:00:00 2001 From: unsettledgames <47360416+unsettledgames@users.noreply.github.com> Date: Sun, 31 Oct 2021 18:31:45 +0100 Subject: [PATCH] Added back fill tool --- js/ToolManager.js | 4 +- js/_fill.js | 111 ---------------------------------- js/_toolButtons.js | 5 -- js/_tools.js | 49 +++++++-------- js/tools/FillTool.js | 139 +++++++++++++++++++++++++++++++++++++++++++ js/tools/_all.js | 4 -- 6 files changed, 163 insertions(+), 149 deletions(-) diff --git a/js/ToolManager.js b/js/ToolManager.js index 935fc2d..f8353fe 100644 --- a/js/ToolManager.js +++ b/js/ToolManager.js @@ -3,9 +3,11 @@ const ToolManager = (() => { eraserTool = new EraserTool("eraser", {type: 'html'}, switchTool); rectangleTool = new RectangleTool("rectangle", {type: 'html'}, switchTool); lineTool = new LineTool("line", {type: 'html'}, switchTool); + fillTool = new FillTool("fill", {type: 'cursor', pic: 'fill.png'}, switchTool); currTool = brushTool; currTool.onSelect(); + canvasView.style.cursor = 'default'; Events.on("mouseup", window, onMouseUp); Events.on("mousemove", window, onMouseMove); @@ -20,7 +22,7 @@ const ToolManager = (() => { switch(mouseEvent.which) { case 1: if (!Input.isDragging()) { - currTool.onStart(mousePos); + currTool.onStart(mousePos, mouseEvent.target); } break; case 2: diff --git a/js/_fill.js b/js/_fill.js index bac646c..e69de29 100644 --- a/js/_fill.js +++ b/js/_fill.js @@ -1,111 +0,0 @@ -// REFACTOR: fill tool onMouseDown -function fill(cursorLocation) { - - //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) - - var r = tempImage.data[pixelPos]; - var g = tempImage.data[pixelPos + 1]; - var b = tempImage.data[pixelPos + 2]; - var 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]); - } - - //save history state - new HistoryState().EditCanvas(); - //saveHistoryState({type: 'canvas', canvas: context.getImageData(0, 0, canvasSize[0], canvasSize[1])}); - //console.log('filling at '+ Math.floor(cursorLocation[0]/zoom) + ','+ Math.floor(cursorLocation[1]/zoom)); - - //temporary image holds the data while we change it - var tempImage = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); - - //this is an array that holds all of the pixels at the top of the cluster - var topmostPixelsArray = [[Math.floor(cursorLocation[0]/zoom), Math.floor(cursorLocation[1]/zoom)]]; - //console.log('topmostPixelsArray:',topmostPixelsArray) - - //the offset of the pixel in the temp image data to start with - var startingPosition = (topmostPixelsArray[0][1] * canvasSize[0] + topmostPixelsArray[0][0]) * 4; - - //the color of the cluster that is being filled - var clusterColor = [tempImage.data[startingPosition],tempImage.data[startingPosition+1],tempImage.data[startingPosition+2], tempImage.data[startingPosition+3]]; - - //the new color to fill with - var fillColor = Color.hexToRgb(currentLayer.context.fillStyle); - - //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) { - console.log("Returned"); - return; - } - - - //loop until there are no more values left in this array - while (topmostPixelsArray.length) { - var reachLeft, reachRight; - - //move the most recent pixel from the array and set it as our current working pixels - var currentPixel = topmostPixelsArray.pop(); - - //set the values of this pixel to x/y variables just for readability - var x = currentPixel[0]; - var 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 - var pixelPos = (y * canvasSize[0] + x) * 4; - - //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)) { - pixelPos -= canvasSize[0] * 4; - } - pixelPos += canvasSize[0] * 4; - ++y; - reachLeft = false; - reachRight = false; - while (y++ < canvasSize[1] - 1 && matchStartColor(tempImage, pixelPos, clusterColor)) { - 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; - } - } - - if (x < canvasSize[0] - 1) { - if (matchStartColor(tempImage, pixelPos + 4, clusterColor)) { - if (!reachRight) { - topmostPixelsArray.push([x + 1, y]); - reachRight = true; - } - } - else if (reachRight) { - reachRight = false; - } - } - - pixelPos += canvasSize[0] * 4; - } - } - currentLayer.context.putImageData(tempImage, 0, 0); - //console.log('done filling') -} diff --git a/js/_toolButtons.js b/js/_toolButtons.js index 9f2d542..c66d4f7 100644 --- a/js/_toolButtons.js +++ b/js/_toolButtons.js @@ -27,11 +27,6 @@ Events.on('click',"ellipse-smaller-button", function(e){ tool.ellipse.brushSize--; }, false); -//fill -Events.on('click',"fill-button", function(){ - tool.fill.switchTo(); -}, false); - //pan Events.on('click',"pan-button", function(){ tool.pan.switchTo(); diff --git a/js/_tools.js b/js/_tools.js index 7bd52de..5d66c2e 100644 --- a/js/_tools.js +++ b/js/_tools.js @@ -37,20 +37,18 @@ class Tool { onSelect() { this.mainButton.parentElement.classList.add("selected"); this.isSelected = true; - /* - //copy options to this object - if (options.cursor) { - //passed statically as a string - if (typeof options.cursor == 'string') this.cursor = options.cursor; - //passed a function which should be used as a getter function - if (typeof options.cursor == 'function') Object.defineProperty(this, 'cursor', { get: options.cursor}); - if (options.imageCursor) this.cursor = "url(\'/pixel-editor/"+options.imageCursor+".png\'), auto"; - - if (options.brushPreview) { - this.brushPreview = true; - } - }*/ + switch (this.cursorType.type) { + case 'html': + canvasView.style.cursor = 'default'; + break; + case 'cursor': + this.cursor = "crosshair"; + canvasView.style.cursor = this.cursor || 'default'; + break; + default: + break; + } } updateCursor() {} @@ -68,22 +66,17 @@ class Tool { brushPreview.style.left = (Math.floor(cursorLocation[0] / zoom) * zoom + currentLayer.canvas.offsetLeft - this.currSize * zoom / 2 - zoom / 2 + toSub * zoom) + 'px'; brushPreview.style.top = (Math.floor(cursorLocation[1] / zoom) * zoom + currentLayer.canvas.offsetTop - this.currSize * zoom / 2 - zoom / 2 + toSub * zoom) + 'px'; - switch (this.cursorType.type) { - case 'html': - if (cursorTarget == 'drawingCanvas'|| cursorTarget.className == 'drawingCanvas') - brushPreview.style.visibility = 'visible'; - else - brushPreview.style.visibility = 'hidden'; + if (this.cursorType.type == 'html') { + if (cursorTarget == 'drawingCanvas'|| cursorTarget.className == 'drawingCanvas') { + brushPreview.style.visibility = 'visible'; + } + else { + brushPreview.style.visibility = 'hidden'; + } - brushPreview.style.display = 'block'; - brushPreview.style.width = this.currSize * zoom + 'px'; - brushPreview.style.height = this.currSize * zoom + 'px'; - break; - case 'cursor': - canvasView.style.cursor = this.cursor || 'default'; - break; - default: - break; + brushPreview.style.display = 'block'; + brushPreview.style.width = this.currSize * zoom + 'px'; + brushPreview.style.height = this.currSize * zoom + 'px'; } } diff --git a/js/tools/FillTool.js b/js/tools/FillTool.js index e69de29..e7d0c11 100644 --- a/js/tools/FillTool.js +++ b/js/tools/FillTool.js @@ -0,0 +1,139 @@ +class FillTool extends Tool { + constructor(name, options, switchFunction) { + super(name, options); + + Events.on('click', this.mainButton, switchFunction, this); + } + + onStart(mousePos, target) { + super.onStart(mousePos); + + if (target.className != 'drawingCanvas') + return; + this.fill(mousePos); + currentLayer.updateLayerPreview(); + } + + + fill(cursorLocation) { + //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]); + } + + //save history state + new HistoryState().EditCanvas(); + + //temporary image holds the data while we change it + let tempImage = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]); + + //this is an array that holds all of the pixels at the top of the cluster + let topmostPixelsArray = [[Math.floor(cursorLocation[0]/zoom), Math.floor(cursorLocation[1]/zoom)]]; + //console.log('topmostPixelsArray:',topmostPixelsArray) + + //the offset of the pixel in the temp image data to start with + let startingPosition = (topmostPixelsArray[0][1] * canvasSize[0] + topmostPixelsArray[0][0]) * 4; + + //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]]; + + //the new color to fill with + let fillColor = Color.hexToRgb(currentLayer.context.fillStyle); + + //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) { + console.log("Returned"); + 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 + let pixelPos = (y * canvasSize[0] + x) * 4; + + //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)) { + pixelPos -= canvasSize[0] * 4; + } + pixelPos += canvasSize[0] * 4; + ++y; + reachLeft = false; + reachRight = false; + while (y++ < canvasSize[1] - 1 && matchStartColor(tempImage, pixelPos, clusterColor)) { + 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; + } + } + + if (x < canvasSize[0] - 1) { + if (matchStartColor(tempImage, pixelPos + 4, clusterColor)) { + if (!reachRight) { + topmostPixelsArray.push([x + 1, y]); + reachRight = true; + } + } + else if (reachRight) { + reachRight = false; + } + } + + pixelPos += canvasSize[0] * 4; + } + } + currentLayer.context.putImageData(tempImage, 0, 0); + } + + onDrag(mousePos, cursorTarget) { + } + + onEnd(mousePos) { + super.onEnd(mousePos); + } + + onSelect() { + super.onSelect(); + } + + onDeselect() { + super.onDeselect(); + } +} \ No newline at end of file diff --git a/js/tools/_all.js b/js/tools/_all.js index ca77dc6..13a8264 100644 --- a/js/tools/_all.js +++ b/js/tools/_all.js @@ -2,10 +2,6 @@ new Tool('eyedropper', { imageCursor: 'eyedropper', }); -new Tool('fill', { - imageCursor: 'fill', -}); - new Tool('resizeline', { cursor: 'default', });