@fnndsc/orrery 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/README.md +12 -0
  2. package/dist/controls/cameraRig.d.ts +223 -0
  3. package/dist/controls/cameraRig.js +353 -0
  4. package/dist/controls/cameraRig.js.map +1 -0
  5. package/dist/controls/gestures.d.ts +133 -0
  6. package/dist/controls/gestures.js +282 -0
  7. package/dist/controls/gestures.js.map +1 -0
  8. package/dist/controls/index.d.ts +9 -0
  9. package/dist/controls/index.js +10 -0
  10. package/dist/controls/index.js.map +1 -0
  11. package/dist/controls/picker.d.ts +117 -0
  12. package/dist/controls/picker.js +167 -0
  13. package/dist/controls/picker.js.map +1 -0
  14. package/dist/controls/replay.d.ts +94 -0
  15. package/dist/controls/replay.js +147 -0
  16. package/dist/controls/replay.js.map +1 -0
  17. package/dist/draw/censusField.d.ts +113 -0
  18. package/dist/draw/censusField.js +241 -0
  19. package/dist/draw/censusField.js.map +1 -0
  20. package/dist/draw/constants.d.ts +13 -0
  21. package/dist/draw/constants.js +14 -0
  22. package/dist/draw/constants.js.map +1 -0
  23. package/dist/draw/geometry.d.ts +33 -0
  24. package/dist/draw/geometry.js +55 -0
  25. package/dist/draw/geometry.js.map +1 -0
  26. package/dist/draw/handoff.d.ts +11 -0
  27. package/dist/draw/handoff.js +12 -0
  28. package/dist/draw/handoff.js.map +1 -0
  29. package/dist/draw/handoffField.d.ts +74 -0
  30. package/dist/draw/handoffField.js +151 -0
  31. package/dist/draw/handoffField.js.map +1 -0
  32. package/dist/draw/index.d.ts +20 -0
  33. package/dist/draw/index.js +21 -0
  34. package/dist/draw/index.js.map +1 -0
  35. package/dist/draw/labelField.d.ts +63 -0
  36. package/dist/draw/labelField.js +149 -0
  37. package/dist/draw/labelField.js.map +1 -0
  38. package/dist/draw/lamps.d.ts +16 -0
  39. package/dist/draw/lamps.js +17 -0
  40. package/dist/draw/lamps.js.map +1 -0
  41. package/dist/draw/nebula.d.ts +8 -0
  42. package/dist/draw/nebula.js +28 -0
  43. package/dist/draw/nebula.js.map +1 -0
  44. package/dist/draw/palette.d.ts +41 -0
  45. package/dist/draw/palette.js +32 -0
  46. package/dist/draw/palette.js.map +1 -0
  47. package/dist/draw/sphereField.d.ts +98 -0
  48. package/dist/draw/sphereField.js +168 -0
  49. package/dist/draw/sphereField.js.map +1 -0
  50. package/dist/draw/starField.d.ts +127 -0
  51. package/dist/draw/starField.js +267 -0
  52. package/dist/draw/starField.js.map +1 -0
  53. package/dist/draw/stars.d.ts +65 -0
  54. package/dist/draw/stars.js +132 -0
  55. package/dist/draw/stars.js.map +1 -0
  56. package/dist/draw/timing.d.ts +11 -0
  57. package/dist/draw/timing.js +12 -0
  58. package/dist/draw/timing.js.map +1 -0
  59. package/dist/draw/tubeField.d.ts +131 -0
  60. package/dist/draw/tubeField.js +352 -0
  61. package/dist/draw/tubeField.js.map +1 -0
  62. package/dist/draw/tubes.d.ts +41 -0
  63. package/dist/draw/tubes.js +116 -0
  64. package/dist/draw/tubes.js.map +1 -0
  65. package/dist/index.d.ts +15 -0
  66. package/dist/index.js +15 -0
  67. package/dist/index.js.map +1 -0
  68. package/dist/layout/accretion.d.ts +31 -0
  69. package/dist/layout/accretion.js +384 -0
  70. package/dist/layout/accretion.js.map +1 -0
  71. package/dist/layout/constellations.d.ts +25 -0
  72. package/dist/layout/constellations.js +197 -0
  73. package/dist/layout/constellations.js.map +1 -0
  74. package/dist/layout/galaxy.d.ts +12 -0
  75. package/dist/layout/galaxy.js +99 -0
  76. package/dist/layout/galaxy.js.map +1 -0
  77. package/dist/layout/hierarchy.d.ts +45 -0
  78. package/dist/layout/hierarchy.js +464 -0
  79. package/dist/layout/hierarchy.js.map +1 -0
  80. package/dist/layout/index.d.ts +20 -0
  81. package/dist/layout/index.js +21 -0
  82. package/dist/layout/index.js.map +1 -0
  83. package/dist/layout/layoutInput.d.ts +29 -0
  84. package/dist/layout/layoutInput.js +45 -0
  85. package/dist/layout/layoutInput.js.map +1 -0
  86. package/dist/layout/molecule.d.ts +64 -0
  87. package/dist/layout/molecule.js +155 -0
  88. package/dist/layout/molecule.js.map +1 -0
  89. package/dist/layout/pull.d.ts +94 -0
  90. package/dist/layout/pull.js +137 -0
  91. package/dist/layout/pull.js.map +1 -0
  92. package/dist/layout/ranked.d.ts +75 -0
  93. package/dist/layout/ranked.js +148 -0
  94. package/dist/layout/ranked.js.map +1 -0
  95. package/dist/layout/registry.d.ts +23 -0
  96. package/dist/layout/registry.js +165 -0
  97. package/dist/layout/registry.js.map +1 -0
  98. package/dist/layout/seeded.d.ts +32 -0
  99. package/dist/layout/seeded.js +48 -0
  100. package/dist/layout/seeded.js.map +1 -0
  101. package/dist/layout/types.d.ts +81 -0
  102. package/dist/layout/types.js +14 -0
  103. package/dist/layout/types.js.map +1 -0
  104. package/dist/scene/index.d.ts +6 -0
  105. package/dist/scene/index.js +7 -0
  106. package/dist/scene/index.js.map +1 -0
  107. package/dist/scene/orrery.d.ts +592 -0
  108. package/dist/scene/orrery.js +1555 -0
  109. package/dist/scene/orrery.js.map +1 -0
  110. package/dist/types/encoding.d.ts +43 -0
  111. package/dist/types/encoding.js +7 -0
  112. package/dist/types/encoding.js.map +1 -0
  113. package/dist/types/space.d.ts +12 -0
  114. package/dist/types/space.js +10 -0
  115. package/dist/types/space.js.map +1 -0
  116. package/package.json +57 -0
