@msb235/blits 0.13.0 → 0.15.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 (178) hide show
  1. package/CHANGELOG.md +183 -0
  2. package/README.md +20 -3
  3. package/dist/ahead.d.ts +26 -0
  4. package/dist/ahead.js +264 -0
  5. package/dist/around.d.ts +11 -0
  6. package/dist/around.js +32 -0
  7. package/dist/bare.js +15 -7
  8. package/dist/blank.d.ts +10 -0
  9. package/dist/blank.js +26 -0
  10. package/dist/blend.d.ts +2 -1
  11. package/dist/blend.js +1 -6
  12. package/dist/bound.d.ts +70 -0
  13. package/dist/bound.js +351 -0
  14. package/dist/chain.d.ts +2 -1
  15. package/dist/chain.js +7 -5
  16. package/dist/changes.d.ts +24 -0
  17. package/dist/changes.js +189 -0
  18. package/dist/channels.d.ts +39 -13
  19. package/dist/channels.js +14 -5
  20. package/dist/closed.d.ts +1 -0
  21. package/dist/closed.js +45 -1
  22. package/dist/color.d.ts +12 -10
  23. package/dist/color.js +25 -25
  24. package/dist/columns.js +7 -3
  25. package/dist/contribution.d.ts +30 -0
  26. package/dist/contribution.js +374 -0
  27. package/dist/copyout.d.ts +10 -0
  28. package/dist/copyout.js +69 -24
  29. package/dist/crowd.d.ts +8 -2
  30. package/dist/crowd.js +4 -5
  31. package/dist/cue.d.ts +8 -1
  32. package/dist/cue.js +47 -14
  33. package/dist/cut.d.ts +8 -0
  34. package/dist/cut.js +4 -0
  35. package/dist/drop.d.ts +9 -0
  36. package/dist/drop.js +84 -0
  37. package/dist/due.d.ts +24 -5
  38. package/dist/due.js +113 -33
  39. package/dist/easing.d.ts +4 -4
  40. package/dist/easing.js +3 -3
  41. package/dist/everyone.d.ts +3 -2
  42. package/dist/everyone.js +3 -3
  43. package/dist/fade.d.ts +2 -1
  44. package/dist/fade.js +2 -1
  45. package/dist/fill.d.ts +3 -2
  46. package/dist/fill.js +51 -19
  47. package/dist/fit.d.ts +44 -26
  48. package/dist/fit.js +10 -9
  49. package/dist/fling.d.ts +66 -0
  50. package/dist/fling.js +162 -0
  51. package/dist/fold.d.ts +4 -37
  52. package/dist/fold.js +5 -512
  53. package/dist/gather.d.ts +12 -7
  54. package/dist/gather.js +179 -44
  55. package/dist/gone.js +2 -2
  56. package/dist/grid.d.ts +47 -0
  57. package/dist/grid.js +247 -0
  58. package/dist/handle.d.ts +3 -0
  59. package/dist/handle.js +19 -8
  60. package/dist/held.d.ts +2 -1
  61. package/dist/history.d.ts +6 -5
  62. package/dist/history.js +9 -9
  63. package/dist/hosts.js +9 -15
  64. package/dist/index.d.ts +5 -4
  65. package/dist/keyfill.d.ts +1 -1
  66. package/dist/keyfill.js +5 -3
  67. package/dist/keyrows.d.ts +12 -0
  68. package/dist/keyrows.js +99 -12
  69. package/dist/lane.d.ts +36 -6
  70. package/dist/lane.js +32 -1
  71. package/dist/lanes.d.ts +23 -8
  72. package/dist/lanes.js +29 -8
  73. package/dist/leavings.d.ts +2 -2
  74. package/dist/leavings.js +1 -1
  75. package/dist/lives.d.ts +47 -0
  76. package/dist/lives.js +180 -0
  77. package/dist/meet.d.ts +2 -2
  78. package/dist/meet.js +90 -4
  79. package/dist/mixer.d.ts +61 -35
  80. package/dist/mixer.js +64 -169
  81. package/dist/motion.d.ts +19 -106
  82. package/dist/motion.js +60 -13
  83. package/dist/motions.d.ts +62 -150
  84. package/dist/motions.js +57 -369
  85. package/dist/move.js +24 -1
  86. package/dist/moved.d.ts +1 -1
  87. package/dist/moved.js +16 -7
  88. package/dist/named.d.ts +0 -1
  89. package/dist/named.js +20 -2
  90. package/dist/numbers.d.ts +2 -0
  91. package/dist/numbers.js +4 -0
  92. package/dist/owed.d.ts +2 -0
  93. package/dist/owed.js +4 -0
  94. package/dist/pack.d.ts +3 -1
  95. package/dist/pack.js +4 -3
  96. package/dist/patch.d.ts +7 -3
  97. package/dist/patch.js +6 -2
  98. package/dist/places.d.ts +53 -0
  99. package/dist/places.js +171 -0
  100. package/dist/plot.d.ts +12 -0
  101. package/dist/plot.js +52 -0
  102. package/dist/project.d.ts +4 -4
  103. package/dist/project.js +9 -211
  104. package/dist/pull.js +11 -8
  105. package/dist/qualify.js +84 -21
  106. package/dist/reading.d.ts +6 -0
  107. package/dist/reading.js +5 -0
  108. package/dist/record.d.ts +5 -1
  109. package/dist/record.js +4 -2
  110. package/dist/relink.d.ts +1 -1
  111. package/dist/restored.d.ts +2 -2
  112. package/dist/restored.js +1 -1
  113. package/dist/rests.d.ts +9 -0
  114. package/dist/rests.js +76 -0
  115. package/dist/revive.d.ts +3 -2
  116. package/dist/revive.js +2 -2
  117. package/dist/{locus.d.ts → role.d.ts} +10 -9
  118. package/dist/{locus.js → role.js} +3 -3
  119. package/dist/roles.d.ts +10 -0
  120. package/dist/roles.js +158 -0
  121. package/dist/roster.js +3 -3
  122. package/dist/rotation.d.ts +1 -1
  123. package/dist/rotation.js +1 -1
  124. package/dist/rows.js +1 -1
  125. package/dist/sample.d.ts +2 -2
  126. package/dist/sample.js +33 -7
  127. package/dist/seek.js +13 -5
  128. package/dist/setting.d.ts +27 -0
  129. package/dist/setting.js +55 -0
  130. package/dist/shared.d.ts +1 -1
  131. package/dist/shared.js +1 -1
  132. package/dist/signals.d.ts +64 -32
  133. package/dist/signals.js +20 -18
  134. package/dist/stack.d.ts +5 -5
  135. package/dist/stack.js +5 -5
  136. package/dist/standing.d.ts +2 -1
  137. package/dist/standing.js +3 -2
  138. package/dist/store.d.ts +9 -0
  139. package/dist/store.js +24 -0
  140. package/dist/strays.d.ts +2 -1
  141. package/dist/strays.js +21 -14
  142. package/dist/stretch.d.ts +112 -0
  143. package/dist/stretch.js +9 -0
  144. package/dist/subject.d.ts +142 -0
  145. package/dist/subject.js +1 -0
  146. package/dist/tape.d.ts +9 -5
  147. package/dist/tape.js +5 -1
  148. package/dist/then.d.ts +9 -0
  149. package/dist/then.js +57 -0
  150. package/dist/ticker.d.ts +4 -4
  151. package/dist/transport.d.ts +0 -8
  152. package/dist/transport.js +0 -4
  153. package/dist/turns.d.ts +4 -3
  154. package/dist/turns.js +4 -3
  155. package/dist/types/arc.d.ts +12 -11
  156. package/dist/types/channel.d.ts +12 -8
  157. package/dist/types/history.d.ts +35 -19
  158. package/dist/types/mix.d.ts +222 -161
  159. package/dist/types/motion.d.ts +151 -0
  160. package/dist/types/motion.js +1 -0
  161. package/dist/types/patch.d.ts +69 -34
  162. package/dist/types/place.d.ts +51 -36
  163. package/dist/types/transport.d.ts +20 -18
  164. package/dist/types/voice.d.ts +145 -72
  165. package/dist/types/watch.d.ts +88 -40
  166. package/dist/types.d.ts +1 -0
  167. package/dist/voice.d.ts +9 -141
  168. package/dist/voice.js +30 -79
  169. package/dist/warn.d.ts +2 -0
  170. package/dist/warn.js +1 -1
  171. package/dist/watch.d.ts +2 -2
  172. package/dist/watch.js +5 -3
  173. package/dist/wave.d.ts +4 -3
  174. package/dist/wave.js +3 -2
  175. package/dist/weigh.d.ts +7 -1
  176. package/dist/weigh.js +27 -0
  177. package/docs/schema.html +223 -37
  178. package/package.json +6 -2
