@pascal-app/core 0.1.13 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/dist/events/bus.d.ts +15 -2
  2. package/dist/events/bus.d.ts.map +1 -1
  3. package/dist/hooks/scene-registry/scene-registry.d.ts +5 -1
  4. package/dist/hooks/scene-registry/scene-registry.d.ts.map +1 -1
  5. package/dist/hooks/scene-registry/scene-registry.js +10 -1
  6. package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts +8 -8
  7. package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts.map +1 -1
  8. package/dist/hooks/spatial-grid/spatial-grid-manager.js +88 -36
  9. package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts +1 -1
  10. package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts.map +1 -1
  11. package/dist/hooks/spatial-grid/spatial-grid-sync.js +16 -8
  12. package/dist/hooks/spatial-grid/spatial-grid.d.ts +3 -3
  13. package/dist/hooks/spatial-grid/spatial-grid.d.ts.map +1 -1
  14. package/dist/hooks/spatial-grid/spatial-grid.js +2 -2
  15. package/dist/hooks/spatial-grid/use-spatial-query.d.ts.map +1 -1
  16. package/dist/hooks/spatial-grid/wall-spatial-grid.d.ts +2 -2
  17. package/dist/hooks/spatial-grid/wall-spatial-grid.d.ts.map +1 -1
  18. package/dist/hooks/spatial-grid/wall-spatial-grid.js +2 -2
  19. package/dist/index.d.ts +6 -2
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +5 -1
  22. package/dist/lib/space-detection.d.ts.map +1 -1
  23. package/dist/lib/space-detection.js +3 -1
  24. package/dist/schema/collections.d.ts +11 -0
  25. package/dist/schema/collections.d.ts.map +1 -0
  26. package/dist/schema/collections.js +2 -0
  27. package/dist/schema/index.d.ts +11 -8
  28. package/dist/schema/index.d.ts.map +1 -1
  29. package/dist/schema/index.js +11 -7
  30. package/dist/schema/nodes/door.d.ts +78 -0
  31. package/dist/schema/nodes/door.d.ts.map +1 -0
  32. package/dist/schema/nodes/door.js +67 -0
  33. package/dist/schema/nodes/item.d.ts +234 -0
  34. package/dist/schema/nodes/item.d.ts.map +1 -1
  35. package/dist/schema/nodes/item.js +65 -1
  36. package/dist/schema/nodes/level.d.ts.map +1 -1
  37. package/dist/schema/nodes/level.js +11 -1
  38. package/dist/schema/nodes/roof-segment.d.ts +51 -0
  39. package/dist/schema/nodes/roof-segment.d.ts.map +1 -0
  40. package/dist/schema/nodes/roof-segment.js +36 -0
  41. package/dist/schema/nodes/roof.d.ts +1 -4
  42. package/dist/schema/nodes/roof.d.ts.map +1 -1
  43. package/dist/schema/nodes/roof.js +9 -16
  44. package/dist/schema/nodes/site.d.ts +46 -0
  45. package/dist/schema/nodes/site.d.ts.map +1 -1
  46. package/dist/schema/types.d.ts +191 -4
  47. package/dist/schema/types.d.ts.map +1 -1
  48. package/dist/schema/types.js +4 -0
  49. package/dist/store/actions/node-actions.d.ts.map +1 -1
  50. package/dist/store/actions/node-actions.js +23 -4
  51. package/dist/store/use-interactive.d.ts +18 -0
  52. package/dist/store/use-interactive.d.ts.map +1 -0
  53. package/dist/store/use-interactive.js +50 -0
  54. package/dist/store/use-scene.d.ts +10 -1
  55. package/dist/store/use-scene.d.ts.map +1 -1
  56. package/dist/store/use-scene.js +190 -57
  57. package/dist/systems/ceiling/ceiling-system.d.ts.map +1 -1
  58. package/dist/systems/ceiling/ceiling-system.js +5 -0
  59. package/dist/systems/door/door-system.d.ts +2 -0
  60. package/dist/systems/door/door-system.d.ts.map +1 -0
  61. package/dist/systems/door/door-system.js +211 -0
  62. package/dist/systems/item/item-system.js +3 -2
  63. package/dist/systems/roof/roof-system.d.ts +11 -3
  64. package/dist/systems/roof/roof-system.d.ts.map +1 -1
  65. package/dist/systems/roof/roof-system.js +705 -210
  66. package/dist/systems/slab/slab-system.js +3 -3
  67. package/dist/systems/wall/wall-footprint.d.ts +7 -0
  68. package/dist/systems/wall/wall-footprint.d.ts.map +1 -0
  69. package/dist/systems/wall/wall-footprint.js +49 -0
  70. package/dist/systems/wall/wall-mitering.js +2 -2
  71. package/dist/systems/wall/wall-system.d.ts.map +1 -1
  72. package/dist/systems/wall/wall-system.js +13 -50
  73. package/dist/systems/window/window-system.js +3 -3
  74. package/package.json +6 -6
@@ -1,5 +1,5 @@
1
1
  import type { ThreeEvent } from '@react-three/fiber';
2
- import type { BuildingNode, CeilingNode, ItemNode, LevelNode, RoofNode, SiteNode, SlabNode, WallNode, WindowNode, ZoneNode } from '../schema';
2
+ import type { BuildingNode, CeilingNode, DoorNode, ItemNode, LevelNode, RoofNode, RoofSegmentNode, SiteNode, SlabNode, WallNode, WindowNode, ZoneNode } from '../schema';
3
3
  import type { AnyNode } from '../schema/types';
