Files
grungnet/src/components/map/Map.tsx

244 lines
6.7 KiB
TypeScript
Raw Normal View History

2021-07-17 12:48:04 +10:00
import { useState } from "react";
2021-05-06 15:04:53 +10:00
import { Box } from "theme-ui";
import { useToasts } from "react-toast-notifications";
import MapControls from "./MapControls";
import MapInteraction from "./MapInteraction";
2020-05-31 16:25:05 +10:00
import MapGrid from "./MapGrid";
import DrawingTool from "../tools/DrawingTool";
import FogTool from "../tools/FogTool";
import MeasureTool from "../tools/MeasureTool";
2020-07-28 17:59:26 +10:00
import NetworkedMapPointer from "../../network/NetworkedMapPointer";
2020-03-20 13:33:12 +11:00
import { useSettings } from "../../contexts/SettingsContext";
import { useUserId } from "../../contexts/UserIdContext";
import Action from "../../actions/Action";
import {
2021-07-16 14:55:33 +10:00
AddStatesAction,
CutFogAction,
EditStatesAction,
RemoveStatesAction,
} from "../../actions";
2021-06-02 17:49:31 +10:00
import Session from "../../network/Session";
2021-07-17 12:48:04 +10:00
import { Drawing, DrawingState } from "../../types/Drawing";
import { Fog, FogState } from "../../types/Fog";
import { Map as MapType, MapToolId } from "../../types/Map";
2021-07-16 14:55:33 +10:00
import { MapState } from "../../types/MapState";
import { Settings } from "../../types/Settings";
import {
MapChangeEventHandler,
MapResetEventHandler,
TokenStateRemoveHandler,
2021-07-17 12:48:04 +10:00
NoteChangeEventHandler,
NoteRemoveEventHander,
TokenStateChangeEventHandler,
NoteCreateEventHander,
2021-07-21 18:56:18 +10:00
SelectionItemsChangeEventHandler,
2021-07-22 16:40:43 +10:00
SelectionItemsRemoveEventHandler,
2021-07-23 15:41:07 +10:00
SelectionItemsCreateEventHandler,
TokensStateCreateHandler,
2021-07-16 14:55:33 +10:00
} from "../../types/Events";
import useMapTokens from "../../hooks/useMapTokens";
import useMapNotes from "../../hooks/useMapNotes";
import { MapActions } from "../../hooks/useMapActions";
2021-07-22 13:16:44 +10:00
import useMapSelection from "../../hooks/useMapSelection";
2021-07-17 12:48:04 +10:00
type MapProps = {
2021-07-17 18:18:57 +10:00
map: MapType | null;
2021-07-17 17:25:41 +10:00
mapState: MapState | null;
mapActions: MapActions;
2021-07-17 12:48:04 +10:00
onMapTokenStateChange: TokenStateChangeEventHandler;
onMapTokenStateRemove: TokenStateRemoveHandler;
onMapTokensStateCreate: TokensStateCreateHandler;
2021-07-21 18:56:18 +10:00
onSelectionItemsChange: SelectionItemsChangeEventHandler;
2021-07-22 16:40:43 +10:00
onSelectionItemsRemove: SelectionItemsRemoveEventHandler;
2021-07-23 15:41:07 +10:00
onSelectionItemsCreate: SelectionItemsCreateEventHandler;
2021-07-17 12:48:04 +10:00
onMapChange: MapChangeEventHandler;
onMapReset: MapResetEventHandler;
onMapDraw: (action: Action<DrawingState>) => void;
onFogDraw: (action: Action<FogState>) => void;
onMapNoteCreate: NoteCreateEventHander;
2021-07-17 12:48:04 +10:00
onMapNoteChange: NoteChangeEventHandler;
onMapNoteRemove: NoteRemoveEventHander;
allowMapChange: boolean;
session: Session;
onUndo: () => void;
onRedo: () => void;
2021-07-17 12:48:04 +10:00
};
2020-03-20 13:33:12 +11:00
function Map({
map,
2020-04-23 17:23:34 +10:00
mapState,
mapActions,
onMapTokenStateChange,
onMapTokenStateRemove,
onMapTokensStateCreate,
2021-07-21 18:56:18 +10:00
onSelectionItemsChange,
2021-07-22 16:40:43 +10:00
onSelectionItemsRemove,
2021-07-23 15:41:07 +10:00
onSelectionItemsCreate,
onMapChange,
2021-02-22 17:14:12 +11:00
onMapReset,
2020-04-19 15:15:48 +10:00
onMapDraw,
onFogDraw,
onMapNoteCreate,
2020-11-04 15:03:34 +11:00
onMapNoteChange,
2020-11-05 14:41:33 +11:00
onMapNoteRemove,
2020-07-17 15:57:52 +10:00
allowMapChange,
2020-07-28 17:59:26 +10:00
session,
onUndo,
onRedo,
2021-07-17 12:48:04 +10:00
}: MapProps) {
const { addToast } = useToasts();
const userId = useUserId();
2021-07-16 14:55:33 +10:00
const [selectedToolId, setSelectedToolId] = useState<MapToolId>("move");
const { settings, setSettings } = useSettings();
2020-04-29 20:55:52 +10:00
2021-07-16 14:55:33 +10:00
function handleToolSettingChange(change: Partial<Settings>) {
setSettings((prevSettings) => ({
...prevSettings,
2021-07-16 14:55:33 +10:00
...change,
}));
}
2020-04-19 00:24:06 +10:00
const drawShapes = Object.values(mapState?.drawings || {});
const fogShapes = Object.values(mapState?.fogs || {});
2021-06-02 17:49:31 +10:00
function handleToolAction(action: string) {
2020-04-29 20:55:52 +10:00
if (action === "eraseAll") {
2021-07-16 14:55:33 +10:00
onMapDraw(new RemoveStatesAction(drawShapes.map((s) => s.id)));
2020-04-29 20:55:52 +10:00
}
}
2021-07-16 14:55:33 +10:00
function handleMapShapeAdd(shape: Drawing) {
onMapDraw(new AddStatesAction([shape]));
}
2021-06-02 17:49:31 +10:00
function handleMapShapesRemove(shapeIds: string[]) {
2021-07-16 14:55:33 +10:00
onMapDraw(new RemoveStatesAction(shapeIds));
}
2021-07-16 14:55:33 +10:00
function handleFogShapesAdd(shapes: Fog[]) {
onFogDraw(new AddStatesAction(shapes));
}
2021-07-16 14:55:33 +10:00
function handleFogShapesCut(shapes: Fog[]) {
onFogDraw(new CutFogAction(shapes));
2020-06-09 12:45:52 +10:00
}
2021-06-02 17:49:31 +10:00
function handleFogShapesRemove(shapeIds: string[]) {
2021-07-16 14:55:33 +10:00
onFogDraw(new RemoveStatesAction(shapeIds));
}
2021-07-16 14:55:33 +10:00
function handleFogShapesEdit(shapes: Partial<Fog>[]) {
onFogDraw(new EditStatesAction(shapes));
2020-04-29 20:40:34 +10:00
}
const { tokens, propTokens, tokenMenu, tokenDragOverlay } = useMapTokens(
map,
mapState,
onMapTokenStateChange,
onMapTokenStateRemove,
onMapTokensStateCreate,
selectedToolId
);
const { notes, noteMenu, noteDragOverlay } = useMapNotes(
map,
mapState,
onMapNoteCreate,
onMapNoteChange,
onMapNoteRemove,
selectedToolId
2021-07-19 11:37:41 +10:00
);
2021-07-22 16:40:43 +10:00
const { selectionTool, selectionMenu, selectionDragOverlay } =
useMapSelection(
map,
mapState,
onSelectionItemsChange,
onSelectionItemsRemove,
2021-07-23 15:41:07 +10:00
onSelectionItemsCreate,
2021-07-22 16:40:43 +10:00
selectedToolId,
settings.select
);
2021-07-22 13:16:44 +10:00
return (
2021-05-06 15:04:53 +10:00
<Box sx={{ flexGrow: 1 }}>
2021-05-13 16:27:07 +10:00
<MapInteraction
map={map}
mapState={mapState}
controls={
<>
<MapControls
onMapChange={onMapChange}
onMapReset={onMapReset}
map={map}
mapState={mapState}
mapActions={mapActions}
allowMapChange={allowMapChange}
onSelectedToolChange={setSelectedToolId}
selectedToolId={selectedToolId}
toolSettings={settings}
onToolSettingChange={handleToolSettingChange}
onToolAction={handleToolAction}
onUndo={onUndo}
onRedo={onRedo}
/>
2021-05-13 16:27:07 +10:00
{tokenMenu}
{noteMenu}
2021-07-22 13:16:44 +10:00
{selectionMenu}
2021-05-13 16:27:07 +10:00
{tokenDragOverlay}
{noteDragOverlay}
2021-07-22 16:40:43 +10:00
{selectionDragOverlay}
2021-05-13 16:27:07 +10:00
</>
}
selectedToolId={selectedToolId}
onSelectedToolChange={setSelectedToolId}
>
{map && map.showGrid && <MapGrid map={map} />}
{propTokens}
<DrawingTool
map={map}
drawings={drawShapes}
onDrawingAdd={handleMapShapeAdd}
onDrawingsRemove={handleMapShapesRemove}
active={selectedToolId === "drawing"}
toolSettings={settings.drawing}
/>
{notes}
{tokens}
<FogTool
map={map}
shapes={fogShapes}
onShapesAdd={handleFogShapesAdd}
onShapesCut={handleFogShapesCut}
onShapesRemove={handleFogShapesRemove}
onShapesEdit={handleFogShapesEdit}
onShapeError={addToast}
active={selectedToolId === "fog"}
toolSettings={settings.fog}
editable={
!!(map?.owner === userId || mapState?.editFlags.includes("fog")) &&
!settings.fog.preview
}
/>
<NetworkedMapPointer
active={selectedToolId === "pointer"}
session={session}
/>
<MeasureTool map={map} active={selectedToolId === "measure"} />
2021-07-22 13:16:44 +10:00
{selectionTool}
2021-05-13 16:27:07 +10:00
</MapInteraction>
2021-05-06 15:04:53 +10:00
</Box>
);
}
export default Map;