package/dist/motion.d.ts CHANGED
@@ -1,64 +1,11 @@
1
1
  import { Motions } from './motions.js';
2
- import type { Easing, Patch } from './types.js';
3
- /**
4
- * A number, or one number per axis.
5
- *
6
- * @category patch
7
- */
8
- export type Value = number | readonly number[];
9
- /**
10
- * One value for every subject, or one per subject.
11
- *
12
- * @category patch
13
- */
14
- export type PerSubject<I, V> = V | ((subject: I) => V);
15
- /**
16
- * Where a subject is and how fast it is moving, at one moment of voice time.
17
- *
18
- * @category patch
19
- */
20
- export interface Motion<V extends Value = number> {
21
- value: V;
22
- /** Units per second. */
23
- velocity: V;
24
- }
25
- /**
26
- * A patch whose motion is a closed form per subject, so it lands in the same place at any frame
27
- * rate, and whose changes mid-flight start from where the subject is and how fast it moves.
28
- *
29
- * @category patch
30
- */
31
- export type Moving<I, O, V extends Value> = Patch<I, O, void> & {
32
- /**
33
- * Where `subject` is and how fast it moves at voice time `at`, default the mix's latest frame,
34
- * counting every change due by then. With no time given, undefined until a frame of its voice
35
- * has met the subject, while the subject is still inside its stagger, and once that voice is gone.
36
- * At any time, undefined for a subject the patch has never met or changed, or that the mix
37
- * dropped.
38
- */
39
- read(subject: I, at?: number): Motion<V> | undefined;
40
- /**
41
- * Sets `subject` moving at `velocity`, units per second, from voice time `at`, default the mix's
42
- * latest frame; for a subject no frame of its voice has met yet, or still inside its stagger, its
43
- * first read, after any change with a time due by then. A subject faded out of the voice comes
44
- * back at the latest frame too, however long it is before it is next read.
45
- */
46
- push(subject: I, velocity: V, at?: number): void;
47
- };
2
+ import type { Glide, GlideOptions, Spring, SpringOptions, Tween, TweenOptions, Value } from './types/motion.js';
3
+ export type { Glide, GlideOptions, Motion, MotionOptions, Moving, PerSubject, Spring, SpringOptions, Tween, TweenOptions, Value, } from './types/motion.js';
48
4
  /**
49
5
  * The state behind a `'motion'` patch, for an engine that reads it directly; a patch another copy
50
6
  * of the same release made counts.
51
7
  */
