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] }); onMapDraw({ type: "add", shapes: [shape] });
} }
function handleMapShapeRemove(shapeId) { function handleMapShapesRemove(shapeIds) {
onMapDraw({ type: "remove", shapeIds: [shapeId] }); onMapDraw({ type: "remove", shapeIds });
} }
const [fogShapes, setFogShapes] = useState([]); const [fogShapes, setFogShapes] = useState([]);
@ -107,12 +107,12 @@ function Map({
onFogDraw({ type: "add", shapes: [shape] }); onFogDraw({ type: "add", shapes: [shape] });
} }
function handleFogShapeRemove(shapeId) { function handleFogShapesRemove(shapeIds) {
onFogDraw({ type: "remove", shapeIds: [shapeId] }); onFogDraw({ type: "remove", shapeIds });
} }
function handleFogShapeEdit(shape) { function handleFogShapesEdit(shapes) {
onFogDraw({ type: "edit", shapes: [shape] }); onFogDraw({ type: "edit", shapes });
} }
// Replay the draw actions and convert them to shapes for the map drawing // Replay the draw actions and convert them to shapes for the map drawing
@ -275,7 +275,7 @@ function Map({
<MapDrawing <MapDrawing
shapes={mapShapes} shapes={mapShapes}
onShapeAdd={handleMapShapeAdd} onShapeAdd={handleMapShapeAdd}
onShapeRemove={handleMapShapeRemove} onShapesRemove={handleMapShapesRemove}
selectedToolId={selectedToolId} selectedToolId={selectedToolId}
selectedToolSettings={toolSettings[selectedToolId]} selectedToolSettings={toolSettings[selectedToolId]}
gridSize={gridSizeNormalized} gridSize={gridSizeNormalized}
@ -286,8 +286,8 @@ function Map({
<MapFog <MapFog
shapes={fogShapes} shapes={fogShapes}
onShapeAdd={handleFogShapeAdd} onShapeAdd={handleFogShapeAdd}
onShapeRemove={handleFogShapeRemove} onShapesRemove={handleFogShapesRemove}
onShapeEdit={handleFogShapeEdit} onShapesEdit={handleFogShapesEdit}
selectedToolId={selectedToolId} selectedToolId={selectedToolId}
selectedToolSettings={toolSettings[selectedToolId]} selectedToolSettings={toolSettings[selectedToolId]}
gridSize={gridSizeNormalized} gridSize={gridSizeNormalized}

View File

@ -19,13 +19,15 @@ import useMapBrush from "../../helpers/useMapBrush";
function MapDrawing({ function MapDrawing({
shapes, shapes,
onShapeAdd, onShapeAdd,
onShapeRemove, onShapesRemove,
selectedToolId, selectedToolId,
selectedToolSettings, selectedToolSettings,
gridSize, gridSize,
}) { }) {
const { stageScale, mapWidth, mapHeight } = useContext(MapInteractionContext); const { stageScale, mapWidth, mapHeight } = useContext(MapInteractionContext);
const [drawingShape, setDrawingShape] = useState(null); const [drawingShape, setDrawingShape] = useState(null);
const [isBrushDown, setIsBrushDown] = useState(false);
const [erasingShapes, setErasingShapes] = useState([]);
const shouldHover = selectedToolId === "erase"; const shouldHover = selectedToolId === "erase";
const isEditing = const isEditing =
@ -33,6 +35,14 @@ function MapDrawing({
selectedToolId === "shape" || selectedToolId === "shape" ||
selectedToolId === "erase"; selectedToolId === "erase";
const handleBrushUp = useCallback(() => {
setIsBrushDown(false);
if (erasingShapes.length > 0) {
onShapesRemove(erasingShapes.map((shape) => shape.id));
setErasingShapes([]);
}
}, [erasingShapes, onShapesRemove]);
const handleShapeDraw = useCallback( const handleShapeDraw = useCallback(
(brushState, mapBrushPosition) => { (brushState, mapBrushPosition) => {
function startShape() { function startShape() {
@ -65,6 +75,7 @@ function MapDrawing({
...commonShapeData, ...commonShapeData,
}); });
} }
setIsBrushDown(true);
} }
function continueShape() { function continueShape() {
@ -119,6 +130,7 @@ function MapDrawing({
onShapeAdd(drawingShape); onShapeAdd(drawingShape);
} }
setDrawingShape(null); setDrawingShape(null);
handleBrushUp();
} }
switch (brushState) { switch (brushState) {
@ -143,48 +155,27 @@ function MapDrawing({
onShapeAdd, onShapeAdd,
shapes, shapes,
drawingShape, drawingShape,
handleBrushUp,
] ]
); );
useMapBrush(isEditing, handleShapeDraw); useMapBrush(isEditing, handleShapeDraw);
function handleShapeClick(_, shape) { function handleShapeOver(shape, isDown) {
if (selectedToolId === "erase") { if (shouldHover && isDown) {
onShapeRemove(shape.id); if (erasingShapes.findIndex((s) => s.id === shape.id) === -1) {
setErasingShapes((prevShapes) => [...prevShapes, shape]);
} }
} }
function handleShapeMouseOver(event, shape) {
if (shouldHover) {
const path = event.target;
const hoverColor = "#BB99FF";
path.fill(hoverColor);
if (shape.type === "path") {
path.stroke(hoverColor);
}
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) { function renderShape(shape) {
const defaultProps = { const defaultProps = {
key: shape.id, key: shape.id,
onMouseOver: (e) => handleShapeMouseOver(e, shape), onMouseMove: () => handleShapeOver(shape, isBrushDown),
onMouseOut: (e) => handleShapeMouseOut(e, shape), onTouchOver: () => handleShapeOver(shape, isBrushDown),
onClick: (e) => handleShapeClick(e, shape), onMouseDown: () => handleShapeOver(shape, true),
onTap: (e) => handleShapeClick(e, shape), onTouchStart: () => handleShapeOver(shape, true),
fill: colors[shape.color] || shape.color, fill: colors[shape.color] || shape.color,
opacity: shape.blend ? 0.5 : 1, opacity: shape.blend ? 0.5 : 1,
}; };
@ -245,10 +236,19 @@ function MapDrawing({
} }
} }
function renderErasingShape(shape) {
const eraseShape = {
...shape,
color: "#BB99FF",
};
return renderShape(eraseShape);
}
return ( return (
<Group> <Group>
{shapes.map(renderShape)} {shapes.map(renderShape)}
{drawingShape && renderShape(drawingShape)} {drawingShape && renderShape(drawingShape)}
{erasingShapes.length > 0 && erasingShapes.map(renderErasingShape)}
</Group> </Group>
); );
} }

View File

@ -20,14 +20,16 @@ import useMapBrush from "../../helpers/useMapBrush";
function MapFog({ function MapFog({
shapes, shapes,
onShapeAdd, onShapeAdd,
onShapeRemove, onShapesRemove,
onShapeEdit, onShapesEdit,
selectedToolId, selectedToolId,
selectedToolSettings, selectedToolSettings,
gridSize, gridSize,
}) { }) {
const { stageScale, mapWidth, mapHeight } = useContext(MapInteractionContext); const { stageScale, mapWidth, mapHeight } = useContext(MapInteractionContext);
const [drawingShape, setDrawingShape] = useState(null); const [drawingShape, setDrawingShape] = useState(null);
const [isBrushDown, setIsBrushDown] = useState(false);
const [editingShapes, setEditingShapes] = useState([]);
const isEditing = selectedToolId === "fog"; const isEditing = selectedToolId === "fog";
const shouldHover = const shouldHover =
@ -37,6 +39,20 @@ function MapFog({
const [patternImage] = useImage(diagonalPattern); 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( const handleShapeDraw = useCallback(
(brushState, mapBrushPosition) => { (brushState, mapBrushPosition) => {
function startShape() { function startShape() {
@ -58,6 +74,7 @@ function MapFog({
visible: true, visible: true,
}); });
} }
setIsBrushDown(true);
} }
function continueShape() { function continueShape() {
@ -106,6 +123,7 @@ function MapFog({
} }
} }
setDrawingShape(null); setDrawingShape(null);
handleBrushUp();
} }
switch (brushState) { switch (brushState) {
@ -130,46 +148,17 @@ function MapFog({
onShapeAdd, onShapeAdd,
shapes, shapes,
drawingShape, drawingShape,
handleBrushUp,
] ]
); );
useMapBrush(isEditing, handleShapeDraw); useMapBrush(isEditing, handleShapeDraw);
function handleShapeClick(_, shape) { function handleShapeOver(shape, isDown) {
if (!isEditing) { if (shouldHover && isDown) {
return; if (editingShapes.findIndex((s) => s.id === shape.id) === -1) {
setEditingShapes((prevShapes) => [...prevShapes, shape]);
} }
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);
}
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 ( return (
<Line <Line
key={shape.id} key={shape.id}
onMouseOver={(e) => handleShapeMouseOver(e, shape)} onMouseMove={() => handleShapeOver(shape, isBrushDown)}
onMouseOut={(e) => handleShapeMouseOut(e, shape)} onTouchOver={() => handleShapeOver(shape, isBrushDown)}
onClick={(e) => handleShapeClick(e, shape)} onMouseDown={() => handleShapeOver(shape, true)}
onTap={(e) => handleShapeClick(e, shape)} onTouchStart={() => handleShapeOver(shape, true)}
points={shape.data.points.reduce( points={shape.data.points.reduce(
(acc, point) => [...acc, point.x * mapWidth, point.y * mapHeight], (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 ( return (
<Group> <Group>
{shapes.map(renderShape)} {shapes.map(renderShape)}
{drawingShape && renderShape(drawingShape)} {drawingShape && renderShape(drawingShape)}
{editingShapes.length > 0 && editingShapes.map(renderEditingShape)}
</Group> </Group>
); );
} }