Added fog subtraction tool
This commit is contained in:
parent
7cc0e6cee0
commit
9eaece24e5
@ -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",
|
||||
|
@ -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}
|
||||
|
@ -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,
|
||||
|
@ -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" })}
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
18
src/icons/FogSubtractIcon.js
Normal file
18
src/icons/FogSubtractIcon.js
Normal 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;
|
12
yarn.lock
12
yarn.lock
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user