@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.
- package/CHANGELOG.md +183 -0
- package/README.md +20 -3
- package/dist/ahead.d.ts +26 -0
- package/dist/ahead.js +264 -0
- package/dist/around.d.ts +11 -0
- package/dist/around.js +32 -0
- package/dist/bare.js +15 -7
- package/dist/blank.d.ts +10 -0
- package/dist/blank.js +26 -0
- package/dist/blend.d.ts +2 -1
- package/dist/blend.js +1 -6
- package/dist/bound.d.ts +70 -0
- package/dist/bound.js +351 -0
- package/dist/chain.d.ts +2 -1
- package/dist/chain.js +7 -5
- package/dist/changes.d.ts +24 -0
- package/dist/changes.js +189 -0
- package/dist/channels.d.ts +39 -13
- package/dist/channels.js +14 -5
- package/dist/closed.d.ts +1 -0
- package/dist/closed.js +45 -1
- package/dist/color.d.ts +12 -10
- package/dist/color.js +25 -25
- package/dist/columns.js +7 -3
- package/dist/contribution.d.ts +30 -0
- package/dist/contribution.js +374 -0
- package/dist/copyout.d.ts +10 -0
- package/dist/copyout.js +69 -24
- package/dist/crowd.d.ts +8 -2
- package/dist/crowd.js +4 -5
- package/dist/cue.d.ts +8 -1
- package/dist/cue.js +47 -14
- package/dist/cut.d.ts +8 -0
- package/dist/cut.js +4 -0
- package/dist/drop.d.ts +9 -0
- package/dist/drop.js +84 -0
- package/dist/due.d.ts +24 -5
- package/dist/due.js +113 -33
- package/dist/easing.d.ts +4 -4
- package/dist/easing.js +3 -3
- package/dist/everyone.d.ts +3 -2
- package/dist/everyone.js +3 -3
- package/dist/fade.d.ts +2 -1
- package/dist/fade.js +2 -1
- package/dist/fill.d.ts +3 -2
- package/dist/fill.js +51 -19
- package/dist/fit.d.ts +44 -26
- package/dist/fit.js +10 -9
- package/dist/fling.d.ts +66 -0
- package/dist/fling.js +162 -0
- package/dist/fold.d.ts +4 -37
- package/dist/fold.js +5 -512
- package/dist/gather.d.ts +12 -7
- package/dist/gather.js +179 -44
- package/dist/gone.js +2 -2
- package/dist/grid.d.ts +47 -0
- package/dist/grid.js +247 -0
- package/dist/handle.d.ts +3 -0
- package/dist/handle.js +19 -8
- package/dist/held.d.ts +2 -1
- package/dist/history.d.ts +6 -5
- package/dist/history.js +9 -9
- package/dist/hosts.js +9 -15
- package/dist/index.d.ts +5 -4
- package/dist/keyfill.d.ts +1 -1
- package/dist/keyfill.js +5 -3
- package/dist/keyrows.d.ts +12 -0
- package/dist/keyrows.js +99 -12
- package/dist/lane.d.ts +36 -6
- package/dist/lane.js +32 -1
- package/dist/lanes.d.ts +23 -8
- package/dist/lanes.js +29 -8
- package/dist/leavings.d.ts +2 -2
- package/dist/leavings.js +1 -1
- package/dist/lives.d.ts +47 -0
- package/dist/lives.js +180 -0
- package/dist/meet.d.ts +2 -2
- package/dist/meet.js +90 -4
- package/dist/mixer.d.ts +61 -35
- package/dist/mixer.js +64 -169
- package/dist/motion.d.ts +19 -106
- package/dist/motion.js +60 -13
- package/dist/motions.d.ts +62 -150
- package/dist/motions.js +57 -369
- package/dist/move.js +24 -1
- package/dist/moved.d.ts +1 -1
- package/dist/moved.js +16 -7
- package/dist/named.d.ts +0 -1
- package/dist/named.js +20 -2
- package/dist/numbers.d.ts +2 -0
- package/dist/numbers.js +4 -0
- package/dist/owed.d.ts +2 -0
- package/dist/owed.js +4 -0
- package/dist/pack.d.ts +3 -1
- package/dist/pack.js +4 -3
- package/dist/patch.d.ts +7 -3
- package/dist/patch.js +6 -2
- package/dist/places.d.ts +53 -0
- package/dist/places.js +171 -0
- package/dist/plot.d.ts +12 -0
- package/dist/plot.js +52 -0
- package/dist/project.d.ts +4 -4
- package/dist/project.js +9 -211
- package/dist/pull.js +11 -8
- package/dist/qualify.js +84 -21
- package/dist/reading.d.ts +6 -0
- package/dist/reading.js +5 -0
- package/dist/record.d.ts +5 -1
- package/dist/record.js +4 -2
- package/dist/relink.d.ts +1 -1
- package/dist/restored.d.ts +2 -2
- package/dist/restored.js +1 -1
- package/dist/rests.d.ts +9 -0
- package/dist/rests.js +76 -0
- package/dist/revive.d.ts +3 -2
- package/dist/revive.js +2 -2
- package/dist/{locus.d.ts → role.d.ts} +10 -9
- package/dist/{locus.js → role.js} +3 -3
- package/dist/roles.d.ts +10 -0
- package/dist/roles.js +158 -0
- package/dist/roster.js +3 -3
- package/dist/rotation.d.ts +1 -1
- package/dist/rotation.js +1 -1
- package/dist/rows.js +1 -1
- package/dist/sample.d.ts +2 -2
- package/dist/sample.js +33 -7
- package/dist/seek.js +13 -5
- package/dist/setting.d.ts +27 -0
- package/dist/setting.js +55 -0
- package/dist/shared.d.ts +1 -1
- package/dist/shared.js +1 -1
- package/dist/signals.d.ts +64 -32
- package/dist/signals.js +20 -18
- package/dist/stack.d.ts +5 -5
- package/dist/stack.js +5 -5
- package/dist/standing.d.ts +2 -1
- package/dist/standing.js +3 -2
- package/dist/store.d.ts +9 -0
- package/dist/store.js +24 -0
- package/dist/strays.d.ts +2 -1
- package/dist/strays.js +21 -14
- package/dist/stretch.d.ts +112 -0
- package/dist/stretch.js +9 -0
- package/dist/subject.d.ts +142 -0
- package/dist/subject.js +1 -0
- package/dist/tape.d.ts +9 -5
- package/dist/tape.js +5 -1
- package/dist/then.d.ts +9 -0
- package/dist/then.js +57 -0
- package/dist/ticker.d.ts +4 -4
- package/dist/transport.d.ts +0 -8
- package/dist/transport.js +0 -4
- package/dist/turns.d.ts +4 -3
- package/dist/turns.js +4 -3
- package/dist/types/arc.d.ts +12 -11
- package/dist/types/channel.d.ts +12 -8
- package/dist/types/history.d.ts +35 -19
- package/dist/types/mix.d.ts +222 -161
- package/dist/types/motion.d.ts +151 -0
- package/dist/types/motion.js +1 -0
- package/dist/types/patch.d.ts +69 -34
- package/dist/types/place.d.ts +51 -36
- package/dist/types/transport.d.ts +20 -18
- package/dist/types/voice.d.ts +145 -72
- package/dist/types/watch.d.ts +88 -40
- package/dist/types.d.ts +1 -0
- package/dist/voice.d.ts +9 -141
- package/dist/voice.js +30 -79
- package/dist/warn.d.ts +2 -0
- package/dist/warn.js +1 -1
- package/dist/watch.d.ts +2 -2
- package/dist/watch.js +5 -3
- package/dist/wave.d.ts +4 -3
- package/dist/wave.js +3 -2
- package/dist/weigh.d.ts +7 -1
- package/dist/weigh.js +27 -0
- package/docs/schema.html +223 -37
- 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 {
|
|
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:
|
|
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
|
-
*
|
|
90
|
-
* `ms`, and comes to rest `velocity · ms / 1000` past
|
|
91
|
-
* again from wherever it is. Closed form, so frame
|
|
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:
|
|
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
|
|
103
|
-
* change where a subject is. `to(subject, target)` retargets one subject mid-flight: the new
|
|
104
|
-
* starts from where it is and takes the full `ms` again, so its velocity jumps where a
|
|
105
|
-
* would not. Time is the voice's, so `rate` and `seek` apply, and a voice's `loop` does
|
|
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
|
-
|
|
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
|
-
*
|
|
226
|
-
* `ms`, and comes to rest `velocity · ms / 1000` past
|
|
227
|
-
* again from wherever it is. Closed form, so frame
|
|
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
|
|
238
|
-
|
|
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
|
|
242
|
-
* change where a subject is. `to(subject, target)` retargets one subject mid-flight: the new
|
|
243
|
-
* starts from where it is and takes the full `ms` again, so its velocity jumps where a
|
|
244
|
-
* would not. Time is the voice's, so `rate` and `seek` apply, and a voice's `loop` does
|
|
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
|
-
*
|
|
5
|
-
*
|
|
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
|
|
8
|
-
|
|
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
|
-
|
|
103
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
129
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
83
|
+
size(n: number): void;
|
|
152
84
|
/** Numbers `subject`, with room for its run. */
|
|
153
|
-
|
|
85
|
+
take(subject: I): number;
|
|
154
86
|
/** The patch's number for `subject`, undefined where it has none. */
|
|
155
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
160
|
+
write(s: number, seg: Segment): void;
|
|
264
161
|
/** The stretch subject `s` is playing now, as an object. */
|
|
265
|
-
|
|
162
|
+
latest(s: number): Segment;
|
|
266
163
|
/** The stretch playing at voice time `t`: the latest released by then, else the first. */
|
|
267
|
-
|
|
268
|
-
|
|
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 {};
|