@kerros/editor 0.0.0-stage → 0.1.0-rc.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.
Files changed (345) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +35 -2
  3. package/dist/SitePlanner.js +1189 -0
  4. package/dist/SitePlanner.js.map +1 -0
  5. package/dist/adapters/basemap.js +11 -0
  6. package/dist/adapters/basemap.js.map +1 -0
  7. package/dist/adapters/persistence.js +121 -0
  8. package/dist/adapters/persistence.js.map +1 -0
  9. package/dist/adapters/status.js +11 -0
  10. package/dist/adapters/status.js.map +1 -0
  11. package/dist/adapters/useProjectPersistence.js +56 -0
  12. package/dist/adapters/useProjectPersistence.js.map +1 -0
  13. package/dist/components/AiImportPanel.js +635 -0
  14. package/dist/components/AiImportPanel.js.map +1 -0
  15. package/dist/components/AnalysisPreview.js +179 -0
  16. package/dist/components/AnalysisPreview.js.map +1 -0
  17. package/dist/components/ElevatorPanel.js +120 -0
  18. package/dist/components/ElevatorPanel.js.map +1 -0
  19. package/dist/components/Icons.js +57 -0
  20. package/dist/components/Icons.js.map +1 -0
  21. package/dist/components/ImportDialog.js +467 -0
  22. package/dist/components/ImportDialog.js.map +1 -0
  23. package/dist/components/Inspector.js +1184 -0
  24. package/dist/components/Inspector.js.map +1 -0
  25. package/dist/components/NavigatePanel.js +301 -0
  26. package/dist/components/NavigatePanel.js.map +1 -0
  27. package/dist/components/NavigationGraph.js +234 -0
  28. package/dist/components/NavigationGraph.js.map +1 -0
  29. package/dist/components/StructureExplorer.js +510 -0
  30. package/dist/components/StructureExplorer.js.map +1 -0
  31. package/dist/components/StructureView.js +286 -0
  32. package/dist/components/StructureView.js.map +1 -0
  33. package/dist/components/controls.js +209 -0
  34. package/dist/components/controls.js.map +1 -0
  35. package/dist/components/graphLayout.js +27 -0
  36. package/dist/components/graphLayout.js.map +1 -0
  37. package/dist/host.js +175 -0
  38. package/dist/host.js.map +1 -0
  39. package/dist/i18n.js +88 -0
  40. package/dist/i18n.js.map +1 -0
  41. package/dist/import/analysisPreview.js +41 -0
  42. package/dist/import/analysisPreview.js.map +1 -0
  43. package/dist/import/brief.js +29 -0
  44. package/dist/import/brief.js.map +1 -0
  45. package/dist/import/checkpoint.js +50 -0
  46. package/dist/import/checkpoint.js.map +1 -0
  47. package/dist/import/detect.js +120 -0
  48. package/dist/import/detect.js.map +1 -0
  49. package/dist/import/documentSvg.js +49 -0
  50. package/dist/import/documentSvg.js.map +1 -0
  51. package/dist/import/instructions.js +20 -0
  52. package/dist/import/instructions.js.map +1 -0
  53. package/dist/import/openings.js +61 -0
  54. package/dist/import/openings.js.map +1 -0
  55. package/dist/import/planImport.js +233 -0
  56. package/dist/import/planImport.js.map +1 -0
  57. package/dist/import/register.js +47 -0
  58. package/dist/import/register.js.map +1 -0
  59. package/dist/import/runs.js +67 -0
  60. package/dist/import/runs.js.map +1 -0
  61. package/dist/import/session.js +23 -0
  62. package/dist/import/session.js.map +1 -0
  63. package/dist/import/types.js +13 -0
  64. package/dist/import/types.js.map +1 -0
  65. package/dist/import/usage.js +29 -0
  66. package/dist/import/usage.js.map +1 -0
  67. package/dist/import/walls.js +112 -0
  68. package/dist/import/walls.js.map +1 -0
  69. package/dist/index.js +178 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/map/CabinMaterials.js +81 -0
  72. package/dist/map/CabinMaterials.js.map +1 -0
  73. package/dist/map/CabinMirror.js +43 -0
  74. package/dist/map/CabinMirror.js.map +1 -0
  75. package/dist/map/Doors.js +80 -0
  76. package/dist/map/Doors.js.map +1 -0
  77. package/dist/map/ElevatorCabin.js +93 -0
  78. package/dist/map/ElevatorCabin.js.map +1 -0
  79. package/dist/map/FixtureLights.js +117 -0
  80. package/dist/map/FixtureLights.js.map +1 -0
  81. package/dist/map/MapCanvas.js +2161 -0
  82. package/dist/map/MapCanvas.js.map +1 -0
  83. package/dist/map/Passenger.js +69 -0
  84. package/dist/map/Passenger.js.map +1 -0
  85. package/dist/map/SceneLayer.js +1534 -0
  86. package/dist/map/SceneLayer.js.map +1 -0
  87. package/dist/map/UndergroundContext.js +153 -0
  88. package/dist/map/UndergroundContext.js.map +1 -0
  89. package/dist/map/ambience.js +194 -0
  90. package/dist/map/ambience.js.map +1 -0
  91. package/dist/map/architecture.js +305 -0
  92. package/dist/map/architecture.js.map +1 -0
  93. package/dist/map/bathMusic.js +92 -0
  94. package/dist/map/bathMusic.js.map +1 -0
  95. package/dist/map/cameraAim.js +33 -0
  96. package/dist/map/cameraAim.js.map +1 -0
  97. package/dist/map/elevators.js +56 -0
  98. package/dist/map/elevators.js.map +1 -0
  99. package/dist/map/excavation.js +52 -0
  100. package/dist/map/excavation.js.map +1 -0
  101. package/dist/map/exteriors.js +25 -0
  102. package/dist/map/exteriors.js.map +1 -0
  103. package/dist/map/features.js +218 -0
  104. package/dist/map/features.js.map +1 -0
  105. package/dist/map/fences.js +29 -0
  106. package/dist/map/fences.js.map +1 -0
  107. package/dist/map/journey.js +112 -0
  108. package/dist/map/journey.js.map +1 -0
  109. package/dist/map/levels.js +6 -0
  110. package/dist/map/levels.js.map +1 -0
  111. package/dist/map/lighting.js +143 -0
  112. package/dist/map/lighting.js.map +1 -0
  113. package/dist/map/loadBasemap.js +26 -0
  114. package/dist/map/loadBasemap.js.map +1 -0
  115. package/dist/map/materials.js +183 -0
  116. package/dist/map/materials.js.map +1 -0
  117. package/dist/map/poolLighting.js +39 -0
  118. package/dist/map/poolLighting.js.map +1 -0
  119. package/dist/map/projection.js +24 -0
  120. package/dist/map/projection.js.map +1 -0
  121. package/dist/map/rampGeometry.js +38 -0
  122. package/dist/map/rampGeometry.js.map +1 -0
  123. package/dist/map/route.js +107 -0
  124. package/dist/map/route.js.map +1 -0
  125. package/dist/map/stairSurfaces.js +115 -0
  126. package/dist/map/stairSurfaces.js.map +1 -0
  127. package/dist/map/surfaces.js +136 -0
  128. package/dist/map/surfaces.js.map +1 -0
  129. package/dist/map/textures.js +95 -0
  130. package/dist/map/textures.js.map +1 -0
  131. package/dist/map/underground.js +34 -0
  132. package/dist/map/underground.js.map +1 -0
  133. package/dist/map/walk.js +433 -0
  134. package/dist/map/walk.js.map +1 -0
  135. package/dist/map/walkContext.js +46 -0
  136. package/dist/map/walkContext.js.map +1 -0
  137. package/dist/map/walkDimensions.js +7 -0
  138. package/dist/map/walkDimensions.js.map +1 -0
  139. package/dist/map/walkJourney.js +85 -0
  140. package/dist/map/walkJourney.js.map +1 -0
  141. package/dist/map/walkSurfaces.js +106 -0
  142. package/dist/map/walkSurfaces.js.map +1 -0
  143. package/dist/map/wallJoins.js +70 -0
  144. package/dist/map/wallJoins.js.map +1 -0
  145. package/dist/map/water.js +274 -0
  146. package/dist/map/water.js.map +1 -0
  147. package/dist/model/authoring.js +99 -0
  148. package/dist/model/authoring.js.map +1 -0
  149. package/dist/model/boundaries.js +548 -0
  150. package/dist/model/boundaries.js.map +1 -0
  151. package/dist/model/coverage.js +30 -0
  152. package/dist/model/coverage.js.map +1 -0
  153. package/dist/model/document.js +52 -0
  154. package/dist/model/document.js.map +1 -0
  155. package/dist/model/doors.js +47 -0
  156. package/dist/model/doors.js.map +1 -0
  157. package/dist/model/factory.js +56 -0
  158. package/dist/model/factory.js.map +1 -0
  159. package/dist/model/geometry.js +454 -0
  160. package/dist/model/geometry.js.map +1 -0
  161. package/dist/model/history.js +29 -0
  162. package/dist/model/history.js.map +1 -0
  163. package/dist/model/imports.js +45 -0
  164. package/dist/model/imports.js.map +1 -0
  165. package/dist/model/inference.js +182 -0
  166. package/dist/model/inference.js.map +1 -0
  167. package/dist/model/materials.js +11 -0
  168. package/dist/model/materials.js.map +1 -0
  169. package/dist/model/mutations.js +157 -0
  170. package/dist/model/mutations.js.map +1 -0
  171. package/dist/model/navigation.js +275 -0
  172. package/dist/model/navigation.js.map +1 -0
  173. package/dist/model/ontology.js +109 -0
  174. package/dist/model/ontology.js.map +1 -0
  175. package/dist/model/passages.js +5 -0
  176. package/dist/model/passages.js.map +1 -0
  177. package/dist/model/portals.js +42 -0
  178. package/dist/model/portals.js.map +1 -0
  179. package/dist/model/precision.js +11 -0
  180. package/dist/model/precision.js.map +1 -0
  181. package/dist/model/project.js +31 -0
  182. package/dist/model/project.js.map +1 -0
  183. package/dist/model/ramps.js +10 -0
  184. package/dist/model/ramps.js.map +1 -0
  185. package/dist/model/roomNavigation.js +87 -0
  186. package/dist/model/roomNavigation.js.map +1 -0
  187. package/dist/model/routeClearance.js +72 -0
  188. package/dist/model/routeClearance.js.map +1 -0
  189. package/dist/model/spaces.js +104 -0
  190. package/dist/model/spaces.js.map +1 -0
  191. package/dist/model/stairGeometry.js +40 -0
  192. package/dist/model/stairGeometry.js.map +1 -0
  193. package/dist/model/stairTraversal.js +48 -0
  194. package/dist/model/stairTraversal.js.map +1 -0
  195. package/dist/model/topology.js +63 -0
  196. package/dist/model/topology.js.map +1 -0
  197. package/dist/model/types.js +35 -0
  198. package/dist/model/types.js.map +1 -0
  199. package/dist/model/validate.js +240 -0
  200. package/dist/model/validate.js.map +1 -0
  201. package/dist/model/vertical.js +129 -0
  202. package/dist/model/vertical.js.map +1 -0
  203. package/dist/model/walls.js +261 -0
  204. package/dist/model/walls.js.map +1 -0
  205. package/dist/planner/DrawingDock.js +231 -0
  206. package/dist/planner/DrawingDock.js.map +1 -0
  207. package/dist/planner/FloorControls.js +93 -0
  208. package/dist/planner/FloorControls.js.map +1 -0
  209. package/dist/planner/MapSettings.js +143 -0
  210. package/dist/planner/MapSettings.js.map +1 -0
  211. package/dist/planner/PlannerHelp.js +57 -0
  212. package/dist/planner/PlannerHelp.js.map +1 -0
  213. package/dist/planner/ProjectSidebar.js +246 -0
  214. package/dist/planner/ProjectSidebar.js.map +1 -0
  215. package/dist/planner/floors.js +18 -0
  216. package/dist/planner/floors.js.map +1 -0
  217. package/dist/planner/useDrawingTools.js +341 -0
  218. package/dist/planner/useDrawingTools.js.map +1 -0
  219. package/dist/planner/useMapDisplay.js +51 -0
  220. package/dist/planner/useMapDisplay.js.map +1 -0
  221. package/dist/planner/usePlannerKeyboard.js +138 -0
  222. package/dist/planner/usePlannerKeyboard.js.map +1 -0
  223. package/dist/planner/useReferenceAlignment.js +50 -0
  224. package/dist/planner/useReferenceAlignment.js.map +1 -0
  225. package/dist/styles.css +4931 -0
  226. package/dist/theme/index.js +34 -0
  227. package/dist/theme/index.js.map +1 -0
  228. package/dist/types/SitePlanner.d.ts +5 -0
  229. package/dist/types/adapters/basemap.d.ts +2 -0
  230. package/dist/types/adapters/persistence.d.ts +29 -0
  231. package/dist/types/adapters/status.d.ts +4 -0
  232. package/dist/types/adapters/useProjectPersistence.d.ts +13 -0
  233. package/dist/types/components/AiImportPanel.d.ts +9 -0
  234. package/dist/types/components/AnalysisPreview.d.ts +4 -0
  235. package/dist/types/components/ElevatorPanel.d.ts +18 -0
  236. package/dist/types/components/Icons.d.ts +8 -0
  237. package/dist/types/components/ImportDialog.d.ts +42 -0
  238. package/dist/types/components/Inspector.d.ts +38 -0
  239. package/dist/types/components/NavigatePanel.d.ts +27 -0
  240. package/dist/types/components/NavigationGraph.d.ts +10 -0
  241. package/dist/types/components/StructureExplorer.d.ts +8 -0
  242. package/dist/types/components/StructureView.d.ts +22 -0
  243. package/dist/types/components/controls.d.ts +52 -0
  244. package/dist/types/components/graphLayout.d.ts +9 -0
  245. package/dist/types/editor/host.d.ts +9 -0
  246. package/dist/types/editor/index.d.ts +2 -0
  247. package/dist/types/i18n.d.ts +85 -0
  248. package/dist/types/import/analysisPreview.d.ts +27 -0
  249. package/dist/types/import/brief.d.ts +22 -0
  250. package/dist/types/import/checkpoint.d.ts +49 -0
  251. package/dist/types/import/detect.d.ts +34 -0
  252. package/dist/types/import/documentSvg.d.ts +2 -0
  253. package/dist/types/import/index.d.ts +10 -0
  254. package/dist/types/import/instructions.d.ts +7 -0
  255. package/dist/types/import/openings.d.ts +22 -0
  256. package/dist/types/import/planImport.d.ts +22 -0
  257. package/dist/types/import/register.d.ts +25 -0
  258. package/dist/types/import/runs.d.ts +31 -0
  259. package/dist/types/import/session.d.ts +33 -0
  260. package/dist/types/import/types.d.ts +56 -0
  261. package/dist/types/import/usage.d.ts +10 -0
  262. package/dist/types/import/walls.d.ts +37 -0
  263. package/dist/types/map/CabinMaterials.d.ts +18 -0
  264. package/dist/types/map/CabinMirror.d.ts +13 -0
  265. package/dist/types/map/Doors.d.ts +11 -0
  266. package/dist/types/map/ElevatorCabin.d.ts +20 -0
  267. package/dist/types/map/FixtureLights.d.ts +35 -0
  268. package/dist/types/map/MapCanvas.d.ts +87 -0
  269. package/dist/types/map/Passenger.d.ts +18 -0
  270. package/dist/types/map/SceneLayer.d.ts +306 -0
  271. package/dist/types/map/UndergroundContext.d.ts +18 -0
  272. package/dist/types/map/ambience.d.ts +29 -0
  273. package/dist/types/map/architecture.d.ts +8 -0
  274. package/dist/types/map/bathMusic.d.ts +14 -0
  275. package/dist/types/map/cameraAim.d.ts +20 -0
  276. package/dist/types/map/elevators.d.ts +16 -0
  277. package/dist/types/map/excavation.d.ts +9 -0
  278. package/dist/types/map/exteriors.d.ts +3 -0
  279. package/dist/types/map/features.d.ts +33 -0
  280. package/dist/types/map/fences.d.ts +4 -0
  281. package/dist/types/map/journey.d.ts +36 -0
  282. package/dist/types/map/levels.d.ts +4 -0
  283. package/dist/types/map/lighting.d.ts +103 -0
  284. package/dist/types/map/loadBasemap.d.ts +4 -0
  285. package/dist/types/map/materials.d.ts +38 -0
  286. package/dist/types/map/poolLighting.d.ts +11 -0
  287. package/dist/types/map/projection.d.ts +9 -0
  288. package/dist/types/map/rampGeometry.d.ts +8 -0
  289. package/dist/types/map/route.d.ts +59 -0
  290. package/dist/types/map/stairSurfaces.d.ts +29 -0
  291. package/dist/types/map/surfaces.d.ts +36 -0
  292. package/dist/types/map/textures.d.ts +8 -0
  293. package/dist/types/map/underground.d.ts +30 -0
  294. package/dist/types/map/walk.d.ts +232 -0
  295. package/dist/types/map/walkContext.d.ts +11 -0
  296. package/dist/types/map/walkDimensions.d.ts +5 -0
  297. package/dist/types/map/walkJourney.d.ts +33 -0
  298. package/dist/types/map/walkSurfaces.d.ts +27 -0
  299. package/dist/types/map/wallJoins.d.ts +6 -0
  300. package/dist/types/map/water.d.ts +12 -0
  301. package/dist/types/model/authoring.d.ts +38 -0
  302. package/dist/types/model/boundaries.d.ts +41 -0
  303. package/dist/types/model/coverage.d.ts +8 -0
  304. package/dist/types/model/document.d.ts +9 -0
  305. package/dist/types/model/doors.d.ts +19 -0
  306. package/dist/types/model/factory.d.ts +5 -0
  307. package/dist/types/model/geometry.d.ts +99 -0
  308. package/dist/types/model/history.d.ts +10 -0
  309. package/dist/types/model/host.d.ts +154 -0
  310. package/dist/types/model/imports.d.ts +7 -0
  311. package/dist/types/model/inference.d.ts +46 -0
  312. package/dist/types/model/live.d.ts +60 -0
  313. package/dist/types/model/materials.d.ts +28 -0
  314. package/dist/types/model/mutations.d.ts +178 -0
  315. package/dist/types/model/navigation.d.ts +70 -0
  316. package/dist/types/model/ontology.d.ts +43 -0
  317. package/dist/types/model/passages.d.ts +2 -0
  318. package/dist/types/model/portals.d.ts +9 -0
  319. package/dist/types/model/precision.d.ts +11 -0
  320. package/dist/types/model/project.d.ts +8 -0
  321. package/dist/types/model/ramps.d.ts +7 -0
  322. package/dist/types/model/roomNavigation.d.ts +15 -0
  323. package/dist/types/model/routeClearance.d.ts +11 -0
  324. package/dist/types/model/spaces.d.ts +46 -0
  325. package/dist/types/model/stairGeometry.d.ts +27 -0
  326. package/dist/types/model/stairTraversal.d.ts +8 -0
  327. package/dist/types/model/topology.d.ts +14 -0
  328. package/dist/types/model/types.d.ts +369 -0
  329. package/dist/types/model/validate.d.ts +38 -0
  330. package/dist/types/model/vertical.d.ts +145 -0
  331. package/dist/types/model/walls.d.ts +71 -0
  332. package/dist/types/planner/DrawingDock.d.ts +16 -0
  333. package/dist/types/planner/FloorControls.d.ts +17 -0
  334. package/dist/types/planner/MapSettings.d.ts +16 -0
  335. package/dist/types/planner/PlannerHelp.d.ts +3 -0
  336. package/dist/types/planner/ProjectSidebar.d.ts +32 -0
  337. package/dist/types/planner/floors.d.ts +3 -0
  338. package/dist/types/planner/types.d.ts +3 -0
  339. package/dist/types/planner/useDrawingTools.d.ts +52 -0
  340. package/dist/types/planner/useMapDisplay.d.ts +29 -0
  341. package/dist/types/planner/usePlannerKeyboard.d.ts +18 -0
  342. package/dist/types/planner/useReferenceAlignment.d.ts +30 -0
  343. package/dist/types/schema/index.d.ts +25 -0
  344. package/dist/types/theme/index.d.ts +55 -0
  345. package/package.json +52 -4
