From 6eb1f71bc28bb745cfa380a182f933803d638888 Mon Sep 17 00:00:00 2001 From: Mitchell McCaffrey Date: Wed, 4 Aug 2021 08:32:27 +1000 Subject: [PATCH] Add shortcut for disabling grid snapping --- src/components/konva/Transformer.tsx | 15 +++++-- src/components/tools/FogTool.tsx | 8 ++-- src/contexts/GridContext.tsx | 62 +++++++++++++++++++++++++++- src/helpers/KonvaBridge.tsx | 11 ++++- src/hooks/useGridSnapping.ts | 20 +++++---- src/shortcuts.ts | 1 + 6 files changed, 100 insertions(+), 17 deletions(-) diff --git a/src/components/konva/Transformer.tsx b/src/components/konva/Transformer.tsx index 137d86a..181d540 100644 --- a/src/components/konva/Transformer.tsx +++ b/src/components/konva/Transformer.tsx @@ -3,7 +3,10 @@ import { Transform } from "konva/lib/Util"; import { useEffect, useMemo, useRef } from "react"; import { Transformer as KonvaTransformer } from "react-konva"; -import { useGridCellPixelSize } from "../../contexts/GridContext"; +import { + useGridCellPixelSize, + useGridSnappingSensitivity, +} from "../../contexts/GridContext"; import { useSetPreventMapInteraction } from "../../contexts/MapInteractionContext"; import { roundTo } from "../../helpers/shared"; import Vector2 from "../../helpers/Vector2"; @@ -56,6 +59,10 @@ function Transformer({ }, [active, nodeRef, gridCellPixelSize]); const scale = parseGridScale(gridScale); + const snappingSensitivity = useGridSnappingSensitivity(); + // Clamp snapping to 0 to accound for -1 snapping override + const gridSnappingSensitivity = Math.max(snappingSensitivity, 0); + const anchorScale = useMemo(() => getAnchorImage(192, scaleDark), []); const anchorRotate = useMemo(() => getAnchorImage(192, rotateDark), []); @@ -192,8 +199,10 @@ function Transformer({ ); const distanceToSnap = Math.abs(snapBox.width - nearestCellWidth); let snapping = false; - if (distanceToSnap < gridCellAbsoluteSize.x * 0.1) { - // TODO: use global grid snapping value + if ( + distanceToSnap < + gridCellAbsoluteSize.x * gridSnappingSensitivity + ) { snapBox.width = nearestCellWidth; snapping = true; } diff --git a/src/components/tools/FogTool.tsx b/src/components/tools/FogTool.tsx index a7a2e4d..9ac7552 100644 --- a/src/components/tools/FogTool.tsx +++ b/src/components/tools/FogTool.tsx @@ -20,6 +20,7 @@ import { useGridStrokeWidth, useGridCellPixelOffset, useGridOffset, + useGridSnappingSensitivity, } from "../../contexts/GridContext"; import { useKeyboard } from "../../contexts/KeyboardContext"; @@ -93,9 +94,10 @@ function FogTool({ const gridCellPixelOffset = useGridCellPixelOffset(); const gridOffset = useGridOffset(); - const [gridSnappingSensitivity] = useSetting( - "map.gridSnappingSensitivity" - ); + const snappingSensitivity = useGridSnappingSensitivity(); + // Clamp snapping to 0 to accound for -1 snapping override + const gridSnappingSensitivity = Math.max(snappingSensitivity, 0); + const [showFogGuides] = useSetting("fog.showGuides"); const [editOpacity] = useSetting("fog.editOpacity"); const mapStageRef = useMapStage(); diff --git a/src/contexts/GridContext.tsx b/src/contexts/GridContext.tsx index 20ffc9d..cbd19de 100644 --- a/src/contexts/GridContext.tsx +++ b/src/contexts/GridContext.tsx @@ -3,8 +3,15 @@ import React, { useContext, useState, useEffect } from "react"; import Vector2 from "../helpers/Vector2"; import Size from "../helpers/Size"; import { getGridPixelSize, getCellPixelSize } from "../helpers/grid"; + import { Grid } from "../types/Grid"; +import useSetting from "../hooks/useSetting"; + +import shortcuts from "../shortcuts"; + +import { useBlur, useKeyboard } from "./KeyboardContext"; + /** * @typedef GridContextValue * @property {Grid} grid Base grid value @@ -23,6 +30,7 @@ type GridContextValue = { gridOffset: Vector2; gridStrokeWidth: number; gridCellPixelOffset: Vector2; + gridSnappingSensitivity: number; }; /** @@ -44,6 +52,7 @@ const defaultValue: GridContextValue = { gridOffset: new Vector2(0, 0), gridStrokeWidth: 0, gridCellPixelOffset: new Vector2(0, 0), + gridSnappingSensitivity: 0, }; export const GridContext = React.createContext(defaultValue.grid); @@ -63,6 +72,9 @@ export const GridStrokeWidthContext = React.createContext( export const GridCellPixelOffsetContext = React.createContext( defaultValue.gridCellPixelOffset ); +export const GridSnappingSensitivityContext = React.createContext( + defaultValue.gridSnappingSensitivity +); const defaultStrokeWidth = 1 / 10; @@ -138,6 +150,40 @@ export function GridProvider({ setGridCellPixelOffset(_gridCellPixelOffset); }, [grid, width, height]); + const [gridSnappingSensitivity, setGridSnappingSensitivity] = useState( + defaultValue.gridSnappingSensitivity + ); + const [defaultSnappingSensitivity] = useSetting( + "map.gridSnappingSensitivity" + ); + useEffect(() => { + if ( + gridSnappingSensitivity !== defaultSnappingSensitivity && + gridSnappingSensitivity !== -1 // Snapping not disabled + ) { + setGridSnappingSensitivity(defaultSnappingSensitivity); + } + }, [defaultSnappingSensitivity, gridSnappingSensitivity]); + + function handleKeyDown(event: KeyboardEvent) { + if (shortcuts.disableSnapping(event)) { + setGridSnappingSensitivity(-1); + } + } + + function handleKeyUp(event: KeyboardEvent) { + if (shortcuts.disableSnapping(event)) { + setGridSnappingSensitivity(defaultSnappingSensitivity); + } + } + + function handleBlur() { + setGridSnappingSensitivity(defaultSnappingSensitivity); + } + + useKeyboard(handleKeyDown, handleKeyUp); + useBlur(handleBlur); + return ( @@ -150,7 +196,11 @@ export function GridProvider({ - {children} + + {children} + @@ -220,3 +270,13 @@ export function useGridCellPixelOffset() { } return context; } + +export function useGridSnappingSensitivity() { + const context = useContext(GridSnappingSensitivityContext); + if (context === undefined) { + throw new Error( + "useGridSnappingSensitivity must be used within a GridProvider" + ); + } + return context; +} diff --git a/src/helpers/KonvaBridge.tsx b/src/helpers/KonvaBridge.tsx index 9f9b70d..bcd4e37 100644 --- a/src/helpers/KonvaBridge.tsx +++ b/src/helpers/KonvaBridge.tsx @@ -35,6 +35,7 @@ import { useGridCellPixelOffset, useGridOffset, useGridPixelSize, + useGridSnappingSensitivity, GridContext, GridPixelSizeContext, GridCellPixelSizeContext, @@ -42,6 +43,7 @@ import { GridOffsetContext, GridStrokeWidthContext, GridCellPixelOffsetContext, + GridSnappingSensitivityContext, } from "../contexts/GridContext"; import DatabaseContext, { useDatabase } from "../contexts/DatabaseContext"; @@ -83,6 +85,7 @@ function KonvaBridge({ const gridStrokeWidth = useGridStrokeWidth(); const gridCellPixelOffset = useGridCellPixelOffset(); const gridOffset = useGridOffset(); + const gridSnappingSensitivity = useGridSnappingSensitivity(); const database = useDatabase(); @@ -128,7 +131,13 @@ function KonvaBridge({ - {children} + + {children} + diff --git a/src/hooks/useGridSnapping.ts b/src/hooks/useGridSnapping.ts index 52676f2..6a9714b 100644 --- a/src/hooks/useGridSnapping.ts +++ b/src/hooks/useGridSnapping.ts @@ -5,13 +5,12 @@ import { getCellCorners, } from "../helpers/grid"; -import useSetting from "./useSetting"; - import { useGrid, useGridOffset, useGridCellPixelSize, useGridCellPixelOffset, + useGridSnappingSensitivity, } from "../contexts/GridContext"; /** @@ -23,13 +22,16 @@ function useGridSnapping( snappingSensitivity: number | undefined = undefined, useCorners: boolean = true ) { - const [defaultSnappingSensitivity] = useSetting( - "map.gridSnappingSensitivity" - ); - let gridSnappingSensitivity = - snappingSensitivity === undefined - ? defaultSnappingSensitivity - : snappingSensitivity; + const defaultSnappingSensitivity = useGridSnappingSensitivity(); + let gridSnappingSensitivity: number; + if (defaultSnappingSensitivity === -1) { + // Snapping disabled via shortcut + gridSnappingSensitivity = 0; + } else if (snappingSensitivity === undefined) { + gridSnappingSensitivity = defaultSnappingSensitivity; + } else { + gridSnappingSensitivity = snappingSensitivity; + } const grid = useGrid(); const gridOffset = useGridOffset(); diff --git a/src/shortcuts.ts b/src/shortcuts.ts index 7f2d9e0..f5e95b7 100644 --- a/src/shortcuts.ts +++ b/src/shortcuts.ts @@ -102,6 +102,7 @@ const shortcuts: Record = { copy, paste, delete: ({ key }) => key === "Backspace" || key === "Delete", + disableSnapping: ({ key }) => key === "Control" || key === "Meta", }; export default shortcuts;