Added is vehicle checkbox and vehicle type tokens
This commit is contained in:
parent
00c24c34a4
commit
a8bd5ab672
@ -32,7 +32,7 @@ function Map({
|
||||
disabledTokens,
|
||||
loading,
|
||||
}) {
|
||||
const { tokens } = useContext(TokenDataContext);
|
||||
const { tokensById } = useContext(TokenDataContext);
|
||||
|
||||
const gridX = map && map.gridX;
|
||||
const gridY = map && map.gridY;
|
||||
@ -200,7 +200,7 @@ function Map({
|
||||
|
||||
const [isTokenMenuOpen, setIsTokenMenuOpen] = useState(false);
|
||||
const [tokenMenuOptions, setTokenMenuOptions] = useState({});
|
||||
const [draggingTokenState, setDraggingTokenState] = useState();
|
||||
const [draggingTokenOptions, setDraggingTokenOptions] = useState();
|
||||
function handleTokenMenuOpen(tokenStateId, tokenImage) {
|
||||
setTokenMenuOptions({ tokenStateId, tokenImage });
|
||||
setIsTokenMenuOpen(true);
|
||||
@ -208,22 +208,30 @@ function Map({
|
||||
|
||||
const mapTokens =
|
||||
mapState &&
|
||||
Object.values(mapState.tokens).map((tokenState) => (
|
||||
<MapToken
|
||||
key={tokenState.id}
|
||||
token={tokens.find((token) => token.id === tokenState.tokenId)}
|
||||
tokenState={tokenState}
|
||||
tokenSizePercent={tokenSizePercent}
|
||||
onTokenStateChange={onMapTokenStateChange}
|
||||
onTokenMenuOpen={handleTokenMenuOpen}
|
||||
onTokenDragStart={() => setDraggingTokenState(tokenState)}
|
||||
onTokenDragEnd={() => setDraggingTokenState(null)}
|
||||
draggable={
|
||||
(selectedToolId === "pan" || selectedToolId === "erase") &&
|
||||
!(tokenState.id in disabledTokens)
|
||||
}
|
||||
/>
|
||||
));
|
||||
Object.values(mapState.tokens)
|
||||
.sort(
|
||||
(a, b) =>
|
||||
tokensById[b.tokenId].isVehicle - tokensById[a.tokenId].isVehicle
|
||||
) // Sort so vehicles render below other tokens
|
||||
.map((tokenState) => (
|
||||
<MapToken
|
||||
key={tokenState.id}
|
||||
token={tokensById[tokenState.tokenId]}
|
||||
tokenState={tokenState}
|
||||
tokenSizePercent={tokenSizePercent}
|
||||
onTokenStateChange={onMapTokenStateChange}
|
||||
onTokenMenuOpen={handleTokenMenuOpen}
|
||||
onTokenDragStart={(e) =>
|
||||
setDraggingTokenOptions({ tokenState, tokenImage: e.target })
|
||||
}
|
||||
onTokenDragEnd={() => setDraggingTokenOptions(null)}
|
||||
draggable={
|
||||
(selectedToolId === "pan" || selectedToolId === "erase") &&
|
||||
!(tokenState.id in disabledTokens)
|
||||
}
|
||||
mapState={mapState}
|
||||
/>
|
||||
));
|
||||
|
||||
const tokenMenu = (
|
||||
<TokenMenu
|
||||
@ -235,12 +243,17 @@ function Map({
|
||||
/>
|
||||
);
|
||||
|
||||
const tokenDragOverlay = draggingTokenState && (
|
||||
const tokenDragOverlay = draggingTokenOptions && (
|
||||
<TokenDragOverlay
|
||||
onTokenStateRemove={() => {
|
||||
onMapTokenStateRemove(draggingTokenState);
|
||||
setDraggingTokenState(null);
|
||||
onTokenStateRemove={(state) => {
|
||||
onMapTokenStateRemove(state);
|
||||
setDraggingTokenOptions(null);
|
||||
}}
|
||||
onTokenStateChange={onMapTokenStateChange}
|
||||
tokenState={draggingTokenOptions && draggingTokenOptions.tokenState}
|
||||
tokenImage={draggingTokenOptions && draggingTokenOptions.tokenImage}
|
||||
token={tokensById[draggingTokenOptions.tokenState.tokenId]}
|
||||
mapState={mapState}
|
||||
/>
|
||||
);
|
||||
|
||||
|
@ -22,6 +22,7 @@ function MapToken({
|
||||
onTokenDragStart,
|
||||
onTokenDragEnd,
|
||||
draggable,
|
||||
mapState,
|
||||
}) {
|
||||
const { userId } = useContext(AuthContext);
|
||||
const {
|
||||
@ -41,15 +42,69 @@ function MapToken({
|
||||
}
|
||||
}, [tokenSourceImage]);
|
||||
|
||||
function handleDragStart(event) {
|
||||
const tokenImage = event.target;
|
||||
const tokenImageRect = tokenImage.getClientRect();
|
||||
|
||||
if (token.isVehicle) {
|
||||
// Find all other tokens on the map
|
||||
const layer = tokenImage.getLayer();
|
||||
const tokens = layer.find(".token");
|
||||
for (let other of tokens) {
|
||||
if (other === tokenImage) {
|
||||
continue;
|
||||
}
|
||||
const otherRect = other.getClientRect();
|
||||
const otherCenter = {
|
||||
x: otherRect.x + otherRect.width / 2,
|
||||
y: otherRect.y + otherRect.height / 2,
|
||||
};
|
||||
// Check the other tokens center overlaps this tokens bounding box
|
||||
if (
|
||||
otherCenter.x > tokenImageRect.x &&
|
||||
otherCenter.x < tokenImageRect.x + tokenImageRect.width &&
|
||||
otherCenter.y > tokenImageRect.y &&
|
||||
otherCenter.y < tokenImageRect.y + tokenImageRect.height
|
||||
) {
|
||||
// Save and restore token position after moving layer
|
||||
const position = other.absolutePosition();
|
||||
other.moveTo(tokenImage);
|
||||
other.absolutePosition(position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onTokenDragStart(event);
|
||||
}
|
||||
|
||||
function handleDragEnd(event) {
|
||||
const tokenImage = event.target;
|
||||
|
||||
if (token.isVehicle) {
|
||||
const layer = tokenImage.getLayer();
|
||||
const mountedTokens = tokenImage.find(".token");
|
||||
for (let mountedToken of mountedTokens) {
|
||||
// Save and restore token position after moving layer
|
||||
const position = mountedToken.absolutePosition();
|
||||
mountedToken.moveTo(layer);
|
||||
mountedToken.absolutePosition(position);
|
||||
onTokenStateChange({
|
||||
...mapState.tokens[mountedToken.id()],
|
||||
x: mountedToken.x() / mapWidth,
|
||||
y: mountedToken.y() / mapHeight,
|
||||
lastEditedBy: userId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
setPreventMapInteraction(false);
|
||||
onTokenStateChange({
|
||||
...tokenState,
|
||||
x: event.target.x() / mapWidth,
|
||||
y: event.target.y() / mapHeight,
|
||||
x: tokenImage.x() / mapWidth,
|
||||
y: tokenImage.y() / mapHeight,
|
||||
lastEditedBy: userId,
|
||||
});
|
||||
onTokenDragEnd();
|
||||
onTokenDragEnd(event);
|
||||
}
|
||||
|
||||
function handleClick(event) {
|
||||
@ -121,8 +176,10 @@ function MapToken({
|
||||
onTouchEnd={handlePointerUp}
|
||||
onClick={handleClick}
|
||||
onDragEnd={handleDragEnd}
|
||||
onDragStart={onTokenDragStart}
|
||||
onDragStart={handleDragStart}
|
||||
opacity={tokenOpacity}
|
||||
name={token.isVehicle ? "vehicle" : "token"}
|
||||
id={tokenState.id}
|
||||
>
|
||||
<KonvaImage
|
||||
ref={imageRef}
|
||||
|
@ -3,13 +3,41 @@ import { Box, IconButton } from "theme-ui";
|
||||
|
||||
import RemoveTokenIcon from "../../icons/RemoveTokenIcon";
|
||||
|
||||
import AuthContext from "../../contexts/AuthContext";
|
||||
import MapInteractionContext from "../../contexts/MapInteractionContext";
|
||||
|
||||
function TokenDragOverlay({ onTokenStateRemove }) {
|
||||
const { setPreventMapInteraction } = useContext(MapInteractionContext);
|
||||
function TokenDragOverlay({
|
||||
onTokenStateRemove,
|
||||
onTokenStateChange,
|
||||
token,
|
||||
tokenState,
|
||||
tokenImage,
|
||||
mapState,
|
||||
}) {
|
||||
const { userId } = useContext(AuthContext);
|
||||
const { setPreventMapInteraction, mapWidth, mapHeight } = useContext(
|
||||
MapInteractionContext
|
||||
);
|
||||
|
||||
function handleTokenRemove() {
|
||||
onTokenStateRemove();
|
||||
// Handle other tokens when a vehicle gets deleted
|
||||
if (token.isVehicle) {
|
||||
const layer = tokenImage.getLayer();
|
||||
const mountedTokens = tokenImage.find(".token");
|
||||
for (let mountedToken of mountedTokens) {
|
||||
// Save and restore token position after moving layer
|
||||
const position = mountedToken.absolutePosition();
|
||||
mountedToken.moveTo(layer);
|
||||
mountedToken.absolutePosition(position);
|
||||
onTokenStateChange({
|
||||
...mapState.tokens[mountedToken.id()],
|
||||
x: mountedToken.x() / mapWidth,
|
||||
y: mountedToken.y() / mapHeight,
|
||||
lastEditedBy: userId,
|
||||
});
|
||||
}
|
||||
}
|
||||
onTokenStateRemove(tokenState);
|
||||
setPreventMapInteraction(false);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import { Flex, Box, Input, IconButton, Label } from "theme-ui";
|
||||
import { Flex, Box, Input, IconButton, Label, Checkbox } from "theme-ui";
|
||||
|
||||
import ExpandMoreIcon from "../../icons/ExpandMoreIcon";
|
||||
|
||||
@ -29,7 +29,7 @@ function TokenSettings({
|
||||
</Flex>
|
||||
{showMore && (
|
||||
<>
|
||||
<Box my={2} sx={{ flexGrow: 1 }}>
|
||||
<Box mt={2} sx={{ flexGrow: 1 }}>
|
||||
<Label htmlFor="name">Name</Label>
|
||||
<Input
|
||||
name="name"
|
||||
@ -39,6 +39,18 @@ function TokenSettings({
|
||||
my={1}
|
||||
/>
|
||||
</Box>
|
||||
<Box my={2}>
|
||||
<Label>
|
||||
<Checkbox
|
||||
checked={token && token.isVehicle}
|
||||
disabled={!token || token.type === "default"}
|
||||
onChange={(e) =>
|
||||
onSettingsChange("isVehicle", e.target.checked)
|
||||
}
|
||||
/>
|
||||
Vehicle / Mount
|
||||
</Label>
|
||||
</Box>
|
||||
</>
|
||||
)}
|
||||
<IconButton
|
||||
|
@ -86,6 +86,11 @@ export function TokenDataProvider({ children }) {
|
||||
|
||||
const ownedTokens = tokens.filter((token) => token.owner === userId);
|
||||
|
||||
const tokensById = tokens.reduce((obj, token) => {
|
||||
obj[token.id] = token;
|
||||
return obj;
|
||||
}, {});
|
||||
|
||||
const value = {
|
||||
tokens,
|
||||
ownedTokens,
|
||||
@ -94,6 +99,7 @@ export function TokenDataProvider({ children }) {
|
||||
updateToken,
|
||||
putToken,
|
||||
getToken,
|
||||
tokensById,
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -64,6 +64,7 @@ function SelectTokensModal({ isOpen, onRequestClose }) {
|
||||
lastModified: Date.now(),
|
||||
owner: userId,
|
||||
defaultSize: 1,
|
||||
isVehicle: false,
|
||||
});
|
||||
setImageLoading(false);
|
||||
};
|
||||
|
@ -85,6 +85,7 @@ export const tokens = Object.keys(tokenSources).map((key) => ({
|
||||
name: Case.capital(key),
|
||||
type: "default",
|
||||
defaultSize: getDefaultTokenSize(key),
|
||||
isVehicle: false,
|
||||
}));
|
||||
|
||||
export const unknownSource = unknown;
|
||||
|
Loading…
Reference in New Issue
Block a user