@solidrt/flux-types 0.0.45 → 0.0.47

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/gui/gpu.d.ts CHANGED
@@ -123,7 +123,7 @@ declare module "flux:gpu" {
123
123
  * messages, so a chain of targets reads as "bloom-h samples particle-verts"
124
124
  * instead of anonymous ids. Not unique, never interpreted; set at create,
125
125
  * kept across id-stable resizes ({@link resizeTexture},
126
- * {@link setShaderSize}).
126
+ * {@link setTargetSize}).
127
127
  */
128
128
  export type LabelOption = { label?: string }
129
129
  /**
@@ -186,8 +186,8 @@ declare module "flux:gpu" {
186
186
  * working, and shaders sampling the texture re-render. `data` seeds the new
187
187
  * contents and, like {@link createMutableTexture}, must hold at least one
188
188
  * frame at the id's format (which survives the resize, like the sampler
189
- * state). Shader/pipeline target ids are rejected - resize those with
190
- * {@link setShaderSize}.
189
+ * state). Render target ids are rejected - resize those with
190
+ * {@link setTargetSize}.
191
191
  */
192
192
  export function resizeTexture(id: TextureId, data: Uint8Array, width: number, height: number): void
193
193
  /**
@@ -205,7 +205,7 @@ declare module "flux:gpu" {
205
205
  * for the value shapes and the validation contract - a typo'd name throws
206
206
  * here, at the create). It is its own argument, not an option, because it
207
207
  * is the initial value of a live channel - the same values the `<texture
208
- * params>` prop and {@link setShaderParams} drive later; pass `null` (or
208
+ * params>` prop and {@link setTargetParams} drive later; pass `null` (or
209
209
  * omit it) for a shader with none. `opts.textures` binds sampler2D
210
210
  * uniforms to texture ids - any texture id, including another
211
211
  * shader/pipeline target's output, under a name that must be an active
@@ -328,8 +328,8 @@ declare module "flux:gpu" {
328
328
  * Create a render target over a {@link createRenderPipeline} pipeline and
329
329
  * render it once: the target half of {@link createPipelineTexture}. Returns
330
330
  * a texture id exactly like the fused creates do (drive uniforms
331
- * via the `params` prop or {@link setShaderParams}, resize with
332
- * {@link setShaderSize}, destroy with {@link destroyTexture}). Many targets
331
+ * via the `params` prop or {@link setTargetParams}, resize with
332
+ * {@link setTargetSize}, destroy with {@link destroyTexture}). Many targets
333
333
  * may share one pipeline, and creating a target compiles nothing. `buffer`
334
334
  * supplies the concrete vertex buffer the pipeline's attribute layout
335
335
  * describes (required when the pipeline declares attributes), and
@@ -385,36 +385,6 @@ declare module "flux:gpu" {
385
385
  * immediately.
386
386
  */
387
387
  export function destroyProgram(id: ProgramId): void
388
- /**
389
- * Update a shader texture's uniforms by name and re-render it (see
390
- * {@link ShaderParams} for the value shapes and the validation contract -
391
- * an unknown name or a mismatched length throws here, on the line that
392
- * wrote it). On a manual target nothing renders here; the values apply at
393
- * its next {@link renderTarget}.
394
- */
395
- export function setShaderParams(id: TextureId, params: ShaderParams): void
396
- /**
397
- * Rebind a shader texture's sampler2D inputs by uniform name and re-render
398
- * it with its last-applied params - the sampler analog of
399
- * {@link setShaderParams}. Bindings not named keep their current source, so
400
- * a single input can be retargeted (post-process source swap, ping-pong
401
- * between two data textures) without recompiling the shader. Throws if the
402
- * shader or a source texture id is unknown, if a binding names anything
403
- * but an active `sampler2D` uniform, if it names the shader's own target
404
- * (same-pass feedback), or if it would close a sampling cycle among
405
- * runtime-rendered targets. A cycle through a
406
- * `render: "manual"` target is legal - the runtime never renders one, so
407
- * the loop only steps when the app calls {@link renderTarget}.
408
- */
409
- export function setShaderTextures(id: TextureId, textures: Record<string, TextureId>): void
410
- /**
411
- * Resize a shader or pipeline target texture in place and re-render it: the
412
- * id, compiled program, last-applied params, and sampler bindings all carry
413
- * over; only the output size changes. The setDraw analog for output
414
- * size.
415
- */
416
- export function setShaderSize(id: TextureId, width: number, height: number): void
417
-
418
388
  export type Topology = "points" | "lines" | "line-strip" | "triangles" | "triangle-strip"
