@seatlayer/core 0.31.0 → 0.33.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.
@@ -1,4 +1,4 @@
1
- import { C as ChartDoc, E as ExpandedSeat } from '../types-CG2pEDoI.cjs';
1
+ import { C as ChartDoc, E as ExpandedSeat } from '../types-DO_J5DtX.cjs';
2
2
 
3
3
  /**
4
4
  * Dirty-flag render loop. A frame is drawn only while the camera is moving /
@@ -27,6 +27,20 @@ declare const STRUCTURE: {
27
27
  readonly ground: RGB;
28
28
  readonly tierTop: RGB;
29
29
  readonly tierWall: RGB;
30
+ /**
31
+ * The lit performance surface.
32
+ *
33
+ * This was [0.42, 0.36, 0.26] and commented "slightly emissive read", which it
34
+ * was not — under the scene's rig it resolved to a mid-brown slab, and from a
35
+ * seat the stage was the DIMMEST large surface in a dark hall. That is exactly
36
+ * backwards: the stage is the one place in a venue with light pointed at it,
37
+ * and it is what a buyer's eye should land on when they arrive at their seat.
38
+ *
39
+ * Bright and warm enough to hold that role against the surrounding structure,
40
+ * which sits around 0.24. An authored `fill` still tints it (see `buildShape`),
41
+ * so an organizer's own stage colour survives — it is just no longer lit like
42
+ * a basement.
43
+ */
30
44
  readonly stageTop: RGB;
31
45
  readonly stageWall: RGB;
32
46
  readonly decorTop: RGB;
@@ -160,6 +174,15 @@ interface SeatInstanceData {
160
174
  iPosition: Float32Array;
161
175
  /** float per instance: index into the seat-state colour LUT. */
162
176
  iState: Float32Array;
177
+ /**
178
+ * vec3 per instance: the seat's CATEGORY colour, used while it is available.
179
+ *
180
+ * 2D fills a free seat with its category colour and only overrides it once the
181
+ * seat is held/sold/selected. 3D used one flat green for every available seat,
182
+ * which threw away the price-tier read on switching views and made a full
183
+ * house look like a status map instead of a venue.
184
+ */
185
+ iCategory: Float32Array;
163
186
  /**
164
187
  * float per instance: the largest world radius this dot may take, metres.
165
188
  *
@@ -188,10 +211,41 @@ interface SeatInstanceData {
188
211
  iRing: Float32Array;
189
212
  /** float per instance: owning floor index, for per-floor isolation. */
190
213
  iFloor: Float32Array;
214
+ /**
215
+ * float per instance: facing yaw in radians, for the near-field chair mesh.
216
+ *
217
+ * A billboard dot has no front, so nothing here ever needed a direction. A
218
+ * chair does, and getting it wrong is worse than drawing nothing — a row of
219
+ * seats with their backs to the stage reads as a mistake immediately.
220
+ *
221
+ * Left at zero by this builder and filled by `sceneModel`, which is the layer
222
+ * that knows what each seat FACES (its floor's focal point). Direct callers
223
+ * and tests that build instances without a scene get zeros, which is a
224
+ * well-defined "facing +Z" rather than an undefined attribute.
225
+ */
226
+ iYaw: Float32Array;
227
+ /**
228
+ * float per instance: half-width of this seat's near-field CHAIR, world metres.
229
+ *
230
+ * Deliberately not `iMaxRadius`. That value is the dot's ceiling — conservative
231
+ * by design so round dots stay visually apart, and clamped to
232
+ * SEAT_DOT_RADIUS_M on top of that. Sizing a chair from it gave 0.34 m chairs
233
+ * under 0.95 m backs: an aspect ratio near 3:1, which reads as a headstone.
234
+ * Real seats very nearly touch. See `chairHalfWidth`.
235
+ */
236
+ iChairWidth: Float32Array;
191
237
  /** seatId → instance index (drives targeted availability updates). */
192
238
  idToIndex: Map<string, number>;
193
239
  }
194
240
 
