From 558db7d88b357be10fb61ac6f373f3c5f7f6434c Mon Sep 17 00:00:00 2001 From: Mitchell McCaffrey Date: Tue, 4 Aug 2020 14:51:31 +1000 Subject: [PATCH] Changed fog so it is tranparent when you can edit it Added a show preview toggle to see how others will see it. Refactored fog and drawing props to simplify --- src/components/map/Map.js | 18 +++-- src/components/map/MapDrawing.js | 48 +++++------ src/components/map/MapFog.js | 80 ++++++++----------- .../map/controls/FogPreviewToggle.js | 19 +++++ .../map/controls/FogToolSettings.js | 7 +- src/icons/FogPreviewOffIcon.js | 18 +++++ src/icons/FogPreviewOnIcon.js | 18 +++++ 7 files changed, 131 insertions(+), 77 deletions(-) create mode 100644 src/components/map/controls/FogPreviewToggle.js create mode 100644 src/icons/FogPreviewOffIcon.js create mode 100644 src/icons/FogPreviewOnIcon.js diff --git a/src/components/map/Map.js b/src/components/map/Map.js index 3ef9c89..7233d05 100644 --- a/src/components/map/Map.js +++ b/src/components/map/Map.js @@ -50,7 +50,12 @@ function Map({ const [selectedToolId, setSelectedToolId] = useState("pan"); const [toolSettings, setToolSettings] = useState({ - fog: { type: "polygon", useEdgeSnapping: false, useFogCut: false }, + fog: { + type: "polygon", + useEdgeSnapping: false, + useFogCut: false, + preview: false, + }, drawing: { color: "red", type: "brush", @@ -278,8 +283,9 @@ function Map({ shapes={mapShapes} onShapeAdd={handleMapShapeAdd} onShapesRemove={handleMapShapesRemove} - selectedToolId={selectedToolId} - selectedToolSettings={toolSettings[selectedToolId]} + active={selectedToolId === "drawing"} + toolId="drawing" + toolSettings={toolSettings.drawing} gridSize={gridSizeNormalized} /> ); @@ -291,9 +297,11 @@ function Map({ onShapeSubtract={handleFogShapeSubtract} onShapesRemove={handleFogShapesRemove} onShapesEdit={handleFogShapesEdit} - selectedToolId={selectedToolId} - selectedToolSettings={toolSettings[selectedToolId]} + active={selectedToolId === "fog"} + toolId="fog" + toolSettings={toolSettings.fog} gridSize={gridSizeNormalized} + transparent={allowFogDrawing && !toolSettings.fog.preview} /> ); diff --git a/src/components/map/MapDrawing.js b/src/components/map/MapDrawing.js index 370baee..b63ec70 100644 --- a/src/components/map/MapDrawing.js +++ b/src/components/map/MapDrawing.js @@ -21,8 +21,9 @@ function MapDrawing({ shapes, onShapeAdd, onShapesRemove, - selectedToolId, - selectedToolSettings, + active, + toolId, + toolSettings, gridSize, }) { const { stageScale, mapWidth, mapHeight, interactionEmitter } = useContext( @@ -33,22 +34,17 @@ function MapDrawing({ const [isBrushDown, setIsBrushDown] = useState(false); const [erasingShapes, setErasingShapes] = useState([]); - const shouldHover = - selectedToolSettings && selectedToolSettings.type === "erase"; - const isEditing = selectedToolId === "drawing"; + const shouldHover = toolSettings.type === "erase"; const isBrush = - selectedToolSettings && - (selectedToolSettings.type === "brush" || - selectedToolSettings.type === "paint"); + toolSettings.type === "brush" || toolSettings.type === "paint"; const isShape = - selectedToolSettings && - (selectedToolSettings.type === "line" || - selectedToolSettings.type === "rectangle" || - selectedToolSettings.type === "circle" || - selectedToolSettings.type === "triangle"); + toolSettings.type === "line" || + toolSettings.type === "rectangle" || + toolSettings.type === "circle" || + toolSettings.type === "triangle"; useEffect(() => { - if (!isEditing) { + if (!active) { return; } const mapStage = mapStageRef.current; @@ -57,8 +53,8 @@ function MapDrawing({ const mapImage = mapStage.findOne("#mapImage"); return getBrushPositionForTool( getRelativePointerPositionNormalized(mapImage), - selectedToolId, - selectedToolSettings, + toolId, + toolSettings, gridSize, shapes ); @@ -67,24 +63,24 @@ function MapDrawing({ function handleBrushDown() { const brushPosition = getBrushPosition(); const commonShapeData = { - color: selectedToolSettings && selectedToolSettings.color, - blend: selectedToolSettings && selectedToolSettings.useBlending, + color: toolSettings.color, + blend: toolSettings.useBlending, id: shortid.generate(), }; if (isBrush) { setDrawingShape({ type: "path", - pathType: selectedToolSettings.type === "brush" ? "stroke" : "fill", + pathType: toolSettings.type === "brush" ? "stroke" : "fill", data: { points: [brushPosition] }, - strokeWidth: selectedToolSettings.type === "brush" ? 1 : 0, + strokeWidth: toolSettings.type === "brush" ? 1 : 0, ...commonShapeData, }); } else if (isShape) { setDrawingShape({ type: "shape", - shapeType: selectedToolSettings.type, - data: getDefaultShapeData(selectedToolSettings.type, brushPosition), - strokeWidth: selectedToolSettings.type === "line" ? 1 : 0, + shapeType: toolSettings.type, + data: getDefaultShapeData(toolSettings.type, brushPosition), + strokeWidth: toolSettings.type === "line" ? 1 : 0, ...commonShapeData, }); } @@ -163,13 +159,13 @@ function MapDrawing({ gridSize, isBrush, isBrushDown, - isEditing, + active, + toolId, isShape, mapStageRef, onShapeAdd, onShapesRemove, - selectedToolId, - selectedToolSettings, + toolSettings, shapes, stageScale, interactionEmitter, diff --git a/src/components/map/MapFog.js b/src/components/map/MapFog.js index 7a03c81..c660017 100644 --- a/src/components/map/MapFog.js +++ b/src/components/map/MapFog.js @@ -27,9 +27,11 @@ function MapFog({ onShapeSubtract, onShapesRemove, onShapesEdit, - selectedToolId, - selectedToolSettings, + active, + toolId, + toolSettings, gridSize, + transparent, }) { const { stageScale, mapWidth, mapHeight, interactionEmitter } = useContext( MapInteractionContext @@ -39,16 +41,14 @@ function MapFog({ const [isBrushDown, setIsBrushDown] = useState(false); const [editingShapes, setEditingShapes] = useState([]); - const isEditing = selectedToolId === "fog"; const shouldHover = - isEditing && - (selectedToolSettings.type === "toggle" || - selectedToolSettings.type === "remove"); + active && + (toolSettings.type === "toggle" || toolSettings.type === "remove"); const [patternImage] = useImage(diagonalPattern); useEffect(() => { - if (!isEditing) { + if (!active) { return; } @@ -58,8 +58,8 @@ function MapFog({ const mapImage = mapStage.findOne("#mapImage"); return getBrushPositionForTool( getRelativePointerPositionNormalized(mapImage), - selectedToolId, - selectedToolSettings, + toolId, + toolSettings, gridSize, shapes ); @@ -67,7 +67,7 @@ function MapFog({ function handleBrushDown() { const brushPosition = getBrushPosition(); - if (selectedToolSettings.type === "brush") { + if (toolSettings.type === "brush") { setDrawingShape({ type: "fog", data: { @@ -75,7 +75,7 @@ function MapFog({ holes: [], }, strokeWidth: 0.5, - color: selectedToolSettings.useFogSubtract ? "red" : "black", + color: toolSettings.useFogSubtract ? "red" : "black", blend: false, id: shortid.generate(), visible: true, @@ -85,11 +85,7 @@ function MapFog({ } function handleBrushMove() { - if ( - selectedToolSettings.type === "brush" && - isBrushDown && - drawingShape - ) { + if (toolSettings.type === "brush" && isBrushDown && drawingShape) { const brushPosition = getBrushPosition(); setDrawingShape((prevShape) => { const prevPoints = prevShape.data.points; @@ -114,8 +110,8 @@ function MapFog({ } function handleBrushUp() { - if (selectedToolSettings.type === "brush" && drawingShape) { - const subtract = selectedToolSettings.useFogSubtract; + if (toolSettings.type === "brush" && drawingShape) { + const subtract = toolSettings.useFogSubtract; if (drawingShape.data.points.length > 1) { let shapeData = {}; @@ -147,9 +143,9 @@ function MapFog({ // Erase if (editingShapes.length > 0) { - if (selectedToolSettings.type === "remove") { + if (toolSettings.type === "remove") { onShapesRemove(editingShapes.map((shape) => shape.id)); - } else if (selectedToolSettings.type === "toggle") { + } else if (toolSettings.type === "toggle") { onShapesEdit( editingShapes.map((shape) => ({ ...shape, @@ -164,7 +160,7 @@ function MapFog({ } function handlePolygonClick() { - if (selectedToolSettings.type === "polygon") { + if (toolSettings.type === "polygon") { const brushPosition = getBrushPosition(); setDrawingShape((prevDrawingShape) => { if (prevDrawingShape) { @@ -183,7 +179,7 @@ function MapFog({ holes: [], }, strokeWidth: 0.5, - color: selectedToolSettings.useFogSubtract ? "red" : "black", + color: toolSettings.useFogSubtract ? "red" : "black", blend: false, id: shortid.generate(), visible: true, @@ -194,7 +190,7 @@ function MapFog({ } function handlePolygonMove() { - if (selectedToolSettings.type === "polygon" && drawingShape) { + if (toolSettings.type === "polygon" && drawingShape) { const brushPosition = getBrushPosition(); setDrawingShape((prevShape) => { if (!prevShape) { @@ -229,7 +225,7 @@ function MapFog({ }; }, [ mapStageRef, - isEditing, + active, drawingShape, editingShapes, gridSize, @@ -238,15 +234,15 @@ function MapFog({ onShapeSubtract, onShapesEdit, onShapesRemove, - selectedToolId, - selectedToolSettings, + toolId, + toolSettings, shapes, stageScale, interactionEmitter, ]); const finishDrawingPolygon = useCallback(() => { - const subtract = selectedToolSettings.useFogSubtract; + const subtract = toolSettings.useFogSubtract; const data = { ...drawingShape.data, // Remove the last point as it hasn't been placed yet @@ -263,16 +259,12 @@ function MapFog({ } setDrawingShape(null); - }, [selectedToolSettings, drawingShape, onShapeSubtract, onShapeAdd]); + }, [toolSettings, drawingShape, onShapeSubtract, onShapeAdd]); // Add keyboard shortcuts useEffect(() => { function handleKeyDown({ key }) { - if ( - key === "Enter" && - selectedToolSettings.type === "polygon" && - drawingShape - ) { + if (key === "Enter" && toolSettings.type === "polygon" && drawingShape) { finishDrawingPolygon(); } if (key === "Escape" && drawingShape) { @@ -296,7 +288,7 @@ function MapFog({ } return { ...prevShape, - color: selectedToolSettings.useFogSubtract ? "black" : "red", + color: toolSettings.useFogSubtract ? "black" : "red", }; }); } @@ -307,12 +299,7 @@ function MapFog({ interactionEmitter.off("keyDown", handleKeyDown); interactionEmitter.off("keyUp", handleKeyUp); }; - }, [ - finishDrawingPolygon, - interactionEmitter, - drawingShape, - selectedToolSettings, - ]); + }, [finishDrawingPolygon, interactionEmitter, drawingShape, toolSettings]); function handleShapeOver(shape, isDown) { if (shouldHover && isDown) { @@ -349,11 +336,14 @@ function MapFog({ mapWidth, mapHeight )} - visible={isEditing || shape.visible} - opacity={isEditing ? 0.5 : 1} + visible={(active && !toolSettings.preview) || shape.visible} + opacity={transparent ? 0.5 : 1} fillPatternImage={patternImage} - fillPriority={isEditing && !shape.visible ? "pattern" : "color"} + fillPriority={active && !shape.visible ? "pattern" : "color"} holes={holes} + // Disable collision if the fog is transparent and we're not editing it + // This allows tokens to be moved under the fog + hitFunc={transparent && !active ? () => {} : undefined} /> ); } @@ -394,8 +384,8 @@ function MapFog({ {shapes.map(renderShape)} {drawingShape && renderShape(drawingShape)} {drawingShape && - selectedToolSettings && - selectedToolSettings.type === "polygon" && + toolSettings && + toolSettings.type === "polygon" && renderPolygonAcceptTick(drawingShape)} {editingShapes.length > 0 && editingShapes.map(renderEditingShape)} diff --git a/src/components/map/controls/FogPreviewToggle.js b/src/components/map/controls/FogPreviewToggle.js new file mode 100644 index 0000000..1e3f58a --- /dev/null +++ b/src/components/map/controls/FogPreviewToggle.js @@ -0,0 +1,19 @@ +import React from "react"; +import { IconButton } from "theme-ui"; + +import PreviewOnIcon from "../../../icons/FogPreviewOnIcon"; +import PreviewOffIcon from "../../../icons/FogPreviewOffIcon"; + +function FogPreviewToggle({ useFogPreview, onFogPreviewChange }) { + return ( + onFogPreviewChange(!useFogPreview)} + > + {useFogPreview ? : } + + ); +} + +export default FogPreviewToggle; diff --git a/src/components/map/controls/FogToolSettings.js b/src/components/map/controls/FogToolSettings.js index f94b386..17c0304 100644 --- a/src/components/map/controls/FogToolSettings.js +++ b/src/components/map/controls/FogToolSettings.js @@ -1,9 +1,10 @@ import React, { useContext, useEffect } from "react"; -import { Flex } from "theme-ui"; +import { Flex, Label, Checkbox } from "theme-ui"; import { useMedia } from "react-media"; import EdgeSnappingToggle from "./EdgeSnappingToggle"; import RadioIconButton from "./RadioIconButton"; +import FogPreviewToggle from "./FogPreviewToggle"; import FogBrushIcon from "../../../icons/FogBrushIcon"; import FogPolygonIcon from "../../../icons/FogPolygonIcon"; @@ -142,6 +143,10 @@ function BrushToolSettings({ onSettingChange({ useEdgeSnapping }) } /> + onSettingChange({ preview })} + /> onToolAction("fogUndo")} diff --git a/src/icons/FogPreviewOffIcon.js b/src/icons/FogPreviewOffIcon.js new file mode 100644 index 0000000..458c9d6 --- /dev/null +++ b/src/icons/FogPreviewOffIcon.js @@ -0,0 +1,18 @@ +import React from "react"; + +function FogPreviewOffIcon() { + return ( + + + + + ); +} + +export default FogPreviewOffIcon; diff --git a/src/icons/FogPreviewOnIcon.js b/src/icons/FogPreviewOnIcon.js new file mode 100644 index 0000000..baacee1 --- /dev/null +++ b/src/icons/FogPreviewOnIcon.js @@ -0,0 +1,18 @@ +import React from "react"; + +function FogPreviewOnIcon() { + return ( + + + + + ); +} + +export default FogPreviewOnIcon;