@pascal-app/core 0.5.0 → 0.5.1
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 +3 -2
- package/dist/events/bus.d.ts.map +1 -1
- package/dist/hooks/scene-registry/scene-registry.d.ts +1 -0
- package/dist/hooks/scene-registry/scene-registry.d.ts.map +1 -1
- package/dist/hooks/scene-registry/scene-registry.js +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/schema/index.d.ts +2 -1
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +2 -1
- package/dist/schema/nodes/fence.d.ts +51 -0
- package/dist/schema/nodes/fence.d.ts.map +1 -0
- package/dist/schema/nodes/fence.js +29 -0
- 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 +2 -0
- package/dist/schema/nodes/stair.d.ts +44 -0
- package/dist/schema/nodes/stair.d.ts.map +1 -1
- package/dist/schema/nodes/stair.js +34 -3
- package/dist/schema/types.d.ts +66 -2
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/types.js +2 -0
- package/dist/store/use-scene.js +1 -1
- package/dist/systems/fence/fence-system.d.ts +2 -0
- package/dist/systems/fence/fence-system.d.ts.map +1 -0
- package/dist/systems/fence/fence-system.js +120 -0
- package/dist/systems/stair/stair-system.js +313 -8
- package/package.json +1 -1
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, DoorNode, ItemNode, LevelNode, RoofNode, RoofSegmentNode, SiteNode, SlabNode, StairNode, StairSegmentNode, WallNode, WindowNode, ZoneNode } from '../schema';
|
|
2
|
+
import type { BuildingNode, CeilingNode, DoorNode, FenceNode, ItemNode, LevelNode, RoofNode, RoofSegmentNode, SiteNode, SlabNode, StairNode, StairSegmentNode, WallNode, WindowNode, ZoneNode } from '../schema';
|
|
3
3
|
import type { AnyNode } from '../schema/types';
|
|
4
4
|
export interface GridEvent {
|
|
5
5
|
/** World-space intersection point on the grid plane. */
|
|
@@ -21,6 +21,7 @@ export interface NodeEvent<T extends AnyNode = AnyNode> {
|
|
|
21
21
|
nativeEvent: ThreeEvent<PointerEvent>;
|
|
22
22
|
}
|
|
23
23
|
export type WallEvent = NodeEvent<WallNode>;
|
|
24
|
+
export type FenceEvent = NodeEvent<FenceNode>;
|
|
24
25
|
export type ItemEvent = NodeEvent<ItemNode>;
|
|
25
26
|
export type SiteEvent = NodeEvent<SiteNode>;
|
|
26
27
|
export type BuildingEvent = NodeEvent<BuildingNode>;
|
|
@@ -74,7 +75,7 @@ type ThumbnailEvents = {
|
|
|
74
75
|
'thumbnail:before-capture': undefined;
|
|
75
76
|
'thumbnail:after-capture': undefined;
|
|
76
77
|
};
|
|
77
|
-
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<'stair', StairEvent> & NodeEvents<'stair-segment', StairSegmentEvent> & NodeEvents<'window', WindowEvent> & NodeEvents<'door', DoorEvent> & CameraControlEvents & ToolEvents & PresetEvents & ThumbnailEvents;
|
|
78
|
+
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<'ceiling', CeilingEvent> & NodeEvents<'roof', RoofEvent> & NodeEvents<'roof-segment', RoofSegmentEvent> & NodeEvents<'stair', StairEvent> & NodeEvents<'stair-segment', StairSegmentEvent> & NodeEvents<'window', WindowEvent> & NodeEvents<'door', DoorEvent> & CameraControlEvents & ToolEvents & PresetEvents & ThumbnailEvents;
|
|
78
79
|
export declare const emitter: import("mitt").Emitter<EditorEvents>;
|
|
79
80
|
export {};
|
|
80
81
|
//# 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":"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"}
|
|
1
|
+
{"version":3,"file":"bus.d.ts","sourceRoot":"","sources":["../../src/events/bus.ts"],"names":[],"mappings":"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"}
|
|
@@ -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;;;;;;;;;;;;;;;;;;;;;IA0BxB,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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { BuildingEvent, CameraControlEvent, CeilingEvent, DoorEvent, EventSuffix, GridEvent, ItemEvent, LevelEvent, NodeEvent, RoofEvent, RoofSegmentEvent, SiteEvent, SlabEvent, StairEvent, StairSegmentEvent, WallEvent, WindowEvent, ZoneEvent, } from './events/bus';
|
|
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';
|
|
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';
|
|
@@ -10,6 +10,7 @@ export { baseMaterial, glassMaterial } from './materials';
|
|
|
10
10
|
export * from './schema';
|
|
11
11
|
export { type ControlValue, type ItemInteractiveState, useInteractive, } from './store/use-interactive';
|
|
12
12
|
export { default as useLiveTransforms, type LiveTransform } from './store/use-live-transforms';
|
|
13
|
+
export { FenceSystem } from './systems/fence/fence-system';
|
|
13
14
|
export { clearSceneHistory, default as useScene } from './store/use-scene';
|
|
14
15
|
export { CeilingSystem } from './systems/ceiling/ceiling-system';
|
|
15
16
|
export { DoorSystem } from './systems/door/door-system';
|
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,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,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AACzD,cAAc,UAAU,CAAA;AACxB,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,cAAc,GACf,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,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,WAAW,EAAE,MAAM,8BAA8B,CAAA;AAC1D,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,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"}
|
|
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,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AACzD,cAAc,UAAU,CAAA;AACxB,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,cAAc,GACf,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,KAAK,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC9F,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAA;AAC1D,OAAO,EAAE,iBAAiB,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC1E,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,WAAW,EAAE,MAAM,8BAA8B,CAAA;AAC1D,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,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
|
@@ -9,6 +9,7 @@ export { baseMaterial, glassMaterial } from './materials';
|
|
|
9
9
|
export * from './schema';
|
|
10
10
|
export { useInteractive, } from './store/use-interactive';
|
|
11
11
|
export { default as useLiveTransforms } from './store/use-live-transforms';
|
|
12
|
+
export { FenceSystem } from './systems/fence/fence-system';
|
|
12
13
|
export { clearSceneHistory, default as useScene } from './store/use-scene';
|
|
13
14
|
export { CeilingSystem } from './systems/ceiling/ceiling-system';
|
|
14
15
|
export { DoorSystem } from './systems/door/door-system';
|
package/dist/schema/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export { DEFAULT_MATERIALS, MaterialPreset, MaterialProperties, MaterialSchema,
|
|
|
5
5
|
export { BuildingNode } from './nodes/building';
|
|
6
6
|
export { CeilingNode } from './nodes/ceiling';
|
|
7
7
|
export { DoorNode, DoorSegment } from './nodes/door';
|
|
8
|
+
export { FenceBaseStyle, FenceNode, FenceStyle } from './nodes/fence';
|
|
8
9
|
export { GuideNode } from './nodes/guide';
|
|
9
10
|
export type { AnimationEffect, Asset, AssetInput, Control, Effect, Interactive, LightEffect, SliderControl, TemperatureControl, ToggleControl, } from './nodes/item';
|
|
10
11
|
export { getScaledDimensions, ItemNode } from './nodes/item';
|
|
@@ -14,7 +15,7 @@ export { RoofSegmentNode, RoofType } from './nodes/roof-segment';
|
|
|
14
15
|
export { ScanNode } from './nodes/scan';
|
|
15
16
|
export { SiteNode } from './nodes/site';
|
|
16
17
|
export { SlabNode } from './nodes/slab';
|
|
17
|
-
export { StairNode } from './nodes/stair';
|
|
18
|
+
export { StairNode, StairRailingMode, StairTopLandingMode, StairType } from './nodes/stair';
|
|
18
19
|
export { AttachmentSide, StairSegmentNode, StairSegmentType } from './nodes/stair-segment';
|
|
19
20
|
export { WallNode } from './nodes/wall';
|
|
20
21
|
export { WindowNode } from './nodes/window';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schema/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAE3E,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAEvC,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,YAAY,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AAExF,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,eAAe,GAChB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzC,YAAY,EACV,eAAe,EACf,KAAK,EACL,UAAU,EACV,OAAO,EACP,MAAM,EACN,WAAW,EACX,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,aAAa,GACd,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAEvC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schema/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAE3E,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAEvC,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,YAAY,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AAExF,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,eAAe,GAChB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AACpD,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AACrE,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzC,YAAY,EACV,eAAe,EACf,KAAK,EACL,UAAU,EACV,OAAO,EACP,MAAM,EACN,WAAW,EACX,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,aAAa,GACd,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAEvC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAC3F,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAC1F,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAErD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA"}
|
package/dist/schema/index.js
CHANGED
|
@@ -9,6 +9,7 @@ export { DEFAULT_MATERIALS, MaterialPreset, MaterialProperties, MaterialSchema,
|
|
|
9
9
|
export { BuildingNode } from './nodes/building';
|
|
10
10
|
export { CeilingNode } from './nodes/ceiling';
|
|
11
11
|
export { DoorNode, DoorSegment } from './nodes/door';
|
|
12
|
+
export { FenceBaseStyle, FenceNode, FenceStyle } from './nodes/fence';
|
|
12
13
|
export { GuideNode } from './nodes/guide';
|
|
13
14
|
export { getScaledDimensions, ItemNode } from './nodes/item';
|
|
14
15
|
export { LevelNode } from './nodes/level';
|
|
@@ -18,7 +19,7 @@ export { ScanNode } from './nodes/scan';
|
|
|
18
19
|
// Nodes
|
|
19
20
|
export { SiteNode } from './nodes/site';
|
|
20
21
|
export { SlabNode } from './nodes/slab';
|
|
21
|
-
export { StairNode } from './nodes/stair';
|
|
22
|
+
export { StairNode, StairRailingMode, StairTopLandingMode, StairType } from './nodes/stair';
|
|
22
23
|
export { AttachmentSide, StairSegmentNode, StairSegmentType } from './nodes/stair-segment';
|
|
23
24
|
export { WallNode } from './nodes/wall';
|
|
24
25
|
export { WindowNode } from './nodes/window';
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const FenceStyle: z.ZodEnum<{
|
|
3
|
+
slat: "slat";
|
|
4
|
+
rail: "rail";
|
|
5
|
+
privacy: "privacy";
|
|
6
|
+
}>;
|
|
7
|
+
export declare const FenceBaseStyle: z.ZodEnum<{
|
|
8
|
+
floating: "floating";
|
|
9
|
+
grounded: "grounded";
|
|
10
|
+
}>;
|
|
11
|
+
export declare const FenceNode: z.ZodObject<{
|
|
12
|
+
object: z.ZodDefault<z.ZodLiteral<"node">>;
|
|
13
|
+
name: z.ZodOptional<z.ZodString>;
|
|
14
|
+
parentId: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
15
|
+
visible: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
16
|
+
camera: z.ZodOptional<z.ZodObject<{
|
|
17
|
+
position: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
|
|
18
|
+
target: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
|
|
19
|
+
mode: z.ZodDefault<z.ZodEnum<{
|
|
20
|
+
perspective: "perspective";
|
|
21
|
+
orthographic: "orthographic";
|
|
22
|
+
}>>;
|
|
23
|
+
fov: z.ZodOptional<z.ZodNumber>;
|
|
24
|
+
zoom: z.ZodOptional<z.ZodNumber>;
|
|
25
|
+
}, z.core.$strip>>;
|
|
26
|
+
metadata: z.ZodDefault<z.ZodOptional<z.ZodJSONSchema>>;
|
|
27
|
+
id: z.ZodDefault<z.ZodTemplateLiteral<`fence_${string}`>>;
|
|
28
|
+
type: z.ZodDefault<z.ZodLiteral<"fence">>;
|
|
29
|
+
start: z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>;
|
|
30
|
+
end: z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>;
|
|
31
|
+
height: z.ZodDefault<z.ZodNumber>;
|
|
32
|
+
thickness: z.ZodDefault<z.ZodNumber>;
|
|
33
|
+
baseHeight: z.ZodDefault<z.ZodNumber>;
|
|
34
|
+
postSpacing: z.ZodDefault<z.ZodNumber>;
|
|
35
|
+
postSize: z.ZodDefault<z.ZodNumber>;
|
|
36
|
+
topRailHeight: z.ZodDefault<z.ZodNumber>;
|
|
37
|
+
groundClearance: z.ZodDefault<z.ZodNumber>;
|
|
38
|
+
edgeInset: z.ZodDefault<z.ZodNumber>;
|
|
39
|
+
baseStyle: z.ZodDefault<z.ZodEnum<{
|
|
40
|
+
floating: "floating";
|
|
41
|
+
grounded: "grounded";
|
|
42
|
+
}>>;
|
|
43
|
+
color: z.ZodDefault<z.ZodString>;
|
|
44
|
+
style: z.ZodDefault<z.ZodEnum<{
|
|
45
|
+
slat: "slat";
|
|
46
|
+
rail: "rail";
|
|
47
|
+
privacy: "privacy";
|
|
48
|
+
}>>;
|
|
49
|
+
}, z.core.$strip>;
|
|
50
|
+
export type FenceNode = z.infer<typeof FenceNode>;
|
|
51
|
+
//# sourceMappingURL=fence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fence.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/fence.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,eAAO,MAAM,UAAU;;;;EAAsC,CAAA;AAC7D,eAAO,MAAM,cAAc;;;EAAmC,CAAA;AAE9D,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAyBrB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAA"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import dedent from 'dedent';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { BaseNode, nodeType, objectId } from '../base';
|
|
4
|
+
export const FenceStyle = z.enum(['slat', 'rail', 'privacy']);
|
|
5
|
+
export const FenceBaseStyle = z.enum(['floating', 'grounded']);
|
|
6
|
+
export const FenceNode = BaseNode.extend({
|
|
7
|
+
id: objectId('fence'),
|
|
8
|
+
type: nodeType('fence'),
|
|
9
|
+
start: z.tuple([z.number(), z.number()]),
|
|
10
|
+
end: z.tuple([z.number(), z.number()]),
|
|
11
|
+
height: z.number().default(1.8),
|
|
12
|
+
thickness: z.number().default(0.08),
|
|
13
|
+
baseHeight: z.number().default(0.22),
|
|
14
|
+
postSpacing: z.number().default(2),
|
|
15
|
+
postSize: z.number().default(0.1),
|
|
16
|
+
topRailHeight: z.number().default(0.04),
|
|
17
|
+
groundClearance: z.number().default(0),
|
|
18
|
+
edgeInset: z.number().default(0.015),
|
|
19
|
+
baseStyle: FenceBaseStyle.default('grounded'),
|
|
20
|
+
color: z.string().default('#ffffff'),
|
|
21
|
+
style: FenceStyle.default('slat'),
|
|
22
|
+
}).describe(dedent `
|
|
23
|
+
Fence node - used to represent a fence segment in the building/site level coordinate system
|
|
24
|
+
- start/end: fence endpoints in level coordinate system
|
|
25
|
+
- height/thickness: overall fence dimensions in meters
|
|
26
|
+
- baseHeight/postSpacing/postSize/topRailHeight: exact geometric controls from the plan3D fence model
|
|
27
|
+
- groundClearance/edgeInset/baseStyle: fence support and inset configuration
|
|
28
|
+
- color/style: visual appearance options
|
|
29
|
+
`);
|
|
@@ -17,7 +17,7 @@ export declare const LevelNode: z.ZodObject<{
|
|
|
17
17
|
metadata: z.ZodDefault<z.ZodOptional<z.ZodJSONSchema>>;
|
|
18
18
|
id: z.ZodDefault<z.ZodTemplateLiteral<`level_${string}`>>;
|
|
19
19
|
type: z.ZodDefault<z.ZodLiteral<"level">>;
|
|
20
|
-
children: z.ZodDefault<z.ZodArray<z.ZodUnion<readonly [z.ZodDefault<z.ZodTemplateLiteral<`wall_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`zone_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`slab_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`ceiling_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`roof_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`stair_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`scan_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`guide_${string}`>>]>>>;
|
|
20
|
+
children: z.ZodDefault<z.ZodArray<z.ZodUnion<readonly [z.ZodDefault<z.ZodTemplateLiteral<`wall_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`fence_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`zone_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`slab_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`ceiling_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`roof_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`stair_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`scan_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`guide_${string}`>>]>>>;
|
|
21
21
|
level: z.ZodDefault<z.ZodNumber>;
|
|
22
22
|
}, z.core.$strip>;
|
|
23
23
|
export type LevelNode = z.infer<typeof LevelNode>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"level.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/level.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;
|
|
1
|
+
{"version":3,"file":"level.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/level.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAYvB,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;iBA0BrB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAA"}
|
|
@@ -2,6 +2,7 @@ import dedent from 'dedent';
|
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { BaseNode, nodeType, objectId } from '../base';
|
|
4
4
|
import { CeilingNode } from './ceiling';
|
|
5
|
+
import { FenceNode } from './fence';
|
|
5
6
|
import { GuideNode } from './guide';
|
|
6
7
|
import { RoofNode } from './roof';
|
|
7
8
|
import { ScanNode } from './scan';
|
|
@@ -15,6 +16,7 @@ export const LevelNode = BaseNode.extend({
|
|
|
15
16
|
children: z
|
|
16
17
|
.array(z.union([
|
|
17
18
|
WallNode.shape.id,
|
|
19
|
+
FenceNode.shape.id,
|
|
18
20
|
ZoneNode.shape.id,
|
|
19
21
|
SlabNode.shape.id,
|
|
20
22
|
CeilingNode.shape.id,
|
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
export declare const StairRailingMode: z.ZodEnum<{
|
|
3
|
+
none: "none";
|
|
4
|
+
left: "left";
|
|
5
|
+
right: "right";
|
|
6
|
+
both: "both";
|
|
7
|
+
}>;
|
|
8
|
+
export declare const StairType: z.ZodEnum<{
|
|
9
|
+
straight: "straight";
|
|
10
|
+
curved: "curved";
|
|
11
|
+
spiral: "spiral";
|
|
12
|
+
}>;
|
|
13
|
+
export declare const StairTopLandingMode: z.ZodEnum<{
|
|
14
|
+
none: "none";
|
|
15
|
+
integrated: "integrated";
|
|
16
|
+
}>;
|
|
17
|
+
export type StairRailingMode = z.infer<typeof StairRailingMode>;
|
|
18
|
+
export type StairType = z.infer<typeof StairType>;
|
|
19
|
+
export type StairTopLandingMode = z.infer<typeof StairTopLandingMode>;
|
|
2
20
|
export declare const StairNode: z.ZodObject<{
|
|
3
21
|
object: z.ZodDefault<z.ZodLiteral<"node">>;
|
|
4
22
|
name: z.ZodOptional<z.ZodString>;
|
|
@@ -50,6 +68,32 @@ export declare const StairNode: z.ZodObject<{
|
|
|
50
68
|
}, z.core.$strip>>;
|
|
51
69
|
position: z.ZodDefault<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
|
|
52
70
|
rotation: z.ZodDefault<z.ZodNumber>;
|
|
71
|
+
stairType: z.ZodDefault<z.ZodEnum<{
|
|
72
|
+
straight: "straight";
|
|
73
|
+
curved: "curved";
|
|
74
|
+
spiral: "spiral";
|
|
75
|
+
}>>;
|
|
76
|
+
width: z.ZodDefault<z.ZodNumber>;
|
|
77
|
+
totalRise: z.ZodDefault<z.ZodNumber>;
|
|
78
|
+
stepCount: z.ZodDefault<z.ZodNumber>;
|
|
79
|
+
thickness: z.ZodDefault<z.ZodNumber>;
|
|
80
|
+
fillToFloor: z.ZodDefault<z.ZodBoolean>;
|
|
81
|
+
innerRadius: z.ZodDefault<z.ZodNumber>;
|
|
82
|
+
sweepAngle: z.ZodDefault<z.ZodNumber>;
|
|
83
|
+
topLandingMode: z.ZodDefault<z.ZodEnum<{
|
|
84
|
+
none: "none";
|
|
85
|
+
integrated: "integrated";
|
|
86
|
+
}>>;
|
|
87
|
+
topLandingDepth: z.ZodDefault<z.ZodNumber>;
|
|
88
|
+
showCenterColumn: z.ZodDefault<z.ZodBoolean>;
|
|
89
|
+
showStepSupports: z.ZodDefault<z.ZodBoolean>;
|
|
90
|
+
railingMode: z.ZodDefault<z.ZodEnum<{
|
|
91
|
+
none: "none";
|
|
92
|
+
left: "left";
|
|
93
|
+
right: "right";
|
|
94
|
+
both: "both";
|
|
95
|
+
}>>;
|
|
96
|
+
railingHeight: z.ZodDefault<z.ZodNumber>;
|
|
53
97
|
children: z.ZodDefault<z.ZodArray<z.ZodDefault<z.ZodTemplateLiteral<`sseg_${string}`>>>>;
|
|
54
98
|
}, z.core.$strip>;
|
|
55
99
|
export type StairNode = z.infer<typeof StairNode>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stair.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/stair.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAKvB,eAAO,MAAM,SAAS
|
|
1
|
+
{"version":3,"file":"stair.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/stair.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAKvB,eAAO,MAAM,gBAAgB;;;;;EAA4C,CAAA;AACzE,eAAO,MAAM,SAAS;;;;EAA2C,CAAA;AACjE,eAAO,MAAM,mBAAmB;;;EAAiC,CAAA;AAEjE,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAA;AAC/D,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAA;AACjD,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAErE,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA8CrB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAA"}
|
|
@@ -3,6 +3,9 @@ import { z } from 'zod';
|
|
|
3
3
|
import { BaseNode, nodeType, objectId } from '../base';
|
|
4
4
|
import { MaterialSchema } from '../material';
|
|
5
5
|
import { StairSegmentNode } from './stair-segment';
|
|
6
|
+
export const StairRailingMode = z.enum(['none', 'left', 'right', 'both']);
|
|
7
|
+
export const StairType = z.enum(['straight', 'curved', 'spiral']);
|
|
8
|
+
export const StairTopLandingMode = z.enum(['none', 'integrated']);
|
|
6
9
|
export const StairNode = BaseNode.extend({
|
|
7
10
|
id: objectId('stair'),
|
|
8
11
|
type: nodeType('stair'),
|
|
@@ -10,13 +13,41 @@ export const StairNode = BaseNode.extend({
|
|
|
10
13
|
position: z.tuple([z.number(), z.number(), z.number()]).default([0, 0, 0]),
|
|
11
14
|
// Rotation around Y axis in radians
|
|
12
15
|
rotation: z.number().default(0),
|
|
16
|
+
stairType: StairType.default('straight'),
|
|
17
|
+
width: z.number().default(1.0),
|
|
18
|
+
totalRise: z.number().default(2.5),
|
|
19
|
+
stepCount: z.number().default(10),
|
|
20
|
+
thickness: z.number().default(0.25),
|
|
21
|
+
fillToFloor: z.boolean().default(true),
|
|
22
|
+
innerRadius: z.number().default(0.9),
|
|
23
|
+
sweepAngle: z.number().default(Math.PI / 2),
|
|
24
|
+
topLandingMode: StairTopLandingMode.default('none'),
|
|
25
|
+
topLandingDepth: z.number().default(0.9),
|
|
26
|
+
showCenterColumn: z.boolean().default(true),
|
|
27
|
+
showStepSupports: z.boolean().default(true),
|
|
28
|
+
railingMode: StairRailingMode.default('none'),
|
|
29
|
+
railingHeight: z.number().default(0.92),
|
|
13
30
|
// Child stair segment IDs
|
|
14
31
|
children: z.array(StairSegmentNode.shape.id).default([]),
|
|
15
32
|
}).describe(dedent `
|
|
16
33
|
Stair node - a container for stair segments.
|
|
17
|
-
Acts as a group that holds one or more StairSegmentNodes (
|
|
18
|
-
|
|
34
|
+
Acts as a group that either holds one or more StairSegmentNodes (straight stairs)
|
|
35
|
+
or stores stair-level geometry properties for curved stairs.
|
|
19
36
|
- position: center position of the stair group
|
|
20
37
|
- rotation: rotation around Y axis
|
|
21
|
-
-
|
|
38
|
+
- stairType: straight (segment-based), curved (arc-based), or spiral
|
|
39
|
+
- width: stair width
|
|
40
|
+
- totalRise: total stair height
|
|
41
|
+
- stepCount: number of visible steps
|
|
42
|
+
- thickness: stair slab / tread thickness
|
|
43
|
+
- fillToFloor: whether the stair mass fills down to the floor or uses tread thickness only
|
|
44
|
+
- innerRadius: inner curve radius for curved stairs
|
|
45
|
+
- sweepAngle: total curved stair sweep in radians
|
|
46
|
+
- topLandingMode: optional integrated top landing for spiral stairs
|
|
47
|
+
- topLandingDepth: depth used to size the integrated spiral top landing
|
|
48
|
+
- showCenterColumn: whether spiral stairs render a center column
|
|
49
|
+
- showStepSupports: whether spiral stairs render step support brackets
|
|
50
|
+
- railingMode: whether to render railings and on which side(s)
|
|
51
|
+
- railingHeight: top height of the railing above the stair surface
|
|
52
|
+
- children: array of StairSegmentNode IDs for straight stairs
|
|
22
53
|
`);
|
package/dist/schema/types.d.ts
CHANGED
|
@@ -175,7 +175,7 @@ export declare const AnyNode: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
175
175
|
metadata: z.ZodDefault<z.ZodOptional<z.ZodJSONSchema>>;
|
|
176
176
|
id: z.ZodDefault<z.ZodTemplateLiteral<`level_${string}`>>;
|
|
177
177
|
type: z.ZodDefault<z.ZodLiteral<"level">>;
|
|
178
|
-
children: z.ZodDefault<z.ZodArray<z.ZodUnion<readonly [z.ZodDefault<z.ZodTemplateLiteral<`wall_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`zone_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`slab_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`ceiling_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`roof_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`stair_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`scan_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`guide_${string}`>>]>>>;
|
|
178
|
+
children: z.ZodDefault<z.ZodArray<z.ZodUnion<readonly [z.ZodDefault<z.ZodTemplateLiteral<`wall_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`fence_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`zone_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`slab_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`ceiling_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`roof_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`stair_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`scan_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`guide_${string}`>>]>>>;
|
|
179
179
|
level: z.ZodDefault<z.ZodNumber>;
|
|
180
180
|
}, z.core.$strip>, z.ZodObject<{
|
|
181
181
|
object: z.ZodDefault<z.ZodLiteral<"node">>;
|
|
@@ -241,6 +241,44 @@ export declare const AnyNode: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
241
241
|
interior: "interior";
|
|
242
242
|
exterior: "exterior";
|
|
243
243
|
}>>;
|
|
244
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
245
|
+
object: z.ZodDefault<z.ZodLiteral<"node">>;
|
|
246
|
+
name: z.ZodOptional<z.ZodString>;
|
|
247
|
+
parentId: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
248
|
+
visible: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
249
|
+
camera: z.ZodOptional<z.ZodObject<{
|
|
250
|
+
position: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
|
|
251
|
+
target: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
|
|
252
|
+
mode: z.ZodDefault<z.ZodEnum<{
|
|
253
|
+
perspective: "perspective";
|
|
254
|
+
orthographic: "orthographic";
|
|
255
|
+
}>>;
|
|
256
|
+
fov: z.ZodOptional<z.ZodNumber>;
|
|
257
|
+
zoom: z.ZodOptional<z.ZodNumber>;
|
|
258
|
+
}, z.core.$strip>>;
|
|
259
|
+
metadata: z.ZodDefault<z.ZodOptional<z.ZodJSONSchema>>;
|
|
260
|
+
id: z.ZodDefault<z.ZodTemplateLiteral<`fence_${string}`>>;
|
|
261
|
+
type: z.ZodDefault<z.ZodLiteral<"fence">>;
|
|
262
|
+
start: z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>;
|
|
263
|
+
end: z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>;
|
|
264
|
+
height: z.ZodDefault<z.ZodNumber>;
|
|
265
|
+
thickness: z.ZodDefault<z.ZodNumber>;
|
|
266
|
+
baseHeight: z.ZodDefault<z.ZodNumber>;
|
|
267
|
+
postSpacing: z.ZodDefault<z.ZodNumber>;
|
|
268
|
+
postSize: z.ZodDefault<z.ZodNumber>;
|
|
269
|
+
topRailHeight: z.ZodDefault<z.ZodNumber>;
|
|
270
|
+
groundClearance: z.ZodDefault<z.ZodNumber>;
|
|
271
|
+
edgeInset: z.ZodDefault<z.ZodNumber>;
|
|
272
|
+
baseStyle: z.ZodDefault<z.ZodEnum<{
|
|
273
|
+
floating: "floating";
|
|
274
|
+
grounded: "grounded";
|
|
275
|
+
}>>;
|
|
276
|
+
color: z.ZodDefault<z.ZodString>;
|
|
277
|
+
style: z.ZodDefault<z.ZodEnum<{
|
|
278
|
+
slat: "slat";
|
|
279
|
+
rail: "rail";
|
|
280
|
+
privacy: "privacy";
|
|
281
|
+
}>>;
|
|
244
282
|
}, z.core.$strip>, z.ZodObject<{
|
|
245
283
|
object: z.ZodDefault<z.ZodLiteral<"node">>;
|
|
246
284
|
name: z.ZodOptional<z.ZodString>;
|
|
@@ -630,6 +668,32 @@ export declare const AnyNode: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
630
668
|
}, z.core.$strip>>;
|
|
631
669
|
position: z.ZodDefault<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
|
|
632
670
|
rotation: z.ZodDefault<z.ZodNumber>;
|
|
671
|
+
stairType: z.ZodDefault<z.ZodEnum<{
|
|
672
|
+
straight: "straight";
|
|
673
|
+
curved: "curved";
|
|
674
|
+
spiral: "spiral";
|
|
675
|
+
}>>;
|
|
676
|
+
width: z.ZodDefault<z.ZodNumber>;
|
|
677
|
+
totalRise: z.ZodDefault<z.ZodNumber>;
|
|
678
|
+
stepCount: z.ZodDefault<z.ZodNumber>;
|
|
679
|
+
thickness: z.ZodDefault<z.ZodNumber>;
|
|
680
|
+
fillToFloor: z.ZodDefault<z.ZodBoolean>;
|
|
681
|
+
innerRadius: z.ZodDefault<z.ZodNumber>;
|
|
682
|
+
sweepAngle: z.ZodDefault<z.ZodNumber>;
|
|
683
|
+
topLandingMode: z.ZodDefault<z.ZodEnum<{
|
|
684
|
+
none: "none";
|
|
685
|
+
integrated: "integrated";
|
|
686
|
+
}>>;
|
|
687
|
+
topLandingDepth: z.ZodDefault<z.ZodNumber>;
|
|
688
|
+
showCenterColumn: z.ZodDefault<z.ZodBoolean>;
|
|
689
|
+
showStepSupports: z.ZodDefault<z.ZodBoolean>;
|
|
690
|
+
railingMode: z.ZodDefault<z.ZodEnum<{
|
|
691
|
+
none: "none";
|
|
692
|
+
left: "left";
|
|
693
|
+
right: "right";
|
|
694
|
+
both: "both";
|
|
695
|
+
}>>;
|
|
696
|
+
railingHeight: z.ZodDefault<z.ZodNumber>;
|
|
633
697
|
children: z.ZodDefault<z.ZodArray<z.ZodDefault<z.ZodTemplateLiteral<`sseg_${string}`>>>>;
|
|
634
698
|
}, z.core.$strip>, z.ZodObject<{
|
|
635
699
|
object: z.ZodDefault<z.ZodLiteral<"node">>;
|
|
@@ -691,9 +755,9 @@ export declare const AnyNode: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
691
755
|
height: z.ZodDefault<z.ZodNumber>;
|
|
692
756
|
stepCount: z.ZodDefault<z.ZodNumber>;
|
|
693
757
|
attachmentSide: z.ZodDefault<z.ZodEnum<{
|
|
694
|
-
front: "front";
|
|
695
758
|
left: "left";
|
|
696
759
|
right: "right";
|
|
760
|
+
front: "front";
|
|
697
761
|
}>>;
|
|
698
762
|
fillToFloor: z.ZodDefault<z.ZodBoolean>;
|
|
699
763
|
thickness: z.ZodDefault<z.ZodNumber>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/schema/types.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,KAAK,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/schema/types.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,KAAK,CAAA;AAmBnB,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAkBlB,CAAA;AAEF,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,OAAO,CAAC,CAAA;AAC7C,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;AACzC,MAAM,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA"}
|
package/dist/schema/types.js
CHANGED
|
@@ -2,6 +2,7 @@ import z from 'zod';
|
|
|
2
2
|
import { BuildingNode } from './nodes/building';
|
|
3
3
|
import { CeilingNode } from './nodes/ceiling';
|
|
4
4
|
import { DoorNode } from './nodes/door';
|
|
5
|
+
import { FenceNode } from './nodes/fence';
|
|
5
6
|
import { GuideNode } from './nodes/guide';
|
|
6
7
|
import { ItemNode } from './nodes/item';
|
|
7
8
|
import { LevelNode } from './nodes/level';
|
|
@@ -20,6 +21,7 @@ export const AnyNode = z.discriminatedUnion('type', [
|
|
|
20
21
|
BuildingNode,
|
|
21
22
|
LevelNode,
|
|
22
23
|
WallNode,
|
|
24
|
+
FenceNode,
|
|
23
25
|
ItemNode,
|
|
24
26
|
ZoneNode,
|
|
25
27
|
SlabNode,
|
package/dist/store/use-scene.js
CHANGED
|
@@ -284,7 +284,7 @@ useScene.temporal.subscribe((state) => {
|
|
|
284
284
|
// Mark sibling nodes dirty so they can update their geometry
|
|
285
285
|
// (e.g. adjacent walls need to recalculate miter/junction geometry)
|
|
286
286
|
const parent = currentNodes[parentId];
|
|
287
|
-
if (parent && 'children' in parent) {
|
|
287
|
+
if (parent && 'children' in parent && Array.isArray(parent.children)) {
|
|
288
288
|
for (const childId of parent.children) {
|
|
289
289
|
markDirty(childId);
|
|
290
290
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fence-system.d.ts","sourceRoot":"","sources":["../../../src/systems/fence/fence-system.tsx"],"names":[],"mappings":"AA+HA,eAAO,MAAM,WAAW,YAiBvB,CAAA"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { useFrame } from '@react-three/fiber';
|
|
2
|
+
import * as THREE from 'three';
|
|
3
|
+
import { mergeGeometries } from 'three/examples/jsm/utils/BufferGeometryUtils.js';
|
|
4
|
+
import { sceneRegistry } from '../../hooks/scene-registry/scene-registry';
|
|
5
|
+
import useScene from '../../store/use-scene';
|
|
6
|
+
function getStyleDefaults(style) {
|
|
7
|
+
if (style === 'privacy') {
|
|
8
|
+
return { spacingFactor: 0.42, postFactor: 1.35, baseFactor: 1.2, topFactor: 1.2 };
|
|
9
|
+
}
|
|
10
|
+
if (style === 'rail') {
|
|
11
|
+
return { spacingFactor: 0.68, postFactor: 0.8, baseFactor: 0.85, topFactor: 0.85 };
|
|
12
|
+
}
|
|
13
|
+
return { spacingFactor: 0.3, postFactor: 0.55, baseFactor: 1, topFactor: 0.75 };
|
|
14
|
+
}
|
|
15
|
+
function createFenceParts(fence) {
|
|
16
|
+
const parts = [];
|
|
17
|
+
const length = Math.max(Math.hypot(fence.end[0] - fence.start[0], fence.end[1] - fence.start[1]), 0.01);
|
|
18
|
+
const panelDepth = Math.max(fence.thickness, 0.03);
|
|
19
|
+
const clearance = Math.max(fence.groundClearance, 0);
|
|
20
|
+
const styleDefaults = getStyleDefaults(fence.style);
|
|
21
|
+
const baseHeight = Math.max(fence.baseHeight * styleDefaults.baseFactor, 0.04);
|
|
22
|
+
const topRailHeight = Math.max(fence.topRailHeight * styleDefaults.topFactor, 0.01);
|
|
23
|
+
const verticalHeight = Math.max(fence.height - baseHeight - topRailHeight, 0.08);
|
|
24
|
+
const postWidth = Math.max(fence.postSize * styleDefaults.postFactor, 0.01);
|
|
25
|
+
const spacing = Math.max(fence.postSpacing * styleDefaults.spacingFactor, postWidth * 1.2);
|
|
26
|
+
const edgeInset = Math.max(fence.edgeInset ?? 0.015, 0.005);
|
|
27
|
+
const isFloating = fence.baseStyle === 'floating';
|
|
28
|
+
const baseY = isFloating ? clearance : 0;
|
|
29
|
+
const effectiveBaseHeight = baseHeight;
|
|
30
|
+
if (!isFloating) {
|
|
31
|
+
parts.push({
|
|
32
|
+
position: [0, baseY + effectiveBaseHeight / 2, 0],
|
|
33
|
+
scale: [length, effectiveBaseHeight, panelDepth * 1.05],
|
|
34
|
+
});
|
|
35
|
+
parts.push({
|
|
36
|
+
position: [0, baseY + effectiveBaseHeight + verticalHeight * 0.15, 0],
|
|
37
|
+
scale: [length, topRailHeight * 0.8, panelDepth * 0.35],
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
const count = Math.max(2, Math.floor((length - edgeInset * 2) / spacing) + 1);
|
|
41
|
+
const step = count > 1 ? (length - edgeInset * 2) / (count - 1) : 0;
|
|
42
|
+
const startX = -length / 2 + edgeInset;
|
|
43
|
+
const verticalY = baseY + effectiveBaseHeight + verticalHeight / 2;
|
|
44
|
+
for (let index = 0; index < count; index += 1) {
|
|
45
|
+
const x = count === 1 ? 0 : startX + step * index;
|
|
46
|
+
let posX = x;
|
|
47
|
+
const isEdgePost = index === 0 || index === count - 1;
|
|
48
|
+
if (count > 1) {
|
|
49
|
+
if (index === 0)
|
|
50
|
+
posX = -length / 2 + edgeInset + postWidth / 2;
|
|
51
|
+
else if (index === count - 1)
|
|
52
|
+
posX = length / 2 - edgeInset - postWidth / 2;
|
|
53
|
+
}
|
|
54
|
+
const postHeight = isFloating && isEdgePost
|
|
55
|
+
? effectiveBaseHeight + verticalHeight + topRailHeight + clearance
|
|
56
|
+
: verticalHeight;
|
|
57
|
+
const postY = isFloating && isEdgePost ? postHeight / 2 : verticalY;
|
|
58
|
+
parts.push({
|
|
59
|
+
position: [posX, postY, 0],
|
|
60
|
+
scale: [postWidth, postHeight, Math.max(panelDepth * 0.35, 0.012)],
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
parts.push({
|
|
64
|
+
position: [0, baseY + effectiveBaseHeight + verticalHeight + topRailHeight / 2, 0],
|
|
65
|
+
scale: [length, topRailHeight, Math.max(panelDepth * 0.55, 0.018)],
|
|
66
|
+
});
|
|
67
|
+
if (isFloating) {
|
|
68
|
+
parts.push({
|
|
69
|
+
position: [0, baseY + effectiveBaseHeight + topRailHeight / 2, 0],
|
|
70
|
+
scale: [length, topRailHeight, Math.max(panelDepth * 0.55, 0.018)],
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
return parts;
|
|
74
|
+
}
|
|
75
|
+
function generateFenceGeometry(fence) {
|
|
76
|
+
const parts = createFenceParts(fence);
|
|
77
|
+
const geometries = parts.map((part) => {
|
|
78
|
+
const geometry = new THREE.BoxGeometry(1, 1, 1);
|
|
79
|
+
geometry.scale(part.scale[0], part.scale[1], part.scale[2]);
|
|
80
|
+
geometry.translate(part.position[0], part.position[1], part.position[2]);
|
|
81
|
+
return geometry;
|
|
82
|
+
});
|
|
83
|
+
const merged = mergeGeometries(geometries, false) ?? new THREE.BufferGeometry();
|
|
84
|
+
geometries.forEach((geometry) => geometry.dispose());
|
|
85
|
+
merged.computeVertexNormals();
|
|
86
|
+
return merged;
|
|
87
|
+
}
|
|
88
|
+
function updateFenceGeometry(fenceId) {
|
|
89
|
+
const node = useScene.getState().nodes[fenceId];
|
|
90
|
+
if (!node || node.type !== 'fence')
|
|
91
|
+
return;
|
|
92
|
+
const mesh = sceneRegistry.nodes.get(fenceId);
|
|
93
|
+
if (!mesh)
|
|
94
|
+
return;
|
|
95
|
+
const newGeometry = generateFenceGeometry(node);
|
|
96
|
+
mesh.geometry.dispose();
|
|
97
|
+
mesh.geometry = newGeometry;
|
|
98
|
+
const centerX = (node.start[0] + node.end[0]) / 2;
|
|
99
|
+
const centerZ = (node.start[1] + node.end[1]) / 2;
|
|
100
|
+
const angle = Math.atan2(node.end[1] - node.start[1], node.end[0] - node.start[0]);
|
|
101
|
+
mesh.position.set(centerX, 0, centerZ);
|
|
102
|
+
mesh.rotation.set(0, -angle, 0);
|
|
103
|
+
}
|
|
104
|
+
export const FenceSystem = () => {
|
|
105
|
+
const dirtyNodes = useScene((state) => state.dirtyNodes);
|
|
106
|
+
const clearDirty = useScene((state) => state.clearDirty);
|
|
107
|
+
useFrame(() => {
|
|
108
|
+
if (dirtyNodes.size === 0)
|
|
109
|
+
return;
|
|
110
|
+
const nodes = useScene.getState().nodes;
|
|
111
|
+
dirtyNodes.forEach((id) => {
|
|
112
|
+
const node = nodes[id];
|
|
113
|
+
if (!node || node.type !== 'fence')
|
|
114
|
+
return;
|
|
115
|
+
updateFenceGeometry(id);
|
|
116
|
+
clearDirty(id);
|
|
117
|
+
});
|
|
118
|
+
}, 4);
|
|
119
|
+
return null;
|
|
120
|
+
};
|
|
@@ -246,14 +246,16 @@ function updateMergedStairGeometry(stairNode, group, nodes) {
|
|
|
246
246
|
const mergedMesh = group.getObjectByName('merged-stair');
|
|
247
247
|
if (!mergedMesh)
|
|
248
248
|
return;
|
|
249
|
+
if (stairNode.stairType === 'curved' || stairNode.stairType === 'spiral') {
|
|
250
|
+
replaceMeshGeometry(mergedMesh, createEmptyGeometry());
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
249
253
|
const children = stairNode.children ?? [];
|
|
250
254
|
const segments = children
|
|
251
255
|
.map((childId) => nodes[childId])
|
|
252
256
|
.filter((n) => n?.type === 'stair-segment');
|
|
253
257
|
if (segments.length === 0) {
|
|
254
|
-
mergedMesh
|
|
255
|
-
mergedMesh.geometry = new THREE.BufferGeometry();
|
|
256
|
-
mergedMesh.geometry.setAttribute('position', new THREE.Float32BufferAttribute([], 3));
|
|
258
|
+
replaceMeshGeometry(mergedMesh, createEmptyGeometry());
|
|
257
259
|
return;
|
|
258
260
|
}
|
|
259
261
|
// Compute chained transforms for segments
|
|
@@ -271,11 +273,8 @@ function updateMergedStairGeometry(stairNode, group, nodes) {
|
|
|
271
273
|
geo.applyMatrix4(_matrix);
|
|
272
274
|
geometries.push(geo);
|
|
273
275
|
}
|
|
274
|
-
const merged = mergeGeometries(geometries, false);
|
|
275
|
-
|
|
276
|
-
mergedMesh.geometry.dispose();
|
|
277
|
-
mergedMesh.geometry = merged;
|
|
278
|
-
}
|
|
276
|
+
const merged = mergeGeometries(geometries, false) ?? createEmptyGeometry();
|
|
277
|
+
replaceMeshGeometry(mergedMesh, merged);
|
|
279
278
|
// Dispose individual geometries
|
|
280
279
|
for (const geo of geometries) {
|
|
281
280
|
geo.dispose();
|
|
@@ -332,6 +331,312 @@ function rotateXZ(x, z, angle) {
|
|
|
332
331
|
const sin = Math.sin(angle);
|
|
333
332
|
return [x * cos + z * sin, -x * sin + z * cos];
|
|
334
333
|
}
|
|
334
|
+
function createEmptyGeometry() {
|
|
335
|
+
const geometry = new THREE.BufferGeometry();
|
|
336
|
+
geometry.setAttribute('position', new THREE.Float32BufferAttribute([], 3));
|
|
337
|
+
return geometry;
|
|
338
|
+
}
|
|
339
|
+
function replaceMeshGeometry(mesh, geometry) {
|
|
340
|
+
mesh.geometry.dispose();
|
|
341
|
+
mesh.geometry = geometry;
|
|
342
|
+
}
|
|
343
|
+
function generateStairRailingGeometry(stairNode, segments, transforms) {
|
|
344
|
+
const railingMode = stairNode.railingMode ?? 'none';
|
|
345
|
+
if (railingMode === 'none') {
|
|
346
|
+
return createEmptyGeometry();
|
|
347
|
+
}
|
|
348
|
+
const railHeight = Math.max(0.5, stairNode.railingHeight ?? 0.92);
|
|
349
|
+
const midRailHeight = Math.max(railHeight * 0.45, 0.35);
|
|
350
|
+
const railRadius = 0.022;
|
|
351
|
+
const postRadius = 0.018;
|
|
352
|
+
const inset = 0.06;
|
|
353
|
+
const landingInset = 0.08;
|
|
354
|
+
const geometries = [];
|
|
355
|
+
const segmentRailPaths = buildStairRailPaths(segments, transforms, railingMode, inset, landingInset);
|
|
356
|
+
for (const segmentRailPath of segmentRailPaths) {
|
|
357
|
+
for (const sidePath of segmentRailPath.sidePaths) {
|
|
358
|
+
const points = sidePath.points;
|
|
359
|
+
if (points.length === 0)
|
|
360
|
+
continue;
|
|
361
|
+
geometries.push(...buildBalusterGeometries(points, railHeight, postRadius));
|
|
362
|
+
geometries.push(...buildOffsetRailSegmentGeometries(points, railHeight, railRadius));
|
|
363
|
+
geometries.push(...buildOffsetRailSegmentGeometries(points, midRailHeight, railRadius * 0.8));
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
for (let index = 1; index < segmentRailPaths.length; index++) {
|
|
367
|
+
const previousPath = segmentRailPaths[index - 1];
|
|
368
|
+
const currentPath = segmentRailPaths[index];
|
|
369
|
+
if (!(previousPath && currentPath && currentPath.connectFromPrevious))
|
|
370
|
+
continue;
|
|
371
|
+
if (previousPath.segment.segmentType === 'landing')
|
|
372
|
+
continue;
|
|
373
|
+
for (const sidePath of currentPath.sidePaths) {
|
|
374
|
+
if (currentPath.segment.segmentType === 'landing')
|
|
375
|
+
continue;
|
|
376
|
+
const currentPoint = sidePath.points[0];
|
|
377
|
+
if (!currentPoint)
|
|
378
|
+
continue;
|
|
379
|
+
const previousSidePath = [...previousPath.sidePaths]
|
|
380
|
+
.map((entry) => ({
|
|
381
|
+
entry,
|
|
382
|
+
distance: entry.points.length
|
|
383
|
+
? entry.points[entry.points.length - 1].distanceTo(currentPoint)
|
|
384
|
+
: Number.POSITIVE_INFINITY,
|
|
385
|
+
}))
|
|
386
|
+
.sort((left, right) => left.distance - right.distance)[0]?.entry;
|
|
387
|
+
const previousPoint = previousSidePath && previousSidePath.points.length > 0
|
|
388
|
+
? previousSidePath.points[previousSidePath.points.length - 1]
|
|
389
|
+
: null;
|
|
390
|
+
if (!(previousPoint && currentPoint))
|
|
391
|
+
continue;
|
|
392
|
+
const connectorPoints = [previousPoint, currentPoint];
|
|
393
|
+
geometries.push(...buildOffsetRailSegmentGeometries(connectorPoints, railHeight, railRadius));
|
|
394
|
+
geometries.push(...buildOffsetRailSegmentGeometries(connectorPoints, midRailHeight, railRadius * 0.8));
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
const merged = mergeGeometries(geometries, false) ?? createEmptyGeometry();
|
|
398
|
+
for (const geometry of geometries) {
|
|
399
|
+
geometry.dispose();
|
|
400
|
+
}
|
|
401
|
+
return merged;
|
|
402
|
+
}
|
|
403
|
+
function buildStairRailPaths(segments, transforms, railingMode, inset, landingInset) {
|
|
404
|
+
const layouts = computeStairRailLayouts(segments, transforms);
|
|
405
|
+
if (railingMode === 'both') {
|
|
406
|
+
const isStraightLineDoubleLandingLayout = segments.length === 4 &&
|
|
407
|
+
segments[0]?.segmentType === 'stair' &&
|
|
408
|
+
segments[1]?.segmentType === 'landing' &&
|
|
409
|
+
segments[2]?.segmentType === 'stair' &&
|
|
410
|
+
segments[2]?.attachmentSide === 'front' &&
|
|
411
|
+
segments[3]?.segmentType === 'landing' &&
|
|
412
|
+
segments[3]?.attachmentSide === 'front';
|
|
413
|
+
return layouts.map((layout, index) => {
|
|
414
|
+
const segment = layout.segment;
|
|
415
|
+
const previousSegment = index > 0 ? segments[index - 1] : undefined;
|
|
416
|
+
const nextSegment = index < segments.length - 1 ? segments[index + 1] : undefined;
|
|
417
|
+
const hideLandingRailing = segment.segmentType === 'landing' &&
|
|
418
|
+
previousSegment?.segmentType === 'stair' &&
|
|
419
|
+
nextSegment?.segmentType === 'stair';
|
|
420
|
+
const visualTurnSide = nextSegment?.attachmentSide;
|
|
421
|
+
const sideCandidates = hideLandingRailing
|
|
422
|
+
? visualTurnSide === 'left'
|
|
423
|
+
? ['front', 'right']
|
|
424
|
+
: visualTurnSide === 'right'
|
|
425
|
+
? ['front', 'left']
|
|
426
|
+
: ['left', 'right']
|
|
427
|
+
: segment.segmentType === 'landing'
|
|
428
|
+
? nextSegment?.segmentType === 'landing' && visualTurnSide === 'left'
|
|
429
|
+
? ['front', 'right']
|
|
430
|
+
: nextSegment?.segmentType === 'landing' && visualTurnSide === 'right'
|
|
431
|
+
? ['front', 'left']
|
|
432
|
+
: visualTurnSide === 'left'
|
|
433
|
+
? ['right']
|
|
434
|
+
: visualTurnSide === 'right'
|
|
435
|
+
? ['left']
|
|
436
|
+
: ['left', 'right']
|
|
437
|
+
: ['left', 'right'];
|
|
438
|
+
const sidePaths = sideCandidates
|
|
439
|
+
.map((side) => buildSegmentRailPath(layout, side, previousSegment, nextSegment, inset, landingInset))
|
|
440
|
+
.filter((entry) => entry !== null);
|
|
441
|
+
return {
|
|
442
|
+
segment,
|
|
443
|
+
sidePaths: isStraightLineDoubleLandingLayout && index === 1
|
|
444
|
+
? (['left', 'right']
|
|
445
|
+
.map((side) => buildSegmentRailPath(layout, side, previousSegment, nextSegment, inset, landingInset))
|
|
446
|
+
.filter((entry) => entry !== null))
|
|
447
|
+
: sidePaths,
|
|
448
|
+
connectFromPrevious: index > 0 &&
|
|
449
|
+
!(previousSegment?.segmentType === 'landing' && segment.segmentType === 'landing'),
|
|
450
|
+
};
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
const isStraightLineDoubleLandingLayout = segments.length === 4 &&
|
|
454
|
+
segments[0]?.segmentType === 'stair' &&
|
|
455
|
+
segments[1]?.segmentType === 'landing' &&
|
|
456
|
+
segments[2]?.segmentType === 'stair' &&
|
|
457
|
+
segments[2]?.attachmentSide === 'front' &&
|
|
458
|
+
segments[3]?.segmentType === 'landing' &&
|
|
459
|
+
segments[3]?.attachmentSide === 'front';
|
|
460
|
+
const resolved = [];
|
|
461
|
+
layouts.forEach((layout, index) => {
|
|
462
|
+
const segment = layout.segment;
|
|
463
|
+
const previousSegment = index > 0 ? segments[index - 1] : undefined;
|
|
464
|
+
const nextSegment = index < segments.length - 1 ? segments[index + 1] : undefined;
|
|
465
|
+
const nextAttachmentSide = nextSegment?.attachmentSide;
|
|
466
|
+
const isMiddleLandingBetweenFlights = segment.segmentType === 'landing' &&
|
|
467
|
+
previousSegment?.segmentType === 'stair' &&
|
|
468
|
+
nextSegment?.segmentType === 'stair';
|
|
469
|
+
const suppressLandingRailing = segment.segmentType === 'landing' &&
|
|
470
|
+
nextSegment?.segmentType === 'landing' &&
|
|
471
|
+
nextAttachmentSide === railingMode;
|
|
472
|
+
const landingContinuesOnPreferredSide = segment.segmentType === 'landing'
|
|
473
|
+
? nextAttachmentSide == null ||
|
|
474
|
+
nextAttachmentSide === 'front' ||
|
|
475
|
+
nextAttachmentSide === railingMode
|
|
476
|
+
: true;
|
|
477
|
+
const sidePaths = suppressLandingRailing
|
|
478
|
+
? []
|
|
479
|
+
: segment.segmentType !== 'landing'
|
|
480
|
+
? [
|
|
481
|
+
buildSegmentRailPath(layout, railingMode, previousSegment, nextSegment, inset, landingInset),
|
|
482
|
+
]
|
|
483
|
+
: isStraightLineDoubleLandingLayout
|
|
484
|
+
? [
|
|
485
|
+
buildSegmentRailPath(layout, railingMode, previousSegment, nextSegment, inset, landingInset),
|
|
486
|
+
]
|
|
487
|
+
: isMiddleLandingBetweenFlights && railingMode === 'left'
|
|
488
|
+
? nextAttachmentSide === 'right'
|
|
489
|
+
? [
|
|
490
|
+
buildSegmentRailPath(layout, 'front', previousSegment, nextSegment, inset, landingInset),
|
|
491
|
+
buildSegmentRailPath(layout, 'left', previousSegment, nextSegment, inset, landingInset),
|
|
492
|
+
]
|
|
493
|
+
: []
|
|
494
|
+
: isMiddleLandingBetweenFlights && railingMode === 'right'
|
|
495
|
+
? nextAttachmentSide === 'left'
|
|
496
|
+
? [
|
|
497
|
+
buildSegmentRailPath(layout, 'front', previousSegment, nextSegment, inset, landingInset),
|
|
498
|
+
buildSegmentRailPath(layout, 'right', previousSegment, nextSegment, inset, landingInset),
|
|
499
|
+
]
|
|
500
|
+
: []
|
|
501
|
+
: nextSegment?.segmentType === 'landing' &&
|
|
502
|
+
nextAttachmentSide != null &&
|
|
503
|
+
nextAttachmentSide !== 'front' &&
|
|
504
|
+
nextAttachmentSide !== railingMode
|
|
505
|
+
? [
|
|
506
|
+
buildSegmentRailPath(layout, 'front', previousSegment, nextSegment, inset, landingInset),
|
|
507
|
+
buildSegmentRailPath(layout, railingMode, previousSegment, nextSegment, inset, landingInset),
|
|
508
|
+
]
|
|
509
|
+
: [
|
|
510
|
+
buildSegmentRailPath(layout, railingMode, previousSegment, nextSegment, inset, landingInset),
|
|
511
|
+
];
|
|
512
|
+
resolved.push({
|
|
513
|
+
segment,
|
|
514
|
+
sidePaths: sidePaths.filter((entry) => entry !== null),
|
|
515
|
+
connectFromPrevious: index > 0 &&
|
|
516
|
+
!suppressLandingRailing &&
|
|
517
|
+
sidePaths.length > 0 &&
|
|
518
|
+
(segment.segmentType === 'landing' ? landingContinuesOnPreferredSide : true),
|
|
519
|
+
});
|
|
520
|
+
});
|
|
521
|
+
return resolved;
|
|
522
|
+
}
|
|
523
|
+
function computeStairRailLayouts(segments, transforms) {
|
|
524
|
+
return segments.map((segment, index) => {
|
|
525
|
+
const transform = transforms[index];
|
|
526
|
+
const [centerOffsetX, centerOffsetZ] = rotateXZ(0, segment.length / 2, transform.rotation);
|
|
527
|
+
return {
|
|
528
|
+
center: [transform.position[0] + centerOffsetX, transform.position[2] + centerOffsetZ],
|
|
529
|
+
elevation: transform.position[1],
|
|
530
|
+
rotation: transform.rotation,
|
|
531
|
+
segment,
|
|
532
|
+
};
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
function buildSegmentRailPath(layout, side, previousSegment, nextSegment, inset, landingInset) {
|
|
536
|
+
const segment = layout.segment;
|
|
537
|
+
const segmentSteps = Math.max(1, segment.segmentType === 'landing' ? 1 : segment.stepCount);
|
|
538
|
+
const segmentStepDepth = segment.length / segmentSteps;
|
|
539
|
+
const segmentStepHeight = segment.segmentType === 'landing' ? 0 : segment.height / segmentSteps;
|
|
540
|
+
const segmentTopThickness = getSegmentTopThickness(segment);
|
|
541
|
+
const flightSideOffset = side === 'left' ? segment.width / 2 - 0.045 : -segment.width / 2 + 0.045;
|
|
542
|
+
const flightStartX = previousSegment?.segmentType === 'landing' ? -segment.length / 2 + landingInset : -segment.length / 2;
|
|
543
|
+
const flightEndX = nextSegment?.segmentType === 'landing' ? segment.length / 2 - landingInset : segment.length / 2;
|
|
544
|
+
if (segment.segmentType === 'landing') {
|
|
545
|
+
return buildLandingRailPathFromScratch(layout, side, previousSegment, nextSegment, segmentTopThickness, landingInset);
|
|
546
|
+
}
|
|
547
|
+
return {
|
|
548
|
+
side,
|
|
549
|
+
points: [
|
|
550
|
+
...(previousSegment?.segmentType === 'landing'
|
|
551
|
+
? []
|
|
552
|
+
: [
|
|
553
|
+
toRailLayoutWorldPoint(layout, flightStartX, segmentTopThickness, flightSideOffset),
|
|
554
|
+
]),
|
|
555
|
+
...Array.from({ length: segmentSteps }).map((_, index) => toRailLayoutWorldPoint(layout, -segment.length / 2 + segmentStepDepth * index + segmentStepDepth / 2, segmentStepHeight * (index + 1), flightSideOffset)),
|
|
556
|
+
...(nextSegment?.segmentType === 'landing'
|
|
557
|
+
? []
|
|
558
|
+
: [
|
|
559
|
+
toRailLayoutWorldPoint(layout, flightEndX, segment.height, flightSideOffset),
|
|
560
|
+
]),
|
|
561
|
+
],
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
function buildLandingRailPathFromScratch(layout, side, previousSegment, nextSegment, topY, inset) {
|
|
565
|
+
const segment = layout.segment;
|
|
566
|
+
const backX = -segment.length / 2 + inset;
|
|
567
|
+
const frontX = segment.length / 2 - inset;
|
|
568
|
+
const leftZ = segment.width / 2 - inset;
|
|
569
|
+
const rightZ = -segment.width / 2 + inset;
|
|
570
|
+
const edgePoints = side === 'left'
|
|
571
|
+
? [
|
|
572
|
+
toRailLayoutWorldPoint(layout, backX, topY, leftZ),
|
|
573
|
+
toRailLayoutWorldPoint(layout, frontX, topY, leftZ),
|
|
574
|
+
]
|
|
575
|
+
: side === 'right'
|
|
576
|
+
? [
|
|
577
|
+
toRailLayoutWorldPoint(layout, backX, topY, rightZ),
|
|
578
|
+
toRailLayoutWorldPoint(layout, frontX, topY, rightZ),
|
|
579
|
+
]
|
|
580
|
+
: [
|
|
581
|
+
// When the next flight turns, rail the visible leading edge nearest the turn opening.
|
|
582
|
+
toRailLayoutWorldPoint(layout, previousSegment?.segmentType === 'stair' &&
|
|
583
|
+
nextSegment?.attachmentSide &&
|
|
584
|
+
nextSegment.attachmentSide !== 'front'
|
|
585
|
+
? backX
|
|
586
|
+
: frontX, topY, leftZ),
|
|
587
|
+
toRailLayoutWorldPoint(layout, previousSegment?.segmentType === 'stair' &&
|
|
588
|
+
nextSegment?.attachmentSide &&
|
|
589
|
+
nextSegment.attachmentSide !== 'front'
|
|
590
|
+
? backX
|
|
591
|
+
: frontX, topY, rightZ),
|
|
592
|
+
];
|
|
593
|
+
return {
|
|
594
|
+
side,
|
|
595
|
+
points: edgePoints,
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
function toRailLayoutWorldPoint(layout, localX, localY, localZ) {
|
|
599
|
+
const [offsetX, offsetZ] = rotateXZ(localZ, localX, layout.rotation);
|
|
600
|
+
return new THREE.Vector3(layout.center[0] + offsetX, layout.elevation + localY, layout.center[1] + offsetZ);
|
|
601
|
+
}
|
|
602
|
+
function buildOffsetRailSegmentGeometries(points, heightOffset, radius) {
|
|
603
|
+
const geometries = [];
|
|
604
|
+
for (let index = 0; index < points.length - 1; index++) {
|
|
605
|
+
const start = points[index];
|
|
606
|
+
const end = points[index + 1];
|
|
607
|
+
if (!(start && end))
|
|
608
|
+
continue;
|
|
609
|
+
const segmentGeometry = createCylinderBetweenPoints(start.clone().add(new THREE.Vector3(0, heightOffset, 0)), end.clone().add(new THREE.Vector3(0, heightOffset, 0)), radius, 8);
|
|
610
|
+
if (segmentGeometry) {
|
|
611
|
+
geometries.push(segmentGeometry);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
return geometries;
|
|
615
|
+
}
|
|
616
|
+
function buildBalusterGeometries(points, height, radius) {
|
|
617
|
+
const geometries = [];
|
|
618
|
+
for (const point of points) {
|
|
619
|
+
const geometry = new THREE.CylinderGeometry(radius, radius, Math.max(height, 0.05), 8);
|
|
620
|
+
geometry.translate(point.x, point.y + height / 2, point.z);
|
|
621
|
+
geometries.push(geometry);
|
|
622
|
+
}
|
|
623
|
+
return geometries;
|
|
624
|
+
}
|
|
625
|
+
function getSegmentTopThickness(segment) {
|
|
626
|
+
return Math.max(segment.thickness ?? 0.25, 0.02);
|
|
627
|
+
}
|
|
628
|
+
function createCylinderBetweenPoints(start, end, radius, radialSegments) {
|
|
629
|
+
const direction = new THREE.Vector3().subVectors(end, start);
|
|
630
|
+
const length = direction.length();
|
|
631
|
+
if (length <= 1e-5)
|
|
632
|
+
return null;
|
|
633
|
+
const midpoint = new THREE.Vector3().addVectors(start, end).multiplyScalar(0.5);
|
|
634
|
+
const quaternion = new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(0, 1, 0), direction.clone().normalize());
|
|
635
|
+
const geometry = new THREE.CylinderGeometry(radius, radius, length, radialSegments);
|
|
636
|
+
geometry.applyQuaternion(quaternion);
|
|
637
|
+
geometry.translate(midpoint.x, midpoint.y, midpoint.z);
|
|
638
|
+
return geometry;
|
|
639
|
+
}
|
|
335
640
|
/**
|
|
336
641
|
* Computes the absolute Y height of a segment by traversing the stair's segment chain.
|
|
337
642
|
*/
|