Moved drawing tools into one section
This commit is contained in:
parent
aa4ba33a0b
commit
3ba7c8809c
@ -49,14 +49,9 @@ function Map({
|
||||
const [selectedToolId, setSelectedToolId] = useState("pan");
|
||||
const [toolSettings, setToolSettings] = useState({
|
||||
fog: { type: "polygon", useEdgeSnapping: false, useFogCut: false },
|
||||
brush: {
|
||||
color: "darkGray",
|
||||
type: "stroke",
|
||||
useBlending: false,
|
||||
},
|
||||
shape: {
|
||||
drawing: {
|
||||
color: "red",
|
||||
type: "rectangle",
|
||||
type: "brush",
|
||||
useBlending: true,
|
||||
},
|
||||
});
|
||||
@ -189,33 +184,27 @@ function Map({
|
||||
|
||||
const disabledControls = [];
|
||||
if (!allowMapDrawing) {
|
||||
disabledControls.push("brush");
|
||||
disabledControls.push("shape");
|
||||
disabledControls.push("erase");
|
||||
disabledControls.push("drawing");
|
||||
}
|
||||
if (!map) {
|
||||
disabledControls.push("pan");
|
||||
}
|
||||
if (mapShapes.length === 0) {
|
||||
disabledControls.push("erase");
|
||||
}
|
||||
if (!allowFogDrawing) {
|
||||
disabledControls.push("fog");
|
||||
}
|
||||
|
||||
const disabledSettings = { fog: [], brush: [], shape: [], erase: [] };
|
||||
const disabledSettings = { fog: [], drawing: [] };
|
||||
if (mapShapes.length === 0) {
|
||||
disabledSettings.drawing.push("erase");
|
||||
}
|
||||
if (!mapState || mapState.mapDrawActionIndex < 0) {
|
||||
disabledSettings.brush.push("undo");
|
||||
disabledSettings.shape.push("undo");
|
||||
disabledSettings.erase.push("undo");
|
||||
disabledSettings.drawing.push("undo");
|
||||
}
|
||||
if (
|
||||
!mapState ||
|
||||
mapState.mapDrawActionIndex === mapState.mapDrawActions.length - 1
|
||||
) {
|
||||
disabledSettings.brush.push("redo");
|
||||
disabledSettings.shape.push("redo");
|
||||
disabledSettings.erase.push("redo");
|
||||
disabledSettings.drawing.push("redo");
|
||||
}
|
||||
if (!mapState || mapState.fogDrawActionIndex < 0) {
|
||||
disabledSettings.fog.push("undo");
|
||||
|
@ -7,15 +7,11 @@ import Divider from "../Divider";
|
||||
import SelectMapButton from "./SelectMapButton";
|
||||
|
||||
import FogToolSettings from "./controls/FogToolSettings";
|
||||
import BrushToolSettings from "./controls/BrushToolSettings";
|
||||
import ShapeToolSettings from "./controls/ShapeToolSettings";
|
||||
import EraseToolSettings from "./controls/EraseToolSettings";
|
||||
import DrawingToolSettings from "./controls/DrawingToolSettings";
|
||||
|
||||
import PanToolIcon from "../../icons/PanToolIcon";
|
||||
import FogToolIcon from "../../icons/FogToolIcon";
|
||||
import BrushToolIcon from "../../icons/BrushToolIcon";
|
||||
import ShapeToolIcon from "../../icons/ShapeToolIcon";
|
||||
import EraseToolIcon from "../../icons/EraseToolIcon";
|
||||
import ExpandMoreIcon from "../../icons/ExpandMoreIcon";
|
||||
|
||||
function MapContols({
|
||||
@ -45,26 +41,14 @@ function MapContols({
|
||||
title: "Fog Tool",
|
||||
SettingsComponent: FogToolSettings,
|
||||
},
|
||||
brush: {
|
||||
drawing: {
|
||||
id: "brush",
|
||||
icon: <BrushToolIcon />,
|
||||
title: "Brush Tool",
|
||||
SettingsComponent: BrushToolSettings,
|
||||
},
|
||||
shape: {
|
||||
id: "shape",
|
||||
icon: <ShapeToolIcon />,
|
||||
title: "Shape Tool",
|
||||
SettingsComponent: ShapeToolSettings,
|
||||
},
|
||||
erase: {
|
||||
id: "erase",
|
||||
icon: <EraseToolIcon />,
|
||||
title: "Erase tool",
|
||||
SettingsComponent: EraseToolSettings,
|
||||
SettingsComponent: DrawingToolSettings,
|
||||
},
|
||||
};
|
||||
const tools = ["pan", "fog", "brush", "shape", "erase"];
|
||||
const tools = ["pan", "fog", "drawing"];
|
||||
|
||||
const sections = [
|
||||
{
|
||||
|
@ -29,11 +29,18 @@ function MapDrawing({
|
||||
const [isBrushDown, setIsBrushDown] = useState(false);
|
||||
const [erasingShapes, setErasingShapes] = useState([]);
|
||||
|
||||
const shouldHover = selectedToolId === "erase";
|
||||
const isEditing =
|
||||
selectedToolId === "brush" ||
|
||||
selectedToolId === "shape" ||
|
||||
selectedToolId === "erase";
|
||||
const shouldHover =
|
||||
selectedToolSettings && selectedToolSettings.type === "erase";
|
||||
const isEditing = selectedToolId === "drawing";
|
||||
const isBrush =
|
||||
selectedToolSettings &&
|
||||
(selectedToolSettings.type === "brush" ||
|
||||
selectedToolSettings.type === "paint");
|
||||
const isShape =
|
||||
selectedToolSettings &&
|
||||
(selectedToolSettings.type === "rectangle" ||
|
||||
selectedToolSettings.type === "circle" ||
|
||||
selectedToolSettings.type === "triangle");
|
||||
|
||||
const handleBrushUp = useCallback(() => {
|
||||
setIsBrushDown(false);
|
||||
@ -58,15 +65,15 @@ function MapDrawing({
|
||||
blend: selectedToolSettings && selectedToolSettings.useBlending,
|
||||
id: shortid.generate(),
|
||||
};
|
||||
if (selectedToolId === "brush") {
|
||||
if (isBrush) {
|
||||
setDrawingShape({
|
||||
type: "path",
|
||||
pathType: selectedToolSettings.type,
|
||||
pathType: selectedToolSettings.type === "brush" ? "stroke" : "fill",
|
||||
data: { points: [brushPosition] },
|
||||
strokeWidth: selectedToolSettings.type === "stroke" ? 1 : 0,
|
||||
strokeWidth: selectedToolSettings.type === "brush" ? 1 : 0,
|
||||
...commonShapeData,
|
||||
});
|
||||
} else if (selectedToolId === "shape") {
|
||||
} else if (isShape) {
|
||||
setDrawingShape({
|
||||
type: "shape",
|
||||
shapeType: selectedToolSettings.type,
|
||||
@ -86,7 +93,7 @@ function MapDrawing({
|
||||
gridSize,
|
||||
shapes
|
||||
);
|
||||
if (selectedToolId === "brush") {
|
||||
if (isBrush) {
|
||||
setDrawingShape((prevShape) => {
|
||||
const prevPoints = prevShape.data.points;
|
||||
if (
|
||||
@ -108,7 +115,7 @@ function MapDrawing({
|
||||
data: { points: simplified },
|
||||
};
|
||||
});
|
||||
} else if (selectedToolId === "shape") {
|
||||
} else if (isShape) {
|
||||
setDrawingShape((prevShape) => ({
|
||||
...prevShape,
|
||||
data: getUpdatedShapeData(
|
||||
@ -122,11 +129,11 @@ function MapDrawing({
|
||||
}
|
||||
|
||||
function endShape() {
|
||||
if (selectedToolId === "brush" && drawingShape) {
|
||||
if (isBrush && drawingShape) {
|
||||
if (drawingShape.data.points.length > 1) {
|
||||
onShapeAdd(drawingShape);
|
||||
}
|
||||
} else if (selectedToolId === "shape" && drawingShape) {
|
||||
} else if (isShape && drawingShape) {
|
||||
onShapeAdd(drawingShape);
|
||||
}
|
||||
setDrawingShape(null);
|
||||
@ -156,6 +163,8 @@ function MapDrawing({
|
||||
shapes,
|
||||
drawingShape,
|
||||
handleBrushUp,
|
||||
isBrush,
|
||||
isShape,
|
||||
]
|
||||
);
|
||||
|
||||
|
@ -172,8 +172,7 @@ function MapInteraction({ map, children, controls, selectedToolId }) {
|
||||
case "pan":
|
||||
return "move";
|
||||
case "fog":
|
||||
case "brush":
|
||||
case "shape":
|
||||
case "drawing":
|
||||
return "crosshair";
|
||||
default:
|
||||
return "default";
|
||||
|
@ -1,61 +0,0 @@
|
||||
import React from "react";
|
||||
import { Flex } from "theme-ui";
|
||||
|
||||
import ColorControl from "./ColorControl";
|
||||
import AlphaBlendToggle from "./AlphaBlendToggle";
|
||||
import RadioIconButton from "./RadioIconButton";
|
||||
|
||||
import BrushStrokeIcon from "../../../icons/BrushStrokeIcon";
|
||||
import BrushFillIcon from "../../../icons/BrushFillIcon";
|
||||
|
||||
import UndoButton from "./UndoButton";
|
||||
import RedoButton from "./RedoButton";
|
||||
|
||||
import Divider from "../../Divider";
|
||||
|
||||
function BrushToolSettings({
|
||||
settings,
|
||||
onSettingChange,
|
||||
onToolAction,
|
||||
disabledActions,
|
||||
}) {
|
||||
return (
|
||||
<Flex sx={{ alignItems: "center" }}>
|
||||
<ColorControl
|
||||
color={settings.color}
|
||||
onColorChange={(color) => onSettingChange({ color })}
|
||||
/>
|
||||
<Divider vertical />
|
||||
<RadioIconButton
|
||||
title="Brush Type Stroke"
|
||||
onClick={() => onSettingChange({ type: "stroke" })}
|
||||
isSelected={settings.type === "stroke"}
|
||||
>
|
||||
<BrushStrokeIcon />
|
||||
</RadioIconButton>
|
||||
<RadioIconButton
|
||||
title="Brush Type Fill"
|
||||
onClick={() => onSettingChange({ type: "fill" })}
|
||||
isSelected={settings.type === "fill"}
|
||||
>
|
||||
<BrushFillIcon />
|
||||
</RadioIconButton>
|
||||
<Divider vertical />
|
||||
<AlphaBlendToggle
|
||||
useBlending={settings.useBlending}
|
||||
onBlendingChange={(useBlending) => onSettingChange({ useBlending })}
|
||||
/>
|
||||
<Divider vertical />
|
||||
<UndoButton
|
||||
onClick={() => onToolAction("mapUndo")}
|
||||
disabled={disabledActions.includes("undo")}
|
||||
/>
|
||||
<RedoButton
|
||||
onClick={() => onToolAction("mapRedo")}
|
||||
disabled={disabledActions.includes("redo")}
|
||||
/>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
export default BrushToolSettings;
|
104
src/components/map/controls/DrawingToolSettings.js
Normal file
104
src/components/map/controls/DrawingToolSettings.js
Normal file
@ -0,0 +1,104 @@
|
||||
import React from "react";
|
||||
import { Flex, IconButton } from "theme-ui";
|
||||
|
||||
import ColorControl from "./ColorControl";
|
||||
import AlphaBlendToggle from "./AlphaBlendToggle";
|
||||
import RadioIconButton from "./RadioIconButton";
|
||||
|
||||
import BrushIcon from "../../../icons/BrushToolIcon";
|
||||
import BrushFillIcon from "../../../icons/BrushPaintIcon";
|
||||
import BrushRectangleIcon from "../../../icons/BrushRectangleIcon";
|
||||
import BrushCircleIcon from "../../../icons/BrushCircleIcon";
|
||||
import BrushTriangleIcon from "../../../icons/BrushTriangleIcon";
|
||||
import EraseAllIcon from "../../../icons/EraseAllIcon";
|
||||
import EraseIcon from "../../../icons/EraseToolIcon";
|
||||
|
||||
import UndoButton from "./UndoButton";
|
||||
import RedoButton from "./RedoButton";
|
||||
|
||||
import Divider from "../../Divider";
|
||||
|
||||
function DrawingToolSettings({
|
||||
settings,
|
||||
onSettingChange,
|
||||
onToolAction,
|
||||
disabledActions,
|
||||
}) {
|
||||
return (
|
||||
<Flex sx={{ alignItems: "center" }}>
|
||||
<ColorControl
|
||||
color={settings.color}
|
||||
onColorChange={(color) => onSettingChange({ color })}
|
||||
/>
|
||||
<Divider vertical />
|
||||
<RadioIconButton
|
||||
title="Brush"
|
||||
onClick={() => onSettingChange({ type: "brush" })}
|
||||
isSelected={settings.type === "brush"}
|
||||
>
|
||||
<BrushIcon />
|
||||
</RadioIconButton>
|
||||
<RadioIconButton
|
||||
title="Paint"
|
||||
onClick={() => onSettingChange({ type: "paint" })}
|
||||
isSelected={settings.type === "paint"}
|
||||
>
|
||||
<BrushFillIcon />
|
||||
</RadioIconButton>
|
||||
<RadioIconButton
|
||||
title="Rectangle"
|
||||
onClick={() => onSettingChange({ type: "rectangle" })}
|
||||
isSelected={settings.type === "rectangle"}
|
||||
>
|
||||
<BrushRectangleIcon />
|
||||
</RadioIconButton>
|
||||
<RadioIconButton
|
||||
title="Circle"
|
||||
onClick={() => onSettingChange({ type: "circle" })}
|
||||
isSelected={settings.type === "circle"}
|
||||
>
|
||||
<BrushCircleIcon />
|
||||
</RadioIconButton>
|
||||
<RadioIconButton
|
||||
title="Triangle"
|
||||
onClick={() => onSettingChange({ type: "triangle" })}
|
||||
isSelected={settings.type === "triangle"}
|
||||
>
|
||||
<BrushTriangleIcon />
|
||||
</RadioIconButton>
|
||||
<Divider vertical />
|
||||
<RadioIconButton
|
||||
title="Erase"
|
||||
onClick={() => onSettingChange({ type: "erase" })}
|
||||
isSelected={settings.type === "erase"}
|
||||
disabled={disabledActions.includes("erase")}
|
||||
>
|
||||
<EraseIcon />
|
||||
</RadioIconButton>
|
||||
<IconButton
|
||||
aria-label="Erase All"
|
||||
title="Erase All"
|
||||
onClick={() => onToolAction("eraseAll")}
|
||||
disabled={disabledActions.includes("erase")}
|
||||
>
|
||||
<EraseAllIcon />
|
||||
</IconButton>
|
||||
<Divider vertical />
|
||||
<AlphaBlendToggle
|
||||
useBlending={settings.useBlending}
|
||||
onBlendingChange={(useBlending) => onSettingChange({ useBlending })}
|
||||
/>
|
||||
<Divider vertical />
|
||||
<UndoButton
|
||||
onClick={() => onToolAction("mapUndo")}
|
||||
disabled={disabledActions.includes("undo")}
|
||||
/>
|
||||
<RedoButton
|
||||
onClick={() => onToolAction("mapRedo")}
|
||||
disabled={disabledActions.includes("redo")}
|
||||
/>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
export default DrawingToolSettings;
|
@ -1,34 +0,0 @@
|
||||
import React from "react";
|
||||
import { Flex, IconButton } from "theme-ui";
|
||||
|
||||
import EraseAllIcon from "../../../icons/EraseAllIcon";
|
||||
|
||||
import UndoButton from "./UndoButton";
|
||||
import RedoButton from "./RedoButton";
|
||||
|
||||
import Divider from "../../Divider";
|
||||
|
||||
function EraseToolSettings({ onToolAction, disabledActions }) {
|
||||
return (
|
||||
<Flex sx={{ alignItems: "center" }}>
|
||||
<IconButton
|
||||
aria-label="Erase All"
|
||||
title="Erase All"
|
||||
onClick={() => onToolAction("eraseAll")}
|
||||
>
|
||||
<EraseAllIcon />
|
||||
</IconButton>
|
||||
<Divider vertical />
|
||||
<UndoButton
|
||||
onClick={() => onToolAction("mapUndo")}
|
||||
disabled={disabledActions.includes("undo")}
|
||||
/>
|
||||
<RedoButton
|
||||
onClick={() => onToolAction("mapRedo")}
|
||||
disabled={disabledActions.includes("redo")}
|
||||
/>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
export default EraseToolSettings;
|
@ -1,69 +0,0 @@
|
||||
import React from "react";
|
||||
import { Flex } from "theme-ui";
|
||||
|
||||
import ColorControl from "./ColorControl";
|
||||
import AlphaBlendToggle from "./AlphaBlendToggle";
|
||||
import RadioIconButton from "./RadioIconButton";
|
||||
|
||||
import ShapeRectangleIcon from "../../../icons/ShapeRectangleIcon";
|
||||
import ShapeCircleIcon from "../../../icons/ShapeCircleIcon";
|
||||
import ShapeTriangleIcon from "../../../icons/ShapeTriangleIcon";
|
||||
|
||||
import UndoButton from "./UndoButton";
|
||||
import RedoButton from "./RedoButton";
|
||||
|
||||
import Divider from "../../Divider";
|
||||
|
||||
function ShapeToolSettings({
|
||||
settings,
|
||||
onSettingChange,
|
||||
onToolAction,
|
||||
disabledActions,
|
||||
}) {
|
||||
return (
|
||||
<Flex sx={{ alignItems: "center" }}>
|
||||
<ColorControl
|
||||
color={settings.color}
|
||||
onColorChange={(color) => onSettingChange({ color })}
|
||||
/>
|
||||
<Divider vertical />
|
||||
<RadioIconButton
|
||||
title="Shape Type Rectangle"
|
||||
onClick={() => onSettingChange({ type: "rectangle" })}
|
||||
isSelected={settings.type === "rectangle"}
|
||||
>
|
||||
<ShapeRectangleIcon />
|
||||
</RadioIconButton>
|
||||
<RadioIconButton
|
||||
title="Shape Type Circle"
|
||||
onClick={() => onSettingChange({ type: "circle" })}
|
||||
isSelected={settings.type === "circle"}
|
||||
>
|
||||
<ShapeCircleIcon />
|
||||
</RadioIconButton>
|
||||
<RadioIconButton
|
||||
title="Shape Type Triangle"
|
||||
onClick={() => onSettingChange({ type: "triangle" })}
|
||||
isSelected={settings.type === "triangle"}
|
||||
>
|
||||
<ShapeTriangleIcon />
|
||||
</RadioIconButton>
|
||||
<Divider vertical />
|
||||
<AlphaBlendToggle
|
||||
useBlending={settings.useBlending}
|
||||
onBlendingChange={(useBlending) => onSettingChange({ useBlending })}
|
||||
/>
|
||||
<Divider vertical />
|
||||
<UndoButton
|
||||
onClick={() => onToolAction("mapUndo")}
|
||||
disabled={disabledActions.includes("undo")}
|
||||
/>
|
||||
<RedoButton
|
||||
onClick={() => onToolAction("mapRedo")}
|
||||
disabled={disabledActions.includes("redo")}
|
||||
/>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
export default ShapeToolSettings;
|
@ -12,7 +12,12 @@ export function getBrushPositionForTool(
|
||||
shapes
|
||||
) {
|
||||
let position = brushPosition;
|
||||
if (tool === "shape") {
|
||||
if (
|
||||
tool === "drawing" &&
|
||||
(toolSettings.type === "rectangle" ||
|
||||
toolSettings.type === "circle" ||
|
||||
toolSettings.type === "triangle")
|
||||
) {
|
||||
const snapped = Vector2.roundTo(position, gridSize);
|
||||
const minGrid = Vector2.min(gridSize);
|
||||
const distance = Vector2.length(Vector2.subtract(snapped, position));
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from "react";
|
||||
|
||||
function ShapeCircleIcon() {
|
||||
function BrushCircleIcon() {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@ -15,4 +15,4 @@ function ShapeCircleIcon() {
|
||||
);
|
||||
}
|
||||
|
||||
export default ShapeCircleIcon;
|
||||
export default BrushCircleIcon;
|
@ -1,6 +1,6 @@
|
||||
import React from "react";
|
||||
|
||||
function ShapeRectangleIcon() {
|
||||
function BrushRectangleIcon() {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@ -15,4 +15,4 @@ function ShapeRectangleIcon() {
|
||||
);
|
||||
}
|
||||
|
||||
export default ShapeRectangleIcon;
|
||||
export default BrushRectangleIcon;
|
@ -1,6 +1,6 @@
|
||||
import React from "react";
|
||||
|
||||
function ShapeTriangleIcon() {
|
||||
function BrushTriangleIcon() {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@ -15,4 +15,4 @@ function ShapeTriangleIcon() {
|
||||
);
|
||||
}
|
||||
|
||||
export default ShapeTriangleIcon;
|
||||
export default BrushTriangleIcon;
|
@ -1,20 +0,0 @@
|
||||
import React from "react";
|
||||
|
||||
function ShapeToolIcon() {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
fill="currentcolor"
|
||||
>
|
||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||
<path d="M11.15 3.4L7.43 9.48c-.41.66.07 1.52.85 1.52h7.43c.78 0 1.26-.86.85-1.52L12.85 3.4c-.39-.64-1.31-.64-1.7 0z" />
|
||||
<circle cx="17.5" cy="17.5" r="4.5" />
|
||||
<path d="M4 21.5h6c.55 0 1-.45 1-1v-6c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export default ShapeToolIcon;
|
Loading…
Reference in New Issue
Block a user