Respect active grid snap for wall dragging and angle
This commit is contained in:
@@ -18,10 +18,7 @@ import { markToolCancelConsumed } from '../../../hooks/use-keyboard'
|
||||
import { sfxEmitter } from '../../../lib/sfx-bus'
|
||||
import useEditor from '../../../store/use-editor'
|
||||
import { CursorSphere } from '../shared/cursor-sphere'
|
||||
|
||||
function snap(value: number) {
|
||||
return Math.round(value * 2) / 2
|
||||
}
|
||||
import { getWallGridStep, snapScalarToGrid } from './wall-drafting'
|
||||
|
||||
export const CurveWallTool: React.FC<{ node: WallNode }> = ({ node }) => {
|
||||
const activatedAtRef = useRef<number>(Date.now())
|
||||
@@ -76,15 +73,22 @@ export const CurveWallTool: React.FC<{ node: WallNode }> = ({ node }) => {
|
||||
}
|
||||
|
||||
const onGridMove = (event: GridEvent) => {
|
||||
const localX = shiftPressedRef.current ? event.localPosition[0] : snap(event.localPosition[0])
|
||||
const localZ = shiftPressedRef.current ? event.localPosition[2] : snap(event.localPosition[2])
|
||||
const snapStep = getWallGridStep()
|
||||
const localX = shiftPressedRef.current
|
||||
? event.localPosition[0]
|
||||
: snapScalarToGrid(event.localPosition[0], snapStep)
|
||||
const localZ = shiftPressedRef.current
|
||||
? event.localPosition[2]
|
||||
: snapScalarToGrid(event.localPosition[2], snapStep)
|
||||
|
||||
const offsetFromMidpoint =
|
||||
-(
|
||||
(localX - chord.midpoint.x) * chord.normal.x +
|
||||
(localZ - chord.midpoint.y) * chord.normal.y
|
||||
)
|
||||
const snappedOffset = shiftPressedRef.current ? offsetFromMidpoint : snap(offsetFromMidpoint)
|
||||
const snappedOffset = shiftPressedRef.current
|
||||
? offsetFromMidpoint
|
||||
: snapScalarToGrid(offsetFromMidpoint, snapStep)
|
||||
const nextCurveOffset = normalizeWallCurveOffset(node, Math.max(-maxCurveOffset, Math.min(maxCurveOffset, snappedOffset)))
|
||||
|
||||
if (
|
||||
|
||||
@@ -7,10 +7,7 @@ import { markToolCancelConsumed } from '../../../hooks/use-keyboard'
|
||||
import { sfxEmitter } from '../../../lib/sfx-bus'
|
||||
import useEditor from '../../../store/use-editor'
|
||||
import { CursorSphere } from '../shared/cursor-sphere'
|
||||
|
||||
function snap(value: number) {
|
||||
return Math.round(value * 2) / 2
|
||||
}
|
||||
import { getWallGridStep, snapScalarToGrid } from './wall-drafting'
|
||||
|
||||
function rotateVector([x, z]: [number, number], angle: number): [number, number] {
|
||||
const cos = Math.cos(angle)
|
||||
@@ -183,8 +180,9 @@ export const MoveWallTool: React.FC<{ node: WallNode }> = ({ node }) => {
|
||||
const onGridMove = (event: GridEvent) => {
|
||||
const rawX = event.localPosition[0]
|
||||
const rawZ = event.localPosition[2]
|
||||
const localX = shiftPressedRef.current ? rawX : snap(rawX)
|
||||
const localZ = shiftPressedRef.current ? rawZ : snap(rawZ)
|
||||
const snapStep = getWallGridStep()
|
||||
const localX = shiftPressedRef.current ? rawX : snapScalarToGrid(rawX, snapStep)
|
||||
const localZ = shiftPressedRef.current ? rawZ : snapScalarToGrid(rawZ, snapStep)
|
||||
|
||||
if (
|
||||
previousGridPosRef.current &&
|
||||
|
||||
@@ -18,6 +18,14 @@ export type WallPlanPoint = [number, number]
|
||||
export const WALL_GRID_STEP = 0.5
|
||||
export const WALL_JOIN_SNAP_RADIUS = 0.35
|
||||
export const WALL_MIN_LENGTH = 0.01
|
||||
const DEFAULT_WALL_ANGLE_SNAP_STEP = Math.PI / 4
|
||||
|
||||
const WALL_ANGLE_SNAP_BY_GRID_STEP: Record<number, number> = {
|
||||
0.5: Math.PI / 4,
|
||||
0.25: Math.PI / 8,
|
||||
0.1: Math.PI / 12,
|
||||
0.05: Math.PI / 36,
|
||||
}
|
||||
|
||||
type WallSplitIntersection = {
|
||||
wallId: WallNode['id']
|
||||
@@ -30,11 +38,11 @@ function distanceSquared(a: WallPlanPoint, b: WallPlanPoint): number {
|
||||
return dx * dx + dz * dz
|
||||
}
|
||||
|
||||
function getWallGridStep(): number {
|
||||
export function getWallGridStep(): number {
|
||||
return useEditor.getState().gridSnapStep
|
||||
}
|
||||
|
||||
function snapScalarToGrid(value: number, step = WALL_GRID_STEP): number {
|
||||
export function snapScalarToGrid(value: number, step = WALL_GRID_STEP): number {
|
||||
return Math.round(value / step) * step
|
||||
}
|
||||
|
||||
@@ -46,11 +54,12 @@ export function snapPointTo45Degrees(
|
||||
start: WallPlanPoint,
|
||||
cursor: WallPlanPoint,
|
||||
step = WALL_GRID_STEP,
|
||||
angleStep = DEFAULT_WALL_ANGLE_SNAP_STEP,
|
||||
): WallPlanPoint {
|
||||
const dx = cursor[0] - start[0]
|
||||
const dz = cursor[1] - start[1]
|
||||
const angle = Math.atan2(dz, dx)
|
||||
const snappedAngle = Math.round(angle / (Math.PI / 4)) * (Math.PI / 4)
|
||||
const snappedAngle = Math.round(angle / angleStep) * angleStep
|
||||
const distance = Math.sqrt(dx * dx + dz * dz)
|
||||
|
||||
return snapPointToGrid([
|
||||
@@ -59,6 +68,10 @@ export function snapPointTo45Degrees(
|
||||
], step)
|
||||
}
|
||||
|
||||
export function getWallAngleSnapStep(step = getWallGridStep()): number {
|
||||
return WALL_ANGLE_SNAP_BY_GRID_STEP[step] ?? DEFAULT_WALL_ANGLE_SNAP_STEP
|
||||
}
|
||||
|
||||
function projectPointOntoWall(point: WallPlanPoint, wall: WallNode): WallPlanPoint | null {
|
||||
const [x1, z1] = wall.start
|
||||
const [x2, z2] = wall.end
|
||||
@@ -358,8 +371,11 @@ export function snapWallDraftPoint(args: {
|
||||
}): WallPlanPoint {
|
||||
const { point, walls, start, angleSnap = false, ignoreWallIds } = args
|
||||
const step = getWallGridStep()
|
||||
const angleStep = getWallAngleSnapStep(step)
|
||||
const basePoint =
|
||||
start && angleSnap ? snapPointTo45Degrees(start, point, step) : snapPointToGrid(point, step)
|
||||
start && angleSnap
|
||||
? snapPointTo45Degrees(start, point, step, angleStep)
|
||||
: snapPointToGrid(point, step)
|
||||
|
||||
return (
|
||||
findWallSnapTarget(basePoint, walls, {
|
||||
|
||||
Reference in New Issue
Block a user