From d4f8433bb18e5acaf9271c3c7a7d9b2e97c3e3dc Mon Sep 17 00:00:00 2001 From: Mitchell McCaffrey Date: Mon, 20 Apr 2020 15:17:56 +1000 Subject: [PATCH] Added brush grid snapping --- src/components/Map.js | 9 ++++++++- src/components/MapControls.js | 33 ++++++++++++++++++++++++++++++++- src/components/MapDrawing.js | 18 ++++++++++++++++-- src/helpers/shared.js | 11 +++++++++++ src/icons/GridOffIcon.js | 18 ++++++++++++++++++ src/icons/GridOnIcon.js | 18 ++++++++++++++++++ 6 files changed, 103 insertions(+), 4 deletions(-) create mode 100644 src/icons/GridOffIcon.js create mode 100644 src/icons/GridOnIcon.js diff --git a/src/components/Map.js b/src/components/Map.js index e155d6c..a2dc2ed 100644 --- a/src/components/Map.js +++ b/src/components/Map.js @@ -45,6 +45,7 @@ function Map({ const [selectedTool, setSelectedTool] = useState("pan"); const [brushColor, setBrushColor] = useState("black"); + const [useBrushGridSnapping, setUseBrushGridSnapping] = useState(false); const [drawnShapes, setDrawnShapes] = useState([]); function handleShapeAdd(shape) { @@ -192,7 +193,9 @@ function Map({ const mapRef = useRef(null); const mapContainerRef = useRef(); const gridX = mapData && mapData.gridX; - const tokenSizePercent = (1 / gridX) * 100; + const gridY = mapData && mapData.gridY; + const gridSizeNormalized = { x: 1 / gridX || 0, y: 1 / gridY || 0 }; + const tokenSizePercent = gridSizeNormalized.x * 100; const aspectRatio = (mapData && mapData.width / mapData.height) || 1; const mapImage = ( @@ -280,6 +283,8 @@ function Map({ onShapeAdd={handleShapeAdd} onShapeRemove={handleShapeRemove} brushColor={brushColor} + useGridSnapping={useBrushGridSnapping} + gridSize={gridSizeNormalized} /> {mapTokens} @@ -296,6 +301,8 @@ function Map({ brushColor={brushColor} onBrushColorChange={setBrushColor} onEraseAll={handleShapeRemoveAll} + useBrushGridSnapping={useBrushGridSnapping} + onBrushGridSnappingChange={setUseBrushGridSnapping} /> ))} + + + ), erase: ( diff --git a/src/components/MapDrawing.js b/src/components/MapDrawing.js index 980c425..3ef1d41 100644 --- a/src/components/MapDrawing.js +++ b/src/components/MapDrawing.js @@ -3,6 +3,7 @@ import simplify from "simplify-js"; import shortid from "shortid"; import colors from "../helpers/colors"; +import { snapPositionToGrid } from "../helpers/shared"; function MapDrawing({ width, @@ -12,6 +13,8 @@ function MapDrawing({ onShapeAdd, onShapeRemove, brushColor, + useGridSnapping, + gridSize, }) { const canvasRef = useRef(); const containerRef = useRef(); @@ -46,7 +49,10 @@ function MapDrawing({ setPointerPosition(position); setIsDrawing(true); if (selectedTool === "brush") { - setBrushPoints([position]); + const brushPosition = useGridSnapping + ? snapPositionToGrid(position, gridSize) + : position; + setBrushPoints([brushPosition]); } } @@ -61,7 +67,15 @@ function MapDrawing({ } if (isDrawing && selectedTool === "brush") { setPointerPosition(position); - setBrushPoints((prevPoints) => [...prevPoints, position]); + const brushPosition = useGridSnapping + ? snapPositionToGrid(position, gridSize) + : position; + setBrushPoints((prevPoints) => { + if (prevPoints[prevPoints.length - 1] === brushPosition) { + return prevPoints; + } + return [...prevPoints, brushPosition]; + }); } } diff --git a/src/helpers/shared.js b/src/helpers/shared.js index b1367ce..aab9b6d 100644 --- a/src/helpers/shared.js +++ b/src/helpers/shared.js @@ -23,3 +23,14 @@ export function fromEntries(iterable) { export function isStreamStopped(stream) { return stream.getTracks().reduce((a, b) => a && b, { mute: true }); } + +export function roundTo(x, to) { + return Math.round(x / to) * to; +} + +export function snapPositionToGrid(position, gridSize) { + return { + x: roundTo(position.x, gridSize.x), + y: roundTo(position.y, gridSize.y), + }; +} diff --git a/src/icons/GridOffIcon.js b/src/icons/GridOffIcon.js new file mode 100644 index 0000000..4996ea0 --- /dev/null +++ b/src/icons/GridOffIcon.js @@ -0,0 +1,18 @@ +import React from "react"; + +function GridOnIcon() { + return ( + + + + + ); +} + +export default GridOnIcon; diff --git a/src/icons/GridOnIcon.js b/src/icons/GridOnIcon.js new file mode 100644 index 0000000..1796b30 --- /dev/null +++ b/src/icons/GridOnIcon.js @@ -0,0 +1,18 @@ +import React from "react"; + +function GridOnIcon() { + return ( + + + + + ); +} + +export default GridOnIcon;