Added fog polygon tool and changed fog interaction method
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React, { useContext, useState, useCallback } from "react";
|
||||
import React, { useContext, useState, useEffect } from "react";
|
||||
import shortid from "shortid";
|
||||
import { Group } from "react-konva";
|
||||
import useImage from "use-image";
|
||||
@@ -6,6 +6,7 @@ import useImage from "use-image";
|
||||
import diagonalPattern from "../../images/DiagonalPattern.png";
|
||||
|
||||
import MapInteractionContext from "../../contexts/MapInteractionContext";
|
||||
import MapStageContext from "../../contexts/MapStageContext";
|
||||
|
||||
import { compare as comparePoints } from "../../helpers/vector2";
|
||||
import {
|
||||
@@ -14,8 +15,10 @@ import {
|
||||
getStrokeWidth,
|
||||
} from "../../helpers/drawing";
|
||||
import colors from "../../helpers/colors";
|
||||
import useMapBrush from "../../helpers/useMapBrush";
|
||||
import { HoleyLine } from "../../helpers/konva";
|
||||
import {
|
||||
HoleyLine,
|
||||
getRelativePointerPositionNormalized,
|
||||
} from "../../helpers/konva";
|
||||
|
||||
function MapFog({
|
||||
shapes,
|
||||
@@ -28,6 +31,7 @@ function MapFog({
|
||||
gridSize,
|
||||
}) {
|
||||
const { stageScale, mapWidth, mapHeight } = useContext(MapInteractionContext);
|
||||
const mapStageRef = useContext(MapStageContext);
|
||||
const [drawingShape, setDrawingShape] = useState(null);
|
||||
const [isBrushDown, setIsBrushDown] = useState(false);
|
||||
const [editingShapes, setEditingShapes] = useState([]);
|
||||
@@ -40,149 +44,209 @@ 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([]);
|
||||
useEffect(() => {
|
||||
if (!isEditing) {
|
||||
return;
|
||||
}
|
||||
}, [editingShapes, onShapesRemove, onShapesEdit, selectedToolSettings]);
|
||||
|
||||
const handleShapeDraw = useCallback(
|
||||
(brushState, mapBrushPosition) => {
|
||||
function startShape() {
|
||||
const brushPosition = getBrushPositionForTool(
|
||||
mapBrushPosition,
|
||||
selectedToolId,
|
||||
selectedToolSettings,
|
||||
gridSize,
|
||||
shapes
|
||||
);
|
||||
if (
|
||||
selectedToolSettings.type === "add" ||
|
||||
selectedToolSettings.type === "subtract"
|
||||
) {
|
||||
setDrawingShape({
|
||||
type: "fog",
|
||||
data: { points: [brushPosition], holes: [] },
|
||||
strokeWidth: 0.5,
|
||||
color: selectedToolSettings.type === "add" ? "black" : "red",
|
||||
blend: false,
|
||||
id: shortid.generate(),
|
||||
visible: true,
|
||||
});
|
||||
}
|
||||
setIsBrushDown(true);
|
||||
const mapStage = mapStageRef.current;
|
||||
|
||||
function getBrushPosition() {
|
||||
const mapImage = mapStage.findOne("#mapImage");
|
||||
return getBrushPositionForTool(
|
||||
getRelativePointerPositionNormalized(mapImage),
|
||||
selectedToolId,
|
||||
selectedToolSettings,
|
||||
gridSize,
|
||||
shapes
|
||||
);
|
||||
}
|
||||
|
||||
function handleBrushDown() {
|
||||
const brushPosition = getBrushPosition();
|
||||
if (selectedToolSettings.type === "brush") {
|
||||
setDrawingShape({
|
||||
type: "fog",
|
||||
data: {
|
||||
points: [brushPosition],
|
||||
holes: [],
|
||||
},
|
||||
strokeWidth: 0.5,
|
||||
color: selectedToolSettings.useFogSubtract ? "red" : "black",
|
||||
blend: false,
|
||||
id: shortid.generate(),
|
||||
visible: true,
|
||||
});
|
||||
}
|
||||
setIsBrushDown(true);
|
||||
}
|
||||
|
||||
function continueShape() {
|
||||
const brushPosition = getBrushPositionForTool(
|
||||
mapBrushPosition,
|
||||
selectedToolId,
|
||||
selectedToolSettings,
|
||||
gridSize,
|
||||
shapes
|
||||
);
|
||||
if (
|
||||
selectedToolSettings.type === "add" ||
|
||||
selectedToolSettings.type === "subtract"
|
||||
) {
|
||||
setDrawingShape((prevShape) => {
|
||||
const prevPoints = prevShape.data.points;
|
||||
if (
|
||||
comparePoints(
|
||||
prevPoints[prevPoints.length - 1],
|
||||
brushPosition,
|
||||
0.001
|
||||
)
|
||||
) {
|
||||
return prevShape;
|
||||
}
|
||||
return {
|
||||
...prevShape,
|
||||
data: {
|
||||
...prevShape.data,
|
||||
points: [...prevPoints, brushPosition],
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
function handleBrushMove() {
|
||||
if (
|
||||
selectedToolSettings.type === "brush" &&
|
||||
isBrushDown &&
|
||||
drawingShape
|
||||
) {
|
||||
const brushPosition = getBrushPosition();
|
||||
setDrawingShape((prevShape) => {
|
||||
const prevPoints = prevShape.data.points;
|
||||
if (
|
||||
comparePoints(
|
||||
prevPoints[prevPoints.length - 1],
|
||||
brushPosition,
|
||||
0.001
|
||||
)
|
||||
) {
|
||||
return prevShape;
|
||||
}
|
||||
return {
|
||||
...prevShape,
|
||||
data: {
|
||||
...prevShape.data,
|
||||
points: [...prevPoints, brushPosition],
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
if (selectedToolSettings.type === "polygon" && drawingShape) {
|
||||
const brushPosition = getBrushPosition();
|
||||
setDrawingShape((prevShape) => {
|
||||
return {
|
||||
...prevShape,
|
||||
data: {
|
||||
...prevShape.data,
|
||||
points: [...prevShape.data.points.slice(0, -1), brushPosition],
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function endShape() {
|
||||
if (selectedToolSettings.type === "add" && drawingShape) {
|
||||
if (drawingShape.data.points.length > 1) {
|
||||
const shape = {
|
||||
...drawingShape,
|
||||
data: {
|
||||
...drawingShape.data,
|
||||
points: simplifyPoints(
|
||||
drawingShape.data.points,
|
||||
gridSize,
|
||||
// Downscale fog as smoothing doesn't currently work with edge snapping
|
||||
stageScale / 2
|
||||
),
|
||||
},
|
||||
};
|
||||
function handleBrushUp() {
|
||||
if (selectedToolSettings.type === "brush" && drawingShape) {
|
||||
const subtract = selectedToolSettings.useFogSubtract;
|
||||
|
||||
if (drawingShape.data.points.length > 1) {
|
||||
let shapeData = {};
|
||||
if (subtract) {
|
||||
shapeData = { id: drawingShape.id, type: drawingShape.type };
|
||||
} else {
|
||||
shapeData = drawingShape;
|
||||
}
|
||||
const shape = {
|
||||
...shapeData,
|
||||
data: {
|
||||
...drawingShape.data,
|
||||
points: simplifyPoints(
|
||||
drawingShape.data.points,
|
||||
gridSize,
|
||||
// Downscale fog as smoothing doesn't currently work with edge snapping
|
||||
stageScale / 2
|
||||
),
|
||||
},
|
||||
};
|
||||
if (subtract) {
|
||||
onShapeSubtract(shape);
|
||||
} else {
|
||||
onShapeAdd(shape);
|
||||
}
|
||||
}
|
||||
if (selectedToolSettings.type === "subtract" && drawingShape) {
|
||||
if (drawingShape.data.points.length > 1) {
|
||||
const shape = {
|
||||
data: {
|
||||
...drawingShape.data,
|
||||
points: simplifyPoints(
|
||||
drawingShape.data.points,
|
||||
gridSize,
|
||||
// Downscale fog as smoothing doesn't currently work with edge snapping
|
||||
stageScale / 2
|
||||
),
|
||||
},
|
||||
id: drawingShape.id,
|
||||
type: drawingShape.type,
|
||||
};
|
||||
onShapeSubtract(shape);
|
||||
}
|
||||
}
|
||||
|
||||
setDrawingShape(null);
|
||||
handleBrushUp();
|
||||
}
|
||||
|
||||
switch (brushState) {
|
||||
case "first":
|
||||
startShape();
|
||||
return;
|
||||
case "drawing":
|
||||
continueShape();
|
||||
return;
|
||||
case "last":
|
||||
endShape();
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
if (selectedToolSettings.type === "polygon") {
|
||||
const brushPosition = getBrushPosition();
|
||||
setDrawingShape({
|
||||
type: "fog",
|
||||
data: {
|
||||
points: [
|
||||
...(drawingShape ? drawingShape.data.points : [brushPosition]),
|
||||
brushPosition,
|
||||
],
|
||||
holes: [],
|
||||
},
|
||||
strokeWidth: 0.5,
|
||||
color: selectedToolSettings.useFogSubtract ? "red" : "black",
|
||||
blend: false,
|
||||
id: shortid.generate(),
|
||||
visible: true,
|
||||
});
|
||||
}
|
||||
},
|
||||
[
|
||||
selectedToolId,
|
||||
selectedToolSettings,
|
||||
gridSize,
|
||||
stageScale,
|
||||
onShapeAdd,
|
||||
onShapeSubtract,
|
||||
shapes,
|
||||
drawingShape,
|
||||
handleBrushUp,
|
||||
]
|
||||
);
|
||||
|
||||
useMapBrush(isEditing, handleShapeDraw);
|
||||
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([]);
|
||||
}
|
||||
|
||||
setIsBrushDown(false);
|
||||
}
|
||||
|
||||
function handleKeyDown(event) {
|
||||
if (
|
||||
event.key === "Enter" &&
|
||||
selectedToolSettings.type === "polygon" &&
|
||||
drawingShape
|
||||
) {
|
||||
const subtract = selectedToolSettings.useFogSubtract;
|
||||
const data = {
|
||||
...drawingShape.data,
|
||||
// Remove the last point as it hasn't been placed yet
|
||||
points: drawingShape.data.points.slice(0, -1),
|
||||
};
|
||||
if (subtract) {
|
||||
onShapeSubtract({
|
||||
id: drawingShape.id,
|
||||
type: drawingShape.type,
|
||||
data: data,
|
||||
});
|
||||
} else {
|
||||
onShapeAdd({ ...drawingShape, data: data });
|
||||
}
|
||||
|
||||
setDrawingShape(null);
|
||||
}
|
||||
if (event.key === "Escape" && drawingShape) {
|
||||
setDrawingShape(null);
|
||||
}
|
||||
}
|
||||
|
||||
mapStage.on("mousedown", handleBrushDown);
|
||||
mapStage.on("mousemove", handleBrushMove);
|
||||
mapStage.on("mouseup", handleBrushUp);
|
||||
mapStage.container().addEventListener("keydown", handleKeyDown);
|
||||
|
||||
return () => {
|
||||
mapStage.off("mousedown", handleBrushDown);
|
||||
mapStage.off("mousemove", handleBrushMove);
|
||||
mapStage.off("mouseup", handleBrushUp);
|
||||
mapStage.container().removeEventListener("keydown", handleKeyDown);
|
||||
};
|
||||
}, [
|
||||
mapStageRef,
|
||||
isEditing,
|
||||
drawingShape,
|
||||
editingShapes,
|
||||
gridSize,
|
||||
isBrushDown,
|
||||
onShapeAdd,
|
||||
onShapeSubtract,
|
||||
onShapesEdit,
|
||||
onShapesRemove,
|
||||
selectedToolId,
|
||||
selectedToolSettings,
|
||||
shapes,
|
||||
stageScale,
|
||||
]);
|
||||
|
||||
function handleShapeOver(shape, isDown) {
|
||||
if (shouldHover && isDown) {
|
||||
|
||||
Reference in New Issue
Block a user