From 161687a2f6b590825f925343d322af3049ff70e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Marino=CC=80?= Date: Sat, 5 Feb 2022 11:50:17 +0100 Subject: [PATCH] rectangle symmetry --- js/tools/BrushTool.js | 1 - js/tools/RectangleTool.js | 300 ++++++++++++++++++++++++++++++++++---- 2 files changed, 274 insertions(+), 27 deletions(-) diff --git a/js/tools/BrushTool.js b/js/tools/BrushTool.js index fb8ac33..f760180 100644 --- a/js/tools/BrushTool.js +++ b/js/tools/BrushTool.js @@ -81,7 +81,6 @@ class BrushTool extends ResizableTool { } if (currFile.hSymmetricLayer.isEnabled && currFile.vSymmetricLayer.isEnabled) { - // Based on current mouse position we can infer which quadrant is the remaining one this.mirrorDraw(mirrorPrevX, mirrorPrevY, mirrorCurrentX, mirrorCurrentY, true, true); } } diff --git a/js/tools/RectangleTool.js b/js/tools/RectangleTool.js index 9d4bfcc..af5228b 100644 --- a/js/tools/RectangleTool.js +++ b/js/tools/RectangleTool.js @@ -10,6 +10,11 @@ class RectangleTool extends ResizableTool { switchFunction = null; + // startX, startY, endX, endY of mirrored rectangles + horizontalMirrorCoordinates = []; + verticalMirrorCoordinates = []; + fourthQuadrantCoordinates = []; + constructor(name, options, switchFunction) { super(name, options); @@ -67,7 +72,157 @@ class RectangleTool extends ResizableTool { let startRectX = this.startMousePos[0]; let startRectY = this.startMousePos[1]; - // Inverting end and start (start must always be the top left corner) + const coordinates = this.adjustCoordinates( + endRectX, + startRectX, + endRectY, + startRectY + ); + + endRectX = coordinates.endRectX; + startRectX = coordinates.startRectX; + endRectY = coordinates.endRectY; + startRectY = coordinates.startRectY; + + // Setting the correct linewidth and colour + currFile.currentLayer.context.lineWidth = this.currSize; + + // Drawing the rect using 4 lines + this.drawFinalRect(startRectX, startRectY, endRectX, endRectY); + + // If I have to fill it, I do so + if (this.currFillMode == 'fill') { + currFile.currentLayer.context.fillRect(startRectX, startRectY, endRectX - startRectX, endRectY - startRectY); + } + + this.clearCanvas(tmpContext); + + if (currFile.hSymmetricLayer.isEnabled) { + if (typeof this.horizontalMirrorCoordinates != 'undefined') { + + let startMirrorRectX = this.horizontalMirrorCoordinates[0]; + let startMirrorRectY = this.horizontalMirrorCoordinates[1]; + let endMirrorRectX = this.horizontalMirrorCoordinates[2]; + let endMirrorRectY = this.horizontalMirrorCoordinates[3]; + + this.handleMirrorRectDrawing( + endMirrorRectX, + startMirrorRectX, + endMirrorRectY, + startMirrorRectY, + tmpContext + ); + } + } + + if (currFile.vSymmetricLayer.isEnabled) { + if (typeof this.verticalMirrorCoordinates != 'undefined') { + + let startMirrorRectX = this.verticalMirrorCoordinates[0]; + let startMirrorRectY = this.verticalMirrorCoordinates[1]; + let endMirrorRectX = this.verticalMirrorCoordinates[2]; + let endMirrorRectY = this.verticalMirrorCoordinates[3]; + + this.handleMirrorRectDrawing( + endMirrorRectX, + startMirrorRectX, + endMirrorRectY, + startMirrorRectY, + tmpContext + ); + } + } + + if (currFile.hSymmetricLayer.isEnabled && currFile.vSymmetricLayer.isEnabled) { + if (typeof this.fourthQuadrantCoordinates != 'undefined') { + let startMirrorRectX = this.fourthQuadrantCoordinates[0]; + let startMirrorRectY = this.fourthQuadrantCoordinates[1]; + let endMirrorRectX = this.fourthQuadrantCoordinates[2]; + let endMirrorRectY = this.fourthQuadrantCoordinates[3]; + + this.handleMirrorRectDrawing( + endMirrorRectX, + startMirrorRectX, + endMirrorRectY, + startMirrorRectY, + tmpContext + ); + } + } + + } + + /** + * It draws the mirror rectangle with adjustments. It also fills rectangle if needed + * @param endMirrorRectX + * @param startMirrorRectX + * @param endMirrorRectY + * @param startMirrorRectY + * @param tmpContext + */ + handleMirrorRectDrawing(endMirrorRectX, startMirrorRectX, endMirrorRectY, startMirrorRectY, tmpContext) { + const mirrorCoordinates = this.adjustCoordinates( + endMirrorRectX, + startMirrorRectX, + endMirrorRectY, + startMirrorRectY + ); + + endMirrorRectX = mirrorCoordinates.endRectX + startMirrorRectX = mirrorCoordinates.startRectX; + endMirrorRectY = mirrorCoordinates.endRectY + startMirrorRectY = mirrorCoordinates.startRectY; + + // Setting the correct linewidth and colour + currFile.currentLayer.context.lineWidth = this.currSize; + + this.drawFinalRect(startMirrorRectX, startMirrorRectY, endMirrorRectX, endMirrorRectY); + + // If I have to fill it, I do so + if (this.currFillMode == 'fill') { + currFile.currentLayer.context.fillRect( + startMirrorRectX, + startMirrorRectY, + endMirrorRectX - startMirrorRectX, + endMirrorRectY - startMirrorRectY + ); + } + this.clearCanvas(tmpContext); + } + + /** Updates the layer preview and clears the tmp canvas + * @param {*} tmpContext tmp canvas context + */ + clearCanvas(tmpContext) { + // Update the layer preview + currFile.currentLayer.updateLayerPreview(); + // Clearing the tmp canvas + tmpContext.clearRect(0, 0, currFile.TMPLayer.canvas.width, currFile.TMPLayer.canvas.height); + } + + /** + * Draws the final rectangle after preview (used in handleMirrorRectDrawing) + * @param startRectX + * @param startRectY + * @param endRectX + * @param endRectY + */ + drawFinalRect(startRectX, startRectY, endRectX, endRectY) { + currFile.currentLayer.drawLine(startRectX, startRectY, endRectX, startRectY, this.currSize); + currFile.currentLayer.drawLine(endRectX, startRectY, endRectX, endRectY, this.currSize); + currFile.currentLayer.drawLine(endRectX, endRectY, startRectX, endRectY, this.currSize); + currFile.currentLayer.drawLine(startRectX, endRectY, startRectX, startRectY, this.currSize); + } + + /** + * Rect coordinates adjustments before draw final rectangle (used in handleMirrorRectDrawing) + * @param endRectX + * @param startRectX + * @param endRectY + * @param startRectY + * @returns {{endRectY, endRectX, startRectY, startRectX}} + */ + adjustCoordinates(endRectX, startRectX, endRectY, startRectY) { if (endRectX < startRectX) { let tmp = endRectX; endRectX = startRectX; @@ -80,31 +235,12 @@ class RectangleTool extends ResizableTool { startRectY = tmp; } - // Drawing the rect - startRectY -= 0.5; - endRectY -= 0.5; - endRectX -= 0.5; startRectX -= 0.5; - - // Setting the correct linewidth and colour - currFile.currentLayer.context.lineWidth = this.currSize; - - // Drawing the rect using 4 lines - currFile.currentLayer.drawLine(startRectX, startRectY, endRectX, startRectY, this.currSize); - currFile.currentLayer.drawLine(endRectX, startRectY, endRectX, endRectY, this.currSize); - currFile.currentLayer.drawLine(endRectX, endRectY, startRectX, endRectY, this.currSize); - currFile.currentLayer.drawLine(startRectX, endRectY, startRectX, startRectY, this.currSize); - - // If I have to fill it, I do so - if (this.currFillMode == 'fill') { - currFile.currentLayer.context.fillRect(startRectX, startRectY, endRectX - startRectX, endRectY - startRectY); - } - - // Update the layer preview - currFile.currentLayer.updateLayerPreview(); - // Clearing the tmp canvas - tmpContext.clearRect(0, 0, currFile.TMPLayer.canvas.width, currFile.TMPLayer.canvas.height); - } + startRectY -= 0.5; + endRectX -= 0.5; + endRectY -= 0.5; + return {endRectX, startRectX, endRectY, startRectY}; + } onSelect() { super.onSelect(); @@ -136,10 +272,122 @@ class RectangleTool extends ResizableTool { tmpContext.rect(this.startMousePos[0] - 0.5, this.startMousePos[1] - 0.5, x - this.startMousePos[0], y - this.startMousePos[1]); } else { - tmpContext.rect(this.startMousePos[0], this.startMousePos[1], x - this.startMousePos[0], y - this.startMousePos[1]); + tmpContext.rect( + this.startMousePos[0], + this.startMousePos[1], + x - this.startMousePos[0], + y - this.startMousePos[1] + ); } tmpContext.setLineDash([]); tmpContext.stroke(); + + let midX = currFile.canvasSize[0] / 2; + let midY = currFile.canvasSize[1] / 2; + let startYMirror, endYMirror; + let startXMirror, endXMirror; + + // Handling horizontal symmetry + if (currFile.hSymmetricLayer.isEnabled) { + // check if start mouse position y is under the y axis + if (this.startMousePos[1] <= midY) { + // console.log("[RECT] => Drawing over the y axis"); + startYMirror = midY + Math.abs(midY - this.startMousePos[1]); + endYMirror = midY + Math.abs(midY - y); + } else { + // console.log("[RECT] => Drawing under the y axis"); + startYMirror = midY - Math.abs(midY - this.startMousePos[1]); + endYMirror = midY - Math.abs(midY - y); + } + + // Every time that a mirror is changed we must update mirrors array + tmpContext.beginPath(); + if ((this.currSize % 2 ) == 0) { + tmpContext.rect(this.startMousePos[0] - 0.5, startYMirror - 0.5, x - this.startMousePos[0], endYMirror - startYMirror); + } + else { + tmpContext.rect( + this.startMousePos[0], + startYMirror, + x - this.startMousePos[0], + endYMirror - startYMirror + ); + } + tmpContext.setLineDash([]); + tmpContext.stroke(); + + this.horizontalMirrorCoordinates = [ + this.startMousePos[0], // start mirror rect x + startYMirror, // start mirror rect y + x, // end mirror rect x + endYMirror// end mirror rect y + ]; + } + + // Handling vertical symmetry + if (currFile.vSymmetricLayer.isEnabled) { + if (this.startMousePos[0] <= midX) { + startXMirror = midX + Math.abs(midX - this.startMousePos[0]); + endXMirror = midX + Math.abs(midX - x); + } else { + startXMirror = midX - Math.abs(midX - this.startMousePos[0]); + endXMirror = midX - Math.abs(midX - x); + } + + tmpContext.beginPath(); + if ((this.currSize % 2 ) == 0) { + tmpContext.rect(startXMirror - 0.5, + this.startMousePos[1] - 0.5, + endXMirror - startXMirror, + y - this.startMousePos[1] + ); + } + else { + tmpContext.rect( + startXMirror, + this.startMousePos[1], + endXMirror - startXMirror, + y - this.startMousePos[1] + ); + } + tmpContext.setLineDash([]); + tmpContext.stroke(); + + this.verticalMirrorCoordinates = [ + startXMirror, // start mirror rect x + this.startMousePos[1], // start mirror rect y + endXMirror, // end mirror rect x + y// end mirror rect y + ]; + } + + if (currFile.hSymmetricLayer.isEnabled && currFile.vSymmetricLayer.isEnabled) { + tmpContext.beginPath(); + if ((this.currSize % 2 ) == 0) { + tmpContext.rect(startXMirror - 0.5, + startYMirror - 0.5, + endXMirror - startXMirror, + endYMirror - startYMirror + ); + } else { + tmpContext.rect( + startXMirror, + startYMirror, + endXMirror - startXMirror, + endYMirror - startYMirror + ); + } + tmpContext.setLineDash([]); + tmpContext.stroke(); + + this.fourthQuadrantCoordinates = [ + startXMirror, + startYMirror, + endXMirror, + endYMirror + ]; + } + } } \ No newline at end of file