52
8
  export declare function motionOf<I>(p: object): Motions<I> | undefined;
53
- interface Common<I, V extends Value> {
54
- /** Units per second each subject starts moving at. Default 0. */
55
- velocity?: PerSubject<I, V>;
56
- /**
57
- * Within this distance of where it heads, and this slow, a subject lands there exactly, so a mix
58
- * can see it at rest. Default 1e-4; 0 keeps the curve exact.
59
- */
60
- settle?: number;
61
- }
62
9
  /**
63
10
  * A damped spring toward a target, solved in closed form. `to(subject, target)` retargets one
64
11
  * subject mid-flight, and the new stretch starts from where it is and how fast it moves, so there is
@@ -67,62 +14,28 @@ interface Common<I, V extends Value> {
67
14
  *
68
15
  * @category patch
69
16
  */
70
- export declare function spring<I, O, V extends Value = number>(writes: keyof O, opts: Common<I, V> & {
71
- to: PerSubject<I, V>;
72
- /** Where each subject starts. Default: `to`, at rest. */
73
- from?: PerSubject<I, V>;
74
- /** Per second squared. Default 170. */
75
- stiffness?: number;
76
- /** Per second. Default 26, just short of critical at the default stiffness. */
77
- damping?: number;
78
- mass?: number;
79
- }): Moving<I, O, V> & {
80
- /**
81
- * Heads `subject` for `target` from voice time `at`, keeping its velocity: by default the mix's
82
- * latest frame, or for a subject no frame of its voice has met yet, or still inside its stagger,
83
- * its first read, after any change with a time due by then. A subject faded out of the voice
84
- * comes back at the latest frame too, however long it is before it is next read.
85
- */
86
- to(subject: I, target: V, at?: number): void;
87
- };
17
+ export declare function spring<I, O, V extends Value = number>(writes: keyof O, opts: SpringOptions<I, V>): Spring<I, O, V>;
88
18
  /**
89
- * Coasting under friction, a fling: a subject keeps its velocity, which falls by a factor of e every
90
- * `ms`, and comes to rest `velocity · ms / 1000` past where it was released. `push` sets it moving
91
- * again from wherever it is. Closed form, so frame rate does not change where it stops.
19
+ * A patch that coasts each subject to a stop under friction, as after a fling. A subject keeps its
20
+ * velocity, which falls by a factor of e every `ms`, and comes to rest `velocity · ms / 1000` past
21
+ * where it was released. `push` sets it moving again from wherever it is. Closed form, so frame
22
+ * rate does not change where it stops.
23
+ *
24
+ * With `bounds`, a coast that would stop past an edge springs back to it from where it crosses, at
25
+ * the speed it crosses at, on a critically damped spring of `stiffness`; one let go past an edge
26
+ * springs back from there, unless it coasts back inside. A `set` past an edge leaves the subject
27
+ * there, coasting on, until the next `push`, so a drag can hold it out.
92
28
  *
93
29
  * @category patch
94
30
  */
