@fxi/zartigl 0.10.0 → 0.10.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/dist/engine.d.ts CHANGED
@@ -193,6 +193,22 @@ export declare function fadeToFrames(fade: number): number;
193
193
  /** Per-frame trail opacity multiplier for a 0–1 `fade`. */
194
194
  export declare function fadeToOpacity(fade: number): number;
195
195
 
196
+ declare interface FieldMeta {
197
+ min: number;
198
+ max: number;
199
+ unit: string;
200
+ time: string;
201
+ depth?: number;
202
+ }
203
+
204
+ /** Shader uniforms a field binds: two time steps, their mix, the bounds. */
205
+ export declare interface FieldUniforms {
206
+ a: string;
207
+ b: string;
208
+ mix: string;
209
+ bounds: string;
210
+ }
211
+
196
212
  /**
197
213
  * Short display label of a CF / UDUNITS `units` attribute, for legends and
198
214
  * query values: "mmol m-3" → "mmol/m³", "degree_Celsius_weeks" → "°C-weeks".
@@ -342,6 +358,103 @@ export declare interface GeoVideoChunkSpan {
342
358
  end: number;
343
359
  }
344
360
 
361
+ /** The playhead shared by the layers: time, play state and speeds. */
362
+ export declare class GeoVideoClock {
363
+ private readonly onPlaying;
364
+ private time;
365
+ private endFraction;
366
+ /** Playhead, epoch ms. Assigning it also resets a terminal step's hold. */
367
+ get ms(): number;
368
+ set ms(value: number);
369
+ /** Playback held, e.g. while a timeline thumb is held. */
370
+ held: boolean;
371
+ private playingValue;
372
+ constructor(playing: boolean, onPlaying: (playing: boolean) => void);
373
+ get playing(): boolean;
374
+ setPlaying(playing: boolean): void;
375
+ /** Playing and not held. */
376
+ get advancing(): boolean;
377
+ /**
378
+ * Advance in step units, including irregular timelines. Returns true at a
379
+ * non-looping end. holdLastStep gives the final sample a full step's duration.
380
+ */
381
+ advance(dt: number, times: ArrayLike<number>, stepsPerSecond: number, range?: readonly [number, number], loop?: boolean, holdLastStep?: boolean): boolean;
382
+ }
383
+
384
+ /**
385
+ * GeoVideo frames as textures, decoded ahead of the playhead: vector frames
386
+ * as float (u, v, validity, 0), scalar frames as the browser decodes them,
387
+ * turned into values in the shader by zartigl's GEOVIDEO_SCALAR_GLSL (with a
388
+ * static mask texture), the decoder of its MapLibre layer. Binds two
389
+ * consecutive time steps and their mix under VELOCITY_UNIFORMS for a vector
390
+ * field, TINT_UNIFORMS for a scalar one.
391
+ */
392
+ export declare class GeoVideoField {
393
+ private readonly gl;
394
+ readonly manifest: GeoVideoManifest;
395
+ private readonly options;
396
+ readonly times: number[];
397
+ readonly bounds: GeoVideoBounds;
398
+ /** Vector field (particles); false for a scalar one (raster or tint). */
399
+ readonly vector: boolean;
400
+ private readonly source;
401
+ private readonly uniforms;
402
+ private readonly textures;
403
+ private readonly pending;
404
+ /** Static validity of a scalar field, uploaded with its first frame. */
405
+ private mask;
406
+ private pair;
407
+ private destroyed;
408
+ private linearFilter;
409
+ uploadedFrames: number;
410
+ lastUploadDurationMs: number;
411
+ get currentPair(): readonly [WebGLTexture, WebGLTexture, number] | null;
412
+ constructor(gl: WebGL2RenderingContext, manifest: GeoVideoManifest, options?: GeoVideoFieldOptions);
413
+ /** Fixed catalog color domain of a scalar field. */
414
+ get domain(): [number, number];
415
+ /** Top of the color ramp and of the particle speed normalization. */
416
+ get maxSpeed(): number;
417
+ /** Resolves once the step at `ms` is uploaded. */
418
+ prime(ms: number): Promise<void>;
419
+ /** True once the frames interpolated at `ms` are uploaded. */
420
+ ready(ms: number): boolean;
421
+ /**
422
+ * Latest wins while scrubbing: drop queued decodes outside the frames at
423
+ * `ms`, then request those first.
424
+ */
425
+ focus(ms: number): void;
426
+ /**
427
+ * Bracketing textures and their mix, retaining the last complete pair
428
+ * while a requested frame decodes.
429
+ */
430
+ sample(ms: number, interpolate?: boolean): readonly [WebGLTexture, WebGLTexture, number] | null;
431
+ /** Switch spatial filtering without changing the decoded-step cache. */
432
+ setFilter(linear: boolean): void;
433
+ get maskTexture(): WebGLTexture | null;
434
+ get cachedFrames(): number;
435
+ bind(program: GeoVideoProgram, ms: number, unit?: number): boolean;
436
+ destroy(): void;
437
+ private request;
438
+ private uploadPreservingState;
439
+ private upload;
440
+ /** The source's mask, loaded with its first frame, as an R8 texture. */
441
+ private uploadMask;
442
+ /** A bound, linearly filtered texture over the field grid. */
443
+ private gridTexture;
444
+ /** Keep a small window around the playhead. */
445
+ private evict;
446
+ }
447
+
448
+ export declare interface GeoVideoFieldOptions {
449
+ /** Repeat global grids in longitude; false for an inset MapLibre grid. */
450
+ repeatLongitude?: boolean;
451
+ /** Play the media frames of a single-date snapshot; times then follow its media cadence. */
452
+ animateSnapshot?: boolean;
453
+ onError?: (error: unknown) => void;
454
+ /** A decoded step was uploaded; a paused renderer can redraw it. */
455
+ onReady?: () => void;
456
+ }
457
+
345
458
  /** A scalar frame image (decoded on the GPU) or u/v components (NaN invalid). */
