Separated map drawing and map fog into separate action lists
This commit is contained in:
parent
b34a7df443
commit
5e2c178118
@ -5,6 +5,7 @@ import ProxyToken from "../token/ProxyToken";
|
||||
import TokenMenu from "../token/TokenMenu";
|
||||
import MapToken from "./MapToken";
|
||||
import MapDrawing from "./MapDrawing";
|
||||
import MapFog from "./MapFog";
|
||||
import MapControls from "./MapControls";
|
||||
|
||||
import { omit } from "../../helpers/shared";
|
||||
@ -25,8 +26,9 @@ function Map({
|
||||
onMapChange,
|
||||
onMapStateChange,
|
||||
onMapDraw,
|
||||
onMapDrawUndo,
|
||||
onMapDrawRedo,
|
||||
onFogDraw,
|
||||
onMapUndo,
|
||||
onMapRedo,
|
||||
allowDrawing,
|
||||
allowTokenChange,
|
||||
allowMapChange,
|
||||
@ -71,17 +73,30 @@ function Map({
|
||||
}));
|
||||
}
|
||||
|
||||
const [drawnShapes, setDrawnShapes] = useState([]);
|
||||
function handleShapeAdd(shape) {
|
||||
onMapDraw({ type: "add", shapes: [shape] });
|
||||
const [mapShapes, setMapShapes] = useState([]);
|
||||
function handleMapShapeAdd(shape) {
|
||||
onMapDraw({ type: "add", shapes: [shape], timestamp: Date.now() });
|
||||
}
|
||||
|
||||
function handleShapeRemove(shapeId) {
|
||||
onMapDraw({ type: "remove", shapeIds: [shapeId] });
|
||||
function handleMapShapeRemove(shapeId) {
|
||||
onMapDraw({ type: "remove", shapeIds: [shapeId], timestamp: Date.now() });
|
||||
}
|
||||
|
||||
function handleShapeRemoveAll() {
|
||||
onMapDraw({ type: "remove", shapeIds: drawnShapes.map((s) => s.id) });
|
||||
onMapDraw({
|
||||
type: "remove",
|
||||
shapeIds: mapShapes.map((s) => s.id),
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
}
|
||||
|
||||
const [fogShapes, setFogShapes] = useState([]);
|
||||
function handleFogShapeAdd(shape) {
|
||||
onFogDraw({ type: "add", shapes: [shape], timestamp: Date.now() });
|
||||
}
|
||||
|
||||
function handleFogShapeRemove(shapeId) {
|
||||
onFogDraw({ type: "remove", shapeIds: [shapeId], timestamp: Date.now() });
|
||||
}
|
||||
|
||||
// Replay the draw actions and convert them to shapes for the map drawing
|
||||
@ -89,19 +104,28 @@ function Map({
|
||||
if (!mapState) {
|
||||
return;
|
||||
}
|
||||
let shapesById = {};
|
||||
for (let i = 0; i <= mapState.drawActionIndex; i++) {
|
||||
const action = mapState.drawActions[i];
|
||||
if (action.type === "add") {
|
||||
for (let shape of action.shapes) {
|
||||
shapesById[shape.id] = shape;
|
||||
function actionsToShapes(actions, actionIndex) {
|
||||
let shapesById = {};
|
||||
for (let i = 0; i <= actionIndex; i++) {
|
||||
const action = actions[i];
|
||||
if (action.type === "add") {
|
||||
for (let shape of action.shapes) {
|
||||
shapesById[shape.id] = shape;
|
||||
}
|
||||
}
|
||||
if (action.type === "remove") {
|
||||
shapesById = omit(shapesById, action.shapeIds);
|
||||
}
|
||||
}
|
||||
if (action.type === "remove") {
|
||||
shapesById = omit(shapesById, action.shapeIds);
|
||||
}
|
||||
return Object.values(shapesById);
|
||||
}
|
||||
setDrawnShapes(Object.values(shapesById));
|
||||
|
||||
setMapShapes(
|
||||
actionsToShapes(mapState.mapDrawActions, mapState.mapDrawActionIndex)
|
||||
);
|
||||
setFogShapes(
|
||||
actionsToShapes(mapState.fogDrawActions, mapState.fogDrawActionIndex)
|
||||
);
|
||||
}, [mapState]);
|
||||
|
||||
const disabledControls = [];
|
||||
@ -115,15 +139,15 @@ function Map({
|
||||
disabledControls.push("pan");
|
||||
disabledControls.push("brush");
|
||||
}
|
||||
if (drawnShapes.length === 0) {
|
||||
if (mapShapes.length === 0) {
|
||||
disabledControls.push("erase");
|
||||
}
|
||||
if (!mapState || mapState.drawActionIndex < 0) {
|
||||
if (!mapState || mapState.mapDrawActionIndex < 0) {
|
||||
disabledControls.push("undo");
|
||||
}
|
||||
if (
|
||||
!mapState ||
|
||||
mapState.drawActionIndex === mapState.drawActions.length - 1
|
||||
mapState.mapDrawActionIndex === mapState.mapDrawActions.length - 1
|
||||
) {
|
||||
disabledControls.push("redo");
|
||||
}
|
||||
@ -191,11 +215,24 @@ function Map({
|
||||
<MapDrawing
|
||||
width={map ? map.width : 0}
|
||||
height={map ? map.height : 0}
|
||||
selectedTool={selectedToolId}
|
||||
selectedTool={selectedToolId !== "fog" ? selectedToolId : "none"}
|
||||
toolSettings={toolSettings[selectedToolId]}
|
||||
shapes={drawnShapes}
|
||||
onShapeAdd={handleShapeAdd}
|
||||
onShapeRemove={handleShapeRemove}
|
||||
shapes={mapShapes}
|
||||
onShapeAdd={handleMapShapeAdd}
|
||||
onShapeRemove={handleMapShapeRemove}
|
||||
gridSize={gridSizeNormalized}
|
||||
/>
|
||||
);
|
||||
|
||||
const mapFog = (
|
||||
<MapFog
|
||||
width={map ? map.width : 0}
|
||||
height={map ? map.height : 0}
|
||||
isEditing={selectedToolId === "fog"}
|
||||
toolSettings={toolSettings["fog"]}
|
||||
shapes={fogShapes}
|
||||
onShapeAdd={handleFogShapeAdd}
|
||||
onShapeRemove={handleFogShapeRemove}
|
||||
gridSize={gridSizeNormalized}
|
||||
/>
|
||||
);
|
||||
@ -210,8 +247,8 @@ function Map({
|
||||
toolSettings={toolSettings}
|
||||
onToolSettingChange={handleToolSettingChange}
|
||||
disabledControls={disabledControls}
|
||||
onUndo={onMapDrawUndo}
|
||||
onRedo={onMapDrawRedo}
|
||||
onUndo={onMapUndo}
|
||||
onRedo={onMapRedo}
|
||||
/>
|
||||
);
|
||||
return (
|
||||
@ -224,6 +261,7 @@ function Map({
|
||||
>
|
||||
{map && mapImage}
|
||||
{map && mapDrawing}
|
||||
{map && mapFog}
|
||||
{map && mapTokens}
|
||||
</MapInteraction>
|
||||
{allowTokenChange && (
|
||||
|
@ -10,6 +10,7 @@ import {
|
||||
isShapeHovered,
|
||||
drawShape,
|
||||
simplifyPoints,
|
||||
getRelativePointerPosition,
|
||||
} from "../../helpers/drawing";
|
||||
|
||||
function MapDrawing({
|
||||
@ -29,34 +30,28 @@ function MapDrawing({
|
||||
const [drawingShape, setDrawingShape] = useState(null);
|
||||
const [pointerPosition, setPointerPosition] = useState({ x: -1, y: -1 });
|
||||
|
||||
const shouldHover =
|
||||
selectedTool === "erase" ||
|
||||
(selectedTool === "fog" &&
|
||||
(toolSettings.type === "toggle" || toolSettings.type === "remove"));
|
||||
const shouldHover = selectedTool === "erase";
|
||||
const isEditing =
|
||||
selectedTool === "brush" ||
|
||||
selectedTool === "shape" ||
|
||||
selectedTool === "erase";
|
||||
|
||||
// Reset pointer position when tool changes
|
||||
useEffect(() => {
|
||||
setPointerPosition({ x: -1, y: -1 });
|
||||
}, [selectedTool]);
|
||||
|
||||
function getRelativePointerPosition(event) {
|
||||
const container = containerRef.current;
|
||||
if (container) {
|
||||
const containerRect = container.getBoundingClientRect();
|
||||
const x = (event.clientX - containerRect.x) / containerRect.width;
|
||||
const y = (event.clientY - containerRect.y) / containerRect.height;
|
||||
return { x, y };
|
||||
}
|
||||
}
|
||||
|
||||
function handleStart(event) {
|
||||
if (!isEditing) {
|
||||
return;
|
||||
}
|
||||
if (event.touches && event.touches.length !== 1) {
|
||||
setIsDrawing(false);
|
||||
setDrawingShape(null);
|
||||
return;
|
||||
}
|
||||
const pointer = event.touches ? event.touches[0] : event;
|
||||
const position = getRelativePointerPosition(pointer);
|
||||
const position = getRelativePointerPosition(pointer, containerRef.current);
|
||||
setPointerPosition(position);
|
||||
setIsDrawing(true);
|
||||
const brushPosition = getBrushPositionForTool(
|
||||
@ -67,6 +62,8 @@ function MapDrawing({
|
||||
shapes
|
||||
);
|
||||
const commonShapeData = {
|
||||
color: toolSettings && toolSettings.color,
|
||||
blend: toolSettings && toolSettings.useBlending,
|
||||
id: shortid.generate(),
|
||||
};
|
||||
if (selectedTool === "brush") {
|
||||
@ -75,8 +72,6 @@ function MapDrawing({
|
||||
pathType: toolSettings.type,
|
||||
data: { points: [brushPosition] },
|
||||
strokeWidth: toolSettings.type === "stroke" ? 1 : 0,
|
||||
color: toolSettings && toolSettings.color,
|
||||
blend: toolSettings && toolSettings.useBlending,
|
||||
...commonShapeData,
|
||||
});
|
||||
} else if (selectedTool === "shape") {
|
||||
@ -85,33 +80,32 @@ function MapDrawing({
|
||||
shapeType: toolSettings.type,
|
||||
data: getDefaultShapeData(toolSettings.type, brushPosition),
|
||||
strokeWidth: 0,
|
||||
color: toolSettings && toolSettings.color,
|
||||
blend: toolSettings && toolSettings.useBlending,
|
||||
...commonShapeData,
|
||||
});
|
||||
} else if (selectedTool === "fog" && toolSettings.type === "add") {
|
||||
setDrawingShape({
|
||||
type: "fog",
|
||||
data: { points: [brushPosition] },
|
||||
strokeWidth: 0.1,
|
||||
color: "black",
|
||||
blend: true, // Blend while drawing
|
||||
...commonShapeData,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function handleMove(event) {
|
||||
if (!isEditing) {
|
||||
return;
|
||||
}
|
||||
if (event.touches && event.touches.length !== 1) {
|
||||
return;
|
||||
}
|
||||
const pointer = event.touches ? event.touches[0] : event;
|
||||
const position = getRelativePointerPosition(pointer);
|
||||
// Set pointer position every frame for erase tool and fog
|
||||
if (shouldHover) {
|
||||
const position = getRelativePointerPosition(
|
||||
pointer,
|
||||
containerRef.current
|
||||
);
|
||||
setPointerPosition(position);
|
||||
}
|
||||
if (isDrawing) {
|
||||
const position = getRelativePointerPosition(
|
||||
pointer,
|
||||
containerRef.current
|
||||
);
|
||||
setPointerPosition(position);
|
||||
const brushPosition = getBrushPositionForTool(
|
||||
position,
|
||||
@ -150,28 +144,14 @@ function MapDrawing({
|
||||
brushPosition
|
||||
),
|
||||
}));
|
||||
} else if (selectedTool === "fog" && toolSettings.type === "add") {
|
||||
setDrawingShape((prevShape) => {
|
||||
const prevPoints = prevShape.data.points;
|
||||
if (
|
||||
comparePoints(
|
||||
prevPoints[prevPoints.length - 1],
|
||||
brushPosition,
|
||||
0.001
|
||||
)
|
||||
) {
|
||||
return prevShape;
|
||||
}
|
||||
return {
|
||||
...prevShape,
|
||||
data: { points: [...prevPoints, brushPosition] },
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleStop(event) {
|
||||
if (!isEditing) {
|
||||
return;
|
||||
}
|
||||
if (event.touches && event.touches.length !== 0) {
|
||||
return;
|
||||
}
|
||||
@ -182,15 +162,6 @@ function MapDrawing({
|
||||
}
|
||||
} else if (selectedTool === "shape") {
|
||||
onShapeAdd(drawingShape);
|
||||
} else if (selectedTool === "fog" && toolSettings.type === "add") {
|
||||
if (drawingShape.data.points.length > 1) {
|
||||
const shape = {
|
||||
...drawingShape,
|
||||
data: { points: simplifyPoints(drawingShape.data.points, gridSize) },
|
||||
blend: false,
|
||||
};
|
||||
onShapeAdd(shape);
|
||||
}
|
||||
}
|
||||
|
||||
setDrawingShape(null);
|
||||
@ -237,17 +208,7 @@ function MapDrawing({
|
||||
hoveredShape = shape;
|
||||
}
|
||||
}
|
||||
if (selectedTool === "fog") {
|
||||
drawShape(
|
||||
{ ...shape, blend: true },
|
||||
context,
|
||||
gridSize,
|
||||
width,
|
||||
height
|
||||
);
|
||||
} else {
|
||||
drawShape(shape, context, gridSize, width, height);
|
||||
}
|
||||
drawShape(shape, context, gridSize, width, height);
|
||||
}
|
||||
if (drawingShape) {
|
||||
drawShape(drawingShape, context, gridSize, width, height);
|
||||
@ -267,11 +228,19 @@ function MapDrawing({
|
||||
selectedTool,
|
||||
drawingShape,
|
||||
gridSize,
|
||||
shouldHover,
|
||||
]);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{ position: "absolute", top: 0, left: 0, right: 0, bottom: 0 }}
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
pointerEvents: "none",
|
||||
}}
|
||||
ref={containerRef}
|
||||
>
|
||||
<canvas
|
||||
|
236
src/components/map/MapFog.js
Normal file
236
src/components/map/MapFog.js
Normal file
@ -0,0 +1,236 @@
|
||||
import React, { useRef, useEffect, useState } from "react";
|
||||
import shortid from "shortid";
|
||||
|
||||
import { compare as comparePoints } from "../../helpers/vector2";
|
||||
|
||||
import {
|
||||
getBrushPositionForTool,
|
||||
isShapeHovered,
|
||||
drawShape,
|
||||
simplifyPoints,
|
||||
getRelativePointerPosition,
|
||||
} from "../../helpers/drawing";
|
||||
|
||||
function MapFog({
|
||||
width,
|
||||
height,
|
||||
isEditing,
|
||||
toolSettings,
|
||||
shapes,
|
||||
onShapeAdd,
|
||||
onShapeRemove,
|
||||
gridSize,
|
||||
}) {
|
||||
const canvasRef = useRef();
|
||||
const containerRef = useRef();
|
||||
|
||||
const [isDrawing, setIsDrawing] = useState(false);
|
||||
const [drawingShape, setDrawingShape] = useState(null);
|
||||
const [pointerPosition, setPointerPosition] = useState({ x: -1, y: -1 });
|
||||
|
||||
const shouldHover =
|
||||
isEditing &&
|
||||
(toolSettings.type === "toggle" || toolSettings.type === "remove");
|
||||
|
||||
// Reset pointer position when tool changes
|
||||
useEffect(() => {
|
||||
setPointerPosition({ x: -1, y: -1 });
|
||||
}, [isEditing, toolSettings]);
|
||||
|
||||
function handleStart(event) {
|
||||
if (!isEditing) {
|
||||
return;
|
||||
}
|
||||
if (event.touches && event.touches.length !== 1) {
|
||||
setIsDrawing(false);
|
||||
setDrawingShape(null);
|
||||
return;
|
||||
}
|
||||
const pointer = event.touches ? event.touches[0] : event;
|
||||
const position = getRelativePointerPosition(pointer, containerRef.current);
|
||||
setPointerPosition(position);
|
||||
setIsDrawing(true);
|
||||
const brushPosition = getBrushPositionForTool(
|
||||
position,
|
||||
"fog",
|
||||
toolSettings,
|
||||
gridSize,
|
||||
shapes
|
||||
);
|
||||
const commonShapeData = {
|
||||
id: shortid.generate(),
|
||||
};
|
||||
if (isEditing && toolSettings.type === "add") {
|
||||
setDrawingShape({
|
||||
type: "fog",
|
||||
data: { points: [brushPosition] },
|
||||
strokeWidth: 0.1,
|
||||
color: "black",
|
||||
blend: true, // Blend while drawing
|
||||
...commonShapeData,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function handleMove(event) {
|
||||
if (!isEditing) {
|
||||
return;
|
||||
}
|
||||
if (event.touches && event.touches.length !== 1) {
|
||||
return;
|
||||
}
|
||||
const pointer = event.touches ? event.touches[0] : event;
|
||||
const position = getRelativePointerPosition(pointer, containerRef.current);
|
||||
// Set pointer position every frame for erase tool and fog
|
||||
if (shouldHover) {
|
||||
setPointerPosition(position);
|
||||
}
|
||||
if (isDrawing) {
|
||||
setPointerPosition(position);
|
||||
const brushPosition = getBrushPositionForTool(
|
||||
position,
|
||||
"fog",
|
||||
toolSettings,
|
||||
gridSize,
|
||||
shapes
|
||||
);
|
||||
if (isEditing && toolSettings.type === "add" && drawingShape) {
|
||||
setDrawingShape((prevShape) => {
|
||||
const prevPoints = prevShape.data.points;
|
||||
if (
|
||||
comparePoints(
|
||||
prevPoints[prevPoints.length - 1],
|
||||
brushPosition,
|
||||
0.001
|
||||
)
|
||||
) {
|
||||
return prevShape;
|
||||
}
|
||||
return {
|
||||
...prevShape,
|
||||
data: { points: [...prevPoints, brushPosition] },
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleStop(event) {
|
||||
if (!isEditing) {
|
||||
return;
|
||||
}
|
||||
if (event.touches && event.touches.length !== 0) {
|
||||
return;
|
||||
}
|
||||
setIsDrawing(false);
|
||||
if (isEditing && toolSettings.type === "add" && drawingShape) {
|
||||
if (drawingShape.data.points.length > 1) {
|
||||
const shape = {
|
||||
...drawingShape,
|
||||
data: { points: simplifyPoints(drawingShape.data.points, gridSize) },
|
||||
blend: false,
|
||||
};
|
||||
onShapeAdd(shape);
|
||||
}
|
||||
}
|
||||
|
||||
setDrawingShape(null);
|
||||
if (toolSettings.type === "remove" && hoveredShapeRef.current) {
|
||||
onShapeRemove(hoveredShapeRef.current.id);
|
||||
}
|
||||
}
|
||||
|
||||
// Add listeners for draw events on map to allow drawing past the bounds
|
||||
// of the container
|
||||
useEffect(() => {
|
||||
const map = document.querySelector(".map");
|
||||
map.addEventListener("mousedown", handleStart);
|
||||
map.addEventListener("mousemove", handleMove);
|
||||
map.addEventListener("mouseup", handleStop);
|
||||
map.addEventListener("touchstart", handleStart);
|
||||
map.addEventListener("touchmove", handleMove);
|
||||
map.addEventListener("touchend", handleStop);
|
||||
|
||||
return () => {
|
||||
map.removeEventListener("mousedown", handleStart);
|
||||
map.removeEventListener("mousemove", handleMove);
|
||||
map.removeEventListener("mouseup", handleStop);
|
||||
map.removeEventListener("touchstart", handleStart);
|
||||
map.removeEventListener("touchmove", handleMove);
|
||||
map.removeEventListener("touchend", handleStop);
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Rendering
|
||||
*/
|
||||
const hoveredShapeRef = useRef(null);
|
||||
useEffect(() => {
|
||||
const canvas = canvasRef.current;
|
||||
if (canvas) {
|
||||
const context = canvas.getContext("2d");
|
||||
|
||||
context.clearRect(0, 0, width, height);
|
||||
let hoveredShape = null;
|
||||
for (let shape of shapes) {
|
||||
if (shouldHover) {
|
||||
if (isShapeHovered(shape, context, pointerPosition, width, height)) {
|
||||
hoveredShape = shape;
|
||||
}
|
||||
}
|
||||
if (isEditing) {
|
||||
drawShape(
|
||||
{ ...shape, blend: true },
|
||||
context,
|
||||
gridSize,
|
||||
width,
|
||||
height
|
||||
);
|
||||
} else {
|
||||
drawShape(shape, context, gridSize, width, height);
|
||||
}
|
||||
}
|
||||
if (drawingShape) {
|
||||
drawShape(drawingShape, context, gridSize, width, height);
|
||||
}
|
||||
if (hoveredShape) {
|
||||
const shape = { ...hoveredShape, color: "#BB99FF", blend: true };
|
||||
drawShape(shape, context, gridSize, width, height);
|
||||
}
|
||||
hoveredShapeRef.current = hoveredShape;
|
||||
}
|
||||
}, [
|
||||
shapes,
|
||||
width,
|
||||
height,
|
||||
pointerPosition,
|
||||
isDrawing,
|
||||
isEditing,
|
||||
drawingShape,
|
||||
gridSize,
|
||||
shouldHover,
|
||||
]);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
pointerEvents: "none",
|
||||
}}
|
||||
ref={containerRef}
|
||||
>
|
||||
<canvas
|
||||
ref={canvasRef}
|
||||
width={width}
|
||||
height={height}
|
||||
style={{ width: "100%", height: "100%" }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default MapFog;
|
@ -23,7 +23,8 @@ function MapTile({
|
||||
const hasMapState =
|
||||
mapState &&
|
||||
(Object.values(mapState.tokens).length > 0 ||
|
||||
mapState.drawActions.length > 0);
|
||||
mapState.mapDrawActions.length > 0 ||
|
||||
mapState.fogDrawActions.length > 0);
|
||||
|
||||
const expandButton = (
|
||||
<IconButton
|
||||
|
@ -308,3 +308,12 @@ const defaultSimplifySize = 1 / 100;
|
||||
export function simplifyPoints(points, gridSize) {
|
||||
return simplify(points, Vector2.min(gridSize) * defaultSimplifySize);
|
||||
}
|
||||
|
||||
export function getRelativePointerPosition(event, container) {
|
||||
if (container) {
|
||||
const containerRect = container.getBoundingClientRect();
|
||||
const x = (event.clientX - containerRect.x) / containerRect.width;
|
||||
const y = (event.clientY - containerRect.y) / containerRect.height;
|
||||
return { x, y };
|
||||
}
|
||||
}
|
||||
|
@ -19,8 +19,10 @@ const defaultMapState = {
|
||||
tokens: {},
|
||||
// An index into the draw actions array to which only actions before the
|
||||
// index will be performed (used in undo and redo)
|
||||
drawActionIndex: -1,
|
||||
drawActions: [],
|
||||
mapDrawActionIndex: -1,
|
||||
mapDrawActions: [],
|
||||
fogDrawActionIndex: -1,
|
||||
fogDrawActions: [],
|
||||
// Flags to determine what other people can edit
|
||||
editFlags: ["map", "drawings", "tokens"],
|
||||
};
|
||||
|
@ -122,14 +122,17 @@ function Game() {
|
||||
function addNewMapDrawActions(actions) {
|
||||
setMapState((prevMapState) => {
|
||||
const newActions = [
|
||||
...prevMapState.drawActions.slice(0, prevMapState.drawActionIndex + 1),
|
||||
...prevMapState.mapDrawActions.slice(
|
||||
0,
|
||||
prevMapState.mapDrawActionIndex + 1
|
||||
),
|
||||
...actions,
|
||||
];
|
||||
const newIndex = newActions.length - 1;
|
||||
return {
|
||||
...prevMapState,
|
||||
drawActions: newActions,
|
||||
drawActionIndex: newIndex,
|
||||
mapDrawActions: newActions,
|
||||
mapDrawActionIndex: newIndex,
|
||||
};
|
||||
});
|
||||
}
|
||||
@ -141,31 +144,57 @@ function Game() {
|
||||
}
|
||||
}
|
||||
|
||||
function handleMapDrawUndo() {
|
||||
const newIndex = Math.max(mapState.drawActionIndex - 1, -1);
|
||||
function handleMapUndo() {
|
||||
// TODO: Check whether to pull from draw actions or fog actions
|
||||
const newIndex = Math.max(mapState.mapDrawActionIndex - 1, -1);
|
||||
setMapState((prevMapState) => ({
|
||||
...prevMapState,
|
||||
drawActionIndex: newIndex,
|
||||
mapDrawActionIndex: newIndex,
|
||||
}));
|
||||
for (let peer of Object.values(peers)) {
|
||||
peer.connection.send({ id: "mapDrawIndex", data: newIndex });
|
||||
}
|
||||
}
|
||||
|
||||
function handleMapDrawRedo() {
|
||||
function handleMapRedo() {
|
||||
const newIndex = Math.min(
|
||||
mapState.drawActionIndex + 1,
|
||||
mapState.drawActions.length - 1
|
||||
mapState.mapDrawActionIndex + 1,
|
||||
mapState.mapDrawActions.length - 1
|
||||
);
|
||||
setMapState((prevMapState) => ({
|
||||
...prevMapState,
|
||||
drawActionIndex: newIndex,
|
||||
mapDrawActionIndex: newIndex,
|
||||
}));
|
||||
for (let peer of Object.values(peers)) {
|
||||
peer.connection.send({ id: "mapDrawIndex", data: newIndex });
|
||||
}
|
||||
}
|
||||
|
||||
function addNewFogDrawActions(actions) {
|
||||
setMapState((prevMapState) => {
|
||||
const newActions = [
|
||||
...prevMapState.fogDrawActions.slice(
|
||||
0,
|
||||
prevMapState.fogDrawActionIndex + 1
|
||||
),
|
||||
...actions,
|
||||
];
|
||||
const newIndex = newActions.length - 1;
|
||||
return {
|
||||
...prevMapState,
|
||||
fogDrawActions: newActions,
|
||||
fogDrawActionIndex: newIndex,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function handleFogDraw(action) {
|
||||
addNewFogDrawActions([action]);
|
||||
for (let peer of Object.values(peers)) {
|
||||
peer.connection.send({ id: "mapFog", data: [action] });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Party state
|
||||
*/
|
||||
@ -238,7 +267,16 @@ function Game() {
|
||||
if (data.id === "mapDrawIndex") {
|
||||
setMapState((prevMapState) => ({
|
||||
...prevMapState,
|
||||
drawActionIndex: data.data,
|
||||
mapDrawActionIndex: data.data,
|
||||
}));
|
||||
}
|
||||
if (data.id === "mapFog") {
|
||||
addNewFogDrawActions(data.data);
|
||||
}
|
||||
if (data.id === "mapFogIndex") {
|
||||
setMapState((prevMapState) => ({
|
||||
...prevMapState,
|
||||
fogDrawActionIndex: data.data,
|
||||
}));
|
||||
}
|
||||
}
|
||||
@ -375,8 +413,9 @@ function Game() {
|
||||
onMapChange={handleMapChange}
|
||||
onMapStateChange={handleMapStateChange}
|
||||
onMapDraw={handleMapDraw}
|
||||
onMapDrawUndo={handleMapDrawUndo}
|
||||
onMapDrawRedo={handleMapDrawRedo}
|
||||
onMapUndo={handleMapUndo}
|
||||
onMapRedo={handleMapRedo}
|
||||
onFogDraw={handleFogDraw}
|
||||
allowDrawing={canEditMapDrawings}
|
||||
allowTokenChange={canEditTokens}
|
||||
allowMapChange={canChangeMap}
|
||||
|
Loading…
Reference in New Issue
Block a user