Add selection drag overlay
This commit is contained in:
parent
19139dec82
commit
ed64294855
@ -30,6 +30,8 @@ type SelectionProps = {
|
|||||||
onSelectionChange: (selection: SelectionType | null) => void;
|
onSelectionChange: (selection: SelectionType | null) => void;
|
||||||
onSelectionItemsChange: SelectionItemsChangeEventHandler;
|
onSelectionItemsChange: SelectionItemsChangeEventHandler;
|
||||||
onPreventSelectionChange: (preventSelection: boolean) => void;
|
onPreventSelectionChange: (preventSelection: boolean) => void;
|
||||||
|
onSelectionDragStart: () => void;
|
||||||
|
onSelectionDragEnd: () => void;
|
||||||
} & Konva.ShapeConfig;
|
} & Konva.ShapeConfig;
|
||||||
|
|
||||||
function Selection({
|
function Selection({
|
||||||
@ -37,6 +39,8 @@ function Selection({
|
|||||||
onSelectionChange,
|
onSelectionChange,
|
||||||
onSelectionItemsChange,
|
onSelectionItemsChange,
|
||||||
onPreventSelectionChange,
|
onPreventSelectionChange,
|
||||||
|
onSelectionDragStart,
|
||||||
|
onSelectionDragEnd,
|
||||||
...props
|
...props
|
||||||
}: SelectionProps) {
|
}: SelectionProps) {
|
||||||
const userId = useUserId();
|
const userId = useUserId();
|
||||||
@ -75,6 +79,7 @@ function Selection({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
onSelectionDragStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleDragMove(event: Konva.KonvaEventObject<DragEvent>) {
|
function handleDragMove(event: Konva.KonvaEventObject<DragEvent>) {
|
||||||
@ -119,6 +124,7 @@ function Selection({
|
|||||||
});
|
});
|
||||||
intersectingNodesRef.current = [];
|
intersectingNodesRef.current = [];
|
||||||
onPreventSelectionChange(false);
|
onPreventSelectionChange(false);
|
||||||
|
onSelectionDragEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
function handlePointerDown() {
|
function handlePointerDown() {
|
||||||
|
@ -38,6 +38,7 @@ import {
|
|||||||
TokenStateChangeEventHandler,
|
TokenStateChangeEventHandler,
|
||||||
NoteCreateEventHander,
|
NoteCreateEventHander,
|
||||||
SelectionItemsChangeEventHandler,
|
SelectionItemsChangeEventHandler,
|
||||||
|
SelectionItemsRemoveEventHandler,
|
||||||
} from "../../types/Events";
|
} from "../../types/Events";
|
||||||
|
|
||||||
import useMapTokens from "../../hooks/useMapTokens";
|
import useMapTokens from "../../hooks/useMapTokens";
|
||||||
@ -52,6 +53,7 @@ type MapProps = {
|
|||||||
onMapTokenStateChange: TokenStateChangeEventHandler;
|
onMapTokenStateChange: TokenStateChangeEventHandler;
|
||||||
onMapTokenStateRemove: TokenStateRemoveHandler;
|
onMapTokenStateRemove: TokenStateRemoveHandler;
|
||||||
onSelectionItemsChange: SelectionItemsChangeEventHandler;
|
onSelectionItemsChange: SelectionItemsChangeEventHandler;
|
||||||
|
onSelectionItemsRemove: SelectionItemsRemoveEventHandler;
|
||||||
onMapChange: MapChangeEventHandler;
|
onMapChange: MapChangeEventHandler;
|
||||||
onMapReset: MapResetEventHandler;
|
onMapReset: MapResetEventHandler;
|
||||||
onMapDraw: (action: Action<DrawingState>) => void;
|
onMapDraw: (action: Action<DrawingState>) => void;
|
||||||
@ -72,6 +74,7 @@ function Map({
|
|||||||
onMapTokenStateChange,
|
onMapTokenStateChange,
|
||||||
onMapTokenStateRemove,
|
onMapTokenStateRemove,
|
||||||
onSelectionItemsChange,
|
onSelectionItemsChange,
|
||||||
|
onSelectionItemsRemove,
|
||||||
onMapChange,
|
onMapChange,
|
||||||
onMapReset,
|
onMapReset,
|
||||||
onMapDraw,
|
onMapDraw,
|
||||||
@ -149,13 +152,15 @@ function Map({
|
|||||||
!!(map?.owner === userId || mapState?.editFlags.includes("notes"))
|
!!(map?.owner === userId || mapState?.editFlags.includes("notes"))
|
||||||
);
|
);
|
||||||
|
|
||||||
const { selectionTool, selectionMenu } = useMapSelection(
|
const { selectionTool, selectionMenu, selectionDragOverlay } =
|
||||||
map,
|
useMapSelection(
|
||||||
mapState,
|
map,
|
||||||
onSelectionItemsChange,
|
mapState,
|
||||||
selectedToolId,
|
onSelectionItemsChange,
|
||||||
settings.select
|
onSelectionItemsRemove,
|
||||||
);
|
selectedToolId,
|
||||||
|
settings.select
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ flexGrow: 1 }}>
|
<Box sx={{ flexGrow: 1 }}>
|
||||||
@ -184,6 +189,7 @@ function Map({
|
|||||||
{selectionMenu}
|
{selectionMenu}
|
||||||
{tokenDragOverlay}
|
{tokenDragOverlay}
|
||||||
{noteDragOverlay}
|
{noteDragOverlay}
|
||||||
|
{selectionDragOverlay}
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
selectedToolId={selectedToolId}
|
selectedToolId={selectedToolId}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import Konva from "konva";
|
|
||||||
import { NoteRemoveEventHander } from "../../types/Events";
|
import { NoteRemoveEventHander } from "../../types/Events";
|
||||||
|
|
||||||
import DragOverlay from "../map/DragOverlay";
|
import DragOverlay from "../map/DragOverlay";
|
||||||
@ -6,27 +5,19 @@ import DragOverlay from "../map/DragOverlay";
|
|||||||
type NoteDragOverlayProps = {
|
type NoteDragOverlayProps = {
|
||||||
onNoteRemove: NoteRemoveEventHander;
|
onNoteRemove: NoteRemoveEventHander;
|
||||||
noteId: string;
|
noteId: string;
|
||||||
noteGroup: Konva.Node;
|
|
||||||
dragging: boolean;
|
dragging: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
function NoteDragOverlay({
|
function NoteDragOverlay({
|
||||||
onNoteRemove,
|
onNoteRemove,
|
||||||
noteId,
|
noteId,
|
||||||
noteGroup,
|
|
||||||
dragging,
|
dragging,
|
||||||
}: NoteDragOverlayProps) {
|
}: NoteDragOverlayProps) {
|
||||||
function handleNoteRemove() {
|
function handleNoteRemove() {
|
||||||
onNoteRemove([noteId]);
|
onNoteRemove([noteId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return <DragOverlay dragging={dragging} onRemove={handleNoteRemove} />;
|
||||||
<DragOverlay
|
|
||||||
dragging={dragging}
|
|
||||||
onRemove={handleNoteRemove}
|
|
||||||
node={noteGroup}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default NoteDragOverlay;
|
export default NoteDragOverlay;
|
||||||
|
33
src/components/selection/SelectionDragOverlay.tsx
Normal file
33
src/components/selection/SelectionDragOverlay.tsx
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { SelectionItemsRemoveEventHandler } from "../../types/Events";
|
||||||
|
import { Selection } from "../../types/Select";
|
||||||
|
|
||||||
|
import DragOverlay from "../map/DragOverlay";
|
||||||
|
|
||||||
|
type NoteDragOverlayProps = {
|
||||||
|
onSelectionItemsRemove: SelectionItemsRemoveEventHandler;
|
||||||
|
selection: Selection;
|
||||||
|
dragging: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
function NoteDragOverlay({
|
||||||
|
onSelectionItemsRemove,
|
||||||
|
selection,
|
||||||
|
dragging,
|
||||||
|
}: NoteDragOverlayProps) {
|
||||||
|
function handleNoteRemove() {
|
||||||
|
const tokenIds: string[] = [];
|
||||||
|
const noteIds: string[] = [];
|
||||||
|
for (let item of selection.items) {
|
||||||
|
if (item.type === "token") {
|
||||||
|
tokenIds.push(item.id);
|
||||||
|
} else {
|
||||||
|
noteIds.push(item.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onSelectionItemsRemove(tokenIds, noteIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <DragOverlay dragging={dragging} onRemove={handleNoteRemove} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NoteDragOverlay;
|
@ -40,6 +40,8 @@ type MapSelectProps = {
|
|||||||
selection: SelectionType | null;
|
selection: SelectionType | null;
|
||||||
onSelectionChange: React.Dispatch<React.SetStateAction<SelectionType | null>>;
|
onSelectionChange: React.Dispatch<React.SetStateAction<SelectionType | null>>;
|
||||||
onSelectionMenuOpen: (open: boolean) => void;
|
onSelectionMenuOpen: (open: boolean) => void;
|
||||||
|
onSelectionDragStart: () => void;
|
||||||
|
onSelectionDragEnd: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
function SelectTool({
|
function SelectTool({
|
||||||
@ -49,6 +51,8 @@ function SelectTool({
|
|||||||
selection,
|
selection,
|
||||||
onSelectionChange,
|
onSelectionChange,
|
||||||
onSelectionMenuOpen,
|
onSelectionMenuOpen,
|
||||||
|
onSelectionDragStart,
|
||||||
|
onSelectionDragEnd,
|
||||||
}: MapSelectProps) {
|
}: MapSelectProps) {
|
||||||
const stageScale = useDebouncedStageScale();
|
const stageScale = useDebouncedStageScale();
|
||||||
const mapWidth = useMapWidth();
|
const mapWidth = useMapWidth();
|
||||||
@ -255,6 +259,8 @@ function SelectTool({
|
|||||||
onPreventSelectionChange={(prevent: boolean) =>
|
onPreventSelectionChange={(prevent: boolean) =>
|
||||||
(preventSelectionRef.current = prevent)
|
(preventSelectionRef.current = prevent)
|
||||||
}
|
}
|
||||||
|
onSelectionDragStart={onSelectionDragStart}
|
||||||
|
onSelectionDragEnd={onSelectionDragEnd}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Group>
|
</Group>
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
import SelectionDragOverlay from "../components/selection/SelectionDragOverlay";
|
||||||
import SelectionMenu from "../components/selection/SelectionMenu";
|
import SelectionMenu from "../components/selection/SelectionMenu";
|
||||||
import SelectTool from "../components/tools/SelectTool";
|
import SelectTool from "../components/tools/SelectTool";
|
||||||
import { SelectionItemsChangeEventHandler } from "../types/Events";
|
import {
|
||||||
|
SelectionItemsChangeEventHandler,
|
||||||
|
SelectionItemsRemoveEventHandler,
|
||||||
|
} from "../types/Events";
|
||||||
import { Map, MapToolId } from "../types/Map";
|
import { Map, MapToolId } from "../types/Map";
|
||||||
import { MapState } from "../types/MapState";
|
import { MapState } from "../types/MapState";
|
||||||
import { Selection } from "../types/Select";
|
import { Selection } from "../types/Select";
|
||||||
@ -11,11 +15,13 @@ function useMapSelection(
|
|||||||
map: Map | null,
|
map: Map | null,
|
||||||
mapState: MapState | null,
|
mapState: MapState | null,
|
||||||
onSelectionItemsChange: SelectionItemsChangeEventHandler,
|
onSelectionItemsChange: SelectionItemsChangeEventHandler,
|
||||||
|
onSelectionItemsRemove: SelectionItemsRemoveEventHandler,
|
||||||
selectedToolId: MapToolId,
|
selectedToolId: MapToolId,
|
||||||
settings: SelectToolSettings
|
settings: SelectToolSettings
|
||||||
) {
|
) {
|
||||||
const [isSelectionMenuOpen, setIsSelectionMenuOpen] =
|
const [isSelectionMenuOpen, setIsSelectionMenuOpen] =
|
||||||
useState<boolean>(false);
|
useState<boolean>(false);
|
||||||
|
const [isSelectionDragging, setIsSelectionDragging] = useState(false);
|
||||||
const [selection, setSelection] = useState<Selection | null>(null);
|
const [selection, setSelection] = useState<Selection | null>(null);
|
||||||
|
|
||||||
function handleSelectionMenuOpen(open: boolean) {
|
function handleSelectionMenuOpen(open: boolean) {
|
||||||
@ -31,6 +37,22 @@ function useMapSelection(
|
|||||||
}
|
}
|
||||||
}, [active]);
|
}, [active]);
|
||||||
|
|
||||||
|
function handleSelectionDragStart() {
|
||||||
|
setIsSelectionDragging(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSelectionDragEnd() {
|
||||||
|
setIsSelectionDragging(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSelectionItemsRemove(
|
||||||
|
tokenStateIds: string[],
|
||||||
|
noteIds: string[]
|
||||||
|
) {
|
||||||
|
setSelection(null);
|
||||||
|
onSelectionItemsRemove(tokenStateIds, noteIds);
|
||||||
|
}
|
||||||
|
|
||||||
const selectionTool = (
|
const selectionTool = (
|
||||||
<SelectTool
|
<SelectTool
|
||||||
active={active}
|
active={active}
|
||||||
@ -39,6 +61,8 @@ function useMapSelection(
|
|||||||
selection={selection}
|
selection={selection}
|
||||||
onSelectionChange={setSelection}
|
onSelectionChange={setSelection}
|
||||||
onSelectionMenuOpen={handleSelectionMenuOpen}
|
onSelectionMenuOpen={handleSelectionMenuOpen}
|
||||||
|
onSelectionDragStart={handleSelectionDragStart}
|
||||||
|
onSelectionDragEnd={handleSelectionDragEnd}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -53,7 +77,15 @@ function useMapSelection(
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
return { selectionTool, selectionMenu };
|
const selectionDragOverlay = selection ? (
|
||||||
|
<SelectionDragOverlay
|
||||||
|
dragging={isSelectionDragging}
|
||||||
|
selection={selection}
|
||||||
|
onSelectionItemsRemove={handleSelectionItemsRemove}
|
||||||
|
/>
|
||||||
|
) : null;
|
||||||
|
|
||||||
|
return { selectionTool, selectionMenu, selectionDragOverlay };
|
||||||
}
|
}
|
||||||
|
|
||||||
export default useMapSelection;
|
export default useMapSelection;
|
||||||
|
@ -330,6 +330,18 @@ function NetworkedMapAndTokens({ session }: { session: Session }) {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleSelectionItemsRemove(
|
||||||
|
tokenStateIds: string[],
|
||||||
|
noteIds: string[]
|
||||||
|
) {
|
||||||
|
const tokenAction = new RemoveStatesAction<TokenState>(tokenStateIds);
|
||||||
|
const noteAction = new RemoveStatesAction<Note>(noteIds);
|
||||||
|
addActions([
|
||||||
|
{ type: "tokens", action: tokenAction },
|
||||||
|
{ type: "notes", action: noteAction },
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function handlePeerData({ id, data, reply }: PeerDataEvent) {
|
async function handlePeerData({ id, data, reply }: PeerDataEvent) {
|
||||||
if (id === "assetRequest") {
|
if (id === "assetRequest") {
|
||||||
@ -394,6 +406,7 @@ function NetworkedMapAndTokens({ session }: { session: Session }) {
|
|||||||
onMapTokenStateChange={handleMapTokenStateChange}
|
onMapTokenStateChange={handleMapTokenStateChange}
|
||||||
onMapTokenStateRemove={handleMapTokenStateRemove}
|
onMapTokenStateRemove={handleMapTokenStateRemove}
|
||||||
onSelectionItemsChange={handleSelectionItemsChange}
|
onSelectionItemsChange={handleSelectionItemsChange}
|
||||||
|
onSelectionItemsRemove={handleSelectionItemsRemove}
|
||||||
onMapChange={handleMapChange}
|
onMapChange={handleMapChange}
|
||||||
onMapReset={handleMapReset}
|
onMapReset={handleMapReset}
|
||||||
onMapDraw={handleMapDraw}
|
onMapDraw={handleMapDraw}
|
||||||
|
@ -63,3 +63,7 @@ export type SelectionItemsChangeEventHandler = (
|
|||||||
tokenChanges: Record<string, Partial<TokenState>>,
|
tokenChanges: Record<string, Partial<TokenState>>,
|
||||||
noteChanges: Record<string, Partial<Note>>
|
noteChanges: Record<string, Partial<Note>>
|
||||||
) => void;
|
) => void;
|
||||||
|
export type SelectionItemsRemoveEventHandler = (
|
||||||
|
tokenStateIds: string[],
|
||||||
|
noteIds: string[]
|
||||||
|
) => void;
|
||||||
|
Loading…
Reference in New Issue
Block a user