346
459
  export declare type GeoVideoFrameData = GeoVideoScalarFrame | GeoVideoVectorFrame;
347
460
 
@@ -524,6 +637,101 @@ export declare interface GeoVideoManifest {
524
637
  };
525
638
  }
526
639
 
640
+ /** Render-driven GeoVideo playback and chunk handoff, shared by both MapLibre adapters. */
641
+ export declare class GeoVideoPlayback {
642
+ private readonly repaint;
643
+ private readonly emit;
644
+ field: GeoVideoField | null;
645
+ manifest: GeoVideoManifest | null;
646
+ private gl;
647
+ private pendingField;
648
+ private standby;
649
+ private awaitingNext;
650
+ private playOnReady;
651
+ private loop;
652
+ private playbackRate;
653
+ private stepsPerSecond?;
654
+ private requestedTime;
655
+ private requestedTimeRange?;
656
+ private timeRange;
657
+ private lastTick;
658
+ private lastStepTime;
659
+ private seekId;
660
+ private seeking;
661
+ private failed;
662
+ private exactTime;
663
+ private endEmitted;
664
+ private destroyed;
665
+ private resumePlayback;
666
+ private readonly clock;
667
+ constructor(options: GeoVideoPlaybackOptions, repaint: () => void, emit: <K extends keyof GeoVideoPlaybackEvents>(event: K, ...args: Parameters<GeoVideoPlaybackEvents[K]>) => void);
668
+ load(gl: WebGL2RenderingContext, manifest: GeoVideoManifest): Promise<void>;
669
+ sample(now: number): readonly [WebGLTexture, WebGLTexture, number] | null;
670
+ get time(): number;
671
+ get preloadedMediaUrl(): string | undefined;
672
+ setStepsPerSecond(value: number): void;
673
+ suspend(): void;
674
+ resume(): void;
675
+ destroy(): void;
676
+ private tick;
677
+ setTime(time: string | number): void;
678
+ /** Load the requested step first; stale seeks and swaps cannot replace it. */
679
+ private prepare;
680
+ /** Keep the outgoing pair until the incoming chunk's requested step is ready. */
681
+ replaceManifest(manifest: GeoVideoManifest, options?: GeoVideoPlaybackReplaceOptions): boolean;
682
+ /** Decode the next chunk ahead of its swap, including its static mask. */
683
+ preloadManifest(manifest: GeoVideoManifest, options?: GeoVideoPlaybackReplaceOptions): boolean;
684
+ private discardStandby;
685
+ /** Clamped time range of a compatible replacement, else null. */
686
+ private replacementTimeRange;
687
+ play(): Promise<void>;
688
+ pause(): void;
689
+ isPlaying(): boolean;
690
+ private reachEnd;
691
+ setLoop(loop: boolean): void;
692
+ setPlaybackRate(rate: number): void;
693
+ setTimeRange(range: [number, number]): void;
694
+ private playbackRange;
695
+ private createField;
696
+ private reportError;
697
+ }
698
+
699
+ export declare type GeoVideoPlaybackEvents = {
700
+ loading: () => void;
701
+ loaded: (meta: FieldMeta) => void;
702
+ error: (error: Error) => void;
703
+ status: (status: ZartiglStatus) => void;
704
+ timeChange: (time: number) => void;
705
+ playbackChange: (playing: boolean) => void;
706
+ /** Playback reached the end of the timeline without looping. */
707
+ playbackEnd: () => void;
708
+ };
709
+
710
+ export declare interface GeoVideoPlaybackOptions {
711
+ time?: string | number;
712
+ timeRange?: [number, number];
713
+ autoplay?: boolean;
714
+ loop?: boolean;
715
+ playbackRate?: number;
716
+ stepsPerSecond?: number;
717
+ }
718
+
719
+ export declare interface GeoVideoPlaybackReplaceOptions {
720
+ time?: number;
721
+ stepsPerSecond?: number;
722
+ timeRange?: [number, number];
723
+ loop?: boolean;
724
+ playbackRate?: number;
725
+ }
726
+
727
+ /** Texture and uniform binding supplied by the renderer. */
728
+ export declare interface GeoVideoProgram {
729
+ texture(name: string, unit: number, texture: WebGLTexture): void;
730
+ float(name: string, value: number): void;
731
+ vec2(name: string, x: number, y: number): void;
732
+ vec4(name: string, value: readonly number[]): void;
733
+ }
734
+
527
735
  declare interface GeoVideoRangeTimeline {
528
736
  kind: "range";
529
737
  dateStart: string;
@@ -809,11 +1017,20 @@ export declare function resolveColorRamp(input: ColorRampInput, options?: {
809
1017
 
810
1018
  export declare type ScalarColorDomain = [number, number];
811
1019
 
1020
+ /** Time at a fractional step, clamped to the available samples. */
1021
+ export declare function stepTime(times: ArrayLike<number>, step: number): number;
1022
+
812
1023
  declare type StyleRenderMode = "particles" | "raster" | "raster+particles";
813
1024
 
814
1025
  /** `anchor` minus an ISO 8601 duration, calendar months and years in UTC. */
815
1026
  export declare function subtractIsoDuration(anchor: number, duration: string): number;
816
1027
 
1028
+ /** Index of the step at or before `ms` and the fraction toward the next. */
1029
+ export declare function timeBracket(times: ArrayLike<number>, ms: number): {
1030
+ index: number;
1031
+ fraction: number;
1032
+ };
1033
+
817
1034
  /**
818
1035
  * Time windows shared by zartigl and the renderers built on its engine: a
819
1036
  * fixed `start`/`end`, either side open, or the `trailing` ISO 8601 duration
@@ -835,6 +1052,9 @@ export declare type TimeRange = {
835
1052
  */
836
1053
  export declare function timeRangeBounds(range: TimeRange, [sourceMin, sourceMax]: readonly [number, number]): [number, number];
837
1054
 
1055
+ /** Fractional step corresponding to a time. */
1056
+ export declare function timeStep(times: ArrayLike<number>, ms: number): number;
1057
+
838
1058
  /**
839
1059
  * Camera-aware per-frame fade opacity: eases toward a short retention while
840
1060
  * the camera moves, then back to the configured one. Smoothstep avoids
@@ -872,6 +1092,28 @@ declare type VectorFieldSource = Pick<ZarrSource, "init" | "cancelAll" | "getCoo
872
1092
  getValueDomain?(): number;
873
1093
  };
874
1094
 
1095
+ /** Physical velocity/validity decoding and temporal blending; GLSL ES 1.0 and 3.0. */
1096
+ export declare const VELOCITY_BLEND_GLSL: string;
1097
+
1098
+ /** Interleaves masked u/v planes into (u, v, validity, 0) texels. */
1099
+ export declare function velocityTexels(frame: GeoVideoVectorFrame): Float32Array;
1100
+
1101
+ /** One bound velocity texture and the physical range used to decode it. */
1102
+ export declare interface VelocityTextureField {
1103
+ unit: number;
1104
+ min: [number, number];
1105
+ max: [number, number];
1106
+ /** Physical (u, v, validity, 0); otherwise normalized (u, v, 0, validity). */
1107
+ physical?: boolean;
1108
+ northToSouth?: boolean;
1109
+ }
1110
+
1111
+ export declare interface VelocityTexturePair {
1112
+ a: VelocityTextureField;
1113
+ b: VelocityTextureField;
1114
+ mix: number;
1115
+ }
1116
+
875
1117
  /** `vec3 applyVibrance(vec3 c, float v)`; GLSL ES 1.0 and 3.0. */
876
1118
  export declare const VIBRANCE_GLSL: string;
877
1119
 
@@ -1021,4 +1263,28 @@ declare interface ZarrVerticalDimension {
1021
1263
  values: number[];
1022
1264
  }
1023
1265
 
1266
+ declare type ZartiglStatus = {
1267
+ phase: "metadata";
1268
+ } | {
1269
+ phase: "fetching";
1270
+ time: number;
1271
+ completed: number;
1272
+ total: number;
1273
+ } | {
1274
+ phase: "rendering";
1275
+ time: number;
1276
+ } | {
1277
+ phase: "ready";
1278
+ time: number;
1279
+ } | {
1280
+ phase: "blocked";
1281
+ time: number;
1282
+ statuses: number[];
1283
+ message: string;
1284
+ } | {
1285
+ phase: "error";
1286
+ time?: number;
1287
+ error: Error;
1288
+ };
1289
+
1024
1290
  export { }
package/dist/engine.js CHANGED
@@ -1,6 +1,14 @@
1
- import { I as i, J as u, K as m, G as v, T as g, L as f, M as x, b as _, N as p, c as V, O as G, P as C, l as S, z as b, E as R, Q as O, R as A, n as L, t as h, A as F, B as I, D as T, m as y, C as D, S as k, U as B, V as E, W as w, p as M, X as N, F as P, Y as z, H as U, v as H } from "./geovideo-index-BJjE_fgO.js";
2
- import { B as J, C as Q, e as W, b as X, d as Y, c as j, g as q, i as Z, a as $, r as aa } from "./backdrop-DctkJ45Q.js";
3
- var a = `vec3 applyVibrance(vec3 c, float v) {
1
+ import { I as u, J as v, K as f, L as x, G as g, M as _, N as V, T as p, O as G, P as C, b as S, Q as b, c as y, R as L, S as R, l as O, z as h, D as A, U as T, V as k, n as I, u as D, q as F, A as B, C as E, m as w, B as N, W as P, X as z, Y as M, Z as U, o as H, _ as K, $ as Y, a0 as q, E as J, a1 as Q, a2 as W, H as X, v as Z, a3 as $ } from "./geovideo-index-BqOLqzgA.js";
2
+ import { B as ee, C as ae, e as oe, b as ne, d as re, c as ce, g as te, i as se, a as ie, r as le } from "./backdrop-DctkJ45Q.js";
3
+ var e = `vec3 velocityValue(vec4 texel, vec2 minimum, vec2 maximum, float physical) {
4
+ if (physical > 0.5) return texel.xyz;
5
+ return vec3(mix(minimum, maximum, texel.rg), texel.a);
6
+ }
7
+
8
+ vec3 blendVelocity(vec3 a, vec3 b, float fraction) {
9
+ if (fraction <= 0.0) return a;
10
+ return mix(a, b, fraction);
11
+ }`, a = `vec3 applyVibrance(vec3 c, float v) {
4
12
  float mx = max(c.r, max(c.g, c.b));
5
13
  float mn = min(c.r, min(c.g, c.b));
6
14
  float boost = v * (1.0 - (mx - mn));
@@ -21,7 +29,7 @@ vec3 gradeColor(vec3 c, vec4 g) {
21
29
 
22
30
  c = mix(c, c * c * (3.0 - 2.0 * c), g.y);
23
31
  return clamp(applyVibrance(c, g.z), 0.0, 1.0);
24
- }`, e = `uniform vec2 u_code_range;
32
+ }`, o = `uniform vec2 u_code_range;
25
33
  uniform vec2 u_value_range;
26
34
  uniform float u_scalar_transfer;
27
35
 
@@ -33,7 +41,7 @@ float geoVideoScalarValue(float r) {
33
41
  float code = geoVideoScalarCode(r);
34
42
  float t = mix(code, (pow(10.0, code) - 1.0) / 9.0, u_scalar_transfer);
35
43
  return mix(u_value_range.x, u_value_range.y, t);
36
- }`, o = `uint pcg(uint v) {
44
+ }`, n = `uint pcg(uint v) {
37
45
  uint state = v * 747796405u + 2891336453u;
38
46
  uint word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u;
39
47
  return (word >> 22u) ^ word;
@@ -48,54 +56,62 @@ float random(uvec3 v) {
48
56
  float luma = dot(c, vec3(0.299, 0.587, 0.114));
49
57
  return mix(vec3(luma), c, 1.0 + boost);
50
58
  }`;
51
- const n = r, c = a, t = o, s = e;
59
+ const c = r, t = a, s = n, i = o, l = e;
52
60
  export {
53
- J as BACKDROP_OFF,
54
- c as COLOR_GRADE_GLSL,
55
- Q as COLOR_GRADE_OFF,
56
- W as COLOR_GRADE_VIBRANT,
57
- s as GEOVIDEO_SCALAR_GLSL,
58
- i as GeoVideoArchiveSource,
59
- u as GeoVideoFrameSource,
60
- m as GeoVideoScalarSource,
61
- v as GeoVideoVectorSource,
62
- t as RANDOM_GLSL,
63
- g as TrailFade,
64
- n as VIBRANCE_GLSL,
65
- f as alphaFadeAt,
66
- x as assertGeoVideoIndexIdentity,
67
- X as backdropVec4,
68
- Y as colorGradeToGrade,
69
- j as colorGradeVec4,
70
- _ as createColorRampTexture,
71
- p as createGeoVideoFrameSource,
72
- V as createProgram,
73
- G as createShader,
74
- C as fadeToFrames,
75
- S as fadeToOpacity,
76
- b as formatUnit,
77
- R as geoVideoChunkSources,
78
- O as geoVideoGrid,
79
- A as geoVideoIndexChunks,
80
- L as geoVideoScalarUniforms,
81
- h as geoVideoTimelineValues,
61
+ ee as BACKDROP_OFF,
62
+ t as COLOR_GRADE_GLSL,
63
+ ae as COLOR_GRADE_OFF,
64
+ oe as COLOR_GRADE_VIBRANT,
65
+ i as GEOVIDEO_SCALAR_GLSL,
66
+ u as GeoVideoArchiveSource,
67
+ v as GeoVideoClock,
68
+ f as GeoVideoField,
69
+ x as GeoVideoFrameSource,
70
+ g as GeoVideoPlayback,
71
+ _ as GeoVideoScalarSource,
72
+ V as GeoVideoVectorSource,
73
+ s as RANDOM_GLSL,
74
+ p as TrailFade,
75
+ l as VELOCITY_BLEND_GLSL,
76
+ c as VIBRANCE_GLSL,
77
+ G as alphaFadeAt,
78
+ C as assertGeoVideoIndexIdentity,
79
+ ne as backdropVec4,
80
+ re as colorGradeToGrade,
81
+ ce as colorGradeVec4,
82
+ S as createColorRampTexture,
83
+ b as createGeoVideoFrameSource,
84
+ y as createProgram,
85
+ L as createShader,
86
+ R as fadeToFrames,
87
+ O as fadeToOpacity,
88
+ h as formatUnit,
89
+ A as geoVideoChunkSources,
90
+ T as geoVideoGrid,
91
+ k as geoVideoIndexChunks,
92
+ I as geoVideoScalarUniforms,
93
+ D as geoVideoTimelineValues,
82
94
  F as getPalettes,
83
- q as gradeToColorGrade,
84
- I as isGeoVideoArchiveSource,
85
- Z as isHexColor,
86
- T as loadGeoVideoIndex,
87
- y as loadGeoVideoManifest,
88
- D as nextChunk,
89
- k as nextChunkSpan,
90
- B as pairChunk,
91
- E as pairChunkSpan,
92
- w as parseTimeRange,
93
- $ as resolveBackdrop,
94
- aa as resolveColorGrade,
95
- M as resolveColorRamp,
96
- N as subtractIsoDuration,
97
- P as timeRangeBounds,
98
- z as validateGeoVideoIndex,
99
- U as validateGeoVideoManifest,
100
- H as validateScalarColorDomain
95
+ te as gradeToColorGrade,
96
+ B as isGeoVideoArchiveSource,
97
+ se as isHexColor,
98
+ E as loadGeoVideoIndex,
99
+ w as loadGeoVideoManifest,
100
+ N as nextChunk,
101
+ P as nextChunkSpan,
102
+ z as pairChunk,
103
+ M as pairChunkSpan,
104
+ U as parseTimeRange,
105
+ ie as resolveBackdrop,
106
+ le as resolveColorGrade,
107
+ H as resolveColorRamp,
108
+ K as stepTime,
109
+ Y as subtractIsoDuration,
110
+ q as timeBracket,
111
+ J as timeRangeBounds,
112
+ Q as timeStep,
113
+ W as validateGeoVideoIndex,
114
+ X as validateGeoVideoManifest,
115
+ Z as validateScalarColorDomain,
116
+ $ as velocityTexels
101
117
  };