@@ -0,0 +1,241 @@
1
+ /**
2
+ * @file The census: every job of every stage.
3
+ *
4
+ * A stage that stands for many jobs is drawn as a shell of them around its
5
+ * place, each job its own sphere (or, under stars, its own point of light);
6
+ * each job is joined to a job of its parent stage — by tubes that carry
7
+ * the feed's pulses while there are few enough of them, by lines past that.
8
+ * A wave down the graph flares every job of a stage together.
9
+ *
10
+ * @module
11
+ */
12
+ import * as THREE from 'three';
13
+ import { THREAD_OPACITY } from './constants.js';
14
+ import { fibonacciPoint_make } from './geometry.js';
15
+ import { WAVE_STEP_MS } from './timing.js';
16
+ import { tubeMode_of } from './tubeField.js';
17
+ import { CENSUS_TUBE_CAP } from './tubes.js';
18
+ /** Every job of every stage, drawn. */
19
+ export class CensusField {
20
+ host;
21
+ mesh = null;
22
+ base = null;
23
+ memberIds = [];
24
+ memberPositions = [];
25
+ /**
26
+ * @param host - What the census draws with.
27
+ */
28
+ constructor(host) {
29
+ this.host = host;
30
+ }
31
+ /** Whether the census is drawn as instanced spheres (not stars). */
32
+ drawn() {
33
+ return this.mesh !== null;
34
+ }
35
+ /** The stage behind each job, in draw order. */
36
+ ids() {
37
+ return this.memberIds;
38
+ }
39
+ /** Where each job stands, in draw order. */
40
+ positions() {
41
+ return this.memberPositions;
42
+ }
43
+ /**
44
+ * Draws the census.
45
+ *
46
+ * @param nodes - The stages.
47
+ * @param starring - Draw jobs as points of light, not spheres.
48
+ * @param palette - The colours.
49
+ * @returns Where the cloud stands and how far it reaches.
50
+ */
51
+ build(nodes, starring, palette) {
52
+ let total = 0;
53
+ for (const node of nodes)
54
+ if (node.ghost !== true)
55
+ total += Math.max(1, node.count);
56
+ const geometry = new THREE.IcosahedronGeometry(1, 1);
57
+ const material = new THREE.MeshStandardMaterial({ color: '#ffffff', roughness: 0.5, metalness: 0.1 });
58
+ const starred = [];
59
+ const instanced = new THREE.InstancedMesh(geometry, material, starring ? 1 : total);
60
+ const color = new THREE.Color();
61
+ const carrier = new THREE.Object3D();
62
+ const shells = new Map();
63
+ const shellRadii = new Map();
64
+ let index = 0;
65
+ let cloudRadius = 1;
66
+ const center = new THREE.Vector3();
67
+ for (const node of nodes)
68
+ center.add(node.position);
69
+ center.divideScalar(Math.max(1, nodes.length));
70
+ for (const node of nodes) {
71
+ // An anchor is nobody's job: a census of it would draw a shell of nothing.
72
+ if (node.ghost === true)
73
+ continue;
74
+ const n = Math.max(1, node.count);
75
+ const shellRadius = n === 1 ? 0 : node.radius * (1.6 + 0.55 * Math.cbrt(n));
76
+ const memberRadius = n === 1 ? node.radius : Math.max(0.06, Math.min(node.radius * 0.5, (2.2 * shellRadius) / Math.sqrt(n)));
77
+ const points = [];
78
+ for (let k = 0; k < n; k++) {
79
+ const point = n === 1 ? node.position.clone() : fibonacciPoint_make(k, n, shellRadius).add(node.position);
80
+ points.push(point);
81
+ color.set(node.color);
82
+ if (starring) {
83
+ starred.push({ id: node.id, position: point, radius: memberRadius, color: color.clone(), dim: node.dim, ember: node.ember });
84
+ }
85
+ else {
86
+ carrier.position.copy(point);
87
+ carrier.scale.setScalar(memberRadius);
88
+ carrier.updateMatrix();
89
+ instanced.setMatrixAt(index, carrier.matrix);
90
+ instanced.setColorAt(index, color);
91
+ }
92
+ this.memberIds.push(node.id);
93
+ this.memberPositions.push(point);
94
+ index += 1;
95
+ cloudRadius = Math.max(cloudRadius, center.distanceTo(point) + memberRadius);
96
+ }
97
+ shells.set(node.id, points);
98
+ shellRadii.set(node.id, memberRadius);
99
+ }
100
+ if (starring) {
101
+ const view = this.host.starsView();
102
+ this.host.stars.draw(starred, view.pixelRatio, view.heightPx, view.fovDeg);
103
+ }
104
+ else {
105
+ if (instanced.instanceColor)
106
+ instanced.instanceColor.needsUpdate = true;
107
+ this.host.parent.add(instanced);
108
+ this.mesh = instanced;
109
+ this.base = instanced.instanceColor ? Float32Array.from(instanced.instanceColor.array) : null;
110
+ }
111
+ const segments = [];
112
+ for (const node of nodes) {
113
+ const mine = shells.get(node.id) ?? [];
114
+ for (const parentId of node.parents) {
115
+ const theirs = shells.get(parentId);
116
+ if (!theirs || theirs.length === 0)
117
+ continue;
118
+ for (let k = 0; k < mine.length; k++) {
119
+ const a = mine[k];
120
+ const b = theirs.length === mine.length ? theirs[k] : theirs[k % theirs.length];
121
+ if (a === undefined || b === undefined)
122
+ continue;
123
+ segments.push(a.x, a.y, a.z, b.x, b.y, b.z);
124
+ }
125
+ }
126
+ }
127
+ // Drawn as spheres, a census joins its jobs with the tubes a feed wears,
128
+ // pulses and all — while there are few enough of them to draw.
129
+ const tubeCount = segments.length / 6;
130
+ if (!starring && tubeCount > 0 && tubeCount <= CENSUS_TUBE_CAP) {
131
+ this.tubes_build(nodes, shells, shellRadii, palette);
132
+ }
133
+ else if (segments.length > 0) {
134
+ const edgeGeometry = new THREE.BufferGeometry();
135
+ edgeGeometry.setAttribute('position', new THREE.Float32BufferAttribute(segments, 3));
136
+ this.host.parent.add(new THREE.LineSegments(edgeGeometry, starring
137
+ ? new THREE.LineBasicMaterial({ color: palette.edge, transparent: true, opacity: THREAD_OPACITY, blending: THREE.AdditiveBlending, depthWrite: false })
138
+ : new THREE.LineBasicMaterial({ color: palette.edge, transparent: true, opacity: 0.35 })));
139
+ }
140
+ return { center, radius: cloudRadius };
141
+ }
142
+ /**
143
+ * Flares every job of a stage with the wave, written straight into the
144
+ * instance colours.
145
+ *
146
+ * @param fireAt - When a stage fires, by id; undefined when it does not.
147
+ * @param elapsed - Time since the wave set off.
148
+ * @param pulse - The flare's hue.
149
+ * @param flareMs - How long a flare lasts.
150
+ * @returns The latest a stage fires, so the caller knows when the wave is done.
151
+ */
152
+ flare(fireAt, elapsed, pulse, flareMs) {
153
+ let peak = 0;
154
+ if (this.mesh === null || this.base === null || !this.mesh.instanceColor)
155
+ return peak;
156
+ const colors = this.mesh.instanceColor.array;
157
+ const base = this.base;
158
+ for (let i = 0; i < this.memberIds.length; i++) {
159
+ const at = fireAt(this.memberIds[i] ?? '');
160
+ if (at === undefined)
161
+ continue;
162
+ peak = Math.max(peak, at);
163
+ const dt = elapsed - at;
164
+ const flare = dt >= 0 && dt <= flareMs ? Math.sin((dt / flareMs) * Math.PI) : 0;
165
+ const o = i * 3;
166
+ colors[o] = base[o] + (pulse.r - base[o]) * flare;
167
+ colors[o + 1] = base[o + 1] + (pulse.g - base[o + 1]) * flare;
168
+ colors[o + 2] = base[o + 2] + (pulse.b - base[o + 2]) * flare;
169
+ }
170
+ this.mesh.instanceColor.needsUpdate = true;
171
+ return peak;
172
+ }
173
+ /**
174
+ * The stage behind the job a ray meets first; the touched job lights up.
175
+ *
176
+ * @param raycaster - The ray, aimed by the caller.
177
+ * @returns The stage, or null.
178
+ */
179
+ pick(raycaster) {
180
+ if (this.mesh === null)
181
+ return null;
182
+ const hit = raycaster.intersectObject(this.mesh)[0];
183
+ if (hit === undefined || hit.instanceId === undefined)
184
+ return null;
185
+ this.mesh.setColorAt(hit.instanceId, new THREE.Color('#ffffff'));
186
+ if (this.mesh.instanceColor)
187
+ this.mesh.instanceColor.needsUpdate = true;
188
+ return this.memberIds[hit.instanceId] ?? null;
189
+ }
190
+ /** Forgets everything: the scene is being redrawn. */
191
+ clear() {
192
+ this.mesh = null;
193
+ this.base = null;
194
+ this.memberIds = [];
195
+ this.memberPositions = [];
196
+ }
197
+ /**
198
+ * Joins the jobs with tubes: each to the job of its parent stage it stands
199
+ * against, in the stage's hue (red into a failed one); a live stage
200
+ * streams, a finished run replays with every job of a stage together.
201
+ */
202
+ tubes_build(nodes, shells, shellRadii, palette) {
203
+ const byId = new Map(nodes.map((node) => [node.id, node]));
204
+ const depth = new Map();
205
+ const depth_of = (id, seen = new Set()) => {
206
+ const known = depth.get(id);
207
+ if (known !== undefined)
208
+ return known;
209
+ if (seen.has(id))
210
+ return 0;
211
+ seen.add(id);
212
+ const parents = (byId.get(id)?.parents ?? []).filter((p) => byId.has(p));
213
+ const d = parents.length === 0 ? 0 : 1 + Math.max(...parents.map((p) => depth_of(p, seen)));
214
+ depth.set(id, d);
215
+ return d;
216
+ };
217
+ const bright = palette.edge.clone().lerp(new THREE.Color('#ffffff'), 0.45);
218
+ const specs = [];
219
+ let deepest = 0;
220
+ for (const node of nodes) {
221
+ const mine = shells.get(node.id) ?? [];
222
+ for (const parentId of node.parents) {
223
+ const theirs = shells.get(parentId);
224
+ if (!theirs || theirs.length === 0)
225
+ continue;
226
+ const width = Math.max(0.02, Math.min(shellRadii.get(node.id) ?? 0.1, shellRadii.get(parentId) ?? 0.1) * 0.34);
227
+ const start = depth_of(parentId) * WAVE_STEP_MS;
228
+ deepest = Math.max(deepest, depth_of(parentId));
229
+ for (let k = 0; k < mine.length; k++) {
230
+ const to = mine[k];
231
+ const from = theirs.length === mine.length ? theirs[k] : theirs[k % theirs.length];
232
+ if (from === undefined || to === undefined)
233
+ continue;
234
+ specs.push({ from, to, width, color: node.state === 'failed' ? palette.error : bright, mode: tubeMode_of(node.state), start });
235
+ }
236
+ }
237
+ }
238
+ this.host.tubes.census_build(specs, deepest);
239
+ }
240
+ }
241
+ //# sourceMappingURL=censusField.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"censusField.js","sourceRoot":"","sources":["../../src/draw/censusField.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @file How faint things are drawn: the opacities the drawers share.
3
+ *
4
+ * @module
5
+ */
6
+ /** How faint a dimmed node and its edges are drawn. */
7
+ export declare const DIM_OPACITY: number;
8
+ /** How faint a cluster's halo is drawn. */
9
+ export declare const HALO_OPACITY: number;
10
+ /** Threads (edges) while the scene draws stars: faint, so the light leads. */
11
+ export declare const THREAD_OPACITY: number;
12
+ /** A nebula's opacity at its heart; a dimmed one a third of it. */
13
+ export declare const NEBULA_OPACITY: number;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @file How faint things are drawn: the opacities the drawers share.
3
+ *
4
+ * @module
5
+ */
6
+ /** How faint a dimmed node and its edges are drawn. */
7
+ export const DIM_OPACITY = 0.16;
8
+ /** How faint a cluster's halo is drawn. */
9
+ export const HALO_OPACITY = 0.09;
10
+ /** Threads (edges) while the scene draws stars: faint, so the light leads. */
11
+ export const THREAD_OPACITY = 0.1;
12
+ /** A nebula's opacity at its heart; a dimmed one a third of it. */
13
+ export const NEBULA_OPACITY = 0.2;
14
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/draw/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,uDAAuD;AACvD,MAAM,CAAC,MAAM,WAAW,GAAW,IAAI,CAAC;AAExC,2CAA2C;AAC3C,MAAM,CAAC,MAAM,YAAY,GAAW,IAAI,CAAC;AAEzC,8EAA8E;AAC9E,MAAM,CAAC,MAAM,cAAc,GAAW,GAAG,CAAC;AAE1C,mEAAmE;AACnE,MAAM,CAAC,MAAM,cAAc,GAAW,GAAG,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @file The shapes the drawers share: halos, shells of points, spheres.
3
+ *
4
+ * @module
5
+ */
6
+ import * as THREE from 'three';
7
+ /**
8
+ * A halo's radius by the feeds it gathers: room for a few, more for a crowd,
9
+ * never so much it swallows the neighbouring cluster.
10
+ *
11
+ * @param count - The feeds of the shape.
12
+ * @returns The radius in scene units.
13
+ */
14
+ export declare function haloRadius_of(count: number): number;
15
+ /** The k-th of n points on a fibonacci sphere of the given radius. */
16
+ export declare function fibonacciPoint_make(k: number, n: number, radius: number): THREE.Vector3;
17
+ /**
18
+ * Sphere geometries shared by radius: one per size a scene draws, not one
19
+ * per node (thousands of identical spheres each built their own, and a
20
+ * rebuild paid for every one).
21
+ */
22
+ export declare class SphereGeometries {
23
+ private readonly byKey;
24
+ /**
25
+ * The sphere of a radius, built once.
26
+ *
27
+ * @param radius - The radius, kept to a thousandth.
28
+ * @returns The shared geometry.
29
+ */
30
+ of(radius: number): THREE.SphereGeometry;
31
+ /** Lets every geometry go. */
32
+ dispose(): void;
33
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * @file The shapes the drawers share: halos, shells of points, spheres.
3
+ *
4
+ * @module
5
+ */
6
+ import * as THREE from 'three';
7
+ /**
8
+ * A halo's radius by the feeds it gathers: room for a few, more for a crowd,
9
+ * never so much it swallows the neighbouring cluster.
10
+ *
11
+ * @param count - The feeds of the shape.
12
+ * @returns The radius in scene units.
13
+ */
14
+ export function haloRadius_of(count) {
15
+ return 1.6 + 0.45 * Math.sqrt(Math.max(1, count));
16
+ }
17
+ /** The k-th of n points on a fibonacci sphere of the given radius. */
18
+ export function fibonacciPoint_make(k, n, radius) {
19
+ const golden = Math.PI * (3 - Math.sqrt(5));
20
+ const y = n === 1 ? 0 : 1 - (2 * k) / (n - 1);
21
+ const ring = Math.sqrt(Math.max(0, 1 - y * y));
22
+ const angle = golden * k;
23
+ return new THREE.Vector3(Math.cos(angle) * ring * radius, y * radius, Math.sin(angle) * ring * radius);
24
+ }
25
+ /**
26
+ * Sphere geometries shared by radius: one per size a scene draws, not one
27
+ * per node (thousands of identical spheres each built their own, and a
28
+ * rebuild paid for every one).
29
+ */
30
+ export class SphereGeometries {
31
+ byKey = new Map();
32
+ /**
33
+ * The sphere of a radius, built once.
34
+ *
35
+ * @param radius - The radius, kept to a thousandth.
36
+ * @returns The shared geometry.
37
+ */
38
+ of(radius) {
39
+ const key = Math.round(radius * 1000);
40
+ let geometry = this.byKey.get(key);
41
+ if (geometry === undefined) {
42
+ geometry = new THREE.SphereGeometry(key / 1000, 24, 18);
43
+ geometry.computeBoundingSphere();
44
+ this.byKey.set(key, geometry);
45
+ }
46
+ return geometry;
47
+ }
48
+ /** Lets every geometry go. */
49
+ dispose() {
50
+ for (const geometry of this.byKey.values())
51
+ geometry.dispose();
52
+ this.byKey.clear();
53
+ }
54
+ }
55
+ //# sourceMappingURL=geometry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geometry.js","sourceRoot":"","sources":["../../src/draw/geometry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,OAAO,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AACpD,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,mBAAmB,CAAC,CAAS,EAAE,CAAS,EAAE,MAAc;IACtE,MAAM,MAAM,GAAW,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACpD,MAAM,CAAC,GAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACtD,MAAM,IAAI,GAAW,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACvD,MAAM,KAAK,GAAW,MAAM,GAAG,CAAC,CAAC;IACjC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,GAAG,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,GAAG,MAAM,CAAC,CAAC;AACzG,CAAC;AAED;;;;GAIG;AACH,MAAM,OAAO,gBAAgB;IACV,KAAK,GAAsC,IAAI,GAAG,EAAE,CAAC;IAEtE;;;;;OAKG;IACI,EAAE,CAAC,MAAc;QACtB,MAAM,GAAG,GAAW,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;QAC9C,IAAI,QAAQ,GAAqC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACrE,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,QAAQ,GAAG,IAAI,KAAK,CAAC,cAAc,CAAC,GAAG,GAAG,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;YACxD,QAAQ,CAAC,qBAAqB,EAAE,CAAC;YACjC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAChC,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,8BAA8B;IACvB,OAAO;QACZ,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;YAAE,QAAQ,CAAC,OAAO,EAAE,CAAC;QAC/D,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;CACF"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @file When a molecule turns from stars to spheres and back, and how long the crossfade takes.
3
+ *
4
+ * @module
5
+ */
6
+ /** A feed switches to solid when its largest sphere spans this many CSS pixels… */
7
+ export declare const HANDOFF_SOLID_PX: number;
8
+ /** …and back to stars below this: the gap keeps a feed at the edge from flickering. */
9
+ export declare const HANDOFF_STAR_PX: number;
10
+ /** The crossfade between a feed's stars and its spheres. */
11
+ export declare const HANDOFF_FADE_MS: number;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @file When a molecule turns from stars to spheres and back, and how long the crossfade takes.
3
+ *
4
+ * @module
5
+ */
6
+ /** A feed switches to solid when its largest sphere spans this many CSS pixels… */
7
+ export const HANDOFF_SOLID_PX = 7;
8
+ /** …and back to stars below this: the gap keeps a feed at the edge from flickering. */
9
+ export const HANDOFF_STAR_PX = 5;
10
+ /** The crossfade between a feed's stars and its spheres. */
11
+ export const HANDOFF_FADE_MS = 300;
12
+ //# sourceMappingURL=handoff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handoff.js","sourceRoot":"","sources":["../../src/draw/handoff.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,mFAAmF;AACnF,MAAM,CAAC,MAAM,gBAAgB,GAAW,CAAC,CAAC;AAE1C,uFAAuF;AACvF,MAAM,CAAC,MAAM,eAAe,GAAW,CAAC,CAAC;AAEzC,4DAA4D;AAC5D,MAAM,CAAC,MAAM,eAAe,GAAW,GAAG,CAAC"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * @file The hand-off between stars and spheres.
3
+ *
4
+ * From afar a molecule is stars; as the camera closes on it — its nearest
5
+ * sphere spanning more than a few pixels — it crossfades to lit spheres in
6
+ * their tubes, its threads rising to edges; drawing back, it fades to stars
7
+ * again and its spheres are let go. A gap between the two thresholds keeps
8
+ * a molecule at the edge from flickering.
9
+ *
10
+ * @module
11
+ */
12
+ import * as THREE from 'three';
13
+ import type { SphereField } from './sphereField.js';
14
+ import type { StarField } from './starField.js';
15
+ import type { StarEntry } from './stars.js';
16
+ import type { TubeField } from './tubeField.js';
17
+ /** How a solid sphere is drawn for a node: where, how large, what hue. */
18
+ export interface HandoffLook {
19
+ position: THREE.Vector3;
20
+ radius: number;
21
+ color: THREE.Color;
22
+ }
23
+ /** What the hand-off draws with. */
24
+ export interface HandoffHost {
25
+ spheres: SphereField;
26
+ stars: StarField;
27
+ tubes: TubeField;
28
+ /** How a node's sphere is drawn, when it turns solid. */
29
+ look(id: string): HandoffLook | undefined;
30
+ }
31
+ /** Every molecule's place between stars and spheres. */
32
+ export declare class HandoffField {
33
+ private readonly host;
34
+ private groups;
35
+ private lastAt;
36
+ /**
37
+ * @param host - What the hand-off draws with.
38
+ */
39
+ constructor(host: HandoffHost);
40
+ /** How many molecules take part. */
41
+ size(): number;
42
+ /** How many are solid, or on their way. */
43
+ solidCount(): number;
44
+ /**
45
+ * Gathers drawn stars into molecules. A dimmed star is scenery and never
46
+ * turns solid.
47
+ *
48
+ * @param starred - The stars as drawn.
49
+ * @param keyOf - The molecule a node belongs to, or null for none.
50
+ */
51
+ gather(starred: ReadonlyArray<StarEntry>, keyOf: (id: string) => string | null): void;
52
+ /**
53
+ * Notes that a thread belongs to a molecule, so it fades as the
54
+ * molecule turns solid.
55
+ *
56
+ * @param key - The molecule.
57
+ * @param segment - The thread's segment.
58
+ */
59
+ thread_note(key: string, segment: number): void;
60
+ /**
61
+ * Steps the hand-off once a frame.
62
+ *
63
+ * @param view - The camera's view of the field (camera inverse × the field's world).
64
+ * @param perUnit - Pixels per unit of size at unit depth.
65
+ * @param now - This frame's time.
66
+ */
67
+ step(view: THREE.Matrix4, perUnit: number, now: number): void;
68
+ /** Forgets everything: the scene is being redrawn. */
69
+ clear(): void;
70
+ /** Draws a molecule's spheres and tubes for its time as solid. */
71
+ private solid_build;
72
+ /** Lets a molecule's spheres and tubes go once it is stars again. */
73
+ private solid_release;
74
+ }
@@ -0,0 +1,151 @@
1
+ /**
2
+ * @file The hand-off between stars and spheres.
3
+ *
4
+ * From afar a molecule is stars; as the camera closes on it — its nearest
5
+ * sphere spanning more than a few pixels — it crossfades to lit spheres in
6
+ * their tubes, its threads rising to edges; drawing back, it fades to stars
7
+ * again and its spheres are let go. A gap between the two thresholds keeps
8
+ * a molecule at the edge from flickering.
9
+ *
10
+ * @module
11
+ */
12
+ import * as THREE from 'three';
13
+ import { HANDOFF_FADE_MS, HANDOFF_SOLID_PX, HANDOFF_STAR_PX } from './handoff.js';
14
+ /** Every molecule's place between stars and spheres. */
15
+ export class HandoffField {
16
+ host;
17
+ groups = new Map();
18
+ lastAt = 0;
19
+ /**
20
+ * @param host - What the hand-off draws with.
21
+ */
22
+ constructor(host) {
23
+ this.host = host;
24
+ }
25
+ /** How many molecules take part. */
26
+ size() {
27
+ return this.groups.size;
28
+ }
29
+ /** How many are solid, or on their way. */
30
+ solidCount() {
31
+ let count = 0;
32
+ for (const group of this.groups.values())
33
+ if (group.mix > 0)
34
+ count += 1;
35
+ return count;
36
+ }
37
+ /**
38
+ * Gathers drawn stars into molecules. A dimmed star is scenery and never
39
+ * turns solid.
40
+ *
41
+ * @param starred - The stars as drawn.
42
+ * @param keyOf - The molecule a node belongs to, or null for none.
43
+ */
44
+ gather(starred, keyOf) {
45
+ for (const entry of starred) {
46
+ if (entry.dim)
47
+ continue;
48
+ const key = keyOf(entry.id);
49
+ if (key === null)
50
+ continue;
51
+ let group = this.groups.get(key);
52
+ if (group === undefined) {
53
+ group = { entries: [], center: new THREE.Vector3(), maxRadius: 0, mix: 0, target: 0, meshes: [], tubes: null, threadSegments: [] };
54
+ this.groups.set(key, group);
55
+ }
56
+ group.entries.push(entry);
57
+ group.maxRadius = Math.max(group.maxRadius, entry.radius);
58
+ }
59
+ for (const group of this.groups.values()) {
60
+ for (const entry of group.entries)
61
+ group.center.add(entry.position);
62
+ group.center.divideScalar(Math.max(1, group.entries.length));
63
+ }
64
+ }
65
+ /**
66
+ * Notes that a thread belongs to a molecule, so it fades as the
67
+ * molecule turns solid.
68
+ *
69
+ * @param key - The molecule.
70
+ * @param segment - The thread's segment.
71
+ */
72
+ thread_note(key, segment) {
73
+ this.groups.get(key)?.threadSegments.push(segment);
74
+ }
75
+ /**
76
+ * Steps the hand-off once a frame.
77
+ *
78
+ * @param view - The camera's view of the field (camera inverse × the field's world).
79
+ * @param perUnit - Pixels per unit of size at unit depth.
80
+ * @param now - This frame's time.
81
+ */
82
+ step(view, perUnit, now) {
83
+ if (this.groups.size === 0)
84
+ return;
85
+ const dt = this.lastAt === 0 ? 0 : Math.min(100, now - this.lastAt);
86
+ this.lastAt = now;
87
+ const v = view.elements;
88
+ for (const group of this.groups.values()) {
89
+ // Its nearest sphere decides: a sprawling molecule with one sphere at
90
+ // the camera turns solid, rather than leaving that sphere a swelling star.
91
+ let depth = Infinity;
92
+ for (const entry of group.entries) {
93
+ const p = entry.position;
94
+ const d = -(v[2] * p.x + v[6] * p.y + v[10] * p.z + v[14]);
95
+ if (d > 0 && d < depth)
96
+ depth = d;
97
+ }
98
+ const px = depth === Infinity ? 0 : (2 * group.maxRadius * perUnit) / depth;
99
+ if (group.target === 0 && px > HANDOFF_SOLID_PX)
100
+ group.target = 1;
101
+ else if (group.target === 1 && px < HANDOFF_STAR_PX)
102
+ group.target = 0;
103
+ if (group.mix === group.target)
104
+ continue;
105
+ const step = dt === 0 ? 1 : dt / HANDOFF_FADE_MS;
106
+ group.mix = group.target > group.mix ? Math.min(1, group.mix + step) : Math.max(0, group.mix - step);
107
+ if (group.mix > 0 && group.meshes.length === 0)
108
+ this.solid_build(group);
109
+ for (const mesh of group.meshes) {
110
+ if (mesh.material instanceof THREE.MeshStandardMaterial)
111
+ mesh.material.opacity = group.mix;
112
+ }
113
+ if (group.tubes !== null && group.tubes.material instanceof THREE.ShaderMaterial) {
114
+ const opacity = group.tubes.material.uniforms['opacity'];
115
+ if (opacity !== undefined)
116
+ opacity.value = group.mix;
117
+ }
118
+ this.host.stars.stars_fade(group.entries, 1 - group.mix);
119
+ this.host.stars.threads_fade(group.threadSegments, 1 - group.mix);
120
+ if (group.mix === 0)
121
+ this.solid_release(group);
122
+ }
123
+ this.host.stars.flush();
124
+ }
125
+ /** Forgets everything: the scene is being redrawn. */
126
+ clear() {
127
+ this.groups = new Map();
128
+ }
129
+ /** Draws a molecule's spheres and tubes for its time as solid. */
130
+ solid_build(group) {
131
+ const members = new Set(group.entries.map((entry) => entry.id));
132
+ for (const entry of group.entries) {
133
+ const look = this.host.look(entry.id);
134
+ if (look === undefined)
135
+ continue;
136
+ group.meshes.push(this.host.spheres.sphere_add(entry.id, look.position, look.radius, { color: look.color, fade: group.mix }));
137
+ }
138
+ this.host.tubes.build(group, group.entries.map((entry) => entry.id), members);
139
+ }
140
+ /** Lets a molecule's spheres and tubes go once it is stars again. */
141
+ solid_release(group) {
142
+ for (const mesh of group.meshes)
143
+ this.host.spheres.remove(mesh);
144
+ if (group.tubes !== null) {
145
+ this.host.tubes.release(group.tubes);
146
+ group.tubes = null;
147
+ }
148
+ group.meshes = [];
149
+ }
150
+ }
151
+ //# sourceMappingURL=handoffField.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handoffField.js","sourceRoot":"","sources":["../../src/draw/handoffField.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAsClF,wDAAwD;AACxD,MAAM,OAAO,YAAY;IACN,IAAI,CAAc;IAC3B,MAAM,GAA8B,IAAI,GAAG,EAAE,CAAC;IAC9C,MAAM,GAAW,CAAC,CAAC;IAE3B;;OAEG;IACH,YAAY,IAAiB;QAC3B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,oCAAoC;IAC7B,IAAI;QACT,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;IAC1B,CAAC;IAED,2CAA2C;IACpC,UAAU;QACf,IAAI,KAAK,GAAW,CAAC,CAAC;QACtB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;YAAE,IAAI,KAAK,CAAC,GAAG,GAAG,CAAC;gBAAE,KAAK,IAAI,CAAC,CAAC;QACxE,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;;;OAMG;IACI,MAAM,CAAC,OAAiC,EAAE,KAAoC;QACnF,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,KAAK,CAAC,GAAG;gBAAE,SAAS;YACxB,MAAM,GAAG,GAAkB,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC3C,IAAI,GAAG,KAAK,IAAI;gBAAE,SAAS;YAC3B,IAAI,KAAK,GAA6B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC3D,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,KAAK,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC;gBACnI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YAC9B,CAAC;YACD,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1B,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QAC5D,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;YACzC,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,OAAO;gBAAE,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YACpE,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACI,WAAW,CAAC,GAAW,EAAE,OAAe;QAC7C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrD,CAAC;IAED;;;;;;OAMG;IACI,IAAI,CAAC,IAAmB,EAAE,OAAe,EAAE,GAAW;QAC3D,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC;YAAE,OAAO;QACnC,MAAM,EAAE,GAAW,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5E,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC;QAClB,MAAM,CAAC,GAAa,IAAI,CAAC,QAAQ,CAAC;QAClC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;YACzC,sEAAsE;YACtE,2EAA2E;YAC3E,IAAI,KAAK,GAAW,QAAQ,CAAC;YAC7B,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;gBAClC,MAAM,CAAC,GAAkB,KAAK,CAAC,QAAQ,CAAC;gBACxC,MAAM,CAAC,GAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAE,CAAC,CAAC;gBACvE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK;oBAAE,KAAK,GAAG,CAAC,CAAC;YACpC,CAAC;YACD,MAAM,EAAE,GAAW,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,SAAS,GAAG,OAAO,CAAC,GAAG,KAAK,CAAC;YACpF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,EAAE,GAAG,gBAAgB;gBAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;iBAC7D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,EAAE,GAAG,eAAe;gBAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;YACtE,IAAI,KAAK,CAAC,GAAG,KAAK,KAAK,CAAC,MAAM;gBAAE,SAAS;YACzC,MAAM,IAAI,GAAW,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,eAAe,CAAC;YACzD,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;YACrG,IAAI,KAAK,CAAC,GAAG,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;gBAAE,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YACxE,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;gBAChC,IAAI,IAAI,CAAC,QAAQ,YAAY,KAAK,CAAC,oBAAoB;oBAAE,IAAI,CAAC,QAAQ,CAAC,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC;YAC7F,CAAC;YACD,IAAI,KAAK,CAAC,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,QAAQ,YAAY,KAAK,CAAC,cAAc,EAAE,CAAC;gBACjF,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;gBACzD,IAAI,OAAO,KAAK,SAAS;oBAAE,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC;YACvD,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;YACzD,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;YAClE,IAAI,KAAK,CAAC,GAAG,KAAK,CAAC;gBAAE,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACjD,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IAC1B,CAAC;IAED,sDAAsD;IAC/C,KAAK;QACV,IAAI,CAAC,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;IAC1B,CAAC;IAED,kEAAkE;IAC1D,WAAW,CAAC,KAAmB;QACrC,MAAM,OAAO,GAAgB,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAgB,EAAU,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;QAChG,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAClC,MAAM,IAAI,GAA4B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC/D,IAAI,IAAI,KAAK,SAAS;gBAAE,SAAS;YACjC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAChI,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAgB,EAAU,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;IACnG,CAAC;IAED,qEAAqE;IAC7D,aAAa,CAAC,KAAmB;QACvC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,MAAM;YAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAChE,IAAI,KAAK,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;YACzB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACrC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;QACrB,CAAC;QACD,KAAK,CAAC,MAAM,GAAG,EAAE,CAAC;IACpB,CAAC;CACF"}