Added fog subtraction tool

This commit is contained in:
Mitchell McCaffrey 2020-06-09 12:45:52 +10:00
parent 7cc0e6cee0
commit 9eaece24e5
7 changed files with 100 additions and 4 deletions

View File

@ -17,6 +17,7 @@
"interactjs": "^1.9.7",
"konva": "^6.0.0",
"normalize-wheel": "^1.0.1",
"polygon-clipping": "^0.14.3",
"raw.macro": "^0.3.0",
"react": "^16.13.0",
"react-dom": "^16.13.0",

View File

@ -1,4 +1,5 @@
import React, { useState, useContext, useEffect } from "react";
import polygonClipping from "polygon-clipping";
import MapControls from "./MapControls";
import MapInteraction from "./MapInteraction";
@ -108,6 +109,10 @@ function Map({
onFogDraw({ type: "add", shapes: [shape] });
}
function handleFogShapeSubtract(shape) {
onFogDraw({ type: "subtract", shapes: [shape] });
}
function handleFogShapesRemove(shapeIds) {
onFogDraw({ type: "remove", shapeIds });
}
@ -133,6 +138,32 @@ function Map({
if (action.type === "remove") {
shapesById = omit(shapesById, action.shapeIds);
}
if (action.type === "subtract") {
const actionGeom = action.shapes.map((actionShape) => [
actionShape.data.points.map(({ x, y }) => [x, y]),
]);
let subtractedShapes = {};
for (let shape of Object.values(shapesById)) {
let shapeGeom = [[shape.data.points.map(({ x, y }) => [x, y])]];
const difference = polygonClipping.difference(
shapeGeom,
actionGeom
);
for (let i = 0; i < difference.length; i++) {
for (let j = 0; j < difference[i].length; j++) {
let newId = `${shape.id}-${i}_${j}`;
subtractedShapes[newId] = {
...shape,
id: newId,
data: {
points: difference[i][j].map(([x, y]) => ({ x, y })),
},
};
}
}
}
shapesById = subtractedShapes;
}
}
return Object.values(shapesById);
}
@ -287,6 +318,7 @@ function Map({
<MapFog
shapes={fogShapes}
onShapeAdd={handleFogShapeAdd}
onShapeSubtract={handleFogShapeSubtract}
onShapesRemove={handleFogShapesRemove}
onShapesEdit={handleFogShapesEdit}
selectedToolId={selectedToolId}

View File

@ -20,6 +20,7 @@ import useMapBrush from "../../helpers/useMapBrush";
function MapFog({
shapes,
onShapeAdd,
onShapeSubtract,
onShapesRemove,
onShapesEdit,
selectedToolId,
@ -63,12 +64,15 @@ function MapFog({
gridSize,
shapes
);
if (selectedToolSettings.type === "add") {
if (
selectedToolSettings.type === "add" ||
selectedToolSettings.type === "subtract"
) {
setDrawingShape({
type: "fog",
data: { points: [brushPosition] },
strokeWidth: 0.5,
color: "black",
color: selectedToolSettings.type === "add" ? "black" : "red",
blend: false,
id: shortid.generate(),
visible: true,
@ -85,7 +89,10 @@ function MapFog({
gridSize,
shapes
);
if (selectedToolSettings.type === "add") {
if (
selectedToolSettings.type === "add" ||
selectedToolSettings.type === "subtract"
) {
setDrawingShape((prevShape) => {
const prevPoints = prevShape.data.points;
if (
@ -122,6 +129,23 @@ function MapFog({
onShapeAdd(shape);
}
}
if (selectedToolSettings.type === "subtract" && drawingShape) {
if (drawingShape.data.points.length > 1) {
const shape = {
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();
}
@ -146,6 +170,7 @@ function MapFog({
gridSize,
stageScale,
onShapeAdd,
onShapeSubtract,
shapes,
drawingShape,
handleBrushUp,

View File

@ -6,6 +6,7 @@ import RadioIconButton from "./RadioIconButton";
import GridSnappingToggle from "./GridSnappingToggle";
import FogAddIcon from "../../../icons/FogAddIcon";
import FogSubtractIcon from "../../../icons/FogSubtractIcon";
import FogRemoveIcon from "../../../icons/FogRemoveIcon";
import FogToggleIcon from "../../../icons/FogToggleIcon";
@ -29,6 +30,13 @@ function BrushToolSettings({
>
<FogAddIcon />
</RadioIconButton>
<RadioIconButton
title="Subtract Fog"
onClick={() => onSettingChange({ type: "subtract" })}
isSelected={settings.type === "subtract"}
>
<FogSubtractIcon />
</RadioIconButton>
<RadioIconButton
title="Remove Fog"
onClick={() => onSettingChange({ type: "remove" })}

View File

@ -10,7 +10,7 @@ function FogRemoveIcon() {
fill="currentcolor"
>
<path d="M0 0h24v24H0z" fill="none" />
<path d="M12 4a7.49 7.49 0 017.35 6.04c2.6.18 4.65 2.32 4.65 4.96 0 2.76-2.24 5-5 5H6c-3.31 0-6-2.69-6-6 0-3.09 2.34-5.64 5.35-5.96A7.496 7.496 0 0112 4zm4 8H8c-.55 0-1 .45-1 1s.45 1 1 1h8c.55 0 1-.45 1-1s-.45-1-1-1z" />
<path d="M19.35 10.04A7.49 7.49 0 0012 4C9.11 4 6.6 5.64 5.35 8.04A5.994 5.994 0 000 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zm-3.814.839L13.414 13l2.122 2.121a1.003 1.003 0 010 1.415 1.003 1.003 0 01-1.415 0L12 14.414l-2.121 2.122a1.003 1.003 0 01-1.415 0 1.003 1.003 0 010-1.415L10.586 13l-2.122-2.121a1.003 1.003 0 010-1.415 1.003 1.003 0 011.415 0L12 11.586l2.121-2.122a1.003 1.003 0 011.415 0 1.003 1.003 0 010 1.415z" />
</svg>
);
}

View File

@ -0,0 +1,18 @@
import React from "react";
function FogRemoveIcon() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
height="24"
viewBox="0 0 24 24"
width="24"
fill="currentcolor"
>
<path d="M0 0h24v24H0z" fill="none" />
<path d="M12 4a7.49 7.49 0 017.35 6.04c2.6.18 4.65 2.32 4.65 4.96 0 2.76-2.24 5-5 5H6c-3.31 0-6-2.69-6-6 0-3.09 2.34-5.64 5.35-5.96A7.496 7.496 0 0112 4zm4 8H8c-.55 0-1 .45-1 1s.45 1 1 1h8c.55 0 1-.45 1-1s-.45-1-1-1z" />
</svg>
);
}
export default FogRemoveIcon;

View File

@ -8251,6 +8251,13 @@ pnp-webpack-plugin@1.6.0:
dependencies:
ts-pnp "^1.1.2"
polygon-clipping@^0.14.3:
version "0.14.3"
resolved "https://registry.yarnpkg.com/polygon-clipping/-/polygon-clipping-0.14.3.tgz#02affe4e2aaee69f686ea9dcd5f9566dd4c941af"
integrity sha512-bIaMFYIsHOShMN0JZsvkfk66S7gKMQMlYUpV7LIx+WOBYvJT09eCgoAv2JCDNj6SofA4+o5tlmV76zzUiG4aBQ==
dependencies:
splaytree "^3.0.1"
portfinder@^1.0.25:
version "1.0.25"
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.25.tgz#254fd337ffba869f4b9d37edc298059cb4d35eca"
@ -10433,6 +10440,11 @@ spdy@^4.0.1:
select-hose "^2.0.0"
spdy-transport "^3.0.0"
splaytree@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/splaytree/-/splaytree-3.0.1.tgz#038d8e6d597a3a1893e8e82693a0f4413b3559f7"
integrity sha512-WvQIHRDXLSVn72xjlIG/WGhv/4QO3m+iY2TpVdFRaXd1+/vkNlpkpw1QaNH5taghF9eWXDHWMWnzXyicR8d6ig==
split-string@^3.0.1, split-string@^3.0.2:
version "3.1.0"
resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2"