Added UI element to allow accepting fog polygon editing
This commit is contained in:
parent
f85b379b15
commit
2f740efd7c
@ -1,4 +1,4 @@
|
|||||||
import React, { useContext, useState, useEffect } from "react";
|
import React, { useContext, useState, useEffect, useCallback } from "react";
|
||||||
import shortid from "shortid";
|
import shortid from "shortid";
|
||||||
import { Group } from "react-konva";
|
import { Group } from "react-konva";
|
||||||
import useImage from "use-image";
|
import useImage from "use-image";
|
||||||
@ -18,6 +18,7 @@ import colors from "../../helpers/colors";
|
|||||||
import {
|
import {
|
||||||
HoleyLine,
|
HoleyLine,
|
||||||
getRelativePointerPositionNormalized,
|
getRelativePointerPositionNormalized,
|
||||||
|
Tick,
|
||||||
} from "../../helpers/konva";
|
} from "../../helpers/konva";
|
||||||
|
|
||||||
function MapFog({
|
function MapFog({
|
||||||
@ -191,45 +192,14 @@ function MapFog({
|
|||||||
setIsBrushDown(false);
|
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("mousedown", handleBrushDown);
|
||||||
mapStage.on("mousemove", handleBrushMove);
|
mapStage.on("mousemove", handleBrushMove);
|
||||||
mapStage.on("mouseup", handleBrushUp);
|
mapStage.on("mouseup", handleBrushUp);
|
||||||
mapStage.container().addEventListener("keydown", handleKeyDown);
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
mapStage.off("mousedown", handleBrushDown);
|
mapStage.off("mousedown", handleBrushDown);
|
||||||
mapStage.off("mousemove", handleBrushMove);
|
mapStage.off("mousemove", handleBrushMove);
|
||||||
mapStage.off("mouseup", handleBrushUp);
|
mapStage.off("mouseup", handleBrushUp);
|
||||||
mapStage.container().removeEventListener("keydown", handleKeyDown);
|
|
||||||
};
|
};
|
||||||
}, [
|
}, [
|
||||||
mapStageRef,
|
mapStageRef,
|
||||||
@ -248,6 +218,49 @@ function MapFog({
|
|||||||
stageScale,
|
stageScale,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const finishDrawingPolygon = useCallback(() => {
|
||||||
|
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);
|
||||||
|
}, [selectedToolSettings, drawingShape, onShapeSubtract, onShapeAdd]);
|
||||||
|
|
||||||
|
// Add keyboard shortcuts
|
||||||
|
useEffect(() => {
|
||||||
|
const mapStage = mapStageRef.current;
|
||||||
|
|
||||||
|
function handleKeyDown(event) {
|
||||||
|
if (
|
||||||
|
event.key === "Enter" &&
|
||||||
|
selectedToolSettings.type === "polygon" &&
|
||||||
|
drawingShape
|
||||||
|
) {
|
||||||
|
finishDrawingPolygon();
|
||||||
|
}
|
||||||
|
if (event.key === "Escape" && drawingShape) {
|
||||||
|
setDrawingShape(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mapStage.container().addEventListener("keydown", handleKeyDown);
|
||||||
|
return () => {
|
||||||
|
mapStage.container().removeEventListener("keydown", handleKeyDown);
|
||||||
|
};
|
||||||
|
}, [finishDrawingPolygon, mapStageRef, drawingShape, selectedToolSettings]);
|
||||||
|
|
||||||
function handleShapeOver(shape, isDown) {
|
function handleShapeOver(shape, isDown) {
|
||||||
if (shouldHover && isDown) {
|
if (shouldHover && isDown) {
|
||||||
if (editingShapes.findIndex((s) => s.id === shape.id) === -1) {
|
if (editingShapes.findIndex((s) => s.id === shape.id) === -1) {
|
||||||
@ -300,10 +313,35 @@ function MapFog({
|
|||||||
return renderShape(editingShape);
|
return renderShape(editingShape);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderPolygonAcceptTick(shape) {
|
||||||
|
if (shape.data.points.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Tick
|
||||||
|
x={shape.data.points[0].x * mapWidth}
|
||||||
|
y={shape.data.points[0].y * mapHeight}
|
||||||
|
scale={1 / stageScale}
|
||||||
|
cross={shape.data.points.length < 4}
|
||||||
|
onClick={() => {
|
||||||
|
// Check that there is enough points after clicking
|
||||||
|
if (shape.data.points.length < 5) {
|
||||||
|
setDrawingShape(null);
|
||||||
|
} else {
|
||||||
|
finishDrawingPolygon();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Group>
|
<Group>
|
||||||
{shapes.map(renderShape)}
|
{shapes.map(renderShape)}
|
||||||
{drawingShape && renderShape(drawingShape)}
|
{drawingShape && renderShape(drawingShape)}
|
||||||
|
{drawingShape &&
|
||||||
|
selectedToolSettings.type === "polygon" &&
|
||||||
|
renderPolygonAcceptTick(drawingShape)}
|
||||||
{editingShapes.length > 0 && editingShapes.map(renderEditingShape)}
|
{editingShapes.length > 0 && editingShapes.map(renderEditingShape)}
|
||||||
</Group>
|
</Group>
|
||||||
);
|
);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React from "react";
|
import React, { useState } from "react";
|
||||||
import { Line } from "react-konva";
|
import { Line, Group, Path, Circle } from "react-konva";
|
||||||
|
|
||||||
// Holes should be wound in the opposite direction as the containing points array
|
// Holes should be wound in the opposite direction as the containing points array
|
||||||
export function HoleyLine({ holes, ...props }) {
|
export function HoleyLine({ holes, ...props }) {
|
||||||
@ -106,6 +106,40 @@ export function HoleyLine({ holes, ...props }) {
|
|||||||
return <Line sceneFunc={sceneFunc} {...props} />;
|
return <Line sceneFunc={sceneFunc} {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function Tick({ x, y, scale, onClick, cross }) {
|
||||||
|
const [fill, setFill] = useState("white");
|
||||||
|
function handleEnter() {
|
||||||
|
setFill("hsl(260, 100%, 80%)");
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleLeave() {
|
||||||
|
setFill("white");
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Group
|
||||||
|
x={x}
|
||||||
|
y={y}
|
||||||
|
scaleX={scale}
|
||||||
|
scaleY={scale}
|
||||||
|
onMouseEnter={handleEnter}
|
||||||
|
onMouseLeave={handleLeave}
|
||||||
|
onClick={onClick}
|
||||||
|
>
|
||||||
|
<Circle radius={12} fill="hsla(230, 25%, 18%, 0.8)" />
|
||||||
|
<Path
|
||||||
|
offsetX={12}
|
||||||
|
offsetY={12}
|
||||||
|
fill={fill}
|
||||||
|
data={
|
||||||
|
cross
|
||||||
|
? "M18.3 5.71c-.39-.39-1.02-.39-1.41 0L12 10.59 7.11 5.7c-.39-.39-1.02-.39-1.41 0-.39.39-.39 1.02 0 1.41L10.59 12 5.7 16.89c-.39.39-.39 1.02 0 1.41.39.39 1.02.39 1.41 0L12 13.41l4.89 4.89c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41L13.41 12l4.89-4.89c.38-.38.38-1.02 0-1.4z"
|
||||||
|
: "M9 16.2l-3.5-3.5c-.39-.39-1.01-.39-1.4 0-.39.39-.39 1.01 0 1.4l4.19 4.19c.39.39 1.02.39 1.41 0L20.3 7.7c.39-.39.39-1.01 0-1.4-.39-.39-1.01-.39-1.4 0L9 16.2z"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Group>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function getRelativePointerPosition(node) {
|
export function getRelativePointerPosition(node) {
|
||||||
let transform = node.getAbsoluteTransform().copy();
|
let transform = node.getAbsoluteTransform().copy();
|
||||||
transform.invert();
|
transform.invert();
|
||||||
|
Loading…
Reference in New Issue
Block a user