diff --git a/src/components/map/Map.js b/src/components/map/Map.js index 9eb2cb8..8b482a9 100644 --- a/src/components/map/Map.js +++ b/src/components/map/Map.js @@ -99,6 +99,10 @@ function Map({ onFogDraw({ type: "remove", shapeIds: [shapeId], timestamp: Date.now() }); } + function handleFogShapeEdit(shape) { + onFogDraw({ type: "edit", shapes: [shape], timestamp: Date.now() }); + } + // Replay the draw actions and convert them to shapes for the map drawing useEffect(() => { if (!mapState) { @@ -108,7 +112,7 @@ function Map({ let shapesById = {}; for (let i = 0; i <= actionIndex; i++) { const action = actions[i]; - if (action.type === "add") { + if (action.type === "add" || action.type === "edit") { for (let shape of action.shapes) { shapesById[shape.id] = shape; } @@ -233,6 +237,7 @@ function Map({ shapes={fogShapes} onShapeAdd={handleFogShapeAdd} onShapeRemove={handleFogShapeRemove} + onShapeEdit={handleFogShapeEdit} gridSize={gridSizeNormalized} /> ); diff --git a/src/components/map/MapDrawing.js b/src/components/map/MapDrawing.js index 8495a7d..fbc5416 100644 --- a/src/components/map/MapDrawing.js +++ b/src/components/map/MapDrawing.js @@ -27,7 +27,7 @@ function MapDrawing({ const canvasRef = useRef(); const containerRef = useRef(); - const [isDrawing, setIsDrawing] = useState(false); + const [isPointerDown, setIsPointerDown] = useState(false); const [drawingShape, setDrawingShape] = useState(null); const [pointerPosition, setPointerPosition] = useState({ x: -1, y: -1 }); @@ -49,14 +49,14 @@ function MapDrawing({ return; } if (event.touches && event.touches.length !== 1) { - setIsDrawing(false); + setIsPointerDown(false); setDrawingShape(null); return; } const pointer = event.touches ? event.touches[0] : event; const position = getRelativePointerPosition(pointer, containerRef.current); setPointerPosition(position); - setIsDrawing(true); + setIsPointerDown(true); const brushPosition = getBrushPositionForTool( position, selectedTool, @@ -104,7 +104,7 @@ function MapDrawing({ ); setPointerPosition(position); } - if (isDrawing) { + if (isPointerDown) { const position = getRelativePointerPosition( pointer, containerRef.current @@ -168,10 +168,10 @@ function MapDrawing({ onShapeAdd(drawingShape); } - if (selectedTool === "erase" && hoveredShapeRef.current && isDrawing) { + if (selectedTool === "erase" && hoveredShapeRef.current && isPointerDown) { onShapeRemove(hoveredShapeRef.current.id); } - setIsDrawing(false); + setIsPointerDown(false); setDrawingShape(null); } @@ -229,7 +229,7 @@ function MapDrawing({ width, height, pointerPosition, - isDrawing, + isPointerDown, selectedTool, drawingShape, gridSize, diff --git a/src/components/map/MapFog.js b/src/components/map/MapFog.js index 7b45f4d..50774e6 100644 --- a/src/components/map/MapFog.js +++ b/src/components/map/MapFog.js @@ -12,6 +12,8 @@ import { import MapInteractionContext from "../../contexts/MapInteractionContext"; +import diagonalPattern from "../../images/DiagonalPattern.png"; + function MapFog({ width, height, @@ -20,12 +22,13 @@ function MapFog({ shapes, onShapeAdd, onShapeRemove, + onShapeEdit, gridSize, }) { const canvasRef = useRef(); const containerRef = useRef(); - const [isDrawing, setIsDrawing] = useState(false); + const [isPointerDown, setIsPointerDown] = useState(false); const [drawingShape, setDrawingShape] = useState(null); const [pointerPosition, setPointerPosition] = useState({ x: -1, y: -1 }); @@ -45,14 +48,14 @@ function MapFog({ return; } if (event.touches && event.touches.length !== 1) { - setIsDrawing(false); + setIsPointerDown(false); setDrawingShape(null); return; } const pointer = event.touches ? event.touches[0] : event; const position = getRelativePointerPosition(pointer, containerRef.current); setPointerPosition(position); - setIsDrawing(true); + setIsPointerDown(true); const brushPosition = getBrushPositionForTool( position, "fog", @@ -68,6 +71,7 @@ function MapFog({ color: "black", blend: true, // Blend while drawing id: shortid.generate(), + visible: true, }); } } @@ -85,7 +89,7 @@ function MapFog({ if (shouldHover) { setPointerPosition(position); } - if (isDrawing) { + if (isPointerDown) { setPointerPosition(position); const brushPosition = getBrushPositionForTool( position, @@ -140,15 +144,18 @@ function MapFog({ } } - if ( - toolSettings.type === "remove" && - hoveredShapeRef.current && - isDrawing - ) { - onShapeRemove(hoveredShapeRef.current.id); + if (hoveredShapeRef.current && isPointerDown) { + if (toolSettings.type === "remove") { + onShapeRemove(hoveredShapeRef.current.id); + } else if (toolSettings.type === "toggle") { + onShapeEdit({ + ...hoveredShapeRef.current, + visible: !hoveredShapeRef.current.visible, + }); + } } setDrawingShape(null); - setIsDrawing(false); + setIsPointerDown(false); } // Add listeners for draw events on map to allow drawing past the bounds @@ -176,6 +183,14 @@ function MapFog({ * Rendering */ const hoveredShapeRef = useRef(null); + const diagonalPatternRef = useRef(); + + useEffect(() => { + let image = new Image(); + image.src = diagonalPattern; + diagonalPatternRef.current = image; + }, []); + useEffect(() => { const canvas = canvasRef.current; if (canvas) { @@ -183,30 +198,45 @@ function MapFog({ context.clearRect(0, 0, width, height); let hoveredShape = null; - for (let shape of shapes) { - if (shouldHover) { - if (isShapeHovered(shape, context, pointerPosition, width, height)) { - hoveredShape = shape; + if (isEditing) { + const editPattern = context.createPattern( + diagonalPatternRef.current, + "repeat" + ); + for (let shape of shapes) { + if (shouldHover) { + if ( + isShapeHovered(shape, context, pointerPosition, width, height) + ) { + hoveredShape = shape; + } } - } - if (isEditing) { drawShape( - { ...shape, blend: true }, + { + ...shape, + blend: true, + color: shape.visible ? "black" : editPattern, + }, context, gridSize, width, height ); - } else { + } + if (drawingShape) { + drawShape(drawingShape, context, gridSize, width, height); + } + if (hoveredShape) { + const shape = { ...hoveredShape, color: "#BB99FF", blend: true }; drawShape(shape, context, gridSize, width, height); } - } - if (drawingShape) { - drawShape(drawingShape, context, gridSize, width, height); - } - if (hoveredShape) { - const shape = { ...hoveredShape, color: "#BB99FF", blend: true }; - drawShape(shape, context, gridSize, width, height); + } else { + // Not editing + for (let shape of shapes) { + if (shape.visible) { + drawShape(shape, context, gridSize, width, height); + } + } } hoveredShapeRef.current = hoveredShape; } @@ -215,7 +245,6 @@ function MapFog({ width, height, pointerPosition, - isDrawing, isEditing, drawingShape, gridSize, diff --git a/src/images/DiagonalPattern.png b/src/images/DiagonalPattern.png new file mode 100644 index 0000000..5d44de9 Binary files /dev/null and b/src/images/DiagonalPattern.png differ