4
4
  export interface GridEvent {
5
5
  position: [number, number, number];
@@ -22,7 +22,9 @@ export type ZoneEvent = NodeEvent<ZoneNode>;
22
22
  export type SlabEvent = NodeEvent<SlabNode>;
23
23
  export type CeilingEvent = NodeEvent<CeilingNode>;
24
24
  export type RoofEvent = NodeEvent<RoofNode>;
25
+ export type RoofSegmentEvent = NodeEvent<RoofSegmentNode>;
25
26
  export type WindowEvent = NodeEvent<WindowNode>;
27
+ export type DoorEvent = NodeEvent<DoorNode>;
26
28
  export declare const eventSuffixes: readonly ["click", "move", "enter", "leave", "pointerdown", "pointerup", "context-menu", "double-click"];
27
29
  export type EventSuffix = (typeof eventSuffixes)[number];
28
30
  type NodeEvents<T extends string, E> = {
@@ -39,6 +41,7 @@ export interface ThumbnailGenerateEvent {
39
41
  }
40
42
  type CameraControlEvents = {
41
43
  'camera-controls:view': CameraControlEvent;
44
+ 'camera-controls:focus': CameraControlEvent;
42
45
  'camera-controls:capture': CameraControlEvent;
43
46
  'camera-controls:top-view': undefined;
44
47
  'camera-controls:orbit-cw': undefined;
@@ -48,7 +51,17 @@ type CameraControlEvents = {
48
51
  type ToolEvents = {
49
52
  'tool:cancel': undefined;
50
53
  };
51
- type EditorEvents = GridEvents & NodeEvents<'wall', WallEvent> & NodeEvents<'item', ItemEvent> & NodeEvents<'site', SiteEvent> & NodeEvents<'building', BuildingEvent> & NodeEvents<'level', LevelEvent> & NodeEvents<'zone', ZoneEvent> & NodeEvents<'slab', SlabEvent> & NodeEvents<'ceiling', CeilingEvent> & NodeEvents<'roof', RoofEvent> & NodeEvents<'window', WindowEvent> & CameraControlEvents & ToolEvents;
54
+ type PresetEvents = {
55
+ 'preset:generate-thumbnail': {
56
+ presetId: string;
57
+ nodeId: string;
58
+ };
59
+ 'preset:thumbnail-updated': {
60
+ presetId: string;
61
+ thumbnailUrl: string;
62
+ };
63
+ };
64
+ type EditorEvents = GridEvents & NodeEvents<'wall', WallEvent> & NodeEvents<'item', ItemEvent> & NodeEvents<'site', SiteEvent> & NodeEvents<'building', BuildingEvent> & NodeEvents<'level', LevelEvent> & NodeEvents<'zone', ZoneEvent> & NodeEvents<'slab', SlabEvent> & NodeEvents<'ceiling', CeilingEvent> & NodeEvents<'roof', RoofEvent> & NodeEvents<'roof-segment', RoofSegmentEvent> & NodeEvents<'window', WindowEvent> & NodeEvents<'door', DoorEvent> & CameraControlEvents & ToolEvents & PresetEvents;
52
65
  export declare const emitter: import("mitt").Emitter<EditorEvents>;
53
66
  export {};
54
67
  //# sourceMappingURL=bus.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bus.d.ts","sourceRoot":"","sources":["../../src/events/bus.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bus.d.ts","sourceRoot":"","sources":["../../src/events/bus.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type * as THREE from "three";
1
+ import type * as THREE from 'three';
2
2
  export declare const sceneRegistry: {
3
3
  nodes: Map<string, THREE.Object3D<THREE.Object3DEventMap>>;
4
4
  byType: {
@@ -11,10 +11,14 @@ export declare const sceneRegistry: {
11
11
  slab: Set<string>;
12
12
  zone: Set<string>;
13
13
  roof: Set<string>;
14
+ 'roof-segment': Set<string>;
14
15
  scan: Set<string>;
15
16
  guide: Set<string>;
16
17
  window: Set<string>;
18
+ door: Set<string>;
17
19
  };
20
+ /** Remove all entries. Call when unloading a scene to prevent stale 3D refs. */
21
+ clear(): void;
18
22
  };
19
23
  export declare function useRegistry(id: string, type: keyof typeof sceneRegistry.byType, ref: React.RefObject<THREE.Object3D>): void;
20
24
  //# sourceMappingURL=scene-registry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scene-registry.d.ts","sourceRoot":"","sources":["../../../src/hooks/scene-registry/scene-registry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAEpC,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;CAoBzB,CAAC;AAEF,wBAAgB,WAAW,CACzB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,OAAO,aAAa,CAAC,MAAM,EACvC,GAAG,EAAE,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,QAkBrC"}
1
+ {"version":3,"file":"scene-registry.d.ts","sourceRoot":"","sources":["../../../src/hooks/scene-registry/scene-registry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAA;AAEnC,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;IAuBxB,gFAAgF;;CAOjF,CAAA;AAED,wBAAgB,WAAW,CACzB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,OAAO,aAAa,CAAC,MAAM,EACvC,GAAG,EAAE,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,QAkBrC"}
@@ -1,4 +1,4 @@
1
- import { useLayoutEffect } from "react";
1
+ import { useLayoutEffect } from 'react';
2
2
  export const sceneRegistry = {
3
3
  // Master lookup: ID -> Object3D
4
4
  nodes: new Map(),
@@ -14,9 +14,18 @@ export const sceneRegistry = {
14
14
  slab: new Set(),
15
15
  zone: new Set(),
16
16
  roof: new Set(),
17
+ 'roof-segment': new Set(),
17
18
  scan: new Set(),
18
19
  guide: new Set(),
19
20
  window: new Set(),
21
+ door: new Set(),
22
+ },
23
+ /** Remove all entries. Call when unloading a scene to prevent stale 3D refs. */
24
+ clear() {
25
+ this.nodes.clear();
26
+ for (const set of Object.values(this.byType)) {
27
+ set.clear();
28
+ }
20
29
  },
21
30
  };
22
31
  export function useRegistry(id, type, ref) {
@@ -20,14 +20,14 @@ export declare function itemOverlapsPolygon(position: [number, number, number],
20
20
  */
21
21
  export declare function wallOverlapsPolygon(start: [number, number], end: [number, number], polygon: Array<[number, number]>): boolean;
22
22
  export declare class SpatialGridManager {
23
- private cellSize;
24
- private floorGrids;
25
- private wallGrids;
26
- private walls;
27
- private slabsByLevel;
28
- private ceilingGrids;
29
- private ceilings;
30
- private itemCeilingMap;
23
+ private readonly floorGrids;
24
+ private readonly wallGrids;
25
+ private readonly walls;
26
+ private readonly slabsByLevel;
27
+ private readonly ceilingGrids;
28
+ private readonly ceilings;
29
+ private readonly itemCeilingMap;
30
+ private readonly cellSize;
31
31
  constructor(cellSize?: number);
32
32
  private getFloorGrid;
33
33
  private getWallGrid;
@@ -1 +1 @@
1
- {"version":3,"file":"spatial-grid-manager.d.ts","sourceRoot":"","sources":["../../../src/hooks/spatial-grid/spatial-grid-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"spatial-grid-manager.d.ts","sourceRoot":"","sources":["../../../src/hooks/spatial-grid/spatial-grid-manager.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { getScaledDimensions } from '../../schema';
1
2
  import { SpatialGrid } from './spatial-grid';
2
3
  import { WallSpatialGrid } from './wall-spatial-grid';
3
4
  // ============================================================================
@@ -12,7 +13,7 @@ export function pointInPolygon(px, pz, polygon) {
12
13
  for (let i = 0, j = n - 1; i < n; j = i++) {
13
14
  const xi = polygon[i][0], zi = polygon[i][1];
14
15
  const xj = polygon[j][0], zj = polygon[j][1];
15
- if ((zi > pz) !== (zj > pz) && px < ((xj - xi) * (pz - zi)) / (zj - zi) + xi) {
16
+ if (zi > pz !== zj > pz && px < ((xj - xi) * (pz - zi)) / (zj - zi) + xi) {
16
17
  inside = !inside;
17
18
  }
18
19
  }
@@ -45,13 +46,14 @@ function segmentsIntersect(ax1, az1, ax2, az2, bx1, bz1, bx2, bz2) {
45
46
  const d2 = cross(bx1, bz1, bx2, bz2, ax2, az2);
46
47
  const d3 = cross(ax1, az1, ax2, az2, bx1, bz1);
47
48
  const d4 = cross(ax1, az1, ax2, az2, bx2, bz2);
48
- if (((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) &&
49
- ((d3 > 0 && d4 < 0) || (d3 < 0 && d4 > 0))) {
49
+ if (((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) && ((d3 > 0 && d4 < 0) || (d3 < 0 && d4 > 0))) {
50
50
  return true;
51
51
  }
52
52
  // Collinear touching cases
53
- const onSeg = (px, pz, qx, qz, rx, rz) => Math.min(px, qx) <= rx && rx <= Math.max(px, qx) &&
54
- Math.min(pz, qz) <= rz && rz <= Math.max(pz, qz);
53
+ const onSeg = (px, pz, qx, qz, rx, rz) => Math.min(px, qx) <= rx &&
54
+ rx <= Math.max(px, qx) &&
55
+ Math.min(pz, qz) <= rz &&
56
+ rz <= Math.max(pz, qz);
55
57
  if (d1 === 0 && onSeg(bx1, bz1, bx2, bz2, ax1, az1))
56
58
  return true;
57
59
  if (d2 === 0 && onSeg(bx1, bz1, bx2, bz2, ax2, az2))
@@ -114,8 +116,10 @@ function segmentsCollinearAndOverlap(ax1, az1, ax2, az2, bx1, bz1, bx2, bz2) {
114
116
  return false; // Not collinear
115
117
  }
116
118
  // Check if a point is on segment b
117
- const onSegment = (px, pz, qx, qz, rx, rz) => Math.min(px, qx) - EPSILON <= rx && rx <= Math.max(px, qx) + EPSILON &&
118
- Math.min(pz, qz) - EPSILON <= rz && rz <= Math.max(pz, qz) + EPSILON;
119
+ const onSegment = (px, pz, qx, qz, rx, rz) => Math.min(px, qx) - EPSILON <= rx &&
120
+ rx <= Math.max(px, qx) + EPSILON &&
121
+ Math.min(pz, qz) - EPSILON <= rz &&
122
+ rz <= Math.max(pz, qz) + EPSILON;
119
123
  // BOTH endpoints of wall (a) must be on edge (b) for substantial overlap
120
124
  const a1OnB = onSegment(bx1, bz1, bx2, bz2, ax1, az1);
121
125
  const a2OnB = onSegment(bx1, bz1, bx2, bz2, ax2, az2);
@@ -132,11 +136,41 @@ function segmentsCollinearAndOverlap(ax1, az1, ax2, az2, bx1, bz1, bx2, bz2) {
132
136
  * is NOT considered overlapping (adjacent only).
133
137
  */
134
138
  export function wallOverlapsPolygon(start, end, polygon) {
135
- const startInside = pointInPolygon(start[0], start[1], polygon);
136
- const endInside = pointInPolygon(end[0], end[1], polygon);
137
- // At least one endpoint strictly inside the polygon
138
- if (startInside || endInside)
139
- return true;
139
+ const dx = end[0] - start[0];
140
+ const dz = end[1] - start[1];
141
+ const len = Math.sqrt(dx * dx + dz * dz);
142
+ // Nudge endpoint test points a tiny step inward along the wall direction before
143
+ // testing containment. pointInPolygon (ray casting) produces false positives for
144
+ // points exactly on polygon vertices or edges — specifically the minimum-z corner
145
+ // of an axis-aligned polygon returns "inside" because the ray hits the opposite
146
+ // vertical edge exactly at its base. Nudging by 1e-6 m avoids this: a wall that
147
+ // merely starts at a slab corner and extends outward will have its nudged point
148
+ // clearly outside, while a wall that genuinely starts inside stays inside.
149
+ if (len > 1e-10) {
150
+ const step = Math.min(1e-6, len * 0.01);
151
+ const nx = (dx / len) * step;
152
+ const nz = (dz / len) * step;
153
+ if (pointInPolygon(start[0] + nx, start[1] + nz, polygon))
154
+ return true;
155
+ if (pointInPolygon(end[0] - nx, end[1] - nz, polygon))
156
+ return true;
157
+ // Also nudge perpendicular to the wall (into the slab interior) for walls that
158
+ // lie exactly on the slab boundary. The along-wall nudge keeps points on the
159
+ // boundary where pointInPolygon is unreliable; a perpendicular inward nudge
160
+ // moves the point clearly inside (or outside) the polygon.
161
+ // Sample the wall at 1/4, 1/2, 3/4 positions with a perpendicular nudge.
162
+ const PERP_STEP = 1e-4;
163
+ const pnx = (-nz / step) * PERP_STEP; // perpendicular left
164
+ const pnz = (nx / step) * PERP_STEP;
165
+ for (const t of [0.25, 0.5, 0.75]) {
166
+ const bx = start[0] + dx * t;
167
+ const bz = start[1] + dz * t;
168
+ if (pointInPolygon(bx + pnx, bz + pnz, polygon))
169
+ return true;
170
+ if (pointInPolygon(bx - pnx, bz - pnz, polygon))
171
+ return true;
172
+ }
173
+ }
140
174
  // Check if midpoint is inside (catches walls crossing through)
141
175
  const midX = (start[0] + end[0]) / 2;
142
176
  const midZ = (start[1] + end[1]) / 2;
@@ -155,7 +189,6 @@ export function wallOverlapsPolygon(start, end, polygon) {
155
189
  return false;
156
190
  }
157
191
  export class SpatialGridManager {
158
- cellSize;
159
192
  floorGrids = new Map(); // levelId -> grid
160
193
  wallGrids = new Map(); // levelId -> wall grid
161
194
  walls = new Map(); // wallId -> wall data (for length calculations)
@@ -163,6 +196,7 @@ export class SpatialGridManager {
163
196
  ceilingGrids = new Map(); // ceilingId -> grid
164
197
  ceilings = new Map(); // ceilingId -> ceiling data
165
198
  itemCeilingMap = new Map(); // itemId -> ceilingId (reverse lookup)
199
+ cellSize;
166
200
  constructor(cellSize = 0.5) {
167
201
  this.cellSize = cellSize;
168
202
  }
@@ -222,14 +256,14 @@ export class SpatialGridManager {
222
256
  if (wallId && this.walls.has(wallId)) {
223
257
  const wallLength = this.getWallLength(wallId);
224
258
  if (wallLength > 0) {
225
- const [width, height] = item.asset.dimensions;
259
+ const [width, height] = getScaledDimensions(item);
226
260
  const halfW = width / wallLength / 2;
227
261
  // Calculate t from local X position (position[0] is distance along wall)
228
262
  const t = item.position[0] / wallLength;
229
263
  // position[1] is the bottom of the item
230
264
  this.getWallGrid(levelId).insert({
231
265
  itemId: item.id,
232
- wallId: wallId,
266
+ wallId,
233
267
  tStart: t - halfW,
234
268
  tEnd: t + halfW,
235
269
  yStart: item.position[1],
@@ -244,13 +278,13 @@ export class SpatialGridManager {
244
278
  // Ceiling item - use parentId as the ceiling ID
245
279
  const ceilingId = item.parentId;
246
280
  if (ceilingId && this.ceilings.has(ceilingId)) {
247
- this.getCeilingGrid(ceilingId).insert(item.id, item.position, item.asset.dimensions, item.rotation);
281
+ this.getCeilingGrid(ceilingId).insert(item.id, item.position, getScaledDimensions(item), item.rotation);
248
282
  this.itemCeilingMap.set(item.id, ceilingId);
249
283
  }
250
284
  }
251
285
  else if (!item.asset.attachTo) {
252
286
  // Floor item
253
- this.getFloorGrid(levelId).insert(item.id, item.position, item.asset.dimensions, item.rotation);
287
+ this.getFloorGrid(levelId).insert(item.id, item.position, getScaledDimensions(item), item.rotation);
254
288
  }
255
289
  }
256
290
  }
@@ -274,14 +308,14 @@ export class SpatialGridManager {
274
308
  if (wallId && this.walls.has(wallId)) {
275
309
  const wallLength = this.getWallLength(wallId);
276
310
  if (wallLength > 0) {
277
- const [width, height] = item.asset.dimensions;
311
+ const [width, height] = getScaledDimensions(item);
278
312
  const halfW = width / wallLength / 2;
279
313
  // Calculate t from local X position (position[0] is distance along wall)
280
314
  const t = item.position[0] / wallLength;
281
315
  // position[1] is the bottom of the item
282
316
  this.getWallGrid(levelId).insert({
283
317
  itemId: item.id,
284
- wallId: wallId,
318
+ wallId,
285
319
  tStart: t - halfW,
286
320
  tEnd: t + halfW,
287
321
  yStart: item.position[1],
@@ -302,12 +336,12 @@ export class SpatialGridManager {
302
336
  // Insert into new ceiling grid
303
337
  const ceilingId = item.parentId;
304
338
  if (ceilingId && this.ceilings.has(ceilingId)) {
305
- this.getCeilingGrid(ceilingId).insert(item.id, item.position, item.asset.dimensions, item.rotation);
339
+ this.getCeilingGrid(ceilingId).insert(item.id, item.position, getScaledDimensions(item), item.rotation);
306
340
  this.itemCeilingMap.set(item.id, ceilingId);
307
341
  }
308
342
  }
309
343
  else if (!item.asset.attachTo) {
310
- this.getFloorGrid(levelId).update(item.id, item.position, item.asset.dimensions, item.rotation);
344
+ this.getFloorGrid(levelId).update(item.id, item.position, getScaledDimensions(item), item.rotation);
311
345
  }
312
346
  }
313
347
  }
@@ -406,9 +440,10 @@ export class SpatialGridManager {
406
440
  const slabMap = this.slabsByLevel.get(levelId);
407
441
  if (!slabMap)
408
442
  return 0;
409
- let maxElevation = -Infinity;
443
+ let maxElevation = Number.NEGATIVE_INFINITY;
410
444
  for (const slab of slabMap.values()) {
411
- if (slab.polygon.length >= 3 && itemOverlapsPolygon(position, dimensions, rotation, slab.polygon, 0.01)) {
445
+ if (slab.polygon.length >= 3 &&
446
+ itemOverlapsPolygon(position, dimensions, rotation, slab.polygon, 0.01)) {
412
447
  // Check if item is entirely within a hole (if so, ignore this slab)
413
448
  // We consider it entirely in a hole if the item center is in the hole
414
449
  let inHole = false;
@@ -428,7 +463,7 @@ export class SpatialGridManager {
428
463
  }
429
464
  }
430
465
  }
431
- return maxElevation === -Infinity ? 0 : maxElevation;
466
+ return maxElevation === Number.NEGATIVE_INFINITY ? 0 : maxElevation;
432
467
  }
433
468
  /**
434
469
  * Get the slab elevation for a wall by checking if it overlaps with any slab polygon (excluding holes).
@@ -439,31 +474,48 @@ export class SpatialGridManager {
439
474
  const slabMap = this.slabsByLevel.get(levelId);
440
475
  if (!slabMap)
441
476
  return 0;
442
- let maxElevation = -Infinity;
477
+ let maxElevation = Number.NEGATIVE_INFINITY;
443
478
  for (const slab of slabMap.values()) {
444
479
  if (slab.polygon.length < 3)
445
480
  continue;
446
- if (wallOverlapsPolygon(start, end, slab.polygon)) {
447
- // Check if wall midpoint is in a hole (if so, ignore this slab)
481
+ if (!wallOverlapsPolygon(start, end, slab.polygon))
482
+ continue;
483
+ const holes = slab.holes || [];
484
+ if (holes.length === 0) {
485
+ // No holes: wall is on this slab
486
+ const elevation = slab.elevation ?? 0.05;
487
+ if (elevation > maxElevation)
488
+ maxElevation = elevation;
489
+ continue;
490
+ }
491
+ // Sample multiple points along the wall to check whether any portion lies on
492
+ // solid slab (not inside any hole). Checking only the midpoint fails when the
493
+ // midpoint falls in a staircase hole but the wall's endpoints are on solid slab.
494
+ const dx = end[0] - start[0];
495
+ const dz = end[1] - start[1];
496
+ let hasValidPoint = false;
497
+ for (const t of [0, 0.25, 0.5, 0.75, 1]) {
498
+ const px = start[0] + dx * t;
499
+ const pz = start[1] + dz * t;
448
500
  let inHole = false;
449
- const midX = (start[0] + end[0]) / 2;
450
- const midZ = (start[1] + end[1]) / 2;
451
- const holes = slab.holes || [];
452
501
  for (const hole of holes) {
453
- if (hole.length >= 3 && pointInPolygon(midX, midZ, hole)) {
502
+ if (hole.length >= 3 && pointInPolygon(px, pz, hole)) {
454
503
  inHole = true;
455
504
  break;
456
505
  }
457
506
  }
458
507
  if (!inHole) {
459
- const elevation = slab.elevation ?? 0.05;
460
- if (elevation > maxElevation) {
461
- maxElevation = elevation;
462
- }
508
+ hasValidPoint = true;
509
+ break;
463
510
  }
464
511
  }
512
+ if (hasValidPoint) {
513
+ const elevation = slab.elevation ?? 0.05;
514
+ if (elevation > maxElevation)
515
+ maxElevation = elevation;
516
+ }
465
517
  }
466
- return maxElevation === -Infinity ? 0 : maxElevation;
518
+ return maxElevation === Number.NEGATIVE_INFINITY ? 0 : maxElevation;
467
519
  }
468
520
  /**
469
521
  * Check if an item can be placed on a ceiling.
@@ -1,4 +1,4 @@
1
- import type { AnyNode } from '../../schema';
1
+ import { type AnyNode } from '../../schema';
2
2
  export declare function resolveLevelId(node: AnyNode, nodes: Record<string, AnyNode>): string;
3
3
  export declare function initSpatialGridSync(): void;
4
4
  //# sourceMappingURL=spatial-grid-sync.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"spatial-grid-sync.d.ts","sourceRoot":"","sources":["../../../src/hooks/spatial-grid/spatial-grid-sync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAA2C,MAAM,cAAc,CAAA;AAIpF,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAmBpF;AAGD,wBAAgB,mBAAmB,SAmElC"}
1
+ {"version":3,"file":"spatial-grid-sync.d.ts","sourceRoot":"","sources":["../../../src/hooks/spatial-grid/spatial-grid-sync.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EAMb,MAAM,cAAc,CAAA;AAQrB,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAmBpF;AAGD,wBAAgB,mBAAmB,SA8ElC"}
@@ -1,5 +1,6 @@
1
+ import { getScaledDimensions, } from '../../schema';
1
2
  import useScene from '../../store/use-scene';
2
- import { itemOverlapsPolygon, spatialGridManager, wallOverlapsPolygon } from './spatial-grid-manager';
3
+ import { itemOverlapsPolygon, spatialGridManager, wallOverlapsPolygon, } from './spatial-grid-manager';
3
4
  export function resolveLevelId(node, nodes) {
4
5
  // If the node itself is a level
5
6
  if (node.type === 'level')
@@ -11,11 +12,11 @@ export function resolveLevelId(node, nodes) {
11
12
  if (current.type === 'level')
12
13
  return current.id;
13
14
  // Find parent (you might need to add parentId to your schema or derive it)
14
- if (!current.parentId) {
15
- current = undefined;
15
+ if (current.parentId) {
16
+ current = nodes[current.parentId];
16
17
  }
17
18
  else {
18
- current = nodes[current.parentId];
19
+ current = undefined;
19
20
  }
20
21
  }
21
22
  return 'default'; // fallback for orphaned items
@@ -61,16 +62,23 @@ export function initSpatialGridSync() {
61
62
  if (!prev)
62
63
  continue;
63
64
  if (node.type === 'item' && prev.type === 'item') {
64
- if (!arraysEqual(node.position, prev.position) ||
65
- !arraysEqual(node.rotation, prev.rotation) ||
65
+ if (!(arraysEqual(node.position, prev.position) &&
66
+ arraysEqual(node.rotation, prev.rotation) &&
67
+ arraysEqual(node.scale, prev.scale)) ||
66
68
  node.parentId !== prev.parentId ||
67
69
  node.side !== prev.side) {
68
70
  const levelId = resolveLevelId(node, state.nodes);
69
71
  spatialGridManager.handleNodeUpdated(node, levelId);
72
+ // Scale changes affect footprint size — mark dirty so slab elevation recalculates
73
+ if (!arraysEqual(node.scale, prev.scale)) {
74
+ markDirty(node.id);
75
+ }
70
76
  }
71
77
  }
72
78
  else if (node.type === 'slab' && prev.type === 'slab') {
73
- if (node.polygon !== prev.polygon || node.elevation !== prev.elevation) {
79
+ if (node.polygon !== prev.polygon ||
80
+ node.elevation !== prev.elevation ||
81
+ node.holes !== prev.holes) {
74
82
  const levelId = resolveLevelId(node, state.nodes);
75
83
  spatialGridManager.handleNodeUpdated(node, levelId);
76
84
  // Mark nodes overlapping old polygon and new polygon as dirty
@@ -99,7 +107,7 @@ function markNodesOverlappingSlab(slab, nodes, markDirty) {
99
107
  continue;
100
108
  if (resolveLevelId(node, nodes) !== slabLevelId)
101
109
  continue;
102
- if (itemOverlapsPolygon(item.position, item.asset.dimensions, item.rotation, slab.polygon, 0.01)) {
110
+ if (itemOverlapsPolygon(item.position, getScaledDimensions(item), item.rotation, slab.polygon, 0.01)) {
103
111
  markDirty(node.id);
104
112
  }
105
113
  }
@@ -2,9 +2,9 @@ interface SpatialGridConfig {
2
2
  cellSize: number;
3
3
  }
4
4
  export declare class SpatialGrid {
5
- private config;
6
- private cells;
7
- private itemCells;
5
+ private readonly cells;
6
+ private readonly itemCells;
7
+ private readonly config;
8
8
  constructor(config: SpatialGridConfig);
9
9
  private posToCell;
10
10
  private cellKey;
@@ -1 +1 @@
1
- {"version":3,"file":"spatial-grid.d.ts","sourceRoot":"","sources":["../../../src/hooks/spatial-grid/spatial-grid.ts"],"names":[],"mappings":"AAMA,UAAU,iBAAiB;IACzB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,qBAAa,WAAW;IAIV,OAAO,CAAC,MAAM;IAH1B,OAAO,CAAC,KAAK,CAA+B;IAC5C,OAAO,CAAC,SAAS,CAAkC;gBAE/B,MAAM,EAAE,iBAAiB;IAE7C,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,OAAO;IAKf,OAAO,CAAC,YAAY;IAsCpB,MAAM,CACJ,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAClC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EACpC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;IAepC,MAAM,CAAC,MAAM,EAAE,MAAM;IAiBrB,MAAM,CACJ,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAClC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EACpC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;IAOpC,QAAQ,CACN,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAClC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EACpC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAClC,SAAS,GAAE,MAAM,EAAO,GACvB;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,WAAW,EAAE,MAAM,EAAE,CAAA;KAAE;IAuB5C,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;IAkB3D,YAAY,IAAI,MAAM;CAGvB"}
1
+ {"version":3,"file":"spatial-grid.d.ts","sourceRoot":"","sources":["../../../src/hooks/spatial-grid/spatial-grid.ts"],"names":[],"mappings":"AAMA,UAAU,iBAAiB;IACzB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA+B;IACrD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkC;IAE5D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;gBAE9B,MAAM,EAAE,iBAAiB;IAIrC,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,OAAO;IAKf,OAAO,CAAC,YAAY;IAsCpB,MAAM,CACJ,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAClC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EACpC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;IAepC,MAAM,CAAC,MAAM,EAAE,MAAM;IAiBrB,MAAM,CACJ,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAClC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EACpC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;IAOpC,QAAQ,CACN,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAClC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EACpC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAClC,SAAS,GAAE,MAAM,EAAO,GACvB;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,WAAW,EAAE,MAAM,EAAE,CAAA;KAAE;IAuB5C,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;IAkB3D,YAAY,IAAI,MAAM;CAGvB"}
@@ -1,7 +1,7 @@
1
1
  export class SpatialGrid {
2
- config;
3
2
  cells = new Map();
4
3
  itemCells = new Map(); // reverse lookup
4
+ config;
5
5
  constructor(config) {
6
6
  this.config = config;
7
7
  }
@@ -48,7 +48,7 @@ export class SpatialGrid {
48
48
  if (!this.cells.has(key)) {
49
49
  this.cells.set(key, { itemIds: new Set() });
50
50
  }
51
- this.cells.get(key).itemIds.add(itemId);
51
+ this.cells.get(key)?.itemIds.add(itemId);
52
52
  }
53
53
  }
54
54
  // Remove an item
@@ -1 +1 @@
1
- {"version":3,"file":"use-spatial-query.d.ts","sourceRoot":"","sources":["../../../src/hooks/spatial-grid/use-spatial-query.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAGpE,wBAAgB,eAAe;+BAGhB,SAAS,CAAC,IAAI,CAAC,YACd,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,cACtB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,YAC1B,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,cACtB,MAAM,EAAE;;;;8BASX,SAAS,CAAC,IAAI,CAAC,UAChB,QAAQ,CAAC,IAAI,CAAC,UACd,MAAM,UACN,MAAM,cACF,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,eACxB,MAAM,GAAG,WAAW,SACzB,OAAO,GAAG,MAAM,cACX,MAAM,EAAE;;;;;;;;;mCAkBT,WAAW,CAAC,IAAI,CAAC,YAClB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,cACtB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,YAC1B,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,cACtB,MAAM,EAAE;;;;EAQzB"}
1
+ {"version":3,"file":"use-spatial-query.d.ts","sourceRoot":"","sources":["../../../src/hooks/spatial-grid/use-spatial-query.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAGpE,wBAAgB,eAAe;+BAGhB,SAAS,CAAC,IAAI,CAAC,YACd,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,cACtB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,YAC1B,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,cACtB,MAAM,EAAE;;;;8BASX,SAAS,CAAC,IAAI,CAAC,UAChB,QAAQ,CAAC,IAAI,CAAC,UACd,MAAM,UACN,MAAM,cACF,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,eACxB,MAAM,GAAG,WAAW,SACzB,OAAO,GAAG,MAAM,cACX,MAAM,EAAE;;;;;;;;;mCAkBT,WAAW,CAAC,IAAI,CAAC,YAClB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,cACtB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,YAC1B,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,cACtB,MAAM,EAAE;;;;EAczB"}
@@ -11,8 +11,8 @@ interface WallItemPlacement {
11
11
  side?: WallSide;
12
12
  }
13
13
  export declare class WallSpatialGrid {
14
- private wallItems;
15
- private itemToWall;
14
+ private readonly wallItems;
15
+ private readonly itemToWall;
16
16
  /**
17
17
  * Check if an item can be placed on a wall with auto-adjustment for vertical position
18
18
  * @param wallId - The wall to place on
@@ -1 +1 @@
1
- {"version":3,"file":"wall-spatial-grid.d.ts","sourceRoot":"","sources":["../../../src/hooks/spatial-grid/wall-spatial-grid.ts"],"names":[],"mappings":"AAAA,KAAK,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAA;AAChC,KAAK,UAAU,GAAG,MAAM,GAAG,WAAW,CAAA;AAQtC,UAAU,iBAAiB;IACzB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,IAAI,CAAC,EAAE,QAAQ,CAAA;CAChB;AAgCD,qBAAa,eAAe;IAC1B,OAAO,CAAC,SAAS,CAAyC;IAC1D,OAAO,CAAC,UAAU,CAA4B;IAE9C;;;;;;;;;;;;;OAaG;IACH,cAAc,CACZ,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,UAAU,GAAE,UAAmB,EAC/B,IAAI,CAAC,EAAE,QAAQ,EACf,SAAS,GAAE,MAAM,EAAO,GACvB;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,WAAW,EAAE,MAAM,EAAE,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,OAAO,CAAA;KAAE;IAsCrF;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IA0BzB,MAAM,CAAC,SAAS,EAAE,iBAAiB;IAUnC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IASrC,cAAc,CAAC,MAAM,EAAE,MAAM;IAQ7B,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;IAapC,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIlD,KAAK;CAIN"}
1
+ {"version":3,"file":"wall-spatial-grid.d.ts","sourceRoot":"","sources":["../../../src/hooks/spatial-grid/wall-spatial-grid.ts"],"names":[],"mappings":"AAAA,KAAK,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAA;AAChC,KAAK,UAAU,GAAG,MAAM,GAAG,WAAW,CAAA;AAQtC,UAAU,iBAAiB;IACzB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,IAAI,CAAC,EAAE,QAAQ,CAAA;CAChB;AAgCD,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyC;IACnE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA4B;IAEvD;;;;;;;;;;;;;OAaG;IACH,cAAc,CACZ,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,UAAU,GAAE,UAAmB,EAC/B,IAAI,CAAC,EAAE,QAAQ,EACf,SAAS,GAAE,MAAM,EAAO,GACvB;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,WAAW,EAAE,MAAM,EAAE,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,OAAO,CAAA;KAAE;IAsCrF;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IA0BzB,MAAM,CAAC,SAAS,EAAE,iBAAiB;IAUnC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IASrC,cAAc,CAAC,MAAM,EAAE,MAAM;IAQ7B,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;IAapC,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIlD,KAAK;CAIN"}
@@ -89,7 +89,7 @@ export class WallSpatialGrid {
89
89
  }
90
90
  // Both are 'wall-side' - only conflict if they're on the same side
91
91
  // If either side is undefined, be conservative and assume conflict
92
- if (!newSide || !existing.side) {
92
+ if (!(newSide && existing.side)) {
93
93
  return true;
94
94
  }
95
95
  return newSide === existing.side;
@@ -99,7 +99,7 @@ export class WallSpatialGrid {
99
99
  if (!this.wallItems.has(wallId)) {
100
100
  this.wallItems.set(wallId, []);
101
101
  }
102
- this.wallItems.get(wallId).push(placement);
102
+ this.wallItems.get(wallId)?.push(placement);
103
103
  this.itemToWall.set(itemId, wallId);
104
104
  }
105
105
  remove(wallId, itemId) {
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export type { BuildingEvent, CameraControlEvent, CeilingEvent, EventSuffix, GridEvent, ItemEvent, LevelEvent, NodeEvent, RoofEvent, SiteEvent, SlabEvent, WallEvent, WindowEvent, ZoneEvent, } from './events/bus';
1
+ export type { BuildingEvent, CameraControlEvent, CeilingEvent, DoorEvent, EventSuffix, GridEvent, ItemEvent, LevelEvent, NodeEvent, RoofEvent, RoofSegmentEvent, SiteEvent, SlabEvent, WallEvent, WindowEvent, ZoneEvent, } from './events/bus';
2
2
  export { emitter, eventSuffixes } from './events/bus';
3
3
  export { sceneRegistry, useRegistry, } from './hooks/scene-registry/scene-registry';
4
4
  export { pointInPolygon, spatialGridManager } from './hooks/spatial-grid/spatial-grid-manager';
@@ -7,11 +7,15 @@ export { useSpatialQuery } from './hooks/spatial-grid/use-spatial-query';
7
7
  export { loadAssetUrl, saveAsset } from './lib/asset-storage';
8
8
  export { detectSpacesForLevel, initSpaceDetectionSync, type Space, wallTouchesOthers, } from './lib/space-detection';
9
9
  export * from './schema';
10
- export { default as useScene } from './store/use-scene';
10
+ export { type ControlValue, type ItemInteractiveState, useInteractive, } from './store/use-interactive';
11
+ export { clearSceneHistory, default as useScene } from './store/use-scene';
11
12
  export { CeilingSystem } from './systems/ceiling/ceiling-system';
13
+ export { DoorSystem } from './systems/door/door-system';
12
14
  export { ItemSystem } from './systems/item/item-system';
13
15
  export { RoofSystem } from './systems/roof/roof-system';
14
16
  export { SlabSystem } from './systems/slab/slab-system';
17
+ export { DEFAULT_WALL_HEIGHT, DEFAULT_WALL_THICKNESS, getWallPlanFootprint, getWallThickness, } from './systems/wall/wall-footprint';
18
+ export { calculateLevelMiters, type Point2D, pointToKey, type WallMiterData, } from './systems/wall/wall-mitering';
15
19
  export { WallSystem } from './systems/wall/wall-system';
16
20
  export { WindowSystem } from './systems/window/window-system';
17
21
  export { isObject } from './utils/types';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,WAAW,EACX,SAAS,EACT,SAAS,EACT,UAAU,EACV,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,WAAW,EACX,SAAS,GACV,MAAM,cAAc,CAAA;AAErB,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAErD,OAAO,EACL,aAAa,EACb,WAAW,GACZ,MAAM,uCAAuC,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAA;AAC9F,OAAO,EACL,mBAAmB,EACnB,cAAc,GACf,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,wCAAwC,CAAA;AAExE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAE7D,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,KAAK,KAAK,EACV,iBAAiB,GAClB,MAAM,uBAAuB,CAAA;AAE9B,cAAc,UAAU,CAAA;AACxB,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAEvD,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAA;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAA;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,WAAW,EACX,SAAS,EACT,SAAS,EACT,UAAU,EACV,SAAS,EACT,SAAS,EACT,gBAAgB,EAChB,SAAS,EACT,SAAS,EACT,SAAS,EACT,WAAW,EACX,SAAS,GACV,MAAM,cAAc,CAAA;AAErB,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAErD,OAAO,EACL,aAAa,EACb,WAAW,GACZ,MAAM,uCAAuC,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAA;AAC9F,OAAO,EACL,mBAAmB,EACnB,cAAc,GACf,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,wCAAwC,CAAA;AAExE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAE7D,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,KAAK,KAAK,EACV,iBAAiB,GAClB,MAAM,uBAAuB,CAAA;AAE9B,cAAc,UAAU,CAAA;AACxB,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,cAAc,GACf,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,iBAAiB,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE1E,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAA;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,+BAA+B,CAAA;AACtC,OAAO,EACL,oBAAoB,EACpB,KAAK,OAAO,EACZ,UAAU,EACV,KAAK,aAAa,GACnB,MAAM,8BAA8B,CAAA;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAA;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA"}
package/dist/index.js CHANGED
@@ -12,12 +12,16 @@ export { loadAssetUrl, saveAsset } from './lib/asset-storage';
12
12
  export { detectSpacesForLevel, initSpaceDetectionSync, wallTouchesOthers, } from './lib/space-detection';
13
13
  // Schema
14
14
  export * from './schema';
15
- export { default as useScene } from './store/use-scene';
15
+ export { useInteractive, } from './store/use-interactive';
16
+ export { clearSceneHistory, default as useScene } from './store/use-scene';
16
17
  // Systems
17
18
  export { CeilingSystem } from './systems/ceiling/ceiling-system';
19
+ export { DoorSystem } from './systems/door/door-system';
18
20
  export { ItemSystem } from './systems/item/item-system';
19
21
  export { RoofSystem } from './systems/roof/roof-system';
20
22
  export { SlabSystem } from './systems/slab/slab-system';
23
+ export { DEFAULT_WALL_HEIGHT, DEFAULT_WALL_THICKNESS, getWallPlanFootprint, getWallThickness, } from './systems/wall/wall-footprint';
24
+ export { calculateLevelMiters, pointToKey, } from './systems/wall/wall-mitering';
21
25
  export { WallSystem } from './systems/wall/wall-system';
22
26
  export { WindowSystem } from './systems/window/window-system';
23
27
  export { isObject } from './utils/types';
@@ -1 +1 @@
1
- {"version":3,"file":"space-detection.d.ts","sourceRoot":"","sources":["../../src/lib/space-detection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAMzC,MAAM,MAAM,KAAK,GAAG;IAClB,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAChC,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,UAAU,EAAE,OAAO,CAAA;CACpB,CAAA;AAMD;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,GAAG,EAAE,iBAAiB;AAClC,WAAW,EAAE,GAAG,GACf,MAAM,IAAI,CAgGZ;AA+DD,KAAK,cAAc,GAAG;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,CAAA;IAC9C,QAAQ,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,CAAA;CAC9C,CAAA;AAMD;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,QAAQ,EAAE,EACjB,cAAc,GAAE,MAAY,GAC3B;IACD,WAAW,EAAE,cAAc,EAAE,CAAA;IAC7B,MAAM,EAAE,KAAK,EAAE,CAAA;CAChB,CAqBA;AAsWD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,OAAO,CAkBjF"}
1
+ {"version":3,"file":"space-detection.d.ts","sourceRoot":"","sources":["../../src/lib/space-detection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAMzC,MAAM,MAAM,KAAK,GAAG;IAClB,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAChC,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,UAAU,EAAE,OAAO,CAAA;CACpB,CAAA;AAMD;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,GAAG,EAAE,iBAAiB;AAClC,WAAW,EAAE,GAAG,GACf,MAAM,IAAI,CAkGZ;AA+DD,KAAK,cAAc,GAAG;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,CAAA;IAC9C,QAAQ,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,CAAA;CAC9C,CAAA;AAMD;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,QAAQ,EAAE,EACjB,cAAc,SAAM,GACnB;IACD,WAAW,EAAE,cAAc,EAAE,CAAA;IAC7B,MAAM,EAAE,KAAK,EAAE,CAAA;CAChB,CAqBA;AAsWD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,OAAO,CAkBjF"}