@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,305 @@
|
|
|
1
|
+
import * as t from "three";
|
|
2
|
+
import { rotate as o0, openRing as Y, distance as n0, segmentProjection as j, pointInRing as r0 } from "../model/geometry.js";
|
|
3
|
+
import { metricUVs as e0 } from "./surfaces.js";
|
|
4
|
+
import { RoundedBoxGeometry as s0 } from "three/addons/geometries/RoundedBoxGeometry.js";
|
|
5
|
+
const a0 = (i, w = 0.8) => new t.MeshStandardMaterial({ color: i, roughness: w }), c = (i, w, S, d, m, n, z, D) => {
|
|
6
|
+
const Z = w > 0.35 && S > 0.25 && d > 0.1 ? new s0(w, S, d, 1, Math.min(0.035, d * 0.12)) : new t.BoxGeometry(w, S, d);
|
|
7
|
+
e0(Z);
|
|
8
|
+
const F = new t.Mesh(Z, D);
|
|
9
|
+
return F.position.set(m, n, z + d / 2), F.castShadow = !0, F.receiveShadow = !0, i.add(F), F;
|
|
10
|
+
};
|
|
11
|
+
function H(i, w, S, d, m) {
|
|
12
|
+
const n = S.clone().sub(w);
|
|
13
|
+
if (n.length() < 1e-3) return;
|
|
14
|
+
const z = new t.Mesh(new t.CylinderGeometry(d, d, n.length(), 10), m);
|
|
15
|
+
z.position.copy(w).add(S).multiplyScalar(0.5), z.quaternion.setFromUnitVectors(new t.Vector3(0, 1, 0), n.normalize()), z.castShadow = !0, i.add(z);
|
|
16
|
+
}
|
|
17
|
+
function c0() {
|
|
18
|
+
const i = [], w = [];
|
|
19
|
+
for (let d = 0; d < 2; d++)
|
|
20
|
+
for (let m = 0; m <= 10; m++) {
|
|
21
|
+
const n = m / 10;
|
|
22
|
+
i.push((n - 0.5) * 0.305, (d - 0.5) * 0.36, 0.02 + 0.025 * Math.sin(n * Math.PI * 2) + d * 0.012);
|
|
23
|
+
}
|
|
24
|
+
for (let d = 0; d < 10; d++)
|
|
25
|
+
w.push(d, d + 1, d + 12, d, d + 12, d + 11);
|
|
26
|
+
const S = new t.BufferGeometry();
|
|
27
|
+
return S.setAttribute("position", new t.Float32BufferAttribute(i, 3)), S.setIndex(w), S.computeVertexNormals(), S;
|
|
28
|
+
}
|
|
29
|
+
function f0(i, w, S, d) {
|
|
30
|
+
const m = new t.Group();
|
|
31
|
+
m.userData.entityId = S, m.userData.roof = !0;
|
|
32
|
+
const z = i.sections.reduce((o, u) => {
|
|
33
|
+
const v = Y(u.footprint);
|
|
34
|
+
return o + Math.abs(
|
|
35
|
+
v.reduce((b, y, x) => {
|
|
36
|
+
const e = v[(x + 1) % v.length];
|
|
37
|
+
return b + y[0] * e[1] - e[0] * y[1];
|
|
38
|
+
}, 0)
|
|
39
|
+
) / 2;
|
|
40
|
+
}, 0) > 180, D = z ? d.get("roof", i.color) : new t.MeshStandardMaterial({
|
|
41
|
+
color: i.color,
|
|
42
|
+
roughness: 0.74,
|
|
43
|
+
metalness: 0.03,
|
|
44
|
+
side: t.DoubleSide
|
|
45
|
+
}), Z = d.solid("#b7b3a7"), F = d.metal("#4c5555"), r = c0();
|
|
46
|
+
function s(o, u, v) {
|
|
47
|
+
const b = w(u), y = w(v), x = w(j(u, ...o.ridge).point), e = w(j(v, ...o.ridge).point);
|
|
48
|
+
let a = [
|
|
49
|
+
new t.Vector3(...b, o.eave),
|
|
50
|
+
new t.Vector3(...y, o.eave),
|
|
51
|
+
new t.Vector3(...e, o.peak),
|
|
52
|
+
new t.Vector3(...x, o.peak)
|
|
53
|
+
];
|
|
54
|
+
if (a = a.filter((f, p) => p === 0 || f.distanceTo(a[p - 1]) > 1e-3), a.length > 2 && a.at(-1).distanceTo(a[0]) < 1e-3 && a.pop(), a.length < 3) return;
|
|
55
|
+
let l = a[1].clone().sub(a[0]).cross(a[2].clone().sub(a[0])).normalize();
|
|
56
|
+
l.z < 0 && (a.reverse(), l.negate());
|
|
57
|
+
const h = a[1].clone().sub(a[0]).normalize(), R = l.clone().cross(h).normalize(), G = a[0], A = a.map((f) => [f.clone().sub(G).dot(h), f.clone().sub(G).dot(R)]), P = a.flatMap((f) => f.toArray()), N = [];
|
|
58
|
+
for (let f = 1; f < a.length - 1; f++) N.push(0, f, f + 1);
|
|
59
|
+
const V = new t.BufferGeometry();
|
|
60
|
+
V.setAttribute("position", new t.Float32BufferAttribute(P, 3)), V.setIndex(N), V.computeVertexNormals(), V.setAttribute("uv", new t.Float32BufferAttribute(A.flat(), 2));
|
|
61
|
+
const I = new t.Mesh(V, D);
|
|
62
|
+
I.castShadow = I.receiveShadow = !0, m.add(I);
|
|
63
|
+
const k = Math.min(...A.map((f) => f[0])), C = Math.max(...A.map((f) => f[0])), J = Math.min(...A.map((f) => f[1])), T = Math.max(...A.map((f) => f[1])), U = [], L = !z && (C - k) / 0.3 * ((T - J) / 0.33) <= 1200;
|
|
64
|
+
if (z) {
|
|
65
|
+
const f = Math.max(0.6, Math.ceil((C - k) / 108) * 0.6);
|
|
66
|
+
for (let p = Math.ceil(k / f) * f; p < C; p += f) {
|
|
67
|
+
const B = [];
|
|
68
|
+
A.forEach((g, q) => {
|
|
69
|
+
const E = A[(q + 1) % A.length];
|
|
70
|
+
(g[0] <= p && E[0] > p || E[0] <= p && g[0] > p) && B.push(g[1] + (E[1] - g[1]) * (p - g[0]) / (E[0] - g[0]));
|
|
71
|
+
}), B.sort((g, q) => g - q);
|
|
72
|
+
for (let g = 0; g + 1 < B.length; g += 2) {
|
|
73
|
+
const q = (E) => G.clone().addScaledVector(h, p).addScaledVector(R, E).addScaledVector(l, 0.025);
|
|
74
|
+
H(m, q(B[g]), q(B[g + 1]), 0.018, F);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (L)
|
|
79
|
+
for (let f = J + 0.19; f < T; f += 0.33)
|
|
80
|
+
for (let p = k + 0.16; p < C; p += 0.3)
|
|
81
|
+
[
|
|
82
|
+
[-0.153, -0.18],
|
|
83
|
+
[0.153, -0.18],
|
|
84
|
+
[0.153, 0.18],
|
|
85
|
+
[-0.153, 0.18]
|
|
86
|
+
].every(([B, g]) => r0([p + B, f + g], A)) && U.push(
|
|
87
|
+
new t.Matrix4().makeBasis(h, R, l).setPosition(G.clone().addScaledVector(h, p).addScaledVector(R, f).addScaledVector(l, 0.018))
|
|
88
|
+
);
|
|
89
|
+
if (U.length) {
|
|
90
|
+
const f = new t.InstancedMesh(r, D, U.length);
|
|
91
|
+
U.forEach((p, B) => {
|
|
92
|
+
f.setMatrixAt(B, p);
|
|
93
|
+
const g = new t.Color().setScalar(0.92 + B % 11 * 0.015);
|
|
94
|
+
f.setColorAt(B, g);
|
|
95
|
+
}), f.instanceMatrix.needsUpdate = !0, f.castShadow = f.receiveShadow = !0, m.add(f);
|
|
96
|
+
}
|
|
97
|
+
if (!L && !z) return;
|
|
98
|
+
const W = new t.Vector3(...b, o.eave - 0.08), K = new t.Vector3(...y, o.eave - 0.08);
|
|
99
|
+
H(m, W, K, 0.07, Z), H(
|
|
100
|
+
m,
|
|
101
|
+
W.clone().add(new t.Vector3(0, 0, -0.12)),
|
|
102
|
+
K.clone().add(new t.Vector3(0, 0, -0.12)),
|
|
103
|
+
0.045,
|
|
104
|
+
F
|
|
105
|
+
), L && x[0] === e[0] && x[1] === e[1] && H(
|
|
106
|
+
m,
|
|
107
|
+
new t.Vector3(...x, o.peak + 0.05),
|
|
108
|
+
new t.Vector3(...b, o.eave + 0.05),
|
|
109
|
+
0.09,
|
|
110
|
+
D
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
return i.sections.forEach((o) => {
|
|
114
|
+
const u = Y(o.footprint);
|
|
115
|
+
if (Math.abs(o.peak - o.eave) < 1e-3) {
|
|
116
|
+
const b = new t.Shape(u.map((e) => new t.Vector2(...w(e)))), y = new t.ExtrudeGeometry(b, { depth: 0.14, bevelEnabled: !1 });
|
|
117
|
+
y.translate(0, 0, -0.14), e0(y);
|
|
118
|
+
const x = new t.Mesh(y, D);
|
|
119
|
+
x.position.z = o.peak, x.castShadow = x.receiveShadow = !0, m.add(x);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
u.forEach((b, y) => s(o, b, u[(y + 1) % u.length])), n0(o.ridge[0], o.ridge[1]) <= 26 && H(
|
|
123
|
+
m,
|
|
124
|
+
new t.Vector3(...w(o.ridge[0]), o.peak + 0.08),
|
|
125
|
+
new t.Vector3(...w(o.ridge[1]), o.peak + 0.08),
|
|
126
|
+
0.13,
|
|
127
|
+
D
|
|
128
|
+
);
|
|
129
|
+
}), m.traverse((o) => {
|
|
130
|
+
o instanceof t.Mesh && (o.userData.entityId = S);
|
|
131
|
+
}), m;
|
|
132
|
+
}
|
|
133
|
+
function h0(i, w, S, d, m) {
|
|
134
|
+
const n = new t.Group(), [z, D] = w(i.position), Z = o0([1, 0], i.rotation), F = w([i.position[0] + Z[0], i.position[1] + Z[1]]);
|
|
135
|
+
n.position.set(z, D, S + (i.baseHeight ?? 0)), n.rotation.z = Math.atan2(F[1] - D, F[0] - z);
|
|
136
|
+
const r = i.width, s = i.depth, o = i.height, u = i.material ? d.get(i.material, i.color ?? "#f2f3ef") : d.solid(i.color ?? "#ddd7c8", i.model === "car" ? 0.3 : 0.72), v = d.get("oak", "#bca27e"), b = d.solid("#f1eee6"), y = d.solid("#3b4240"), x = d.metal("#858e8c");
|
|
137
|
+
if (i.model === "bed") {
|
|
138
|
+
c(n, r, s, 0.25, 0, 0, 0.12, v), c(n, r - 0.05, s - 0.05, 0.22, 0, 0, 0.37, b), c(n, r - 0.1, s * 0.67, 0.06, 0, -s * 0.12, 0.59, u), c(n, r, 0.09, 0.85, 0, s / 2, 0.06, v);
|
|
139
|
+
for (const e of r > 1.3 ? [-r * 0.24, r * 0.24] : [0]) {
|
|
140
|
+
const a = c(n, r > 1.3 ? r * 0.4 : r * 0.8, 0.43, 0.12, e, s * 0.32, 0.59, b);
|
|
141
|
+
a.rotation.z = 0.02;
|
|
142
|
+
}
|
|
143
|
+
} else if (i.model === "sofa") {
|
|
144
|
+
c(n, r, s, 0.4, 0, 0, 0.1, u), c(n, r, 0.19, 0.72, 0, s * 0.4, 0.1, u);
|
|
145
|
+
for (const e of [-r * 0.45, r * 0.45]) c(n, 0.15, s, 0.65, e, 0, 0.1, u);
|
|
146
|
+
for (let e = 0; e < 3; e++)
|
|
147
|
+
c(n, (r - 0.38) / 3 - 0.025, s * 0.7, 0.15, -(r - 0.38) / 3 + e * (r - 0.38) / 3, -0.03, 0.5, u);
|
|
148
|
+
} else if (i.model === "dining") {
|
|
149
|
+
c(n, r, s, 0.065, 0, 0, o, v);
|
|
150
|
+
for (const e of [-r * 0.4, r * 0.4])
|
|
151
|
+
for (const a of [-s * 0.35, s * 0.35]) c(n, 0.065, 0.065, o, e, a, 0, y);
|
|
152
|
+
if (o > 0.6)
|
|
153
|
+
for (const e of [-r * 0.3, r * 0.3])
|
|
154
|
+
for (const a of [-1, 1]) {
|
|
155
|
+
c(n, 0.43, 0.43, 0.07, e, a * (s / 2 + 0.38), 0.44, v), c(n, 0.43, 0.055, 0.43, e, a * (s / 2 + 0.59), 0.44, v);
|
|
156
|
+
for (const l of [-0.15, 0.15]) c(n, 0.045, 0.3, 0.44, e + l, a * (s / 2 + 0.38), 0, y);
|
|
157
|
+
}
|
|
158
|
+
} else if (i.model === "cabinet" || i.model === "counter") {
|
|
159
|
+
c(n, r, s, o, 0, 0, 0, u);
|
|
160
|
+
const e = Math.max(1, Math.round(r / 0.55));
|
|
161
|
+
for (let a = 0; a < e; a++) {
|
|
162
|
+
const l = -r / 2 + (a + 0.5) * r / e;
|
|
163
|
+
c(n, r / e - 0.015, 0.025, o - 0.06, l, -s / 2 - 0.015, 0.03, u), c(n, 0.018, 0.035, 0.18, l + r / e * 0.32, -s / 2 - 0.045, o * 0.55, x);
|
|
164
|
+
}
|
|
165
|
+
i.model === "counter" && c(n, r + 0.04, s + 0.035, 0.045, 0, 0, o, d.get("tile", "#777b73"));
|
|
166
|
+
} else if (i.model === "toilet") {
|
|
167
|
+
const e = new t.Mesh(new t.SphereGeometry(0.5, 16, 12), b);
|
|
168
|
+
e.scale.set(r, s * 0.8, 0.3), e.position.z = 0.35, n.add(e), c(n, r * 0.75, 0.15, 0.63, 0, s * 0.35, 0, b), c(n, r * 0.55, s * 0.5, 0.3, 0, 0, 0, b);
|
|
169
|
+
} else if (i.model === "basin") {
|
|
170
|
+
c(n, r, s, o - 0.12, 0, 0, 0, v), c(n, r + 0.04, s + 0.04, 0.1, 0, 0, o - 0.1, b);
|
|
171
|
+
const e = new t.Mesh(new t.SphereGeometry(0.2, 16, 8), a0("#b6c3c2"));
|
|
172
|
+
e.scale.set(1, 0.8, 0.15), e.position.z = o + 5e-3, n.add(e), H(n, new t.Vector3(0, s * 0.3, o), new t.Vector3(0, s * 0.3, o + 0.2), 0.022, x);
|
|
173
|
+
} else if (i.model === "sauna") {
|
|
174
|
+
for (let e = 0; e < 8; e++) c(n, r, 0.09, 0.06, 0, -s / 2 + e * s / 8, 0.48, v);
|
|
175
|
+
for (let e = 0; e < 5; e++) c(n, r, 0.095, 0.06, 0, s / 2 - 0.5 + e * 0.1, 0.98, v);
|
|
176
|
+
c(n, 0.3, 0.3, 0.6, r / 2 - 0.25, -s / 2 + 0.2, 0, y);
|
|
177
|
+
} else if (i.model === "shower") {
|
|
178
|
+
const e = new t.MeshStandardMaterial({
|
|
179
|
+
color: "#bbdbde",
|
|
180
|
+
transparent: !0,
|
|
181
|
+
opacity: 0.22,
|
|
182
|
+
roughness: 0.15,
|
|
183
|
+
side: t.DoubleSide,
|
|
184
|
+
depthWrite: !1
|
|
185
|
+
});
|
|
186
|
+
c(n, r, 0.025, o, 0, s / 2, 0, e), c(n, 0.025, s, o, r / 2, 0, 0, e), H(
|
|
187
|
+
n,
|
|
188
|
+
new t.Vector3(-r * 0.35, s * 0.4, 0.4),
|
|
189
|
+
new t.Vector3(-r * 0.35, s * 0.4, o - 0.1),
|
|
190
|
+
0.015,
|
|
191
|
+
x
|
|
192
|
+
), c(n, 0.22, 0.18, 0.025, -r * 0.35, s * 0.25, o - 0.1, x);
|
|
193
|
+
} else if (i.model === "tree" || i.model === "shrub") {
|
|
194
|
+
i.model === "tree" && H(
|
|
195
|
+
n,
|
|
196
|
+
new t.Vector3(0, 0, 0),
|
|
197
|
+
new t.Vector3(0.12, 0, o * 0.73),
|
|
198
|
+
0.085,
|
|
199
|
+
d.get("plaster", "#dedbd0")
|
|
200
|
+
);
|
|
201
|
+
for (let e = 0; e < 9; e++) {
|
|
202
|
+
const a = d.shaded(
|
|
203
|
+
d.solid(e % 3 === 0 ? "#58764a" : e % 3 === 1 ? "#425f3b" : "#78945a", 0.95)
|
|
204
|
+
), l = new t.IcosahedronGeometry(1, 2), h = l.getAttribute("position"), R = [];
|
|
205
|
+
for (let P = 0; P < h.count; P++) {
|
|
206
|
+
const N = h.getX(P), V = h.getY(P), I = h.getZ(P), k = 1 + Math.sin(N * 12 + e) * Math.sin(V * 9 - e) * Math.sin(I * 11) * 0.14;
|
|
207
|
+
h.setXYZ(P, N * k, V * k, I * k);
|
|
208
|
+
const C = 0.66 + (I + 1) * 0.17;
|
|
209
|
+
R.push(C, C, C);
|
|
210
|
+
}
|
|
211
|
+
l.setAttribute("color", new t.Float32BufferAttribute(R, 3)), l.computeVertexNormals();
|
|
212
|
+
const G = new t.Mesh(l, a), A = e * 2.399;
|
|
213
|
+
G.position.set(
|
|
214
|
+
Math.cos(A) * r * 0.24,
|
|
215
|
+
Math.sin(A) * s * 0.24,
|
|
216
|
+
i.model === "tree" ? o * 0.64 + e % 3 * 0.35 : o * 0.45
|
|
217
|
+
), G.scale.set(r * 0.35, s * 0.35, i.model === "tree" ? o * 0.28 : o * 0.55), G.castShadow = G.receiveShadow = !0, n.add(G);
|
|
218
|
+
}
|
|
219
|
+
} else if (i.model === "lamp") {
|
|
220
|
+
if (H(n, new t.Vector3(0, 0, 0), new t.Vector3(0, 0, o), 0.035, y), c(
|
|
221
|
+
n,
|
|
222
|
+
0.18,
|
|
223
|
+
0.18,
|
|
224
|
+
0.12,
|
|
225
|
+
0,
|
|
226
|
+
0,
|
|
227
|
+
o - 0.15,
|
|
228
|
+
new t.MeshStandardMaterial({ color: "#f4dfae", emissive: "#ffcf79", emissiveIntensity: m ? 2 : 0.2 })
|
|
229
|
+
), m) {
|
|
230
|
+
const e = new t.PointLight("#ffd197", 9, 5, 2);
|
|
231
|
+
e.position.z = o, n.add(e);
|
|
232
|
+
}
|
|
233
|
+
} else if (i.model === "car") {
|
|
234
|
+
const e = new t.Group(), a = Math.max(r, s), l = Math.min(r, s), h = Math.max(1.2, o);
|
|
235
|
+
s > r && (e.rotation.z = Math.PI / 2), n.add(e);
|
|
236
|
+
const R = d.glass(m), G = d.solid("#23262a", 0.62), A = d.metal("#b3b8bc"), P = d.solid("#9c2f28", 0.42), N = h * 0.09, V = h * 0.2, I = h * 0.63, k = h * 0.73, C = h * 0.98, J = a * 0.3, T = h * 0.22, U = l * 0.12, L = a * 0.1, W = -a * 0.25, K = a * 0.02, f = -a * 0.19;
|
|
237
|
+
c(e, a - 0.3, l - 0.16, V - N, 0, 0, N, G), c(e, a - 0.5, l - 0.08, I - V, 0, 0, V, u);
|
|
238
|
+
for (const M of [-1, 1]) c(e, 0.3, l - 0.24, I - V - 0.04, M * (a / 2 - 0.14), 0, V, u);
|
|
239
|
+
for (const M of [-1, 1]) c(e, 0.34, l - 0.15, I - V - 0.02, M * (a / 2 - 0.29), 0, V, u);
|
|
240
|
+
c(e, a * 0.68, l, k - (I - 0.1), -a * 0.16, 0, I - 0.1, u);
|
|
241
|
+
for (const M of [-J, J]) c(e, T * 2.6, l + 0.05, h * 0.2, M, 0, h * 0.3, u);
|
|
242
|
+
const p = c(e, a / 2 - L, l - 0.07, h * 0.05, (a / 2 + L) / 2, 0, I - 0.03, u);
|
|
243
|
+
p.rotation.y = 0.03, c(e, a / 2 + W, l - 0.07, h * 0.05, (-a / 2 + W) / 2, 0, k - 0.02, u), c(e, K - f, l * 0.84, h * 0.05, (K + f) / 2, 0, C - h * 0.05, u);
|
|
244
|
+
for (const M of [-1, 1]) {
|
|
245
|
+
const O = c(
|
|
246
|
+
e,
|
|
247
|
+
L - W,
|
|
248
|
+
0.03,
|
|
249
|
+
C - k,
|
|
250
|
+
(L + W) / 2,
|
|
251
|
+
M * l * 0.43,
|
|
252
|
+
k,
|
|
253
|
+
R
|
|
254
|
+
);
|
|
255
|
+
O.rotation.x = M * 0.1;
|
|
256
|
+
}
|
|
257
|
+
const B = (M, O, $) => {
|
|
258
|
+
const Q = C - k, _ = M - O, X = c(
|
|
259
|
+
e,
|
|
260
|
+
0.03,
|
|
261
|
+
l * 0.76,
|
|
262
|
+
Math.hypot(Q, _),
|
|
263
|
+
(M + O) / 2,
|
|
264
|
+
0,
|
|
265
|
+
(k + C) / 2 - Math.hypot(Q, _) / 2,
|
|
266
|
+
$
|
|
267
|
+
);
|
|
268
|
+
return X.rotation.y = -Math.atan2(_, Q), X;
|
|
269
|
+
};
|
|
270
|
+
B(L, K, R), B(W, f, R);
|
|
271
|
+
for (const M of [-1, 1]) c(e, 0.16, 0.1, 0.09, L - 0.1, M * (l / 2 + 0.04), k - 0.06, G);
|
|
272
|
+
const g = new t.CylinderGeometry(T, T, U, 20), q = new t.CylinderGeometry(T * 0.62, T * 0.62, U + 0.01, 14);
|
|
273
|
+
for (const M of [-J, J])
|
|
274
|
+
for (const O of [-1, 1]) {
|
|
275
|
+
const $ = O * (l / 2 - U / 2 - 0.015), Q = new t.Mesh(g, y);
|
|
276
|
+
Q.position.set(M, $, T), e.add(Q);
|
|
277
|
+
const _ = new t.Mesh(q, A);
|
|
278
|
+
_.position.set(M, $, T), e.add(_);
|
|
279
|
+
}
|
|
280
|
+
const E = a / 2 + 0.03;
|
|
281
|
+
c(e, 0.06, l * 0.42, h * 0.13, E, 0, h * 0.37, G), c(e, 0.06, l * 0.6, h * 0.09, E - 0.01, 0, V + 0.03, G);
|
|
282
|
+
const t0 = d.solid("#cfd3d0", 0.22);
|
|
283
|
+
for (const M of [-1, 1])
|
|
284
|
+
c(e, 0.07, l * 0.18, h * 0.06, E - 0.01, M * l * 0.28, h * 0.51, t0), c(e, 0.07, l * 0.2, h * 0.07, -E + 0.01, M * l * 0.27, h * 0.58, P);
|
|
285
|
+
c(e, 0.05, l * 0.26, 0.11, -E + 0.01, 0, h * 0.25, b);
|
|
286
|
+
} else if (i.model === "vent") {
|
|
287
|
+
const e = Math.min(r, s) * 0.4, a = new t.CatmullRomCurve3([
|
|
288
|
+
new t.Vector3(0, s * 0.1, o),
|
|
289
|
+
new t.Vector3(0, -s * 0.45, o),
|
|
290
|
+
new t.Vector3(0, -s * 0.7, o - e),
|
|
291
|
+
new t.Vector3(0, -s * 0.7, o - e * 1.8)
|
|
292
|
+
]), l = new t.Mesh(new t.TubeGeometry(a, 16, e, 14, !1), d.metal("#394f48"));
|
|
293
|
+
n.add(l);
|
|
294
|
+
const h = new t.Mesh(new t.CircleGeometry(e * 0.94, 14), d.solid("#172722"));
|
|
295
|
+
h.position.set(0, -s * 0.7, o - e * 1.8), h.rotation.x = Math.PI, n.add(h);
|
|
296
|
+
} else i.model === "chimney" ? (c(n, r, s, o, 0, 0, 0, d.get("brick", i.color ?? "#c0b8a7")), c(n, r + 0.16, s + 0.16, 0.12, 0, 0, o, x)) : c(n, r, s, o, 0, 0, 0, u);
|
|
297
|
+
return n.traverse((e) => {
|
|
298
|
+
e instanceof t.Mesh && (e.userData.entityId = i.id, e.castShadow = !0, e.receiveShadow = !0);
|
|
299
|
+
}), n;
|
|
300
|
+
}
|
|
301
|
+
export {
|
|
302
|
+
h0 as makeFixture,
|
|
303
|
+
f0 as makeRoof
|
|
304
|
+
};
|
|
305
|
+
//# sourceMappingURL=architecture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"architecture.js","sources":["../../../../src/map/architecture.ts"],"sourcesContent":["import * as THREE from 'three';\nimport type { BuildingRoof, Point, RoofSection, SiteObject } from '../model/types';\nimport { distance, openRing, pointInRing, rotate, segmentProjection } from '../model/geometry';\nimport { MaterialLibrary } from './materials';\nimport { metricUVs } from './surfaces';\nimport { RoundedBoxGeometry } from 'three/addons/geometries/RoundedBoxGeometry.js';\n\ntype ProjectXY = (point: Point) => Point;\nconst standard = (color: string, roughness = 0.8) => new THREE.MeshStandardMaterial({ color, roughness });\nconst box = (\n group: 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 const geometry =\n w > 0.35 && d > 0.25 && h > 0.1\n ? new RoundedBoxGeometry(w, d, h, 1, Math.min(0.035, h * 0.12))\n : new THREE.BoxGeometry(w, d, h);\n metricUVs(geometry);\n const mesh = new THREE.Mesh(geometry, material);\n mesh.position.set(x, y, z + h / 2);\n mesh.castShadow = true;\n mesh.receiveShadow = true;\n group.add(mesh);\n return mesh;\n};\nfunction cylinder(group: THREE.Group, a: THREE.Vector3, b: THREE.Vector3, r: number, material: THREE.Material) {\n const delta = b.clone().sub(a);\n if (delta.length() < 0.001) return;\n const mesh = new THREE.Mesh(new THREE.CylinderGeometry(r, r, delta.length(), 10), material);\n mesh.position.copy(a).add(b).multiplyScalar(0.5);\n mesh.quaternion.setFromUnitVectors(new THREE.Vector3(0, 1, 0), delta.normalize());\n mesh.castShadow = true;\n group.add(mesh);\n}\n\nfunction tileGeometry() {\n const points: number[] = [],\n indices: number[] = [];\n for (let y = 0; y < 2; y++)\n for (let i = 0; i <= 10; i++) {\n const x = i / 10;\n points.push((x - 0.5) * 0.305, (y - 0.5) * 0.36, 0.02 + 0.025 * Math.sin(x * Math.PI * 2) + y * 0.012);\n }\n for (let i = 0; i < 10; i++) {\n indices.push(i, i + 1, i + 12, i, i + 12, i + 11);\n }\n const g = new THREE.BufferGeometry();\n g.setAttribute('position', new THREE.Float32BufferAttribute(points, 3));\n g.setIndex(indices);\n g.computeVertexNormals();\n return g;\n}\n\n/** Convex eaves fan into a ridge. Each plane receives actual interlocking tile geometry. */\nexport function makeRoof(\n roof: BuildingRoof,\n projectXY: ProjectXY,\n id: string,\n materials: MaterialLibrary,\n): THREE.Group {\n const group = new THREE.Group();\n group.userData.entityId = id;\n group.userData.roof = true;\n const area = roof.sections.reduce((sum, section) => {\n const ring = openRing(section.footprint);\n return (\n sum +\n Math.abs(\n ring.reduce((a, p, i) => {\n const q = ring[(i + 1) % ring.length];\n return a + p[0] * q[1] - q[0] * p[1];\n }, 0),\n ) /\n 2\n );\n }, 0);\n const sheetMetal = area > 180;\n const roofMaterial = sheetMetal\n ? materials.get('roof', roof.color)\n : new THREE.MeshStandardMaterial({\n color: roof.color,\n roughness: 0.74,\n metalness: 0.03,\n side: THREE.DoubleSide,\n });\n const trim = materials.solid('#b7b3a7'),\n gutter = materials.metal('#4c5555'),\n tiles = tileGeometry();\n function plane(section: RoofSection, a: Point, b: Point) {\n const pa = projectXY(a),\n pb = projectXY(b),\n ra = projectXY(segmentProjection(a, ...section.ridge).point),\n rb = projectXY(segmentProjection(b, ...section.ridge).point);\n let points = [\n new THREE.Vector3(...pa, section.eave),\n new THREE.Vector3(...pb, section.eave),\n new THREE.Vector3(...rb, section.peak),\n new THREE.Vector3(...ra, section.peak),\n ];\n points = points.filter((p, i) => i === 0 || p.distanceTo(points[i - 1]) > 0.001);\n if (points.length > 2 && points.at(-1)!.distanceTo(points[0]) < 0.001) points.pop();\n if (points.length < 3) return;\n let normal = points[1].clone().sub(points[0]).cross(points[2].clone().sub(points[0])).normalize();\n if (normal.z < 0) {\n points.reverse();\n normal.negate();\n }\n const u = points[1].clone().sub(points[0]).normalize(),\n v = normal.clone().cross(u).normalize(),\n base = points[0];\n const polygon = points.map(p => [p.clone().sub(base).dot(u), p.clone().sub(base).dot(v)] as Point);\n const positions = points.flatMap(p => p.toArray()),\n indices: number[] = [];\n for (let i = 1; i < points.length - 1; i++) indices.push(0, i, i + 1);\n const geometry = new THREE.BufferGeometry();\n geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));\n geometry.setIndex(indices);\n geometry.computeVertexNormals();\n geometry.setAttribute('uv', new THREE.Float32BufferAttribute(polygon.flat(), 2));\n const face = new THREE.Mesh(geometry, roofMaterial);\n face.castShadow = face.receiveShadow = true;\n group.add(face);\n const minX = Math.min(...polygon.map(p => p[0])),\n maxX = Math.max(...polygon.map(p => p[0])),\n minY = Math.min(...polygon.map(p => p[1])),\n maxY = Math.max(...polygon.map(p => p[1]));\n const matrices: THREE.Matrix4[] = [];\n // Clay tiles, fascia boards, gutters and ridge poles are all house-scale flourishes. On a large\n // roof the tile scan alone runs to hundreds of thousands of iterations — each with a point-in-ring\n // test — and emits as many instances; the trims meanwhile draw as bright seams straight across\n // what should read as one sheet. Past a modest budget the plane is left plain, which is what the\n // roof of a department store or a warehouse actually is.\n const detailed = !sheetMetal && ((maxX - minX) / 0.3) * ((maxY - minY) / 0.33) <= 1200;\n if (sheetMetal) {\n // Raised standing seams remain legible when texture mipmaps fade at city scale.\n const spacing = Math.max(0.6, Math.ceil((maxX - minX) / 108) * 0.6);\n for (let x = Math.ceil(minX / spacing) * spacing; x < maxX; x += spacing) {\n const cuts: number[] = [];\n polygon.forEach((a, i) => {\n const b = polygon[(i + 1) % polygon.length];\n if ((a[0] <= x && b[0] > x) || (b[0] <= x && a[0] > x))\n cuts.push(a[1] + ((b[1] - a[1]) * (x - a[0])) / (b[0] - a[0]));\n });\n cuts.sort((a, b) => a - b);\n for (let i = 0; i + 1 < cuts.length; i += 2) {\n const at = (y: number) =>\n base.clone().addScaledVector(u, x).addScaledVector(v, y).addScaledVector(normal, 0.025);\n cylinder(group, at(cuts[i]), at(cuts[i + 1]), 0.018, gutter);\n }\n }\n }\n if (detailed)\n for (let y = minY + 0.19; y < maxY; y += 0.33)\n for (let x = minX + 0.16; x < maxX; x += 0.3) {\n if (\n !(\n [\n [-0.153, -0.18],\n [0.153, -0.18],\n [0.153, 0.18],\n [-0.153, 0.18],\n ] as Point[]\n ).every(([dx, dy]) => pointInRing([x + dx, y + dy], polygon))\n )\n continue;\n matrices.push(\n new THREE.Matrix4()\n .makeBasis(u, v, normal)\n .setPosition(base.clone().addScaledVector(u, x).addScaledVector(v, y).addScaledVector(normal, 0.018)),\n );\n }\n if (matrices.length) {\n const batch = new THREE.InstancedMesh(tiles, roofMaterial, matrices.length);\n matrices.forEach((matrix, i) => {\n batch.setMatrixAt(i, matrix);\n const tone = new THREE.Color().setScalar(0.92 + (i % 11) * 0.015);\n batch.setColorAt(i, tone);\n });\n batch.instanceMatrix.needsUpdate = true;\n batch.castShadow = batch.receiveShadow = true;\n group.add(batch);\n }\n if (!detailed && !sheetMetal) return;\n // White fascia and rain gutter along the eave.\n const edgeA = new THREE.Vector3(...pa, section.eave - 0.08),\n edgeB = new THREE.Vector3(...pb, section.eave - 0.08);\n cylinder(group, edgeA, edgeB, 0.07, trim);\n cylinder(\n group,\n edgeA.clone().add(new THREE.Vector3(0, 0, -0.12)),\n edgeB.clone().add(new THREE.Vector3(0, 0, -0.12)),\n 0.045,\n gutter,\n );\n if (detailed && ra[0] === rb[0] && ra[1] === rb[1])\n cylinder(\n group,\n new THREE.Vector3(...ra, section.peak + 0.05),\n new THREE.Vector3(...pa, section.eave + 0.05),\n 0.09,\n roofMaterial,\n );\n }\n roof.sections.forEach(section => {\n const outline = openRing(section.footprint);\n // A section with no fall is a deck, not a pitch. Fanning it from the ridge the way a sloped plane\n // is fanned lays overlapping coplanar quads over each other, whose per-quad normals disagree just\n // enough to show as creases across what should be one flat surface. Triangulate it once instead.\n if (Math.abs(section.peak - section.eave) < 0.001) {\n const shape = new THREE.Shape(outline.map(pt => new THREE.Vector2(...projectXY(pt))));\n const geometry = new THREE.ExtrudeGeometry(shape, { depth: 0.14, bevelEnabled: false });\n geometry.translate(0, 0, -0.14);\n metricUVs(geometry);\n const deck = new THREE.Mesh(geometry, roofMaterial);\n deck.position.z = section.peak;\n deck.castShadow = deck.receiveShadow = true;\n group.add(deck);\n return;\n }\n outline.forEach((a, i) => plane(section, a, outline[(i + 1) % outline.length]));\n const ridgeLength = distance(section.ridge[0], section.ridge[1]);\n if (ridgeLength <= 26)\n cylinder(\n group,\n new THREE.Vector3(...projectXY(section.ridge[0]), section.peak + 0.08),\n new THREE.Vector3(...projectXY(section.ridge[1]), section.peak + 0.08),\n 0.13,\n roofMaterial,\n );\n });\n group.traverse(o => {\n if (o instanceof THREE.Mesh) o.userData.entityId = id;\n });\n return group;\n}\n\nexport function makeFixture(\n o: SiteObject,\n projectXY: ProjectXY,\n z: number,\n materials: MaterialLibrary,\n evening: boolean,\n): THREE.Group {\n const group = new THREE.Group(),\n [x, y] = projectXY(o.position),\n direction = rotate([1, 0], o.rotation),\n along = projectXY([o.position[0] + direction[0], o.position[1] + direction[1]]);\n group.position.set(x, y, z + (o.baseHeight ?? 0));\n group.rotation.z = Math.atan2(along[1] - y, along[0] - x);\n const w = o.width,\n d = o.depth,\n h = o.height,\n paint = o.material\n ? materials.get(o.material, o.color ?? '#f2f3ef')\n : materials.solid(o.color ?? '#ddd7c8', o.model === 'car' ? 0.3 : 0.72),\n wood = materials.get('oak', '#bca27e'),\n white = materials.solid('#f1eee6'),\n dark = materials.solid('#3b4240'),\n metal = materials.metal('#858e8c');\n if (o.model === 'bed') {\n box(group, w, d, 0.25, 0, 0, 0.12, wood);\n box(group, w - 0.05, d - 0.05, 0.22, 0, 0, 0.37, white);\n box(group, w - 0.1, d * 0.67, 0.06, 0, -d * 0.12, 0.59, paint);\n box(group, w, 0.09, 0.85, 0, d / 2, 0.06, wood);\n for (const px of w > 1.3 ? [-w * 0.24, w * 0.24] : [0]) {\n const pillow = box(group, w > 1.3 ? w * 0.4 : w * 0.8, 0.43, 0.12, px, d * 0.32, 0.59, white);\n pillow.rotation.z = 0.02;\n }\n } else if (o.model === 'sofa') {\n box(group, w, d, 0.4, 0, 0, 0.1, paint);\n box(group, w, 0.19, 0.72, 0, d * 0.4, 0.1, paint);\n for (const x of [-w * 0.45, w * 0.45]) box(group, 0.15, d, 0.65, x, 0, 0.1, paint);\n for (let i = 0; i < 3; i++)\n box(group, (w - 0.38) / 3 - 0.025, d * 0.7, 0.15, -(w - 0.38) / 3 + (i * (w - 0.38)) / 3, -0.03, 0.5, paint);\n } else if (o.model === 'dining') {\n box(group, w, d, 0.065, 0, 0, h, wood);\n for (const x of [-w * 0.4, w * 0.4])\n for (const y of [-d * 0.35, d * 0.35]) box(group, 0.065, 0.065, h, x, y, 0, dark);\n if (h > 0.6)\n for (const x of [-w * 0.3, w * 0.3])\n for (const y of [-1, 1]) {\n box(group, 0.43, 0.43, 0.07, x, y * (d / 2 + 0.38), 0.44, wood);\n box(group, 0.43, 0.055, 0.43, x, y * (d / 2 + 0.59), 0.44, wood);\n for (const dx of [-0.15, 0.15]) box(group, 0.045, 0.3, 0.44, x + dx, y * (d / 2 + 0.38), 0, dark);\n }\n } else if (o.model === 'cabinet' || o.model === 'counter') {\n box(group, w, d, h, 0, 0, 0, paint);\n const panels = Math.max(1, Math.round(w / 0.55));\n for (let i = 0; i < panels; i++) {\n const x = -w / 2 + ((i + 0.5) * w) / panels;\n box(group, w / panels - 0.015, 0.025, h - 0.06, x, -d / 2 - 0.015, 0.03, paint);\n box(group, 0.018, 0.035, 0.18, x + (w / panels) * 0.32, -d / 2 - 0.045, h * 0.55, metal);\n }\n if (o.model === 'counter') box(group, w + 0.04, d + 0.035, 0.045, 0, 0, h, materials.get('tile', '#777b73'));\n } else if (o.model === 'toilet') {\n const bowl = new THREE.Mesh(new THREE.SphereGeometry(0.5, 16, 12), white);\n bowl.scale.set(w, d * 0.8, 0.3);\n bowl.position.z = 0.35;\n group.add(bowl);\n box(group, w * 0.75, 0.15, 0.63, 0, d * 0.35, 0, white);\n box(group, w * 0.55, d * 0.5, 0.3, 0, 0, 0, white);\n } else if (o.model === 'basin') {\n box(group, w, d, h - 0.12, 0, 0, 0, wood);\n box(group, w + 0.04, d + 0.04, 0.1, 0, 0, h - 0.1, white);\n const bowl = new THREE.Mesh(new THREE.SphereGeometry(0.2, 16, 8), standard('#b6c3c2'));\n bowl.scale.set(1, 0.8, 0.15);\n bowl.position.z = h + 0.005;\n group.add(bowl);\n cylinder(group, new THREE.Vector3(0, d * 0.3, h), new THREE.Vector3(0, d * 0.3, h + 0.2), 0.022, metal);\n } else if (o.model === 'sauna') {\n for (let i = 0; i < 8; i++) box(group, w, 0.09, 0.06, 0, -d / 2 + (i * d) / 8, 0.48, wood);\n for (let i = 0; i < 5; i++) box(group, w, 0.095, 0.06, 0, d / 2 - 0.5 + i * 0.1, 0.98, wood);\n box(group, 0.3, 0.3, 0.6, w / 2 - 0.25, -d / 2 + 0.2, 0, dark);\n } else if (o.model === 'shower') {\n const glass = new THREE.MeshStandardMaterial({\n color: '#bbdbde',\n transparent: true,\n opacity: 0.22,\n roughness: 0.15,\n side: THREE.DoubleSide,\n depthWrite: false,\n });\n box(group, w, 0.025, h, 0, d / 2, 0, glass);\n box(group, 0.025, d, h, w / 2, 0, 0, glass);\n cylinder(\n group,\n new THREE.Vector3(-w * 0.35, d * 0.4, 0.4),\n new THREE.Vector3(-w * 0.35, d * 0.4, h - 0.1),\n 0.015,\n metal,\n );\n box(group, 0.22, 0.18, 0.025, -w * 0.35, d * 0.25, h - 0.1, metal);\n } else if (o.model === 'tree' || o.model === 'shrub') {\n if (o.model === 'tree')\n cylinder(\n group,\n new THREE.Vector3(0, 0, 0),\n new THREE.Vector3(0.12, 0, h * 0.73),\n 0.085,\n materials.get('plaster', '#dedbd0'),\n );\n for (let i = 0; i < 9; i++) {\n const leaf = materials.shaded(\n materials.solid(i % 3 === 0 ? '#58764a' : i % 3 === 1 ? '#425f3b' : '#78945a', 0.95),\n );\n const geometry = new THREE.IcosahedronGeometry(1, 2);\n const vertices = geometry.getAttribute('position');\n const shades: number[] = [];\n for (let j = 0; j < vertices.count; j++) {\n const x = vertices.getX(j),\n y = vertices.getY(j),\n z = vertices.getZ(j);\n const r = 1 + Math.sin(x * 12 + i) * Math.sin(y * 9 - i) * Math.sin(z * 11) * 0.14;\n vertices.setXYZ(j, x * r, y * r, z * r);\n const shade = 0.66 + (z + 1) * 0.17;\n shades.push(shade, shade, shade);\n }\n geometry.setAttribute('color', new THREE.Float32BufferAttribute(shades, 3));\n geometry.computeVertexNormals();\n const mesh = new THREE.Mesh(geometry, leaf);\n const t = i * 2.399;\n mesh.position.set(\n Math.cos(t) * w * 0.24,\n Math.sin(t) * d * 0.24,\n o.model === 'tree' ? h * 0.64 + (i % 3) * 0.35 : h * 0.45,\n );\n mesh.scale.set(w * 0.35, d * 0.35, o.model === 'tree' ? h * 0.28 : h * 0.55);\n mesh.castShadow = mesh.receiveShadow = true;\n group.add(mesh);\n }\n } else if (o.model === 'lamp') {\n cylinder(group, new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, 0, h), 0.035, dark);\n box(\n group,\n 0.18,\n 0.18,\n 0.12,\n 0,\n 0,\n h - 0.15,\n new THREE.MeshStandardMaterial({ color: '#f4dfae', emissive: '#ffcf79', emissiveIntensity: evening ? 2 : 0.2 }),\n );\n if (evening) {\n const light = new THREE.PointLight('#ffd197', 9, 5, 2);\n light.position.z = h;\n group.add(light);\n }\n } else if (o.model === 'car') {\n // A car is built along its long axis whichever of width and depth the author made the long one:\n // the garage draws its cars 4.5 wide and 1.85 deep, pointing down the bay. Local X is the\n // length from here on, +X the nose.\n //\n // The proportions are a European saloon's, which is what a Helsinki car park is full of: a long\n // bonnet, a short deck, and the glasshouse set well back over the rear axle. That set-back is\n // most of what makes a car read as a car rather than as a box with a smaller box on it — get it\n // wrong and you have drawn a van.\n const car = new THREE.Group();\n const L = Math.max(w, d),\n W = Math.min(w, d),\n H = Math.max(1.2, h);\n if (d > w) car.rotation.z = Math.PI / 2;\n group.add(car);\n const glass = materials.glass(evening);\n const trim = materials.solid('#23262a', 0.62); // grille, sills, the shadow under the car\n const chrome = materials.metal('#b3b8bc');\n const tail = materials.solid('#9c2f28', 0.42);\n // Heights, as fractions of the authored height so an odd one still builds a car.\n const clear = H * 0.09, // the air under the sills\n sill = H * 0.2, // where the painted flank starts\n bonnet = H * 0.63, // the nose: a saloon's bonnet sits well below its door tops\n belt = H * 0.73, // the shoulder: top of the doors, bottom of the glass\n roof = H * 0.98;\n // A 2.7 m wheelbase in a 4.5 m car — short overhangs, which is the other half of the look.\n const axle = L * 0.3,\n tyreR = H * 0.22,\n tyreW = W * 0.12;\n // The glasshouse, set back: the windscreen base sits just behind the front axle.\n const screenFoot = L * 0.1,\n backFoot = -L * 0.25,\n screenTop = L * 0.02,\n backTop = -L * 0.19;\n box(car, L - 0.3, W - 0.16, sill - clear, 0, 0, clear, trim);\n // The flank in bands. The whole length rises only to bonnet height; the shoulder — the top of\n // the doors — is a second band over the rear two thirds. That step is the saloon profile, and\n // it is what one full-length block gets wrong: carry the beltline forward over the wings and\n // you have drawn a van, whatever you then put on the roof.\n box(car, L - 0.5, W - 0.08, bonnet - sill, 0, 0, sill, paint);\n // The last hand's width at each end is drawn in, so the car does not end in a flat wall.\n for (const end of [-1, 1]) box(car, 0.3, W - 0.24, bonnet - sill - 0.04, end * (L / 2 - 0.14), 0, sill, paint);\n for (const end of [-1, 1]) box(car, 0.34, W - 0.15, bonnet - sill - 0.02, end * (L / 2 - 0.29), 0, sill, paint);\n box(car, L * 0.68, W, belt - (bonnet - 0.1), -L * 0.16, 0, bonnet - 0.1, paint);\n // Blistered arches over each axle, so the wheels stand in something.\n for (const x of [-axle, axle]) box(car, tyreR * 2.6, W + 0.05, H * 0.2, x, 0, H * 0.3, paint);\n // The bonnet, dropping a little toward the nose, and the boot lid a touch above the shoulder.\n const lid = box(car, L / 2 - screenFoot, W - 0.07, H * 0.05, (L / 2 + screenFoot) / 2, 0, bonnet - 0.03, paint);\n lid.rotation.y = 0.03;\n box(car, L / 2 + backFoot, W - 0.07, H * 0.05, (-L / 2 + backFoot) / 2, 0, belt - 0.02, paint);\n // Roof, narrower than the shoulder: a greenhouse that tapers is what stops the cabin reading as\n // a crate. The screens rake off it at each end.\n box(car, screenTop - backTop, W * 0.84, H * 0.05, (screenTop + backTop) / 2, 0, roof - H * 0.05, paint);\n for (const side of [-1, 1]) {\n const pane = box(\n car,\n screenFoot - backFoot,\n 0.03,\n roof - belt,\n (screenFoot + backFoot) / 2,\n side * W * 0.43,\n belt,\n glass,\n );\n pane.rotation.x = side * 0.1; // tumblehome: the glass leans in at the top\n }\n const rake = (foot: number, top: number, material: THREE.Material) => {\n const rise = roof - belt,\n run = foot - top;\n const pane = box(\n car,\n 0.03,\n W * 0.76,\n Math.hypot(rise, run),\n (foot + top) / 2,\n 0,\n (belt + roof) / 2 - Math.hypot(rise, run) / 2,\n material,\n );\n // A windscreen leans BACK: its top is rearward of its foot, which for a +X nose is a negative\n // rotation about the width axis. The rear screen leans the other way by the same rule.\n pane.rotation.y = -Math.atan2(run, rise);\n return pane;\n };\n rake(screenFoot, screenTop, glass);\n rake(backFoot, backTop, glass);\n // Mirrors on the A-pillar, which is most of what a car's plan silhouette is.\n for (const side of [-1, 1]) box(car, 0.16, 0.1, 0.09, screenFoot - 0.1, side * (W / 2 + 0.04), belt - 0.06, trim);\n // Wheels: the axle runs across the car, so a cylinder's own Y axis is already the right way up.\n const tyre = new THREE.CylinderGeometry(tyreR, tyreR, tyreW, 20),\n rim = new THREE.CylinderGeometry(tyreR * 0.62, tyreR * 0.62, tyreW + 0.01, 14);\n for (const x of [-axle, axle])\n for (const y of [-1, 1]) {\n const at = y * (W / 2 - tyreW / 2 - 0.015);\n const wheel = new THREE.Mesh(tyre, dark);\n wheel.position.set(x, at, tyreR);\n car.add(wheel);\n const cap = new THREE.Mesh(rim, chrome);\n cap.position.set(x, at, tyreR);\n car.add(cap);\n }\n // The face: a grille between the headlamps, an intake under it, and lamps that wrap a little\n // way down the wing. Nothing here is fine detail — at eye level in a bay it is all you see.\n // Proud of the chamfer, or the drawn-in nose swallows every one of them.\n const nose = L / 2 + 0.03;\n box(car, 0.06, W * 0.42, H * 0.13, nose, 0, H * 0.37, trim);\n box(car, 0.06, W * 0.6, H * 0.09, nose - 0.01, 0, sill + 0.03, trim);\n const lens = materials.solid('#cfd3d0', 0.22);\n for (const y of [-1, 1]) {\n box(car, 0.07, W * 0.18, H * 0.06, nose - 0.01, y * W * 0.28, H * 0.51, lens);\n box(car, 0.07, W * 0.2, H * 0.07, -nose + 0.01, y * W * 0.27, H * 0.58, tail);\n }\n box(car, 0.05, W * 0.26, 0.11, -nose + 0.01, 0, H * 0.25, white);\n } else if (o.model === 'vent') {\n const radius = Math.min(w, d) * 0.4;\n const pipe = new THREE.CatmullRomCurve3([\n new THREE.Vector3(0, d * 0.1, h),\n new THREE.Vector3(0, -d * 0.45, h),\n new THREE.Vector3(0, -d * 0.7, h - radius),\n new THREE.Vector3(0, -d * 0.7, h - radius * 1.8),\n ]);\n const duct = new THREE.Mesh(new THREE.TubeGeometry(pipe, 16, radius, 14, false), materials.metal('#394f48'));\n group.add(duct);\n const mouth = new THREE.Mesh(new THREE.CircleGeometry(radius * 0.94, 14), materials.solid('#172722'));\n mouth.position.set(0, -d * 0.7, h - radius * 1.8);\n mouth.rotation.x = Math.PI;\n group.add(mouth);\n } else if (o.model === 'chimney') {\n box(group, w, d, h, 0, 0, 0, materials.get('brick', o.color ?? '#c0b8a7'));\n box(group, w + 0.16, d + 0.16, 0.12, 0, 0, h, metal);\n } else box(group, w, d, h, 0, 0, 0, paint);\n group.traverse(child => {\n if (child instanceof THREE.Mesh) {\n child.userData.entityId = o.id;\n child.castShadow = true;\n child.receiveShadow = true;\n }\n });\n return group;\n}\n"],"names":["standard","color","roughness","THREE","box","group","d","h","x","y","material","geometry","RoundedBoxGeometry","metricUVs","mesh","cylinder","a","b","r","delta","tileGeometry","points","indices","i","g","makeRoof","roof","projectXY","id","materials","sheetMetal","sum","section","ring","openRing","p","q","roofMaterial","trim","gutter","tiles","plane","pa","pb","ra","segmentProjection","rb","normal","u","v","base","polygon","positions","face","minX","maxX","minY","maxY","matrices","detailed","spacing","cuts","at","dx","dy","pointInRing","batch","matrix","tone","edgeA","edgeB","outline","shape","pt","deck","distance","makeFixture","o","z","evening","direction","rotate","along","w","paint","wood","white","dark","metal","px","pillow","panels","bowl","glass","leaf","vertices","shades","j","shade","t","light","car","L","W","H","chrome","tail","clear","sill","bonnet","belt","axle","tyreR","tyreW","screenFoot","backFoot","screenTop","backTop","end","lid","side","pane","rake","foot","top","rise","run","tyre","rim","wheel","cap","nose","lens","radius","pipe","duct","mouth","child"],"mappings":";;;;AAQA,MAAMA,KAAW,CAACC,GAAeC,IAAY,QAAQ,IAAIC,EAAM,qBAAqB,EAAE,OAAAF,GAAO,WAAAC,GAAW,GAClGE,IAAM,CACVC,GACA,GACAC,GACAC,GACAC,GACAC,GACA,GACAC,MACG;AACH,QAAMC,IACJ,IAAI,QAAQL,IAAI,QAAQC,IAAI,MACxB,IAAIK,GAAmB,GAAGN,GAAGC,GAAG,GAAG,KAAK,IAAI,OAAOA,IAAI,IAAI,CAAC,IAC5D,IAAIJ,EAAM,YAAY,GAAGG,GAAGC,CAAC;AACnC,EAAAM,GAAUF,CAAQ;AAClB,QAAMG,IAAO,IAAIX,EAAM,KAAKQ,GAAUD,CAAQ;AAC9C,SAAAI,EAAK,SAAS,IAAIN,GAAGC,GAAG,IAAIF,IAAI,CAAC,GACjCO,EAAK,aAAa,IAClBA,EAAK,gBAAgB,IACrBT,EAAM,IAAIS,CAAI,GACPA;AACT;AACA,SAASC,EAASV,GAAoBW,GAAkBC,GAAkBC,GAAWR,GAA0B;AAC7G,QAAMS,IAAQF,EAAE,MAAA,EAAQ,IAAID,CAAC;AAC7B,MAAIG,EAAM,OAAA,IAAW,KAAO;AAC5B,QAAML,IAAO,IAAIX,EAAM,KAAK,IAAIA,EAAM,iBAAiBe,GAAGA,GAAGC,EAAM,OAAA,GAAU,EAAE,GAAGT,CAAQ;AAC1F,EAAAI,EAAK,SAAS,KAAKE,CAAC,EAAE,IAAIC,CAAC,EAAE,eAAe,GAAG,GAC/CH,EAAK,WAAW,mBAAmB,IAAIX,EAAM,QAAQ,GAAG,GAAG,CAAC,GAAGgB,EAAM,UAAA,CAAW,GAChFL,EAAK,aAAa,IAClBT,EAAM,IAAIS,CAAI;AAChB;AAEA,SAASM,KAAe;AACtB,QAAMC,IAAmB,IACvBC,IAAoB,CAAA;AACtB,WAASb,IAAI,GAAGA,IAAI,GAAGA;AACrB,aAASc,IAAI,GAAGA,KAAK,IAAIA,KAAK;AAC5B,YAAMf,IAAIe,IAAI;AACd,MAAAF,EAAO,MAAMb,IAAI,OAAO,QAAQC,IAAI,OAAO,MAAM,OAAO,QAAQ,KAAK,IAAID,IAAI,KAAK,KAAK,CAAC,IAAIC,IAAI,KAAK;AAAA,IACvG;AACF,WAASc,IAAI,GAAGA,IAAI,IAAIA;AACtB,IAAAD,EAAQ,KAAKC,GAAGA,IAAI,GAAGA,IAAI,IAAIA,GAAGA,IAAI,IAAIA,IAAI,EAAE;AAElD,QAAMC,IAAI,IAAIrB,EAAM,eAAA;AACpB,SAAAqB,EAAE,aAAa,YAAY,IAAIrB,EAAM,uBAAuBkB,GAAQ,CAAC,CAAC,GACtEG,EAAE,SAASF,CAAO,GAClBE,EAAE,qBAAA,GACKA;AACT;AAGO,SAASC,GACdC,GACAC,GACAC,GACAC,GACa;AACb,QAAMxB,IAAQ,IAAIF,EAAM,MAAA;AACxB,EAAAE,EAAM,SAAS,WAAWuB,GAC1BvB,EAAM,SAAS,OAAO;AActB,QAAMyB,IAbOJ,EAAK,SAAS,OAAO,CAACK,GAAKC,MAAY;AAClD,UAAMC,IAAOC,EAASF,EAAQ,SAAS;AACvC,WACED,IACA,KAAK;AAAA,MACHE,EAAK,OAAO,CAACjB,GAAGmB,GAAGZ,MAAM;AACvB,cAAMa,IAAIH,GAAMV,IAAI,KAAKU,EAAK,MAAM;AACpC,eAAOjB,IAAImB,EAAE,CAAC,IAAIC,EAAE,CAAC,IAAIA,EAAE,CAAC,IAAID,EAAE,CAAC;AAAA,MACrC,GAAG,CAAC;AAAA,IAAA,IAEJ;AAAA,EAEN,GAAG,CAAC,IACsB,KACpBE,IAAeP,IACjBD,EAAU,IAAI,QAAQH,EAAK,KAAK,IAChC,IAAIvB,EAAM,qBAAqB;AAAA,IAC7B,OAAOuB,EAAK;AAAA,IACZ,WAAW;AAAA,IACX,WAAW;AAAA,IACX,MAAMvB,EAAM;AAAA,EAAA,CACb,GACCmC,IAAOT,EAAU,MAAM,SAAS,GACpCU,IAASV,EAAU,MAAM,SAAS,GAClCW,IAAQpB,GAAA;AACV,WAASqB,EAAMT,GAAsBhB,GAAUC,GAAU;AACvD,UAAMyB,IAAKf,EAAUX,CAAC,GACpB2B,IAAKhB,EAAUV,CAAC,GAChB2B,IAAKjB,EAAUkB,EAAkB7B,GAAG,GAAGgB,EAAQ,KAAK,EAAE,KAAK,GAC3Dc,IAAKnB,EAAUkB,EAAkB5B,GAAG,GAAGe,EAAQ,KAAK,EAAE,KAAK;AAC7D,QAAIX,IAAS;AAAA,MACX,IAAIlB,EAAM,QAAQ,GAAGuC,GAAIV,EAAQ,IAAI;AAAA,MACrC,IAAI7B,EAAM,QAAQ,GAAGwC,GAAIX,EAAQ,IAAI;AAAA,MACrC,IAAI7B,EAAM,QAAQ,GAAG2C,GAAId,EAAQ,IAAI;AAAA,MACrC,IAAI7B,EAAM,QAAQ,GAAGyC,GAAIZ,EAAQ,IAAI;AAAA,IAAA;AAIvC,QAFAX,IAASA,EAAO,OAAO,CAACc,GAAGZ,MAAMA,MAAM,KAAKY,EAAE,WAAWd,EAAOE,IAAI,CAAC,CAAC,IAAI,IAAK,GAC3EF,EAAO,SAAS,KAAKA,EAAO,GAAG,EAAE,EAAG,WAAWA,EAAO,CAAC,CAAC,IAAI,UAAc,IAAA,GAC1EA,EAAO,SAAS,EAAG;AACvB,QAAI0B,IAAS1B,EAAO,CAAC,EAAE,QAAQ,IAAIA,EAAO,CAAC,CAAC,EAAE,MAAMA,EAAO,CAAC,EAAE,QAAQ,IAAIA,EAAO,CAAC,CAAC,CAAC,EAAE,UAAA;AACtF,IAAI0B,EAAO,IAAI,MACb1B,EAAO,QAAA,GACP0B,EAAO,OAAA;AAET,UAAMC,IAAI3B,EAAO,CAAC,EAAE,QAAQ,IAAIA,EAAO,CAAC,CAAC,EAAE,UAAA,GACzC4B,IAAIF,EAAO,MAAA,EAAQ,MAAMC,CAAC,EAAE,aAC5BE,IAAO7B,EAAO,CAAC,GACX8B,IAAU9B,EAAO,IAAI,CAAAc,MAAK,CAACA,EAAE,QAAQ,IAAIe,CAAI,EAAE,IAAIF,CAAC,GAAGb,EAAE,MAAA,EAAQ,IAAIe,CAAI,EAAE,IAAID,CAAC,CAAC,CAAU,GAC3FG,IAAY/B,EAAO,QAAQ,CAAAc,MAAKA,EAAE,QAAA,CAAS,GAC/Cb,IAAoB,CAAA;AACtB,aAASC,IAAI,GAAGA,IAAIF,EAAO,SAAS,GAAGE,IAAK,CAAAD,EAAQ,KAAK,GAAGC,GAAGA,IAAI,CAAC;AACpE,UAAMZ,IAAW,IAAIR,EAAM,eAAA;AAC3B,IAAAQ,EAAS,aAAa,YAAY,IAAIR,EAAM,uBAAuBiD,GAAW,CAAC,CAAC,GAChFzC,EAAS,SAASW,CAAO,GACzBX,EAAS,qBAAA,GACTA,EAAS,aAAa,MAAM,IAAIR,EAAM,uBAAuBgD,EAAQ,QAAQ,CAAC,CAAC;AAC/E,UAAME,IAAO,IAAIlD,EAAM,KAAKQ,GAAU0B,CAAY;AAClD,IAAAgB,EAAK,aAAaA,EAAK,gBAAgB,IACvChD,EAAM,IAAIgD,CAAI;AACd,UAAMC,IAAO,KAAK,IAAI,GAAGH,EAAQ,IAAI,CAAAhB,MAAKA,EAAE,CAAC,CAAC,CAAC,GAC7CoB,IAAO,KAAK,IAAI,GAAGJ,EAAQ,IAAI,CAAAhB,MAAKA,EAAE,CAAC,CAAC,CAAC,GACzCqB,IAAO,KAAK,IAAI,GAAGL,EAAQ,IAAI,CAAAhB,MAAKA,EAAE,CAAC,CAAC,CAAC,GACzCsB,IAAO,KAAK,IAAI,GAAGN,EAAQ,IAAI,CAAAhB,MAAKA,EAAE,CAAC,CAAC,CAAC,GACrCuB,IAA4B,CAAA,GAM5BC,IAAW,CAAC7B,MAAgByB,IAAOD,KAAQ,QAASG,IAAOD,KAAQ,SAAS;AAClF,QAAI1B,GAAY;AAEd,YAAM8B,IAAU,KAAK,IAAI,KAAK,KAAK,MAAML,IAAOD,KAAQ,GAAG,IAAI,GAAG;AAClE,eAAS9C,IAAI,KAAK,KAAK8C,IAAOM,CAAO,IAAIA,GAASpD,IAAI+C,GAAM/C,KAAKoD,GAAS;AACxE,cAAMC,IAAiB,CAAA;AACvB,QAAAV,EAAQ,QAAQ,CAACnC,GAAGO,MAAM;AACxB,gBAAMN,IAAIkC,GAAS5B,IAAI,KAAK4B,EAAQ,MAAM;AAC1C,WAAKnC,EAAE,CAAC,KAAKR,KAAKS,EAAE,CAAC,IAAIT,KAAOS,EAAE,CAAC,KAAKT,KAAKQ,EAAE,CAAC,IAAIR,MAClDqD,EAAK,KAAK7C,EAAE,CAAC,KAAMC,EAAE,CAAC,IAAID,EAAE,CAAC,MAAMR,IAAIQ,EAAE,CAAC,MAAOC,EAAE,CAAC,IAAID,EAAE,CAAC,EAAE;AAAA,QACjE,CAAC,GACD6C,EAAK,KAAK,CAAC7C,GAAGC,MAAMD,IAAIC,CAAC;AACzB,iBAASM,IAAI,GAAGA,IAAI,IAAIsC,EAAK,QAAQtC,KAAK,GAAG;AAC3C,gBAAMuC,IAAK,CAACrD,MACVyC,EAAK,MAAA,EAAQ,gBAAgBF,GAAGxC,CAAC,EAAE,gBAAgByC,GAAGxC,CAAC,EAAE,gBAAgBsC,GAAQ,KAAK;AACxF,UAAAhC,EAASV,GAAOyD,EAAGD,EAAKtC,CAAC,CAAC,GAAGuC,EAAGD,EAAKtC,IAAI,CAAC,CAAC,GAAG,OAAOgB,CAAM;AAAA,QAC7D;AAAA,MACF;AAAA,IACF;AACA,QAAIoB;AACF,eAASlD,IAAI+C,IAAO,MAAM/C,IAAIgD,GAAMhD,KAAK;AACvC,iBAASD,IAAI8C,IAAO,MAAM9C,IAAI+C,GAAM/C,KAAK;AACvC,UAEI;AAAA,YACE,CAAC,QAAQ,KAAK;AAAA,YACd,CAAC,OAAO,KAAK;AAAA,YACb,CAAC,OAAO,IAAI;AAAA,YACZ,CAAC,QAAQ,IAAI;AAAA,UAAA,EAEf,MAAM,CAAC,CAACuD,GAAIC,CAAE,MAAMC,GAAY,CAACzD,IAAIuD,GAAItD,IAAIuD,CAAE,GAAGb,CAAO,CAAC,KAG9DO,EAAS;AAAA,YACP,IAAIvD,EAAM,QAAA,EACP,UAAU6C,GAAGC,GAAGF,CAAM,EACtB,YAAYG,EAAK,MAAA,EAAQ,gBAAgBF,GAAGxC,CAAC,EAAE,gBAAgByC,GAAGxC,CAAC,EAAE,gBAAgBsC,GAAQ,KAAK,CAAC;AAAA,UAAA;AAG9G,QAAIW,EAAS,QAAQ;AACnB,YAAMQ,IAAQ,IAAI/D,EAAM,cAAcqC,GAAOH,GAAcqB,EAAS,MAAM;AAC1E,MAAAA,EAAS,QAAQ,CAACS,GAAQ5C,MAAM;AAC9B,QAAA2C,EAAM,YAAY3C,GAAG4C,CAAM;AAC3B,cAAMC,IAAO,IAAIjE,EAAM,MAAA,EAAQ,UAAU,OAAQoB,IAAI,KAAM,KAAK;AAChE,QAAA2C,EAAM,WAAW3C,GAAG6C,CAAI;AAAA,MAC1B,CAAC,GACDF,EAAM,eAAe,cAAc,IACnCA,EAAM,aAAaA,EAAM,gBAAgB,IACzC7D,EAAM,IAAI6D,CAAK;AAAA,IACjB;AACA,QAAI,CAACP,KAAY,CAAC7B,EAAY;AAE9B,UAAMuC,IAAQ,IAAIlE,EAAM,QAAQ,GAAGuC,GAAIV,EAAQ,OAAO,IAAI,GACxDsC,IAAQ,IAAInE,EAAM,QAAQ,GAAGwC,GAAIX,EAAQ,OAAO,IAAI;AACtD,IAAAjB,EAASV,GAAOgE,GAAOC,GAAO,MAAMhC,CAAI,GACxCvB;AAAA,MACEV;AAAA,MACAgE,EAAM,QAAQ,IAAI,IAAIlE,EAAM,QAAQ,GAAG,GAAG,KAAK,CAAC;AAAA,MAChDmE,EAAM,QAAQ,IAAI,IAAInE,EAAM,QAAQ,GAAG,GAAG,KAAK,CAAC;AAAA,MAChD;AAAA,MACAoC;AAAA,IAAA,GAEEoB,KAAYf,EAAG,CAAC,MAAME,EAAG,CAAC,KAAKF,EAAG,CAAC,MAAME,EAAG,CAAC,KAC/C/B;AAAA,MACEV;AAAA,MACA,IAAIF,EAAM,QAAQ,GAAGyC,GAAIZ,EAAQ,OAAO,IAAI;AAAA,MAC5C,IAAI7B,EAAM,QAAQ,GAAGuC,GAAIV,EAAQ,OAAO,IAAI;AAAA,MAC5C;AAAA,MACAK;AAAA,IAAA;AAAA,EAEN;AACA,SAAAX,EAAK,SAAS,QAAQ,CAAAM,MAAW;AAC/B,UAAMuC,IAAUrC,EAASF,EAAQ,SAAS;AAI1C,QAAI,KAAK,IAAIA,EAAQ,OAAOA,EAAQ,IAAI,IAAI,MAAO;AACjD,YAAMwC,IAAQ,IAAIrE,EAAM,MAAMoE,EAAQ,IAAI,CAAAE,MAAM,IAAItE,EAAM,QAAQ,GAAGwB,EAAU8C,CAAE,CAAC,CAAC,CAAC,GAC9E9D,IAAW,IAAIR,EAAM,gBAAgBqE,GAAO,EAAE,OAAO,MAAM,cAAc,IAAO;AACtF,MAAA7D,EAAS,UAAU,GAAG,GAAG,KAAK,GAC9BE,GAAUF,CAAQ;AAClB,YAAM+D,IAAO,IAAIvE,EAAM,KAAKQ,GAAU0B,CAAY;AAClD,MAAAqC,EAAK,SAAS,IAAI1C,EAAQ,MAC1B0C,EAAK,aAAaA,EAAK,gBAAgB,IACvCrE,EAAM,IAAIqE,CAAI;AACd;AAAA,IACF;AACA,IAAAH,EAAQ,QAAQ,CAACvD,GAAGO,MAAMkB,EAAMT,GAAShB,GAAGuD,GAAShD,IAAI,KAAKgD,EAAQ,MAAM,CAAC,CAAC,GAC1DI,GAAS3C,EAAQ,MAAM,CAAC,GAAGA,EAAQ,MAAM,CAAC,CAAC,KAC5C,MACjBjB;AAAA,MACEV;AAAA,MACA,IAAIF,EAAM,QAAQ,GAAGwB,EAAUK,EAAQ,MAAM,CAAC,CAAC,GAAGA,EAAQ,OAAO,IAAI;AAAA,MACrE,IAAI7B,EAAM,QAAQ,GAAGwB,EAAUK,EAAQ,MAAM,CAAC,CAAC,GAAGA,EAAQ,OAAO,IAAI;AAAA,MACrE;AAAA,MACAK;AAAA,IAAA;AAAA,EAEN,CAAC,GACDhC,EAAM,SAAS,CAAA,MAAK;AAClB,IAAI,aAAaF,EAAM,SAAM,EAAE,SAAS,WAAWyB;AAAA,EACrD,CAAC,GACMvB;AACT;AAEO,SAASuE,GACdC,GACAlD,GACAmD,GACAjD,GACAkD,GACa;AACb,QAAM1E,IAAQ,IAAIF,EAAM,MAAA,GACtB,CAACK,GAAGC,CAAC,IAAIkB,EAAUkD,EAAE,QAAQ,GAC7BG,IAAYC,GAAO,CAAC,GAAG,CAAC,GAAGJ,EAAE,QAAQ,GACrCK,IAAQvD,EAAU,CAACkD,EAAE,SAAS,CAAC,IAAIG,EAAU,CAAC,GAAGH,EAAE,SAAS,CAAC,IAAIG,EAAU,CAAC,CAAC,CAAC;AAChF,EAAA3E,EAAM,SAAS,IAAIG,GAAGC,GAAGqE,KAAKD,EAAE,cAAc,EAAE,GAChDxE,EAAM,SAAS,IAAI,KAAK,MAAM6E,EAAM,CAAC,IAAIzE,GAAGyE,EAAM,CAAC,IAAI1E,CAAC;AACxD,QAAM2E,IAAIN,EAAE,OACVvE,IAAIuE,EAAE,OACNtE,IAAIsE,EAAE,QACNO,IAAQP,EAAE,WACNhD,EAAU,IAAIgD,EAAE,UAAUA,EAAE,SAAS,SAAS,IAC9ChD,EAAU,MAAMgD,EAAE,SAAS,WAAWA,EAAE,UAAU,QAAQ,MAAM,IAAI,GACxEQ,IAAOxD,EAAU,IAAI,OAAO,SAAS,GACrCyD,IAAQzD,EAAU,MAAM,SAAS,GACjC0D,IAAO1D,EAAU,MAAM,SAAS,GAChC2D,IAAQ3D,EAAU,MAAM,SAAS;AACnC,MAAIgD,EAAE,UAAU,OAAO;AACrB,IAAAzE,EAAIC,GAAO8E,GAAG7E,GAAG,MAAM,GAAG,GAAG,MAAM+E,CAAI,GACvCjF,EAAIC,GAAO8E,IAAI,MAAM7E,IAAI,MAAM,MAAM,GAAG,GAAG,MAAMgF,CAAK,GACtDlF,EAAIC,GAAO8E,IAAI,KAAK7E,IAAI,MAAM,MAAM,GAAG,CAACA,IAAI,MAAM,MAAM8E,CAAK,GAC7DhF,EAAIC,GAAO8E,GAAG,MAAM,MAAM,GAAG7E,IAAI,GAAG,MAAM+E,CAAI;AAC9C,eAAWI,KAAMN,IAAI,MAAM,CAAC,CAACA,IAAI,MAAMA,IAAI,IAAI,IAAI,CAAC,CAAC,GAAG;AACtD,YAAMO,IAAStF,EAAIC,GAAO8E,IAAI,MAAMA,IAAI,MAAMA,IAAI,KAAK,MAAM,MAAMM,GAAInF,IAAI,MAAM,MAAMgF,CAAK;AAC5F,MAAAI,EAAO,SAAS,IAAI;AAAA,IACtB;AAAA,EACF,WAAWb,EAAE,UAAU,QAAQ;AAC7B,IAAAzE,EAAIC,GAAO8E,GAAG7E,GAAG,KAAK,GAAG,GAAG,KAAK8E,CAAK,GACtChF,EAAIC,GAAO8E,GAAG,MAAM,MAAM,GAAG7E,IAAI,KAAK,KAAK8E,CAAK;AAChD,eAAW5E,KAAK,CAAC,CAAC2E,IAAI,MAAMA,IAAI,IAAI,EAAG,CAAA/E,EAAIC,GAAO,MAAMC,GAAG,MAAME,GAAG,GAAG,KAAK4E,CAAK;AACjF,aAAS7D,IAAI,GAAGA,IAAI,GAAGA;AACrB,MAAAnB,EAAIC,IAAQ8E,IAAI,QAAQ,IAAI,OAAO7E,IAAI,KAAK,MAAM,EAAE6E,IAAI,QAAQ,IAAK5D,KAAK4D,IAAI,QAAS,GAAG,OAAO,KAAKC,CAAK;AAAA,EAC/G,WAAWP,EAAE,UAAU,UAAU;AAC/B,IAAAzE,EAAIC,GAAO8E,GAAG7E,GAAG,OAAO,GAAG,GAAGC,GAAG8E,CAAI;AACrC,eAAW7E,KAAK,CAAC,CAAC2E,IAAI,KAAKA,IAAI,GAAG;AAChC,iBAAW1E,KAAK,CAAC,CAACH,IAAI,MAAMA,IAAI,IAAI,EAAG,CAAAF,EAAIC,GAAO,OAAO,OAAOE,GAAGC,GAAGC,GAAG,GAAG8E,CAAI;AAClF,QAAIhF,IAAI;AACN,iBAAWC,KAAK,CAAC,CAAC2E,IAAI,KAAKA,IAAI,GAAG;AAChC,mBAAW1E,KAAK,CAAC,IAAI,CAAC,GAAG;AACvB,UAAAL,EAAIC,GAAO,MAAM,MAAM,MAAMG,GAAGC,KAAKH,IAAI,IAAI,OAAO,MAAM+E,CAAI,GAC9DjF,EAAIC,GAAO,MAAM,OAAO,MAAMG,GAAGC,KAAKH,IAAI,IAAI,OAAO,MAAM+E,CAAI;AAC/D,qBAAWtB,KAAM,CAAC,OAAO,IAAI,KAAO1D,GAAO,OAAO,KAAK,MAAMG,IAAIuD,GAAItD,KAAKH,IAAI,IAAI,OAAO,GAAGiF,CAAI;AAAA,QAClG;AAAA,EACN,WAAWV,EAAE,UAAU,aAAaA,EAAE,UAAU,WAAW;AACzD,IAAAzE,EAAIC,GAAO8E,GAAG7E,GAAGC,GAAG,GAAG,GAAG,GAAG6E,CAAK;AAClC,UAAMO,IAAS,KAAK,IAAI,GAAG,KAAK,MAAMR,IAAI,IAAI,CAAC;AAC/C,aAAS5D,IAAI,GAAGA,IAAIoE,GAAQpE,KAAK;AAC/B,YAAMf,IAAI,CAAC2E,IAAI,KAAM5D,IAAI,OAAO4D,IAAKQ;AACrC,MAAAvF,EAAIC,GAAO8E,IAAIQ,IAAS,OAAO,OAAOpF,IAAI,MAAMC,GAAG,CAACF,IAAI,IAAI,OAAO,MAAM8E,CAAK,GAC9EhF,EAAIC,GAAO,OAAO,OAAO,MAAMG,IAAK2E,IAAIQ,IAAU,MAAM,CAACrF,IAAI,IAAI,OAAOC,IAAI,MAAMiF,CAAK;AAAA,IACzF;AACA,IAAIX,EAAE,UAAU,aAAWzE,EAAIC,GAAO8E,IAAI,MAAM7E,IAAI,OAAO,OAAO,GAAG,GAAGC,GAAGsB,EAAU,IAAI,QAAQ,SAAS,CAAC;AAAA,EAC7G,WAAWgD,EAAE,UAAU,UAAU;AAC/B,UAAMe,IAAO,IAAIzF,EAAM,KAAK,IAAIA,EAAM,eAAe,KAAK,IAAI,EAAE,GAAGmF,CAAK;AACxE,IAAAM,EAAK,MAAM,IAAIT,GAAG7E,IAAI,KAAK,GAAG,GAC9BsF,EAAK,SAAS,IAAI,MAClBvF,EAAM,IAAIuF,CAAI,GACdxF,EAAIC,GAAO8E,IAAI,MAAM,MAAM,MAAM,GAAG7E,IAAI,MAAM,GAAGgF,CAAK,GACtDlF,EAAIC,GAAO8E,IAAI,MAAM7E,IAAI,KAAK,KAAK,GAAG,GAAG,GAAGgF,CAAK;AAAA,EACnD,WAAWT,EAAE,UAAU,SAAS;AAC9B,IAAAzE,EAAIC,GAAO8E,GAAG7E,GAAGC,IAAI,MAAM,GAAG,GAAG,GAAG8E,CAAI,GACxCjF,EAAIC,GAAO8E,IAAI,MAAM7E,IAAI,MAAM,KAAK,GAAG,GAAGC,IAAI,KAAK+E,CAAK;AACxD,UAAMM,IAAO,IAAIzF,EAAM,KAAK,IAAIA,EAAM,eAAe,KAAK,IAAI,CAAC,GAAGH,GAAS,SAAS,CAAC;AACrF,IAAA4F,EAAK,MAAM,IAAI,GAAG,KAAK,IAAI,GAC3BA,EAAK,SAAS,IAAIrF,IAAI,MACtBF,EAAM,IAAIuF,CAAI,GACd7E,EAASV,GAAO,IAAIF,EAAM,QAAQ,GAAGG,IAAI,KAAKC,CAAC,GAAG,IAAIJ,EAAM,QAAQ,GAAGG,IAAI,KAAKC,IAAI,GAAG,GAAG,OAAOiF,CAAK;AAAA,EACxG,WAAWX,EAAE,UAAU,SAAS;AAC9B,aAAStD,IAAI,GAAGA,IAAI,GAAGA,IAAK,CAAAnB,EAAIC,GAAO8E,GAAG,MAAM,MAAM,GAAG,CAAC7E,IAAI,IAAKiB,IAAIjB,IAAK,GAAG,MAAM+E,CAAI;AACzF,aAAS9D,IAAI,GAAGA,IAAI,GAAGA,OAASlB,GAAO8E,GAAG,OAAO,MAAM,GAAG7E,IAAI,IAAI,MAAMiB,IAAI,KAAK,MAAM8D,CAAI;AAC3F,IAAAjF,EAAIC,GAAO,KAAK,KAAK,KAAK8E,IAAI,IAAI,MAAM,CAAC7E,IAAI,IAAI,KAAK,GAAGiF,CAAI;AAAA,EAC/D,WAAWV,EAAE,UAAU,UAAU;AAC/B,UAAMgB,IAAQ,IAAI1F,EAAM,qBAAqB;AAAA,MAC3C,OAAO;AAAA,MACP,aAAa;AAAA,MACb,SAAS;AAAA,MACT,WAAW;AAAA,MACX,MAAMA,EAAM;AAAA,MACZ,YAAY;AAAA,IAAA,CACb;AACD,IAAAC,EAAIC,GAAO8E,GAAG,OAAO5E,GAAG,GAAGD,IAAI,GAAG,GAAGuF,CAAK,GAC1CzF,EAAIC,GAAO,OAAOC,GAAGC,GAAG4E,IAAI,GAAG,GAAG,GAAGU,CAAK,GAC1C9E;AAAA,MACEV;AAAA,MACA,IAAIF,EAAM,QAAQ,CAACgF,IAAI,MAAM7E,IAAI,KAAK,GAAG;AAAA,MACzC,IAAIH,EAAM,QAAQ,CAACgF,IAAI,MAAM7E,IAAI,KAAKC,IAAI,GAAG;AAAA,MAC7C;AAAA,MACAiF;AAAA,IAAA,GAEFpF,EAAIC,GAAO,MAAM,MAAM,OAAO,CAAC8E,IAAI,MAAM7E,IAAI,MAAMC,IAAI,KAAKiF,CAAK;AAAA,EACnE,WAAWX,EAAE,UAAU,UAAUA,EAAE,UAAU,SAAS;AACpD,IAAIA,EAAE,UAAU,UACd9D;AAAA,MACEV;AAAA,MACA,IAAIF,EAAM,QAAQ,GAAG,GAAG,CAAC;AAAA,MACzB,IAAIA,EAAM,QAAQ,MAAM,GAAGI,IAAI,IAAI;AAAA,MACnC;AAAA,MACAsB,EAAU,IAAI,WAAW,SAAS;AAAA,IAAA;AAEtC,aAASN,IAAI,GAAGA,IAAI,GAAGA,KAAK;AAC1B,YAAMuE,IAAOjE,EAAU;AAAA,QACrBA,EAAU,MAAMN,IAAI,MAAM,IAAI,YAAYA,IAAI,MAAM,IAAI,YAAY,WAAW,IAAI;AAAA,MAAA,GAE/EZ,IAAW,IAAIR,EAAM,oBAAoB,GAAG,CAAC,GAC7C4F,IAAWpF,EAAS,aAAa,UAAU,GAC3CqF,IAAmB,CAAA;AACzB,eAASC,IAAI,GAAGA,IAAIF,EAAS,OAAOE,KAAK;AACvC,cAAMzF,IAAIuF,EAAS,KAAKE,CAAC,GACvBxF,IAAIsF,EAAS,KAAKE,CAAC,GACnBnB,IAAIiB,EAAS,KAAKE,CAAC,GACf/E,IAAI,IAAI,KAAK,IAAIV,IAAI,KAAKe,CAAC,IAAI,KAAK,IAAId,IAAI,IAAIc,CAAC,IAAI,KAAK,IAAIuD,IAAI,EAAE,IAAI;AAC9E,QAAAiB,EAAS,OAAOE,GAAGzF,IAAIU,GAAGT,IAAIS,GAAG4D,IAAI5D,CAAC;AACtC,cAAMgF,IAAQ,QAAQpB,IAAI,KAAK;AAC/B,QAAAkB,EAAO,KAAKE,GAAOA,GAAOA,CAAK;AAAA,MACjC;AACA,MAAAvF,EAAS,aAAa,SAAS,IAAIR,EAAM,uBAAuB6F,GAAQ,CAAC,CAAC,GAC1ErF,EAAS,qBAAA;AACT,YAAMG,IAAO,IAAIX,EAAM,KAAKQ,GAAUmF,CAAI,GACpCK,IAAI5E,IAAI;AACd,MAAAT,EAAK,SAAS;AAAA,QACZ,KAAK,IAAIqF,CAAC,IAAIhB,IAAI;AAAA,QAClB,KAAK,IAAIgB,CAAC,IAAI7F,IAAI;AAAA,QAClBuE,EAAE,UAAU,SAAStE,IAAI,OAAQgB,IAAI,IAAK,OAAOhB,IAAI;AAAA,MAAA,GAEvDO,EAAK,MAAM,IAAIqE,IAAI,MAAM7E,IAAI,MAAMuE,EAAE,UAAU,SAAStE,IAAI,OAAOA,IAAI,IAAI,GAC3EO,EAAK,aAAaA,EAAK,gBAAgB,IACvCT,EAAM,IAAIS,CAAI;AAAA,IAChB;AAAA,EACF,WAAW+D,EAAE,UAAU;AAYrB,QAXA9D,EAASV,GAAO,IAAIF,EAAM,QAAQ,GAAG,GAAG,CAAC,GAAG,IAAIA,EAAM,QAAQ,GAAG,GAAGI,CAAC,GAAG,OAAOgF,CAAI,GACnFnF;AAAA,MACEC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACAE,IAAI;AAAA,MACJ,IAAIJ,EAAM,qBAAqB,EAAE,OAAO,WAAW,UAAU,WAAW,mBAAmB4E,IAAU,IAAI,IAAA,CAAK;AAAA,IAAA,GAE5GA,GAAS;AACX,YAAMqB,IAAQ,IAAIjG,EAAM,WAAW,WAAW,GAAG,GAAG,CAAC;AACrD,MAAAiG,EAAM,SAAS,IAAI7F,GACnBF,EAAM,IAAI+F,CAAK;AAAA,IACjB;AAAA,aACSvB,EAAE,UAAU,OAAO;AAS5B,UAAMwB,IAAM,IAAIlG,EAAM,MAAA,GAChBmG,IAAI,KAAK,IAAInB,GAAG7E,CAAC,GACrBiG,IAAI,KAAK,IAAIpB,GAAG7E,CAAC,GACjBkG,IAAI,KAAK,IAAI,KAAKjG,CAAC;AACrB,IAAID,IAAI6E,MAAGkB,EAAI,SAAS,IAAI,KAAK,KAAK,IACtChG,EAAM,IAAIgG,CAAG;AACb,UAAMR,IAAQhE,EAAU,MAAMkD,CAAO,GAC/BzC,IAAOT,EAAU,MAAM,WAAW,IAAI,GACtC4E,IAAS5E,EAAU,MAAM,SAAS,GAClC6E,IAAO7E,EAAU,MAAM,WAAW,IAAI,GAEtC8E,IAAQH,IAAI,MAChBI,IAAOJ,IAAI,KACXK,IAASL,IAAI,MACbM,IAAON,IAAI,MACX9E,IAAO8E,IAAI,MAEPO,IAAOT,IAAI,KACfU,IAAQR,IAAI,MACZS,IAAQV,IAAI,MAERW,IAAaZ,IAAI,KACrBa,IAAW,CAACb,IAAI,MAChBc,IAAYd,IAAI,MAChBe,IAAU,CAACf,IAAI;AACjB,IAAAlG,EAAIiG,GAAKC,IAAI,KAAKC,IAAI,MAAMK,IAAOD,GAAO,GAAG,GAAGA,GAAOrE,CAAI,GAK3DlC,EAAIiG,GAAKC,IAAI,KAAKC,IAAI,MAAMM,IAASD,GAAM,GAAG,GAAGA,GAAMxB,CAAK;AAE5D,eAAWkC,KAAO,CAAC,IAAI,CAAC,EAAG,CAAAlH,EAAIiG,GAAK,KAAKE,IAAI,MAAMM,IAASD,IAAO,MAAMU,KAAOhB,IAAI,IAAI,OAAO,GAAGM,GAAMxB,CAAK;AAC7G,eAAWkC,KAAO,CAAC,IAAI,CAAC,EAAG,CAAAlH,EAAIiG,GAAK,MAAME,IAAI,MAAMM,IAASD,IAAO,MAAMU,KAAOhB,IAAI,IAAI,OAAO,GAAGM,GAAMxB,CAAK;AAC9G,IAAAhF,EAAIiG,GAAKC,IAAI,MAAMC,GAAGO,KAAQD,IAAS,MAAM,CAACP,IAAI,MAAM,GAAGO,IAAS,KAAKzB,CAAK;AAE9E,eAAW5E,KAAK,CAAC,CAACuG,GAAMA,CAAI,KAAOV,GAAKW,IAAQ,KAAKT,IAAI,MAAMC,IAAI,KAAKhG,GAAG,GAAGgG,IAAI,KAAKpB,CAAK;AAE5F,UAAMmC,IAAMnH,EAAIiG,GAAKC,IAAI,IAAIY,GAAYX,IAAI,MAAMC,IAAI,OAAOF,IAAI,IAAIY,KAAc,GAAG,GAAGL,IAAS,MAAMzB,CAAK;AAC9G,IAAAmC,EAAI,SAAS,IAAI,MACjBnH,EAAIiG,GAAKC,IAAI,IAAIa,GAAUZ,IAAI,MAAMC,IAAI,OAAO,CAACF,IAAI,IAAIa,KAAY,GAAG,GAAGL,IAAO,MAAM1B,CAAK,GAG7FhF,EAAIiG,GAAKe,IAAYC,GAASd,IAAI,MAAMC,IAAI,OAAOY,IAAYC,KAAW,GAAG,GAAG3F,IAAO8E,IAAI,MAAMpB,CAAK;AACtG,eAAWoC,KAAQ,CAAC,IAAI,CAAC,GAAG;AAC1B,YAAMC,IAAOrH;AAAA,QACXiG;AAAA,QACAa,IAAaC;AAAA,QACb;AAAA,QACAzF,IAAOoF;AAAA,SACNI,IAAaC,KAAY;AAAA,QAC1BK,IAAOjB,IAAI;AAAA,QACXO;AAAA,QACAjB;AAAA,MAAA;AAEF,MAAA4B,EAAK,SAAS,IAAID,IAAO;AAAA,IAC3B;AACA,UAAME,IAAO,CAACC,GAAcC,GAAalH,MAA6B;AACpE,YAAMmH,IAAOnG,IAAOoF,GAClBgB,IAAMH,IAAOC,GACTH,IAAOrH;AAAA,QACXiG;AAAA,QACA;AAAA,QACAE,IAAI;AAAA,QACJ,KAAK,MAAMsB,GAAMC,CAAG;AAAA,SACnBH,IAAOC,KAAO;AAAA,QACf;AAAA,SACCd,IAAOpF,KAAQ,IAAI,KAAK,MAAMmG,GAAMC,CAAG,IAAI;AAAA,QAC5CpH;AAAA,MAAA;AAIF,aAAA+G,EAAK,SAAS,IAAI,CAAC,KAAK,MAAMK,GAAKD,CAAI,GAChCJ;AAAA,IACT;AACA,IAAAC,EAAKR,GAAYE,GAAWvB,CAAK,GACjC6B,EAAKP,GAAUE,GAASxB,CAAK;AAE7B,eAAW2B,KAAQ,CAAC,IAAI,CAAC,EAAG,CAAApH,EAAIiG,GAAK,MAAM,KAAK,MAAMa,IAAa,KAAKM,KAAQjB,IAAI,IAAI,OAAOO,IAAO,MAAMxE,CAAI;AAEhH,UAAMyF,IAAO,IAAI5H,EAAM,iBAAiB6G,GAAOA,GAAOC,GAAO,EAAE,GAC7De,IAAM,IAAI7H,EAAM,iBAAiB6G,IAAQ,MAAMA,IAAQ,MAAMC,IAAQ,MAAM,EAAE;AAC/E,eAAWzG,KAAK,CAAC,CAACuG,GAAMA,CAAI;AAC1B,iBAAWtG,KAAK,CAAC,IAAI,CAAC,GAAG;AACvB,cAAMqD,IAAKrD,KAAK8F,IAAI,IAAIU,IAAQ,IAAI,QAC9BgB,IAAQ,IAAI9H,EAAM,KAAK4H,GAAMxC,CAAI;AACvC,QAAA0C,EAAM,SAAS,IAAIzH,GAAGsD,GAAIkD,CAAK,GAC/BX,EAAI,IAAI4B,CAAK;AACb,cAAMC,IAAM,IAAI/H,EAAM,KAAK6H,GAAKvB,CAAM;AACtC,QAAAyB,EAAI,SAAS,IAAI1H,GAAGsD,GAAIkD,CAAK,GAC7BX,EAAI,IAAI6B,CAAG;AAAA,MACb;AAIF,UAAMC,IAAO7B,IAAI,IAAI;AACrB,IAAAlG,EAAIiG,GAAK,MAAME,IAAI,MAAMC,IAAI,MAAM2B,GAAM,GAAG3B,IAAI,MAAMlE,CAAI,GAC1DlC,EAAIiG,GAAK,MAAME,IAAI,KAAKC,IAAI,MAAM2B,IAAO,MAAM,GAAGvB,IAAO,MAAMtE,CAAI;AACnE,UAAM8F,KAAOvG,EAAU,MAAM,WAAW,IAAI;AAC5C,eAAWpB,KAAK,CAAC,IAAI,CAAC;AACpB,MAAAL,EAAIiG,GAAK,MAAME,IAAI,MAAMC,IAAI,MAAM2B,IAAO,MAAM1H,IAAI8F,IAAI,MAAMC,IAAI,MAAM4B,EAAI,GAC5EhI,EAAIiG,GAAK,MAAME,IAAI,KAAKC,IAAI,MAAM,CAAC2B,IAAO,MAAM1H,IAAI8F,IAAI,MAAMC,IAAI,MAAME,CAAI;AAE9E,IAAAtG,EAAIiG,GAAK,MAAME,IAAI,MAAM,MAAM,CAAC4B,IAAO,MAAM,GAAG3B,IAAI,MAAMlB,CAAK;AAAA,EACjE,WAAWT,EAAE,UAAU,QAAQ;AAC7B,UAAMwD,IAAS,KAAK,IAAIlD,GAAG7E,CAAC,IAAI,KAC1BgI,IAAO,IAAInI,EAAM,iBAAiB;AAAA,MACtC,IAAIA,EAAM,QAAQ,GAAGG,IAAI,KAAKC,CAAC;AAAA,MAC/B,IAAIJ,EAAM,QAAQ,GAAG,CAACG,IAAI,MAAMC,CAAC;AAAA,MACjC,IAAIJ,EAAM,QAAQ,GAAG,CAACG,IAAI,KAAKC,IAAI8H,CAAM;AAAA,MACzC,IAAIlI,EAAM,QAAQ,GAAG,CAACG,IAAI,KAAKC,IAAI8H,IAAS,GAAG;AAAA,IAAA,CAChD,GACKE,IAAO,IAAIpI,EAAM,KAAK,IAAIA,EAAM,aAAamI,GAAM,IAAID,GAAQ,IAAI,EAAK,GAAGxG,EAAU,MAAM,SAAS,CAAC;AAC3G,IAAAxB,EAAM,IAAIkI,CAAI;AACd,UAAMC,IAAQ,IAAIrI,EAAM,KAAK,IAAIA,EAAM,eAAekI,IAAS,MAAM,EAAE,GAAGxG,EAAU,MAAM,SAAS,CAAC;AACpG,IAAA2G,EAAM,SAAS,IAAI,GAAG,CAAClI,IAAI,KAAKC,IAAI8H,IAAS,GAAG,GAChDG,EAAM,SAAS,IAAI,KAAK,IACxBnI,EAAM,IAAImI,CAAK;AAAA,EACjB,MAAA,CAAW3D,EAAE,UAAU,aACrBzE,EAAIC,GAAO8E,GAAG7E,GAAGC,GAAG,GAAG,GAAG,GAAGsB,EAAU,IAAI,SAASgD,EAAE,SAAS,SAAS,CAAC,GACzEzE,EAAIC,GAAO8E,IAAI,MAAM7E,IAAI,MAAM,MAAM,GAAG,GAAGC,GAAGiF,CAAK,OAC1CnF,GAAO8E,GAAG7E,GAAGC,GAAG,GAAG,GAAG,GAAG6E,CAAK;AACzC,SAAA/E,EAAM,SAAS,CAAAoI,MAAS;AACtB,IAAIA,aAAiBtI,EAAM,SACzBsI,EAAM,SAAS,WAAW5D,EAAE,IAC5B4D,EAAM,aAAa,IACnBA,EAAM,gBAAgB;AAAA,EAE1B,CAAC,GACMpI;AACT;"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
const N = [
|
|
2
|
+
{ chord: [50, 57, 60, 65], melody: [76, 74, 69] },
|
|
3
|
+
// Dm7, with a ninth in the melody
|
|
4
|
+
{ chord: [53, 60, 64, 69], melody: [72, 76, 69] },
|
|
5
|
+
// Fmaj7
|
|
6
|
+
{ chord: [48, 55, 62, 67], melody: [74, 79, 76] },
|
|
7
|
+
// Csus2
|
|
8
|
+
{ chord: [43, 57, 62, 65], melody: [77, 74, 69] }
|
|
9
|
+
// Gm9, open voicing
|
|
10
|
+
], P = (e) => 440 * 2 ** ((e - 69) / 12), S = /* @__PURE__ */ new WeakMap();
|
|
11
|
+
function Q(e) {
|
|
12
|
+
const t = S.get(e);
|
|
13
|
+
if (t) return t;
|
|
14
|
+
const c = 6, p = e.createBuffer(2, Math.ceil(e.sampleRate * c), e.sampleRate);
|
|
15
|
+
let r = 1886351212;
|
|
16
|
+
for (let d = 0; d < 2; d++) {
|
|
17
|
+
const u = p.getChannelData(d);
|
|
18
|
+
for (let m = 0; m < u.length; m++) {
|
|
19
|
+
r = Math.imul(r, 1664525) + 1013904223 | 0;
|
|
20
|
+
const s = m / e.sampleRate;
|
|
21
|
+
u[m] = s < 0.045 ? 0 : ((r >>> 0) / 4294967295 * 2 - 1) * Math.exp(-s / 1.25) * (1 - s / c) ** 2;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return S.set(e, p), p;
|
|
25
|
+
}
|
|
26
|
+
const _ = (e, t) => q(e, t, !1), j = (e, t) => q(e, t, !0);
|
|
27
|
+
function q(e, t, c) {
|
|
28
|
+
const p = 60 / (c ? 88 : 48), r = p * 8, d = c ? [
|
|
29
|
+
{ chord: [48, 55, 59, 64], melody: [76, 79, 74] },
|
|
30
|
+
{ chord: [45, 52, 55, 60], melody: [72, 76, 71] },
|
|
31
|
+
{ chord: [50, 57, 60, 65], melody: [74, 77, 76] },
|
|
32
|
+
{ chord: [43, 53, 57, 62], melody: [74, 71, 72] }
|
|
33
|
+
] : N, u = [], m = [], s = e.createGain();
|
|
34
|
+
s.gain.setValueAtTime(0, e.currentTime), s.gain.linearRampToValueAtTime(1, e.currentTime + 0.6);
|
|
35
|
+
const h = e.createBiquadFilter();
|
|
36
|
+
h.type = "lowpass", h.frequency.value = 3200, h.Q.value = 0.5;
|
|
37
|
+
const y = e.createGain();
|
|
38
|
+
y.gain.value = 0.72;
|
|
39
|
+
const A = e.createConvolver();
|
|
40
|
+
A.buffer = Q(e);
|
|
41
|
+
const R = e.createGain();
|
|
42
|
+
R.gain.value = c ? 0.09 : 0.48, s.connect(h), h.connect(y).connect(t), h.connect(A).connect(R).connect(t), u.push(s, h, y, A, R);
|
|
43
|
+
const w = (l, i) => {
|
|
44
|
+
const n = e.createGain();
|
|
45
|
+
n.gain.value = 0;
|
|
46
|
+
const V = e.createStereoPanner();
|
|
47
|
+
V.pan.value = l, n.connect(V).connect(s), u.push(n, V);
|
|
48
|
+
const z = [1, i ? 2.002 : 1].map((M, o) => {
|
|
49
|
+
const a = e.createOscillator();
|
|
50
|
+
a.type = !i && o === 1 ? "triangle" : "sine", a.detune.value = i ? 0 : o ? 3 : -3;
|
|
51
|
+
const T = e.createGain();
|
|
52
|
+
return T.gain.value = o ? i ? 0.22 : 0.3 : 1, a.connect(T).connect(n), a.start(), u.push(T), m.push(a), { oscillator: a, ratio: M };
|
|
53
|
+
});
|
|
54
|
+
return { note: (M, o, a, T, F, O) => {
|
|
55
|
+
for (const { oscillator: H, ratio: I } of z) H.frequency.setValueAtTime(P(M) * I, o);
|
|
56
|
+
const g = n.gain;
|
|
57
|
+
g.setValueAtTime(0, o), g.linearRampToValueAtTime(a, o + T), g.setValueAtTime(a, o + T + F), g.exponentialRampToValueAtTime(1e-5, o + O - 0.05), g.linearRampToValueAtTime(0, o + O);
|
|
58
|
+
} };
|
|
59
|
+
}, B = [-0.55, 0.25, -0.2, 0.6].map((l) => w(l, !1)), b = [-0.4, 0.3, 0.5, -0.25].map((l) => w(l, !0));
|
|
60
|
+
let f = e.currentTime + 0.05, v = 0, D = 0, C = !1, E;
|
|
61
|
+
const G = () => {
|
|
62
|
+
if (!C) {
|
|
63
|
+
for (; f < e.currentTime; )
|
|
64
|
+
f += r, v++;
|
|
65
|
+
for (; f < e.currentTime + r * 2; ) {
|
|
66
|
+
const l = d[v % d.length];
|
|
67
|
+
l.chord.forEach(
|
|
68
|
+
(i, n) => B[n].note(i, f, n ? 0.045 : 0.055, c ? 0.08 : 2, c ? 1.5 : 3, r)
|
|
69
|
+
), l.melody.forEach((i, n) => {
|
|
70
|
+
b[D++ % b.length].note(i, f + [1, 3.5, 6][n] * p, 0.065, 0.025, 0, c ? 1.5 : 3.8);
|
|
71
|
+
}), f += r, v++;
|
|
72
|
+
}
|
|
73
|
+
E = setTimeout(G, 1e3);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
return G(), {
|
|
77
|
+
nodes: u,
|
|
78
|
+
sources: [
|
|
79
|
+
...m,
|
|
80
|
+
{
|
|
81
|
+
stop() {
|
|
82
|
+
C = !0, clearTimeout(E);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
export {
|
|
89
|
+
_ as bathMusic,
|
|
90
|
+
j as elevatorMusic
|
|
91
|
+
};
|
|
92
|
+
//# sourceMappingURL=bathMusic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bathMusic.js","sources":["../../../../src/map/bathMusic.ts"],"sourcesContent":["/** An original, quiet score for the tiled baths: suspended chords and a sparse glass-bell melody.\n * Synthesised locally, with a repeating forty-second phrase and a long stereo room tail. */\n\nconst SCORE = [\n { chord: [50, 57, 60, 65], melody: [76, 74, 69] }, // Dm7, with a ninth in the melody\n { chord: [53, 60, 64, 69], melody: [72, 76, 69] }, // Fmaj7\n { chord: [48, 55, 62, 67], melody: [74, 79, 76] }, // Csus2\n { chord: [43, 57, 62, 65], melody: [77, 74, 69] }, // Gm9, open voicing\n];\nconst hz = (midi: number) => 440 * 2 ** ((midi - 69) / 12);\nconst impulses = new WeakMap<BaseAudioContext, AudioBuffer>();\n\nfunction roomImpulse(ctx: BaseAudioContext) {\n const cached = impulses.get(ctx);\n if (cached) return cached;\n const seconds = 6;\n const buffer = ctx.createBuffer(2, Math.ceil(ctx.sampleRate * seconds), ctx.sampleRate);\n let seed = 0x706f6f6c;\n for (let channel = 0; channel < 2; channel++) {\n const data = buffer.getChannelData(channel);\n for (let i = 0; i < data.length; i++) {\n seed = (Math.imul(seed, 1664525) + 1013904223) | 0;\n const t = i / ctx.sampleRate;\n // A small pre-delay leaves the notes legible before the diffuse tiled-room reflections.\n data[i] = t < 0.045 ? 0 : (((seed >>> 0) / 0xffffffff) * 2 - 1) * Math.exp(-t / 1.25) * (1 - t / seconds) ** 2;\n }\n }\n impulses.set(ctx, buffer);\n return buffer;\n}\n\nexport const bathMusic = (ctx: BaseAudioContext, out: AudioNode) => roomMusic(ctx, out, false);\nexport const elevatorMusic = (ctx: BaseAudioContext, out: AudioNode) => roomMusic(ctx, out, true);\n\nfunction roomMusic(ctx: BaseAudioContext, out: AudioNode, elevator: boolean) {\n const BEAT = 60 / (elevator ? 88 : 48),\n CHORD_SECONDS = BEAT * 8;\n const score = elevator\n ? [\n { chord: [48, 55, 59, 64], melody: [76, 79, 74] },\n { chord: [45, 52, 55, 60], melody: [72, 76, 71] },\n { chord: [50, 57, 60, 65], melody: [74, 77, 76] },\n { chord: [43, 53, 57, 62], melody: [74, 71, 72] },\n ]\n : SCORE;\n const nodes: AudioNode[] = [];\n const oscillators: OscillatorNode[] = [];\n const bus = ctx.createGain();\n // Give the first chord a gentle entrance even outside the walk engine's cross-fade.\n bus.gain.setValueAtTime(0, ctx.currentTime);\n bus.gain.linearRampToValueAtTime(1, ctx.currentTime + 0.6);\n const low = ctx.createBiquadFilter();\n low.type = 'lowpass';\n low.frequency.value = 3200;\n low.Q.value = 0.5;\n const dry = ctx.createGain();\n dry.gain.value = 0.72;\n const reverb = ctx.createConvolver();\n reverb.buffer = roomImpulse(ctx);\n const wet = ctx.createGain();\n wet.gain.value = elevator ? 0.09 : 0.48;\n bus.connect(low);\n low.connect(dry).connect(out);\n low.connect(reverb).connect(wet).connect(out);\n nodes.push(bus, low, dry, reverb, wet);\n\n const voice = (pan: number, bell: boolean) => {\n const envelope = ctx.createGain();\n envelope.gain.value = 0;\n const stereo = ctx.createStereoPanner();\n stereo.pan.value = pan;\n envelope.connect(stereo).connect(bus);\n nodes.push(envelope, stereo);\n const tones = [1, bell ? 2.002 : 1].map((ratio, i) => {\n const oscillator = ctx.createOscillator();\n oscillator.type = !bell && i === 1 ? 'triangle' : 'sine';\n oscillator.detune.value = bell ? 0 : i ? 3 : -3;\n const gain = ctx.createGain();\n gain.gain.value = i ? (bell ? 0.22 : 0.3) : 1;\n oscillator.connect(gain).connect(envelope);\n oscillator.start();\n nodes.push(gain);\n oscillators.push(oscillator);\n return { oscillator, ratio };\n });\n const note = (midi: number, at: number, level: number, attack: number, hold: number, duration: number) => {\n for (const { oscillator, ratio } of tones) oscillator.frequency.setValueAtTime(hz(midi) * ratio, at);\n const gain = envelope.gain;\n gain.setValueAtTime(0, at);\n gain.linearRampToValueAtTime(level, at + attack);\n gain.setValueAtTime(level, at + attack + hold);\n gain.exponentialRampToValueAtTime(0.00001, at + duration - 0.05);\n gain.linearRampToValueAtTime(0, at + duration);\n };\n return { note };\n };\n const pads = [-0.55, 0.25, -0.2, 0.6].map(pan => voice(pan, false));\n const bells = [-0.4, 0.3, 0.5, -0.25].map(pan => voice(pan, true));\n let next = ctx.currentTime + 0.05;\n let bar = 0;\n let bell = 0;\n let stopped = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const schedule = () => {\n if (stopped) return;\n // Skip elapsed bars after a background-tab stall instead of firing a backlog of notes.\n while (next < ctx.currentTime) {\n next += CHORD_SECONDS;\n bar++;\n }\n while (next < ctx.currentTime + CHORD_SECONDS * 2) {\n const phrase = score[bar % score.length];\n phrase.chord.forEach((midi, i) =>\n pads[i].note(midi, next, i ? 0.045 : 0.055, elevator ? 0.08 : 2, elevator ? 1.5 : 3, CHORD_SECONDS),\n );\n phrase.melody.forEach((midi, i) => {\n bells[bell++ % bells.length].note(midi, next + [1, 3.5, 6][i] * BEAT, 0.065, 0.025, 0, elevator ? 1.5 : 3.8);\n });\n next += CHORD_SECONDS;\n bar++;\n }\n timer = setTimeout(schedule, 1000);\n };\n schedule();\n // A fixed voice bank bounds memory for an indefinitely long walk. No new nodes per note.\n return {\n nodes,\n sources: [\n ...oscillators,\n {\n stop() {\n stopped = true;\n clearTimeout(timer);\n },\n },\n ],\n };\n}\n"],"names":["SCORE","hz","midi","impulses","roomImpulse","ctx","cached","seconds","buffer","seed","channel","data","i","t","bathMusic","out","roomMusic","elevatorMusic","elevator","BEAT","CHORD_SECONDS","score","nodes","oscillators","bus","low","dry","reverb","wet","voice","pan","bell","envelope","stereo","tones","ratio","oscillator","gain","at","level","attack","hold","duration","pads","bells","next","bar","stopped","timer","schedule","phrase"],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as g from "maplibre-gl";
|
|
2
|
+
import { toLngLat as M } from "../model/geometry.js";
|
|
3
|
+
import { undergroundView as f } from "./underground.js";
|
|
4
|
+
function u(t) {
|
|
5
|
+
const o = t.getVerticalFieldOfView() * Math.PI / 360;
|
|
6
|
+
return 0.5 / Math.tan(o) * Math.max(1, t.getCanvas().clientHeight);
|
|
7
|
+
}
|
|
8
|
+
function C(t) {
|
|
9
|
+
const o = t.getCenter(), i = t.getCenterElevation(), a = t.getPitch() * Math.PI / 180, r = t.getBearing() * Math.PI / 180, n = g.MercatorCoordinate.fromLngLat(o, i), e = n.meterInMercatorCoordinateUnits(), s = e * 512 * 2 ** t.getZoom(), c = u(t) / s, l = Math.sin(a) * c * e, h = new g.MercatorCoordinate(
|
|
10
|
+
n.x - Math.sin(r) * l,
|
|
11
|
+
n.y + Math.cos(r) * l,
|
|
12
|
+
n.z + Math.cos(a) * c * e
|
|
13
|
+
);
|
|
14
|
+
return { lngLat: h.toLngLat(), altitude: h.toAltitude() };
|
|
15
|
+
}
|
|
16
|
+
function d(t, o, i, a) {
|
|
17
|
+
if (!o) return t;
|
|
18
|
+
const r = o * Math.tan(i * Math.PI / 180), n = a * Math.PI / 180, e = g.MercatorCoordinate.fromLngLat({ lng: t[0], lat: t[1] }), s = e.meterInMercatorCoordinateUnits();
|
|
19
|
+
e.x += r * Math.sin(n) * s, e.y -= r * Math.cos(n) * s;
|
|
20
|
+
const c = e.toLngLat();
|
|
21
|
+
return [c.lng, c.lat];
|
|
22
|
+
}
|
|
23
|
+
function P(t, o, i, a, r) {
|
|
24
|
+
const n = M(i, o.origin), e = r.threeD ? f(o, a, r.stack).focusElevation : 0;
|
|
25
|
+
return d([n[0], n[1]], e, t.getPitch(), t.getBearing());
|
|
26
|
+
}
|
|
27
|
+
export {
|
|
28
|
+
d as aimCenter,
|
|
29
|
+
C as cameraPosition,
|
|
30
|
+
u as cameraToCenterDistance,
|
|
31
|
+
P as floorAim
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=cameraAim.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cameraAim.js","sources":["../../../../src/map/cameraAim.ts"],"sourcesContent":["import * as maplibregl from 'maplibre-gl';\nimport type { Map as GLMap } from 'maplibre-gl';\nimport type { Point, ProjectDocument } from '../model/types';\nimport { toLngLat } from '../model/geometry';\nimport { undergroundView } from './underground';\n\nexport function cameraToCenterDistance(map: GLMap): number {\n const halfFov = (map.getVerticalFieldOfView() * Math.PI) / 360;\n return (0.5 / Math.tan(halfFov)) * Math.max(1, map.getCanvas().clientHeight);\n}\n\nexport function cameraPosition(map: GLMap) {\n const center = map.getCenter();\n const elevation = map.getCenterElevation();\n const pitch = (map.getPitch() * Math.PI) / 180;\n const bearing = (map.getBearing() * Math.PI) / 180;\n const target = maplibregl.MercatorCoordinate.fromLngLat(center, elevation);\n const mercatorUnitsPerMetre = target.meterInMercatorCoordinateUnits();\n const pixelsPerMetre = mercatorUnitsPerMetre * 512 * 2 ** map.getZoom();\n const distanceMetres = cameraToCenterDistance(map) / pixelsPerMetre;\n const horizontal = Math.sin(pitch) * distanceMetres * mercatorUnitsPerMetre;\n const eye = new maplibregl.MercatorCoordinate(\n target.x - Math.sin(bearing) * horizontal,\n target.y + Math.cos(bearing) * horizontal,\n target.z + Math.cos(pitch) * distanceMetres * mercatorUnitsPerMetre,\n );\n return { lngLat: eye.toLngLat(), altitude: eye.toAltitude() };\n}\n\n/** fit()'s depth-aim factored out and shared with the journey: with a pitched camera a plate at\n * elevation elev projects off-centre unless the ground target shifts by elev·tan(pitch) along the\n * view bearing. elev must already be the PRESENTED elevation (undergroundView().focusElevation). */\nexport function aimCenter(\n center: [number, number],\n elev: number,\n pitchDeg: number,\n bearingDeg: number,\n): [number, number] {\n if (!elev) return center;\n const shift = elev * Math.tan((pitchDeg * Math.PI) / 180),\n bearing = (bearingDeg * Math.PI) / 180;\n const target = maplibregl.MercatorCoordinate.fromLngLat({ lng: center[0], lat: center[1] }),\n unit = target.meterInMercatorCoordinateUnits();\n target.x += shift * Math.sin(bearing) * unit;\n target.y -= shift * Math.cos(bearing) * unit;\n const ll = target.toLngLat();\n return [ll.lng, ll.lat];\n}\n\n/** The map centre that brings a plan position on `floorId` under the crosshair. Anyone easing to a\n * point in the document wants this rather than the raw ground coordinate: the storey is drawn at its\n * presented elevation, and a pitched camera sees it displaced along the view bearing, so centring on\n * the ground beneath a basement leaves the thing you asked for a good ten metres off screen centre. */\nexport function floorAim(\n map: GLMap,\n project: ProjectDocument,\n position: Point,\n floorId: string | null,\n view: { threeD: boolean; stack: boolean },\n): [number, number] {\n const ll = toLngLat(position, project.origin);\n const elev = view.threeD ? undergroundView(project, floorId, view.stack).focusElevation : 0;\n return aimCenter([ll[0], ll[1]], elev, map.getPitch(), map.getBearing());\n}\n"],"names":["cameraToCenterDistance","map","halfFov","cameraPosition","center","elevation","pitch","bearing","target","maplibregl","mercatorUnitsPerMetre","pixelsPerMetre","distanceMetres","horizontal","eye","aimCenter","elev","pitchDeg","bearingDeg","shift","unit","ll","floorAim","project","position","floorId","view","toLngLat","undergroundView"],"mappings":";;;AAMO,SAASA,EAAuBC,GAAoB;AACzD,QAAMC,IAAWD,EAAI,uBAAA,IAA2B,KAAK,KAAM;AAC3D,SAAQ,MAAM,KAAK,IAAIC,CAAO,IAAK,KAAK,IAAI,GAAGD,EAAI,UAAA,EAAY,YAAY;AAC7E;AAEO,SAASE,EAAeF,GAAY;AACzC,QAAMG,IAASH,EAAI,UAAA,GACbI,IAAYJ,EAAI,mBAAA,GAChBK,IAASL,EAAI,SAAA,IAAa,KAAK,KAAM,KACrCM,IAAWN,EAAI,WAAA,IAAe,KAAK,KAAM,KACzCO,IAASC,EAAW,mBAAmB,WAAWL,GAAQC,CAAS,GACnEK,IAAwBF,EAAO,+BAAA,GAC/BG,IAAiBD,IAAwB,MAAM,KAAKT,EAAI,QAAA,GACxDW,IAAiBZ,EAAuBC,CAAG,IAAIU,GAC/CE,IAAa,KAAK,IAAIP,CAAK,IAAIM,IAAiBF,GAChDI,IAAM,IAAIL,EAAW;AAAA,IACzBD,EAAO,IAAI,KAAK,IAAID,CAAO,IAAIM;AAAA,IAC/BL,EAAO,IAAI,KAAK,IAAID,CAAO,IAAIM;AAAA,IAC/BL,EAAO,IAAI,KAAK,IAAIF,CAAK,IAAIM,IAAiBF;AAAA,EAAA;AAEhD,SAAO,EAAE,QAAQI,EAAI,SAAA,GAAY,UAAUA,EAAI,aAAW;AAC5D;AAKO,SAASC,EACdX,GACAY,GACAC,GACAC,GACkB;AAClB,MAAI,CAACF,EAAM,QAAOZ;AAClB,QAAMe,IAAQH,IAAO,KAAK,IAAKC,IAAW,KAAK,KAAM,GAAG,GACtDV,IAAWW,IAAa,KAAK,KAAM,KAC/BV,IAASC,EAAW,mBAAmB,WAAW,EAAE,KAAKL,EAAO,CAAC,GAAG,KAAKA,EAAO,CAAC,EAAA,CAAG,GACxFgB,IAAOZ,EAAO,+BAAA;AAChB,EAAAA,EAAO,KAAKW,IAAQ,KAAK,IAAIZ,CAAO,IAAIa,GACxCZ,EAAO,KAAKW,IAAQ,KAAK,IAAIZ,CAAO,IAAIa;AACxC,QAAMC,IAAKb,EAAO,SAAA;AAClB,SAAO,CAACa,EAAG,KAAKA,EAAG,GAAG;AACxB;AAMO,SAASC,EACdrB,GACAsB,GACAC,GACAC,GACAC,GACkB;AAClB,QAAML,IAAKM,EAASH,GAAUD,EAAQ,MAAM,GACtCP,IAAOU,EAAK,SAASE,EAAgBL,GAASE,GAASC,EAAK,KAAK,EAAE,iBAAiB;AAC1F,SAAOX,EAAU,CAACM,EAAG,CAAC,GAAGA,EAAG,CAAC,CAAC,GAAGL,GAAMf,EAAI,SAAA,GAAYA,EAAI,YAAY;AACzE;"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { add as d, rotate as a, rectangle as l, objectRotation as m, objectPosition as g } from "../model/geometry.js";
|
|
2
|
+
import { servedFloors as w } from "../model/vertical.js";
|
|
3
|
+
const v = (t) => ({
|
|
4
|
+
width: Math.max(0.7, t.width - 0.28),
|
|
5
|
+
depth: Math.max(0.7, t.depth - 0.28)
|
|
6
|
+
});
|
|
7
|
+
function S(t, n, r) {
|
|
8
|
+
return t.objects.filter((i) => i.kind === "elevator" && r.has(i.id) && w(t, i).some((o) => o.id === n)).map((i) => {
|
|
9
|
+
const { width: o, depth: e } = v(i);
|
|
10
|
+
return l(g(t, i), o, e, m(t, i));
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
const M = (t, n = 0) => Math.max(0.7, Math.min(1.6, (n % 180 ? t.depth : t.width) - 0.5)), f = (t) => {
|
|
14
|
+
var n;
|
|
15
|
+
return t.rotation + { front: 0, right: 90, back: 180, left: 270 }[((n = t.doorSides) == null ? void 0 : n[0]) ?? "front"];
|
|
16
|
+
}, D = (t) => {
|
|
17
|
+
const n = f(t) - t.rotation;
|
|
18
|
+
return d(t.position, a([0, (n % 180 ? t.width : t.depth) / 2 + 0.8], f(t)));
|
|
19
|
+
};
|
|
20
|
+
function P(t, n) {
|
|
21
|
+
const r = a([n[0] - t.position[0], n[1] - t.position[1]], -t.rotation);
|
|
22
|
+
return Math.abs(r[0]) < t.width / 2 - 0.2 && Math.abs(r[1]) < t.depth / 2 - 0.2;
|
|
23
|
+
}
|
|
24
|
+
function W(t, n) {
|
|
25
|
+
const r = [];
|
|
26
|
+
for (const [i, o] of [
|
|
27
|
+
["front", 0],
|
|
28
|
+
["right", 90],
|
|
29
|
+
["back", 180],
|
|
30
|
+
["left", 270]
|
|
31
|
+
]) {
|
|
32
|
+
const e = o % 180 ? t.depth : t.width, p = o % 180 ? t.width : t.depth, c = M(t, o), u = n && (t.doorSides ?? ["front"]).includes(i), h = (s, b) => r.push(
|
|
33
|
+
l(d(t.position, a([s, p / 2 - 0.1], t.rotation + o)), b, 0.2, t.rotation + o)
|
|
34
|
+
);
|
|
35
|
+
if (!u) h(0, e);
|
|
36
|
+
else for (const s of [-1, 1]) h(s * (e + c) / 4, (e - c) / 2);
|
|
37
|
+
}
|
|
38
|
+
return r;
|
|
39
|
+
}
|
|
40
|
+
const k = (t) => ["back", "left", "right", "front"].find((n) => !(t.doorSides ?? ["front"]).includes(n));
|
|
41
|
+
function y(t) {
|
|
42
|
+
const n = { front: 0, right: 90, back: 180, left: 270 }[k(t) ?? "back"];
|
|
43
|
+
return d(t.position, a([0, (n % 180 ? t.width : t.depth) / 2], t.rotation + n));
|
|
44
|
+
}
|
|
45
|
+
export {
|
|
46
|
+
v as cabinDimensions,
|
|
47
|
+
S as cabinFloorVoids,
|
|
48
|
+
M as elevatorDoorWidth,
|
|
49
|
+
f as elevatorFacing,
|
|
50
|
+
D as elevatorLanding,
|
|
51
|
+
k as elevatorMirrorFace,
|
|
52
|
+
y as elevatorMirrorPoint,
|
|
53
|
+
W as elevatorWalls,
|
|
54
|
+
P as insideElevator
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=elevators.js.map
|