@kerros/editor 0.0.0-stage → 0.1.0-rc.2
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/LICENSE +21 -0
- package/README.md +35 -2
- package/dist/SitePlanner.js +1189 -0
- package/dist/SitePlanner.js.map +1 -0
- package/dist/adapters/basemap.js +11 -0
- package/dist/adapters/basemap.js.map +1 -0
- package/dist/adapters/persistence.js +121 -0
- package/dist/adapters/persistence.js.map +1 -0
- package/dist/adapters/status.js +11 -0
- package/dist/adapters/status.js.map +1 -0
- package/dist/adapters/useProjectPersistence.js +56 -0
- package/dist/adapters/useProjectPersistence.js.map +1 -0
- package/dist/components/AiImportPanel.js +635 -0
- package/dist/components/AiImportPanel.js.map +1 -0
- package/dist/components/AnalysisPreview.js +179 -0
- package/dist/components/AnalysisPreview.js.map +1 -0
- package/dist/components/ElevatorPanel.js +120 -0
- package/dist/components/ElevatorPanel.js.map +1 -0
- package/dist/components/Icons.js +57 -0
- package/dist/components/Icons.js.map +1 -0
- package/dist/components/ImportDialog.js +467 -0
- package/dist/components/ImportDialog.js.map +1 -0
- package/dist/components/Inspector.js +1184 -0
- package/dist/components/Inspector.js.map +1 -0
- package/dist/components/NavigatePanel.js +301 -0
- package/dist/components/NavigatePanel.js.map +1 -0
- package/dist/components/NavigationGraph.js +234 -0
- package/dist/components/NavigationGraph.js.map +1 -0
- package/dist/components/StructureExplorer.js +510 -0
- package/dist/components/StructureExplorer.js.map +1 -0
- package/dist/components/StructureView.js +286 -0
- package/dist/components/StructureView.js.map +1 -0
- package/dist/components/controls.js +209 -0
- package/dist/components/controls.js.map +1 -0
- package/dist/components/graphLayout.js +27 -0
- package/dist/components/graphLayout.js.map +1 -0
- package/dist/host.js +175 -0
- package/dist/host.js.map +1 -0
- package/dist/i18n.js +88 -0
- package/dist/i18n.js.map +1 -0
- package/dist/import/analysisPreview.js +41 -0
- package/dist/import/analysisPreview.js.map +1 -0
- package/dist/import/brief.js +29 -0
- package/dist/import/brief.js.map +1 -0
- package/dist/import/checkpoint.js +50 -0
- package/dist/import/checkpoint.js.map +1 -0
- package/dist/import/detect.js +120 -0
- package/dist/import/detect.js.map +1 -0
- package/dist/import/documentSvg.js +49 -0
- package/dist/import/documentSvg.js.map +1 -0
- package/dist/import/instructions.js +20 -0
- package/dist/import/instructions.js.map +1 -0
- package/dist/import/openings.js +61 -0
- package/dist/import/openings.js.map +1 -0
- package/dist/import/planImport.js +233 -0
- package/dist/import/planImport.js.map +1 -0
- package/dist/import/register.js +47 -0
- package/dist/import/register.js.map +1 -0
- package/dist/import/runs.js +67 -0
- package/dist/import/runs.js.map +1 -0
- package/dist/import/session.js +23 -0
- package/dist/import/session.js.map +1 -0
- package/dist/import/types.js +13 -0
- package/dist/import/types.js.map +1 -0
- package/dist/import/usage.js +29 -0
- package/dist/import/usage.js.map +1 -0
- package/dist/import/walls.js +112 -0
- package/dist/import/walls.js.map +1 -0
- package/dist/index.js +178 -0
- package/dist/index.js.map +1 -0
- package/dist/map/CabinMaterials.js +81 -0
- package/dist/map/CabinMaterials.js.map +1 -0
- package/dist/map/CabinMirror.js +43 -0
- package/dist/map/CabinMirror.js.map +1 -0
- package/dist/map/Doors.js +80 -0
- package/dist/map/Doors.js.map +1 -0
- package/dist/map/ElevatorCabin.js +93 -0
- package/dist/map/ElevatorCabin.js.map +1 -0
- package/dist/map/FixtureLights.js +117 -0
- package/dist/map/FixtureLights.js.map +1 -0
- package/dist/map/MapCanvas.js +2161 -0
- package/dist/map/MapCanvas.js.map +1 -0
- package/dist/map/Passenger.js +69 -0
- package/dist/map/Passenger.js.map +1 -0
- package/dist/map/SceneLayer.js +1534 -0
- package/dist/map/SceneLayer.js.map +1 -0
- package/dist/map/UndergroundContext.js +153 -0
- package/dist/map/UndergroundContext.js.map +1 -0
- package/dist/map/ambience.js +194 -0
- package/dist/map/ambience.js.map +1 -0
- package/dist/map/architecture.js +305 -0
- package/dist/map/architecture.js.map +1 -0
- package/dist/map/bathMusic.js +92 -0
- package/dist/map/bathMusic.js.map +1 -0
- package/dist/map/cameraAim.js +33 -0
- package/dist/map/cameraAim.js.map +1 -0
- package/dist/map/elevators.js +56 -0
- package/dist/map/elevators.js.map +1 -0
- package/dist/map/excavation.js +52 -0
- package/dist/map/excavation.js.map +1 -0
- package/dist/map/exteriors.js +25 -0
- package/dist/map/exteriors.js.map +1 -0
- package/dist/map/features.js +218 -0
- package/dist/map/features.js.map +1 -0
- package/dist/map/fences.js +29 -0
- package/dist/map/fences.js.map +1 -0
- package/dist/map/journey.js +112 -0
- package/dist/map/journey.js.map +1 -0
- package/dist/map/levels.js +6 -0
- package/dist/map/levels.js.map +1 -0
- package/dist/map/lighting.js +143 -0
- package/dist/map/lighting.js.map +1 -0
- package/dist/map/loadBasemap.js +26 -0
- package/dist/map/loadBasemap.js.map +1 -0
- package/dist/map/materials.js +183 -0
- package/dist/map/materials.js.map +1 -0
- package/dist/map/poolLighting.js +39 -0
- package/dist/map/poolLighting.js.map +1 -0
- package/dist/map/projection.js +24 -0
- package/dist/map/projection.js.map +1 -0
- package/dist/map/rampGeometry.js +38 -0
- package/dist/map/rampGeometry.js.map +1 -0
- package/dist/map/route.js +107 -0
- package/dist/map/route.js.map +1 -0
- package/dist/map/stairSurfaces.js +115 -0
- package/dist/map/stairSurfaces.js.map +1 -0
- package/dist/map/surfaces.js +136 -0
- package/dist/map/surfaces.js.map +1 -0
- package/dist/map/textures.js +95 -0
- package/dist/map/textures.js.map +1 -0
- package/dist/map/underground.js +34 -0
- package/dist/map/underground.js.map +1 -0
- package/dist/map/walk.js +433 -0
- package/dist/map/walk.js.map +1 -0
- package/dist/map/walkContext.js +46 -0
- package/dist/map/walkContext.js.map +1 -0
- package/dist/map/walkDimensions.js +7 -0
- package/dist/map/walkDimensions.js.map +1 -0
- package/dist/map/walkJourney.js +85 -0
- package/dist/map/walkJourney.js.map +1 -0
- package/dist/map/walkSurfaces.js +106 -0
- package/dist/map/walkSurfaces.js.map +1 -0
- package/dist/map/wallJoins.js +70 -0
- package/dist/map/wallJoins.js.map +1 -0
- package/dist/map/water.js +274 -0
- package/dist/map/water.js.map +1 -0
- package/dist/model/authoring.js +99 -0
- package/dist/model/authoring.js.map +1 -0
- package/dist/model/boundaries.js +548 -0
- package/dist/model/boundaries.js.map +1 -0
- package/dist/model/coverage.js +30 -0
- package/dist/model/coverage.js.map +1 -0
- package/dist/model/document.js +52 -0
- package/dist/model/document.js.map +1 -0
- package/dist/model/doors.js +47 -0
- package/dist/model/doors.js.map +1 -0
- package/dist/model/factory.js +56 -0
- package/dist/model/factory.js.map +1 -0
- package/dist/model/geometry.js +454 -0
- package/dist/model/geometry.js.map +1 -0
- package/dist/model/history.js +29 -0
- package/dist/model/history.js.map +1 -0
- package/dist/model/imports.js +45 -0
- package/dist/model/imports.js.map +1 -0
- package/dist/model/inference.js +182 -0
- package/dist/model/inference.js.map +1 -0
- package/dist/model/materials.js +11 -0
- package/dist/model/materials.js.map +1 -0
- package/dist/model/mutations.js +157 -0
- package/dist/model/mutations.js.map +1 -0
- package/dist/model/navigation.js +275 -0
- package/dist/model/navigation.js.map +1 -0
- package/dist/model/ontology.js +109 -0
- package/dist/model/ontology.js.map +1 -0
- package/dist/model/passages.js +5 -0
- package/dist/model/passages.js.map +1 -0
- package/dist/model/portals.js +42 -0
- package/dist/model/portals.js.map +1 -0
- package/dist/model/precision.js +11 -0
- package/dist/model/precision.js.map +1 -0
- package/dist/model/project.js +31 -0
- package/dist/model/project.js.map +1 -0
- package/dist/model/ramps.js +10 -0
- package/dist/model/ramps.js.map +1 -0
- package/dist/model/roomNavigation.js +87 -0
- package/dist/model/roomNavigation.js.map +1 -0
- package/dist/model/routeClearance.js +72 -0
- package/dist/model/routeClearance.js.map +1 -0
- package/dist/model/spaces.js +104 -0
- package/dist/model/spaces.js.map +1 -0
- package/dist/model/stairGeometry.js +40 -0
- package/dist/model/stairGeometry.js.map +1 -0
- package/dist/model/stairTraversal.js +48 -0
- package/dist/model/stairTraversal.js.map +1 -0
- package/dist/model/topology.js +63 -0
- package/dist/model/topology.js.map +1 -0
- package/dist/model/types.js +35 -0
- package/dist/model/types.js.map +1 -0
- package/dist/model/validate.js +240 -0
- package/dist/model/validate.js.map +1 -0
- package/dist/model/vertical.js +129 -0
- package/dist/model/vertical.js.map +1 -0
- package/dist/model/walls.js +261 -0
- package/dist/model/walls.js.map +1 -0
- package/dist/planner/DrawingDock.js +231 -0
- package/dist/planner/DrawingDock.js.map +1 -0
- package/dist/planner/FloorControls.js +93 -0
- package/dist/planner/FloorControls.js.map +1 -0
- package/dist/planner/MapSettings.js +143 -0
- package/dist/planner/MapSettings.js.map +1 -0
- package/dist/planner/PlannerHelp.js +57 -0
- package/dist/planner/PlannerHelp.js.map +1 -0
- package/dist/planner/ProjectSidebar.js +246 -0
- package/dist/planner/ProjectSidebar.js.map +1 -0
- package/dist/planner/floors.js +18 -0
- package/dist/planner/floors.js.map +1 -0
- package/dist/planner/useDrawingTools.js +341 -0
- package/dist/planner/useDrawingTools.js.map +1 -0
- package/dist/planner/useMapDisplay.js +51 -0
- package/dist/planner/useMapDisplay.js.map +1 -0
- package/dist/planner/usePlannerKeyboard.js +138 -0
- package/dist/planner/usePlannerKeyboard.js.map +1 -0
- package/dist/planner/useReferenceAlignment.js +50 -0
- package/dist/planner/useReferenceAlignment.js.map +1 -0
- package/dist/styles.css +4931 -0
- package/dist/theme/index.js +34 -0
- package/dist/theme/index.js.map +1 -0
- package/dist/types/SitePlanner.d.ts +5 -0
- package/dist/types/adapters/basemap.d.ts +2 -0
- package/dist/types/adapters/persistence.d.ts +29 -0
- package/dist/types/adapters/status.d.ts +4 -0
- package/dist/types/adapters/useProjectPersistence.d.ts +13 -0
- package/dist/types/components/AiImportPanel.d.ts +9 -0
- package/dist/types/components/AnalysisPreview.d.ts +4 -0
- package/dist/types/components/ElevatorPanel.d.ts +18 -0
- package/dist/types/components/Icons.d.ts +8 -0
- package/dist/types/components/ImportDialog.d.ts +42 -0
- package/dist/types/components/Inspector.d.ts +38 -0
- package/dist/types/components/NavigatePanel.d.ts +27 -0
- package/dist/types/components/NavigationGraph.d.ts +10 -0
- package/dist/types/components/StructureExplorer.d.ts +8 -0
- package/dist/types/components/StructureView.d.ts +22 -0
- package/dist/types/components/controls.d.ts +52 -0
- package/dist/types/components/graphLayout.d.ts +9 -0
- package/dist/types/editor/host.d.ts +9 -0
- package/dist/types/editor/index.d.ts +2 -0
- package/dist/types/i18n.d.ts +85 -0
- package/dist/types/import/analysisPreview.d.ts +27 -0
- package/dist/types/import/brief.d.ts +22 -0
- package/dist/types/import/checkpoint.d.ts +49 -0
- package/dist/types/import/detect.d.ts +34 -0
- package/dist/types/import/documentSvg.d.ts +2 -0
- package/dist/types/import/index.d.ts +10 -0
- package/dist/types/import/instructions.d.ts +7 -0
- package/dist/types/import/openings.d.ts +22 -0
- package/dist/types/import/planImport.d.ts +22 -0
- package/dist/types/import/register.d.ts +25 -0
- package/dist/types/import/runs.d.ts +31 -0
- package/dist/types/import/session.d.ts +33 -0
- package/dist/types/import/types.d.ts +56 -0
- package/dist/types/import/usage.d.ts +10 -0
- package/dist/types/import/walls.d.ts +37 -0
- package/dist/types/map/CabinMaterials.d.ts +18 -0
- package/dist/types/map/CabinMirror.d.ts +13 -0
- package/dist/types/map/Doors.d.ts +11 -0
- package/dist/types/map/ElevatorCabin.d.ts +20 -0
- package/dist/types/map/FixtureLights.d.ts +35 -0
- package/dist/types/map/MapCanvas.d.ts +87 -0
- package/dist/types/map/Passenger.d.ts +18 -0
- package/dist/types/map/SceneLayer.d.ts +306 -0
- package/dist/types/map/UndergroundContext.d.ts +18 -0
- package/dist/types/map/ambience.d.ts +29 -0
- package/dist/types/map/architecture.d.ts +8 -0
- package/dist/types/map/bathMusic.d.ts +14 -0
- package/dist/types/map/cameraAim.d.ts +20 -0
- package/dist/types/map/elevators.d.ts +16 -0
- package/dist/types/map/excavation.d.ts +9 -0
- package/dist/types/map/exteriors.d.ts +3 -0
- package/dist/types/map/features.d.ts +33 -0
- package/dist/types/map/fences.d.ts +4 -0
- package/dist/types/map/journey.d.ts +36 -0
- package/dist/types/map/levels.d.ts +4 -0
- package/dist/types/map/lighting.d.ts +103 -0
- package/dist/types/map/loadBasemap.d.ts +4 -0
- package/dist/types/map/materials.d.ts +38 -0
- package/dist/types/map/poolLighting.d.ts +11 -0
- package/dist/types/map/projection.d.ts +9 -0
- package/dist/types/map/rampGeometry.d.ts +8 -0
- package/dist/types/map/route.d.ts +59 -0
- package/dist/types/map/stairSurfaces.d.ts +29 -0
- package/dist/types/map/surfaces.d.ts +36 -0
- package/dist/types/map/textures.d.ts +8 -0
- package/dist/types/map/underground.d.ts +30 -0
- package/dist/types/map/walk.d.ts +232 -0
- package/dist/types/map/walkContext.d.ts +11 -0
- package/dist/types/map/walkDimensions.d.ts +5 -0
- package/dist/types/map/walkJourney.d.ts +33 -0
- package/dist/types/map/walkSurfaces.d.ts +27 -0
- package/dist/types/map/wallJoins.d.ts +6 -0
- package/dist/types/map/water.d.ts +12 -0
- package/dist/types/model/authoring.d.ts +38 -0
- package/dist/types/model/boundaries.d.ts +41 -0
- package/dist/types/model/coverage.d.ts +8 -0
- package/dist/types/model/document.d.ts +9 -0
- package/dist/types/model/doors.d.ts +19 -0
- package/dist/types/model/factory.d.ts +5 -0
- package/dist/types/model/geometry.d.ts +99 -0
- package/dist/types/model/history.d.ts +10 -0
- package/dist/types/model/host.d.ts +154 -0
- package/dist/types/model/imports.d.ts +7 -0
- package/dist/types/model/inference.d.ts +46 -0
- package/dist/types/model/live.d.ts +60 -0
- package/dist/types/model/materials.d.ts +28 -0
- package/dist/types/model/mutations.d.ts +178 -0
- package/dist/types/model/navigation.d.ts +70 -0
- package/dist/types/model/ontology.d.ts +43 -0
- package/dist/types/model/passages.d.ts +2 -0
- package/dist/types/model/portals.d.ts +9 -0
- package/dist/types/model/precision.d.ts +11 -0
- package/dist/types/model/project.d.ts +8 -0
- package/dist/types/model/ramps.d.ts +7 -0
- package/dist/types/model/roomNavigation.d.ts +15 -0
- package/dist/types/model/routeClearance.d.ts +11 -0
- package/dist/types/model/spaces.d.ts +46 -0
- package/dist/types/model/stairGeometry.d.ts +27 -0
- package/dist/types/model/stairTraversal.d.ts +8 -0
- package/dist/types/model/topology.d.ts +14 -0
- package/dist/types/model/types.d.ts +369 -0
- package/dist/types/model/validate.d.ts +38 -0
- package/dist/types/model/vertical.d.ts +145 -0
- package/dist/types/model/walls.d.ts +71 -0
- package/dist/types/planner/DrawingDock.d.ts +16 -0
- package/dist/types/planner/FloorControls.d.ts +17 -0
- package/dist/types/planner/MapSettings.d.ts +16 -0
- package/dist/types/planner/PlannerHelp.d.ts +3 -0
- package/dist/types/planner/ProjectSidebar.d.ts +32 -0
- package/dist/types/planner/floors.d.ts +3 -0
- package/dist/types/planner/types.d.ts +3 -0
- package/dist/types/planner/useDrawingTools.d.ts +52 -0
- package/dist/types/planner/useMapDisplay.d.ts +29 -0
- package/dist/types/planner/usePlannerKeyboard.d.ts +18 -0
- package/dist/types/planner/useReferenceAlignment.d.ts +30 -0
- package/dist/types/schema/index.d.ts +25 -0
- package/dist/types/theme/index.d.ts +55 -0
- package/package.json +58 -4
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { type SurfaceFinish } from './textures';
|
|
3
|
+
/** Small deterministic, metre-scaled textures keep exported projects independent of CDNs. */
|
|
4
|
+
export declare class MaterialLibrary {
|
|
5
|
+
private materials;
|
|
6
|
+
private textures;
|
|
7
|
+
solid(color: string, roughness?: number): THREE.MeshStandardMaterial;
|
|
8
|
+
/** The active storey's own plate, when the stack has storeys under it. Opaque enough to read as
|
|
9
|
+
* the floor you are standing on, sheer enough that the levels beneath show through it — without
|
|
10
|
+
* this the plate is a lid and "All floors" shows one. depthWrite stays on: the plate must still
|
|
11
|
+
* occlude its own walls' hidden faces, and the ghosts below carry depthWrite off already, so they
|
|
12
|
+
* blend rather than fight it. */
|
|
13
|
+
plate(color: string, roughness?: number): THREE.MeshStandardMaterial;
|
|
14
|
+
/** A lit ceiling. Its underside faces down, so every light in the scene misses it and a plain
|
|
15
|
+
* material renders it as the darkest thing in the room — which is the opposite of what a ceiling
|
|
16
|
+
* full of fittings looks like from beneath. Emissive is the honest fix: the ceiling is not lit,
|
|
17
|
+
* it is the thing doing the lighting, and `tint` is whatever the floor's lamps are. */
|
|
18
|
+
luminous(color: string, tint: string, strength: number, finish?: SurfaceFinish): THREE.MeshStandardMaterial;
|
|
19
|
+
/** A polished twin of a finish, for the floor you are standing on in walk mode. Seen from above a
|
|
20
|
+
* floor is a flat patch of its own colour and matte is right; seen along at eye level it is the
|
|
21
|
+
* one surface in the room that shows you where the light is, because a grazing angle is where
|
|
22
|
+
* reflectance lives. The roughness map still multiplies through, so the polish keeps the finish's
|
|
23
|
+
* own variation instead of turning the plate into a mirror. */
|
|
24
|
+
polished(base: THREE.MeshStandardMaterial, roughness?: number): THREE.MeshStandardMaterial;
|
|
25
|
+
/** A vertex-coloured twin of an existing material, so geometry can carry baked shading without
|
|
26
|
+
* doubling the palette. Cached per source material: everything drawn with the twin must supply a
|
|
27
|
+
* colour attribute, since a merge needs matching attributes across all its geometries. */
|
|
28
|
+
shaded(base: THREE.MeshStandardMaterial): THREE.MeshStandardMaterial;
|
|
29
|
+
/** Translucent variant for de-emphasised floors in the stacked view. */
|
|
30
|
+
ghost(color: string, opacity?: number): THREE.MeshStandardMaterial;
|
|
31
|
+
private finishes;
|
|
32
|
+
get(kind: SurfaceFinish, color: string): THREE.MeshStandardMaterial;
|
|
33
|
+
glass(evening?: boolean, lit?: boolean): THREE.MeshStandardMaterial;
|
|
34
|
+
metal(color?: string): THREE.MeshStandardMaterial;
|
|
35
|
+
/** One image per step; the UVs follow the machine's run, including rotated/reversed flights. */
|
|
36
|
+
escalator(): THREE.MeshStandardMaterial;
|
|
37
|
+
dispose(): void;
|
|
38
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ProjectDocument, SiteObject } from '../model/types';
|
|
2
|
+
export interface PoolBounce {
|
|
3
|
+
room: SiteObject;
|
|
4
|
+
pool?: SiteObject;
|
|
5
|
+
strength: number;
|
|
6
|
+
height: number;
|
|
7
|
+
}
|
|
8
|
+
/** A diffuse approximation for white tiled rooms. Pool chambers receive the submerged fixtures;
|
|
9
|
+
* connecting chambers receive a weaker bounce through open portals. No light crosses a sealed
|
|
10
|
+
* wall, and switching off the source removes its reflected light as well. */
|
|
11
|
+
export declare function poolBounces(project: ProjectDocument, floorId: string): PoolBounce[];
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Box3, Camera, Matrix4 } from 'three';
|
|
2
|
+
/** Split the map's combined matrix so PBR shading sees the same eye as projection and picking.
|
|
3
|
+
* Keeping the camera axes in world space avoids decomposing Mercator's reflected Y axis. */
|
|
4
|
+
export declare function syncLightingCamera(camera: Camera, worldToClip: Matrix4, clipToWorld: Matrix4): void;
|
|
5
|
+
/** Extend a Mercator scene's far plane without changing its screen position or near plane. */
|
|
6
|
+
export declare function includeSceneDepth(matrix: Matrix4, bounds: Box3, scaleZ: number, near: number, far: number): void;
|
|
7
|
+
/** MapLibre's near distance follows viewport pixels and can cut away a wall before the walker
|
|
8
|
+
* touches it. Give POV a 4 cm near plane in scene metres, preserving the eye, X/Y and far plane. */
|
|
9
|
+
export declare function walkNearPlane(matrix: Matrix4, near: number, far: number): number;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ProjectDocument, Ring, Slope } from '../model/types';
|
|
2
|
+
/** Clip in the slope's local frame. Clipping, rather than moving existing corner vertices, inserts
|
|
3
|
+
* the break lines where an incline meets its flat aprons, including concave outlines and holes. */
|
|
4
|
+
export declare function rampBand(rings: Ring[], slope: Slope, from: number, to: number): Ring[][];
|
|
5
|
+
export declare const rampSections: (rings: Ring[], slope: Slope) => Ring[][];
|
|
6
|
+
/** A descending ramp replaces the upper floor. The ceiling below also needs an opening wherever
|
|
7
|
+
* the ramp comes within head height. Arrival aprons stay supported by their lower deck. */
|
|
8
|
+
export declare function rampVoids(project: ProjectDocument, floorId: string, through?: 'floor' | 'ceiling'): Ring[];
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { FeatureCollection } from 'geojson';
|
|
2
|
+
import type { Origin, Point, ProjectDocument } from '../model/types';
|
|
3
|
+
import type { Route } from '../model/navigation';
|
|
4
|
+
/** The route's own colours. A wayfinding line is not a plan colour — it is a thing laid ON the plan
|
|
5
|
+
* for someone to follow, so it wants to be the one saturated element in a scene of pale rooms, and
|
|
6
|
+
* it wants a white edge so it reads over a dark floor as well as a light one. Green because green
|
|
7
|
+
* is what "this way" looks like on every floor of every building anyone has walked through. */
|
|
8
|
+
export declare const ROUTE_COLOR = "#16a34a";
|
|
9
|
+
/** Steps either side of the one being walked: the same green, not a different colour — the path is
|
|
10
|
+
* one path, and only emphasis separates the part you are on from the rest of it. */
|
|
11
|
+
export declare const ROUTE_SOFT = "#6fc98d";
|
|
12
|
+
export declare const ROUTE_EDGE = "#ffffff";
|
|
13
|
+
/** Step index owning each traversal leg, in leg order. Every walk/door/vertical step carries
|
|
14
|
+
* nodeIds for the nodes it visits (one more than its legs); depart/arrive own no legs. */
|
|
15
|
+
export declare function legStepIndices(route: Route): number[];
|
|
16
|
+
/** GeoJSON for the 2D route layers. Walk/door legs chain into per-step polylines (so dashes and
|
|
17
|
+
* chevrons flow continuously); vertical legs become Point features at the shaft. Every feature
|
|
18
|
+
* carries { step, active, onFloor, vertical, dir }. Outdoor legs count as on-floor everywhere,
|
|
19
|
+
* mirroring visibleOnFloor — the outdoor tail of an egress route must stay readable. */
|
|
20
|
+
export declare function routeFeatures(project: ProjectDocument, route: Route, floorId: string | null, activeStep: number | null): FeatureCollection;
|
|
21
|
+
/** The route as something to be walked: its contiguous same-floor stretches, in travel order, in
|
|
22
|
+
* plan metres. A flight is a break rather than a stretch — you do not walk up a lift shaft — so each
|
|
23
|
+
* run ends where the route leaves the floor, and the floor it ends on is the one to switch to.
|
|
24
|
+
*
|
|
25
|
+
* This is the same decomposition the flow features use, kept apart from GeoJSON because walking a
|
|
26
|
+
* route wants plan coordinates and a map layer wants degrees. */
|
|
27
|
+
export declare function routeWalks(route: Route): {
|
|
28
|
+
floorId: string | null;
|
|
29
|
+
points: Point[];
|
|
30
|
+
}[];
|
|
31
|
+
/** A band of light travelling along the path, as a line-gradient over `line-progress`.
|
|
32
|
+
*
|
|
33
|
+
* Built from stops at fixed, strictly ascending positions with the band expressed as an alpha
|
|
34
|
+
* falling off either side of `phase` — rather than by moving the stops, which is the obvious way
|
|
35
|
+
* and the wrong one: a moving window has to be clamped as it wraps past 0 and 1, and interpolate
|
|
36
|
+
* refuses stops that are not strictly ascending. This way there is nothing to clamp. */
|
|
37
|
+
export declare function routeFlowGradient(phase: number, color?: string, stops?: number): unknown[];
|
|
38
|
+
/** 32×32 chevron sprite for the symbol-placement:'line' arrow layer (points +x; MapLibre rotates it
|
|
39
|
+
* along the travel direction). White on a halo of the path's own colour: the arrow sits ON the green
|
|
40
|
+
* track, so it has to be the light thing, and the halo is what keeps it legible where the track
|
|
41
|
+
* passes over a pale floor. Drawn on a canvas — no glyphs, no external assets. */
|
|
42
|
+
export declare function routeArrowImage(color?: string): ImageData;
|
|
43
|
+
/** The track's repeating tile, for the 3D ribbon: a green band with white edges and a white chevron
|
|
44
|
+
* pointing along it, drawn once and tiled every `TRACK_TILE` metres of path.
|
|
45
|
+
*
|
|
46
|
+
* One texture answers all of it. The ribbon is a constant width, so the tile's top and bottom edges
|
|
47
|
+
* ARE the track's edges — mitres and corners included, which is the part a separate outline geometry
|
|
48
|
+
* gets wrong. The chevron rides in the same tile, so the arrows are spaced in metres of walking
|
|
49
|
+
* rather than in pixels of screen. And scrolling the tile along the path is the animation: the
|
|
50
|
+
* arrows march towards the destination instead of sitting still and merely pointing at it. */
|
|
51
|
+
export declare const TRACK_TILE = 2.6;
|
|
52
|
+
/** The tile's own size in pixels, described in one place. Powers of two so it can carry mipmaps:
|
|
53
|
+
* at eye level most of the track is seen at a grazing angle, and that is exactly where an
|
|
54
|
+
* unmipmapped texture turns its chevrons into glitter. */
|
|
55
|
+
export declare const TRACK_PIXELS: [number, number];
|
|
56
|
+
export declare function routeTrackImage(color?: string, active?: boolean): ImageData;
|
|
57
|
+
/** Heading in degrees from true north between two local points, computed in geographic space so a
|
|
58
|
+
* rotated Origin yields the bearing the map camera actually needs. */
|
|
59
|
+
export declare function pathHeading(a: Point, b: Point, origin: Origin): number;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Point, ProjectDocument, Ring } from '../model/types';
|
|
2
|
+
import type { StatusReading } from '../model/live';
|
|
3
|
+
export interface StairSurface {
|
|
4
|
+
flightId: string;
|
|
5
|
+
fromFloor: string;
|
|
6
|
+
toFloor: string;
|
|
7
|
+
low: number;
|
|
8
|
+
high: number;
|
|
9
|
+
ring: Ring;
|
|
10
|
+
holes?: Ring[];
|
|
11
|
+
height(at: Point): number;
|
|
12
|
+
drive?: Point;
|
|
13
|
+
rail?: true;
|
|
14
|
+
}
|
|
15
|
+
/** Build once per document/status/floor change, not once per walking frame. Heights are absolute
|
|
16
|
+
* floor elevations so switching the scene's floor datum cannot change the passenger's support. */
|
|
17
|
+
export declare function stairSurfaces(project: ProjectDocument, statuses?: Map<string, StatusReading>): StairSurface[];
|
|
18
|
+
/** Continuous walking support on the shared flights. The ramp envelope smooths the small tread
|
|
19
|
+
* risers; high side entries are solid, and leaving a flight sideways cannot step into mid-air. */
|
|
20
|
+
export declare class StairWalker {
|
|
21
|
+
height: number;
|
|
22
|
+
active?: StairSurface;
|
|
23
|
+
pending?: string;
|
|
24
|
+
private floor;
|
|
25
|
+
sync(floor: string | null, elevation: number): void;
|
|
26
|
+
refresh(surfaces: StairSurface[], at: Point): void;
|
|
27
|
+
reset(elevation: number): void;
|
|
28
|
+
step(from: Point, to: Point, surfaces: StairSurface[], floor: string | null, elevation: number, supports?: (at: Point, floorId: string | null) => boolean): Point;
|
|
29
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
/** The scene renders on two layers. Everything is on OUTSIDE-or-INSIDE: the sun and the sky light
|
|
3
|
+
* both, but the building's own ceiling lighting is on INSIDE alone, so turning the lamps up to read
|
|
4
|
+
* a shop floor does not also floodlight the pavement at midnight. */
|
|
5
|
+
export declare const INSIDE = 0, OUTSIDE = 1;
|
|
6
|
+
/** Batch static surfaces by material, retaining triangle ownership for picking/highlights. */
|
|
7
|
+
export declare class SurfaceBatch {
|
|
8
|
+
private pending;
|
|
9
|
+
private meshes;
|
|
10
|
+
/** Side of the square cells the batch is cut into, in scene metres; 0 batches a whole material
|
|
11
|
+
* into one mesh. Looking down on a floor from above, every part of it is in the frame and one
|
|
12
|
+
* mesh per material is the cheapest way to draw it. Standing on it, most of it is behind you or
|
|
13
|
+
* round a corner, and a lamp's shadow reaches twelve metres — but a mesh is culled whole or not
|
|
14
|
+
* at all, and one floor-sized mesh is never culled. Cut into cells, the frustum and every
|
|
15
|
+
* shadow pass keep only the cells they can see. */
|
|
16
|
+
chunk: number;
|
|
17
|
+
/** `outdoor` puts the surface on the OUTSIDE layer, out of reach of the interior lighting. It is
|
|
18
|
+
* part of the bucket key as well as a property of the mesh: two surfaces that share a material
|
|
19
|
+
* but not a side of the wall cannot be merged into one mesh, because a mesh sits on one layer. */
|
|
20
|
+
add(geometry: THREE.BufferGeometry, material: THREE.Material, id: string, outdoor?: boolean): void;
|
|
21
|
+
/** Fold a built object tree (a furniture group, a roof) into the batch, baking each mesh's world
|
|
22
|
+
* transform into its geometry. makeFixture emits one mesh per box, so a demo with a few hundred
|
|
23
|
+
* cars and columns was contributing thousands of draw calls and as many buffer uploads; merged by
|
|
24
|
+
* material they cost a handful. Instanced children are left alone — they are already batched. */
|
|
25
|
+
addObject(root: THREE.Object3D, id: string, outdoor?: boolean): THREE.Object3D<THREE.Object3DEventMap>[];
|
|
26
|
+
finish(scene: THREE.Scene): void;
|
|
27
|
+
outline(id: string, color: string): THREE.LineSegments | null;
|
|
28
|
+
clear(): void;
|
|
29
|
+
}
|
|
30
|
+
export declare function hitEntity(hit: THREE.Intersection): string | null;
|
|
31
|
+
/** Use distances along each face, not a world-axis projection that squashes diagonal façades. */
|
|
32
|
+
export declare function metricUVs(geometry: THREE.BufferGeometry, horizontalAxis?: readonly [number, number]): void;
|
|
33
|
+
/** Transfer an extrusion's vertical face to a separate material, without overlapping triangles.
|
|
34
|
+
* The supplied edge is in scene coordinates. Caps and the other sides remain in `geometry`.
|
|
35
|
+
* ExtrudeGeometry is non-indexed; retaining indices here preserves its UVs and contact shading. */
|
|
36
|
+
export declare function splitWallFace(geometry: THREE.BufferGeometry, edge: [[number, number], [number, number]]): THREE.BufferGeometry<THREE.NormalBufferAttributes, THREE.BufferGeometryEventMap> | null;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import type { MaterialKind } from '../model/types';
|
|
3
|
+
/** `roof` and `ceiling` are finishes with no authorable material behind them: nobody writes "this
|
|
4
|
+
* wall is made of roof". They exist because the renderer draws two surfaces the document never
|
|
5
|
+
* names — the cap over a building, and the soffit walk mode puts over the storey you are in. */
|
|
6
|
+
export type SurfaceFinish = MaterialKind | 'roof' | 'ceiling' | 'veneer';
|
|
7
|
+
/** Separate colour, relief and roughness maps: a dark stain must not become a dent in the wall. */
|
|
8
|
+
export declare function surfaceTextures(kind: SurfaceFinish): THREE.CanvasTexture[];
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Floor, ProjectDocument, SiteObject } from '../model/types';
|
|
2
|
+
export declare const DEPTH_CAP = 96;
|
|
3
|
+
export declare const MAX_CAGE_LEVELS = 32;
|
|
4
|
+
/** The camera, model, overlays and depth label must use the same presentation transform. */
|
|
5
|
+
export declare function undergroundView(project: ProjectDocument, floorId: string | null, stack: boolean): {
|
|
6
|
+
active: Floor | undefined;
|
|
7
|
+
levels: Floor[];
|
|
8
|
+
buried: boolean;
|
|
9
|
+
depthScale: number;
|
|
10
|
+
elevation: (z: number) => number;
|
|
11
|
+
focusElevation: number;
|
|
12
|
+
compressed: boolean;
|
|
13
|
+
};
|
|
14
|
+
export type UndergroundView = ReturnType<typeof undergroundView>;
|
|
15
|
+
interface FloorIndex {
|
|
16
|
+
floors: Map<string, Floor>;
|
|
17
|
+
objects: Map<string | null, SiteObject[]>;
|
|
18
|
+
outlines: Map<string, SiteObject>;
|
|
19
|
+
/** Ids of the objects that stand for their shaft — see primaryShafts. Anything vertical NOT in
|
|
20
|
+
* here is a twin of one that is, and is left to it to draw. */
|
|
21
|
+
primary: Set<string>;
|
|
22
|
+
/** Shafts that reach a floor without being filed under it. A stair lives on one storey and climbs
|
|
23
|
+
* to another, and the storey it arrives at has to draw it or the flight appears to come from
|
|
24
|
+
* nowhere — which is exactly what it did. Kept apart from `objects` so that everything already
|
|
25
|
+
* counting a floor's own objects keeps counting the same ones. */
|
|
26
|
+
reaching: Map<string, SiteObject[]>;
|
|
27
|
+
}
|
|
28
|
+
/** Project documents are immutable between edits. Floor navigation reuses this index. */
|
|
29
|
+
export declare function floorIndex(project: ProjectDocument): FloorIndex;
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import type { Map as GLMap } from 'maplibre-gl';
|
|
2
|
+
import type { Origin, Point, Ring } from '../model/types';
|
|
3
|
+
import { type StairSurface } from './stairSurfaces';
|
|
4
|
+
/** Eye above the slab it stands on. A constant, not the floor's height: a mezzanine and a hall are
|
|
5
|
+
* different rooms but the same visitor. */
|
|
6
|
+
export { EYE, BODY, HEAD_ROOM } from './walkDimensions';
|
|
7
|
+
/** Shoulder radius. Generous enough that you do not clip a corner, tight enough for a 0.9 m door. */
|
|
8
|
+
/** Faster than anyone walks a corridor, because on a screen the corridor is the size of a hand and
|
|
9
|
+
* a literal 1.4 m/s reads as wading. Games settle around 3–4 m/s for the same reason. */
|
|
10
|
+
export declare const WALK_SPEED = 3;
|
|
11
|
+
export declare const RUN_SPEED = 6;
|
|
12
|
+
/** Following a route on its own. A touch over walking pace, because nobody watches a demonstration
|
|
13
|
+
* dawdle, and short of the run — a tour is for looking about you, and at eye level 6 m/s is a
|
|
14
|
+
* sprint. */
|
|
15
|
+
export declare const TOUR_SPEED = 3.5;
|
|
16
|
+
/** How fast the head can swing while a route is driving. A corner taken at the full rate still
|
|
17
|
+
* reads as a turn rather than as a cut, and anything quicker is the sharp turn this replaced. */
|
|
18
|
+
export declare const TURN_RATE = 120;
|
|
19
|
+
/** How far up the path to look while following it. Aiming at a point ahead rather than at the
|
|
20
|
+
* segment you are on is what makes the camera begin its turn before the corner instead of at it —
|
|
21
|
+
* it is also what a person does, which is why it looks right. */
|
|
22
|
+
export declare const LOOK_AHEAD = 2.6;
|
|
23
|
+
/** Pitch is MapLibre's: 0 looks straight down at the ground, 90 is level with it. The head can drop
|
|
24
|
+
* to 55° below level — enough to read a floor marking at your feet — and rise to a degree short of
|
|
25
|
+
* level. Not level itself: at 90° the point the map looks at leaves the ground, and MapLibre then
|
|
26
|
+
* has to invent a target in the sky, which pulls its zoom (and every zoom-gated layer) down to
|
|
27
|
+
* what a satellite would use. At 89° the target is a hundred-odd metres up the corridor, the
|
|
28
|
+
* horizon is a degree above the middle of the frame, and nothing has to be invented. */
|
|
29
|
+
export declare const MIN_PITCH = 35, MAX_PITCH = 89;
|
|
30
|
+
/** Where the head rests: a few degrees below level, so the near floor is in frame and walking reads
|
|
31
|
+
* as walking, with room to look up from. */
|
|
32
|
+
export declare const REST_PITCH = 86;
|
|
33
|
+
/** The plan camera's zoom ceiling, and the one the walk raises it to while it has the map. MapLibre
|
|
34
|
+
* puts its camera at the eye by choosing a zoom for the ground point the eye looks at, and jumpTo
|
|
35
|
+
* clamps that zoom to the ceiling without a word — a ceiling the solve can hit is a ceiling that
|
|
36
|
+
* silently lifts the eye off the floor. A 2 m eye looking 55° down on a 4K display at the equator
|
|
37
|
+
* needs 26.6, so the walk's ceiling is 28. Kept here so MapCanvas and the solve agree. */
|
|
38
|
+
export declare const MAX_MAP_ZOOM = 26, WALK_ZOOM = 28;
|
|
39
|
+
/** The most device pixels per CSS pixel the walk will draw. A retina display asks for two, which
|
|
40
|
+
* is four times the pixels of one, and at eye level every one of them is lit by the sun, the sky
|
|
41
|
+
* and four lamps with shadows: a dense floor measured at 11 frames a second at two and 35 at one.
|
|
42
|
+
* A plan is read; a walk is watched, and a watched picture has to move. 1.25 keeps most of the
|
|
43
|
+
* crispness of a retina display for a third of its cost. */
|
|
44
|
+
export declare const WALK_PIXEL_RATIO = 1.25;
|
|
45
|
+
/** Horizontal field of view in degrees. Kept stable when side panels resize the viewport. */
|
|
46
|
+
export declare const DEFAULT_WALK_FOV = 100, MIN_WALK_FOV = 60, MAX_WALK_FOV = 120;
|
|
47
|
+
export declare function walkFieldOfView(value: number): number;
|
|
48
|
+
/** MapLibre takes a vertical angle; tan(h/2) = aspect · tan(v/2). */
|
|
49
|
+
export declare function verticalFieldOfView(horizontal: number, aspect: number): number;
|
|
50
|
+
/** Degrees the view turns per pixel while dragging to look around. */
|
|
51
|
+
export declare const DRAG_LOOK = 0.22;
|
|
52
|
+
export declare const TURN_SPEED = 120;
|
|
53
|
+
/** Where the walker is, kept apart from the camera: the camera is whatever mode you are in, the
|
|
54
|
+
* avatar is the person, and they persist across leaving the walk and coming back to it. */
|
|
55
|
+
export interface WalkAvatar {
|
|
56
|
+
floorId: string | null;
|
|
57
|
+
/** Plan metres. */
|
|
58
|
+
position: Point;
|
|
59
|
+
/** Clockwise from plan +Y, as WalkPose.heading. */
|
|
60
|
+
heading: number;
|
|
61
|
+
pitch?: number;
|
|
62
|
+
}
|
|
63
|
+
export interface WalkPose {
|
|
64
|
+
/** Where the walker stands, in plan metres. */
|
|
65
|
+
position: Point;
|
|
66
|
+
/** Clockwise from plan +Y, matching the plan's own grid rather than the compass. */
|
|
67
|
+
heading: number;
|
|
68
|
+
pitch: number;
|
|
69
|
+
/** True while the mouse is held down and dragged to aim the view. */
|
|
70
|
+
looking: boolean;
|
|
71
|
+
}
|
|
72
|
+
/** Push a walker of radius `r` out of every wall it overlaps.
|
|
73
|
+
*
|
|
74
|
+
* Resolving each wall independently and in sequence is what produces sliding for free: walking into
|
|
75
|
+
* a wall at an angle leaves the along-wall component of the move untouched and cancels only the
|
|
76
|
+
* component that would have gone through it. Two passes settle inside corners, where pushing out of
|
|
77
|
+
* one wall can push you into its neighbour. */
|
|
78
|
+
export declare function unstick(p: Point, walls: Ring[], r?: number): Point;
|
|
79
|
+
/** The MapLibre camera that stands at `eye`, `alt` metres up, facing `bearing` and tilted `pitch`:
|
|
80
|
+
* the ground point it looks at and the zoom that puts it that far away.
|
|
81
|
+
*
|
|
82
|
+
* This is MapLibre's calculateCenterFromCameraLngLatAlt() for a camera that looks at the ground —
|
|
83
|
+
* the ray from the eye meets the ground alt/cos(pitch) away, and the zoom is the one at which that
|
|
84
|
+
* distance fills cameraToCenterDistance pixels. MapLibre's own copy gives up within six degrees of
|
|
85
|
+
* level and invents a target ten kilometres off instead, which is fine for a plane and is a 700 m
|
|
86
|
+
* eye for a person; this one holds to the ground right up to MAX_PITCH. The mercator scale is
|
|
87
|
+
* taken at the target rather than the eye, iterated, because a metre is a different fraction of
|
|
88
|
+
* the world at each latitude and the target is the point the zoom is measured at. */
|
|
89
|
+
export declare function eyeCamera(view: {
|
|
90
|
+
cameraToCenterDistance: number;
|
|
91
|
+
tileSize: number;
|
|
92
|
+
}, eye: [number, number], alt: number, bearing: number, pitch: number): {
|
|
93
|
+
center: [number, number];
|
|
94
|
+
zoom: number;
|
|
95
|
+
};
|
|
96
|
+
/** What a mouse movement does to where you are looking. Right turns you right; up looks up — which
|
|
97
|
+
* in MapLibre's terms is a LARGER pitch, 90 being level and 0 the floor. The head stops at the
|
|
98
|
+
* limits rather than wrapping: nobody looks at the ceiling by looking too far at their feet. */
|
|
99
|
+
export declare function aim(heading: number, pitch: number, dx: number, dy: number, perPixel?: number): {
|
|
100
|
+
heading: number;
|
|
101
|
+
pitch: number;
|
|
102
|
+
};
|
|
103
|
+
/** One frame of walking: what the held keys do to a heading and a position over `dt` seconds.
|
|
104
|
+
*
|
|
105
|
+
* Pulled out of the controller because it is the part with an opinion in it — which key turns you
|
|
106
|
+
* and which key carries you — and that opinion is worth stating somewhere a test can read it.
|
|
107
|
+
* Returns the new heading and the step to take, in plan metres, before any wall gets a say. */
|
|
108
|
+
export declare function stride(keys: ReadonlySet<string>, heading: number, dt: number): {
|
|
109
|
+
heading: number;
|
|
110
|
+
step?: Point;
|
|
111
|
+
};
|
|
112
|
+
/** Where you are after walking `travelled` metres along a polyline, and which way the path is
|
|
113
|
+
* heading `ahead` metres further on. Clamped at both ends, and `done` once the path runs out. */
|
|
114
|
+
export declare function alongPath(points: Point[], travelled: number, ahead?: number): {
|
|
115
|
+
at: Point;
|
|
116
|
+
heading: number;
|
|
117
|
+
done: boolean;
|
|
118
|
+
left: number;
|
|
119
|
+
};
|
|
120
|
+
/** Turn `from` towards `to` by at most `step` degrees, the short way round. */
|
|
121
|
+
export declare function easeHeading(from: number, to: number, step: number): number;
|
|
122
|
+
export interface WalkTerrain {
|
|
123
|
+
/** Solid wall bodies on the floor being walked, in plan metres. */
|
|
124
|
+
walls: Ring[];
|
|
125
|
+
/** Eye height above the presented ground plane: EYE plus whatever lifts the slab. */
|
|
126
|
+
eye: number;
|
|
127
|
+
floorId?: string | null;
|
|
128
|
+
elevation?: number;
|
|
129
|
+
stairs?: StairSurface[];
|
|
130
|
+
/** Whether a storey's slab supports the point, or an intentional drop has a landing below. */
|
|
131
|
+
supports?: (at: Point, floorId: string | null) => boolean;
|
|
132
|
+
dropAt?: (at: Point) => {
|
|
133
|
+
floorId: string;
|
|
134
|
+
distance: number;
|
|
135
|
+
} | undefined;
|
|
136
|
+
}
|
|
137
|
+
export interface WalkCallbacks {
|
|
138
|
+
/** Rebase at a stair landing, or before descending below the active scene's datum. */
|
|
139
|
+
onFloor?(floorId: string): void;
|
|
140
|
+
/** A real opening has a landing below. Rebase the scene onto that floor before animating descent. */
|
|
141
|
+
onDrop?(floorId: string): void;
|
|
142
|
+
/** Fired when the position, heading, pitch or look gesture changes. */
|
|
143
|
+
onPose(pose: WalkPose): void;
|
|
144
|
+
/** The walker asked to change level (F, or Shift+F for down). The host decides whether there is
|
|
145
|
+
* anywhere to go from where they are standing. */
|
|
146
|
+
onUse(down: boolean): void;
|
|
147
|
+
/** Escape: the host leaves walk mode. */
|
|
148
|
+
onExit(): void;
|
|
149
|
+
/** M: the walker wants the sound on or off. */
|
|
150
|
+
onSound?(): void;
|
|
151
|
+
}
|
|
152
|
+
/** The keys, by physical position rather than by letter so the layout survives a French or a Dvorak
|
|
153
|
+
* keyboard. W and S walk, A and D turn — the way Doom bound the arrows, and what a person
|
|
154
|
+
* walking a floor plan reaches for: the point of A is to look down the other corridor, not to
|
|
155
|
+
* sidle towards it. Q and E sidestep for whoever wants it, the arrows mirror the letters, and Shift
|
|
156
|
+
* runs. */
|
|
157
|
+
export declare const KEYS: Record<string, string>;
|
|
158
|
+
export declare class WalkController {
|
|
159
|
+
private readonly on;
|
|
160
|
+
private map?;
|
|
161
|
+
private origin;
|
|
162
|
+
private terrain;
|
|
163
|
+
private keys;
|
|
164
|
+
private frame;
|
|
165
|
+
private last;
|
|
166
|
+
private handlers;
|
|
167
|
+
private maxPitch;
|
|
168
|
+
private maxZoom;
|
|
169
|
+
private pixelRatio;
|
|
170
|
+
private planFov;
|
|
171
|
+
private fieldOfView;
|
|
172
|
+
private running;
|
|
173
|
+
private dragPointer;
|
|
174
|
+
private drag;
|
|
175
|
+
private path;
|
|
176
|
+
private travelled;
|
|
177
|
+
private arrive?;
|
|
178
|
+
private followOptions?;
|
|
179
|
+
private fall?;
|
|
180
|
+
private stairs;
|
|
181
|
+
position: Point;
|
|
182
|
+
heading: number;
|
|
183
|
+
pitch: number;
|
|
184
|
+
constructor(on: WalkCallbacks);
|
|
185
|
+
attach(map: GLMap, origin: Origin, start: {
|
|
186
|
+
position: Point;
|
|
187
|
+
heading: number;
|
|
188
|
+
pitch?: number;
|
|
189
|
+
}): void;
|
|
190
|
+
detach(): void;
|
|
191
|
+
/** The floor under the walker changed, or its walls were edited. */
|
|
192
|
+
setTerrain(terrain: WalkTerrain): void;
|
|
193
|
+
/** Widen the lens without changing the person's position, heading or eye height. */
|
|
194
|
+
setFieldOfView(value: number): void;
|
|
195
|
+
private resize;
|
|
196
|
+
/** Walk a path on its own, as far as it goes on this floor, then call `onArrive`. Taking any
|
|
197
|
+
* control cancels it: a tour you cannot interrupt is a video. */
|
|
198
|
+
follow(points: Point[], onArrive: () => void, options?: {
|
|
199
|
+
speed?: number;
|
|
200
|
+
physical?: boolean;
|
|
201
|
+
onCancel?: () => void;
|
|
202
|
+
}): void;
|
|
203
|
+
cancelFollow(notify?: boolean): void;
|
|
204
|
+
get following(): boolean;
|
|
205
|
+
/** Put the walker somewhere — arriving at a new floor, or jumping to a route's start. */
|
|
206
|
+
place(position: Point, heading?: number): void;
|
|
207
|
+
/** Inspect something from the current position. Only the walker writes a POV camera: panning
|
|
208
|
+
* its ground target like a plan camera would move the eye far behind the selected object. */
|
|
209
|
+
lookAt(point: Point): void;
|
|
210
|
+
get pose(): WalkPose;
|
|
211
|
+
get onStairs(): boolean;
|
|
212
|
+
/** Drag to look. Capture only delivers the remainder of this gesture if it leaves the canvas;
|
|
213
|
+
* the cursor stays visible and is free to operate panels as soon as the button is released. */
|
|
214
|
+
private grab;
|
|
215
|
+
private drop;
|
|
216
|
+
private endDrag;
|
|
217
|
+
private release;
|
|
218
|
+
private look;
|
|
219
|
+
private down;
|
|
220
|
+
private up;
|
|
221
|
+
private tick;
|
|
222
|
+
/** Stop at the first substep entering a hole, even when running over a narrow opening. */
|
|
223
|
+
private beginFall;
|
|
224
|
+
/** One frame of being carried along a route. The heading is rate-limited towards a point further
|
|
225
|
+
* up the path rather than snapped to the segment underfoot, which is what turns a corner into a
|
|
226
|
+
* turn instead of a cut. */
|
|
227
|
+
private advance;
|
|
228
|
+
/** One camera write per frame. The eye is where the walker stands, `terrain.eye` metres up, facing
|
|
229
|
+
* `heading` and tilted `pitch`; eyeCamera() turns that into the ground point the camera looks at
|
|
230
|
+
* and how far away it is, which is all a MapLibre camera can be told. */
|
|
231
|
+
private apply;
|
|
232
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Floor, ProjectDocument, Ring } from '../model/types';
|
|
2
|
+
/** Build the structural surroundings of both landings before a passenger starts climbing.
|
|
3
|
+
* The selected floor remains the walking datum; these levels only supply visible context. */
|
|
4
|
+
export declare function walkConnectionContext(project: ProjectDocument, active: Floor, primary?: Set<string>): Floor[];
|
|
5
|
+
/** Structural storeys seen through an authored atrium. Stops at a plate that closes the opening;
|
|
6
|
+
* room fit-out is deliberately left on its own floor. A room nested in a zone adds no new void. */
|
|
7
|
+
export declare function walkVoidContext(project: ProjectDocument, active: Floor, ceilingFloor: Floor): {
|
|
8
|
+
levels: Floor[];
|
|
9
|
+
roof: Floor | undefined;
|
|
10
|
+
ceilingOpenings: Ring[];
|
|
11
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Eye height and shoulder radius in scene metres. Shared by stair rails and planar collision. */
|
|
2
|
+
export declare const EYE = 1.7;
|
|
3
|
+
export declare const BODY = 0.28;
|
|
4
|
+
/** Walls starting above this band are lintels the walker can pass beneath. */
|
|
5
|
+
export declare const HEAD_ROOM = 1.25;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ElevatorControls } from '../model/host';
|
|
2
|
+
import type { StatusReading } from '../model/live';
|
|
3
|
+
import type { Route } from '../model/navigation';
|
|
4
|
+
import type { Point, ProjectDocument } from '../model/types';
|
|
5
|
+
export interface WalkJourneyHost {
|
|
6
|
+
project: ProjectDocument;
|
|
7
|
+
floor(): string | null;
|
|
8
|
+
changeFloor(id: string | null): Promise<void>;
|
|
9
|
+
position(): Point;
|
|
10
|
+
walk(points: Point[], options?: {
|
|
11
|
+
speed?: number;
|
|
12
|
+
physical?: boolean;
|
|
13
|
+
}): Promise<void>;
|
|
14
|
+
controls(): ElevatorControls | undefined;
|
|
15
|
+
status(feedId: string): StatusReading | undefined;
|
|
16
|
+
ride(id: string | null): void;
|
|
17
|
+
message(text: string): void;
|
|
18
|
+
step(index: number): void;
|
|
19
|
+
}
|
|
20
|
+
/** Stateful playback uses the same lift commands/readings as a passenger. Vertical legs must not
|
|
21
|
+
* disappear when a route is split into floor runs: that used to teleport straight past the ride. */
|
|
22
|
+
export declare class WalkJourney {
|
|
23
|
+
private host;
|
|
24
|
+
private stopped;
|
|
25
|
+
private timer?;
|
|
26
|
+
private rejectWait?;
|
|
27
|
+
constructor(host: WalkJourneyHost);
|
|
28
|
+
stop(): void;
|
|
29
|
+
private waitUntil;
|
|
30
|
+
private object;
|
|
31
|
+
private entry;
|
|
32
|
+
play(route: Route): Promise<void>;
|
|
33
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Point, ProjectDocument, Ring, SiteObject } from '../model/types';
|
|
2
|
+
/** Evaluate wall solids in absolute building heights. A host wall may continue through a
|
|
3
|
+
* mezzanine, while a low partition below it and a lintel overhead do not obstruct the walker. */
|
|
4
|
+
export declare function walkingWallRings(project: ProjectDocument, floorId: string | null): Ring[];
|
|
5
|
+
/** Build the support lookup when geometry changes, not for every walking frame. Open-air grade
|
|
6
|
+
* and floors without authored plates stay traversable. Higher and buried plates have real edges. */
|
|
7
|
+
export declare function floorSupport(project: ProjectDocument): {
|
|
8
|
+
supports: (at: Point, id: string | null) => boolean;
|
|
9
|
+
dropAt: (at: Point, id: string | null) => {
|
|
10
|
+
floorId: string;
|
|
11
|
+
distance: number;
|
|
12
|
+
} | undefined;
|
|
13
|
+
};
|
|
14
|
+
/** Clip a small walking step at the last supported point; never snap it onto another island. */
|
|
15
|
+
export declare function supportedStep(from: Point, to: Point, supports: (at: Point) => boolean): Point;
|
|
16
|
+
/** Keep a valid position across storeys, including a fall's landing. A floor picker can instead
|
|
17
|
+
* select a smaller footprint: enter it at a dry navigation point, not in the void outside it. */
|
|
18
|
+
export declare function floorArrival(project: ProjectDocument, floorId: string | null, at: Point): Point;
|
|
19
|
+
/** Only authored openings trigger a drop. Gaps outside the building, an undrawn floor, and
|
|
20
|
+
* overlapping areas that still provide a slab are not floor holes. */
|
|
21
|
+
export declare function floorDropAt(project: ProjectDocument, floorId: string | null, at: Point): {
|
|
22
|
+
floorId: string;
|
|
23
|
+
distance: number;
|
|
24
|
+
} | undefined;
|
|
25
|
+
/** Rooms which span the active storey bring the geometry inside their footprint along with them.
|
|
26
|
+
* The same context supplies the lower plate seen through an opening and the gallery seen from below. */
|
|
27
|
+
export declare function tallSpaceContext(project: ProjectDocument, floorId: string | null): SiteObject[];
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Point, ProjectDocument, Ring } from '../model/types';
|
|
2
|
+
/** Adjacent wall faces intersect once at each junction. Both walls use that same corner, so
|
|
3
|
+
* oblique L, T and four-way joins close without rectangular end caps protruding through them. */
|
|
4
|
+
export declare function wallFootprints(project: ProjectDocument): Map<string, Ring>;
|
|
5
|
+
/** Cut an opening across the joined footprint, retaining the mitres on the wall's outside ends. */
|
|
6
|
+
export declare function wallSpan(ring: Ring, origin: Point, direction: Point, start: number | null, end: number | null): Ring;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import type { Point, SiteObject } from '../model/types';
|
|
3
|
+
import type { MaterialLibrary } from './materials';
|
|
4
|
+
export declare function makePool(o: SiteObject, xy: (p: Point) => Point, base: number, materials: MaterialLibrary, time: {
|
|
5
|
+
value: number;
|
|
6
|
+
}, detailed?: boolean): THREE.Group;
|
|
7
|
+
export declare function makeWaterSlide(o: SiteObject, xy: (p: Point) => Point, base: number, materials: MaterialLibrary): THREE.Group<THREE.Object3DEventMap>;
|
|
8
|
+
/** Moving blue caustics from lit pools, restricted to their containing tiled chambers. This
|
|
9
|
+
* inexpensive projection approximates the focused light from small ripples; it is not ray tracing. */
|
|
10
|
+
export declare function applyPoolCaustics(scene: THREE.Scene, project: import('../model/types').ProjectDocument, floorId: string, xy: (point: Point) => Point, base: number, time: {
|
|
11
|
+
value: number;
|
|
12
|
+
}): void;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Point, ProjectDocument, Ring } from './types';
|
|
2
|
+
/** Ignore double-click duplicates; reject a crossing while the last good draft is still editable. */
|
|
3
|
+
export declare function appendAreaPoint(draft: Ring, point: Point): {
|
|
4
|
+
points: Ring;
|
|
5
|
+
error?: string;
|
|
6
|
+
};
|
|
7
|
+
/** The wall/partition tool: divide along the endpoints actually used after welding. */
|
|
8
|
+
export declare function drawBarrier(project: ProjectDocument, floorId: string | null, a: Point, b: Point, kind?: 'wall' | 'fence'): import("./types").Barrier | undefined;
|
|
9
|
+
/** A completed stroke stops chaining when its tip meets an existing boundary, including an
|
|
10
|
+
* earlier segment of the same outline. Test before adding the segment: afterwards every tip
|
|
11
|
+
* belongs to a boundary. Use the model's joining tolerance, not the pointer's snap reach. */
|
|
12
|
+
export declare function endsBoundaryStroke(project: ProjectDocument, floorId: string | null, a: Point, b: Point, kind?: 'wall' | 'fence' | 'boundary'): boolean;
|
|
13
|
+
/** The enclose tool: creating and re-fitting use exactly the same generated outline. */
|
|
14
|
+
export declare function encloseRoom(project: ProjectDocument, floorId: string | null, point: Point): {
|
|
15
|
+
room: import("./types").SiteObject;
|
|
16
|
+
existing: boolean;
|
|
17
|
+
} | null;
|
|
18
|
+
export type GeometryDrag = {
|
|
19
|
+
kind: 'junction';
|
|
20
|
+
id: string;
|
|
21
|
+
point: Point;
|
|
22
|
+
} | {
|
|
23
|
+
kind: 'barrier';
|
|
24
|
+
id: string;
|
|
25
|
+
point: Point;
|
|
26
|
+
} | {
|
|
27
|
+
kind: 'ring';
|
|
28
|
+
id: string;
|
|
29
|
+
point: Point;
|
|
30
|
+
ringIndex: number;
|
|
31
|
+
index: number;
|
|
32
|
+
};
|
|
33
|
+
/** Apply one requested drop to a transaction draft. The editor previews snapping alone and calls
|
|
34
|
+
* this once on release; transact either accepts the entire move or leaves the original intact. */
|
|
35
|
+
export declare function applyGeometryDrag(project: ProjectDocument, move: GeometryDrag): void;
|
|
36
|
+
/** Optional constrained authoring operation for hosts and scripted drawing: find a valid position
|
|
37
|
+
* along a requested movement. Interactive editor drags use applyGeometryDrag on release instead. */
|
|
38
|
+
export declare function dragGeometry(project: ProjectDocument, _floorId: string | null, move: GeometryDrag): ProjectDocument;
|