241
+ /** Axis-aligned stage footprint in world metres. */
242
+ interface StageBounds {
243
+ cx: number;
244
+ cz: number;
245
+ y: number;
246
+ halfX: number;
247
+ halfZ: number;
248
+ }
195
249
  /**
196
250
  * A navigable zone — the venue's own top-level grouping (Orchestra, Lower Bowl,
197
251
  * Hall A), resolved for camera framing and for the section/zone LOD rung.
@@ -263,6 +317,16 @@ interface SceneModel {
263
317
  focalWorld: [number, number, number];
264
318
  /** The venue's zones, in authored order. Empty when the chart has none. */
265
319
  zones: SceneZone[];
320
+ /**
321
+ * Stage footprints in world metres.
322
+ *
323
+ * Collected for stage lighting, which is not shipped: additive cones were
324
+ * built, placed correctly and still could not be read from a seat (see
325
+ * `git log` for `stageLight.ts`). The bounds stay because they are cheap,
326
+ * correct, and exactly what a second attempt needs — the geometry was never
327
+ * the hard part, the technique was.
328
+ */
329
+ stages: StageBounds[];
266
330
  /** Seated sections, in authored order — the navigable middle rung. */
267
331
  sections: SceneSection[];
268
332
  /**
@@ -302,6 +366,21 @@ declare function buildSceneModel(input: SceneModelInput): SceneModel;
302
366
  */