95
- export declare function glide<I, O, V extends Value = number>(writes: keyof O, opts: Common<I, V> & {
96
- /** Where each subject starts. */
97
- from: PerSubject<I, V>;
98
- /** The friction's time constant, ms. Default 325, a touch scroll's. */
99
- ms?: number;
100
- }): Moving<I, O, V>;
31
+ export declare function glide<I, O, V extends Value = number>(writes: keyof O, opts: GlideOptions<I, V>): Glide<I, O, V>;
101
32
  /**
102
- * From one value to another over `ms` along an easing, solved in closed form, so frame rate does not
103
- * change where a subject is. `to(subject, target)` retargets one subject mid-flight: the new stretch
104
- * starts from where it is and takes the full `ms` again, so its velocity jumps where a spring's
105
- * would not. Time is the voice's, so `rate` and `seek` apply, and a voice's `loop` does not repeat
106
- * it. Cue each tween on one voice. Every subject moves on the same number of axes.
33
+ * From one value to another over `ms` along an easing. Solved in closed form, so frame rate does
34
+ * not change where a subject is. `to(subject, target)` retargets one subject mid-flight: the new
35
+ * stretch starts from where it is and takes the full `ms` again, so its velocity jumps where a
36
+ * spring's would not. Time is the voice's, so `rate` and `seek` apply, and a voice's `loop` does
37
+ * not repeat it. Cue each tween on one voice. Every subject moves on the same number of axes.
107
38
  *
108
39
  * @category patch
109
40
  */
110
- export declare function tween<I, O, V extends Value = number>(writes: keyof O, opts: {
111
- /** Where each subject starts. */
112
- from: PerSubject<I, V>;
113
- /** Where each subject ends. */
114
- to: PerSubject<I, V>;
115
- /** How long a stretch takes, ms: asked per subject each time one of its stretches starts. */
116
- ms: PerSubject<I, number>;
117
- /** The curve from `from` to `to`. Default `'ease'`, as CSS's. */
118
- ease?: Easing;
119
- }): Omit<Moving<I, O, V>, 'push'> & {
120
- /**
121
- * Heads `subject` for `target` from voice time `at`, over a full `ms` from where it is: by default
122
- * the mix's latest frame, or for a subject no frame of its voice has met yet, or still inside its
123
- * stagger, its first read, after any change with a time due by then. A subject faded out of the
124
- * voice comes back at the latest frame too, however long it is before it is next read.
125
- */
126
- to(subject: I, target: V, at?: number): void;
127
- };
128
- export {};
41
+ export declare function tween<I, O, V extends Value = number>(writes: keyof O, opts: TweenOptions<I, V>): Tween<I, O, V>;
package/dist/motion.js CHANGED
@@ -1,7 +1,9 @@
1
- import { COAST, CRITICAL, EASED, OVER, UNDER } from './closed.js';
1
+ import { BOUND, COAST, CRITICAL, EASED, OVER, UNDER } from './closed.js';
2
2
  import { curve } from './easing.js';
3
3
  import { Motions } from './motions.js';
4
+ import { reading } from './reading.js';
4
5
  import { release } from './shared.js';
6
+ import { sampleThen } from './then.js';
5
7
  const axes = (v) => (typeof v === 'number' ? [v] : [...v]);
6
8
  /** Zero on every axis `x` has: a motion's velocity where its options give none. */
7
9
  const still = (x) => new Array(x.length).fill(0);
@@ -40,10 +42,18 @@ class MotionPatch {
40
42
  }
41
43
  at(_phase, subject, setting) {
42
44
  const state = this.motions;
45
+ const back = reading.back;
46
+ if (back !== null) {
47
+ const flags = sampleThen(state, subject, setting.elapsed, back);
48
+ return { [this.writes[0]]: state.valueOf(flags, state.xs) };
49
+ }
43
50
  const s = state.slot(subject);
44
51
  state.sample(s, setting.elapsed, state.xs, state.vs);
45
52
  return { [this.writes[0]]: state.value(s, state.xs) };
46
53
  }
54
+ set(subject, value, at) {
55
+ this.motions.change(subject, { at, x: axes(value) });
56
+ }
47
57
  read(subject, at) {
48
58
  const state = this.motions;
49
59
  const r = state.read(subject, at);
@@ -63,9 +73,18 @@ class SpringPatch extends TweenPatch {
63
73
  }
64
74
  }
65
75
  class GlidePatch extends MotionPatch {
76
+ edges;
77
+ constructor(writes, motions, edges) {
78
+ super(writes, motions);
79
+ this.edges = edges;
80
+ }
66
81
  push(subject, velocity, at) {
67
82
  this.motions.change(subject, { at, v: axes(velocity) });
68
83
  }
84
+ bounds(subject) {
85
+ const b = this.edges;
86
+ return b === undefined ? undefined : per(b, subject);
87
+ }
69
88
  }
