This commit is contained in:
Mitchell McCaffrey 2021-07-08 12:00:47 +10:00
parent 62686136ab
commit 123ebd880a
6 changed files with 151 additions and 116 deletions

View File

@ -31,72 +31,70 @@ import Session from "../../network/Session";
import { Grid } from "../../helpers/grid";
import { ImageFile } from "../../helpers/image";
export type Resolutions = Record<string, ImageFile>
export type Resolutions = Record<string, ImageFile>;
export type Map = {
id: string,
name: string,
owner: string,
file?: Uint8Array,
quality?: string,
resolutions?: Resolutions,
grid: Grid,
group: string,
width: number,
height: number,
type: string,
lastUsed: number,
lastModified: number,
created: number,
showGrid: boolean,
snapToGrid: boolean,
thumbnail?: ImageFile,
}
id: string;
name: string;
owner: string;
file?: Uint8Array;
quality?: string;
resolutions?: Resolutions;
grid: Grid;
group: string;
width: number;
height: number;
type: string;
lastUsed: number;
lastModified: number;
created: number;
showGrid: boolean;
snapToGrid: boolean;
thumbnail?: ImageFile;
};
export type Note = {
id: string,
color: string,
lastModified: number,
lastModifiedBy: string,
locked: boolean,
size: number,
text: string,
textOnly: boolean,
visible: boolean,
x: number,
y: number,
}
id: string;
color: string;
lastModified: number;
lastModifiedBy: string;
locked: boolean;
size: number;
text: string;
textOnly: boolean;
visible: boolean;
x: number;
y: number;
};
export type TokenState = {
id: string,
tokenId: string,
owner: string,
size: number,
label: string,
status: string[],
x: number,
y: number,
lastModifiedBy: string,
lastModified: number,
rotation: number,
locked: boolean,
visible: boolean
}
id: string;
tokenId: string;
owner: string;
size: number;
category: string;
label: string;
statuses: string[];
x: number;
y: number;
lastModifiedBy: string;
lastModified: number;
rotation: number;
locked: boolean;
visible: boolean;
type: "default" | "file";
outline: any;
width: number;
height: number;
};
interface PathId extends Path {
id: string
}
interface ShapeId extends Shape {
id: string
}
export type MapState = {
tokens: Record<string, TokenState>,
drawShapes: PathId | ShapeId,
fogShapes: Fog[],
editFlags: ["drawing", "tokens", "notes", "fog"],
notes: Note[],
mapId: string,
}
tokens: Record<string, TokenState>;
drawShapes: Record<string, Path | Shape>;
fogShapes: Record<string, Fog>;
editFlags: ["drawing", "tokens", "notes", "fog"];
notes: Record<string, Note>;
mapId: string;
};
function Map({
map,
@ -121,34 +119,35 @@ function Map({
disabledTokens,
session,
}: {
map: any
mapState: MapState
mapActions: any,
onMapTokenStateChange: any,
onMapTokenStateRemove: any,
onMapChange: any,
onMapReset: any,
onMapDraw: any,
onMapDrawUndo: any,
onMapDrawRedo: any,
onFogDraw: any,
onFogDrawUndo: any,
onFogDrawRedo: any,
onMapNoteChange: any,
onMapNoteRemove: any,
allowMapDrawing: boolean,
allowFogDrawing: boolean,
allowMapChange: boolean,
allowNoteEditing: boolean,
disabledTokens: any,
session: Session
map: any;
mapState: MapState;
mapActions: any;
onMapTokenStateChange: any;
onMapTokenStateRemove: any;
onMapChange: any;
onMapReset: any;
onMapDraw: any;
onMapDrawUndo: any;
onMapDrawRedo: any;
onFogDraw: any;
onFogDrawUndo: any;
onFogDrawRedo: any;
onMapNoteChange: any;
onMapNoteRemove: any;
allowMapDrawing: boolean;
allowFogDrawing: boolean;
allowMapChange: boolean;
allowNoteEditing: boolean;
disabledTokens: any;
session: Session;
}) {
const { addToast } = useToasts();
const { tokensById } = useTokenData();
const [selectedToolId, setSelectedToolId] = useState("move");
const { settings, setSettings }: { settings: any, setSettings: any} = useSettings();
const { settings, setSettings }: { settings: any; setSettings: any } =
useSettings();
function handleToolSettingChange(tool: any, change: any) {
setSettings((prevSettings: any) => ({
@ -224,7 +223,10 @@ function Map({
disabledControls.push("note");
}
const disabledSettings: { fog: any[], drawing: any[]} = { fog: [], drawing: [] };
const disabledSettings: { fog: any[]; drawing: any[] } = {
fog: [],
drawing: [],
};
if (drawShapes.length === 0) {
disabledSettings.drawing.push("erase");
}
@ -263,9 +265,18 @@ function Map({
/>
);
const [isTokenMenuOpen, setIsTokenMenuOpen]: [ isTokenMenuOpen: boolean, setIsTokenMenuOpen: React.Dispatch<React.SetStateAction<boolean>>] = useState<boolean>(false);
const [tokenMenuOptions, setTokenMenuOptions]: [ tokenMenuOptions: any, setTokenMenuOptions: any ] = useState({});
const [tokenDraggingOptions, setTokenDraggingOptions]: [ tokenDraggingOptions: any, setTokenDragginOptions: any ] = useState();
const [isTokenMenuOpen, setIsTokenMenuOpen]: [
isTokenMenuOpen: boolean,
setIsTokenMenuOpen: React.Dispatch<React.SetStateAction<boolean>>
] = useState<boolean>(false);
const [tokenMenuOptions, setTokenMenuOptions]: [
tokenMenuOptions: any,
setTokenMenuOptions: any
] = useState({});
const [tokenDraggingOptions, setTokenDraggingOptions]: [
tokenDraggingOptions: any,
setTokenDragginOptions: any
] = useState();
function handleTokenMenuOpen(tokenStateId: string, tokenImage: any) {
setTokenMenuOptions({ tokenStateId, tokenImage });
setIsTokenMenuOpen(true);
@ -338,10 +349,7 @@ function Map({
const mapGrid = map && map.showGrid && <MapGrid map={map} />;
const mapMeasure = (
<MapMeasure
map={map}
active={selectedToolId === "measure"}
/>
<MapMeasure map={map} active={selectedToolId === "measure"} />
);
const mapPointer = (
@ -353,7 +361,7 @@ function Map({
const [isNoteMenuOpen, setIsNoteMenuOpen] = useState<boolean>(false);
const [noteMenuOptions, setNoteMenuOptions] = useState<any>({});
const [noteDraggingOptions, setNoteDraggingOptions]= useState<any>();
const [noteDraggingOptions, setNoteDraggingOptions] = useState<any>();
function handleNoteMenuOpen(noteId: string, noteNode: any) {
setNoteMenuOptions({ noteId, noteNode });
setIsNoteMenuOpen(true);

View File

@ -11,12 +11,8 @@ import { getGroupItems } from "../../helpers/group";
import { useGroup } from "../../contexts/GroupContext";
function MapTiles({ mapsById, onMapEdit, onMapSelect, subgroup }) {
const {
selectedGroupIds,
selectMode,
onGroupOpen,
onGroupSelect,
} = useGroup();
const { selectedGroupIds, selectMode, onGroupOpen, onGroupSelect } =
useGroup();
function renderTile(group) {
if (group.type === "item") {
@ -66,4 +62,8 @@ function MapTiles({ mapsById, onMapEdit, onMapSelect, subgroup }) {
);
}
MapTiles.defaultProps = {
subgroup: false,
};
export default MapTiles;

View File

@ -12,12 +12,8 @@ import { getGroupItems } from "../../helpers/group";
import { useGroup } from "../../contexts/GroupContext";
function TokenTiles({ tokensById, onTokenEdit, subgroup }) {
const {
selectedGroupIds,
selectMode,
onGroupOpen,
onGroupSelect,
} = useGroup();
const { selectedGroupIds, selectMode, onGroupOpen, onGroupSelect } =
useGroup();
function renderTile(group) {
if (group.type === "item") {
@ -70,4 +66,8 @@ function TokenTiles({ tokensById, onTokenEdit, subgroup }) {
);
}
TokenTiles.defaultProps = {
subgroup: false,
};
export default TokenTiles;

View File

@ -1,8 +1,6 @@
import React, { useContext } from "react";
const MapStageContext = React.createContext({
mapStageRef: { current: null },
});
const MapStageContext = React.createContext({ current: null });
export const MapStageProvider: any = MapStageContext.Provider;
export function useMapStage() {

View File

@ -44,10 +44,11 @@ class Vector2 {
}
/**
* Returns the length of vector `p` Note: magnitude to not conflict with native length property
* @param {Vector2} p
* @returns {number} Length of `p`
*/
static setLength(p: Vector2): number {
static magnitude(p: Vector2): number {
return Math.sqrt(this.lengthSquared(p));
}
@ -56,7 +57,7 @@ class Vector2 {
* @returns {Vector2} `p` normalized, if length of `p` is 0 `{x: 0, y: 0}` is returned
*/
static normalize(p: Vector2): Vector2 {
const l = this.setLength(p);
const l = this.magnitude(p);
if (l === 0) {
return { x: 0, y: 0 };
}
@ -271,7 +272,7 @@ class Vector2 {
const pa = this.subtract(p, a);
const ba = this.subtract(b, a);
const h = Math.min(Math.max(this.dot(pa, ba) / this.dot(ba, ba), 0), 1);
const distance = this.setLength(this.subtract(pa, this.multiply(ba, h)));
const distance = this.magnitude(this.subtract(pa, this.multiply(ba, h)));
const point = this.add(a, this.multiply(ba, h));
return { distance, point };
}
@ -443,7 +444,7 @@ class Vector2 {
* @returns {number}
*/
static distance(a: Vector2, b: Vector2): number {
return this.setLength(this.subtract(a, b));
return this.magnitude(this.subtract(a, b));
}
/**

View File

@ -6,7 +6,7 @@ import Color from "color";
import Vector2 from "./Vector2";
// Holes should be wound in the opposite direction as the containing points array
export function HoleyLine({ holes, ...props }: { holes: any, props: []}) {
export function HoleyLine({ holes, ...props }: { holes: any; props: [] }) {
// Converted from https://github.com/rfestag/konva/blob/master/src/shapes/Line.ts
function drawLine(points: number[], context: any, shape: any) {
const length = points.length;
@ -109,7 +109,19 @@ export function HoleyLine({ holes, ...props }: { holes: any, props: []}) {
return <Line sceneFunc={sceneFunc} {...props} />;
}
export function Tick({ x, y, scale, onClick, cross }: { x: any, y: any, scale: any, onClick: any, cross: any}) {
export function Tick({
x,
y,
scale,
onClick,
cross,
}: {
x: any;
y: any;
scale: any;
onClick: any;
cross: any;
}) {
const [fill, setFill] = useState("white");
function handleEnter() {
setFill("hsl(260, 100%, 80%)");
@ -145,10 +157,22 @@ export function Tick({ x, y, scale, onClick, cross }: { x: any, y: any, scale: a
}
interface TrailPoint extends Vector2 {
lifetime: number
lifetime: number;
}
export function Trail({ position, size, duration, segments, color }: { position: Vector2, size: any, duration: number, segments: any, color: string }) {
export function Trail({
position,
size,
duration,
segments,
color,
}: {
position: Vector2;
size: any;
duration: number;
segments: any;
color: string;
}) {
const trailRef: React.MutableRefObject<Konva.Line | undefined> = useRef();
const pointsRef: React.MutableRefObject<TrailPoint[]> = useRef([]);
const prevPositionRef = useRef(position);
@ -259,7 +283,7 @@ export function Trail({ position, size, duration, segments, color }: { position:
// Create a radial gradient from the center of the trail to the tail
const gradientCenter = resampledPoints[resampledPoints.length - 1];
const gradientEnd = resampledPoints[0];
const gradientRadius = Vector2.setLength(
const gradientRadius = Vector2.magnitude(
Vector2.subtract(gradientCenter, gradientEnd)
);
let gradient = context.createRadialGradient(
@ -302,7 +326,9 @@ Trail.defaultProps = {
* @param {Konva.Node} node
* @returns {Vector2}
*/
export function getRelativePointerPosition(node: Konva.Node): { x: number, y: number } | undefined {
export function getRelativePointerPosition(
node: Konva.Node
): { x: number; y: number } | undefined {
let transform = node.getAbsoluteTransform().copy();
transform.invert();
// TODO: handle possible null value
@ -314,7 +340,9 @@ export function getRelativePointerPosition(node: Konva.Node): { x: number, y: nu
return transform.point(position);
}
export function getRelativePointerPositionNormalized(node: Konva.Node): { x: number, y: number } | undefined {
export function getRelativePointerPositionNormalized(
node: Konva.Node
): { x: number; y: number } | undefined {
const relativePosition = getRelativePointerPosition(node);
if (!relativePosition) {
// TODO: handle possible null value