From 337a769fe455314a661746c297437901f8dad607 Mon Sep 17 00:00:00 2001 From: Mitchell McCaffrey Date: Sun, 31 May 2020 12:12:16 +1000 Subject: [PATCH] Changed map and fog erase to allow for multi item selection --- src/components/map/Map.js | 18 ++++---- src/components/map/MapDrawing.js | 62 ++++++++++++------------- src/components/map/MapFog.js | 78 ++++++++++++++++---------------- 3 files changed, 78 insertions(+), 80 deletions(-) diff --git a/src/components/map/Map.js b/src/components/map/Map.js index f44e5e1..71b0a1f 100644 --- a/src/components/map/Map.js +++ b/src/components/map/Map.js @@ -97,8 +97,8 @@ function Map({ onMapDraw({ type: "add", shapes: [shape] }); } - function handleMapShapeRemove(shapeId) { - onMapDraw({ type: "remove", shapeIds: [shapeId] }); + function handleMapShapesRemove(shapeIds) { + onMapDraw({ type: "remove", shapeIds }); } const [fogShapes, setFogShapes] = useState([]); @@ -107,12 +107,12 @@ function Map({ onFogDraw({ type: "add", shapes: [shape] }); } - function handleFogShapeRemove(shapeId) { - onFogDraw({ type: "remove", shapeIds: [shapeId] }); + function handleFogShapesRemove(shapeIds) { + onFogDraw({ type: "remove", shapeIds }); } - function handleFogShapeEdit(shape) { - onFogDraw({ type: "edit", shapes: [shape] }); + function handleFogShapesEdit(shapes) { + onFogDraw({ type: "edit", shapes }); } // Replay the draw actions and convert them to shapes for the map drawing @@ -275,7 +275,7 @@ function Map({ { + setIsBrushDown(false); + if (erasingShapes.length > 0) { + onShapesRemove(erasingShapes.map((shape) => shape.id)); + setErasingShapes([]); + } + }, [erasingShapes, onShapesRemove]); + const handleShapeDraw = useCallback( (brushState, mapBrushPosition) => { function startShape() { @@ -65,6 +75,7 @@ function MapDrawing({ ...commonShapeData, }); } + setIsBrushDown(true); } function continueShape() { @@ -119,6 +130,7 @@ function MapDrawing({ onShapeAdd(drawingShape); } setDrawingShape(null); + handleBrushUp(); } switch (brushState) { @@ -143,48 +155,27 @@ function MapDrawing({ onShapeAdd, shapes, drawingShape, + handleBrushUp, ] ); useMapBrush(isEditing, handleShapeDraw); - function handleShapeClick(_, shape) { - if (selectedToolId === "erase") { - onShapeRemove(shape.id); - } - } - - function handleShapeMouseOver(event, shape) { - if (shouldHover) { - const path = event.target; - const hoverColor = "#BB99FF"; - path.fill(hoverColor); - if (shape.type === "path") { - path.stroke(hoverColor); + function handleShapeOver(shape, isDown) { + if (shouldHover && isDown) { + if (erasingShapes.findIndex((s) => s.id === shape.id) === -1) { + setErasingShapes((prevShapes) => [...prevShapes, shape]); } - path.getLayer().draw(); - } - } - - function handleShapeMouseOut(event, shape) { - if (shouldHover) { - const path = event.target; - const color = colors[shape.color] || shape.color; - path.fill(color); - if (shape.type === "path") { - path.stroke(color); - } - path.getLayer().draw(); } } function renderShape(shape) { const defaultProps = { key: shape.id, - onMouseOver: (e) => handleShapeMouseOver(e, shape), - onMouseOut: (e) => handleShapeMouseOut(e, shape), - onClick: (e) => handleShapeClick(e, shape), - onTap: (e) => handleShapeClick(e, shape), + onMouseMove: () => handleShapeOver(shape, isBrushDown), + onTouchOver: () => handleShapeOver(shape, isBrushDown), + onMouseDown: () => handleShapeOver(shape, true), + onTouchStart: () => handleShapeOver(shape, true), fill: colors[shape.color] || shape.color, opacity: shape.blend ? 0.5 : 1, }; @@ -245,10 +236,19 @@ function MapDrawing({ } } + function renderErasingShape(shape) { + const eraseShape = { + ...shape, + color: "#BB99FF", + }; + return renderShape(eraseShape); + } + return ( {shapes.map(renderShape)} {drawingShape && renderShape(drawingShape)} + {erasingShapes.length > 0 && erasingShapes.map(renderErasingShape)} ); } diff --git a/src/components/map/MapFog.js b/src/components/map/MapFog.js index fbb8782..84dc929 100644 --- a/src/components/map/MapFog.js +++ b/src/components/map/MapFog.js @@ -20,14 +20,16 @@ import useMapBrush from "../../helpers/useMapBrush"; function MapFog({ shapes, onShapeAdd, - onShapeRemove, - onShapeEdit, + onShapesRemove, + onShapesEdit, selectedToolId, selectedToolSettings, gridSize, }) { const { stageScale, mapWidth, mapHeight } = useContext(MapInteractionContext); const [drawingShape, setDrawingShape] = useState(null); + const [isBrushDown, setIsBrushDown] = useState(false); + const [editingShapes, setEditingShapes] = useState([]); const isEditing = selectedToolId === "fog"; const shouldHover = @@ -37,6 +39,20 @@ function MapFog({ const [patternImage] = useImage(diagonalPattern); + const handleBrushUp = useCallback(() => { + setIsBrushDown(false); + if (editingShapes.length > 0) { + if (selectedToolSettings.type === "remove") { + onShapesRemove(editingShapes.map((shape) => shape.id)); + } else if (selectedToolSettings.type === "toggle") { + onShapesEdit( + editingShapes.map((shape) => ({ ...shape, visible: !shape.visible })) + ); + } + setEditingShapes([]); + } + }, [editingShapes, onShapesRemove, onShapesEdit, selectedToolSettings]); + const handleShapeDraw = useCallback( (brushState, mapBrushPosition) => { function startShape() { @@ -58,6 +74,7 @@ function MapFog({ visible: true, }); } + setIsBrushDown(true); } function continueShape() { @@ -106,6 +123,7 @@ function MapFog({ } } setDrawingShape(null); + handleBrushUp(); } switch (brushState) { @@ -130,46 +148,17 @@ function MapFog({ onShapeAdd, shapes, drawingShape, + handleBrushUp, ] ); useMapBrush(isEditing, handleShapeDraw); - function handleShapeClick(_, shape) { - if (!isEditing) { - return; - } - - if (selectedToolSettings.type === "remove") { - onShapeRemove(shape.id); - } else if (selectedToolSettings.type === "toggle") { - onShapeEdit({ ...shape, visible: !shape.visible }); - } - } - - function handleShapeMouseOver(event, shape) { - if (shouldHover) { - const path = event.target; - if (shape.visible) { - const hoverColor = "#BB99FF"; - path.fill(hoverColor); - } else { - path.opacity(1); + function handleShapeOver(shape, isDown) { + if (shouldHover && isDown) { + if (editingShapes.findIndex((s) => s.id === shape.id) === -1) { + setEditingShapes((prevShapes) => [...prevShapes, shape]); } - path.getLayer().draw(); - } - } - - function handleShapeMouseOut(event, shape) { - if (shouldHover) { - const path = event.target; - if (shape.visible) { - const color = colors[shape.color] || shape.color; - path.fill(color); - } else { - path.opacity(0.5); - } - path.getLayer().draw(); } } @@ -177,10 +166,10 @@ function MapFog({ return ( handleShapeMouseOver(e, shape)} - onMouseOut={(e) => handleShapeMouseOut(e, shape)} - onClick={(e) => handleShapeClick(e, shape)} - onTap={(e) => handleShapeClick(e, shape)} + onMouseMove={() => handleShapeOver(shape, isBrushDown)} + onTouchOver={() => handleShapeOver(shape, isBrushDown)} + onMouseDown={() => handleShapeOver(shape, true)} + onTouchStart={() => handleShapeOver(shape, true)} points={shape.data.points.reduce( (acc, point) => [...acc, point.x * mapWidth, point.y * mapHeight], [] @@ -203,10 +192,19 @@ function MapFog({ ); } + function renderEditingShape(shape) { + const editingShape = { + ...shape, + color: "#BB99FF", + }; + return renderShape(editingShape); + } + return ( {shapes.map(renderShape)} {drawingShape && renderShape(drawingShape)} + {editingShapes.length > 0 && editingShapes.map(renderEditingShape)} ); }