@pascal-app/core 0.1.13 → 0.2.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.
- package/dist/events/bus.d.ts +14 -2
- package/dist/events/bus.d.ts.map +1 -1
- package/dist/hooks/scene-registry/scene-registry.d.ts +5 -1
- package/dist/hooks/scene-registry/scene-registry.d.ts.map +1 -1
- package/dist/hooks/scene-registry/scene-registry.js +10 -1
- package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts +8 -8
- package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/spatial-grid-manager.js +88 -36
- package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts +1 -1
- package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/spatial-grid-sync.js +16 -8
- package/dist/hooks/spatial-grid/spatial-grid.d.ts +3 -3
- package/dist/hooks/spatial-grid/spatial-grid.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/spatial-grid.js +2 -2
- package/dist/hooks/spatial-grid/use-spatial-query.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/wall-spatial-grid.d.ts +2 -2
- package/dist/hooks/spatial-grid/wall-spatial-grid.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/wall-spatial-grid.js +2 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/lib/space-detection.d.ts.map +1 -1
- package/dist/lib/space-detection.js +1 -1
- package/dist/schema/collections.d.ts +11 -0
- package/dist/schema/collections.d.ts.map +1 -0
- package/dist/schema/collections.js +2 -0
- package/dist/schema/index.d.ts +11 -8
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +11 -7
- package/dist/schema/nodes/door.d.ts +78 -0
- package/dist/schema/nodes/door.d.ts.map +1 -0
- package/dist/schema/nodes/door.js +67 -0
- package/dist/schema/nodes/item.d.ts +234 -0
- package/dist/schema/nodes/item.d.ts.map +1 -1
- package/dist/schema/nodes/item.js +65 -1
- package/dist/schema/nodes/level.d.ts.map +1 -1
- package/dist/schema/nodes/level.js +11 -1
- package/dist/schema/nodes/roof-segment.d.ts +51 -0
- package/dist/schema/nodes/roof-segment.d.ts.map +1 -0
- package/dist/schema/nodes/roof-segment.js +36 -0
- package/dist/schema/nodes/roof.d.ts +1 -4
- package/dist/schema/nodes/roof.d.ts.map +1 -1
- package/dist/schema/nodes/roof.js +9 -16
- package/dist/schema/nodes/site.d.ts +46 -0
- package/dist/schema/nodes/site.d.ts.map +1 -1
- package/dist/schema/types.d.ts +191 -4
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/types.js +4 -0
- package/dist/store/actions/node-actions.d.ts.map +1 -1
- package/dist/store/actions/node-actions.js +23 -4
- package/dist/store/use-interactive.d.ts +18 -0
- package/dist/store/use-interactive.d.ts.map +1 -0
- package/dist/store/use-interactive.js +50 -0
- package/dist/store/use-scene.d.ts +10 -1
- package/dist/store/use-scene.d.ts.map +1 -1
- package/dist/store/use-scene.js +180 -57
- package/dist/systems/ceiling/ceiling-system.d.ts.map +1 -1
- package/dist/systems/ceiling/ceiling-system.js +5 -0
- package/dist/systems/door/door-system.d.ts +2 -0
- package/dist/systems/door/door-system.d.ts.map +1 -0
- package/dist/systems/door/door-system.js +211 -0
- package/dist/systems/item/item-system.js +3 -2
- package/dist/systems/roof/roof-system.d.ts +11 -3
- package/dist/systems/roof/roof-system.d.ts.map +1 -1
- package/dist/systems/roof/roof-system.js +705 -210
- package/dist/systems/slab/slab-system.js +3 -3
- package/dist/systems/wall/wall-mitering.js +2 -2
- package/dist/systems/wall/wall-system.d.ts.map +1 -1
- package/dist/systems/wall/wall-system.js +6 -6
- package/dist/systems/window/window-system.js +3 -3
- package/package.json +6 -6
package/dist/events/bus.d.ts
CHANGED
|
@@ -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> = {
|
|
@@ -48,7 +50,17 @@ type CameraControlEvents = {
|
|
|
48
50
|
type ToolEvents = {
|
|
49
51
|
'tool:cancel': undefined;
|
|
50
52
|
};
|
|
51
|
-
type
|
|
53
|
+
type PresetEvents = {
|
|
54
|
+
'preset:generate-thumbnail': {
|
|
55
|
+
presetId: string;
|
|
56
|
+
nodeId: string;
|
|
57
|
+
};
|
|
58
|
+
'preset:thumbnail-updated': {
|
|
59
|
+
presetId: string;
|
|
60
|
+
thumbnailUrl: string;
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
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
64
|
export declare const emitter: import("mitt").Emitter<EditorEvents>;
|
|
53
65
|
export {};
|
|
54
66
|
//# sourceMappingURL=bus.d.ts.map
|
package/dist/events/bus.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bus.d.ts","sourceRoot":"","sources":["../../src/events/bus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAEpD,OAAO,KAAK,
|
|
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
|
|
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,
|
|
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
|
|
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
|
|
24
|
-
private
|
|
25
|
-
private
|
|
26
|
-
private
|
|
27
|
-
private
|
|
28
|
-
private
|
|
29
|
-
private
|
|
30
|
-
private
|
|
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":"AAAA,OAAO,KAAK,EAAE,OAAO,EAA6C,MAAM,cAAc,CAAA;
|
|
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 (
|
|
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 &&
|
|
54
|
-
|
|
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 &&
|
|
118
|
-
|
|
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
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
443
|
+
let maxElevation = Number.NEGATIVE_INFINITY;
|
|
410
444
|
for (const slab of slabMap.values()) {
|
|
411
|
-
if (slab.polygon.length >= 3 &&
|
|
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 ===
|
|
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 =
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
460
|
-
|
|
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 ===
|
|
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
|
|
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,
|
|
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 (
|
|
15
|
-
current =
|
|
15
|
+
if (current.parentId) {
|
|
16
|
+
current = nodes[current.parentId];
|
|
16
17
|
}
|
|
17
18
|
else {
|
|
18
|
-
current =
|
|
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
|
-
|
|
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 ||
|
|
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
|
|
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
|
|
6
|
-
private
|
|
7
|
-
private
|
|
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;
|
|
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)
|
|
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;;;;
|
|
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;
|
|
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
|
|
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)
|
|
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,8 +7,10 @@ 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 {
|
|
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';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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;
|
|
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,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,9 +12,11 @@ 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 {
|
|
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';
|
|
@@ -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,
|
|
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,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"}
|