import Vector2 from "../helpers/Vector2"; import { getCellLocation, getNearestCellCoordinates, getCellCorners, } from "../helpers/grid"; import { useGrid, useGridOffset, useGridCellPixelSize, useGridCellPixelOffset, useGridSnappingSensitivity, } from "../contexts/GridContext"; /** * Returns a function that when called will snap a node to the current grid * @param {number=} snappingSensitivity 1 = Always snap, 0 = never snap if undefined the default user setting will be used * @param {boolean=} useCorners Snap to grid cell corners */ function useGridSnapping( snappingSensitivity: number | undefined = undefined, useCorners: boolean = true ) { 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(); const gridCellPixelSize = useGridCellPixelSize(); const gridCellPixelOffset = useGridCellPixelOffset(); /** * @param {Vector2} node The node to snap */ function snapPositionToGrid(position: Vector2) { // Account for grid offset let offsetPosition = Vector2.subtract( Vector2.subtract(position, gridOffset), gridCellPixelOffset ); const nearsetCell = getNearestCellCoordinates( grid, offsetPosition.x, offsetPosition.y, gridCellPixelSize ); const cellPosition = getCellLocation( grid, nearsetCell.x, nearsetCell.y, gridCellPixelSize ); const cellCorners = getCellCorners( grid, cellPosition.x, cellPosition.y, gridCellPixelSize ); const snapPoints = [cellPosition]; if (useCorners) { snapPoints.push(...cellCorners); } for (let snapPoint of snapPoints) { const distanceToSnapPoint = Vector2.distance(offsetPosition, snapPoint); if ( distanceToSnapPoint < Vector2.componentMin(gridCellPixelSize) * gridSnappingSensitivity ) { // Reverse grid offset let offsetSnapPoint = Vector2.add( Vector2.add(snapPoint, gridOffset), gridCellPixelOffset ); return offsetSnapPoint; } } return position; } return snapPositionToGrid; } export default useGridSnapping;