70
89
  /**
71
90
  * The state behind a `'motion'` patch, for an engine that reads it directly; a patch another copy
@@ -124,12 +143,14 @@ class GlideShape {
124
143
  ms = undefined;
125
144
  start;
126
145
  speed;
146
+ edges;
127
147
  constructor(law, motion, opts, tau) {
128
148
  this.law = law;
129
149
  this.motion = motion;
130
150
  this.tau = tau;
131
151
  this.start = opts.from;
132
152
  this.speed = opts.velocity;
153
+ this.edges = opts.bounds;
133
154
  }
134
155
  spec() {
135
156
  return this.motion;
@@ -141,8 +162,24 @@ class GlideShape {
141
162
  const v = this.speed;
142
163
  return v === undefined ? still(x) : axes(per(v, s));
143
164
  }
144
- aim(x, v) {
145
- return x.map((xi, i) => xi + v[i] * this.tau);
165
+ aim(x, v, _was, s, put) {
166
+ const rest = x.map((xi, i) => xi + v[i] * this.tau);
167
+ if (this.edges === undefined)
168
+ return rest;
169
+ const [lo, hi] = per(this.edges, s);
170
+ const min = axes(lo);
171
+ const max = axes(hi);
172
+ if (min.length !== rest.length || max.length !== rest.length)
173
+ throw new Error('blits: bounds on a glide have as many axes as its subjects');
174
+ return rest.map((r, i) => {
175
+ const a = min[i];
176
+ const b = max[i];
177
+ const xi = x[i];
178
+ // A set past an edge stays there: a drag holds it out, and only a push lets it spring back.
179
+ if (put && (xi < a || xi > b))
180
+ return r;
181
+ return r < a ? a : r > b ? b : r;
182
+ });
146
183
  }
147
184
  scalar(s) {
148
185
  return typeof per(this.start, s) === 'number';
@@ -222,9 +259,15 @@ export function spring(writes, opts) {
222
259
  return new SpringPatch(writes, new Motions(new SpringShape(law, motion, opts)));
223
260
  }
224
261
  /**
225
- * Coasting under friction, a fling: a subject keeps its velocity, which falls by a factor of e every
226
- * `ms`, and comes to rest `velocity · ms / 1000` past where it was released. `push` sets it moving
227
- * again from wherever it is. Closed form, so frame rate does not change where it stops.
262
+ * A patch that coasts each subject to a stop under friction, as after a fling. A subject keeps its
263
+ * velocity, which falls by a factor of e every `ms`, and comes to rest `velocity · ms / 1000` past
264
+ * where it was released. `push` sets it moving again from wherever it is. Closed form, so frame
265
+ * rate does not change where it stops.
266
+ *
267
+ * With `bounds`, a coast that would stop past an edge springs back to it from where it crosses, at
268
+ * the speed it crosses at, on a critically damped spring of `stiffness`; one let go past an edge
269
+ * springs back from there, unless it coasts back inside. A `set` past an edge leaves the subject
270
+ * there, coasting on, until the next `push`, so a drag can hold it out.
228
271
  *
229
272
  * @category patch
230
273
  */
@@ -232,17 +275,21 @@ export function glide(writes, opts) {
232
275
  const ms = opts.ms ?? 325;
233
276
  if (!(ms > 0))
234
277
  throw new RangeError('blits: a glide takes a positive ms');
278
+ const k = opts.stiffness ?? 170;
279
+ if (!(k > 0))
280
+ throw new RangeError('blits: a glide takes a positive stiffness');
235
281
  const tau = ms / 1000;
236
282
  const settle = opts.settle ?? 1e-4;
237
- const shape = new GlideShape([COAST, settle, tau, 0, 0], { kind: 'glide', ms, settle }, opts, tau);
238
- return new GlidePatch(writes, new Motions(shape));
283
+ const bounded = opts.bounds !== undefined;
284
+ const shape = new GlideShape(bounded ? [BOUND, settle, tau, Math.sqrt(k), 0] : [COAST, settle, tau, 0, 0], bounded ? { kind: 'glide', ms, settle, stiffness: k } : { kind: 'glide', ms, settle }, opts, tau);
285
+ return new GlidePatch(writes, new Motions(shape), opts.bounds);
239
286
  }
