import type { WallNode } from '@pascal-app/core' /** * Default sill height (metres from the floor to the BOTTOM of a window) for a * fresh window that has no wall-face height yet — the off-wall ghost and the * floor-cursor placement use it so a new window floats slightly above the * ground rather than sitting on it. The committed Y is the window's CENTRE, so * callers add `height / 2`. An existing window keeps its own sill. */ export const DEFAULT_WINDOW_SILL_M = 0.5 /** * Converts wall-local (X along wall, Y = height above wall base) to world XYZ. * Wall XZ uses level-local coordinates (levels only offset in Y, not XZ). * Pass levelYOffset (the level group's current world Y) and slabElevation (the * wall mesh's Y within the level group) so the cursor lands at the correct world * height — matching how WallSystem positions the wall mesh at slabElevation. */ export function wallLocalToWorld( wallNode: WallNode, localX: number, localY: number, levelYOffset = 0, slabElevation = 0, ): [number, number, number] { const wallAngle = Math.atan2( wallNode.end[1] - wallNode.start[1], wallNode.end[0] - wallNode.start[0], ) return [ wallNode.start[0] + localX * Math.cos(wallAngle), slabElevation + localY + levelYOffset, wallNode.start[1] + localX * Math.sin(wallAngle), ] } /** * Clamps window center position so it stays fully within wall bounds. */ export function clampToWall( wallNode: WallNode, localX: number, localY: number, width: number, height: number, ): { clampedX: number; clampedY: number } { const dx = wallNode.end[0] - wallNode.start[0] const dz = wallNode.end[1] - wallNode.start[1] const wallLength = Math.sqrt(dx * dx + dz * dz) const wallHeight = wallNode.height ?? 2.5 const clampedX = Math.max(width / 2, Math.min(wallLength - width / 2, localX)) const clampedY = Math.max(height / 2, Math.min(wallHeight - height / 2, localY)) return { clampedX, clampedY } } /** * Wall-child overlap is shared by door + window placement (one source of * truth in `shared/wall-attach-target.ts`). Re-exported here so existing * `./window-math` importers don't change. */ export { hasWallChildOverlap } from '../shared/wall-attach-target'