grungnet/src/hooks/useGridSnapping.ts
2021-08-04 08:32:27 +10:00

96 lines
2.5 KiB
TypeScript

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;