Changed map and fog erase to allow for multi item selection

This commit is contained in:
Mitchell McCaffrey 2020-05-31 12:12:16 +10:00
parent 55bf9e4d03
commit 337a769fe4
3 changed files with 78 additions and 80 deletions

View File

@ -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({
<MapDrawing
shapes={mapShapes}
onShapeAdd={handleMapShapeAdd}
onShapeRemove={handleMapShapeRemove}
onShapesRemove={handleMapShapesRemove}
selectedToolId={selectedToolId}
selectedToolSettings={toolSettings[selectedToolId]}
gridSize={gridSizeNormalized}
@ -286,8 +286,8 @@ function Map({
<MapFog
shapes={fogShapes}
onShapeAdd={handleFogShapeAdd}
onShapeRemove={handleFogShapeRemove}
onShapeEdit={handleFogShapeEdit}
onShapesRemove={handleFogShapesRemove}
onShapesEdit={handleFogShapesEdit}
selectedToolId={selectedToolId}
selectedToolSettings={toolSettings[selectedToolId]}
gridSize={gridSizeNormalized}

View File

@ -19,13 +19,15 @@ import useMapBrush from "../../helpers/useMapBrush";
function MapDrawing({
shapes,
onShapeAdd,
onShapeRemove,
onShapesRemove,
selectedToolId,
selectedToolSettings,
gridSize,
}) {
const { stageScale, mapWidth, mapHeight } = useContext(MapInteractionContext);
const [drawingShape, setDrawingShape] = useState(null);
const [isBrushDown, setIsBrushDown] = useState(false);
const [erasingShapes, setErasingShapes] = useState([]);
const shouldHover = selectedToolId === "erase";
const isEditing =
@ -33,6 +35,14 @@ function MapDrawing({
selectedToolId === "shape" ||
selectedToolId === "erase";
const handleBrushUp = useCallback(() => {
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 (
<Group>
{shapes.map(renderShape)}
{drawingShape && renderShape(drawingShape)}
{erasingShapes.length > 0 && erasingShapes.map(renderErasingShape)}
</Group>
);
}

View File

@ -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 (
<Line
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)}
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 (
<Group>
{shapes.map(renderShape)}
{drawingShape && renderShape(drawingShape)}
{editingShapes.length > 0 && editingShapes.map(renderEditingShape)}
</Group>
);
}