303
367
  interface SeatView {
304
368
  url: string;
369
+ /**
370
+ * True when `url` is a SYNTHESISED panorama rather than a real photograph.
371
+ *
372
+ * It decides which of two very different things the buyer gets, so the caller
373
+ * must say rather than the renderer guess. A generated equirect is a picture
374
+ * of a 3D scene the renderer already has: at 2048×1024 it covers 106° of
375
+ * horizontal view in ~600 source pixels, which a 3072-device-pixel viewport
376
+ * magnifies FIVE times, and no amount of art survives that. So a generated
377
+ * view is not drawn as an image at all — the camera simply looks around the
378
+ * real scene, which has no resolution ceiling.
379
+ *
380
+ * A real photo has no such substitute and goes on the sphere, where a 5760 or
381
+ * 8192-wide capture has three to four times the detail to give.
382
+ */
383
+ generated?: boolean;
305
384
  /** Bearing (deg, 0 = facing the focal/stage) the panorama should open centred
306
385
  * on, to match the camera's final yaw. Default 0 (both face the stage). */
307
386
  initialBearingDeg?: number;
@@ -1,4 +1,4 @@
1
- import { C as ChartDoc, E as ExpandedSeat } from '../types-CG2pEDoI.js';
1
+ import { C as ChartDoc, E as ExpandedSeat } from '../types-DO_J5DtX.js';
2
2
 
3
3
  /**
4
4
  * Dirty-flag render loop. A frame is drawn only while the camera is moving /
@@ -27,6 +27,20 @@ declare const STRUCTURE: {
27
27
  readonly ground: RGB;
28
28
  readonly tierTop: RGB;
29
29
  readonly tierWall: RGB;
30
+ /**
31
+ * The lit performance surface.
32
+ *
33
+ * This was [0.42, 0.36, 0.26] and commented "slightly emissive read", which it
34
+ * was not — under the scene's rig it resolved to a mid-brown slab, and from a
35
+ * seat the stage was the DIMMEST large surface in a dark hall. That is exactly
36
+ * backwards: the stage is the one place in a venue with light pointed at it,
37
+ * and it is what a buyer's eye should land on when they arrive at their seat.
38
+ *
39
+ * Bright and warm enough to hold that role against the surrounding structure,
40
+ * which sits around 0.24. An authored `fill` still tints it (see `buildShape`),
41
+ * so an organizer's own stage colour survives — it is just no longer lit like
42
+ * a basement.
43
+ */
30
44
  readonly stageTop: RGB;
31
45
  readonly stageWall: RGB;
32
46
  readonly decorTop: RGB;
@@ -160,6 +174,15 @@ interface SeatInstanceData {
160
174
  iPosition: Float32Array;
161
175
  /** float per instance: index into the seat-state colour LUT. */
162
176
  iState: Float32Array;
177
+ /**
178
+ * vec3 per instance: the seat's CATEGORY colour, used while it is available.
179
+ *
180
+ * 2D fills a free seat with its category colour and only overrides it once the
181
+ * seat is held/sold/selected. 3D used one flat green for every available seat,
182
+ * which threw away the price-tier read on switching views and made a full
183
+ * house look like a status map instead of a venue.
184
+ */
185
+ iCategory: Float32Array;
163
186
  /**
164
187
  * float per instance: the largest world radius this dot may take, metres.
165
188
  *
@@ -188,10 +211,41 @@ interface SeatInstanceData {
188
211
  iRing: Float32Array;
189
212
  /** float per instance: owning floor index, for per-floor isolation. */
190
213
  iFloor: Float32Array;
214
+ /**
215
+ * float per instance: facing yaw in radians, for the near-field chair mesh.
216
+ *
217
+ * A billboard dot has no front, so nothing here ever needed a direction. A
218
+ * chair does, and getting it wrong is worse than drawing nothing — a row of
219
+ * seats with their backs to the stage reads as a mistake immediately.
220
+ *
221
+ * Left at zero by this builder and filled by `sceneModel`, which is the layer
222
+ * that knows what each seat FACES (its floor's focal point). Direct callers
223
+ * and tests that build instances without a scene get zeros, which is a
224
+ * well-defined "facing +Z" rather than an undefined attribute.
225
+ */
226
+ iYaw: Float32Array;
227
+ /**
228
+ * float per instance: half-width of this seat's near-field CHAIR, world metres.
229
+ *
230
+ * Deliberately not `iMaxRadius`. That value is the dot's ceiling — conservative
231
+ * by design so round dots stay visually apart, and clamped to
232
+ * SEAT_DOT_RADIUS_M on top of that. Sizing a chair from it gave 0.34 m chairs
233
+ * under 0.95 m backs: an aspect ratio near 3:1, which reads as a headstone.
234
+ * Real seats very nearly touch. See `chairHalfWidth`.
235
+ */
236
+ iChairWidth: Float32Array;
191
237
  /** seatId → instance index (drives targeted availability updates). */
192
238
  idToIndex: Map<string, number>;
193
239
  }
194
240
 
241
+ /** Axis-aligned stage footprint in world metres. */
242
+ interface StageBounds {
243
+ cx: number;
244
+ cz: number;
245
+ y: number;
246
+ halfX: number;
247
+ halfZ: number;
248
+ }
195
249
  /**
196
250
  * A navigable zone — the venue's own top-level grouping (Orchestra, Lower Bowl,
197
251
  * Hall A), resolved for camera framing and for the section/zone LOD rung.
@@ -263,6 +317,16 @@ interface SceneModel {
263
317
  focalWorld: [number, number, number];
264
318
  /** The venue's zones, in authored order. Empty when the chart has none. */
265
319
  zones: SceneZone[];
320
+ /**
321
+ * Stage footprints in world metres.
322
+ *
323
+ * Collected for stage lighting, which is not shipped: additive cones were
324
+ * built, placed correctly and still could not be read from a seat (see
325
+ * `git log` for `stageLight.ts`). The bounds stay because they are cheap,
326
+ * correct, and exactly what a second attempt needs — the geometry was never
327
+ * the hard part, the technique was.
328
+ */
329
+ stages: StageBounds[];
266
330
  /** Seated sections, in authored order — the navigable middle rung. */
267
331
  sections: SceneSection[];
268
332
  /**
@@ -302,6 +366,21 @@ declare function buildSceneModel(input: SceneModelInput): SceneModel;
302
366
  */
303
367
  interface SeatView {
304
368
  url: string;
369
+ /**
370
+ * True when `url` is a SYNTHESISED panorama rather than a real photograph.
371
+ *
372
+ * It decides which of two very different things the buyer gets, so the caller
373
+ * must say rather than the renderer guess. A generated equirect is a picture
374
+ * of a 3D scene the renderer already has: at 2048×1024 it covers 106° of
375
+ * horizontal view in ~600 source pixels, which a 3072-device-pixel viewport
376
+ * magnifies FIVE times, and no amount of art survives that. So a generated
377
+ * view is not drawn as an image at all — the camera simply looks around the
378
+ * real scene, which has no resolution ceiling.
379
+ *
380
+ * A real photo has no such substitute and goes on the sphere, where a 5760 or
381
+ * 8192-wide capture has three to four times the detail to give.
382
+ */
383
+ generated?: boolean;
305
384
  /** Bearing (deg, 0 = facing the focal/stage) the panorama should open centred
306
385
  * on, to match the camera's final yaw. Default 0 (both face the stage). */
307
386
  initialBearingDeg?: number;