240
287
  /**
241
- * From one value to another over `ms` along an easing, solved in closed form, so frame rate does not
242
- * change where a subject is. `to(subject, target)` retargets one subject mid-flight: the new stretch
243
- * starts from where it is and takes the full `ms` again, so its velocity jumps where a spring's
244
- * would not. Time is the voice's, so `rate` and `seek` apply, and a voice's `loop` does not repeat
245
- * it. Cue each tween on one voice. Every subject moves on the same number of axes.
288
+ * From one value to another over `ms` along an easing. Solved in closed form, so frame rate does
289
+ * not change where a subject is. `to(subject, target)` retargets one subject mid-flight: the new
290
+ * stretch starts from where it is and takes the full `ms` again, so its velocity jumps where a
291
+ * spring's would not. Time is the voice's, so `rate` and `seek` apply, and a voice's `loop` does
292
+ * not repeat it. Cue each tween on one voice. Every subject moves on the same number of axes.
246
293
  *
247
294
  * @category patch
248
295
  */
package/dist/motions.d.ts CHANGED
@@ -1,92 +1,17 @@
1
+ import { applied, change, commit, cut, dueTo, insert, peek, queue, rewind } from './changes.js';
1
2
  import type { Curve } from './easing.js';
3
+ import { made, pack, prune, type Released, reclaim, release, restretch, runAt, runThen, unpack, unrelease } from './lives.js';
4
+ import { Numbers } from './numbers.js';
5
+ import { Store } from './store.js';
6
+ import { type Change, type MotionOwner, type Run, type Segment, type Shape, type Watcher } from './stretch.js';
2
7
  import type { MotionSpec } from './types.js';
3
8
  /**
4
- * One closed-form stretch: released at `at` (voice ms) from `x0` moving at `v0`, toward `to`, over
5
- * `ms` for a tween (0 for any other shape).
9
+ * A patch's law, `[form, settle, k1, k2, k3]`: which closed form its stretches follow, its `settle`,
10
+ * and up to three constants that form reads. It heads the patch's `runs`, so `solve` finds them in
11
+ * the buffer a sample already reads rather than in an object of their own.
6
12
  */
