@pascal-app/core 0.5.1 → 0.7.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 +74 -4
- package/dist/events/bus.d.ts.map +1 -1
- package/dist/events/bus.js +1 -1
- package/dist/hooks/scene-registry/scene-registry.d.ts +2 -0
- package/dist/hooks/scene-registry/scene-registry.d.ts.map +1 -1
- package/dist/hooks/scene-registry/scene-registry.js +2 -0
- package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/spatial-grid-manager.js +164 -6
- package/dist/hooks/spatial-grid/spatial-grid.d.ts +2 -0
- package/dist/hooks/spatial-grid/spatial-grid.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/spatial-grid.js +43 -20
- package/dist/index.d.ts +9 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -11
- package/dist/lib/door-operation.d.ts +7 -0
- package/dist/lib/door-operation.d.ts.map +1 -0
- package/dist/lib/door-operation.js +25 -0
- package/dist/lib/polygon-geometry.d.ts +3 -0
- package/dist/lib/polygon-geometry.d.ts.map +1 -0
- package/dist/lib/polygon-geometry.js +90 -0
- package/dist/lib/slab-polygon.d.ts +3 -0
- package/dist/lib/slab-polygon.d.ts.map +1 -0
- package/dist/lib/slab-polygon.js +58 -0
- package/dist/lib/space-detection.d.ts +10 -17
- package/dist/lib/space-detection.d.ts.map +1 -1
- package/dist/lib/space-detection.js +666 -453
- package/dist/material-library.d.ts +20 -0
- package/dist/material-library.d.ts.map +1 -0
- package/dist/material-library.js +580 -0
- package/dist/schema/asset-url.d.ts +34 -0
- package/dist/schema/asset-url.d.ts.map +1 -0
- package/dist/schema/asset-url.js +79 -0
- package/dist/schema/asset-url.test.d.ts +2 -0
- package/dist/schema/asset-url.test.d.ts.map +1 -0
- package/dist/schema/asset-url.test.js +138 -0
- package/dist/schema/index.d.ts +14 -7
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +10 -7
- package/dist/schema/material.d.ts +112 -2
- package/dist/schema/material.d.ts.map +1 -1
- package/dist/schema/material.js +55 -1
- package/dist/schema/nodes/ceiling.d.ts +11 -1
- package/dist/schema/nodes/ceiling.d.ts.map +1 -1
- package/dist/schema/nodes/ceiling.js +6 -0
- package/dist/schema/nodes/column.d.ts +520 -0
- package/dist/schema/nodes/column.d.ts.map +1 -0
- package/dist/schema/nodes/column.js +385 -0
- package/dist/schema/nodes/door.d.ts +74 -1
- package/dist/schema/nodes/door.d.ts.map +1 -1
- package/dist/schema/nodes/door.js +39 -2
- package/dist/schema/nodes/fence.d.ts +34 -0
- package/dist/schema/nodes/fence.d.ts.map +1 -1
- package/dist/schema/nodes/fence.js +5 -0
- package/dist/schema/nodes/guide.d.ts +17 -0
- package/dist/schema/nodes/guide.d.ts.map +1 -1
- package/dist/schema/nodes/guide.js +11 -1
- package/dist/schema/nodes/item.d.ts +10 -2
- package/dist/schema/nodes/item.d.ts.map +1 -1
- package/dist/schema/nodes/item.js +18 -1
- package/dist/schema/nodes/level.d.ts +1 -1
- package/dist/schema/nodes/level.d.ts.map +1 -1
- package/dist/schema/nodes/level.js +6 -0
- package/dist/schema/nodes/roof-segment.d.ts +3 -1
- package/dist/schema/nodes/roof-segment.d.ts.map +1 -1
- package/dist/schema/nodes/roof-segment.js +1 -0
- package/dist/schema/nodes/roof.d.ts +108 -0
- package/dist/schema/nodes/roof.d.ts.map +1 -1
- package/dist/schema/nodes/roof.js +58 -2
- package/dist/schema/nodes/scan.d.ts.map +1 -1
- package/dist/schema/nodes/scan.js +2 -1
- package/dist/schema/nodes/site.d.ts +2 -1
- package/dist/schema/nodes/site.d.ts.map +1 -1
- package/dist/schema/nodes/slab.d.ts +11 -1
- package/dist/schema/nodes/slab.d.ts.map +1 -1
- package/dist/schema/nodes/slab.js +7 -0
- package/dist/schema/nodes/spawn.d.ts +24 -0
- package/dist/schema/nodes/spawn.d.ts.map +1 -0
- package/dist/schema/nodes/spawn.js +8 -0
- package/dist/schema/nodes/stair-segment.d.ts +3 -1
- package/dist/schema/nodes/stair-segment.d.ts.map +1 -1
- package/dist/schema/nodes/stair-segment.js +1 -0
- package/dist/schema/nodes/stair.d.ts +122 -2
- package/dist/schema/nodes/stair.d.ts.map +1 -1
- package/dist/schema/nodes/stair.js +72 -2
- package/dist/schema/nodes/surface-hole-metadata.d.ts +10 -0
- package/dist/schema/nodes/surface-hole-metadata.d.ts.map +1 -0
- package/dist/schema/nodes/surface-hole-metadata.js +5 -0
- package/dist/schema/nodes/wall.d.ts +87 -1
- package/dist/schema/nodes/wall.d.ts.map +1 -1
- package/dist/schema/nodes/wall.js +45 -4
- package/dist/schema/nodes/window.d.ts +57 -1
- package/dist/schema/nodes/window.d.ts.map +1 -1
- package/dist/schema/nodes/window.js +29 -0
- package/dist/schema/types.d.ts +653 -12
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/types.js +4 -0
- package/dist/store/actions/node-actions.d.ts +1 -1
- package/dist/store/actions/node-actions.d.ts.map +1 -1
- package/dist/store/actions/node-actions.js +181 -5
- package/dist/store/history-control.d.ts +14 -0
- package/dist/store/history-control.d.ts.map +1 -0
- package/dist/store/history-control.js +22 -0
- package/dist/store/use-interactive.d.ts +43 -0
- package/dist/store/use-interactive.d.ts.map +1 -1
- package/dist/store/use-interactive.js +66 -0
- package/dist/store/use-scene.d.ts.map +1 -1
- package/dist/store/use-scene.js +307 -3
- package/dist/systems/ceiling/ceiling-system.d.ts.map +1 -1
- package/dist/systems/ceiling/ceiling-system.js +7 -0
- package/dist/systems/fence/fence-system.d.ts.map +1 -1
- package/dist/systems/fence/fence-system.js +106 -39
- package/dist/systems/roof/roof-system.d.ts.map +1 -1
- package/dist/systems/roof/roof-system.js +31 -1
- package/dist/systems/slab/slab-system.d.ts.map +1 -1
- package/dist/systems/slab/slab-system.js +45 -8
- package/dist/systems/stair/stair-opening-sync.d.ts +6 -0
- package/dist/systems/stair/stair-opening-sync.d.ts.map +1 -0
- package/dist/systems/stair/stair-opening-sync.js +576 -0
- package/dist/systems/stair/stair-opening-sync.test.d.ts +2 -0
- package/dist/systems/stair/stair-opening-sync.test.d.ts.map +1 -0
- package/dist/systems/stair/stair-opening-sync.test.js +65 -0
- package/dist/systems/stair/stair-system.d.ts.map +1 -1
- package/dist/systems/stair/stair-system.js +119 -2
- package/dist/systems/wall/wall-curve.d.ts +43 -0
- package/dist/systems/wall/wall-curve.d.ts.map +1 -0
- package/dist/systems/wall/wall-curve.js +176 -0
- package/dist/systems/wall/wall-footprint.d.ts.map +1 -1
- package/dist/systems/wall/wall-footprint.js +16 -2
- package/dist/systems/wall/wall-mitering.d.ts +7 -0
- package/dist/systems/wall/wall-mitering.d.ts.map +1 -1
- package/dist/systems/wall/wall-mitering.js +76 -3
- package/dist/systems/wall/wall-system.d.ts.map +1 -1
- package/dist/systems/wall/wall-system.js +202 -2
- package/package.json +33 -5
package/dist/events/bus.d.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import type { ThreeEvent } from '@react-three/fiber';
|
|
2
|
-
import type {
|
|
2
|
+
import type { Object3D } from 'three';
|
|
3
|
+
import type { BuildingNode, CeilingNode, ColumnNode, DoorNode, FenceNode, GuideNode, ItemNode, LevelNode, RoofNode, RoofSegmentNode, SiteNode, SlabNode, SpawnNode, StairNode, StairSegmentNode, WallNode, WindowNode, ZoneNode } from '../schema';
|
|
3
4
|
import type { AnyNode } from '../schema/types';
|
|
4
5
|
export interface GridEvent {
|
|
5
6
|
/** World-space intersection point on the grid plane. */
|
|
6
7
|
position: [number, number, number];
|
|
7
8
|
/**
|
|
8
|
-
* Building-local intersection point
|
|
9
|
+
* Building-local intersection point, relative to the currently selected building.
|
|
9
10
|
* Equals `position` when no building is selected.
|
|
10
|
-
* Use this for placing
|
|
11
|
+
* Use this for placing or committing anything that lives inside a building
|
|
12
|
+
* (walls, slabs, items, etc.).
|
|
11
13
|
*/
|
|
12
14
|
localPosition: [number, number, number];
|
|
13
15
|
nativeEvent: ThreeEvent<PointerEvent>;
|
|
@@ -17,6 +19,8 @@ export interface NodeEvent<T extends AnyNode = AnyNode> {
|
|
|
17
19
|
position: [number, number, number];
|
|
18
20
|
localPosition: [number, number, number];
|
|
19
21
|
normal?: [number, number, number];
|
|
22
|
+
faceIndex?: number;
|
|
23
|
+
object: Object3D;
|
|
20
24
|
stopPropagation: () => void;
|
|
21
25
|
nativeEvent: ThreeEvent<PointerEvent>;
|
|
22
26
|
}
|
|
@@ -28,7 +32,9 @@ export type BuildingEvent = NodeEvent<BuildingNode>;
|
|
|
28
32
|
export type LevelEvent = NodeEvent<LevelNode>;
|
|
29
33
|
export type ZoneEvent = NodeEvent<ZoneNode>;
|
|
30
34
|
export type SlabEvent = NodeEvent<SlabNode>;
|
|
35
|
+
export type SpawnEvent = NodeEvent<SpawnNode>;
|
|
31
36
|
export type CeilingEvent = NodeEvent<CeilingNode>;
|
|
37
|
+
export type ColumnEvent = NodeEvent<ColumnNode>;
|
|
32
38
|
export type RoofEvent = NodeEvent<RoofNode>;
|
|
33
39
|
export type RoofSegmentEvent = NodeEvent<RoofSegmentNode>;
|
|
34
40
|
export type StairEvent = NodeEvent<StairNode>;
|
|
@@ -48,6 +54,32 @@ export interface CameraControlEvent {
|
|
|
48
54
|
}
|
|
49
55
|
export interface ThumbnailGenerateEvent {
|
|
50
56
|
projectId: string;
|
|
57
|
+
captureMode?: 'standard' | 'viewport' | 'area';
|
|
58
|
+
cropRegion?: {
|
|
59
|
+
x: number;
|
|
60
|
+
y: number;
|
|
61
|
+
width: number;
|
|
62
|
+
height: number;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* When true, snap levels to their true positions before capturing (for a
|
|
66
|
+
* consistent auto-thumbnail angle) and defer the capture if the tab is
|
|
67
|
+
* hidden, the background auto-save path. Omit for user-driven captures
|
|
68
|
+
* that should fire immediately from the current camera pose.
|
|
69
|
+
*/
|
|
70
|
+
snapLevels?: boolean;
|
|
71
|
+
}
|
|
72
|
+
export interface CameraControlFitSceneEvent {
|
|
73
|
+
/**
|
|
74
|
+
* XZ-plane axis-aligned bounds for camera framing. Omitted values let the
|
|
75
|
+
* listener choose its default framing pose.
|
|
76
|
+
*/
|
|
77
|
+
bounds?: {
|
|
78
|
+
min: [number, number];
|
|
79
|
+
max: [number, number];
|
|
80
|
+
center: [number, number];
|
|
81
|
+
size: [number, number];
|
|
82
|
+
};
|
|
51
83
|
}
|
|
52
84
|
type CameraControlEvents = {
|
|
53
85
|
'camera-controls:view': CameraControlEvent;
|
|
@@ -56,11 +88,33 @@ type CameraControlEvents = {
|
|
|
56
88
|
'camera-controls:top-view': undefined;
|
|
57
89
|
'camera-controls:orbit-cw': undefined;
|
|
58
90
|
'camera-controls:orbit-ccw': undefined;
|
|
91
|
+
'camera-controls:fit-scene': CameraControlFitSceneEvent;
|
|
59
92
|
'camera-controls:generate-thumbnail': ThumbnailGenerateEvent;
|
|
60
93
|
};
|
|
61
94
|
type ToolEvents = {
|
|
62
95
|
'tool:cancel': undefined;
|
|
63
96
|
};
|
|
97
|
+
type GuideEvents = {
|
|
98
|
+
'guide:set-reference-scale': {
|
|
99
|
+
guideId: GuideNode['id'];
|
|
100
|
+
};
|
|
101
|
+
'guide:cancel-reference-scale': undefined;
|
|
102
|
+
'guide:deleted': {
|
|
103
|
+
guideId: GuideNode['id'];
|
|
104
|
+
};
|
|
105
|
+
};
|
|
106
|
+
type DoorAnimationEvents = {
|
|
107
|
+
'door:animation-completed': {
|
|
108
|
+
doorId: DoorNode['id'];
|
|
109
|
+
field: 'operationState' | 'swingAngle';
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
type WindowAnimationEvents = {
|
|
113
|
+
'window:animation-completed': {
|
|
114
|
+
windowId: WindowNode['id'];
|
|
115
|
+
field: 'operationState';
|
|
116
|
+
};
|
|
117
|
+
};
|
|
64
118
|
type PresetEvents = {
|
|
65
119
|
'preset:generate-thumbnail': {
|
|
66
120
|
presetId: string;
|
|
@@ -75,7 +129,23 @@ type ThumbnailEvents = {
|
|
|
75
129
|
'thumbnail:before-capture': undefined;
|
|
76
130
|
'thumbnail:after-capture': undefined;
|
|
77
131
|
};
|
|
78
|
-
type
|
|
132
|
+
type SnapshotEvents = {
|
|
133
|
+
'snapshot:saved': undefined;
|
|
134
|
+
'camera:go-to-position': {
|
|
135
|
+
position: [number, number, number];
|
|
136
|
+
target: [number, number, number];
|
|
137
|
+
};
|
|
138
|
+
};
|
|
139
|
+
type AIChatEvents = {
|
|
140
|
+
'ai-chat:attach-images': {
|
|
141
|
+
images: {
|
|
142
|
+
url: string;
|
|
143
|
+
name: string;
|
|
144
|
+
kind: 'snapshot' | 'render';
|
|
145
|
+
}[];
|
|
146
|
+
};
|
|
147
|
+
};
|
|
148
|
+
type EditorEvents = GridEvents & NodeEvents<'wall', WallEvent> & NodeEvents<'fence', FenceEvent> & NodeEvents<'item', ItemEvent> & NodeEvents<'site', SiteEvent> & NodeEvents<'building', BuildingEvent> & NodeEvents<'level', LevelEvent> & NodeEvents<'zone', ZoneEvent> & NodeEvents<'slab', SlabEvent> & NodeEvents<'spawn', SpawnEvent> & NodeEvents<'ceiling', CeilingEvent> & NodeEvents<'column', ColumnEvent> & NodeEvents<'roof', RoofEvent> & NodeEvents<'roof-segment', RoofSegmentEvent> & NodeEvents<'stair', StairEvent> & NodeEvents<'stair-segment', StairSegmentEvent> & NodeEvents<'window', WindowEvent> & NodeEvents<'door', DoorEvent> & CameraControlEvents & ToolEvents & GuideEvents & DoorAnimationEvents & WindowAnimationEvents & PresetEvents & ThumbnailEvents & SnapshotEvents & AIChatEvents;
|
|
79
149
|
export declare const emitter: import("mitt").Emitter<EditorEvents>;
|
|
80
150
|
export {};
|
|
81
151
|
//# 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,EACV,YAAY,EACZ,WAAW,EACX,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,eAAe,EACf,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,gBAAgB,EAChB,QAAQ,EACR,UAAU,EACV,QAAQ,EACT,MAAM,WAAW,CAAA;AAClB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAG9C,MAAM,WAAW,SAAS;IACxB,wDAAwD;IACxD,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IAClC
|
|
1
|
+
{"version":3,"file":"bus.d.ts","sourceRoot":"","sources":["../../src/events/bus.ts"],"names":[],"mappings":"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"}
|
package/dist/events/bus.js
CHANGED
|
@@ -5,11 +5,13 @@ export declare const sceneRegistry: {
|
|
|
5
5
|
site: Set<string>;
|
|
6
6
|
building: Set<string>;
|
|
7
7
|
ceiling: Set<string>;
|
|
8
|
+
column: Set<string>;
|
|
8
9
|
level: Set<string>;
|
|
9
10
|
wall: Set<string>;
|
|
10
11
|
fence: Set<string>;
|
|
11
12
|
item: Set<string>;
|
|
12
13
|
slab: Set<string>;
|
|
14
|
+
spawn: Set<string>;
|
|
13
15
|
zone: Set<string>;
|
|
14
16
|
roof: Set<string>;
|
|
15
17
|
'roof-segment': Set<string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scene-registry.d.ts","sourceRoot":"","sources":["../../../src/hooks/scene-registry/scene-registry.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAA;AAEnC,eAAO,MAAM,aAAa
|
|
1
|
+
{"version":3,"file":"scene-registry.d.ts","sourceRoot":"","sources":["../../../src/hooks/scene-registry/scene-registry.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAA;AAEnC,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;IA4BxB,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"}
|
|
@@ -9,11 +9,13 @@ export const sceneRegistry = {
|
|
|
9
9
|
site: new Set(),
|
|
10
10
|
building: new Set(),
|
|
11
11
|
ceiling: new Set(),
|
|
12
|
+
column: new Set(),
|
|
12
13
|
level: new Set(),
|
|
13
14
|
wall: new Set(),
|
|
14
15
|
fence: new Set(),
|
|
15
16
|
item: new Set(),
|
|
16
17
|
slab: new Set(),
|
|
18
|
+
spawn: new Set(),
|
|
17
19
|
zone: new Set(),
|
|
18
20
|
roof: new Set(),
|
|
19
21
|
'roof-segment': new Set(),
|
|
@@ -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,4 +1,5 @@
|
|
|
1
|
-
import { getScaledDimensions } from '../../schema';
|
|
1
|
+
import { getScaledDimensions, isLowProfileItemSurface } from '../../schema';
|
|
2
|
+
import useScene from '../../store/use-scene';
|
|
2
3
|
import { SpatialGrid } from './spatial-grid';
|
|
3
4
|
import { WallSpatialGrid } from './wall-spatial-grid';
|
|
4
5
|
// ============================================================================
|
|
@@ -37,6 +38,65 @@ function getItemFootprint(position, dimensions, rotation, inset = 0) {
|
|
|
37
38
|
[x + (-halfW * cos - halfD * sin), z + (-halfW * sin + halfD * cos)],
|
|
38
39
|
];
|
|
39
40
|
}
|
|
41
|
+
function getItemLocalBounds(item) {
|
|
42
|
+
const [width, height, depth] = getScaledDimensions(item);
|
|
43
|
+
const minZ = item.asset.attachTo === 'wall-side' ? -depth : -depth / 2;
|
|
44
|
+
const maxZ = item.asset.attachTo === 'wall-side' ? 0 : depth / 2;
|
|
45
|
+
return {
|
|
46
|
+
min: [-width / 2, 0, minZ],
|
|
47
|
+
max: [width / 2, height, maxZ],
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function getItemParentAabb(item) {
|
|
51
|
+
const bounds = getItemLocalBounds(item);
|
|
52
|
+
const corners = [
|
|
53
|
+
[bounds.min[0], bounds.min[1], bounds.min[2]],
|
|
54
|
+
[bounds.min[0], bounds.min[1], bounds.max[2]],
|
|
55
|
+
[bounds.min[0], bounds.max[1], bounds.min[2]],
|
|
56
|
+
[bounds.min[0], bounds.max[1], bounds.max[2]],
|
|
57
|
+
[bounds.max[0], bounds.min[1], bounds.min[2]],
|
|
58
|
+
[bounds.max[0], bounds.min[1], bounds.max[2]],
|
|
59
|
+
[bounds.max[0], bounds.max[1], bounds.min[2]],
|
|
60
|
+
[bounds.max[0], bounds.max[1], bounds.max[2]],
|
|
61
|
+
];
|
|
62
|
+
const yRot = item.rotation[1] ?? 0;
|
|
63
|
+
const cos = Math.cos(yRot);
|
|
64
|
+
const sin = Math.sin(yRot);
|
|
65
|
+
let minX = Number.POSITIVE_INFINITY;
|
|
66
|
+
let minY = Number.POSITIVE_INFINITY;
|
|
67
|
+
let minZ = Number.POSITIVE_INFINITY;
|
|
68
|
+
let maxX = Number.NEGATIVE_INFINITY;
|
|
69
|
+
let maxY = Number.NEGATIVE_INFINITY;
|
|
70
|
+
let maxZ = Number.NEGATIVE_INFINITY;
|
|
71
|
+
for (const [cx, cy, cz] of corners) {
|
|
72
|
+
const rotatedX = cx * cos + cz * sin;
|
|
73
|
+
const rotatedZ = -cx * sin + cz * cos;
|
|
74
|
+
const worldX = rotatedX + item.position[0];
|
|
75
|
+
const worldY = cy + item.position[1];
|
|
76
|
+
const worldZ = rotatedZ + item.position[2];
|
|
77
|
+
minX = Math.min(minX, worldX);
|
|
78
|
+
minY = Math.min(minY, worldY);
|
|
79
|
+
minZ = Math.min(minZ, worldZ);
|
|
80
|
+
maxX = Math.max(maxX, worldX);
|
|
81
|
+
maxY = Math.max(maxY, worldY);
|
|
82
|
+
maxZ = Math.max(maxZ, worldZ);
|
|
83
|
+
}
|
|
84
|
+
return { minX, maxX, minY, maxY, minZ, maxZ };
|
|
85
|
+
}
|
|
86
|
+
function intervalsOverlap(minA, maxA, minB, maxB, epsilon = 1e-4) {
|
|
87
|
+
return minA < maxB - epsilon && maxA > minB + epsilon;
|
|
88
|
+
}
|
|
89
|
+
function resolveNodeLevelId(node, nodes) {
|
|
90
|
+
if (node.type === 'level')
|
|
91
|
+
return node.id;
|
|
92
|
+
let current = node;
|
|
93
|
+
while (current) {
|
|
94
|
+
if (current.type === 'level')
|
|
95
|
+
return current.id;
|
|
96
|
+
current = current.parentId ? nodes[current.parentId] : undefined;
|
|
97
|
+
}
|
|
98
|
+
return 'default';
|
|
99
|
+
}
|
|
40
100
|
/**
|
|
41
101
|
* Test if two line segments (a1->a2) and (b1->b2) intersect.
|
|
42
102
|
*/
|
|
@@ -373,8 +433,40 @@ export class SpatialGridManager {
|
|
|
373
433
|
}
|
|
374
434
|
// Query methods
|
|
375
435
|
canPlaceOnFloor(levelId, position, dimensions, rotation, ignoreIds) {
|
|
376
|
-
const
|
|
377
|
-
|
|
436
|
+
const nodes = useScene.getState().nodes;
|
|
437
|
+
const ignoreSet = new Set(ignoreIds ?? []);
|
|
438
|
+
const [width, , depth] = dimensions;
|
|
439
|
+
const yRot = rotation[1];
|
|
440
|
+
const cos = Math.abs(Math.cos(yRot));
|
|
441
|
+
const sin = Math.abs(Math.sin(yRot));
|
|
442
|
+
const rotatedW = width * cos + depth * sin;
|
|
443
|
+
const rotatedD = width * sin + depth * cos;
|
|
444
|
+
const draftBounds = {
|
|
445
|
+
minX: position[0] - rotatedW / 2,
|
|
446
|
+
maxX: position[0] + rotatedW / 2,
|
|
447
|
+
minZ: position[2] - rotatedD / 2,
|
|
448
|
+
maxZ: position[2] + rotatedD / 2,
|
|
449
|
+
};
|
|
450
|
+
const conflicts = [];
|
|
451
|
+
for (const node of Object.values(nodes)) {
|
|
452
|
+
if (node.type !== 'item')
|
|
453
|
+
continue;
|
|
454
|
+
const item = node;
|
|
455
|
+
if (item.asset.attachTo)
|
|
456
|
+
continue;
|
|
457
|
+
if (isLowProfileItemSurface(item))
|
|
458
|
+
continue;
|
|
459
|
+
if (ignoreSet.has(item.id))
|
|
460
|
+
continue;
|
|
461
|
+
if (resolveNodeLevelId(item, nodes) !== levelId)
|
|
462
|
+
continue;
|
|
463
|
+
const bounds = getItemParentAabb(item);
|
|
464
|
+
if (intervalsOverlap(draftBounds.minX, draftBounds.maxX, bounds.minX, bounds.maxX) &&
|
|
465
|
+
intervalsOverlap(draftBounds.minZ, draftBounds.maxZ, bounds.minZ, bounds.maxZ)) {
|
|
466
|
+
conflicts.push(item.id);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
return { valid: conflicts.length === 0, conflictIds: conflicts };
|
|
378
470
|
}
|
|
379
471
|
/**
|
|
380
472
|
* Check if an item can be placed on a wall
|
|
@@ -396,7 +488,43 @@ export class SpatialGridManager {
|
|
|
396
488
|
// Convert local X position to parametric t (0-1)
|
|
397
489
|
const tCenter = localX / wallLength;
|
|
398
490
|
const [itemWidth, itemHeight] = dimensions;
|
|
399
|
-
|
|
491
|
+
const baseResult = this.getWallGrid(levelId).canPlaceOnWall(wallId, wallLength, wallHeight, tCenter, itemWidth, localY, itemHeight, attachType, side, ignoreIds);
|
|
492
|
+
if (!baseResult.valid)
|
|
493
|
+
return baseResult;
|
|
494
|
+
const nodes = useScene.getState().nodes;
|
|
495
|
+
const ignoreSet = new Set(ignoreIds ?? []);
|
|
496
|
+
const draftBounds = {
|
|
497
|
+
minX: localX - itemWidth / 2,
|
|
498
|
+
maxX: localX + itemWidth / 2,
|
|
499
|
+
minY: baseResult.adjustedY,
|
|
500
|
+
maxY: baseResult.adjustedY + itemHeight,
|
|
501
|
+
};
|
|
502
|
+
const conflicts = [];
|
|
503
|
+
for (const node of Object.values(nodes)) {
|
|
504
|
+
if (node.type !== 'item')
|
|
505
|
+
continue;
|
|
506
|
+
const item = node;
|
|
507
|
+
if (!(item.asset.attachTo === 'wall' || item.asset.attachTo === 'wall-side'))
|
|
508
|
+
continue;
|
|
509
|
+
if (ignoreSet.has(item.id))
|
|
510
|
+
continue;
|
|
511
|
+
if (item.parentId !== wallId)
|
|
512
|
+
continue;
|
|
513
|
+
if (attachType === 'wall-side' && item.asset.attachTo === 'wall-side' && side && item.side) {
|
|
514
|
+
if (side !== item.side)
|
|
515
|
+
continue;
|
|
516
|
+
}
|
|
517
|
+
const bounds = getItemParentAabb(item);
|
|
518
|
+
if (intervalsOverlap(draftBounds.minX, draftBounds.maxX, bounds.minX, bounds.maxX) &&
|
|
519
|
+
intervalsOverlap(draftBounds.minY, draftBounds.maxY, bounds.minY, bounds.maxY)) {
|
|
520
|
+
conflicts.push(item.id);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
return {
|
|
524
|
+
...baseResult,
|
|
525
|
+
valid: conflicts.length === 0,
|
|
526
|
+
conflictIds: conflicts,
|
|
527
|
+
};
|
|
400
528
|
}
|
|
401
529
|
getWallForItem(levelId, itemId) {
|
|
402
530
|
return this.getWallGrid(levelId).getWallForItem(itemId);
|
|
@@ -541,8 +669,38 @@ export class SpatialGridManager {
|
|
|
541
669
|
return { valid: false, conflictIds: [] };
|
|
542
670
|
}
|
|
543
671
|
}
|
|
544
|
-
|
|
545
|
-
|
|
672
|
+
const nodes = useScene.getState().nodes;
|
|
673
|
+
const ignoreSet = new Set(ignoreIds ?? []);
|
|
674
|
+
const [width, , depth] = dimensions;
|
|
675
|
+
const yRot = rotation[1];
|
|
676
|
+
const cos = Math.abs(Math.cos(yRot));
|
|
677
|
+
const sin = Math.abs(Math.sin(yRot));
|
|
678
|
+
const rotatedW = width * cos + depth * sin;
|
|
679
|
+
const rotatedD = width * sin + depth * cos;
|
|
680
|
+
const draftBounds = {
|
|
681
|
+
minX: position[0] - rotatedW / 2,
|
|
682
|
+
maxX: position[0] + rotatedW / 2,
|
|
683
|
+
minZ: position[2] - rotatedD / 2,
|
|
684
|
+
maxZ: position[2] + rotatedD / 2,
|
|
685
|
+
};
|
|
686
|
+
const conflicts = [];
|
|
687
|
+
for (const node of Object.values(nodes)) {
|
|
688
|
+
if (node.type !== 'item')
|
|
689
|
+
continue;
|
|
690
|
+
const item = node;
|
|
691
|
+
if (item.asset.attachTo !== 'ceiling')
|
|
692
|
+
continue;
|
|
693
|
+
if (ignoreSet.has(item.id))
|
|
694
|
+
continue;
|
|
695
|
+
if (item.parentId !== ceilingId)
|
|
696
|
+
continue;
|
|
697
|
+
const bounds = getItemParentAabb(item);
|
|
698
|
+
if (intervalsOverlap(draftBounds.minX, draftBounds.maxX, bounds.minX, bounds.maxX) &&
|
|
699
|
+
intervalsOverlap(draftBounds.minZ, draftBounds.maxZ, bounds.minZ, bounds.maxZ)) {
|
|
700
|
+
conflicts.push(item.id);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
return { valid: conflicts.length === 0, conflictIds: conflicts };
|
|
546
704
|
}
|
|
547
705
|
clearLevel(levelId) {
|
|
548
706
|
this.floorGrids.delete(levelId);
|
|
@@ -4,10 +4,12 @@ interface SpatialGridConfig {
|
|
|
4
4
|
export declare class SpatialGrid {
|
|
5
5
|
private readonly cells;
|
|
6
6
|
private readonly itemCells;
|
|
7
|
+
private readonly itemBounds;
|
|
7
8
|
private readonly config;
|
|
8
9
|
constructor(config: SpatialGridConfig);
|
|
9
10
|
private posToCell;
|
|
10
11
|
private cellKey;
|
|
12
|
+
private getAABB;
|
|
11
13
|
private getItemCells;
|
|
12
14
|
insert(itemId: string, position: [number, number, number], dimensions: [number, number, number], rotation: [number, number, number]): void;
|
|
13
15
|
remove(itemId: string): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spatial-grid.d.ts","sourceRoot":"","sources":["../../../src/hooks/spatial-grid/spatial-grid.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"spatial-grid.d.ts","sourceRoot":"","sources":["../../../src/hooks/spatial-grid/spatial-grid.ts"],"names":[],"mappings":"AAaA,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;IAC5D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgC;IAE3D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;gBAE9B,MAAM,EAAE,iBAAiB;IAIrC,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,OAAO;IAKf,OAAO,CAAC,OAAO;IAuBf,OAAO,CAAC,YAAY;IAgBpB,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;IAiBpC,MAAM,CAAC,MAAM,EAAE,MAAM;IAkBrB,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;IASpC,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;IA0C5C,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;IAkB3D,YAAY,IAAI,MAAM;CAGvB"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export class SpatialGrid {
|
|
2
2
|
cells = new Map();
|
|
3
3
|
itemCells = new Map(); // reverse lookup
|
|
4
|
+
itemBounds = new Map(); // actual AABB for narrow-phase
|
|
4
5
|
config;
|
|
5
6
|
constructor(config) {
|
|
6
7
|
this.config = config;
|
|
@@ -11,27 +12,27 @@ export class SpatialGrid {
|
|
|
11
12
|
cellKey(cx, cz) {
|
|
12
13
|
return `${cx},${cz}`;
|
|
13
14
|
}
|
|
14
|
-
//
|
|
15
|
-
|
|
16
|
-
// Simplified: axis-aligned bounding box
|
|
17
|
-
// For full rotation support, compute rotated corners
|
|
15
|
+
// Compute the axis-aligned bounding box for a rotated item
|
|
16
|
+
getAABB(position, dimensions, rotation) {
|
|
18
17
|
const [x, , z] = position;
|
|
19
18
|
const [w, , d] = dimensions;
|
|
20
|
-
const yRot = rotation[1];
|
|
21
|
-
// Compute rotated footprint (simplified for 90° increments)
|
|
19
|
+
const yRot = rotation[1];
|
|
22
20
|
const cos = Math.abs(Math.cos(yRot));
|
|
23
21
|
const sin = Math.abs(Math.sin(yRot));
|
|
24
22
|
const rotatedW = w * cos + d * sin;
|
|
25
23
|
const rotatedD = w * sin + d * cos;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
return {
|
|
25
|
+
minX: x - rotatedW / 2,
|
|
26
|
+
maxX: x + rotatedW / 2,
|
|
27
|
+
minZ: z - rotatedD / 2,
|
|
28
|
+
maxZ: z + rotatedD / 2,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
// Get all cells an item occupies based on its AABB
|
|
32
|
+
getItemCells(bounds) {
|
|
33
|
+
const { minX, maxX, minZ, maxZ } = bounds;
|
|
30
34
|
const [minCx, minCz] = this.posToCell(minX, minZ);
|
|
31
|
-
|
|
32
|
-
// This allows adjacent items (touching but not overlapping) to not conflict
|
|
33
|
-
const epsilon = 1e-6;
|
|
34
|
-
const [maxCx, maxCz] = this.posToCell(maxX - epsilon, maxZ - epsilon);
|
|
35
|
+
const [maxCx, maxCz] = this.posToCell(maxX, maxZ);
|
|
35
36
|
const keys = [];
|
|
36
37
|
for (let cx = minCx; cx <= maxCx; cx++) {
|
|
37
38
|
for (let cz = minCz; cz <= maxCz; cz++) {
|
|
@@ -42,8 +43,10 @@ export class SpatialGrid {
|
|
|
42
43
|
}
|
|
43
44
|
// Register an item
|
|
44
45
|
insert(itemId, position, dimensions, rotation) {
|
|
45
|
-
const
|
|
46
|
+
const bounds = this.getAABB(position, dimensions, rotation);
|
|
47
|
+
const cellKeys = this.getItemCells(bounds);
|
|
46
48
|
this.itemCells.set(itemId, new Set(cellKeys));
|
|
49
|
+
this.itemBounds.set(itemId, bounds);
|
|
47
50
|
for (const key of cellKeys) {
|
|
48
51
|
if (!this.cells.has(key)) {
|
|
49
52
|
this.cells.set(key, { itemIds: new Set() });
|
|
@@ -66,6 +69,7 @@ export class SpatialGrid {
|
|
|
66
69
|
}
|
|
67
70
|
}
|
|
68
71
|
this.itemCells.delete(itemId);
|
|
72
|
+
this.itemBounds.delete(itemId);
|
|
69
73
|
}
|
|
70
74
|
// Update = remove + insert
|
|
71
75
|
update(itemId, position, dimensions, rotation) {
|
|
@@ -73,23 +77,42 @@ export class SpatialGrid {
|
|
|
73
77
|
this.insert(itemId, position, dimensions, rotation);
|
|
74
78
|
}
|
|
75
79
|
// Query: is this placement valid?
|
|
80
|
+
// Uses cells as broad-phase, then checks actual AABB overlap (narrow-phase)
|
|
81
|
+
// to avoid false positives when adjacent items share a cell but don't overlap.
|
|
76
82
|
canPlace(position, dimensions, rotation, ignoreIds = []) {
|
|
77
|
-
const
|
|
83
|
+
const bounds = this.getAABB(position, dimensions, rotation);
|
|
84
|
+
const cellKeys = this.getItemCells(bounds);
|
|
78
85
|
const ignoreSet = new Set(ignoreIds);
|
|
79
|
-
|
|
86
|
+
// Broad phase: collect candidate items from overlapping cells
|
|
87
|
+
const candidates = new Set();
|
|
80
88
|
for (const key of cellKeys) {
|
|
81
89
|
const cell = this.cells.get(key);
|
|
82
90
|
if (cell) {
|
|
83
91
|
for (const id of cell.itemIds) {
|
|
84
92
|
if (!ignoreSet.has(id)) {
|
|
85
|
-
|
|
93
|
+
candidates.add(id);
|
|
86
94
|
}
|
|
87
95
|
}
|
|
88
96
|
}
|
|
89
97
|
}
|
|
98
|
+
// Narrow phase: check actual AABB overlap
|
|
99
|
+
// Items that merely touch (share an edge) are allowed; only true overlap conflicts.
|
|
100
|
+
const EPSILON = 1e-4; // tolerance to allow touching
|
|
101
|
+
const conflicts = [];
|
|
102
|
+
for (const id of candidates) {
|
|
103
|
+
const other = this.itemBounds.get(id);
|
|
104
|
+
if (!other)
|
|
105
|
+
continue;
|
|
106
|
+
if (bounds.minX < other.maxX - EPSILON &&
|
|
107
|
+
bounds.maxX > other.minX + EPSILON &&
|
|
108
|
+
bounds.minZ < other.maxZ - EPSILON &&
|
|
109
|
+
bounds.maxZ > other.minZ + EPSILON) {
|
|
110
|
+
conflicts.push(id);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
90
113
|
return {
|
|
91
|
-
valid: conflicts.
|
|
92
|
-
conflictIds:
|
|
114
|
+
valid: conflicts.length === 0,
|
|
115
|
+
conflictIds: conflicts,
|
|
93
116
|
};
|
|
94
117
|
}
|
|
95
118
|
// Query: get all items near a point (for snapping, selection, etc.)
|
package/dist/index.d.ts
CHANGED
|
@@ -1,27 +1,23 @@
|
|
|
1
|
-
export type { BuildingEvent, CameraControlEvent, CeilingEvent, DoorEvent, EventSuffix, FenceEvent, GridEvent, ItemEvent, LevelEvent, NodeEvent, RoofEvent, RoofSegmentEvent, SiteEvent, SlabEvent, StairEvent, StairSegmentEvent, WallEvent, WindowEvent, ZoneEvent, } from './events/bus';
|
|
1
|
+
export type { BuildingEvent, CameraControlEvent, CameraControlFitSceneEvent, CeilingEvent, ColumnEvent, DoorEvent, EventSuffix, FenceEvent, GridEvent, ItemEvent, LevelEvent, NodeEvent, RoofEvent, RoofSegmentEvent, SiteEvent, SlabEvent, SpawnEvent, StairEvent, StairSegmentEvent, 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';
|
|
5
5
|
export { initSpatialGridSync, resolveLevelId, } from './hooks/spatial-grid/spatial-grid-sync';
|
|
6
6
|
export { useSpatialQuery } from './hooks/spatial-grid/use-spatial-query';
|
|
7
7
|
export { loadAssetUrl, saveAsset } from './lib/asset-storage';
|
|
8
|
+
export { clampDoorOperationState, getDoorRenderOpenAmount, getGarageVisibleOpeningRatio, isOperationDoorType, SECTIONAL_GARAGE_RENDER_OPEN_SCALE, } from './lib/door-operation';
|
|
9
|
+
export { getRenderableSlabPolygon } from './lib/slab-polygon';
|
|
8
10
|
export { detectSpacesForLevel, initSpaceDetectionSync, type Space, wallTouchesOthers, } from './lib/space-detection';
|
|
9
|
-
export {
|
|
11
|
+
export { getCatalogMaterialById, getLibraryMaterialIdFromRef, getMaterialPresetByRef, getMaterialsForCategory, LIBRARY_MATERIAL_REF_PREFIX, MATERIAL_CATALOG, MATERIAL_CATEGORIES, type MaterialCatalogItem, type MaterialCategory, toLibraryMaterialRef, } from './material-library';
|
|
10
12
|
export * from './schema';
|
|
11
|
-
export {
|
|
13
|
+
export { getSceneHistoryPauseDepth, pauseSceneHistory, resetSceneHistoryPauseDepth, resumeSceneHistory, } from './store/history-control';
|
|
14
|
+
export { type ControlValue, type DoorAnimationState, type DoorInteractiveState, type ItemInteractiveState, useInteractive, type WindowAnimationState, type WindowInteractiveState, } from './store/use-interactive';
|
|
12
15
|
export { default as useLiveTransforms, type LiveTransform } from './store/use-live-transforms';
|
|
13
|
-
export { FenceSystem } from './systems/fence/fence-system';
|
|
14
16
|
export { clearSceneHistory, default as useScene } from './store/use-scene';
|
|
15
|
-
export {
|
|
16
|
-
export {
|
|
17
|
-
export { ItemSystem } from './systems/item/item-system';
|
|
18
|
-
export { RoofSystem } from './systems/roof/roof-system';
|
|
19
|
-
export { SlabSystem } from './systems/slab/slab-system';
|
|
20
|
-
export { StairSystem } from './systems/stair/stair-system';
|
|
17
|
+
export { syncAutoStairOpenings } from './systems/stair/stair-opening-sync';
|
|
18
|
+
export { getClampedWallCurveOffset, getMaxWallCurveOffset, getWallChordFrame, getWallCurveFrameAt, getWallCurveLength, getWallMidpointHandlePoint, getWallStraightSnapOffset, getWallSurfacePolygon, isCurvedWall, normalizeWallCurveOffset, sampleWallCenterline, } from './systems/wall/wall-curve';
|
|
21
19
|
export { DEFAULT_WALL_HEIGHT, DEFAULT_WALL_THICKNESS, getWallPlanFootprint, getWallThickness, } from './systems/wall/wall-footprint';
|
|
22
|
-
export { calculateLevelMiters, type Point2D, pointToKey, type WallMiterData, } from './systems/wall/wall-mitering';
|
|
23
|
-
export { WallSystem } from './systems/wall/wall-system';
|
|
24
|
-
export { WindowSystem } from './systems/window/window-system';
|
|
20
|
+
export { calculateLevelMiters, getAdjacentWallIds, getWallMiterBoundaryPoints, type Point2D, pointToKey, type WallMiterBoundaryPoints, type WallMiterData, } from './systems/wall/wall-mitering';
|
|
25
21
|
export type { SceneGraph } from './utils/clone-scene-graph';
|
|
26
22
|
export { cloneLevelSubtree, cloneSceneGraph, forkSceneGraph } from './utils/clone-scene-graph';
|
|
27
23
|
export { isObject } from './utils/types';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,WAAW,EACX,UAAU,EACV,SAAS,EACT,SAAS,EACT,UAAU,EACV,SAAS,EACT,SAAS,EACT,gBAAgB,EAChB,SAAS,EACT,SAAS,EACT,UAAU,EACV,iBAAiB,EACjB,SAAS,EACT,WAAW,EACX,SAAS,GACV,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACrD,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;AACxE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,KAAK,KAAK,EACV,iBAAiB,GAClB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,0BAA0B,EAC1B,YAAY,EACZ,WAAW,EACX,SAAS,EACT,WAAW,EACX,UAAU,EACV,SAAS,EACT,SAAS,EACT,UAAU,EACV,SAAS,EACT,SAAS,EACT,gBAAgB,EAChB,SAAS,EACT,SAAS,EACT,UAAU,EACV,UAAU,EACV,iBAAiB,EACjB,SAAS,EACT,WAAW,EACX,SAAS,GACV,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACrD,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;AACxE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,4BAA4B,EAC5B,mBAAmB,EACnB,kCAAkC,GACnC,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAA;AAC7D,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,KAAK,KAAK,EACV,iBAAiB,GAClB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,sBAAsB,EACtB,2BAA2B,EAC3B,sBAAsB,EACtB,uBAAuB,EACvB,2BAA2B,EAC3B,gBAAgB,EAChB,mBAAmB,EACnB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,oBAAoB,GACrB,MAAM,oBAAoB,CAAA;AAC3B,cAAc,UAAU,CAAA;AACxB,OAAO,EACL,yBAAyB,EACzB,iBAAiB,EACjB,2BAA2B,EAC3B,kBAAkB,GACnB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,cAAc,EACd,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,GAC5B,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,KAAK,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC9F,OAAO,EAAE,iBAAiB,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAA;AAC1E,OAAO,EACL,yBAAyB,EACzB,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,0BAA0B,EAC1B,yBAAyB,EACzB,qBAAqB,EACrB,YAAY,EACZ,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,2BAA2B,CAAA;AAClC,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,+BAA+B,CAAA;AACtC,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,0BAA0B,EAC1B,KAAK,OAAO,EACZ,UAAU,EACV,KAAK,uBAAuB,EAC5B,KAAK,aAAa,GACnB,MAAM,8BAA8B,CAAA;AACrC,YAAY,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA;AAC3D,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC9F,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -4,22 +4,18 @@ export { pointInPolygon, spatialGridManager } from './hooks/spatial-grid/spatial
|
|
|
4
4
|
export { initSpatialGridSync, resolveLevelId, } from './hooks/spatial-grid/spatial-grid-sync';
|
|
5
5
|
export { useSpatialQuery } from './hooks/spatial-grid/use-spatial-query';
|
|
6
6
|
export { loadAssetUrl, saveAsset } from './lib/asset-storage';
|
|
7
|
+
export { clampDoorOperationState, getDoorRenderOpenAmount, getGarageVisibleOpeningRatio, isOperationDoorType, SECTIONAL_GARAGE_RENDER_OPEN_SCALE, } from './lib/door-operation';
|
|
8
|
+
export { getRenderableSlabPolygon } from './lib/slab-polygon';
|
|
7
9
|
export { detectSpacesForLevel, initSpaceDetectionSync, wallTouchesOthers, } from './lib/space-detection';
|
|
8
|
-
export {
|
|
10
|
+
export { getCatalogMaterialById, getLibraryMaterialIdFromRef, getMaterialPresetByRef, getMaterialsForCategory, LIBRARY_MATERIAL_REF_PREFIX, MATERIAL_CATALOG, MATERIAL_CATEGORIES, toLibraryMaterialRef, } from './material-library';
|
|
9
11
|
export * from './schema';
|
|
12
|
+
export { getSceneHistoryPauseDepth, pauseSceneHistory, resetSceneHistoryPauseDepth, resumeSceneHistory, } from './store/history-control';
|
|
10
13
|
export { useInteractive, } from './store/use-interactive';
|
|
11
14
|
export { default as useLiveTransforms } from './store/use-live-transforms';
|
|
12
|
-
export { FenceSystem } from './systems/fence/fence-system';
|
|
13
15
|
export { clearSceneHistory, default as useScene } from './store/use-scene';
|
|
14
|
-
export {
|
|
15
|
-
export {
|
|
16
|
-
export { ItemSystem } from './systems/item/item-system';
|
|
17
|
-
export { RoofSystem } from './systems/roof/roof-system';
|
|
18
|
-
export { SlabSystem } from './systems/slab/slab-system';
|
|
19
|
-
export { StairSystem } from './systems/stair/stair-system';
|
|
16
|
+
export { syncAutoStairOpenings } from './systems/stair/stair-opening-sync';
|
|
17
|
+
export { getClampedWallCurveOffset, getMaxWallCurveOffset, getWallChordFrame, getWallCurveFrameAt, getWallCurveLength, getWallMidpointHandlePoint, getWallStraightSnapOffset, getWallSurfacePolygon, isCurvedWall, normalizeWallCurveOffset, sampleWallCenterline, } from './systems/wall/wall-curve';
|
|
20
18
|
export { DEFAULT_WALL_HEIGHT, DEFAULT_WALL_THICKNESS, getWallPlanFootprint, getWallThickness, } from './systems/wall/wall-footprint';
|
|
21
|
-
export { calculateLevelMiters, pointToKey, } from './systems/wall/wall-mitering';
|
|
22
|
-
export { WallSystem } from './systems/wall/wall-system';
|
|
23
|
-
export { WindowSystem } from './systems/window/window-system';
|
|
19
|
+
export { calculateLevelMiters, getAdjacentWallIds, getWallMiterBoundaryPoints, pointToKey, } from './systems/wall/wall-mitering';
|
|
24
20
|
export { cloneLevelSubtree, cloneSceneGraph, forkSceneGraph } from './utils/clone-scene-graph';
|
|
25
21
|
export { isObject } from './utils/types';
|