@@ -0,0 +1,43 @@
1
+ var y = Object.defineProperty;
2
+ var f = (i, e, r) => e in i ? y(i, e, { enumerable: !0, configurable: !0, writable: !0, value: r }) : i[e] = r;
3
+ var l = (i, e, r) => f(i, typeof e != "symbol" ? e + "" : e, r);
4
+ import * as t from "three";
5
+ import { Reflector as h } from "three/addons/objects/Reflector.js";
6
+ const w = 29;
7
+ function d(i, e) {
8
+ const r = i.projectionMatrixInverse.clone().premultiply(i.matrixWorld), a = new t.Vector3(0, 0, 0).applyMatrix4(r), s = new t.Vector3(0, 0.5, 0).applyMatrix4(r);
9
+ e.position.copy(i.position), e.up.copy(s).sub(a).normalize(), e.lookAt(a), e.updateMatrixWorld(!0), e.projectionMatrix.copy(i.projectionMatrix).multiply(i.matrixWorldInverse).multiply(e.matrixWorld);
10
+ const o = -1 / e.projectionMatrix.elements[11];
11
+ e.projectionMatrix.multiplyScalar(o), e.projectionMatrixInverse.copy(e.projectionMatrix).invert(), e.layers.mask = i.layers.mask, e.layers.enable(w), e.far = 1e4;
12
+ }
13
+ class j extends h {
14
+ constructor(r, a) {
15
+ super(new t.PlaneGeometry(r, a), {
16
+ textureWidth: 768,
17
+ textureHeight: 768,
18
+ multisample: 0,
19
+ color: "#c7d1d4",
20
+ clipBias: 2e-3
21
+ });
22
+ l(this, "view", new t.PerspectiveCamera());
23
+ l(this, "frames", 0);
24
+ this.name = "Cabin mirror", this.userData.cabinMirror = !0;
25
+ const s = this.onBeforeRender;
26
+ this.onBeforeRender = (o, c, n, p, m, x) => {
27
+ if (n.userData.cabinReflection || new t.Vector3().setFromMatrixPosition(this.matrixWorld).distanceToSquared(n.position) > 100) return;
28
+ d(n, this.view), this.camera.userData.cabinReflection = !0, this.camera.layers.mask = this.view.layers.mask;
29
+ const u = o.getViewport(new t.Vector4());
30
+ try {
31
+ s.call(this, o, c, this.view, p, m, x), this.userData.reflectionFrames = ++this.frames;
32
+ } finally {
33
+ o.setViewport(u);
34
+ }
35
+ };
36
+ }
37
+ }
38
+ export {
39
+ j as CabinMirror,
40
+ w as REFLECTION_BODY,
41
+ d as mirrorViewCamera
42
+ };
43
+ //# sourceMappingURL=CabinMirror.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CabinMirror.js","sources":["../../../../src/map/CabinMirror.ts"],"sourcesContent":["import * as THREE from 'three';\nimport { Reflector } from 'three/addons/objects/Reflector.js';\n\n/** The head is visible in the mirror, but never surrounds the first-person camera. */\nexport const REFLECTION_BODY = 29;\n\n/** MapLibre's camera encodes rotation in its projection matrix. Give the mirror a conventional\n * view frame while preserving the exact world-to-clip mapping, including the chosen POV lens. */\nexport function mirrorViewCamera(source: THREE.Camera, target: THREE.PerspectiveCamera) {\n const inverse = source.projectionMatrixInverse.clone().premultiply(source.matrixWorld);\n const ahead = new THREE.Vector3(0, 0, 0).applyMatrix4(inverse);\n const above = new THREE.Vector3(0, 0.5, 0).applyMatrix4(inverse);\n target.position.copy(source.position);\n target.up.copy(above).sub(ahead).normalize();\n target.lookAt(ahead);\n target.updateMatrixWorld(true);\n target.projectionMatrix\n .copy(source.projectionMatrix)\n .multiply(source.matrixWorldInverse)\n .multiply(target.matrixWorld);\n // The map's homogeneous matrix carries its metre-to-Mercator scale. Reflector's oblique\n // near-plane formula requires the conventional perspective row with P[3,2] = -1.\n const scale = -1 / target.projectionMatrix.elements[11];\n target.projectionMatrix.multiplyScalar(scale);\n target.projectionMatrixInverse.copy(target.projectionMatrix).invert();\n target.layers.mask = source.layers.mask;\n target.layers.enable(REFLECTION_BODY);\n target.far = 10000;\n}\n\n/** One live planar reflection, rendered only near a visible cabin. No recursive mirror passes. */\nexport class CabinMirror extends Reflector {\n private view = new THREE.PerspectiveCamera();\n private frames = 0;\n constructor(width: number, height: number) {\n super(new THREE.PlaneGeometry(width, height), {\n textureWidth: 768,\n textureHeight: 768,\n multisample: 0,\n color: '#c7d1d4',\n clipBias: 0.002,\n });\n this.name = 'Cabin mirror';\n this.userData.cabinMirror = true;\n const reflect = this.onBeforeRender;\n this.onBeforeRender = (renderer, scene, camera, geometry, material, group) => {\n if (camera.userData.cabinReflection) return;\n const at = new THREE.Vector3().setFromMatrixPosition(this.matrixWorld);\n if (at.distanceToSquared(camera.position) > 100) return;\n mirrorViewCamera(camera, this.view);\n this.camera.userData.cabinReflection = true;\n this.camera.layers.mask = this.view.layers.mask;\n const viewport = renderer.getViewport(new THREE.Vector4());\n try {\n reflect.call(this, renderer, scene, this.view, geometry, material, group);\n this.userData.reflectionFrames = ++this.frames;\n } finally {\n renderer.setViewport(viewport);\n }\n };\n }\n}\n"],"names":["REFLECTION_BODY","mirrorViewCamera","source","target","inverse","ahead","THREE","above","scale","CabinMirror","Reflector","width","height","__publicField","reflect","renderer","scene","camera","geometry","material","group","viewport"],"mappings":";;;;;AAIO,MAAMA,IAAkB;AAIxB,SAASC,EAAiBC,GAAsBC,GAAiC;AACtF,QAAMC,IAAUF,EAAO,wBAAwB,QAAQ,YAAYA,EAAO,WAAW,GAC/EG,IAAQ,IAAIC,EAAM,QAAQ,GAAG,GAAG,CAAC,EAAE,aAAaF,CAAO,GACvDG,IAAQ,IAAID,EAAM,QAAQ,GAAG,KAAK,CAAC,EAAE,aAAaF,CAAO;AAC/D,EAAAD,EAAO,SAAS,KAAKD,EAAO,QAAQ,GACpCC,EAAO,GAAG,KAAKI,CAAK,EAAE,IAAIF,CAAK,EAAE,UAAA,GACjCF,EAAO,OAAOE,CAAK,GACnBF,EAAO,kBAAkB,EAAI,GAC7BA,EAAO,iBACJ,KAAKD,EAAO,gBAAgB,EAC5B,SAASA,EAAO,kBAAkB,EAClC,SAASC,EAAO,WAAW;AAG9B,QAAMK,IAAQ,KAAKL,EAAO,iBAAiB,SAAS,EAAE;AACtD,EAAAA,EAAO,iBAAiB,eAAeK,CAAK,GAC5CL,EAAO,wBAAwB,KAAKA,EAAO,gBAAgB,EAAE,OAAA,GAC7DA,EAAO,OAAO,OAAOD,EAAO,OAAO,MACnCC,EAAO,OAAO,OAAOH,CAAe,GACpCG,EAAO,MAAM;AACf;AAGO,MAAMM,UAAoBC,EAAU;AAAA,EAGzC,YAAYC,GAAeC,GAAgB;AACzC,UAAM,IAAIN,EAAM,cAAcK,GAAOC,CAAM,GAAG;AAAA,MAC5C,cAAc;AAAA,MACd,eAAe;AAAA,MACf,aAAa;AAAA,MACb,OAAO;AAAA,MACP,UAAU;AAAA,IAAA,CACX;AATK,IAAAC,EAAA,cAAO,IAAIP,EAAM,kBAAA;AACjB,IAAAO,EAAA,gBAAS;AASf,SAAK,OAAO,gBACZ,KAAK,SAAS,cAAc;AAC5B,UAAMC,IAAU,KAAK;AACrB,SAAK,iBAAiB,CAACC,GAAUC,GAAOC,GAAQC,GAAUC,GAAUC,MAAU;AAG5E,UAFIH,EAAO,SAAS,mBACT,IAAIX,EAAM,UAAU,sBAAsB,KAAK,WAAW,EAC9D,kBAAkBW,EAAO,QAAQ,IAAI,IAAK;AACjD,MAAAhB,EAAiBgB,GAAQ,KAAK,IAAI,GAClC,KAAK,OAAO,SAAS,kBAAkB,IACvC,KAAK,OAAO,OAAO,OAAO,KAAK,KAAK,OAAO;AAC3C,YAAMI,IAAWN,EAAS,YAAY,IAAIT,EAAM,SAAS;AACzD,UAAI;AACF,QAAAQ,EAAQ,KAAK,MAAMC,GAAUC,GAAO,KAAK,MAAME,GAAUC,GAAUC,CAAK,GACxE,KAAK,SAAS,mBAAmB,EAAE,KAAK;AAAA,MAC1C,UAAA;AACE,QAAAL,EAAS,YAAYM,CAAQ;AAAA,MAC/B;AAAA,IACF;AAAA,EACF;AACF;"}
@@ -0,0 +1,80 @@
1
+ import * as x from "three";
2
+ import { mergeGeometries as I } from "three/addons/utils/BufferGeometryUtils.js";
3
+ import { metricUVs as z } from "./surfaces.js";
4
+ function O(o, d, c, a) {
5
+ const n = new x.Group(), t = o.width, S = o.doorSwing ?? 1, E = a.get("veneer", o.color ?? "#cab69a"), M = a.get("plaster", "#e1ded5"), g = a.metal("#aab0b2"), h = a.solid("#414448"), H = a.get("veneer", o.color ?? "#c0aa8d"), r = (i, f, p, e, b, u, T, s) => {
6
+ if (f <= 0 || p <= 0 || e <= 0) return;
7
+ const y = new x.BoxGeometry(f, p, e);
8
+ y.translate(b, u, T), z(y);
9
+ const G = new x.Mesh(y, s);
10
+ G.castShadow = G.receiveShadow = !0, G.userData.entityId = o.id, i.add(G);
11
+ };
12
+ for (const i of [-1, 1]) {
13
+ r(n, 0.035, d + 0.025, c, i * (t / 2 - 0.0175), 0, c / 2, M);
14
+ for (const f of [-1, 1])
15
+ r(
16
+ n,
17
+ 0.07,
18
+ 0.025,
19
+ c + 0.035,
20
+ i * (t / 2 + 5e-3),
21
+ f * (d / 2 + 0.012),
22
+ (c + 0.035) / 2,
23
+ M
24
+ );
25
+ }
26
+ r(n, t, d + 0.025, 0.035, 0, 0, c - 0.0175, M);
27
+ for (const i of [-1, 1]) r(n, t + 0.08, 0.025, 0.07, 0, i * (d / 2 + 0.012), c, M);
28
+ r(n, t, d + 0.04, 0.012, 0, 0, 6e-3, g);
29
+ const k = [], m = o.doorType === "sliding", l = o.doorType === "double", v = o.doorHinge === "right" ? 1 : -1, w = (l ? t / 2 : t) - (l ? 0.025 : 0.045);
30
+ for (let i = 0; i < (l ? 2 : 1); i++) {
31
+ const f = l ? i ? -1 : 1 : o.doorHinge === "right" ? -1 : 1, p = new x.Group(), e = new x.Group();
32
+ p.add(e), e.position.x = m ? 0 : -f * t / 2, e.position.y = m ? S * (d / 2 + 0.045) : 0;
33
+ const b = m ? 0 : f * (w / 2 + 0.025), u = c - 0.06, T = 0.02;
34
+ r(e, w, 0.045, u, b, 0, T + u / 2, E);
35
+ for (const s of [-1, 1]) {
36
+ r(
37
+ e,
38
+ Math.max(0.1, w - 0.16),
39
+ 6e-3,
40
+ Math.max(0.2, u - 0.38),
41
+ b,
42
+ s * 0.025,
43
+ T + u / 2 + 0.03,
44
+ H
45
+ ), r(e, Math.max(0.1, w - 0.1), 8e-3, 0.13, b, s * 0.027, 0.13, g);
46
+ const y = b + (m ? -v : f) * (w / 2 - 0.09);
47
+ m ? r(e, 0.026, 0.035, 0.3, y, s * 0.047, 1.03, g) : (r(e, 0.052, 0.012, 0.12, y, s * 0.033, 1.03, g), r(e, 0.11, 0.024, 0.021, y - f * 0.035, s * 0.067, 1.06, g), r(e, 0.017, 0.012, 0.028, y, s * 0.042, 1, h));
48
+ }
49
+ if (!m) for (const s of [0.25, u / 2, u - 0.22]) r(e, 0.025, 0.058, 0.09, f * 0.025, 0, s, g);
50
+ R(e), p.traverse((s) => {
51
+ s instanceof x.Mesh && (s.userData.entityId = o.id);
52
+ }), p.userData.doorType = o.doorType ?? "hinged", p.userData.entityId = o.id, k.push({
53
+ group: p,
54
+ setOpen: (s) => {
55
+ m ? e.position.x = v * (t + 0.03) * s : e.rotation.z = S * f * x.MathUtils.degToRad(72) * s;
56
+ }
57
+ });
58
+ }
59
+ if (m) {
60
+ const i = S * (d / 2 + 0.065);
61
+ r(n, t * 2 + 0.12, 0.05, 0.065, v * t / 2, i, c + 0.12, g);
62
+ for (const f of [-t / 2, t / 2, v * t]) r(n, 0.045, 0.08, 0.13, f, i, c + 0.1, h);
63
+ }
64
+ return { frame: n, panels: k };
65
+ }
66
+ function R(o) {
67
+ const d = /* @__PURE__ */ new Map();
68
+ for (const c of [...o.children]) {
69
+ const a = c, n = d.get(a.material) ?? [];
70
+ n.push(a.geometry), d.set(a.material, n), o.remove(a);
71
+ }
72
+ for (const [c, a] of d) {
73
+ const n = new x.Mesh(I(a), c);
74
+ n.castShadow = n.receiveShadow = !0, o.add(n), a.forEach((t) => t.dispose());
75
+ }
76
+ }
77
+ export {
78
+ O as makeDoor
79
+ };
80
+ //# sourceMappingURL=Doors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Doors.js","sources":["../../../../src/map/Doors.ts"],"sourcesContent":["import * as THREE from 'three';\nimport { mergeGeometries } from 'three/addons/utils/BufferGeometryUtils.js';\nimport type { SiteObject } from '../model/types';\nimport type { MaterialLibrary } from './materials';\nimport { metricUVs } from './surfaces';\n\n/** Local metres: X along the opening, Y toward side A, Z up. Hardware moves with its leaf. */\nexport function makeDoor(door: SiteObject, wallDepth: number, height: number, materials: MaterialLibrary) {\n const frame = new THREE.Group(),\n width = door.width,\n side = door.doorSwing ?? 1;\n const wood = materials.get('veneer', door.color ?? '#cab69a');\n const trim = materials.get('plaster', '#e1ded5'),\n metal = materials.metal('#aab0b2');\n const dark = materials.solid('#414448'),\n inset = materials.get('veneer', door.color ?? '#c0aa8d');\n const box = (\n parent: THREE.Group,\n w: number,\n d: number,\n h: number,\n x: number,\n y: number,\n z: number,\n material: THREE.Material,\n ) => {\n if (w <= 0 || d <= 0 || h <= 0) return;\n const geometry = new THREE.BoxGeometry(w, d, h);\n geometry.translate(x, y, z);\n metricUVs(geometry);\n const mesh = new THREE.Mesh(geometry, material);\n mesh.castShadow = mesh.receiveShadow = true;\n mesh.userData.entityId = door.id;\n parent.add(mesh);\n };\n // Recessed jambs and architraves on both sides, with a metal threshold at floor level.\n for (const sign of [-1, 1]) {\n box(frame, 0.035, wallDepth + 0.025, height, sign * (width / 2 - 0.0175), 0, height / 2, trim);\n for (const face of [-1, 1])\n box(\n frame,\n 0.07,\n 0.025,\n height + 0.035,\n sign * (width / 2 + 0.005),\n face * (wallDepth / 2 + 0.012),\n (height + 0.035) / 2,\n trim,\n );\n }\n box(frame, width, wallDepth + 0.025, 0.035, 0, 0, height - 0.0175, trim);\n for (const face of [-1, 1]) box(frame, width + 0.08, 0.025, 0.07, 0, face * (wallDepth / 2 + 0.012), height, trim);\n box(frame, width, wallDepth + 0.04, 0.012, 0, 0, 0.006, metal);\n\n const panels: { group: THREE.Group; setOpen: (value: number) => void }[] = [];\n const sliding = door.doorType === 'sliding',\n double = door.doorType === 'double';\n const travel = door.doorHinge === 'right' ? 1 : -1;\n const leafWidth = (double ? width / 2 : width) - (double ? 0.025 : 0.045);\n for (let i = 0; i < (double ? 2 : 1); i++) {\n const hand = double ? (i ? -1 : 1) : door.doorHinge === 'right' ? -1 : 1;\n const group = new THREE.Group(),\n pivot = new THREE.Group();\n group.add(pivot);\n pivot.position.x = sliding ? 0 : (-hand * width) / 2;\n pivot.position.y = sliding ? side * (wallDepth / 2 + 0.045) : 0;\n const x = sliding ? 0 : hand * (leafWidth / 2 + 0.025),\n h = height - 0.06,\n bottom = 0.02;\n box(pivot, leafWidth, 0.045, h, x, 0, bottom + h / 2, wood);\n // A shallow inset panel, narrow stile borders and a kick plate give depth at eye level.\n for (const face of [-1, 1]) {\n box(\n pivot,\n Math.max(0.1, leafWidth - 0.16),\n 0.006,\n Math.max(0.2, h - 0.38),\n x,\n face * 0.025,\n bottom + h / 2 + 0.03,\n inset,\n );\n box(pivot, Math.max(0.1, leafWidth - 0.1), 0.008, 0.13, x, face * 0.027, 0.13, metal);\n const latch = x + (sliding ? -travel : hand) * (leafWidth / 2 - 0.09);\n if (sliding) {\n box(pivot, 0.026, 0.035, 0.3, latch, face * 0.047, 1.03, metal);\n } else {\n box(pivot, 0.052, 0.012, 0.12, latch, face * 0.033, 1.03, metal);\n box(pivot, 0.11, 0.024, 0.021, latch - hand * 0.035, face * 0.067, 1.06, metal);\n box(pivot, 0.017, 0.012, 0.028, latch, face * 0.042, 1.0, dark);\n }\n }\n if (!sliding) for (const z of [0.25, h / 2, h - 0.22]) box(pivot, 0.025, 0.058, 0.09, hand * 0.025, 0, z, metal);\n mergeParts(pivot);\n group.traverse(child => {\n if (child instanceof THREE.Mesh) child.userData.entityId = door.id;\n });\n group.userData.doorType = door.doorType ?? 'hinged';\n group.userData.entityId = door.id;\n panels.push({\n group,\n setOpen: value => {\n if (sliding) pivot.position.x = travel * (width + 0.03) * value;\n else pivot.rotation.z = side * hand * THREE.MathUtils.degToRad(72) * value;\n },\n });\n }\n if (sliding) {\n const y = side * (wallDepth / 2 + 0.065);\n box(frame, width * 2 + 0.12, 0.05, 0.065, (travel * width) / 2, y, height + 0.12, metal);\n for (const x of [-width / 2, width / 2, travel * width]) box(frame, 0.045, 0.08, 0.13, x, y, height + 0.1, dark);\n }\n return { frame, panels };\n}\n\n/** Each articulated leaf costs one draw per finish, rather than one per handle or trim strip. */\nfunction mergeParts(group: THREE.Group) {\n const buckets = new Map<THREE.Material, THREE.BufferGeometry[]>();\n for (const child of [...group.children]) {\n const mesh = child as THREE.Mesh<THREE.BufferGeometry, THREE.Material>;\n const list = buckets.get(mesh.material) ?? [];\n list.push(mesh.geometry);\n buckets.set(mesh.material, list);\n group.remove(mesh);\n }\n for (const [material, parts] of buckets) {\n const mesh = new THREE.Mesh(mergeGeometries(parts)!, material);\n mesh.castShadow = mesh.receiveShadow = true;\n group.add(mesh);\n parts.forEach(p => p.dispose());\n }\n}\n"],"names":["makeDoor","door","wallDepth","height","materials","frame","THREE","width","side","wood","trim","metal","dark","inset","box","parent","w","d","h","x","y","z","material","geometry","metricUVs","mesh","sign","face","panels","sliding","double","travel","leafWidth","hand","group","pivot","bottom","latch","mergeParts","child","value","buckets","list","parts","mergeGeometries","p"],"mappings":"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"}
@@ -0,0 +1,93 @@
1
+ import * as c from "three";
2
+ import { elevatorMirrorFace as E, elevatorDoorWidth as F } from "./elevators.js";
3
+ import { CabinMirror as P } from "./CabinMirror.js";
4
+ const R = { front: 0, right: 90, back: 180, left: 270 };
5
+ function j(e, r, t, u, m) {
6
+ const n = new c.Group();
7
+ n.name = "Detailed elevator cabin", n.userData.cabin = !0;
8
+ const a = (o, b, d, w, k, M, l, D) => {
9
+ const i = new c.Mesh(new c.BoxGeometry(b, d, w), D);
10
+ return i.position.set(k, M, l), i.castShadow = i.receiveShadow = !0, o.add(i), i;
11
+ }, v = a(n, e.width, e.depth, 0.08, 0, 0, -0.04, t.floor);
12
+ v.name = "Cabin stone floor", v.userData.cabinFloor = !0, a(n, e.width, e.depth, 0.07, 0, 0, r, t.wall);
13
+ for (let o = -e.width / 2 + 0.6; o < e.width / 2; o += 0.6)
14
+ a(n, 8e-3, e.depth, 3e-3, o, 0, 2e-3, t.dark);
15
+ for (let o = -e.depth / 2 + 0.6; o < e.depth / 2; o += 0.6)
16
+ a(n, e.width, 8e-3, 3e-3, 0, o, 2e-3, t.dark);
17
+ for (const o of [-1, 1])
18
+ a(n, 0.22, e.depth * 0.7, 0.025, o * e.width * 0.3, 0, r - 0.05, t.trim), a(n, 0.17, e.depth * 0.67, 0.026, o * e.width * 0.3, 0, r - 0.065, t.lamp);
19
+ for (let o = 0; o < 9; o++) a(n, 0.36, 0.015, 0.012, 0, (o - 4) * 0.045, r - 0.045, t.dark);
20
+ const C = E(e);
21
+ for (const [o, b] of Object.entries(R)) {
22
+ const d = new c.Group();
23
+ d.rotation.z = b * Math.PI / 180, n.add(d);
24
+ const w = b % 180 ? e.depth : e.width, M = (b % 180 ? e.width : e.depth) / 2 - 0.045, l = M - 0.055, D = (e.doorSides ?? ["front"]).includes(o), i = F(e, b);
25
+ if (D) {
26
+ const x = Math.max(0.04, (w - i) / 2);
27
+ for (const f of [-1, 1])
28
+ a(d, x, 0.09, r, f * (i / 2 + x / 2), M, r / 2, t.steel), a(d, 0.032, 0.045, 2.3, f * (i / 2 + 0.025), l - 0.01, 1.15, t.trim);
29
+ a(d, i, 0.09, Math.max(0.05, r - 2.25), 0, M, (r + 2.25) / 2, t.steel), a(d, i, 0.22, 0.015, 0, M - 0.045, 7e-3, t.trim);
30
+ const s = document.createElement("canvas");
31
+ s.width = 256, s.height = 80;
32
+ const p = s.getContext("2d");
33
+ p.fillStyle = "#101a1f", p.fillRect(0, 0, 256, 80), p.fillStyle = "#f8ce82", p.font = "500 48px monospace", p.textAlign = "center", p.textBaseline = "middle", p.fillText(`${m ? "↕ " : ""}${u}`, 128, 42);
34
+ const S = new c.CanvasTexture(s);
35
+ S.colorSpace = c.SRGBColorSpace;
36
+ const y = new c.MeshBasicMaterial({ map: S, toneMapped: !1 });
37
+ y.userData.ownedMap = !0;
38
+ const G = new c.Mesh(new c.PlaneGeometry(0.42, 0.13), y);
39
+ G.position.set(0, l - 0.02, Math.min(r - 0.1, 2.36)), G.rotation.x = Math.PI / 2, d.add(G);
40
+ const h = i / 2 + x / 2;
41
+ a(d, Math.min(0.22, x * 0.85), 0.025, 0.78, h, l - 0.025, 1.26, t.trim);
42
+ for (let f = 0; f < 5; f++) {
43
+ const B = new c.Mesh(
44
+ new c.CylinderGeometry(0.019, 0.019, 0.015, 16),
45
+ f === 0 ? t.display : t.dark
46
+ );
47
+ B.position.set(h, l - 0.047, 1.48 - f * 0.105), d.add(B);
48
+ }
49
+ } else {
50
+ a(d, w, 0.09, r, 0, M, r / 2, t.wall);
51
+ for (let s = -w / 2 + 0.55; s < w / 2; s += 0.55)
52
+ a(d, 0.012, 8e-3, r - 0.16, s, l, r / 2, t.dark);
53
+ if (a(d, w, 0.014, 0.15, 0, l, 0.075, t.steel), o === C) {
54
+ const s = Math.max(0.35, w - 0.34), p = Math.min(1.93, r - 0.42), S = 0.26 + p / 2;
55
+ a(d, s + 0.05, 0.035, p + 0.05, 0, l - 0.018, S, t.trim);
56
+ const y = new P(s, p);
57
+ y.position.set(0, l - 0.041, S), y.rotation.x = Math.PI / 2, d.add(y);
58
+ }
59
+ const x = new c.Mesh(
60
+ new c.CylinderGeometry(0.025, 0.025, Math.max(0.25, w - 0.38), 12).rotateZ(Math.PI / 2),
61
+ t.trim
62
+ );
63
+ x.position.set(0, l - 0.12, 0.94), d.add(x);
64
+ for (const s of [-1, 1])
65
+ a(d, 0.035, 0.11, 0.035, s * (w / 2 - 0.28), l - 0.065, 0.94, t.trim);
66
+ }
67
+ }
68
+ return n;
69
+ }
70
+ function I(e, r, t) {
71
+ const u = e / 2, m = u * (1 - Math.max(0, Math.min(1, t)));
72
+ return { width: Math.max(0, m - 4e-3), center: r * (u - m / 2) };
73
+ }
74
+ function A(e, r, t, u) {
75
+ const m = new c.Group();
76
+ m.name = "Recessed metallic elevator door", m.userData.cabinDoor = !0;
77
+ const n = new c.Mesh(new c.BoxGeometry(1, 0.065, r), u.steel);
78
+ n.position.z = r / 2, n.castShadow = n.receiveShadow = !0, m.add(n);
79
+ const a = new c.Mesh(new c.BoxGeometry(6e-3, 0.069, r), u.trim);
80
+ a.position.z = r / 2, m.add(a);
81
+ const v = (C) => {
82
+ const o = I(e, t, C);
83
+ n.visible = a.visible = o.width > 1e-3, n.scale.x = o.width, n.position.x = o.center, a.position.x = o.center - t * o.width / 2, m.userData.openFraction = C;
84
+ };
85
+ return v(0), { group: m, update: v };
86
+ }
87
+ export {
88
+ R as FACE_TURN,
89
+ I as doorLeafSlice,
90
+ A as makeCabinDoor,
91
+ j as makeElevatorCabin
92
+ };
93
+ //# sourceMappingURL=ElevatorCabin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ElevatorCabin.js","sources":["../../../../src/map/ElevatorCabin.ts"],"sourcesContent":["import * as THREE from 'three';\nimport type { SiteObject } from '../model/types';\nimport { elevatorDoorWidth, elevatorMirrorFace } from './elevators';\nimport { CabinMirror } from './CabinMirror';\nimport type { CabinMaterials } from './CabinMaterials';\n\nexport const FACE_TURN = { front: 0, right: 90, back: 180, left: 270 };\n\nexport function makeElevatorCabin(\n o: SiteObject,\n height: number,\n finish: CabinMaterials,\n floorCode: string,\n moving: boolean,\n) {\n const group = new THREE.Group();\n group.name = 'Detailed elevator cabin';\n group.userData.cabin = true;\n const box = (\n parent: THREE.Object3D,\n w: number,\n d: number,\n h: number,\n x: number,\n y: number,\n z: number,\n material: THREE.Material,\n ) => {\n const mesh = new THREE.Mesh(new THREE.BoxGeometry(w, d, h), material);\n mesh.position.set(x, y, z);\n mesh.castShadow = mesh.receiveShadow = true;\n parent.add(mesh);\n return mesh;\n };\n const floor = box(group, o.width, o.depth, 0.08, 0, 0, -0.04, finish.floor);\n floor.name = 'Cabin stone floor';\n floor.userData.cabinFloor = true;\n box(group, o.width, o.depth, 0.07, 0, 0, height, finish.wall);\n // Stone floor panels, with dark narrow joints and a steel threshold.\n for (let x = -o.width / 2 + 0.6; x < o.width / 2; x += 0.6)\n box(group, 0.008, o.depth, 0.003, x, 0, 0.002, finish.dark);\n for (let y = -o.depth / 2 + 0.6; y < o.depth / 2; y += 0.6)\n box(group, o.width, 0.008, 0.003, 0, y, 0.002, finish.dark);\n for (const side of [-1, 1]) {\n box(group, 0.22, o.depth * 0.7, 0.025, side * o.width * 0.3, 0, height - 0.05, finish.trim);\n box(group, 0.17, o.depth * 0.67, 0.026, side * o.width * 0.3, 0, height - 0.065, finish.lamp);\n }\n for (let i = 0; i < 9; i++) box(group, 0.36, 0.015, 0.012, 0, (i - 4) * 0.045, height - 0.045, finish.dark);\n const mirrorFace = elevatorMirrorFace(o);\n for (const [face, turn] of Object.entries(FACE_TURN) as [keyof typeof FACE_TURN, number][]) {\n const wall = new THREE.Group();\n wall.rotation.z = (turn * Math.PI) / 180;\n group.add(wall);\n const across = turn % 180 ? o.depth : o.width,\n depth = turn % 180 ? o.width : o.depth;\n const y = depth / 2 - 0.045,\n inside = y - 0.055;\n const hasDoor = (o.doorSides ?? ['front']).includes(face),\n gap = elevatorDoorWidth(o, turn);\n if (hasDoor) {\n const jamb = Math.max(0.04, (across - gap) / 2);\n for (const side of [-1, 1]) {\n box(wall, jamb, 0.09, height, side * (gap / 2 + jamb / 2), y, height / 2, finish.steel);\n box(wall, 0.032, 0.045, 2.3, side * (gap / 2 + 0.025), inside - 0.01, 1.15, finish.trim);\n }\n box(wall, gap, 0.09, Math.max(0.05, height - 2.25), 0, y, (height + 2.25) / 2, finish.steel);\n box(wall, gap, 0.22, 0.015, 0, y - 0.045, 0.007, finish.trim);\n // Backlit floor display above the door; visible both directly and in the mirror.\n const canvas = document.createElement('canvas');\n canvas.width = 256;\n canvas.height = 80;\n const c = canvas.getContext('2d')!;\n c.fillStyle = '#101a1f';\n c.fillRect(0, 0, 256, 80);\n c.fillStyle = '#f8ce82';\n c.font = '500 48px monospace';\n c.textAlign = 'center';\n c.textBaseline = 'middle';\n c.fillText(`${moving ? '↕ ' : ''}${floorCode}`, 128, 42);\n const texture = new THREE.CanvasTexture(canvas);\n texture.colorSpace = THREE.SRGBColorSpace;\n const display = new THREE.MeshBasicMaterial({ map: texture, toneMapped: false });\n display.userData.ownedMap = true;\n const screen = new THREE.Mesh(new THREE.PlaneGeometry(0.42, 0.13), display);\n screen.position.set(0, inside - 0.02, Math.min(height - 0.1, 2.36));\n screen.rotation.x = Math.PI / 2;\n wall.add(screen);\n // A recessed control plate to one side of the entrance. Commands remain in the sidebar.\n const panelX = gap / 2 + jamb / 2;\n box(wall, Math.min(0.22, jamb * 0.85), 0.025, 0.78, panelX, inside - 0.025, 1.26, finish.trim);\n for (let i = 0; i < 5; i++) {\n const button = new THREE.Mesh(\n new THREE.CylinderGeometry(0.019, 0.019, 0.015, 16),\n i === 0 ? finish.display : finish.dark,\n );\n button.position.set(panelX, inside - 0.047, 1.48 - i * 0.105);\n wall.add(button);\n }\n } else {\n box(wall, across, 0.09, height, 0, y, height / 2, finish.wall);\n for (let x = -across / 2 + 0.55; x < across / 2; x += 0.55)\n box(wall, 0.012, 0.008, height - 0.16, x, inside, height / 2, finish.dark);\n box(wall, across, 0.014, 0.15, 0, inside, 0.075, finish.steel);\n if (face === mirrorFace) {\n const width = Math.max(0.35, across - 0.34),\n mirrorHeight = Math.min(1.93, height - 0.42),\n centerZ = 0.26 + mirrorHeight / 2;\n box(wall, width + 0.05, 0.035, mirrorHeight + 0.05, 0, inside - 0.018, centerZ, finish.trim);\n const mirror = new CabinMirror(width, mirrorHeight);\n mirror.position.set(0, inside - 0.041, centerZ);\n mirror.rotation.x = Math.PI / 2;\n wall.add(mirror);\n }\n const rail = new THREE.Mesh(\n new THREE.CylinderGeometry(0.025, 0.025, Math.max(0.25, across - 0.38), 12).rotateZ(Math.PI / 2),\n finish.trim,\n );\n rail.position.set(0, inside - 0.12, 0.94);\n wall.add(rail);\n for (const side of [-1, 1])\n box(wall, 0.035, 0.11, 0.035, side * (across / 2 - 0.28), inside - 0.065, 0.94, finish.trim);\n }\n }\n return group;\n}\n\n/** The visible portion of a leaf as it retracts behind the jamb. Clipping at the opening keeps\n * the concealed leaf inside its pocket even on shafts narrower than a full exposed door travel. */\nexport function doorLeafSlice(gap: number, sign: number, progress: number) {\n const half = gap / 2,\n remaining = half * (1 - Math.max(0, Math.min(1, progress)));\n return { width: Math.max(0, remaining - 0.004), center: sign * (half - remaining / 2) };\n}\nexport function makeCabinDoor(gap: number, height: number, sign: number, finish: CabinMaterials) {\n const group = new THREE.Group();\n group.name = 'Recessed metallic elevator door';\n group.userData.cabinDoor = true;\n const leaf = new THREE.Mesh(new THREE.BoxGeometry(1, 0.065, height), finish.steel);\n leaf.position.z = height / 2;\n leaf.castShadow = leaf.receiveShadow = true;\n group.add(leaf);\n const edge = new THREE.Mesh(new THREE.BoxGeometry(0.006, 0.069, height), finish.trim);\n edge.position.z = height / 2;\n group.add(edge);\n const update = (progress: number) => {\n const slice = doorLeafSlice(gap, sign, progress);\n leaf.visible = edge.visible = slice.width > 0.001;\n leaf.scale.x = slice.width;\n leaf.position.x = slice.center;\n edge.position.x = slice.center - (sign * slice.width) / 2;\n group.userData.openFraction = progress;\n };\n update(0);\n return { group, update };\n}\n"],"names":["FACE_TURN","makeElevatorCabin","o","height","finish","floorCode","moving","group","THREE","box","parent","w","h","x","y","z","material","mesh","floor","side","i","mirrorFace","elevatorMirrorFace","face","turn","wall","across","inside","hasDoor","gap","elevatorDoorWidth","jamb","canvas","c","texture","display","screen","panelX","button","width","mirrorHeight","centerZ","mirror","CabinMirror","rail","doorLeafSlice","sign","progress","half","remaining","makeCabinDoor","leaf","edge","update","slice"],"mappings":"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"}
@@ -0,0 +1,117 @@
1
+ var w = Object.defineProperty;
2
+ var M = (l, o, e) => o in l ? w(l, o, { enumerable: !0, configurable: !0, writable: !0, value: e }) : l[o] = e;
3
+ var d = (l, o, e) => M(l, typeof o != "symbol" ? o + "" : o, e);
4
+ import * as c from "three";
5
+ import { kelvinColor as S } from "./lighting.js";
6
+ function u(l, o, e = 0) {
7
+ if (e <= 0) return 1;
8
+ let n = 0;
9
+ for (let a = 0; a < l.length; a++) n = Math.imul(n, 31) + l.charCodeAt(a) | 0;
10
+ const h = (o + (n >>> 0) / 1e3) % 7.7, f = h < 0.09 || h > 0.18 && h < 0.25;
11
+ return 1 - e * (f ? 0.95 : 0.015 * (1 + Math.sin(o * 37 + n)));
12
+ }
13
+ const v = 4, p = 2;
14
+ class I {
15
+ constructor(o, e, n, h, f) {
16
+ d(this, "points");
17
+ d(this, "colors");
18
+ d(this, "emitters");
19
+ d(this, "lights");
20
+ d(this, "active", []);
21
+ d(this, "lastFlicker", -1 / 0);
22
+ d(this, "flickering");
23
+ this.fixtures = e, this.points = e.map((t) => {
24
+ var s;
25
+ return new c.Vector3(...n(t.position), h + (((s = t.light) == null ? void 0 : s.mountHeight) ?? t.height));
26
+ }), this.colors = e.map((t) => new c.Color(S(t.light.kelvin))), this.flickering = e.some((t) => {
27
+ var s;
28
+ return !!((s = t.light) != null && s.flicker);
29
+ });
30
+ const a = new c.InstancedMesh(
31
+ new c.BoxGeometry(1, 1, 1),
32
+ f.solid("#b6b4a6"),
33
+ e.length
34
+ );
35
+ this.emitters = new c.InstancedMesh(
36
+ new c.BoxGeometry(1, 1, 1),
37
+ new c.MeshBasicMaterial({ color: "#ffffff", toneMapped: !1 }),
38
+ e.length
39
+ );
40
+ for (const t of [a, this.emitters])
41
+ t.userData.entityIds = e.map((s) => s.id), t.castShadow = !1, o.add(t);
42
+ const i = new c.Object3D();
43
+ e.forEach((t, s) => {
44
+ const r = n(t.position), g = n([
45
+ t.position[0] + Math.cos(t.rotation * Math.PI / 180),
46
+ t.position[1] + Math.sin(t.rotation * Math.PI / 180)
47
+ ]);
48
+ i.position.copy(this.points[s]), i.rotation.set(
49
+ t.light.mountHeight !== void 0 && t.light.mountHeight < 0 ? -Math.PI / 2 : 0,
50
+ 0,
51
+ Math.atan2(g[1] - r[1], g[0] - r[0]),
52
+ "ZYX"
53
+ ), i.scale.set(t.width + 0.08, t.depth + 0.08, 0.09), i.updateMatrix(), a.setMatrixAt(s, i.matrix), i.translateZ(-0.052), i.scale.set(t.width, t.depth, 0.018), i.updateMatrix(), this.emitters.setMatrixAt(s, i.matrix), this.emitters.setColorAt(s, this.colors[s].clone().multiplyScalar(t.light.intensity > 0 ? 1 : 0.08));
54
+ }), this.emitters.instanceColor.setUsage(c.DynamicDrawUsage), this.lights = Array.from({ length: Math.min(v, e.length) }, () => {
55
+ const t = new c.PointLight("#fff", 0, 12, 2);
56
+ return t.castShadow = !1, t.shadow.autoUpdate = !1, t.shadow.mapSize.set(256, 256), t.shadow.camera.near = 0.1, t.shadow.bias = -1e-3, t.shadow.normalBias = 0.025, o.add(t), t;
57
+ }), this.lights.slice(0, p).forEach((t) => {
58
+ t.castShadow = !0;
59
+ });
60
+ }
61
+ /** The shadows go to the nearest lamps, and stay with them until a lamp without one is clearly
62
+ * nearer — a swap redraws a shadow, so a walker straddling two lamps must not swap on every step.
63
+ * Always exactly SHADOWED_FIXTURE_LIGHTS flags are set, empty slots included: see the constant. */
64
+ assignShadows(o) {
65
+ const e = this.lights.map((i, t) => ({ light: i, slot: t, i: this.active[t] })), n = e.filter((i) => i.i !== void 0), h = (i) => this.points[i.i].distanceToSquared(o), f = [...n].sort((i, t) => h(i) - h(t)), a = new Set(n.filter((i) => i.light.castShadow));
66
+ for (const i of f.slice(0, p)) {
67
+ if (a.has(i)) continue;
68
+ const t = [...a].sort((s, r) => h(r) - h(s))[0];
69
+ t && h(i) * 1.3 < h(t) ? (a.delete(t), a.add(i)) : a.size < p && a.add(i);
70
+ }
71
+ for (const i of e) a.size < p && i.i === void 0 && a.add(i);
72
+ for (const i of e) {
73
+ const t = a.has(i);
74
+ t && !i.light.castShadow && (i.light.shadow.needsUpdate = !0), i.light.castShadow = t;
75
+ }
76
+ }
77
+ /** Every lamp's shadow is stale — the scene changed under them. */
78
+ invalidate() {
79
+ for (const o of this.lights) o.shadow.needsUpdate = !0;
80
+ }
81
+ update(o, e) {
82
+ const n = this.points.map((t, s) => ({ i: s, distance: t.distanceToSquared(o) })).filter(
83
+ ({ i: t, distance: s }) => this.fixtures[t].light.intensity > 0 && s < this.fixtures[t].light.range ** 2
84
+ ).sort((t, s) => t.distance - s.distance).map((t) => t.i), h = n.slice(0, this.lights.length), f = new Set(n.slice(0, this.lights.length + 1)), a = this.lights.map((t, s) => {
85
+ const r = this.active[s];
86
+ return r !== void 0 && f.has(r) ? r : void 0;
87
+ });
88
+ for (const t of h) {
89
+ if (a.includes(t)) continue;
90
+ const s = a.indexOf(void 0);
91
+ if (s < 0) break;
92
+ a[s] = t;
93
+ }
94
+ let i = !1;
95
+ return this.lights.forEach((t, s) => {
96
+ const r = a[s];
97
+ if (this.active[s] !== r && (i = !0, t.shadow.needsUpdate = !0), r === void 0) {
98
+ t.intensity = 0;
99
+ return;
100
+ }
101
+ const g = this.fixtures[r], m = g.light;
102
+ t.position.copy(this.points[r]), t.position.z -= 0.12, t.color.copy(this.colors[r]), t.distance = m.range, t.intensity = m.intensity * u(g.id, e, m.flicker);
103
+ }), this.active = a, this.assignShadows(o), this.flickering && e - this.lastFlicker >= 0.04 && (this.fixtures.forEach((t, s) => {
104
+ t.light.flicker && this.emitters.setColorAt(
105
+ s,
106
+ this.colors[s].clone().multiplyScalar(t.light.intensity > 0 ? u(t.id, e, t.light.flicker) : 0.08)
107
+ );
108
+ }), this.emitters.instanceColor.needsUpdate = !0, this.lastFlicker = e), { shadowsChanged: i, animate: this.flickering };
109
+ }
110
+ }
111
+ export {
112
+ I as FixtureLights,
113
+ v as MAX_FIXTURE_LIGHTS,
114
+ p as SHADOWED_FIXTURE_LIGHTS,
115
+ u as fixtureOutput
116
+ };
117
+ //# sourceMappingURL=FixtureLights.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FixtureLights.js","sources":["../../../../src/map/FixtureLights.ts"],"sourcesContent":["import * as THREE from 'three';\nimport type { Point, SiteObject } from '../model/types';\nimport { kelvinColor } from './lighting';\nimport type { MaterialLibrary } from './materials';\n\n/** Occasional ballast dropouts, not a regular strobe. Stable per fixture and elapsed time. */\nexport function fixtureOutput(id: string, seconds: number, flicker = 0): number {\n if (flicker <= 0) return 1;\n let hash = 0;\n for (let i = 0; i < id.length; i++) hash = (Math.imul(hash, 31) + id.charCodeAt(i)) | 0;\n const phase = (seconds + (hash >>> 0) / 1000) % 7.7;\n const dropout = phase < 0.09 || (phase > 0.18 && phase < 0.25);\n return 1 - flicker * (dropout ? 0.95 : 0.015 * (1 + Math.sin(seconds * 37 + hash)));\n}\nexport const MAX_FIXTURE_LIGHTS = 4;\n/** How many of those throw shadows. A shadowed lamp is six shadow passes when it moves and a cube\n * of shadow taps on every pixel every frame; the two nearest carry the room, and the two beyond\n * them light without shadow, which nobody notices past the first two. The count is held constant\n * — an empty slot keeps its flag — because the shader is compiled for a number of shadowed lights\n * and changing that number recompiles every material in the scene. */\nexport const SHADOWED_FIXTURE_LIGHTS = 2;\n\n/** All fittings are two instanced draws. Only the nearest few cast light/shadows, keeping the\n * shader and shadow-map budget constant whether the document contains ten lamps or ten thousand. */\nexport class FixtureLights {\n private points: THREE.Vector3[];\n private colors: THREE.Color[];\n private emitters: THREE.InstancedMesh;\n private lights: THREE.PointLight[];\n private active: (number | undefined)[] = [];\n private lastFlicker = -Infinity;\n private flickering: boolean;\n constructor(\n scene: THREE.Scene,\n private fixtures: SiteObject[],\n xy: (p: Point) => Point,\n base: number,\n materials: MaterialLibrary,\n ) {\n this.points = fixtures.map(o => new THREE.Vector3(...xy(o.position), base + (o.light?.mountHeight ?? o.height)));\n this.colors = fixtures.map(o => new THREE.Color(kelvinColor(o.light!.kelvin)));\n this.flickering = fixtures.some(o => !!o.light?.flicker);\n const housings = new THREE.InstancedMesh(\n new THREE.BoxGeometry(1, 1, 1),\n materials.solid('#b6b4a6'),\n fixtures.length,\n );\n this.emitters = new THREE.InstancedMesh(\n new THREE.BoxGeometry(1, 1, 1),\n new THREE.MeshBasicMaterial({ color: '#ffffff', toneMapped: false }),\n fixtures.length,\n );\n for (const mesh of [housings, this.emitters]) {\n mesh.userData.entityIds = fixtures.map(o => o.id);\n mesh.castShadow = false;\n scene.add(mesh);\n }\n const transform = new THREE.Object3D();\n fixtures.forEach((o, i) => {\n const origin = xy(o.position),\n along = xy([\n o.position[0] + Math.cos((o.rotation * Math.PI) / 180),\n o.position[1] + Math.sin((o.rotation * Math.PI) / 180),\n ]);\n transform.position.copy(this.points[i]);\n transform.rotation.set(\n o.light!.mountHeight !== undefined && o.light!.mountHeight < 0 ? -Math.PI / 2 : 0,\n 0,\n Math.atan2(along[1] - origin[1], along[0] - origin[0]),\n 'ZYX',\n );\n transform.scale.set(o.width + 0.08, o.depth + 0.08, 0.09);\n transform.updateMatrix();\n housings.setMatrixAt(i, transform.matrix);\n // Offset out of the housing along the fitting's own face: downward for ceiling panels,\n // horizontally into the pool for wall-mounted submerged fittings.\n transform.translateZ(-0.052);\n transform.scale.set(o.width, o.depth, 0.018);\n transform.updateMatrix();\n this.emitters.setMatrixAt(i, transform.matrix);\n this.emitters.setColorAt(i, this.colors[i].clone().multiplyScalar(o.light!.intensity > 0 ? 1 : 0.08));\n });\n this.emitters.instanceColor!.setUsage(THREE.DynamicDrawUsage);\n this.lights = Array.from({ length: Math.min(MAX_FIXTURE_LIGHTS, fixtures.length) }, () => {\n const light = new THREE.PointLight('#fff', 0, 12, 2);\n light.castShadow = false;\n // Each lamp's shadow is six passes over the scene, and they are redrawn only when the lamp\n // itself changes — see update(). Left on automatic, every one of them would be redrawn each\n // time anything at all asked for shadows, the sun included.\n light.shadow.autoUpdate = false;\n light.shadow.mapSize.set(256, 256);\n light.shadow.camera.near = 0.1;\n light.shadow.bias = -0.001;\n light.shadow.normalBias = 0.025;\n scene.add(light);\n return light;\n });\n this.lights.slice(0, SHADOWED_FIXTURE_LIGHTS).forEach(light => {\n light.castShadow = true;\n });\n }\n /** The shadows go to the nearest lamps, and stay with them until a lamp without one is clearly\n * nearer — a swap redraws a shadow, so a walker straddling two lamps must not swap on every step.\n * Always exactly SHADOWED_FIXTURE_LIGHTS flags are set, empty slots included: see the constant. */\n private assignShadows(eye: THREE.Vector3) {\n const active = this.lights.map((light, slot) => ({ light, slot, i: this.active[slot] }));\n const lit = active.filter(a => a.i !== undefined);\n const distance = (a: (typeof lit)[number]) => this.points[a.i!].distanceToSquared(eye);\n const nearest = [...lit].sort((a, b) => distance(a) - distance(b));\n const casters = new Set(lit.filter(a => a.light.castShadow));\n // Promote a lamp only when it is nearer than a current caster by a margin: 1.3 in squared\n // distance is about 14 % in metres, a clear step and not a wobble.\n for (const a of nearest.slice(0, SHADOWED_FIXTURE_LIGHTS)) {\n if (casters.has(a)) continue;\n const worst = [...casters].sort((x, y) => distance(y) - distance(x))[0];\n if (worst && distance(a) * 1.3 < distance(worst)) {\n casters.delete(worst);\n casters.add(a);\n } else if (casters.size < SHADOWED_FIXTURE_LIGHTS) casters.add(a);\n }\n // Pad with empty slots so the number of shadowed lights never changes.\n for (const a of active) if (casters.size < SHADOWED_FIXTURE_LIGHTS && a.i === undefined) casters.add(a);\n for (const a of active) {\n const cast = casters.has(a);\n if (cast && !a.light.castShadow) a.light.shadow.needsUpdate = true;\n a.light.castShadow = cast;\n }\n }\n /** Every lamp's shadow is stale — the scene changed under them. */\n invalidate() {\n for (const light of this.lights) light.shadow.needsUpdate = true;\n }\n update(eye: THREE.Vector3, seconds: number) {\n const ranked = this.points\n .map((at, i) => ({ i, distance: at.distanceToSquared(eye) }))\n .filter(\n ({ i, distance }) => this.fixtures[i].light!.intensity > 0 && distance < this.fixtures[i].light!.range ** 2,\n )\n .sort((a, b) => a.distance - b.distance)\n .map(c => c.i);\n // A lamp keeps its slot for as long as it is lit and near: swapping a lamp means redrawing its\n // shadow, six passes over everything it can reach, so the assignment has to be stable under a\n // walker's ordinary jitter. Re-sorting by distance every frame was not — two lamps at similar\n // range traded slots on every step and every step redrew both. A lamp stays while it ranks\n // within one place of the cut, so a lamp on the boundary does not flicker in and out either.\n const wanted = ranked.slice(0, this.lights.length);\n const keep = new Set(ranked.slice(0, this.lights.length + 1));\n const next: (number | undefined)[] = this.lights.map((_, slot) => {\n const i = this.active[slot];\n return i !== undefined && keep.has(i) ? i : undefined;\n });\n for (const i of wanted) {\n if (next.includes(i)) continue;\n const free = next.indexOf(undefined);\n if (free < 0) break;\n next[free] = i;\n }\n let shadowsChanged = false;\n this.lights.forEach((light, slot) => {\n const i = next[slot];\n if (this.active[slot] !== i) {\n shadowsChanged = true;\n light.shadow.needsUpdate = true;\n }\n if (i === undefined) {\n light.intensity = 0;\n return;\n }\n const o = this.fixtures[i],\n spec = o.light!;\n light.position.copy(this.points[i]);\n light.position.z -= 0.12;\n light.color.copy(this.colors[i]);\n light.distance = spec.range;\n light.intensity = spec.intensity * fixtureOutput(o.id, seconds, spec.flicker);\n });\n this.active = next;\n this.assignShadows(eye);\n if (this.flickering && seconds - this.lastFlicker >= 0.04) {\n this.fixtures.forEach((o, i) => {\n if (o.light!.flicker)\n this.emitters.setColorAt(\n i,\n this.colors[i]\n .clone()\n .multiplyScalar(o.light!.intensity > 0 ? fixtureOutput(o.id, seconds, o.light!.flicker) : 0.08),\n );\n });\n this.emitters.instanceColor!.needsUpdate = true;\n this.lastFlicker = seconds;\n }\n return { shadowsChanged, animate: this.flickering };\n }\n}\n"],"names":["fixtureOutput","id","seconds","flicker","hash","i","phase","dropout","MAX_FIXTURE_LIGHTS","SHADOWED_FIXTURE_LIGHTS","FixtureLights","scene","fixtures","xy","base","materials","__publicField","THREE","o","_a","kelvinColor","housings","mesh","transform","origin","along","light","eye","active","slot","lit","a","distance","nearest","b","casters","worst","x","y","cast","ranked","at","c","wanted","keep","next","_","free","shadowsChanged","spec"],"mappings":"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"}