@msb235/blits 0.2.1 → 0.4.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.
- package/CHANGELOG.md +140 -0
- package/README.md +9 -2
- package/dist/channels.d.ts +34 -5
- package/dist/channels.js +172 -23
- package/dist/clock.d.ts +19 -0
- package/dist/clock.js +44 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/lanes.d.ts +353 -0
- package/dist/lanes.js +1850 -0
- package/dist/mixer.d.ts +212 -2
- package/dist/mixer.js +1775 -167
- package/dist/motion.d.ts +209 -9
- package/dist/motion.js +674 -114
- package/dist/numbers.d.ts +22 -0
- package/dist/numbers.js +64 -0
- package/dist/patch.d.ts +13 -2
- package/dist/patch.js +44 -18
- package/dist/reading.d.ts +23 -0
- package/dist/reading.js +23 -0
- package/dist/types.d.ts +279 -18
- package/docs/schema.html +146 -27
- package/package.json +3 -6
package/dist/motion.d.ts
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
|
-
import type
|
|
2
|
-
|
|
1
|
+
import { type Curve } from './easing.js';
|
|
2
|
+
import type { Easing, Patch } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* A number, or one number per axis.
|
|
5
|
+
*
|
|
6
|
+
* @category patch
|
|
7
|
+
*/
|
|
3
8
|
export type Value = number | readonly number[];
|
|
4
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* One value for every subject, or one per subject.
|
|
11
|
+
*
|
|
12
|
+
* @category patch
|
|
13
|
+
*/
|
|
5
14
|
export type PerSubject<I, V> = V | ((subject: I) => V);
|
|
6
15
|
/**
|
|
7
16
|
* Where a subject is and how fast it is moving, at one moment of voice time.
|
|
@@ -13,6 +22,19 @@ export interface Motion<V extends Value = number> {
|
|
|
13
22
|
/** Units per second. */
|
|
14
23
|
velocity: V;
|
|
15
24
|
}
|
|
25
|
+
interface Change {
|
|
26
|
+
/**
|
|
27
|
+
* Voice ms it takes effect at; absent, until the subject's next read stamps it with that read's
|
|
28
|
+
* time, for one made while no frame had met the subject.
|
|
29
|
+
*/
|
|
30
|
+
at?: number;
|
|
31
|
+
to?: number[];
|
|
32
|
+
v?: number[];
|
|
33
|
+
}
|
|
34
|
+
/** A motion patch's `frame` while no mix plays it: no subject has a latest frame. */
|
|
35
|
+
export declare const noFrame: () => number;
|
|
36
|
+
export declare const noRevive: () => void;
|
|
37
|
+
export declare const noTouch: () => void;
|
|
16
38
|
/**
|
|
17
39
|
* A patch whose motion is a closed form per subject, so it lands in the same place at any frame
|
|
18
40
|
* rate, and whose changes mid-flight start from where the subject is and how fast it moves.
|
|
@@ -20,11 +42,160 @@ export interface Motion<V extends Value = number> {
|
|
|
20
42
|
* @category patch
|
|
21
43
|
*/
|
|
22
44
|
export type Moving<I, O, V extends Value> = Patch<I, O, void> & {
|
|
23
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* Where `subject` is and how fast it moves at voice time `at`, default the mix's latest frame,
|
|
47
|
+
* counting every change due by then. With no time given, undefined until a frame of its voice
|
|
48
|
+
* has met the subject, while the subject is still inside its stagger, and once that voice is gone.
|
|
49
|
+
*/
|
|
24
50
|
read(subject: I, at?: number): Motion<V> | undefined;
|
|
25
|
-
/**
|
|
51
|
+
/**
|
|
52
|
+
* Sets `subject` moving at `velocity`, units per second, from voice time `at`, default the mix's
|
|
53
|
+
* latest frame; for a subject no frame of its voice has met yet, or still inside its stagger, its
|
|
54
|
+
* first read, after any change with a time due by then.
|
|
55
|
+
*/
|
|
26
56
|
push(subject: I, velocity: V, at?: number): void;
|
|
27
57
|
};
|
|
58
|
+
interface Shape<I> {
|
|
59
|
+
from: (subject: I) => number[];
|
|
60
|
+
velocity: (subject: I) => number[];
|
|
61
|
+
/** Where it heads when released from `x` at `v`, given where it was heading. */
|
|
62
|
+
aim: (x: number[], v: number[], was: number[] | null, subject: I) => number[];
|
|
63
|
+
/** `[form, settle, k1, k2, k3]`. */
|
|
64
|
+
law: readonly number[];
|
|
65
|
+
/** Whether a subject's value is a number rather than an array. */
|
|
66
|
+
scalar: (subject: I) => boolean;
|
|
67
|
+
/** A tween's easing, which its law cannot hold; undefined, but present, on every other shape. */
|
|
68
|
+
ease: Curve | undefined;
|
|
69
|
+
/** A tween's seconds for a stretch the subject starts now; undefined, but present, on the rest. */
|
|
70
|
+
ms: ((subject: I) => number) | undefined;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* A motion patch's subjects: the stretch each is playing, in one flat array by a number the patch
|
|
74
|
+
* gives it, with earlier stretches a read back may reach and changes not yet applied beside them.
|
|
75
|
+
* The one copy, read by `at` and by a mix's lane alike.
|
|
76
|
+
*
|
|
77
|
+
* After the law, each subject's run of `stride` numbers is its release time, its flags, a tween's
|
|
78
|
+
* seconds for the stretch, then `x0`, `v0` and `to` per axis. A live sample reads this one buffer and nothing else the patch owns: at
|
|
79
|
+
* 10k springs of one subject each, a buffer per field, a map lookup per sample and the law in an
|
|
80
|
+
* object of its own took a call from 130 ns to 490.
|
|
81
|
+
*/
|
|
82
|
+
export declare class Motions<I> {
|
|
83
|
+
private readonly shape;
|
|
84
|
+
private readonly numbers;
|
|
85
|
+
private readonly slots;
|
|
86
|
+
/** Axes per subject; -1 until the first subject sets it. */
|
|
87
|
+
n: number;
|
|
88
|
+
private cap;
|
|
89
|
+
private stride;
|
|
90
|
+
private runs;
|
|
91
|
+
/**
|
|
92
|
+
* Where `sample` leaves a subject's position and velocity, per axis. Shared by every patch, so
|
|
93
|
+
* read it before the next sample.
|
|
94
|
+
*/
|
|
95
|
+
xs: Float64Array<ArrayBuffer>;
|
|
96
|
+
vs: Float64Array<ArrayBuffer>;
|
|
97
|
+
private readonly pending;
|
|
98
|
+
private readonly older;
|
|
99
|
+
/**
|
|
100
|
+
* The subject's voice time at the mix's latest frame, which an untimed change and a `read` with
|
|
101
|
+
* no time take; NaN where no frame of the patch's voice has met the subject. Set by the mix that
|
|
102
|
+
* cues the patch, and put back when its voice retires.
|
|
103
|
+
*/
|
|
104
|
+
frame: (subject: I) => number;
|
|
105
|
+
/**
|
|
106
|
+
* Brings a subject its voice faded out back to it, so a change is not made for nothing. Set by
|
|
107
|
+
* the mix that cues the patch, and put back when its voice retires.
|
|
108
|
+
*/
|
|
109
|
+
revive: (subject: I) => void;
|
|
110
|
+
constructor(shape: Shape<I>);
|
|
111
|
+
/** The patch's number for `subject`, made with its first stretch on first ask. */
|
|
112
|
+
slot(subject: I): number;
|
|
113
|
+
/** Forgets a subject, so a later ask starts it afresh from `from`. */
|
|
114
|
+
release(subject: I): void;
|
|
115
|
+
/**
|
|
116
|
+
* Called with a subject's number whenever its stretch or what is pending for it changes, so a
|
|
117
|
+
* mix keeping a copy of it knows to read it again. Set by the mix, put back when its voice retires.
|
|
118
|
+
*/
|
|
119
|
+
touched: (s: number) => void;
|
|
120
|
+
/** The easing a tween's stretches follow; undefined for every other shape. */
|
|
121
|
+
get ease(): Curve | undefined;
|
|
122
|
+
/** A copy of the patch's law, `[form, settle, k1, k2, k3]`. */
|
|
123
|
+
law(): Float64Array;
|
|
124
|
+
/**
|
|
125
|
+
* Copies subject `s`'s current stretch into `out` from `o` as its release time, its seconds, then
|
|
126
|
+
* `x0`, `v0` and `to` per axis; false, copying nothing, while it has a change pending or an
|
|
127
|
+
* earlier stretch kept, which only `sample` handles.
|
|
128
|
+
*/
|
|
129
|
+
stretchInto(s: number, out: Float64Array, o: number): boolean;
|
|
130
|
+
/** Whether subject `s`'s value is a number rather than an array. */
|
|
131
|
+
scalar(s: number): boolean;
|
|
132
|
+
/** The value `at` hands the mix: the first axis for a number, a fresh array otherwise. */
|
|
133
|
+
value(s: number, xs: Float64Array): number | number[];
|
|
134
|
+
/**
|
|
135
|
+
* Position and velocity at voice time `t` into `xo` and `vo`, a tween's velocity left at 0. A live
|
|
136
|
+
* read stamps every untimed change with `t` and commits every change due by then, in time order;
|
|
137
|
+
* a projection's read applies the timed ones to a copy and commits nothing.
|
|
138
|
+
*/
|
|
139
|
+
sample(s: number, t: number, xo: Float64Array, vo: Float64Array): void;
|
|
140
|
+
/**
|
|
141
|
+
* A live `sample` at `t` for a subject with nothing pending and no earlier stretch kept, true
|
|
142
|
+
* then; false, writing nothing, for any other, which `quiet` and `sample` take instead.
|
|
143
|
+
*/
|
|
144
|
+
sampleBare(s: number, t: number, xo: Float64Array, vo: Float64Array): boolean;
|
|
145
|
+
/**
|
|
146
|
+
* Whether every subject has landed on its target at its voice time at the latest frame, as a
|
|
147
|
+
* sample there would find; one with a change waiting has not. Commits nothing.
|
|
148
|
+
*/
|
|
149
|
+
landed(): boolean;
|
|
150
|
+
/**
|
|
151
|
+
* Whether a live `sample` at `t` would leave the subject's state as it is: nothing to stamp or
|
|
152
|
+
* commit by then, and nothing older than `reading.horizon` to let go of.
|
|
153
|
+
*/
|
|
154
|
+
quiet(s: number, t: number): boolean;
|
|
155
|
+
/** Position and velocity at `at`, default the latest frame; undefined until there is one. */
|
|
156
|
+
read(subject: I, at?: number): {
|
|
157
|
+
x: Float64Array;
|
|
158
|
+
v: Float64Array;
|
|
159
|
+
s: number;
|
|
160
|
+
} | undefined;
|
|
161
|
+
/**
|
|
162
|
+
* Queues a retarget or push, untimed at the latest frame, for `subject`'s next read past its time.
|
|
163
|
+
* The queue keeps the changes with a time in time order, ahead of any still waiting for one.
|
|
164
|
+
*/
|
|
165
|
+
change(subject: I, c: Change): void;
|
|
166
|
+
/** Files a change with a time after every one due by then, ahead of those still waiting for one. */
|
|
167
|
+
private queue;
|
|
168
|
+
/** Every change due by `t` applied to a copy of the stretch playing then, committing nothing. */
|
|
169
|
+
private peek;
|
|
170
|
+
private check;
|
|
171
|
+
private flag;
|
|
172
|
+
private forget;
|
|
173
|
+
/** Where subject `s`'s run starts in `runs`. */
|
|
174
|
+
private base;
|
|
175
|
+
private grow;
|
|
176
|
+
private write;
|
|
177
|
+
/** The stretch subject `s` is playing now, as an object. */
|
|
178
|
+
private latest;
|
|
179
|
+
/** The stretch playing at voice time `t`: the latest released by then, else the first. */
|
|
180
|
+
private playing;
|
|
181
|
+
private applied;
|
|
182
|
+
private commit;
|
|
183
|
+
private insert;
|
|
184
|
+
/** Lets go of stretches older than the one in force at `reading.horizon`. */
|
|
185
|
+
private prune;
|
|
186
|
+
private evaluateSegment;
|
|
187
|
+
private evaluate;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* A stretch `t` voice ms into it, released at `at` from `x0` moving at `v0` toward `to` (each read
|
|
191
|
+
* from its offset), into `xo` and `vo`: the one copy of the closed forms, which `law` (a patch's
|
|
192
|
+
* `[form, settle, k1, k2, k3]`, the head of a patch's buffer or a copy of it) picks between. A tween reads `ease` and
|
|
193
|
+
* `ms`, the stretch's length, dividing in milliseconds so a boundary lands exactly; every other
|
|
194
|
+
* form ignores them.
|
|
195
|
+
*/
|
|
196
|
+
export declare function closed(law: Float64Array, ease: Curve | undefined, n: number, at: number, ms: number, x0: ArrayLike<number>, x: number, v0: ArrayLike<number>, v: number, to: ArrayLike<number>, g: number, t: number, xo: Float64Array, vo: Float64Array): boolean;
|
|
197
|
+
/** The state behind a `'motion'` patch, for an engine that reads it directly. */
|
|
198
|
+
export declare function motionOf<I>(p: object): Motions<I> | undefined;
|
|
28
199
|
interface Common<I, V extends Value> {
|
|
29
200
|
/** Units per second each subject starts moving at. Default 0. */
|
|
30
201
|
velocity?: PerSubject<I, V>;
|
|
@@ -37,9 +208,8 @@ interface Common<I, V extends Value> {
|
|
|
37
208
|
/**
|
|
38
209
|
* A damped spring toward a target, solved in closed form. `to(subject, target)` retargets one
|
|
39
210
|
* subject mid-flight, and the new stretch starts from where it is and how fast it moves, so there is
|
|
40
|
-
* no kink. Time is the voice's, so `rate` and `seek` apply
|
|
41
|
-
*
|
|
42
|
-
* on one voice.
|
|
211
|
+
* no kink. Time is the voice's, so `rate` and `seek` apply. Its state is its own, kept per subject:
|
|
212
|
+
* cue each spring on one voice. Every subject moves on the same number of axes.
|
|
43
213
|
*
|
|
44
214
|
* @category patch
|
|
45
215
|
*/
|
|
@@ -53,7 +223,11 @@ export declare function spring<I, O, V extends Value = number>(writes: keyof O,
|
|
|
53
223
|
damping?: number;
|
|
54
224
|
mass?: number;
|
|
55
225
|
}): Moving<I, O, V> & {
|
|
56
|
-
/**
|
|
226
|
+
/**
|
|
227
|
+
* Heads `subject` for `target` from voice time `at`, keeping its velocity: by default the mix's
|
|
228
|
+
* latest frame, or for a subject no frame of its voice has met yet, or still inside its stagger,
|
|
229
|
+
* its first read, after any change with a time due by then.
|
|
230
|
+
*/
|
|
57
231
|
to(subject: I, target: V, at?: number): void;
|
|
58
232
|
};
|
|
59
233
|
/**
|
|
@@ -69,4 +243,30 @@ export declare function glide<I, O, V extends Value = number>(writes: keyof O, o
|
|
|
69
243
|
/** The friction's time constant, ms. Default 325, a touch scroll's. */
|
|
70
244
|
ms?: number;
|
|
71
245
|
}): Moving<I, O, V>;
|
|
246
|
+
/**
|
|
247
|
+
* From one value to another over `ms` along an easing, solved in closed form, so frame rate does not
|
|
248
|
+
* change where a subject is. `to(subject, target)` retargets one subject mid-flight: the new stretch
|
|
249
|
+
* starts from where it is and takes the full `ms` again, so its velocity jumps where a spring's
|
|
250
|
+
* would not. Time is the voice's, so `rate` and `seek` apply, and a voice's `loop` does not repeat
|
|
251
|
+
* it. Cue each tween on one voice. Every subject moves on the same number of axes.
|
|
252
|
+
*
|
|
253
|
+
* @category patch
|
|
254
|
+
*/
|
|
255
|
+
export declare function tween<I, O, V extends Value = number>(writes: keyof O, opts: {
|
|
256
|
+
/** Where each subject starts. */
|
|
257
|
+
from: PerSubject<I, V>;
|
|
258
|
+
/** Where each subject ends. */
|
|
259
|
+
to: PerSubject<I, V>;
|
|
260
|
+
/** How long a stretch takes, ms: asked per subject each time one of its stretches starts. */
|
|
261
|
+
ms: PerSubject<I, number>;
|
|
262
|
+
/** The curve from `from` to `to`. Default `'ease'`, as CSS's. */
|
|
263
|
+
ease?: Easing;
|
|
264
|
+
}): Omit<Moving<I, O, V>, 'push'> & {
|
|
265
|
+
/**
|
|
266
|
+
* Heads `subject` for `target` from voice time `at`, over a full `ms` from where it is: by default
|
|
267
|
+
* the mix's latest frame, or for a subject no frame of its voice has met yet, or still inside its
|
|
268
|
+
* stagger, its first read, after any change with a time due by then.
|
|
269
|
+
*/
|
|
270
|
+
to(subject: I, target: V, at?: number): void;
|
|
271
|
+
};
|
|
72
272
|
export {};
|