419
389
  /**
420
390
  * Blending for a pipeline's own draw. "none" (default) overwrites:
@@ -526,7 +496,7 @@ declare module "flux:gpu" {
526
496
  * {@link renderTarget}, and `loadOp: "load"` (manual-only) keeps the
527
497
  * previous contents under each draw.
528
498
  * Returns a texture id: display it with `<texture src>`, drive uniforms via
529
- * the `params` prop or {@link setShaderParams}, destroy with
499
+ * the `params` prop or {@link setTargetParams}, destroy with
530
500
  * {@link destroyTexture}.
531
501
  */
532
502
  export function createPipelineTexture(
@@ -605,6 +575,15 @@ declare module "flux:gpu" {
605
575
  * entry tests/writes depth is its pipeline's `depth`/`depthWrite` state,
606
576
  * and adding a depth-testing pipeline to a target without storage throws.
607
577
  *
578
+ * `params` seeds the target's SHARED params - the target-level values
579
+ * every entry reads, the same live channel {@link setTargetParams} drives
580
+ * later (positional like every create's params; see there for the
581
+ * precedence and validation contract). `opts.textures` seeds the shared
582
+ * sampler bindings the same way, the channel {@link setTargetTextures}
583
+ * drives (in opts like every create's textures). At creation there are no
584
+ * entries to validate against, so names are accepted as-is and simply
585
+ * apply to whichever later entries' programs declare them.
586
+ *
608
587
  * The render contract is unchanged: the list is input data like params, so
609
588
  * "render twice = render once" still holds and the default `render:
610
589
  * "auto"` target re-renders exactly when its entries or their inputs
@@ -618,8 +597,10 @@ declare module "flux:gpu" {
618
597
  export function createDrawTarget(
619
598
  width: number,
620
599
  height: number,
600
+ params?: ShaderParams | null,
621
601
  opts?: {
622
602
  depth?: boolean
603
+ textures?: Record<string, TextureId>
623
604
  clearColor?: [number, number, number, number]
624
605
  render?: "auto" | "manual"
625
606
  loadOp?: "clear" | "load"
@@ -646,6 +627,14 @@ declare module "flux:gpu" {
646
627
  * `instanceBuffer` supplies the per-instance records the pipeline's
647
628
  * `instanceAttributes` describe (required exactly when it declares any);
648
629
  * `instanceCount` then defaults to one instance per record.
630
+ *
631
+ * Seed every uniform the entry's program declares - here, via the
632
+ * target's shared params, or with a later write. GL uniform state lives
633
+ * on the program object, so a declared name nothing writes holds
634
+ * whatever the last draw through that program applied, from any entry
635
+ * or target sharing it - not zero (only a freshly linked program reads
636
+ * the link-time zero). Coverage is deliberately not validated here:
637
+ * adding entries first and setting shared values after is legal.
649
638
  */
650
639
  export function addDraw(
651
640
  target: TextureId,
@@ -665,15 +654,75 @@ declare module "flux:gpu" {
665
654
  */
666
655
  export function removeDraw(target: TextureId, draw: DrawId): void
667
656
  /**
668
- * Update one draw entry's uniforms by name: {@link setShaderParams}
657
+ * Update one draw entry's uniforms by name: {@link setTargetParams}
669
658
  * addressed to a single entry, same merge and validation contract. The
670
659
  * per-object hot path - a moved mesh is one setDrawParams with its new
671
660
  * model matrix.
672
661
  */
673
662
  export function setDrawParams(target: TextureId, draw: DrawId, params: ShaderParams): void
663
+ /**
664
+ * Update a target's target-level uniforms by name, on any target kind,
665
+ * with the usual merge-by-name (see {@link ShaderParams} for value shapes;
666
+ * a bad name or a mismatched length throws here, on the line that wrote
667
+ * it). On a single-program target (a fragment texture or a pipeline
668
+ * target) the target level IS its one pass: every name validates against
669
+ * that program and the target re-renders. On a manual target nothing
670
+ * renders here; the values apply at its next {@link renderTarget}.
671
+ *
672
+ * On a draw target these are the SHARED params: values every entry reads
673
+ * - a camera's view-projection above all - written once per target
674
+ * instead of once per entry. Shared values apply at render before each
675
+ * entry's own params, so an entry naming the same uniform overrides the
676
+ * shared value (specific beats general), and they are target state: entry
677
+ * add/remove/rebuild cannot lose them. A draw target legitimately mixes
678
+ * material classes, so coverage may be partial: a name only some entries'
679
+ * programs declare is applied where declared and skipped elsewhere - down
680
+ * to zero coverage: a name no current entry declares is stored and skips
681
+ * everywhere until a declaring entry arrives, so shared state does not
682
+ * depend on write order (a seed before entries and a write after are the
683
+ * same state). Validation is arity where declared: a name must match the
684
+ * declared component count in every entry program that declares it; an
685
+ * entry added later whose program lacks an already-set name is never a
686
+ * retroactive error, the value just skips it.
687
+ */
688
+ export function setTargetParams(target: TextureId, params: ShaderParams): void
689
+ /**
690
+ * Rebind a target's target-level sampler2D inputs by uniform name, on any
691
+ * target kind - {@link setTargetParams}'s sampler analog. Bindings not
692
+ * named keep their current source, so a single input can be retargeted
693
+ * (post-process source swap, ping-pong between two data textures) without
694
+ * recompiling anything. Bound sources are live dependencies: the target
695
+ * re-renders when one changes. Every path throws if the target or a
696
+ * source texture id is unknown, if a binding names the target's own
697
+ * texture (same-pass feedback), or if it would close a sampling cycle
698
+ * among runtime-rendered targets; a cycle through a `render: "manual"`
699
+ * target is legal - the runtime never renders one, so the loop only steps
700
+ * when the app calls {@link renderTarget}. On a single-program target each
701
+ * name must be an active `sampler2D` of its one program.
702
+ *
703
+ * On a draw target these are the SHARED bindings: sources every entry
704
+ * reads - an environment map, a shadow map, a LUT - bound once per
705
+ * target, with the shared-params rules throughout: an entry's own binding
706
+ * for the same name wins; a name only some entries' programs declare
707
+ * binds where declared and is skipped elsewhere, down to zero coverage
708
+ * (an undeclared name is stored, joins the sampler graph, and binds when
709
+ * a declaring entry arrives); shared bindings are target state that entry
710
+ * add/remove/rebuild cannot lose. Each name must be a sampler2D
711
+ * everywhere it is declared, and each entry's effective inputs (its own
712
+ * plus the applicable shared ones) must fit the device's texture units.
713
+ */
714
+ export function setTargetTextures(target: TextureId, textures: Record<string, TextureId>): void
715
+ /**
716
+ * Resize a render target of any kind in place and re-render it: the id,
717
+ * compiled programs, last-applied params, sampler bindings, and draw
718
+ * state all carry over; only the output size changes. The setDraw analog
719
+ * for output size. (Pixel textures resize with {@link resizeTexture},
720
+ * which carries seed pixels instead.)
721
+ */
722
+ export function setTargetSize(id: TextureId, width: number, height: number): void
674
723
  /**
675
724
  * Rebind one draw entry's sampler2D inputs by uniform name:
676
- * {@link setShaderTextures} addressed to a single entry, same merge,
725
+ * {@link setTargetTextures} addressed to a single entry, same merge,
677
726
  * validation, and cycle rules. Entries bind independently - two entries
678
727
  * may bind the same uniform name to different sources.
679
728
  */
@@ -698,7 +747,7 @@ declare module "flux:gpu" {
698
747
  export function setDrawOrder(target: TextureId, order: DrawId[]): void
699
748
  /**
700
749
  * Render a `render: "manual"` target once, now. Renders land in call order
701
- * relative to every other GPU call: a `setShaderParams`/`writeBuffer`
750
+ * relative to every other GPU call: a `setTargetParams`/`writeBuffer`
702
751
  * issued before is visible to the pass, a {@link readTexture} issued after
703
752
  * observes it, and two renders run the pass twice in order. Inputs are
704
753
  * fresh: pending runtime-driven renders of sampled targets resolve first.
@@ -726,7 +775,8 @@ declare module "flux:gpu" {
726
775
  */
727
776
  export function copyTexture(src: TextureId, dst: TextureId): void
728
777
  /**
729
- * Capture a render-tree node's subtree into a new GPU texture, resolving once
778
+ * Capture a render-tree node's subtree as RGBA8 pixels (tightly packed,
779
+ * top-to-bottom rows - the {@link readTexture} result shape), resolving once
730
780
  * it has been rendered on the next paint pass. The node must be attached to
731
781
  * the live tree (an unmounted node is never painted, so its capture rejects)
732
782
  * and paint a non-zero box. A laid-out node captures its layout box. A `d-*`
@@ -734,34 +784,32 @@ declare module "flux:gpu" {
734
784
  * painted box instead: its own `w`/`h` when set, else the nearest laid-out
735
785
  * ancestor's box (the same box the render tree reports for it), with its
736
786
  * `x`/`y` paint offset mapped to the texture origin.
737
- * Rendered at the current display scale, so `width`/`height` are the texture's
738
- * actual pixel dimensions (ceil(logicalSize * displayScale)), not logical
739
- * points. Each call returns an independent id you must {@link destroyTexture}
740
- * when done. Use the returned id anywhere a texture id is accepted
741
- * (`<texture src>`, a shader sampler input, {@link readTexture}).
787
+ * Rendered at the current display scale, so `width`/`height` are actual
788
+ * pixel dimensions (ceil(logicalSize * displayScale)), not logical points.
789
+ * No texture is created and there is nothing to free; to display or sample
790
+ * the result, upload it with {@link createTexture}.
742
791
  *
743
792
  * Intended for one-shot bakes and inspection: turning something the engine
744
793
  * can draw but the app cannot compute - shaped text, an SVG, a themed view -
745
- * into pixels, usually to hand to {@link readTexture} and process on the CPU.
746
- * Baking a glyph atlas by laying out cells, capturing them and keeping the
747
- * coverage channel is the worked example. Tests and freeze-frames are the
748
- * same shape.
794
+ * into pixels the app processes on the CPU. Baking a glyph atlas by laying
795
+ * out cells, capturing them and keeping the coverage channel is the worked
796
+ * example. Tests and freeze-frames are the same shape.
749
797
  *
750
798
  * Not a rendering primitive. Every call rasterizes the subtree into a fresh
751
- * offscreen MSAA target, reads the pixels back to the CPU and uploads them
752
- * again as a new texture: a full GPU -> CPU -> GPU round trip plus a paint
753
- * pass of latency, per call, with nothing incremental about it. Batch what
754
- * you capture (many nodes captured together are serviced by one paint pass),
755
- * and do not drive it per frame or reach for it to feed live content into a
756
- * shader - an effect over what is beneath it, a backdrop filter. Content that
757
- * must stay current has to come from a source that updates in place: another
758
- * pipeline's render target, a camera texture, a mutable texture.
799
+ * offscreen MSAA target and reads the pixels back to the CPU: a GPU -> CPU
800
+ * readback stall plus a paint pass of latency, per call, with nothing
801
+ * incremental about it. Batch what you capture (many nodes captured together
802
+ * are serviced by one paint pass), and do not drive it per frame or reach
803
+ * for it to feed live content into a shader - an effect over what is beneath
804
+ * it, a backdrop filter. Content that must stay current has to come from a
805
+ * source that updates in place: another pipeline's render target, a camera
806
+ * texture, a mutable texture.
759
807
  */
760
- export function captureSnapshot(nodeId: number): Promise<{ id: TextureId; width: number; height: number }>
808
+ export function captureSnapshot(nodeId: number): Promise<{ width: number; height: number; data: Uint8Array }>
761
809
  /**
762
810
  * Read back a registered texture's current pixels as RGBA8 (tightly packed,
763
811
  * top-to-bottom rows), for any texture id whatever created it (createTexture,
764
- * createShaderTexture, captureSnapshot). Synchronous. Throws if the id is
812
+ * createShaderTexture, a render target). Synchronous. Throws if the id is
765
813
  * unknown.
766
814
  */
767
815
  export function readTexture(id: TextureId): { width: number; height: number; data: Uint8Array }
@@ -28,7 +28,13 @@ declare module "flux:rendertree" {
28
28
  export function detachNode(parentId: number, nodeId: number): void
29
29
  /** Free `nodeId` and its whole subtree. Call after {@link detachNode}. */
30
30
  export function destroyNode(nodeId: number): void
31
- /** Write a single property on a node; `value` is marshalled per property. */
31
+ /**
32
+ * Write a single property on a node; `value` is marshalled per property.
33
+ * Throws an `Error` for an unknown property name (message starts with
34
+ * "Unknown property") or a value that does not decode; it never aborts the
35
+ * runtime. Core's renderer warns-and-continues on the name-level rejections
36
+ * and rethrows value errors.
37
+ */
32
38
  export function setProperty(nodeId: number, name: string, value: unknown): void
33
39
  /**
34
40
  * Declare which pointer deliveries the node's handlers want, as a bitmask
package/index.d.ts CHANGED
@@ -5,6 +5,7 @@
5
5
  /// <reference path="./modules/sqlite.d.ts" />
6
6
  /// <reference path="./modules/subprocess.d.ts" />
7
7
  /// <reference path="./modules/svg.d.ts" />
8
+ /// <reference path="./modules/image.d.ts" />
8
9
  /// <reference path="./modules/p2p.d.ts" />
9
10
  /// <reference path="./modules/net.d.ts" />
10
11
  /// <reference path="./modules/mdns.d.ts" />
@@ -0,0 +1,24 @@
1
+ declare module "flux:image" {
2
+ /** Decoded pixels: tightly-packed RGBA8 plus the pixel dimensions. */
3
+ export type DecodedImage = {
4
+ data: Uint8Array
5
+ width: number
6
+ height: number
7
+ }
8
+
9
+ /**
10
+ * Decodes encoded image bytes (png, jpeg, webp, gif, bmp, ico) into raw
11
+ * RGBA8 pixels plus the decoded dimensions. Synchronous, pure CPU. Throws
12
+ * when the bytes are not a decodable image.
13
+ */
14
+ export function decodeImage(bytes: Uint8Array): DecodedImage
15
+
16
+ /**
17
+ * Encodes raw RGBA8 pixels into an image file, the reverse of `decodeImage`
18
+ * (`encodeImage(decodeImage(bytes))` round-trips). `format` defaults to
19
+ * `"png"` (lossless, keeps alpha); `"jpeg"` drops the alpha channel and
20
+ * takes `quality` in 0..1 (default 0.9, ignored for png). Throws when
21
+ * `data.length` does not match `width * height * 4`.
22
+ */
23
+ export function encodeImage(img: DecodedImage, options?: { format?: "png" | "jpeg"; quality?: number }): Uint8Array
24
+ }
@@ -1,7 +1,9 @@
1
1
  declare module "flux:process" {
2
2
  /**
3
- * The program's command-line arguments. `argv[0]` is the script path;
4
- * `argv[1]` onward are the user-supplied arguments.
3
+ * The arguments the app was started with; empty when there are none.
4
+ * App arguments only: no executable path, no script path (deliberately
5
+ * simpler than Node/Bun's two leading entries), so `argv[0]` is the first
6
+ * argument.
5
7
  */
6
8
  export let argv: string[]
7
9
  /** The host OS: "darwin", "win32", "linux", "android", ... */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidrt/flux-types",
3
- "version": "0.0.45",
3
+ "version": "0.0.47",
4
4
  "license": "MIT",
5
5
  "author": "Antoine van Wel",
6
6
  "types": "index.d.ts",
@@ -10,7 +10,8 @@
10
10
  declare function btoa(data: string): string
11
11
  /**
12
12
  * Base64-decode to a binary string: each decoded byte becomes one char code
13
- * (read the bytes back with `charCodeAt`). ASCII whitespace in the input is
14
- * ignored; anything else that is not valid base64 throws.
13
+ * (read the bytes back with `charCodeAt`). Forgiving per WHATWG: ASCII
14
+ * whitespace is ignored and missing `=` padding is tolerated; anything else
15
+ * that is not valid base64 throws.
15
16
  */
16
17
  declare function atob(data: string): string
@@ -4,12 +4,16 @@
4
4
  // Grouped in one file because the four share BodyInit/HeadersInit and reference
5
5
  // each other.
6
6
 
7
- /** Header initializer: a plain name -> value object, or another Headers. */
7
+ /**
8
+ * Header initializer: a plain name -> value object, or another Headers.
9
+ * Values must be strings: a non-string value throws (the web stringifies it).
10
+ */
8
11
  type HeadersInit = Record<string, string> | Headers
9
12
 
10
13
  /**
11
14
  * A message body: a string, raw bytes, or an async-iterable of string/byte
12
- * chunks (e.g. an `async function*`), which is sent as a stream.
15
+ * chunks (e.g. an `async function*`), which is sent as a stream. Any other
16
+ * value throws (the web stringifies it).
13
17
  */
14
18
  type BodyInit = string | Uint8Array | AsyncIterable<string | Uint8Array>
15
19
 
@@ -1,6 +1,15 @@
1
1
  // Timers, microtask scheduling, and the monotonic clock. flux's timers differ
2
2
  // from the browser in two ways: the delay is required, and no extra callback
3
3
  // arguments are forwarded.
4
+ //
5
+ // In a GUI runtime the whole time surface here is FRAME-STEPPED: timers and
6
+ // performance.now() march on the same paced timeline as onFrame and
7
+ // requestAnimationFrame, quantized to frames. So timer resolution is one
8
+ // frame (~16 ms at 60 Hz; a setTimeout of 0 runs on the next frame), an
9
+ // interval fires at most once per frame, and pausing the runtime clock (the
10
+ // dev tools' set_time_scale 0) freezes all of it together deterministically.
11
+ // Date.now() is the wall-clock escape hatch: it always reports real calendar
12
+ // time. Headless flux (scripts, servers) keeps ordinary wall-clock timers.
4
13
 
5
14
  /**
6
15
  * Run `callback` after at least `ms` milliseconds. Returns a timer id for
@@ -25,7 +34,16 @@ declare function queueMicrotask(callback: () => void): void
25
34
  declare let performance: {
26
35
  /**
27
36
  * Milliseconds since a monotonic origin (high-resolution, not wall-clock). Use
28
- * for measuring durations, not for calendar time.
37
+ * for measuring durations, not for calendar time. In a GUI runtime this is
38
+ * the paced frame timeline (same clock as the onFrame/requestAnimationFrame
39
+ * timestamps, frozen while the runtime clock is paused); for real elapsed
40
+ * wall time use Date.now().
29
41
  */
30
42
  now(): number
43
+ /**
44
+ * Wall-clock time (ms since the Unix epoch) when the runtime started. Unlike
45
+ * the browser, timeOrigin + now() is not the current wall-clock time: now()
46
+ * runs on the paced runtime timeline, which can be frozen or scaled.
47
+ */
48
+ readonly timeOrigin: number
31
49
  }