From 2b08f2b1b1d14c39e738e5a8d41a0f830acd9359 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Marino=CC=80?= Date: Mon, 27 Dec 2021 16:31:46 +0100 Subject: [PATCH 01/10] Started symmetry refactoring --- js/Startup.js | 8 + js/layers/SymmetryModule.js | 701 ++++++++++++++++++++++++++++++++++++ js/pixel-editor.js | 1 + views/canvases.hbs | 2 + views/main-menu.hbs | 2 + 5 files changed, 714 insertions(+) create mode 100644 js/layers/SymmetryModule.js diff --git a/js/Startup.js b/js/Startup.js index 999bb0a..3e7b8f5 100644 --- a/js/Startup.js +++ b/js/Startup.js @@ -106,6 +106,12 @@ const Startup = (() => { console.log("CREATED GRID"); currFile.pixelGrid = new PixelGrid(width, height, "pixel-grid"); + // Horizontal symmetric layer + let hSymmetricLayer = new Layer(width, height, SymmetryModule.hSymmetricCanvas); + // Vertical symmetric layer + let vSymmetricLayer = new Layer(width, height, SymmetryModule.vSymmetricCanvas); + SymmetryModule.initSymmetricCanvas(); + // Creating the vfx layer on top of everything currFile.VFXLayer = new Layer(width, height, 'vfx-canvas'); // Tmp layer to draw previews on @@ -118,6 +124,8 @@ const Startup = (() => { currFile.layers.push(currFile.TMPLayer); currFile.layers.push(currFile.pixelGrid); currFile.layers.push(currFile.VFXLayer); + currFile.layers.push(hSymmetricLayer); + currFile.layers.push(vSymmetricLayer); } } diff --git a/js/layers/SymmetryModule.js b/js/layers/SymmetryModule.js new file mode 100644 index 0000000..c91b900 --- /dev/null +++ b/js/layers/SymmetryModule.js @@ -0,0 +1,701 @@ +/** + * SymmetryModule holds the functions used to implement symmetry options. + */ + const SymmetryModule = (() => { + // Saving the canvas containing the horizontal symmetric line + const hSymmetricCanvas = document.getElementById("horizontal-symmetric"); + // Saving the canvas containing the vertical symmetric line + const vSymmetricCanvas = document.getElementById("vertical-symmetric"); + + // Binding events to callbacks + document.getElementById('toggle-horizontal-simmetry-button').addEventListener('click', toggleHorizontalSymmetry, false); + document.getElementById('toggle-vertical-simmetry-button').addEventListener('click', toggleVerticalSymmetry, false); + + // Symmetric axes properties + // The horizontal simmetry is not visible by default + let horizontalSimmetryVisible = false; + // The vertical simmetry is not visible by default + let verticalSimmetryVisible = false; + + const hAxisColor = "#FF0000"; + const vAxisColor = "#00FF00"; + + // dragging vars + var axisOriginX; // for the vertical axis + var axisOriginY; // for the horizontal axis + + function initSymmetricCanvas() { + hSymmetricCanvas.style.display = "none"; + vSymmetricCanvas.style.display = "none"; + } + + const ShapeType = { + RECT: "rect", + ELLIPSE: "ellipse", + } + + // getters for internal state + function getHorizontalSymmetryVisible() { + return horizontalSimmetryVisible; + } + + function getVerticalSymmetryVisible() { + return verticalSimmetryVisible; + } + + // ! + // * Some important notes about the symmetric axes + // * h/vDrawAxis function takes levelY/X in input, because you can choose + // * the origin y/x of the axis. In order to do that the level is multiplied + // * by the lineDistance. That's a good thing because the symmetric axis + // * dynamically changes when the lineDistance declared in _pixelGrid.js changes + // ! + + /** + * It draws the horizontal symmetric axis + * @param {*} levelY indicates at which y the line will be positionated + * @param {String} axisColor axis stroke color as string (i.e: 'red') + * @param {*} axisLineWidth axis stroke width + */ + function hDrawAxis(levelY, axisColor, axisLineWidth) { + + axisOriginY = levelY; + + console.log(axisOriginY); + + // pre-conditions + // if it is not possible to retrieve the context, return + if (!hSymmetricCanvas.getContext) { return; } + + const hCtx = hSymmetricCanvas.getContext("2d"); + let originalSize = currFile.layers[5].canvas; + + if (levelY > originalSize.height) { return; } + + // ? The hSymmetricCanvas is lineDistance times bigger so that the lines don't take 1 canvas pixel + // ? but they take 1/lineDistance canvas pixels + hSymmetricCanvas.width = originalSize.width * lineDistance; + hSymmetricCanvas.height = originalSize.height * lineDistance; + + // set the stroke line + hCtx.strokeStyle = axisColor; + hCtx.lineWidth = axisLineWidth; + + hCtx.beginPath(); + + hCtx.rect(0, levelY * lineDistance, originalSize.width * lineDistance, 0); + + hCtx.stroke(); + hCtx.closePath(); + + + } + + /** + * It draws the vertical symmetric axis + * @param {*} levelX indicates at which x the line will be positionated + * @param {String} axisColor axis stroke color as string (i.e: 'red') + * @param {*} axisLineWidth axis stroke width + */ + function vDrawAxis(levelX, axisColor, axisLineWidth) { + + axisOriginX = levelX; + + // if it is not possible to retrieve the context, return + if (!vSymmetricCanvas.getContext) { + return; + } + + const vCtx = vSymmetricCanvas.getContext("2d"); + let originalSize = currFile.layers[0].canvasSize; + + // ? The vSymmetricCanvas is lineDistance times bigger so that the lines don't take 1 canvas pixel + // ? but they take 1/lineDistance canvas pixels + vSymmetricCanvas.width = originalSize[0] * lineDistance; + vSymmetricCanvas.height = originalSize[1] * lineDistance; + + // set the stroke line + vCtx.strokeStyle = axisColor; + vCtx.lineWidth = axisLineWidth; + + vCtx.beginPath(); + + vCtx.rect(levelX * lineDistance, 0, 0, originalSize[1] * lineDistance); + + vCtx.stroke(); + vCtx.closePath(); + + } + + // ? For the moment both horizontal and vertical symmetry are centered only + + /** + * It toggles the horizontal symmetry in the editor + */ + function toggleHorizontalSymmetry() { + console.log("toggling"); + // Getting the button to change its text + let button = document.getElementById("toggle-horizontal-simmetry-button"); + let originalSize = currFile.layers[0].canvas; + + horizontalSimmetryVisible = !horizontalSimmetryVisible + + if (!horizontalSimmetryVisible) { + + // alert("Horizontal Simmetry OFF"); + button.innerHTML = "Horizontal Simmetry (Off)"; + hSymmetricCanvas.style.display = "none"; + + return; + } + + // alert("Horizontal Simmetry ON"); + button.innerHTML = "Horizontal Simmetry (On)"; + hSymmetricCanvas.style.display = "inline-block"; + + // DONE: Show an horizontal line on the canvas + hDrawAxis(originalSize.height / 4, 'blue', 1); + } + + /** + * It toggles the vertical symmetry in the editor + */ + function toggleVerticalSymmetry() { + // Getting the button to change its text + let button = document.getElementById("toggle-vertical-simmetry-button"); + let originalSize = currFile.layers[0].canvasSize; + + verticalSimmetryVisible = !verticalSimmetryVisible + + if (!verticalSimmetryVisible) { + + button.innerHTML = "Vertical Simmetry (Off)"; + vSymmetricCanvas.style.display = "none"; + + return; + + } + + // alert("Horizontal Simmetry ON"); + button.innerHTML = "Vertical Simmetry (On)"; + vSymmetricCanvas.style.display = "inline-block"; + + // DONE: Show an horizontal line on the canvas + vDrawAxis(originalSize[0] / 1.5, 'red', 1); + } + + // ! + // * Important notes on specular drawing + // * Suppose that we want to draw specular based on vertical axis: + // * the x of vertical line is by default layers[0].canvasSize[0]/2 + // * (I'm going to call it as "axisOriginX"). + // * If we draw a pixel at (pixelX: 3, pixelY: 2) it specular pixel will be at + // * (x: axisOriginX +- abs(axisOriginX - pixelX), y: pixelY) + // ! + + // ! At the moment the axis origin X/Y is layers[0].canvasSize[0/1]/2 + + // TODO: Mirroring the line + function drawLineSpecular(cursorPosition, toolBrushSize) { + + let originalSize = currFile.layers[0].canvasSize; + + var originPixelX = Math.floor(lastMouseClickPos[0] / zoom); + var originPixelY = Math.floor(lastMouseClickPos[1] / zoom); + var destinationPixelX = Math.floor(cursorPosition[0] / zoom); + var destinationPixelY = Math.floor(cursorPosition[1] / zoom); + + var mirrorOriginY; + var mirrorDestinationY; + + var mirrorOriginX; + var mirrorDestinationX; + + if (horizontalSimmetryVisible) { + // DONE: implement horizontal specular drawing + + var isUnderHorizontalAxis = (originPixelY >= (originalSize[1] / 2)); + + if (!isUnderHorizontalAxis) { + + if (toolBrushSize % 2 == 0) { + mirrorOriginY = Math.floor(axisOriginY + Math.abs(axisOriginY - originPixelY)); + mirrorDestinationY = Math.floor(axisOriginY + Math.abs(axisOriginY - destinationPixelY)); + } else { + // ? otherwise we have to substract a pixel, in order that the mirror pixel is adjacent to the line + mirrorOriginY = Math.floor(axisOriginY + Math.abs(axisOriginY - originPixelY) - 1); + mirrorDestinationY = Math.floor(axisOriginY + Math.abs(axisOriginY - destinationPixelY) - 1); + } + + } else { + + if (toolBrushSize % 2 == 0) { + mirrorOriginY = Math.floor(axisOriginY - Math.abs(axisOriginY - originPixelY)); + mirrorDestinationY = Math.floor(axisOriginY - Math.abs(axisOriginY - destinationPixelY)); + } else { + mirrorOriginY = Math.floor(axisOriginY - Math.abs(axisOriginY - originPixelY) - 1); + mirrorDestinationY = Math.floor(axisOriginY - Math.abs(axisOriginY - destinationPixelY) - 1); + } + + } + + // User draw + diagLine( + originPixelX, + originPixelY, + destinationPixelX, + destinationPixelY + ); + + diagLine( + originPixelX, + mirrorOriginY, + destinationPixelX, + mirrorDestinationY + ); + } + + if (verticalSimmetryVisible) { + // DONE: implement vertical specular drawing + + var isOverVerticalAxis = (originPixelX >= (originalSize[0] / 2)); + + if (!isOverVerticalAxis) { + + if (tool.pencil.brushSize % 2 == 0) { + mirrorOriginX = Math.floor(axisOriginX + Math.abs(axisOriginX - originPixelX)); + mirrorDestinationX = Math.floor(axisOriginX + Math.abs(axisOriginX - destinationPixelX)); + } else { + // ? otherwise we have to substract a pixel, in order that the mirror pixel is adjacent to the line + mirrorOriginX = Math.floor(axisOriginX + Math.abs(axisOriginX - originPixelX) - 1); + mirrorDestinationX = Math.floor(axisOriginX + Math.abs(axisOriginX - destinationPixelX) - 1); + } + + } else { + + if (tool.pencil.brushSize % 2 == 0) { + mirrorOriginX = Math.floor(axisOriginX - Math.abs(axisOriginX - originPixelX)); + mirrorDestinationX = Math.floor(axisOriginX - Math.abs(axisOriginX - destinationPixelX)); + } else { + mirrorOriginX = Math.floor(axisOriginX - Math.abs(axisOriginX - originPixelX) - 1); + mirrorDestinationX = Math.floor(axisOriginX - Math.abs(axisOriginX - destinationPixelX) - 1); + } + + } + + // User draw + diagLine( + originPixelX, + originPixelY, + destinationPixelX, + destinationPixelY + ); + + // Mirror draw + diagLine( + mirrorOriginX, + originPixelY, + mirrorDestinationX, + destinationPixelY + ); + + if (horizontalSimmetryVisible) { + // * I do not need to re-compute the mirror coordinates + // * It is basically a combination of vertical and horizontal projection + + // Mirror draw + diagLine( + mirrorOriginX, + mirrorOriginY, + mirrorDestinationX, + mirrorDestinationY + ); + } + } + } + + /** + * It draws the same content that the user draws, but in the opposite side + * based on where the symmetric axes are positionated in the editor. Like a mirror + * @param {*} cursorPosition current cursor position + */ + function drawBrushSpecular(cursorPosition, toolBrushSize) { + + let originalSize = currFile.layers[0].canvasSize; + + var originPixelX = Math.floor(lastMouseClickPos[0] / zoom); + var originPixelY = Math.floor(lastMouseClickPos[1] / zoom); + var destinationPixelX = Math.floor(cursorPosition[0] / zoom); + var destinationPixelY = Math.floor(cursorPosition[1] / zoom); + + var mirrorOriginY; + var mirrorDestinationY; + + var mirrorOriginX; + var mirrorDestinationX; + + if (horizontalSimmetryVisible) { + // DONE: implement horizontal specular drawing + + var isUnderHorizontalAxis = (originPixelY >= axisOriginY); + + if (!isUnderHorizontalAxis) { + + if (toolBrushSize % 2 == 0) { + mirrorOriginY = Math.floor(axisOriginY + Math.abs(axisOriginY - originPixelY)); + mirrorDestinationY = Math.floor(axisOriginY + Math.abs(axisOriginY - destinationPixelY)); + } else { + // ? otherwise we have to substract a pixel, in order that the mirror pixel is adjacent to the line + mirrorOriginY = Math.floor(axisOriginY + Math.abs(axisOriginY - originPixelY) - 1); + mirrorDestinationY = Math.floor(axisOriginY + Math.abs(axisOriginY - destinationPixelY) - 1); + } + + } else { + + if (toolBrushSize % 2 == 0) { + mirrorOriginY = Math.floor(axisOriginY - Math.abs(axisOriginY - originPixelY)); + mirrorDestinationY = Math.floor(axisOriginY - Math.abs(axisOriginY - destinationPixelY)); + } else { + mirrorOriginY = Math.floor(axisOriginY - Math.abs(axisOriginY - originPixelY) - 1); + mirrorDestinationY = Math.floor(axisOriginY - Math.abs(axisOriginY - destinationPixelY) - 1); + } + + } + + // User draw + line( + originPixelX, + originPixelY, + destinationPixelX, + destinationPixelY, + toolBrushSize + // tool.pencil.brushSize + ); + + // Mirror draw + line( + originPixelX, + mirrorOriginY, + destinationPixelX, + mirrorDestinationY, + toolBrushSize + // tool.pencil.brushSize + ); + } + + if (verticalSimmetryVisible) { + // DONE: implement vertical specular drawing + + var isOverVerticalAxis = (originPixelX >= (axisOriginX)); + + if (!isOverVerticalAxis) { + + if (tool.pencil.brushSize % 2 == 0) { + mirrorOriginX = Math.floor(axisOriginX + Math.abs(axisOriginX - originPixelX)); + mirrorDestinationX = Math.floor(axisOriginX + Math.abs(axisOriginX - destinationPixelX)); + } else { + // ? otherwise we have to substract a pixel, in order that the mirror pixel is adjacent to the line + mirrorOriginX = Math.floor(axisOriginX + Math.abs(axisOriginX - originPixelX) - 1); + mirrorDestinationX = Math.floor(axisOriginX + Math.abs(axisOriginX - destinationPixelX) - 1); + } + + } else { + + if (tool.pencil.brushSize % 2 == 0) { + mirrorOriginX = Math.floor(axisOriginX - Math.abs(axisOriginX - originPixelX)); + mirrorDestinationX = Math.floor(axisOriginX - Math.abs(axisOriginX - destinationPixelX)); + } else { + mirrorOriginX = Math.floor(axisOriginX - Math.abs(axisOriginX - originPixelX) - 1); + mirrorDestinationX = Math.floor(axisOriginX - Math.abs(axisOriginX - destinationPixelX) - 1); + } + + } + + // User draw + line( + originPixelX, + originPixelY, + destinationPixelX, + destinationPixelY, + tool.pencil.brushSize + ); + + // Mirror draw + line( + mirrorOriginX, + originPixelY, + mirrorDestinationX, + destinationPixelY, + tool.pencil.brushSize + ); + + if (horizontalSimmetryVisible) { + // * I do not need to re-compute the mirror coordinates + // * It is basically a combination of vertical and horizontal projection + + // Mirror draw + line( + mirrorOriginX, + mirrorOriginY, + mirrorDestinationX, + mirrorDestinationY, + tool.pencil.brushSize + ); + } + } + + } + + // TODO: Implement vertical symmetry + + // * Shape Mirroring + function startShapeDrawingSpecular(startX, startY, shapeType) { + + console.clear(); + console.log("START\n"); + + // normal drawing + console.log("normal start rect"); + startRectDrawing(startX, startY, 0); + + let originalSize = currFile.layers[0].canvasSize; + + if (horizontalSimmetryVisible) { + var isUnderHorizontalAxis = (startY >= axisOriginY); + + // startMirrorRectX is the same as startX, only startMirrorRectY changes + startMirrorRectX = startX; + + if (!isUnderHorizontalAxis) { + + // case when the user draws onto the top of the horizontal axis + // console.log("starting point on the top"); + + if (tool.rectangle.brushSize % 2 == 0) { + startMirrorRectY = Math.floor(axisOriginY + Math.abs(axisOriginY - startY) + 1) + 0.5; + } else { + startMirrorRectY = Math.floor(axisOriginY + Math.abs(axisOriginY - startY)) + 0.5; + } + + } else { + + // case when the user draws onto the bottom of the horizontal axis + // console.log("starting point on the bottom"); + + if (tool.rectangle.brushSize % 2 == 0) { + startMirrorRectY = Math.floor(axisOriginY - Math.abs(axisOriginY - startY) + 1) + 0.5; + } else { + startMirrorRectY = Math.floor(axisOriginY - Math.abs(axisOriginY - startY)) + 0.5; + } + + + } + + /* console.log("drawing rect in terms of cells at (" + startX + ", " + startY + ")"); + console.log("drawing mirror in terms of cells at (" + startMirrorRectX + ", " + startMirrorRectY + ")"); */ + + switch (shapeType) { + case ShapeType.RECT: + + // mirror drawing + console.log("horizontal start rect"); + startRectDrawing(startMirrorRectX, startMirrorRectY, 1); + break; + + default: + break; + } + } + + if (verticalSimmetryVisible) { + var isOverVerticalAxis = (startX >= axisOriginX); + + // startMirrorRectY is the same as startY, only startMirrorRectX changes + _startMirrorRectY = startY; + + if (!isOverVerticalAxis) { + + // case when the user draws onto the left of the vertical axis + if (tool.rectangle.brushSize % 2 == 0) { + _startMirrorRectX = Math.floor(axisOriginX + Math.abs(axisOriginX - startX) + 1) + 0.5; + } else { + _startMirrorRectX = Math.floor(axisOriginX + Math.abs(axisOriginX - startX)) + 0.5; + } + + } else { + + // case when the user draws onto the right of the vertical axis + if (tool.rectangle.brushSize % 2 == 0) { + _startMirrorRectX = Math.floor(axisOriginX - Math.abs(axisOriginX - startX) + 1) + 0.5; + } else { + _startMirrorRectX = Math.floor(axisOriginX - Math.abs(axisOriginX - startX)) + 0.5; + } + + } + + switch (shapeType) { + case ShapeType.RECT: + + // mirror drawing + console.log("vertical start rect"); + startRectDrawing(_startMirrorRectX, _startMirrorRectY, 2); + + if (horizontalSimmetryVisible) { + // I have to draw the shape into the fourth quadrant + __startMirrorRectX = _startMirrorRectX; + __startMirrorRectY = startMirrorRectY; + startRectDrawing(_startMirrorRectX, startMirrorRectY, 3); + } + break; + + default: + break; + } + + + } + + } + + // * Metrics are right + // TODO: Fix the mirror preview + function updateShapeDrawingSpecular(x, y, shapeType) { + + switch (shapeType) { + case ShapeType.RECT: + // normal drawing + updateRectDrawing(x, y, 0); + + // mirror drawing + // updateRectDrawing(x, mirrorY, true); + break; + + default: + break; + } + + } + + function endShapeDrawingSpecular(x, y, shapeType) { + + //console.clear(); + console.log("END\n"); + + let originalSize = currFile.layers[0].canvasSize; + + // in terms of px + let mirrorY; + let mirrorX; + + // in terms of cells + let originPixelX = Math.floor(x / zoom); + let originPixelY = Math.floor(y / zoom); + + // normal drawing + endRectDrawing(x, y, 0); + + if (horizontalSimmetryVisible) { + + var isUnderHorizontalAxis = (originPixelY >= axisOriginY); + + if (!isUnderHorizontalAxis) { + + if (tool.rectangle.brushSize % 2 == 0) { + mirrorY = Math.floor(axisOriginY + Math.abs(axisOriginY - originPixelY)); + } else { + mirrorY = Math.floor(axisOriginY + Math.abs(axisOriginY - originPixelY) - 1); + } + + } else { + /* console.log("axis origin Y = " + axisOriginY); + console.log("originPixelY = " + originPixelY); */ + if (tool.rectangle.brushSize % 2 == 0) { + mirrorY = Math.floor(axisOriginY - Math.abs(axisOriginY - originPixelY)); + } else { + mirrorY = Math.floor(axisOriginY - Math.abs(axisOriginY - originPixelY)) - 1; + } + + } + + endMirrorRectX = originPixelX; + endMirrorRectY = mirrorY; + + console.log("end rect in terms of cells at (" + originPixelX + ", " + originPixelY + ")"); + console.log("end mirror in terms of cells at (" + originPixelX + ", " + mirrorY + ")"); + + switch (shapeType) { + case ShapeType.RECT: + + // mirror drawing + console.log("horizontal end rect"); + endRectDrawing(x, mirrorY, 1); + break; + + default: + break; + } + + } + + if (verticalSimmetryVisible) { + var isOverVerticalAxis = (originPixelX >= axisOriginX); + + if (!isOverVerticalAxis) { + + if (tool.rectangle.brushSize % 2 == 0) { + mirrorX = Math.floor(axisOriginX + Math.abs(axisOriginX - originPixelX)); + } else { + mirrorX = Math.floor(axisOriginX + Math.abs(axisOriginX - originPixelX) - 1); + } + + } else { + /* console.log("axis origin Y = " + axisOriginY); + console.log("originPixelY = " + originPixelY); */ + if (tool.rectangle.brushSize % 2 == 0) { + mirrorX = Math.floor(axisOriginX - Math.abs(axisOriginX - originPixelX)); + } else { + mirrorX = Math.floor(axisOriginX - Math.abs(axisOriginX - originPixelX)) - 1; + } + + } + + // console.log("assigning _ends"); + _endMirrorRectX = mirrorX; + _endMirrorRectY = originPixelY; + + switch (shapeType) { + case ShapeType.RECT: + + // mirror drawing + console.log("vertical end rect"); + endRectDrawing(mirrorX, y, 2); + + if (horizontalSimmetryVisible) { + // I have to draw the shape into the fourth quadrant + __endMirrorRectX = _endMirrorRectX; + __endMirrorRectY = endMirrorRectY; + endRectDrawing(mirrorX, __endMirrorRectY); + } + break; + + default: + break; + } + } + + } + + return { + hSymmetricCanvas, + vSymmetricCanvas, + initSymmetricCanvas, + getHorizontalSymmetryVisible, + getVerticalSymmetryVisible, + ShapeType, + startShapeDrawingSpecular, + updateShapeDrawingSpecular, + endShapeDrawingSpecular, + drawBrushSpecular + } + +})(); \ No newline at end of file diff --git a/js/pixel-editor.js b/js/pixel-editor.js index 29a8087..950a9fd 100644 --- a/js/pixel-editor.js +++ b/js/pixel-editor.js @@ -27,6 +27,7 @@ /** SPECIAL LAYERS **/ //=include layers/Checkerboard.js //=include layers/PixelGrid.js +//=include layers/SymmetryModule.js /** TOOLS **/ //=include tools/DrawingTool.js diff --git a/views/canvases.hbs b/views/canvases.hbs index b17615f..a42fa97 100644 --- a/views/canvases.hbs +++ b/views/canvases.hbs @@ -5,5 +5,7 @@ + +
\ No newline at end of file diff --git a/views/main-menu.hbs b/views/main-menu.hbs index a7d04b6..b1a7dc5 100644 --- a/views/main-menu.hbs +++ b/views/main-menu.hbs @@ -24,6 +24,8 @@
  • From 43df37dc811af8f9a32adb5b19614989787caca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Marino=CC=80?= Date: Fri, 28 Jan 2022 19:05:17 +0100 Subject: [PATCH 02/10] horizontal symmetry brush + symmetry settings --- css/_canvas.scss | 5 + js/File.js | 2 + js/Settings.js | 6 +- js/Startup.js | 10 +- js/layers/HSymmetryLayer.js | 82 +++++ js/layers/PixelGrid.js | 2 +- js/layers/SymmetryModule.js | 701 ------------------------------------ js/pixel-editor.js | 2 +- js/tools/BrushTool.js | 52 ++- js/tools/EraserTool.js | 47 +++ views/canvases.hbs | 1 - views/main-menu.hbs | 3 +- views/popups/settings.hbs | 5 + 13 files changed, 203 insertions(+), 715 deletions(-) create mode 100644 js/layers/HSymmetryLayer.js delete mode 100644 js/layers/SymmetryModule.js diff --git a/css/_canvas.scss b/css/_canvas.scss index 5d02f4c..1dba7fa 100644 --- a/css/_canvas.scss +++ b/css/_canvas.scss @@ -42,6 +42,11 @@ background: transparent; } +#horizontal-symmetric { + z-index: 6001; + background: transparent; +} + #tmp-canvas { z-index: 5; background: transparent; diff --git a/js/File.js b/js/File.js index 6d2cf2b..025820a 100644 --- a/js/File.js +++ b/js/File.js @@ -10,6 +10,7 @@ class File { VFXLayer = undefined; TMPLayer = undefined; pixelGrid = undefined; + hSymmetricLayer = undefined; checkerBoard = undefined // Canvas resize attributes @@ -162,6 +163,7 @@ class File { // Regenerate the checkerboard currFile.checkerBoard.fillCheckerboard(); currFile.pixelGrid.fillPixelGrid(); + currFile.hSymmetricLayer.fillAxis(); // Put the imageDatas in the right position switch (this.rcPivot) { diff --git a/js/Settings.js b/js/Settings.js index bb9e63d..608cad1 100644 --- a/js/Settings.js +++ b/js/Settings.js @@ -23,7 +23,8 @@ const Settings = (() => { enableEyedropperPreview: true, //unused - performance numberOfHistoryStates: 256, maxColorsOnImportedImage: 128, - pixelGridColour: '#000000' + pixelGridColour: '#000000', + hAxisGridColour: '#FF0000' }; } else{ @@ -44,8 +45,11 @@ const Settings = (() => { //save new settings to settings object settings.numberOfHistoryStates = Util.getValue('setting-numberOfHistoryStates'); settings.pixelGridColour = Util.getValue('setting-pixelGridColour'); + settings.hAxisGridColour = Util.getValue('setting-hSymmetryColor'); // Filling pixel grid again if colour changed Events.emit("refreshPixelGrid"); + // Filling symmetric axes again if colour changed + Events.emit("refreshHorizontalAxis"); //save settings object to cookie let cookieValue = JSON.stringify(settings); diff --git a/js/Startup.js b/js/Startup.js index 3e7b8f5..d07e051 100644 --- a/js/Startup.js +++ b/js/Startup.js @@ -86,6 +86,7 @@ const Startup = (() => { Layer.unusedIDs.push(currentEntry.id); // Removing the entry from the menu currentEntry.remove(); + } } @@ -107,10 +108,8 @@ const Startup = (() => { currFile.pixelGrid = new PixelGrid(width, height, "pixel-grid"); // Horizontal symmetric layer - let hSymmetricLayer = new Layer(width, height, SymmetryModule.hSymmetricCanvas); - // Vertical symmetric layer - let vSymmetricLayer = new Layer(width, height, SymmetryModule.vSymmetricCanvas); - SymmetryModule.initSymmetricCanvas(); + console.log("CREATING HSymmetryAxis"); + currFile.hSymmetricLayer = new HSymmetryLayer(width, height, "horizontal-symmetric"); // Creating the vfx layer on top of everything currFile.VFXLayer = new Layer(width, height, 'vfx-canvas'); @@ -123,9 +122,8 @@ const Startup = (() => { currFile.layers.push(currFile.currentLayer); currFile.layers.push(currFile.TMPLayer); currFile.layers.push(currFile.pixelGrid); + currFile.layers.push(currFile.hSymmetricLayer); currFile.layers.push(currFile.VFXLayer); - currFile.layers.push(hSymmetricLayer); - currFile.layers.push(vSymmetricLayer); } } diff --git a/js/layers/HSymmetryLayer.js b/js/layers/HSymmetryLayer.js new file mode 100644 index 0000000..a75b1e9 --- /dev/null +++ b/js/layers/HSymmetryLayer.js @@ -0,0 +1,82 @@ +class HSymmetryLayer extends Layer { + // symmetry line color + axisColor = "#FF0000"; + // is hidden && enabled + isEnabled = false; + // Distance between one line and another in HTML pixels + lineDistance = 10; + + constructor(width, height, canvas, menuEntry) { + super(width, height, canvas, menuEntry); + this.initialize(); + Events.onCustom("refreshHorizontalAxis", this.fillAxis.bind(this)); + } + + initialize() { + super.initialize(); + this.fillAxis(); + } + + // Enable or not + disableAxis() { + // get toggle h axis button + let toggleButton = document.getElementById("toggle-h-symmetry-button"); + toggleButton.innerHTML = "Show Horizontal Symmetry"; + this.isEnabled = false; + this.canvas.style.display = "none"; + } + + enableAxis() { + // get toggle h axis button + let toggleButton = document.getElementById("toggle-h-symmetry-button"); + toggleButton.innerHTML = "Hide Horizontal Symmetry"; + this.isEnabled = true; + this.canvas.style.display = "inline-block"; + } + + repaint(factor) { + this.lineDistance += factor; + this.fillAxis(); + } + + /** + * Shows or hides axis depending on its current visibility + * (triggered by the show h symmetry button in the top menu) + */ + toggleHAxis() { + console.log("toggleHAxis"); + if (this.isEnabled) { + this.disableAxis(); + } else { + this.enableAxis(); + } + } + + /** + * It fills the canvas + */ + fillAxis() { + let originalSize = currFile.canvasSize; + this.canvas.width = originalSize[0] * Math.round(this.lineDistance); + this.canvas.height = originalSize[1] * Math.round(this.lineDistance); + + this.context.strokeStyle = Settings.getCurrSettings().hAxisGridColour; + + // Draw horizontal axis + this.drawHAxis(); + + if (!this.isEnabled) { + this.canvas.style.display = 'none'; + } + } + + drawHAxis() { + // Get middle y + let midY = Math.round(this.canvas.height / 2); + this.context.beginPath(); + this.context.moveTo(0, midY); + this.context.lineTo(this.canvas.width, midY); + this.context.stroke(); + this.context.closePath(); + } +} \ No newline at end of file diff --git a/js/layers/PixelGrid.js b/js/layers/PixelGrid.js index 5401ccb..ff9c116 100644 --- a/js/layers/PixelGrid.js +++ b/js/layers/PixelGrid.js @@ -52,7 +52,7 @@ class PixelGrid extends Layer { this.fillPixelGrid(); } - /** Shows or hides the pixel grid depening on its current visibility + /** Shows or hides the pixel grid depending on its current visibility * (triggered by the show pixel grid button in the top menu) * */ diff --git a/js/layers/SymmetryModule.js b/js/layers/SymmetryModule.js deleted file mode 100644 index c91b900..0000000 --- a/js/layers/SymmetryModule.js +++ /dev/null @@ -1,701 +0,0 @@ -/** - * SymmetryModule holds the functions used to implement symmetry options. - */ - const SymmetryModule = (() => { - // Saving the canvas containing the horizontal symmetric line - const hSymmetricCanvas = document.getElementById("horizontal-symmetric"); - // Saving the canvas containing the vertical symmetric line - const vSymmetricCanvas = document.getElementById("vertical-symmetric"); - - // Binding events to callbacks - document.getElementById('toggle-horizontal-simmetry-button').addEventListener('click', toggleHorizontalSymmetry, false); - document.getElementById('toggle-vertical-simmetry-button').addEventListener('click', toggleVerticalSymmetry, false); - - // Symmetric axes properties - // The horizontal simmetry is not visible by default - let horizontalSimmetryVisible = false; - // The vertical simmetry is not visible by default - let verticalSimmetryVisible = false; - - const hAxisColor = "#FF0000"; - const vAxisColor = "#00FF00"; - - // dragging vars - var axisOriginX; // for the vertical axis - var axisOriginY; // for the horizontal axis - - function initSymmetricCanvas() { - hSymmetricCanvas.style.display = "none"; - vSymmetricCanvas.style.display = "none"; - } - - const ShapeType = { - RECT: "rect", - ELLIPSE: "ellipse", - } - - // getters for internal state - function getHorizontalSymmetryVisible() { - return horizontalSimmetryVisible; - } - - function getVerticalSymmetryVisible() { - return verticalSimmetryVisible; - } - - // ! - // * Some important notes about the symmetric axes - // * h/vDrawAxis function takes levelY/X in input, because you can choose - // * the origin y/x of the axis. In order to do that the level is multiplied - // * by the lineDistance. That's a good thing because the symmetric axis - // * dynamically changes when the lineDistance declared in _pixelGrid.js changes - // ! - - /** - * It draws the horizontal symmetric axis - * @param {*} levelY indicates at which y the line will be positionated - * @param {String} axisColor axis stroke color as string (i.e: 'red') - * @param {*} axisLineWidth axis stroke width - */ - function hDrawAxis(levelY, axisColor, axisLineWidth) { - - axisOriginY = levelY; - - console.log(axisOriginY); - - // pre-conditions - // if it is not possible to retrieve the context, return - if (!hSymmetricCanvas.getContext) { return; } - - const hCtx = hSymmetricCanvas.getContext("2d"); - let originalSize = currFile.layers[5].canvas; - - if (levelY > originalSize.height) { return; } - - // ? The hSymmetricCanvas is lineDistance times bigger so that the lines don't take 1 canvas pixel - // ? but they take 1/lineDistance canvas pixels - hSymmetricCanvas.width = originalSize.width * lineDistance; - hSymmetricCanvas.height = originalSize.height * lineDistance; - - // set the stroke line - hCtx.strokeStyle = axisColor; - hCtx.lineWidth = axisLineWidth; - - hCtx.beginPath(); - - hCtx.rect(0, levelY * lineDistance, originalSize.width * lineDistance, 0); - - hCtx.stroke(); - hCtx.closePath(); - - - } - - /** - * It draws the vertical symmetric axis - * @param {*} levelX indicates at which x the line will be positionated - * @param {String} axisColor axis stroke color as string (i.e: 'red') - * @param {*} axisLineWidth axis stroke width - */ - function vDrawAxis(levelX, axisColor, axisLineWidth) { - - axisOriginX = levelX; - - // if it is not possible to retrieve the context, return - if (!vSymmetricCanvas.getContext) { - return; - } - - const vCtx = vSymmetricCanvas.getContext("2d"); - let originalSize = currFile.layers[0].canvasSize; - - // ? The vSymmetricCanvas is lineDistance times bigger so that the lines don't take 1 canvas pixel - // ? but they take 1/lineDistance canvas pixels - vSymmetricCanvas.width = originalSize[0] * lineDistance; - vSymmetricCanvas.height = originalSize[1] * lineDistance; - - // set the stroke line - vCtx.strokeStyle = axisColor; - vCtx.lineWidth = axisLineWidth; - - vCtx.beginPath(); - - vCtx.rect(levelX * lineDistance, 0, 0, originalSize[1] * lineDistance); - - vCtx.stroke(); - vCtx.closePath(); - - } - - // ? For the moment both horizontal and vertical symmetry are centered only - - /** - * It toggles the horizontal symmetry in the editor - */ - function toggleHorizontalSymmetry() { - console.log("toggling"); - // Getting the button to change its text - let button = document.getElementById("toggle-horizontal-simmetry-button"); - let originalSize = currFile.layers[0].canvas; - - horizontalSimmetryVisible = !horizontalSimmetryVisible - - if (!horizontalSimmetryVisible) { - - // alert("Horizontal Simmetry OFF"); - button.innerHTML = "Horizontal Simmetry (Off)"; - hSymmetricCanvas.style.display = "none"; - - return; - } - - // alert("Horizontal Simmetry ON"); - button.innerHTML = "Horizontal Simmetry (On)"; - hSymmetricCanvas.style.display = "inline-block"; - - // DONE: Show an horizontal line on the canvas - hDrawAxis(originalSize.height / 4, 'blue', 1); - } - - /** - * It toggles the vertical symmetry in the editor - */ - function toggleVerticalSymmetry() { - // Getting the button to change its text - let button = document.getElementById("toggle-vertical-simmetry-button"); - let originalSize = currFile.layers[0].canvasSize; - - verticalSimmetryVisible = !verticalSimmetryVisible - - if (!verticalSimmetryVisible) { - - button.innerHTML = "Vertical Simmetry (Off)"; - vSymmetricCanvas.style.display = "none"; - - return; - - } - - // alert("Horizontal Simmetry ON"); - button.innerHTML = "Vertical Simmetry (On)"; - vSymmetricCanvas.style.display = "inline-block"; - - // DONE: Show an horizontal line on the canvas - vDrawAxis(originalSize[0] / 1.5, 'red', 1); - } - - // ! - // * Important notes on specular drawing - // * Suppose that we want to draw specular based on vertical axis: - // * the x of vertical line is by default layers[0].canvasSize[0]/2 - // * (I'm going to call it as "axisOriginX"). - // * If we draw a pixel at (pixelX: 3, pixelY: 2) it specular pixel will be at - // * (x: axisOriginX +- abs(axisOriginX - pixelX), y: pixelY) - // ! - - // ! At the moment the axis origin X/Y is layers[0].canvasSize[0/1]/2 - - // TODO: Mirroring the line - function drawLineSpecular(cursorPosition, toolBrushSize) { - - let originalSize = currFile.layers[0].canvasSize; - - var originPixelX = Math.floor(lastMouseClickPos[0] / zoom); - var originPixelY = Math.floor(lastMouseClickPos[1] / zoom); - var destinationPixelX = Math.floor(cursorPosition[0] / zoom); - var destinationPixelY = Math.floor(cursorPosition[1] / zoom); - - var mirrorOriginY; - var mirrorDestinationY; - - var mirrorOriginX; - var mirrorDestinationX; - - if (horizontalSimmetryVisible) { - // DONE: implement horizontal specular drawing - - var isUnderHorizontalAxis = (originPixelY >= (originalSize[1] / 2)); - - if (!isUnderHorizontalAxis) { - - if (toolBrushSize % 2 == 0) { - mirrorOriginY = Math.floor(axisOriginY + Math.abs(axisOriginY - originPixelY)); - mirrorDestinationY = Math.floor(axisOriginY + Math.abs(axisOriginY - destinationPixelY)); - } else { - // ? otherwise we have to substract a pixel, in order that the mirror pixel is adjacent to the line - mirrorOriginY = Math.floor(axisOriginY + Math.abs(axisOriginY - originPixelY) - 1); - mirrorDestinationY = Math.floor(axisOriginY + Math.abs(axisOriginY - destinationPixelY) - 1); - } - - } else { - - if (toolBrushSize % 2 == 0) { - mirrorOriginY = Math.floor(axisOriginY - Math.abs(axisOriginY - originPixelY)); - mirrorDestinationY = Math.floor(axisOriginY - Math.abs(axisOriginY - destinationPixelY)); - } else { - mirrorOriginY = Math.floor(axisOriginY - Math.abs(axisOriginY - originPixelY) - 1); - mirrorDestinationY = Math.floor(axisOriginY - Math.abs(axisOriginY - destinationPixelY) - 1); - } - - } - - // User draw - diagLine( - originPixelX, - originPixelY, - destinationPixelX, - destinationPixelY - ); - - diagLine( - originPixelX, - mirrorOriginY, - destinationPixelX, - mirrorDestinationY - ); - } - - if (verticalSimmetryVisible) { - // DONE: implement vertical specular drawing - - var isOverVerticalAxis = (originPixelX >= (originalSize[0] / 2)); - - if (!isOverVerticalAxis) { - - if (tool.pencil.brushSize % 2 == 0) { - mirrorOriginX = Math.floor(axisOriginX + Math.abs(axisOriginX - originPixelX)); - mirrorDestinationX = Math.floor(axisOriginX + Math.abs(axisOriginX - destinationPixelX)); - } else { - // ? otherwise we have to substract a pixel, in order that the mirror pixel is adjacent to the line - mirrorOriginX = Math.floor(axisOriginX + Math.abs(axisOriginX - originPixelX) - 1); - mirrorDestinationX = Math.floor(axisOriginX + Math.abs(axisOriginX - destinationPixelX) - 1); - } - - } else { - - if (tool.pencil.brushSize % 2 == 0) { - mirrorOriginX = Math.floor(axisOriginX - Math.abs(axisOriginX - originPixelX)); - mirrorDestinationX = Math.floor(axisOriginX - Math.abs(axisOriginX - destinationPixelX)); - } else { - mirrorOriginX = Math.floor(axisOriginX - Math.abs(axisOriginX - originPixelX) - 1); - mirrorDestinationX = Math.floor(axisOriginX - Math.abs(axisOriginX - destinationPixelX) - 1); - } - - } - - // User draw - diagLine( - originPixelX, - originPixelY, - destinationPixelX, - destinationPixelY - ); - - // Mirror draw - diagLine( - mirrorOriginX, - originPixelY, - mirrorDestinationX, - destinationPixelY - ); - - if (horizontalSimmetryVisible) { - // * I do not need to re-compute the mirror coordinates - // * It is basically a combination of vertical and horizontal projection - - // Mirror draw - diagLine( - mirrorOriginX, - mirrorOriginY, - mirrorDestinationX, - mirrorDestinationY - ); - } - } - } - - /** - * It draws the same content that the user draws, but in the opposite side - * based on where the symmetric axes are positionated in the editor. Like a mirror - * @param {*} cursorPosition current cursor position - */ - function drawBrushSpecular(cursorPosition, toolBrushSize) { - - let originalSize = currFile.layers[0].canvasSize; - - var originPixelX = Math.floor(lastMouseClickPos[0] / zoom); - var originPixelY = Math.floor(lastMouseClickPos[1] / zoom); - var destinationPixelX = Math.floor(cursorPosition[0] / zoom); - var destinationPixelY = Math.floor(cursorPosition[1] / zoom); - - var mirrorOriginY; - var mirrorDestinationY; - - var mirrorOriginX; - var mirrorDestinationX; - - if (horizontalSimmetryVisible) { - // DONE: implement horizontal specular drawing - - var isUnderHorizontalAxis = (originPixelY >= axisOriginY); - - if (!isUnderHorizontalAxis) { - - if (toolBrushSize % 2 == 0) { - mirrorOriginY = Math.floor(axisOriginY + Math.abs(axisOriginY - originPixelY)); - mirrorDestinationY = Math.floor(axisOriginY + Math.abs(axisOriginY - destinationPixelY)); - } else { - // ? otherwise we have to substract a pixel, in order that the mirror pixel is adjacent to the line - mirrorOriginY = Math.floor(axisOriginY + Math.abs(axisOriginY - originPixelY) - 1); - mirrorDestinationY = Math.floor(axisOriginY + Math.abs(axisOriginY - destinationPixelY) - 1); - } - - } else { - - if (toolBrushSize % 2 == 0) { - mirrorOriginY = Math.floor(axisOriginY - Math.abs(axisOriginY - originPixelY)); - mirrorDestinationY = Math.floor(axisOriginY - Math.abs(axisOriginY - destinationPixelY)); - } else { - mirrorOriginY = Math.floor(axisOriginY - Math.abs(axisOriginY - originPixelY) - 1); - mirrorDestinationY = Math.floor(axisOriginY - Math.abs(axisOriginY - destinationPixelY) - 1); - } - - } - - // User draw - line( - originPixelX, - originPixelY, - destinationPixelX, - destinationPixelY, - toolBrushSize - // tool.pencil.brushSize - ); - - // Mirror draw - line( - originPixelX, - mirrorOriginY, - destinationPixelX, - mirrorDestinationY, - toolBrushSize - // tool.pencil.brushSize - ); - } - - if (verticalSimmetryVisible) { - // DONE: implement vertical specular drawing - - var isOverVerticalAxis = (originPixelX >= (axisOriginX)); - - if (!isOverVerticalAxis) { - - if (tool.pencil.brushSize % 2 == 0) { - mirrorOriginX = Math.floor(axisOriginX + Math.abs(axisOriginX - originPixelX)); - mirrorDestinationX = Math.floor(axisOriginX + Math.abs(axisOriginX - destinationPixelX)); - } else { - // ? otherwise we have to substract a pixel, in order that the mirror pixel is adjacent to the line - mirrorOriginX = Math.floor(axisOriginX + Math.abs(axisOriginX - originPixelX) - 1); - mirrorDestinationX = Math.floor(axisOriginX + Math.abs(axisOriginX - destinationPixelX) - 1); - } - - } else { - - if (tool.pencil.brushSize % 2 == 0) { - mirrorOriginX = Math.floor(axisOriginX - Math.abs(axisOriginX - originPixelX)); - mirrorDestinationX = Math.floor(axisOriginX - Math.abs(axisOriginX - destinationPixelX)); - } else { - mirrorOriginX = Math.floor(axisOriginX - Math.abs(axisOriginX - originPixelX) - 1); - mirrorDestinationX = Math.floor(axisOriginX - Math.abs(axisOriginX - destinationPixelX) - 1); - } - - } - - // User draw - line( - originPixelX, - originPixelY, - destinationPixelX, - destinationPixelY, - tool.pencil.brushSize - ); - - // Mirror draw - line( - mirrorOriginX, - originPixelY, - mirrorDestinationX, - destinationPixelY, - tool.pencil.brushSize - ); - - if (horizontalSimmetryVisible) { - // * I do not need to re-compute the mirror coordinates - // * It is basically a combination of vertical and horizontal projection - - // Mirror draw - line( - mirrorOriginX, - mirrorOriginY, - mirrorDestinationX, - mirrorDestinationY, - tool.pencil.brushSize - ); - } - } - - } - - // TODO: Implement vertical symmetry - - // * Shape Mirroring - function startShapeDrawingSpecular(startX, startY, shapeType) { - - console.clear(); - console.log("START\n"); - - // normal drawing - console.log("normal start rect"); - startRectDrawing(startX, startY, 0); - - let originalSize = currFile.layers[0].canvasSize; - - if (horizontalSimmetryVisible) { - var isUnderHorizontalAxis = (startY >= axisOriginY); - - // startMirrorRectX is the same as startX, only startMirrorRectY changes - startMirrorRectX = startX; - - if (!isUnderHorizontalAxis) { - - // case when the user draws onto the top of the horizontal axis - // console.log("starting point on the top"); - - if (tool.rectangle.brushSize % 2 == 0) { - startMirrorRectY = Math.floor(axisOriginY + Math.abs(axisOriginY - startY) + 1) + 0.5; - } else { - startMirrorRectY = Math.floor(axisOriginY + Math.abs(axisOriginY - startY)) + 0.5; - } - - } else { - - // case when the user draws onto the bottom of the horizontal axis - // console.log("starting point on the bottom"); - - if (tool.rectangle.brushSize % 2 == 0) { - startMirrorRectY = Math.floor(axisOriginY - Math.abs(axisOriginY - startY) + 1) + 0.5; - } else { - startMirrorRectY = Math.floor(axisOriginY - Math.abs(axisOriginY - startY)) + 0.5; - } - - - } - - /* console.log("drawing rect in terms of cells at (" + startX + ", " + startY + ")"); - console.log("drawing mirror in terms of cells at (" + startMirrorRectX + ", " + startMirrorRectY + ")"); */ - - switch (shapeType) { - case ShapeType.RECT: - - // mirror drawing - console.log("horizontal start rect"); - startRectDrawing(startMirrorRectX, startMirrorRectY, 1); - break; - - default: - break; - } - } - - if (verticalSimmetryVisible) { - var isOverVerticalAxis = (startX >= axisOriginX); - - // startMirrorRectY is the same as startY, only startMirrorRectX changes - _startMirrorRectY = startY; - - if (!isOverVerticalAxis) { - - // case when the user draws onto the left of the vertical axis - if (tool.rectangle.brushSize % 2 == 0) { - _startMirrorRectX = Math.floor(axisOriginX + Math.abs(axisOriginX - startX) + 1) + 0.5; - } else { - _startMirrorRectX = Math.floor(axisOriginX + Math.abs(axisOriginX - startX)) + 0.5; - } - - } else { - - // case when the user draws onto the right of the vertical axis - if (tool.rectangle.brushSize % 2 == 0) { - _startMirrorRectX = Math.floor(axisOriginX - Math.abs(axisOriginX - startX) + 1) + 0.5; - } else { - _startMirrorRectX = Math.floor(axisOriginX - Math.abs(axisOriginX - startX)) + 0.5; - } - - } - - switch (shapeType) { - case ShapeType.RECT: - - // mirror drawing - console.log("vertical start rect"); - startRectDrawing(_startMirrorRectX, _startMirrorRectY, 2); - - if (horizontalSimmetryVisible) { - // I have to draw the shape into the fourth quadrant - __startMirrorRectX = _startMirrorRectX; - __startMirrorRectY = startMirrorRectY; - startRectDrawing(_startMirrorRectX, startMirrorRectY, 3); - } - break; - - default: - break; - } - - - } - - } - - // * Metrics are right - // TODO: Fix the mirror preview - function updateShapeDrawingSpecular(x, y, shapeType) { - - switch (shapeType) { - case ShapeType.RECT: - // normal drawing - updateRectDrawing(x, y, 0); - - // mirror drawing - // updateRectDrawing(x, mirrorY, true); - break; - - default: - break; - } - - } - - function endShapeDrawingSpecular(x, y, shapeType) { - - //console.clear(); - console.log("END\n"); - - let originalSize = currFile.layers[0].canvasSize; - - // in terms of px - let mirrorY; - let mirrorX; - - // in terms of cells - let originPixelX = Math.floor(x / zoom); - let originPixelY = Math.floor(y / zoom); - - // normal drawing - endRectDrawing(x, y, 0); - - if (horizontalSimmetryVisible) { - - var isUnderHorizontalAxis = (originPixelY >= axisOriginY); - - if (!isUnderHorizontalAxis) { - - if (tool.rectangle.brushSize % 2 == 0) { - mirrorY = Math.floor(axisOriginY + Math.abs(axisOriginY - originPixelY)); - } else { - mirrorY = Math.floor(axisOriginY + Math.abs(axisOriginY - originPixelY) - 1); - } - - } else { - /* console.log("axis origin Y = " + axisOriginY); - console.log("originPixelY = " + originPixelY); */ - if (tool.rectangle.brushSize % 2 == 0) { - mirrorY = Math.floor(axisOriginY - Math.abs(axisOriginY - originPixelY)); - } else { - mirrorY = Math.floor(axisOriginY - Math.abs(axisOriginY - originPixelY)) - 1; - } - - } - - endMirrorRectX = originPixelX; - endMirrorRectY = mirrorY; - - console.log("end rect in terms of cells at (" + originPixelX + ", " + originPixelY + ")"); - console.log("end mirror in terms of cells at (" + originPixelX + ", " + mirrorY + ")"); - - switch (shapeType) { - case ShapeType.RECT: - - // mirror drawing - console.log("horizontal end rect"); - endRectDrawing(x, mirrorY, 1); - break; - - default: - break; - } - - } - - if (verticalSimmetryVisible) { - var isOverVerticalAxis = (originPixelX >= axisOriginX); - - if (!isOverVerticalAxis) { - - if (tool.rectangle.brushSize % 2 == 0) { - mirrorX = Math.floor(axisOriginX + Math.abs(axisOriginX - originPixelX)); - } else { - mirrorX = Math.floor(axisOriginX + Math.abs(axisOriginX - originPixelX) - 1); - } - - } else { - /* console.log("axis origin Y = " + axisOriginY); - console.log("originPixelY = " + originPixelY); */ - if (tool.rectangle.brushSize % 2 == 0) { - mirrorX = Math.floor(axisOriginX - Math.abs(axisOriginX - originPixelX)); - } else { - mirrorX = Math.floor(axisOriginX - Math.abs(axisOriginX - originPixelX)) - 1; - } - - } - - // console.log("assigning _ends"); - _endMirrorRectX = mirrorX; - _endMirrorRectY = originPixelY; - - switch (shapeType) { - case ShapeType.RECT: - - // mirror drawing - console.log("vertical end rect"); - endRectDrawing(mirrorX, y, 2); - - if (horizontalSimmetryVisible) { - // I have to draw the shape into the fourth quadrant - __endMirrorRectX = _endMirrorRectX; - __endMirrorRectY = endMirrorRectY; - endRectDrawing(mirrorX, __endMirrorRectY); - } - break; - - default: - break; - } - } - - } - - return { - hSymmetricCanvas, - vSymmetricCanvas, - initSymmetricCanvas, - getHorizontalSymmetryVisible, - getVerticalSymmetryVisible, - ShapeType, - startShapeDrawingSpecular, - updateShapeDrawingSpecular, - endShapeDrawingSpecular, - drawBrushSpecular - } - -})(); \ No newline at end of file diff --git a/js/pixel-editor.js b/js/pixel-editor.js index 950a9fd..844fc64 100644 --- a/js/pixel-editor.js +++ b/js/pixel-editor.js @@ -27,7 +27,7 @@ /** SPECIAL LAYERS **/ //=include layers/Checkerboard.js //=include layers/PixelGrid.js -//=include layers/SymmetryModule.js +//=include layers/HSymmetryLayer.js /** TOOLS **/ //=include tools/DrawingTool.js diff --git a/js/tools/BrushTool.js b/js/tools/BrushTool.js index 70776b9..12360d3 100644 --- a/js/tools/BrushTool.js +++ b/js/tools/BrushTool.js @@ -19,18 +19,66 @@ class BrushTool extends ResizableTool { return; //draw line to current pixel if (cursorTarget.className == 'drawingCanvas' || cursorTarget.className == 'drawingCanvas') { - currFile.currentLayer.drawLine(Math.floor(this.prevMousePos[0]/currFile.zoom), + currFile.currentLayer.drawLine( + Math.floor(this.prevMousePos[0]/currFile.zoom), Math.floor(this.prevMousePos[1]/currFile.zoom), Math.floor(this.currMousePos[0]/currFile.zoom), Math.floor(this.currMousePos[1]/currFile.zoom), this.currSize ); + + // If Horizontal Symmetry mode is activated + // draw specular + if (currFile.hSymmetricLayer.isEnabled) { + // if the current mouse position is over the horizontal axis + let originalSize = currFile.canvasSize; + let midY = (originalSize[1] / 2); + let prevMousePosY = Math.floor(this.prevMousePos[1] / currFile.zoom); + let currMousePosY = Math.floor(this.currMousePos[1] / currFile.zoom); + + console.log("midY: " + midY); + console.log("currMouseY: " + currMousePosY); + + if (currMousePosY <= midY) { + console.log("Drawing over the horizontal axis"); + let mirrorPrevY = Math.floor(midY + Math.abs(midY - prevMousePosY)); + let mirrorCurrentY = Math.floor(midY + Math.abs(midY - currMousePosY)); + + this.mirrorDraw(mirrorPrevY, mirrorCurrentY); + } else { + console.log("Drawing under the horizontal axis"); + let mirrorPrevY = Math.floor(midY - Math.abs(midY - prevMousePosY)); + let mirrorCurrentY = Math.floor(midY - Math.abs(midY - currMousePosY)); + + this.mirrorDraw(mirrorPrevY, mirrorCurrentY); + } + } } currFile.currentLayer.updateLayerPreview(); } - onEnd(mousePos) { + mirrorDraw(mirrorPrevY, mirrorCurrentY) { + if (this.currSize % 2 === 0) { + currFile.currentLayer.drawLine( + Math.floor(this.prevMousePos[0] / currFile.zoom), + Math.floor(mirrorPrevY), + Math.floor(this.currMousePos[0] / currFile.zoom), + Math.floor(mirrorCurrentY), + this.currSize + ); + } else { + currFile.currentLayer.drawLine( + Math.floor(this.prevMousePos[0] / currFile.zoom), + Math.floor(mirrorPrevY - 1), + Math.floor(this.currMousePos[0] / currFile.zoom), + Math.floor(mirrorCurrentY - 1), + this.currSize + ); + } + } + + onEnd(mousePos) { super.onEnd(mousePos); } diff --git a/js/tools/EraserTool.js b/js/tools/EraserTool.js index 7a296c2..ece711b 100644 --- a/js/tools/EraserTool.js +++ b/js/tools/EraserTool.js @@ -27,9 +27,56 @@ class EraserTool extends ResizableTool { ); } + // If Horizontal Symmetry mode is activated + // draw specular + if (currFile.hSymmetricLayer.isEnabled) { + // if the current mouse position is over the horizontal axis + let originalSize = currFile.canvasSize; + let midY = (originalSize[1] / 2); + let prevMousePosY = Math.floor(this.prevMousePos[1] / currFile.zoom); + let currMousePosY = Math.floor(this.currMousePos[1] / currFile.zoom); + + console.log("midY: " + midY); + console.log("currMouseY: " + currMousePosY); + + if (currMousePosY <= midY) { + console.log("Drawing over the horizontal axis"); + let mirrorPrevY = Math.floor(midY + Math.abs(midY - prevMousePosY)); + let mirrorCurrentY = Math.floor(midY + Math.abs(midY - currMousePosY)); + + this.mirrorDraw(mirrorPrevY, mirrorCurrentY); + } else { + console.log("Drawing under the horizontal axis"); + let mirrorPrevY = Math.floor(midY - Math.abs(midY - prevMousePosY)); + let mirrorCurrentY = Math.floor(midY - Math.abs(midY - currMousePosY)); + + this.mirrorDraw(mirrorPrevY, mirrorCurrentY); + } + } + currFile.currentLayer.updateLayerPreview(); } + mirrorDraw(mirrorPrevY, mirrorCurrentY) { + if (this.currSize % 2 === 0) { + currFile.currentLayer.drawLine( + Math.floor(this.prevMousePos[0] / currFile.zoom), + Math.floor(mirrorPrevY), + Math.floor(this.currMousePos[0] / currFile.zoom), + Math.floor(mirrorCurrentY), + this.currSize + ); + } else { + currFile.currentLayer.drawLine( + Math.floor(this.prevMousePos[0] / currFile.zoom), + Math.floor(mirrorPrevY - 1), + Math.floor(this.currMousePos[0] / currFile.zoom), + Math.floor(mirrorCurrentY - 1), + this.currSize + ); + } + } + onEnd(mousePos) { super.onEnd(mousePos); this.endMousePos = mousePos; diff --git a/views/canvases.hbs b/views/canvases.hbs index a42fa97..9255a72 100644 --- a/views/canvases.hbs +++ b/views/canvases.hbs @@ -6,6 +6,5 @@ -
    \ No newline at end of file diff --git a/views/main-menu.hbs b/views/main-menu.hbs index b1a7dc5..b994e7d 100644 --- a/views/main-menu.hbs +++ b/views/main-menu.hbs @@ -24,8 +24,7 @@
    • -
    • -
    • +
  • diff --git a/views/popups/settings.hbs b/views/popups/settings.hbs index 159e64c..3b907d6 100644 --- a/views/popups/settings.hbs +++ b/views/popups/settings.hbs @@ -12,6 +12,11 @@
    + +

    H Symmetry Axis

    +
    + +

    Your browsers cookies are disabled, settings will be lost upon closing this page.

    From c9dd3644a454e179f0dee8161496484b6b681b72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Marino=CC=80?= Date: Sat, 29 Jan 2022 11:45:47 +0100 Subject: [PATCH 03/10] vertical symmetry + refactoring --- css/_canvas.scss | 5 +++ js/File.js | 2 + js/Settings.js | 5 ++- js/Startup.js | 5 ++- js/layers/HSymmetryLayer.js | 2 - js/layers/VSymmetryLayer.js | 80 +++++++++++++++++++++++++++++++++++ js/pixel-editor.js | 1 + js/tools/BrushTool.js | 84 ++++++++++++++++++++++++++----------- views/canvases.hbs | 1 + views/main-menu.hbs | 3 +- views/popups/settings.hbs | 9 +++- 11 files changed, 165 insertions(+), 32 deletions(-) create mode 100644 js/layers/VSymmetryLayer.js diff --git a/css/_canvas.scss b/css/_canvas.scss index 1dba7fa..9a79f5a 100644 --- a/css/_canvas.scss +++ b/css/_canvas.scss @@ -47,6 +47,11 @@ background: transparent; } +#vertical-symmetric { + z-index: 6002; + background: transparent; +} + #tmp-canvas { z-index: 5; background: transparent; diff --git a/js/File.js b/js/File.js index 025820a..5ee3e30 100644 --- a/js/File.js +++ b/js/File.js @@ -11,6 +11,7 @@ class File { TMPLayer = undefined; pixelGrid = undefined; hSymmetricLayer = undefined; + vSymmetricLayer = undefined; checkerBoard = undefined // Canvas resize attributes @@ -164,6 +165,7 @@ class File { currFile.checkerBoard.fillCheckerboard(); currFile.pixelGrid.fillPixelGrid(); currFile.hSymmetricLayer.fillAxis(); + currFile.vSymmetricLayer.fillAxis(); // Put the imageDatas in the right position switch (this.rcPivot) { diff --git a/js/Settings.js b/js/Settings.js index 608cad1..547dfc7 100644 --- a/js/Settings.js +++ b/js/Settings.js @@ -24,7 +24,8 @@ const Settings = (() => { numberOfHistoryStates: 256, maxColorsOnImportedImage: 128, pixelGridColour: '#000000', - hAxisGridColour: '#FF0000' + hAxisGridColour: '#FF0000', + vAxisGridColour: '#0000FF', }; } else{ @@ -46,10 +47,12 @@ const Settings = (() => { settings.numberOfHistoryStates = Util.getValue('setting-numberOfHistoryStates'); settings.pixelGridColour = Util.getValue('setting-pixelGridColour'); settings.hAxisGridColour = Util.getValue('setting-hSymmetryColor'); + settings.vAxisGridColour = Util.getValue('setting-vSymmetryColor'); // Filling pixel grid again if colour changed Events.emit("refreshPixelGrid"); // Filling symmetric axes again if colour changed Events.emit("refreshHorizontalAxis"); + Events.emit("refreshVerticalAxis"); //save settings object to cookie let cookieValue = JSON.stringify(settings); diff --git a/js/Startup.js b/js/Startup.js index d07e051..13c7677 100644 --- a/js/Startup.js +++ b/js/Startup.js @@ -108,9 +108,11 @@ const Startup = (() => { currFile.pixelGrid = new PixelGrid(width, height, "pixel-grid"); // Horizontal symmetric layer - console.log("CREATING HSymmetryAxis"); currFile.hSymmetricLayer = new HSymmetryLayer(width, height, "horizontal-symmetric"); + // Vertical symmetric layer + currFile.vSymmetricLayer = new VSymmetryLayer(width, height, "vertical-symmetric"); + // Creating the vfx layer on top of everything currFile.VFXLayer = new Layer(width, height, 'vfx-canvas'); // Tmp layer to draw previews on @@ -123,6 +125,7 @@ const Startup = (() => { currFile.layers.push(currFile.TMPLayer); currFile.layers.push(currFile.pixelGrid); currFile.layers.push(currFile.hSymmetricLayer); + currFile.layers.push(currFile.vSymmetricLayer); currFile.layers.push(currFile.VFXLayer); } } diff --git a/js/layers/HSymmetryLayer.js b/js/layers/HSymmetryLayer.js index a75b1e9..bd98de0 100644 --- a/js/layers/HSymmetryLayer.js +++ b/js/layers/HSymmetryLayer.js @@ -1,6 +1,4 @@ class HSymmetryLayer extends Layer { - // symmetry line color - axisColor = "#FF0000"; // is hidden && enabled isEnabled = false; // Distance between one line and another in HTML pixels diff --git a/js/layers/VSymmetryLayer.js b/js/layers/VSymmetryLayer.js new file mode 100644 index 0000000..601a4bd --- /dev/null +++ b/js/layers/VSymmetryLayer.js @@ -0,0 +1,80 @@ +class VSymmetryLayer extends Layer { + // is hidden && enabled + isEnabled = false; + // Distance between one line and another in HTML pixels + lineDistance = 10; + + constructor(width, height, canvas, menuEntry) { + super(width, height, canvas, menuEntry); + this.initialize(); + Events.onCustom("refreshVerticalAxis", this.fillAxis.bind(this)); + } + + initialize() { + super.initialize(); + this.fillAxis(); + } + + // Enable or not + disableAxis() { + // get toggle h axis button + let toggleButton = document.getElementById("toggle-v-symmetry-button"); + toggleButton.innerHTML = "Show Vertical Axis"; + this.isEnabled = false; + this.canvas.style.display = "none"; + } + + enableAxis() { + // get toggle h axis button + let toggleButton = document.getElementById("toggle-v-symmetry-button"); + toggleButton.innerHTML = "Hide Vertical Axis"; + this.isEnabled = true; + this.canvas.style.display = "inline-block"; + } + + repaint(factor) { + this.lineDistance += factor; + this.fillAxis(); + } + + /** + * Shows or hides axis depending on its current visibility + * (triggered by the show h symmetry button in the top menu) + */ + toggleVAxis() { + console.log("toggleVAxis"); + if (this.isEnabled) { + this.disableAxis(); + } else { + this.enableAxis(); + } + } + + /** + * It fills the canvas + */ + fillAxis() { + let originalSize = currFile.canvasSize; + this.canvas.width = originalSize[0] * Math.round(this.lineDistance); + this.canvas.height = originalSize[1] * Math.round(this.lineDistance); + + this.context.strokeStyle = Settings.getCurrSettings().vAxisGridColour; + + // Draw horizontal axis + this.drawVAxis(); + + if (!this.isEnabled) { + this.canvas.style.display = 'none'; + } + } + + drawVAxis() { + // Get middle y + let midX = Math.round(this.canvas.width / 2); + this.context.beginPath(); + this.context.moveTo(midX, 0); + this.context.lineTo(midX, this.canvas.height); + this.context.stroke(); + this.context.closePath(); + } +} \ No newline at end of file diff --git a/js/pixel-editor.js b/js/pixel-editor.js index 844fc64..81285b1 100644 --- a/js/pixel-editor.js +++ b/js/pixel-editor.js @@ -28,6 +28,7 @@ //=include layers/Checkerboard.js //=include layers/PixelGrid.js //=include layers/HSymmetryLayer.js +//=include layers/VSymmetryLayer.js /** TOOLS **/ //=include tools/DrawingTool.js diff --git a/js/tools/BrushTool.js b/js/tools/BrushTool.js index 12360d3..763f264 100644 --- a/js/tools/BrushTool.js +++ b/js/tools/BrushTool.js @@ -27,52 +27,86 @@ class BrushTool extends ResizableTool { this.currSize ); - // If Horizontal Symmetry mode is activated - // draw specular + let midX = (currFile.canvasSize[0] / 2); + let midY = (currFile.canvasSize[1] / 2); + let prevMousePosX = Math.floor(this.prevMousePos[0] / currFile.zoom); + let prevMousePosY = Math.floor(this.prevMousePos[1] / currFile.zoom); + let currMousePosX = Math.floor(this.currMousePos[0] / currFile.zoom); + let currMousePosY = Math.floor(this.currMousePos[1] / currFile.zoom); + let mirrorPrevX, mirrorPrevY, mirrorCurrentX, mirrorCurrentY; + if (currFile.hSymmetricLayer.isEnabled) { + // if the current mouse position is over the horizontal axis - let originalSize = currFile.canvasSize; - let midY = (originalSize[1] / 2); - let prevMousePosY = Math.floor(this.prevMousePos[1] / currFile.zoom); - let currMousePosY = Math.floor(this.currMousePos[1] / currFile.zoom); - - console.log("midY: " + midY); - console.log("currMouseY: " + currMousePosY); - if (currMousePosY <= midY) { console.log("Drawing over the horizontal axis"); - let mirrorPrevY = Math.floor(midY + Math.abs(midY - prevMousePosY)); - let mirrorCurrentY = Math.floor(midY + Math.abs(midY - currMousePosY)); + mirrorPrevY = Math.floor(midY + Math.abs(midY - prevMousePosY)); + mirrorCurrentY = Math.floor(midY + Math.abs(midY - currMousePosY)); - this.mirrorDraw(mirrorPrevY, mirrorCurrentY); } else { console.log("Drawing under the horizontal axis"); - let mirrorPrevY = Math.floor(midY - Math.abs(midY - prevMousePosY)); - let mirrorCurrentY = Math.floor(midY - Math.abs(midY - currMousePosY)); + mirrorPrevY = Math.floor(midY - Math.abs(midY - prevMousePosY)); + mirrorCurrentY = Math.floor(midY - Math.abs(midY - currMousePosY)); - this.mirrorDraw(mirrorPrevY, mirrorCurrentY); } + + this.mirrorDraw( + Math.floor(this.prevMousePos[0] / currFile.zoom), + mirrorPrevY, + Math.floor(this.currMousePos[0] / currFile.zoom), + mirrorCurrentY, + true, false + ); + } + + if (currFile.vSymmetricLayer.isEnabled) { + // console.log("midX => " + midX); + // console.log("currMouseX => " + currMousePosX); + + // if the current mouse position is over the horizontal axis + if (currMousePosX <= midX) { + mirrorPrevX = Math.floor(midX + Math.abs(midX - prevMousePosX)); + mirrorCurrentX = Math.floor(midX + Math.abs(midX - currMousePosX)); + } else { + mirrorPrevX = Math.floor(midX - Math.abs(midX - prevMousePosX)); + mirrorCurrentX = Math.floor(midX - Math.abs(midX - currMousePosX)); + } + + this.mirrorDraw( + mirrorPrevX, + Math.floor(this.prevMousePos[1] / currFile.zoom), + mirrorCurrentX, + Math.floor(this.currMousePos[1] / currFile.zoom), + false, true + ); + } + + 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); } } currFile.currentLayer.updateLayerPreview(); } - mirrorDraw(mirrorPrevY, mirrorCurrentY) { + mirrorDraw(prevX, prevY, currX, currY, isHorizontal, isVertical) { + let horizontalFactor = (isHorizontal) ? 1 : 0; + let verticalFactor = (isVertical) ? 1 : 0; if (this.currSize % 2 === 0) { currFile.currentLayer.drawLine( - Math.floor(this.prevMousePos[0] / currFile.zoom), - Math.floor(mirrorPrevY), - Math.floor(this.currMousePos[0] / currFile.zoom), - Math.floor(mirrorCurrentY), + prevX, + prevY, + currX, + currY, this.currSize ); } else { currFile.currentLayer.drawLine( - Math.floor(this.prevMousePos[0] / currFile.zoom), - Math.floor(mirrorPrevY - 1), - Math.floor(this.currMousePos[0] / currFile.zoom), - Math.floor(mirrorCurrentY - 1), + prevX - verticalFactor, + prevY - horizontalFactor, + currX - verticalFactor, + currY - horizontalFactor, this.currSize ); } diff --git a/views/canvases.hbs b/views/canvases.hbs index 9255a72..c2f6a6a 100644 --- a/views/canvases.hbs +++ b/views/canvases.hbs @@ -6,5 +6,6 @@ +
    \ No newline at end of file diff --git a/views/main-menu.hbs b/views/main-menu.hbs index b994e7d..e214f43 100644 --- a/views/main-menu.hbs +++ b/views/main-menu.hbs @@ -24,7 +24,8 @@
    • -
    • +
    • +
  • diff --git a/views/popups/settings.hbs b/views/popups/settings.hbs index 3b907d6..b5483e7 100644 --- a/views/popups/settings.hbs +++ b/views/popups/settings.hbs @@ -13,10 +13,15 @@ -

    H Symmetry Axis

    +

    Horizontal Axis

    - +
    + +

    Vertical Axis

    +
    + +

    Your browsers cookies are disabled, settings will be lost upon closing this page.

    From 74aba784244c9197aacb50ac83608e01e9dc9557 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Marino=CC=80?= Date: Sat, 29 Jan 2022 11:56:15 +0100 Subject: [PATCH 04/10] mirror eraser --- js/tools/BrushTool.js | 1 - js/tools/EraserTool.js | 85 ++++++++++++++++++++++++++++-------------- 2 files changed, 58 insertions(+), 28 deletions(-) diff --git a/js/tools/BrushTool.js b/js/tools/BrushTool.js index 763f264..fb8ac33 100644 --- a/js/tools/BrushTool.js +++ b/js/tools/BrushTool.js @@ -47,7 +47,6 @@ class BrushTool extends ResizableTool { console.log("Drawing under the horizontal axis"); mirrorPrevY = Math.floor(midY - Math.abs(midY - prevMousePosY)); mirrorCurrentY = Math.floor(midY - Math.abs(midY - currMousePosY)); - } this.mirrorDraw( diff --git a/js/tools/EraserTool.js b/js/tools/EraserTool.js index ece711b..d9793e6 100644 --- a/js/tools/EraserTool.js +++ b/js/tools/EraserTool.js @@ -27,51 +27,82 @@ class EraserTool extends ResizableTool { ); } + let midX = (currFile.canvasSize[0] / 2); + let midY = (currFile.canvasSize[1] / 2); + let prevMousePosX = Math.floor(this.prevMousePos[0] / currFile.zoom); + let prevMousePosY = Math.floor(this.prevMousePos[1] / currFile.zoom); + let currMousePosX = Math.floor(this.currMousePos[0] / currFile.zoom); + let currMousePosY = Math.floor(this.currMousePos[1] / currFile.zoom); + let mirrorPrevX, mirrorPrevY, mirrorCurrentX, mirrorCurrentY; + // If Horizontal Symmetry mode is activated // draw specular if (currFile.hSymmetricLayer.isEnabled) { // if the current mouse position is over the horizontal axis - let originalSize = currFile.canvasSize; - let midY = (originalSize[1] / 2); - let prevMousePosY = Math.floor(this.prevMousePos[1] / currFile.zoom); - let currMousePosY = Math.floor(this.currMousePos[1] / currFile.zoom); - - console.log("midY: " + midY); - console.log("currMouseY: " + currMousePosY); - if (currMousePosY <= midY) { - console.log("Drawing over the horizontal axis"); - let mirrorPrevY = Math.floor(midY + Math.abs(midY - prevMousePosY)); - let mirrorCurrentY = Math.floor(midY + Math.abs(midY - currMousePosY)); - - this.mirrorDraw(mirrorPrevY, mirrorCurrentY); + mirrorPrevY = Math.floor(midY + Math.abs(midY - prevMousePosY)); + mirrorCurrentY = Math.floor(midY + Math.abs(midY - currMousePosY)); } else { - console.log("Drawing under the horizontal axis"); - let mirrorPrevY = Math.floor(midY - Math.abs(midY - prevMousePosY)); - let mirrorCurrentY = Math.floor(midY - Math.abs(midY - currMousePosY)); - - this.mirrorDraw(mirrorPrevY, mirrorCurrentY); + mirrorPrevY = Math.floor(midY - Math.abs(midY - prevMousePosY)); + mirrorCurrentY = Math.floor(midY - Math.abs(midY - currMousePosY)); } + this.mirrorErase( + Math.floor(this.prevMousePos[0] / currFile.zoom), + mirrorPrevY, + Math.floor(this.currMousePos[0] / currFile.zoom), + mirrorCurrentY, + true, false + ); + + } + + if (currFile.vSymmetricLayer.isEnabled) { + // console.log("midX => " + midX); + // console.log("currMouseX => " + currMousePosX); + + // if the current mouse position is over the horizontal axis + if (currMousePosX <= midX) { + mirrorPrevX = Math.floor(midX + Math.abs(midX - prevMousePosX)); + mirrorCurrentX = Math.floor(midX + Math.abs(midX - currMousePosX)); + } else { + mirrorPrevX = Math.floor(midX - Math.abs(midX - prevMousePosX)); + mirrorCurrentX = Math.floor(midX - Math.abs(midX - currMousePosX)); + } + + this.mirrorErase( + mirrorPrevX, + Math.floor(this.prevMousePos[1] / currFile.zoom), + mirrorCurrentX, + Math.floor(this.currMousePos[1] / currFile.zoom), + false, true + ); + } + + if (currFile.hSymmetricLayer.isEnabled && currFile.vSymmetricLayer.isEnabled) { + // Based on current mouse position we can infer which quadrant is the remaining one + this.mirrorErase(mirrorPrevX, mirrorPrevY, mirrorCurrentX, mirrorCurrentY, true, true); } currFile.currentLayer.updateLayerPreview(); } - mirrorDraw(mirrorPrevY, mirrorCurrentY) { + mirrorErase(prevX, prevY, currX, currY, isHorizontal, isVertical) { + let horizontalFactor = (isHorizontal) ? 1 : 0; + let verticalFactor = (isVertical) ? 1 : 0; if (this.currSize % 2 === 0) { currFile.currentLayer.drawLine( - Math.floor(this.prevMousePos[0] / currFile.zoom), - Math.floor(mirrorPrevY), - Math.floor(this.currMousePos[0] / currFile.zoom), - Math.floor(mirrorCurrentY), + prevX, + prevY, + currX, + currY, this.currSize ); } else { currFile.currentLayer.drawLine( - Math.floor(this.prevMousePos[0] / currFile.zoom), - Math.floor(mirrorPrevY - 1), - Math.floor(this.currMousePos[0] / currFile.zoom), - Math.floor(mirrorCurrentY - 1), + prevX - verticalFactor, + prevY - horizontalFactor, + currX - verticalFactor, + currY - horizontalFactor, this.currSize ); } 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 05/10] 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 From c5113db10c0e89ae938b73b56e6722f7b435afbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Marino=CC=80?= Date: Sat, 5 Feb 2022 12:41:44 +0100 Subject: [PATCH 06/10] fixed rectangle symmetry on update color --- js/tools/RectangleTool.js | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/js/tools/RectangleTool.js b/js/tools/RectangleTool.js index af5228b..5a8921c 100644 --- a/js/tools/RectangleTool.js +++ b/js/tools/RectangleTool.js @@ -49,6 +49,10 @@ class RectangleTool extends ResizableTool { this.startMousePos[0] = Math.floor(mousePos[0] / currFile.zoom) + 0.5; this.startMousePos[1] = Math.floor(mousePos[1] / currFile.zoom) + 0.5; + this.drawRect(this.startMousePos[0], this.startMousePos[1], + this.startMousePos[0], this.startMousePos[1] + ); + new HistoryState().EditCanvas(); } @@ -95,8 +99,6 @@ class RectangleTool extends ResizableTool { currFile.currentLayer.context.fillRect(startRectX, startRectY, endRectX - startRectX, endRectY - startRectY); } - this.clearCanvas(tmpContext); - if (currFile.hSymmetricLayer.isEnabled) { if (typeof this.horizontalMirrorCoordinates != 'undefined') { @@ -109,8 +111,7 @@ class RectangleTool extends ResizableTool { endMirrorRectX, startMirrorRectX, endMirrorRectY, - startMirrorRectY, - tmpContext + startMirrorRectY ); } } @@ -127,8 +128,7 @@ class RectangleTool extends ResizableTool { endMirrorRectX, startMirrorRectX, endMirrorRectY, - startMirrorRectY, - tmpContext + startMirrorRectY ); } } @@ -144,12 +144,13 @@ class RectangleTool extends ResizableTool { endMirrorRectX, startMirrorRectX, endMirrorRectY, - startMirrorRectY, - tmpContext + startMirrorRectY ); } } + this.clearCanvas(tmpContext); + } /** @@ -158,9 +159,8 @@ class RectangleTool extends ResizableTool { * @param startMirrorRectX * @param endMirrorRectY * @param startMirrorRectY - * @param tmpContext */ - handleMirrorRectDrawing(endMirrorRectX, startMirrorRectX, endMirrorRectY, startMirrorRectY, tmpContext) { + handleMirrorRectDrawing(endMirrorRectX, startMirrorRectX, endMirrorRectY, startMirrorRectY) { const mirrorCoordinates = this.adjustCoordinates( endMirrorRectX, startMirrorRectX, @@ -187,15 +187,12 @@ class RectangleTool extends ResizableTool { 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); } From c47686e4c8e539d53c06576c94f91c6a51656c22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Marino=CC=80?= Date: Sat, 5 Feb 2022 13:32:53 +0100 Subject: [PATCH 07/10] line tool symmetry --- js/tools/LineTool.js | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/js/tools/LineTool.js b/js/tools/LineTool.js index 8fb8006..a883b43 100644 --- a/js/tools/LineTool.js +++ b/js/tools/LineTool.js @@ -77,6 +77,47 @@ class LineTool extends ResizableTool { while (true) { context.fillRect(x0-Math.floor(this.currSize/2), y0-Math.floor(this.currSize/2), this.currSize, this.currSize); + // handle symmetry + let midY = (currFile.canvasSize[1] / 2); + let midX = (currFile.canvasSize[0] / 2); + let mirrorX, mirrorY; + + if (currFile.hSymmetricLayer.isEnabled) { + if (y0 <= midY) { + mirrorY = Math.floor(midY + Math.abs(midY - y0)); + } else { + mirrorY = Math.floor(midY - Math.abs(midY - y0)); + } + mirrorY -= (this.currSize % 2 === 0) ? 0 : 1; + context.fillRect( + x0 - Math.floor(this.currSize/2), + mirrorY - Math.floor(this.currSize/2), + this.currSize, this.currSize + ); + } + + if (currFile.vSymmetricLayer.isEnabled) { + if (x0 <= midX) { + mirrorX = Math.floor(midX + Math.abs(midX - x0)); + } else { + mirrorX = Math.floor(midX - Math.abs(midX - x0)); + } + mirrorX -= (this.currSize % 2 === 0) ? 0 : 1; + context.fillRect( + mirrorX - Math.floor(this.currSize/2), + y0 - Math.floor(this.currSize/2), + this.currSize, this.currSize + ); + } + + if (currFile.hSymmetricLayer.isEnabled && currFile.vSymmetricLayer.isEnabled) { + context.fillRect( + mirrorX - Math.floor(this.currSize/2), + mirrorY - Math.floor(this.currSize/2), + this.currSize, this.currSize + ); + } + //if we've reached the end goal, exit the loop if ((x0==x1) && (y0==y1)) break; var e2 = 2*err; From b85befd0bc169a202c53f35151bb7efbc677c41e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Marino=CC=80?= Date: Sat, 5 Feb 2022 15:17:37 +0100 Subject: [PATCH 08/10] fill symmetry --- js/tools/FillTool.js | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/js/tools/FillTool.js b/js/tools/FillTool.js index cdcd0df..0826c98 100644 --- a/js/tools/FillTool.js +++ b/js/tools/FillTool.js @@ -8,9 +8,44 @@ class FillTool extends DrawingTool { onStart(mousePos, target) { super.onStart(mousePos); + this.startMousePos[0] = Math.floor(mousePos[0]) + 0.5; + this.startMousePos[1] = Math.floor(mousePos[1]) + 0.5; + if (target.className != 'drawingCanvas') return; + this.fill(mousePos); + + let midX = (currFile.canvasSize[0] / 2); + let midY = (currFile.canvasSize[1] / 2); + let x0 = Math.floor(this.startMousePos[0]/currFile.zoom); + let y0 = Math.floor(this.startMousePos[1]/currFile.zoom); + let mirrorX, mirrorY; + if (currFile.hSymmetricLayer.isEnabled) { + if (y0 <= midY) { + mirrorY = Math.floor(midY + Math.abs(midY - y0)); + } else { + mirrorY = Math.floor(midY - Math.abs(midY - y0)); + } + let symmetryPos = [mousePos[0], mirrorY * currFile.zoom]; + this.fill(symmetryPos); + } + + if (currFile.vSymmetricLayer.isEnabled) { + if (x0 <= midX) { + mirrorX = Math.floor(midX + Math.abs(midX - x0)); + } else { + mirrorX = Math.floor(midX - Math.abs(midX - x0)); + } + let symmetryPos = [mirrorX * currFile.zoom, mousePos[1]]; + this.fill(symmetryPos); + } + + if (currFile.hSymmetricLayer.isEnabled && currFile.vSymmetricLayer.isEnabled) { + let symmetryPos = [mirrorX * currFile.zoom, mirrorY * currFile.zoom]; + this.fill(symmetryPos); + } + currFile.currentLayer.updateLayerPreview(); new HistoryState().EditCanvas(); From 7467353e70ec593ceff1734a137d515fc5453d54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Marino=CC=80?= Date: Sat, 5 Feb 2022 18:24:53 +0100 Subject: [PATCH 09/10] updated eraser tool --- js/tools/EraserTool.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/tools/EraserTool.js b/js/tools/EraserTool.js index 730fae2..37f8933 100644 --- a/js/tools/EraserTool.js +++ b/js/tools/EraserTool.js @@ -103,7 +103,7 @@ class EraserTool extends ResizableTool { prevY, currX, currY, - this.currSize + this.currSize, true ); } else { currFile.currentLayer.drawLine( @@ -111,7 +111,7 @@ class EraserTool extends ResizableTool { prevY - horizontalFactor, currX - verticalFactor, currY - horizontalFactor, - this.currSize + this.currSize, true ); } } From c10af4623ef6403812a14bc871394e9cc1f70b7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Marino=CC=80?= Date: Sat, 5 Feb 2022 22:24:13 +0100 Subject: [PATCH 10/10] resizable axis based on zoom --- js/Startup.js | 2 +- js/layers/HSymmetryLayer.js | 11 +++++++++++ js/layers/VSymmetryLayer.js | 11 +++++++++++ js/tools/ZoomTool.js | 12 +++++++++++- 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/js/Startup.js b/js/Startup.js index 13c7677..a8f2c1b 100644 --- a/js/Startup.js +++ b/js/Startup.js @@ -123,9 +123,9 @@ const Startup = (() => { currFile.layers.push(currFile.checkerBoard); currFile.layers.push(currFile.currentLayer); currFile.layers.push(currFile.TMPLayer); - currFile.layers.push(currFile.pixelGrid); currFile.layers.push(currFile.hSymmetricLayer); currFile.layers.push(currFile.vSymmetricLayer); + currFile.layers.push(currFile.pixelGrid); currFile.layers.push(currFile.VFXLayer); } } diff --git a/js/layers/HSymmetryLayer.js b/js/layers/HSymmetryLayer.js index bd98de0..488ce2c 100644 --- a/js/layers/HSymmetryLayer.js +++ b/js/layers/HSymmetryLayer.js @@ -28,15 +28,26 @@ class HSymmetryLayer extends Layer { // get toggle h axis button let toggleButton = document.getElementById("toggle-h-symmetry-button"); toggleButton.innerHTML = "Hide Horizontal Symmetry"; + this.isEnabled = true; this.canvas.style.display = "inline-block"; } + initPaint() { + this.lineDistance = 5; + this.fillAxis(); + } + repaint(factor) { this.lineDistance += factor; this.fillAxis(); } + normalPaint() { + this.lineDistance = 10; + this.fillAxis(); + } + /** * Shows or hides axis depending on its current visibility * (triggered by the show h symmetry button in the top menu) diff --git a/js/layers/VSymmetryLayer.js b/js/layers/VSymmetryLayer.js index 601a4bd..711d240 100644 --- a/js/layers/VSymmetryLayer.js +++ b/js/layers/VSymmetryLayer.js @@ -30,6 +30,12 @@ class VSymmetryLayer extends Layer { toggleButton.innerHTML = "Hide Vertical Axis"; this.isEnabled = true; this.canvas.style.display = "inline-block"; + this.initPaint(); + } + + initPaint() { + this.lineDistance = 5; + this.fillAxis(); } repaint(factor) { @@ -37,6 +43,11 @@ class VSymmetryLayer extends Layer { this.fillAxis(); } + normalPaint() { + this.lineDistance = 10; + this.fillAxis(); + } + /** * Shows or hides axis depending on its current visibility * (triggered by the show h symmetry button in the top menu) diff --git a/js/tools/ZoomTool.js b/js/tools/ZoomTool.js index a945bb6..b2782ba 100644 --- a/js/tools/ZoomTool.js +++ b/js/tools/ZoomTool.js @@ -60,18 +60,28 @@ class ZoomTool extends Tool { // Adjust pixel grid thickness if (zoomed) { - if (currFile.zoom <= 7) + + if (currFile.zoom <= 7) { currFile.pixelGrid.disablePixelGrid(); + currFile.hSymmetricLayer.repaint((currFile.zoom - prevZoom) * 1.8); + currFile.vSymmetricLayer.repaint((currFile.zoom - prevZoom) * 1.8); + } else if (currFile.zoom >= 20 && mode == 'in') { currFile.pixelGrid.enablePixelGrid(); currFile.pixelGrid.repaintPixelGrid((currFile.zoom - prevZoom) * 0.6); + currFile.hSymmetricLayer.normalPaint(); + currFile.vSymmetricLayer.normalPaint(); } else if (prevZoom >= 20 && mode == 'out') { currFile.pixelGrid.enablePixelGrid(); currFile.pixelGrid.repaintPixelGrid((currFile.zoom - prevZoom) * 0.6); + currFile.hSymmetricLayer.normalPaint(); + currFile.vSymmetricLayer.normalPaint(); } else { currFile.pixelGrid.enablePixelGrid(); + currFile.hSymmetricLayer.normalPaint(); + currFile.vSymmetricLayer.normalPaint(); } }