7
- export interface Segment {
8
- at: number;
9
- ms: number;
10
- x0: number[];
11
- v0: number[];
12
- to: number[];
13
- /** The change that released it; undefined for a subject's first stretch. */
14
- change?: Change;
15
- }
16
- export interface Change {
17
- /**
18
- * Voice ms it takes effect at; absent, until the subject's next read stamps it with that read's
19
- * time, for one made while no frame had met the subject.
20
- */
21
- at?: number;
22
- to?: number[];
23
- v?: number[];
24
- /** The mix clock when it was made, NaN where no mix was playing the patch. */
25
- made?: number;
26
- /** The frame it was made in, which a rewind partitions by; NaN where no mix was playing the patch. */
27
- seq?: number;
28
- }
29
- /**
30
- * The mix playing a patch, asked with its voice's id: an owner and an id, where a pair of closures
31
- * cost two functions, their contexts and a weak reference per voice.
32
- */
33
- export interface MotionOwner {
34
- /** The subject's voice time at the mix's latest frame; NaN where no frame of the voice met it. */
35
- frame(id: number, subject: unknown): number;
36
- /**
37
- * Brings a subject the voice faded out back to it, so a change is not made for nothing: its
38
- * voice time now, which a change bringing it back is made at; NaN for any other subject.
39
- */
40
- revive(id: number, subject: unknown): number;
41
- /** The mix clock at its latest frame; NaN before the first. */
42
- now(): number;
43
- /** The number of the frame the mix is playing. */
44
- seq(): number;
45
- /**
46
- * The host made a change, already given its time, which a seek makes again on the patch its
47
- * voice plays then: a voice a history store paged out comes back with a patch of its own.
48
- */
49
- changed<I>(id: number, motion: Motions<I>, subject: I, change: Change): void;
50
- /** History leaving memory for a subject, which a mix with a history store pages out. */
51
- page(id: number, stream: 'released' | 'stretch', subject: unknown, out: Paging[]): void;
52
- }
53
- /** A record of a motion patch's history leaving memory, at a mix time and frame. */
54
- export interface Paging {
55
- at: number;
56
- seq: number;
57
- data: unknown;
58
- }
59
- /** A subject's run as plain data: its flags, its stretches oldest first, and changes still to apply. */
60
- export interface Run {
61
- flags: number;
62
- stretches: Segment[];
63
- pending: Change[] | undefined;
64
- }
65
- /**
66
- * What a mix keeping copies of a patch's stretches is told, with its id and the subject's number,
67
- * before one changes.
68
- */
69
- export interface Watcher {
70
- stretchChanged(id: number, s: number): void;
71
- }
72
- export interface Shape<I> {
73
- from: (subject: I) => number[];
74
- /** How fast each axis starts moving, given where it starts: still unless the options say. */
75
- velocity: (subject: I, x: number[]) => number[];
76
- /** Where it heads when released from `x` at `v`, given where it was heading. */
77
- aim: (x: number[], v: number[], was: number[] | null, subject: I) => number[];
78
- /** `[form, settle, k1, k2, k3]`. */
79
- law: readonly number[];
80
- /** Whether a subject's value is a number rather than an array. */
81
- scalar: (subject: I) => boolean;
82
- /** Whether every subject's value is a number; undefined where that depends on the subject. */
83
- scalarEvery(): boolean | undefined;
84
- /** A tween's easing, which its law cannot hold; undefined, but present, on every other shape. */
85
- ease: Curve | undefined;
86
- /** A tween's ms for a stretch the subject starts now; undefined, but present, on the rest. */
87
- ms: ((subject: I) => number) | undefined;
88
- /** The patch's kind and constants, as `Patch.motion` reports them. */
89
- spec(): MotionSpec;
13
+ export declare const enum Law {
14
+ HEAD = 5
90
15
  }
91
16
  /**
92
17
  * A motion patch's subjects: the stretch each is playing, in one flat array by a number the patch
@@ -99,16 +24,17 @@ export interface Shape<I> {
99
24
  * object of its own took a call from 130 ns to 490.
100
25
  */
101
26
  export declare class Motions<I> {
102
- private readonly shape;
103
- private readonly numbers;
27
+ readonly shape: Shape<I>;
28
+ readonly numbers: Numbers<I>;
104
29
  /** Numbers by subject once a second is numbered: till then the one subject is found by `numbers`. */
105
- private readonly slots;
30
+ readonly slots: Store<I, number>;
106
31
  /** How many numbers have been given up, so a number kept elsewhere can tell it is stale. */
107
32
  freed: number;
108
33
  /** Axes per subject; -1 until the first subject sets it. */
109
34
  n: number;
110
35
  private cap;
111
- private stride;
36
+ /** Numbers in each subject's run; a run starts at `base`. Written only here. */
37
+ stride: number;
112
38
  /**
113
39
  * The law, then each subject's run; empty until the first subject, the law read from `shape`.
114
40
  * Read outside, at `bareAt`, and written only here.
@@ -125,10 +51,10 @@ export declare class Motions<I> {
125
51
  * until a subject first has one, since many patches are never changed. Each starts with room for
126
52
  * one: an empty array written at 0 reserves 17, and most patches have one subject.
127
53
  */
128
- private pending;
129
- private older;
54
+ pending: (Change[] | undefined)[] | null;
55
+ older: (Segment[] | undefined)[] | null;
130
56
  /** By subject number, the change that released the stretch it is playing; null until one has. */
131
- private causes;
57
+ causes: (Change | undefined)[] | null;
132
58
  /**
133
59
  * The mix playing the patch and its voice's id, which an untimed change and a `read` with no time
134
60
  * ask for the latest frame. Set by the mix that cues the patch, and cleared when its voice retires.
@@ -143,43 +69,29 @@ export declare class Motions<I> {
143
69
  * where every subject's value is one kind, else on the first sample of a subject whose value is not.
144
70
  */
145
71
  cuedOn(channel: string, holdsNumber: boolean): void;
146
- private frame;
72
+ frame(subject: I): number;
147
73
  constructor(shape: Shape<I>);
148
74
  /** The patch's number for `subject`, made with its first stretch on first ask. */
149
75
  slot(subject: I): number;
76
+ /** The flags of the run `fresh` last started. */
77
+ private freshFlags;
78
+ /** The stretch a subject met afresh starts with, its axes and the law set up for it, numbering no one. */
79
+ fresh(subject: I): Segment;
80
+ /** The run `fresh` starts, as plain data. */
81
+ freshRun(subject: I): Run;
150
82
  /** Sets the axes every subject moves on, at the first. */
151
- private size;
83
+ size(n: number): void;
152
84
  /** Numbers `subject`, with room for its run. */
153
- private take;
85
+ take(subject: I): number;
154
86
  /** The patch's number for `subject`, undefined where it has none. */
155
- private known;
87
+ known(subject: I): number | undefined;
156
88
  /**
157
89
  * Subjects released at a mix time a rewind may still reach, with their run as it stood, so a
158
90
  * rewind before the release plays them on from there. Empty without history.
159
91
  */
160
- private released;
161
- /**
162
- * Forgets a subject, so a later ask starts it afresh from `from`. Given the mix time `at` and frame
163
- * `seq`, under history, its run is kept for a rewind before then, until `reach` passes it.
164
- */
165
- release(subject: I, at?: number, reach?: number, seq?: number): void;
166
- /** Puts back each subject released after frame `seq`, as it stood when released. */
167
- private unrelease;
168
- /** Subject `s`'s run as it stands. */
169
- private runAt;
92
+ released: Released<I>[];
170
93
  /** Whether the patch holds a run for `subject`. */
171
94
  holds(subject: I): boolean;
172
- /** A subject's run as plain data, for a voice leaving memory; undefined where it has none. */
173
- pack(subject: I): Run | undefined;
174
- /** Puts a subject's run back as `pack` or a release left it, replacing any it has now. */
175
- unpack(subject: I, run: Run): void;
176
- /** A released run a history store gave back, for a rewind to before its release. */
177
- reclaim(subject: I, at: number, seq: number, run: Run): void;
178
- /**
179
- * Stretches a history store gave back, each by the frame it was in force by: each life of the
180
- * subject, ended by a release, takes those from its own, ahead of the earliest it still keeps.
181
- */
182
- restretch(subject: I, back: readonly Paging[]): void;
183
95
  /**
184
96
  * Told, with `watchId`, whenever a subject's stretch or what is pending for it changes, so a mix
185
97
  * keeping a copy of it knows to read it again. Set by the mix, cleared when its voice retires. An
@@ -205,6 +117,8 @@ export declare class Motions<I> {
205
117
  scalar(s: number): boolean;
206
118
  /** The value `at` hands the mix: the first axis for a number, a fresh array otherwise. */
207
119
  value(s: number, xs: Float64Array): number | number[];
120
+ /** The value `at` hands the mix for a run with `flags`. */
121
+ valueOf(flags: number, xs: Float64Array): number | number[];
208
122
  /**
209
123
  * Position and velocity at voice time `t` into `xo` and `vo`, a tween's velocity left at 0. A live
210
124
  * read stamps every untimed change with `t` and commits every change due by then, in time order;
@@ -237,44 +151,42 @@ export declare class Motions<I> {
237
151
  v: Float64Array;
238
152
  s: number;
239
153
  } | undefined;
240
- /**
241
- * Queues a retarget or push, untimed at the latest frame, for `subject`'s next read past its time.
242
- * The queue keeps the changes with a time in time order, ahead of any still waiting for one.
243
- */
244
- change(subject: I, c: Change): void;
245
- /** Files a change with a time after every one due by then, ahead of those still waiting for one. */
246
- private queue;
247
- /** Every change due by `t` applied to a copy of the stretch playing then, committing nothing. */
248
- private peek;
249
- /** Subject `s`'s changes waiting, with those a read ahead's tape made filed among them by time. */
250
- private dueTo;
251
- private check;
252
- private flag;
154
+ check(a: readonly number[] | undefined, n: number): void;
155
+ flag(s: number, bit: number, on: boolean): void;
253
156
  forget(s: number): void;
254
- /**
255
- * Takes back every change made after frame `seq`: each subject plays from its earliest stretch
256
- * kept, with the changes made by then queued to be applied again.
257
- */
258
- rewind(seq: number): void;
259
- private cut;
260
157
  /** Where subject `s`'s run starts in `runs`. */
261
158
  base(s: number): number;
262
159
  private grow;
263
- private write;
160
+ write(s: number, seg: Segment): void;
264
161
  /** The stretch subject `s` is playing now, as an object. */
265
- private latest;
162
+ latest(s: number): Segment;
266
163
  /** The stretch playing at voice time `t`: the latest released by then, else the first. */
267
- private playing;
268
- private applied;
269
- private commit;
270
- private insert;
271
- /**
272
- * The mix time and frame a stretch was in force by, which a store keys it under: when the change
273
- * that ended it was made, which falls in the same life of the subject.
274
- */
275
- private made;
276
- /** Lets go of stretches older than the one in force at `reading.horizon`. */
277
- private prune;
278
- private evaluateSegment;
164
+ playing(s: number, t: number): Segment;
165
+ evaluateSegment(seg: Segment, t: number, xo: Float64Array, vo: Float64Array): void;
279
166
  private evaluate;
280
167
  }
168
+ declare const methods: {
169
+ release: typeof release;
170
+ unrelease: typeof unrelease;
171
+ runAt: typeof runAt;
172
+ pack: typeof pack;
173
+ unpack: typeof unpack;
174
+ reclaim: typeof reclaim;
175
+ runThen: typeof runThen;
176
+ restretch: typeof restretch;
177
+ made: typeof made;
178
+ prune: typeof prune;
179
+ change: typeof change;
180
+ queue: typeof queue;
181
+ peek: typeof peek;
182
+ dueTo: typeof dueTo;
183
+ rewind: typeof rewind;
184
+ cut: typeof cut;
185
+ applied: typeof applied;
186
+ commit: typeof commit;
187
+ insert: typeof insert;
188
+ };
189
+ type Methods = typeof methods;
190
+ export interface Motions<I> extends Methods {
191
+ }
192
+ export {};