Optimize elevator editing performance with live previews

This commit is contained in:
sudhir
2026-05-09 19:09:48 +05:30
parent 0514363136
commit 2480be91b1
59 changed files with 4299 additions and 176 deletions
+1
View File
@@ -42,6 +42,7 @@ export {
ColumnSupportStyle,
} from './nodes/column'
export { DoorNode, DoorSegment } from './nodes/door'
export { ElevatorDoorStyle, ElevatorNode } from './nodes/elevator'
export { FenceBaseStyle, FenceNode, FenceStyle } from './nodes/fence'
export { GuideNode, GuideScaleReference } from './nodes/guide'
export type {
+3 -2
View File
@@ -1,12 +1,13 @@
import dedent from 'dedent'
import { z } from 'zod'
import { BaseNode, nodeType, objectId } from '../base'
import { ElevatorNode } from './elevator'
import { LevelNode } from './level'
export const BuildingNode = BaseNode.extend({
id: objectId('building'),
type: nodeType('building'),
children: z.array(LevelNode.shape.id).default([]),
children: z.array(z.union([LevelNode.shape.id, ElevatorNode.shape.id])).default([]),
position: z.tuple([z.number(), z.number(), z.number()]).default([0, 0, 0]),
rotation: z.tuple([z.number(), z.number(), z.number()]).default([0, 0, 0]),
}).describe(
@@ -14,7 +15,7 @@ export const BuildingNode = BaseNode.extend({
Building node - used to represent a building
- position: position in site coordinate system
- rotation: rotation in site coordinate system
- children: array of level nodes (each level is a tree of floor and wall nodes)
- children: array of level nodes and building-level systems such as elevators
`,
)
+1 -1
View File
@@ -21,7 +21,7 @@ export const CeilingNode = BaseNode.extend({
Ceiling node - used to represent a ceiling in the building
- polygon: array of [x, z] points defining the ceiling boundary
- holes: array of polygons representing holes in the ceiling
- holeMetadata: metadata parallel to holes, used to preserve manual and stair-managed cutouts
- holeMetadata: metadata parallel to holes, used to preserve manual and auto-managed cutouts
- autoFromWalls: whether the ceiling is automatically generated from a closed wall loop
`,
)
@@ -0,0 +1,47 @@
import dedent from 'dedent'
import { z } from 'zod'
import { BaseNode, nodeType, objectId } from '../base'
import { MaterialSchema } from '../material'
export const ElevatorDoorStyle = z.enum(['center-opening', 'single-left', 'single-right'])
export type ElevatorDoorStyle = z.infer<typeof ElevatorDoorStyle>
export const ElevatorNode = BaseNode.extend({
id: objectId('elevator'),
type: nodeType('elevator'),
material: MaterialSchema.optional(),
materialPreset: z.string().optional(),
position: z.tuple([z.number(), z.number(), z.number()]).default([0, 0, 0]),
// Rotation around the Y axis in radians.
rotation: z.number().default(0),
width: z.number().default(1.6),
depth: z.number().default(1.6),
cabHeight: z.number().default(2.35),
doorWidth: z.number().default(0.95),
doorHeight: z.number().default(2.1),
doorStyle: ElevatorDoorStyle.default('center-opening'),
fromLevelId: z.string().nullable().default(null),
toLevelId: z.string().nullable().default(null),
servedLevelIds: z.array(z.string()).optional(),
defaultLevelId: z.string().nullable().default(null),
speed: z.number().default(2.2),
doorDurationMs: z.number().default(900),
dwellMs: z.number().default(1400),
}).describe(
dedent`
Elevator node - a vertical transport core attached to a building.
- parentId: building that owns this elevator
- position: building-local shaft center on the X/Z plane
- rotation: rotation around the Y axis
- width/depth: shaft and cab footprint
- cabHeight: visible elevator cab height
- doorWidth/doorHeight/doorStyle: landing and cab door presentation
- fromLevelId / toLevelId: source and destination levels used for service range and auto cutouts
- servedLevelIds: legacy optional explicit level list; used only when from/to are missing
- defaultLevelId: starting/resting level, falling back to the lowest served level
- speed/doorDurationMs/dwellMs: runtime animation defaults
`,
)
export type ElevatorNode = z.infer<typeof ElevatorNode>
+1 -1
View File
@@ -19,7 +19,7 @@ export const SlabNode = BaseNode.extend({
Slab node - used to represent a slab/floor in the building
- polygon: array of [x, z] points defining the slab boundary
- holes: array of [x, z] polygons representing cutouts in the slab
- holeMetadata: metadata parallel to holes, used to preserve manual and stair-managed cutouts
- holeMetadata: metadata parallel to holes, used to preserve manual and auto-managed cutouts
- elevation: elevation in meters
- autoFromWalls: whether the slab is automatically generated from a closed wall loop
`,
@@ -1,8 +1,9 @@
import { z } from 'zod'
export const SurfaceHoleMetadata = z.object({
source: z.enum(['manual', 'stair']).default('manual'),
source: z.enum(['manual', 'stair', 'elevator']).default('manual'),
stairId: z.string().optional(),
elevatorId: z.string().optional(),
})
export type SurfaceHoleMetadata = z.infer<typeof SurfaceHoleMetadata>
+2
View File
@@ -3,6 +3,7 @@ import { BuildingNode } from './nodes/building'
import { CeilingNode } from './nodes/ceiling'
import { ColumnNode } from './nodes/column'
import { DoorNode } from './nodes/door'
import { ElevatorNode } from './nodes/elevator'
import { FenceNode } from './nodes/fence'
import { GuideNode } from './nodes/guide'
import { ItemNode } from './nodes/item'
@@ -22,6 +23,7 @@ import { ZoneNode } from './nodes/zone'
export const AnyNode = z.discriminatedUnion('type', [
SiteNode,
BuildingNode,
ElevatorNode,
LevelNode,
ColumnNode,
WallNode,