@msb235/blits 0.15.1 → 0.16.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 +35 -0
- package/README.md +1 -1
- package/dist/ahead.js +5 -4
- package/dist/chain.js +2 -3
- package/dist/color.d.ts +36 -14
- package/dist/color.js +186 -58
- package/dist/columns.d.ts +1 -11
- package/dist/columns.js +1 -6
- package/dist/crowd.d.ts +0 -6
- package/dist/crowd.js +0 -11
- package/dist/cue.js +7 -4
- package/dist/everyone.d.ts +17 -6
- package/dist/everyone.js +17 -8
- package/dist/fade.d.ts +11 -0
- package/dist/fade.js +44 -8
- package/dist/fold.js +4 -7
- package/dist/held.js +3 -4
- package/dist/hosts.d.ts +7 -0
- package/dist/hosts.js +18 -5
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lanes.d.ts +26 -1
- package/dist/lanes.js +7 -0
- package/dist/lch.d.ts +23 -0
- package/dist/lch.js +126 -0
- package/dist/mixer.d.ts +4 -1
- package/dist/mixer.js +3 -0
- package/dist/motions.d.ts +4 -1
- package/dist/motions.js +16 -2
- package/dist/move.js +15 -10
- package/dist/owner.d.ts +7 -2
- package/dist/owner.js +13 -3
- package/dist/project.js +3 -8
- package/dist/pull.d.ts +11 -0
- package/dist/pull.js +10 -6
- package/dist/qualify.js +1 -1
- package/dist/roles.js +1 -3
- package/dist/roster.d.ts +6 -0
- package/dist/roster.js +8 -1
- package/dist/sample.js +2 -1
- package/dist/seek.js +1 -13
- package/dist/shared.d.ts +1 -1
- package/dist/shared.js +1 -1
- package/dist/spans.d.ts +4 -1
- package/dist/spans.js +6 -3
- package/dist/touch.js +1 -2
- package/dist/turns.js +2 -1
- package/dist/types/voice.d.ts +3 -2
- package/dist/voice.d.ts +19 -0
- package/dist/voice.js +35 -1
- package/docs/schema.html +37 -11
- package/package.json +1 -1
package/dist/everyone.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { headOf } from './chain.js';
|
|
2
2
|
import { numericOf } from './channels.js';
|
|
3
3
|
import { record } from './record.js';
|
|
4
|
+
import { detour } from './roster.js';
|
|
4
5
|
/**
|
|
5
6
|
* Whether a voice can keep one record for every subject, decided when it is cued. A record holds
|
|
6
7
|
* what a voice knows of one subject; where the voice is over every subject with no stagger, keeps
|
|
@@ -263,17 +264,25 @@ export function unshare(mix, voice, kept = false, keeper) {
|
|
|
263
264
|
detour(mix);
|
|
264
265
|
mix.lanes?.refill();
|
|
265
266
|
}
|
|
266
|
-
/**
|
|
267
|
-
* Counts what makes a mix's fold more than a walk of each chain: a role, a voice sharing one
|
|
268
|
-
* record, a voice that stopped sharing this frame. Called wherever one of the three changes, so
|
|
269
|
-
* `foldWith` asks one number.
|
|
270
|
-
*/
|
|
271
|
-
export function detour(mix) {
|
|
272
|
-
mix.detours = mix.roleVoices + mix.sharers.length + (mix.unshared ? 1 : 0);
|
|
273
|
-
}
|
|
274
267
|
/** Gives a record just made for a subject a sharing voice had seen what the voice kept for it. */
|
|
275
268
|
export function inherit(voice, held, slot) {
|
|
276
269
|
held.weight = weightAt(voice, slot);
|
|
277
270
|
open(voice, held, slot);
|
|
278
271
|
unsight(voice, slot);
|
|
279
272
|
}
|
|
273
|
+
/** What the general path calls on a sharing voice, reached through `Lanes`, so a lean bundle leaves it out. */
|
|
274
|
+
export const share = {
|
|
275
|
+
shares,
|
|
276
|
+
outgrow,
|
|
277
|
+
everyoneOf,
|
|
278
|
+
sighted,
|
|
279
|
+
sight,
|
|
280
|
+
weightAt,
|
|
281
|
+
weighAt,
|
|
282
|
+
open,
|
|
283
|
+
shut,
|
|
284
|
+
restamp,
|
|
285
|
+
unsight,
|
|
286
|
+
unshare,
|
|
287
|
+
inherit,
|
|
288
|
+
};
|
package/dist/fade.d.ts
CHANGED
|
@@ -30,7 +30,13 @@ export declare function beginFade<I, O>(mix: Mixer<I, O>, voice: Voice<I, O>, op
|
|
|
30
30
|
at?: 'rest';
|
|
31
31
|
deadline?: number;
|
|
32
32
|
back?: boolean;
|
|
33
|
+
stays?: boolean;
|
|
33
34
|
}, at?: number): void;
|
|
35
|
+
/**
|
|
36
|
+
* Keeps a voice faded at the end of its passes with its owner, live and quiet, rather than letting
|
|
37
|
+
* it leave; the owner leaves at `at` if it holds no child still playing.
|
|
38
|
+
*/
|
|
39
|
+
export declare function stay<I, O>(mix: Mixer<I, O>, voice: Voice<I, O>, at: number): void;
|
|
34
40
|
/**
|
|
35
41
|
* Turns a fading voice around: it climbs back from where its fade out had got to, up the same
|
|
36
42
|
* curve, at the whole curve per `over` ms. A fade waiting for rest is taken back at once. A voice
|
|
@@ -44,5 +50,10 @@ export declare function beginRise<I, O>(mix: Mixer<I, O>, voice: Voice<I, O>, op
|
|
|
44
50
|
* exactly there; at or behind now, the fade began then and is partway.
|
|
45
51
|
*/
|
|
46
52
|
export declare function fadeAt<I, O>(mix: Mixer<I, O>, voice: Voice<I, O>, at: number, over: number | undefined): void;
|
|
53
|
+
/**
|
|
54
|
+
* Brings back a voice kept quiet past its passes, its clock back in them by mix time `now`: it
|
|
55
|
+
* climbs from nothing over the fade it left over, from when its clock reached them.
|
|
56
|
+
*/
|
|
57
|
+
export declare function rouse<I, O>(mix: Mixer<I, O>, voice: Voice<I, O>, now: number): void;
|
|
47
58
|
/** Removes a voice, recording that it left at `at`, default now. */
|
|
48
59
|
export declare function retire<I, O>(mix: Mixer<I, O>, voice: Voice<I, O>, at?: number): void;
|
package/dist/fade.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { changed, headOf, unlink } from './chain.js';
|
|
2
2
|
import { envelope } from './clock.js';
|
|
3
3
|
import { schedule } from './due.js';
|
|
4
|
-
import { unshare, unsight } from './everyone.js';
|
|
5
4
|
import { leave, noted, releasing } from './history.js';
|
|
6
5
|
import { markOf } from './marks.js';
|
|
7
|
-
import { orphan, ownerReading } from './owner.js';
|
|
6
|
+
import { orphan, ownerReading, plays } from './owner.js';
|
|
8
7
|
import { startOf } from './place.js';
|
|
9
8
|
import { isRested } from './record.js';
|
|
10
9
|
import { scoreTouched } from './scored.js';
|
|
@@ -14,7 +13,7 @@ import { unreach } from './unreached.js';
|
|
|
14
13
|
export function fadeSubject(mix, voice, subject, over) {
|
|
15
14
|
if (voice.state === 'done' || voice.parted?.has(subject) || voice.parts?.has(subject))
|
|
16
15
|
return;
|
|
17
|
-
unshare(mix, voice);
|
|
16
|
+
mix.share?.unshare(mix, voice);
|
|
18
17
|
mix.stir();
|
|
19
18
|
const ms = mix.reduced ? 0 : (over ?? voice.fade.out ?? 0);
|
|
20
19
|
const at = Number.isNaN(mix.now) ? startOf(voice) : mix.now;
|
|
@@ -104,7 +103,7 @@ function forgetIn(mix, voice, subject) {
|
|
|
104
103
|
if (head !== undefined && head.slot >= 0) {
|
|
105
104
|
unreach(voice, head.slot, false);
|
|
106
105
|
// What the voice kept for the subject while it shared one record, which `weightOf` reads.
|
|
107
|
-
unsight(voice, head.slot);
|
|
106
|
+
mix.share?.unsight(voice, head.slot);
|
|
108
107
|
}
|
|
109
108
|
const held = voice.subjects.get(subject);
|
|
110
109
|
if (held !== undefined) {
|
|
@@ -135,7 +134,7 @@ export function beginFade(mix, voice, opts, at) {
|
|
|
135
134
|
// A fade at rest marks each subject's record as it comes to rest, at its next read: one already
|
|
136
135
|
// read this frame is read again, as after `touch`.
|
|
137
136
|
if (opts.at === 'rest') {
|
|
138
|
-
unshare(mix, voice);
|
|
137
|
+
mix.share?.unshare(mix, voice);
|
|
139
138
|
voice.seeks++;
|
|
140
139
|
}
|
|
141
140
|
voice.state = 'fading';
|
|
@@ -148,14 +147,36 @@ export function beginFade(mix, voice, opts, at) {
|
|
|
148
147
|
};
|
|
149
148
|
if (opts.back)
|
|
150
149
|
voice.out.back = true;
|
|
150
|
+
if (opts.stays)
|
|
151
|
+
voice.out.stays = true;
|
|
151
152
|
noted(mix, voice);
|
|
152
153
|
// A fade at rest, from a voice's start, or of a voice yet to start takes it off its lane.
|
|
153
154
|
if (opts.at === 'rest' || opts.back || waiting)
|
|
154
155
|
mix.lanes?.invalidate();
|
|
155
156
|
else
|
|
156
157
|
mix.lanes?.refill();
|
|
157
|
-
if (over === 0 && opts.at !== 'rest')
|
|
158
|
-
|
|
158
|
+
if (over === 0 && opts.at !== 'rest') {
|
|
159
|
+
if (opts.stays)
|
|
160
|
+
stay(mix, voice, voice.out.at);
|
|
161
|
+
else
|
|
162
|
+
retire(mix, voice, voice.out.at);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Keeps a voice faded at the end of its passes with its owner, live and quiet, rather than letting
|
|
167
|
+
* it leave; the owner leaves at `at` if it holds no child still playing.
|
|
168
|
+
*/
|
|
169
|
+
export function stay(mix, voice, at) {
|
|
170
|
+
voice.state = 'live';
|
|
171
|
+
mix.lanes?.refill();
|
|
172
|
+
const owner = voice.owner;
|
|
173
|
+
if (owner.state === 'done')
|
|
174
|
+
return;
|
|
175
|
+
const now = Number.isNaN(mix.now) ? Number.NEGATIVE_INFINITY : mix.now;
|
|
176
|
+
if (!plays(owner, now) && !lingers(owner, at))
|
|
177
|
+
retire(mix, owner, at);
|
|
178
|
+
else if (owner.fitting !== null && !voice.skipped)
|
|
179
|
+
refit(mix, owner, at);
|
|
159
180
|
}
|
|
160
181
|
/**
|
|
161
182
|
* Turns a fading voice around: it climbs back from where its fade out had got to, up the same
|
|
@@ -211,6 +232,21 @@ export function fadeAt(mix, voice, at, over) {
|
|
|
211
232
|
voice.outSet = true;
|
|
212
233
|
noted(mix, voice);
|
|
213
234
|
}
|
|
235
|
+
/**
|
|
236
|
+
* Brings back a voice kept quiet past its passes, its clock back in them by mix time `now`: it
|
|
237
|
+
* climbs from nothing over the fade it left over, from when its clock reached them.
|
|
238
|
+
*/
|
|
239
|
+
export function rouse(mix, voice, now) {
|
|
240
|
+
const out = voice.out;
|
|
241
|
+
const edge = out.back === true ? voice.soonest : voice.span + voice.latest;
|
|
242
|
+
const reached = voice.reaches(edge);
|
|
243
|
+
const at = Math.max(out.at + out.over, reached <= now ? reached : now);
|
|
244
|
+
const over = mix.reduced ? 0 : out.over;
|
|
245
|
+
voice.out = null;
|
|
246
|
+
voice.back = over > 0 ? { from: 0, at, over } : null;
|
|
247
|
+
noted(mix, voice);
|
|
248
|
+
mix.lanes?.refill();
|
|
249
|
+
}
|
|
214
250
|
/** Whether a motion patch still asks this voice of this mix for its time. */
|
|
215
251
|
function asks(mix, motion, voice) {
|
|
216
252
|
return motion.owner === mix.owner && motion.ownerId === voice.id;
|
|
@@ -248,7 +284,7 @@ export function retire(mix, voice, at) {
|
|
|
248
284
|
if (voice.owner !== null) {
|
|
249
285
|
const span = voice.owner;
|
|
250
286
|
leaving(mix, voice);
|
|
251
|
-
const owner = orphan(voice);
|
|
287
|
+
const owner = orphan(voice, now);
|
|
252
288
|
if (owner !== null && !lingers(owner, voice.doneAt))
|
|
253
289
|
retire(mix, owner, voice.doneAt);
|
|
254
290
|
// A child the fit skipped had no time in it, so the rest of the fit stands: fitting again
|
package/dist/fold.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { foldNumber } from './channels.js';
|
|
2
2
|
import { copy as copyValue, first } from './clone.js';
|
|
3
|
-
import { open as openRecord, shut as shutRecord, weighAt } from './everyone.js';
|
|
4
3
|
// V8 reads a local const as a constant, where it reads an import from its module on every call.
|
|
5
4
|
const copy = copyValue;
|
|
6
|
-
const open = openRecord;
|
|
7
|
-
const shut = shutRecord;
|
|
8
5
|
/** A record's band state, made when a rest-less channel first asks. */
|
|
9
6
|
function bandsFor(held, n) {
|
|
10
7
|
const bands = new Uint8Array(n);
|
|
@@ -107,9 +104,9 @@ export function shared(voice, slot, rec, q) {
|
|
|
107
104
|
// A projection numbers no subject, and keeps nothing by subject.
|
|
108
105
|
if (slot < 0)
|
|
109
106
|
return q;
|
|
110
|
-
const
|
|
111
|
-
weighAt(voice, slot, rec.weight, cap);
|
|
112
|
-
shut(voice, rec, slot, cap);
|
|
107
|
+
const lanes = this.lanes;
|
|
108
|
+
this.share.weighAt(voice, slot, rec.weight, lanes.cap);
|
|
109
|
+
this.share.shut(voice, rec, slot, lanes.cap);
|
|
113
110
|
return q;
|
|
114
111
|
}
|
|
115
112
|
const sharers = this.sharers;
|
|
@@ -265,7 +262,7 @@ export function foldSharers(pose, subject, head, q, before, laned, dry, except,
|
|
|
265
262
|
continue;
|
|
266
263
|
if (voice.id === except || voice.state === 'done')
|
|
267
264
|
continue;
|
|
268
|
-
open(voice, rec, head.slot);
|
|
265
|
+
this.share.open(voice, rec, head.slot);
|
|
269
266
|
const delta = this.read(voice, subject, now, dry, rec);
|
|
270
267
|
if (owed >= 0 && voice.laned)
|
|
271
268
|
this.lanes.paid(voice.id, owed, rec.weight);
|
package/dist/held.js
CHANGED
|
@@ -2,7 +2,6 @@ import { changed } from './chain.js';
|
|
|
2
2
|
import { stepOf } from './clock.js';
|
|
3
3
|
import { delayOf } from './delay.js';
|
|
4
4
|
import { schedule } from './due.js';
|
|
5
|
-
import { everyoneOf, inherit, sighted } from './everyone.js';
|
|
6
5
|
import { originOf } from './origin.js';
|
|
7
6
|
import { startOf } from './place.js';
|
|
8
7
|
import { record } from './record.js';
|
|
@@ -24,7 +23,7 @@ export function unreachedOf(voice, now) {
|
|
|
24
23
|
*/
|
|
25
24
|
export function held(voice, subject, slot, guess = null) {
|
|
26
25
|
if (voice.sharing) {
|
|
27
|
-
const all = everyoneOf(this, voice);
|
|
26
|
+
const all = this.share.everyoneOf(this, voice);
|
|
28
27
|
if (all !== null)
|
|
29
28
|
return all;
|
|
30
29
|
}
|
|
@@ -67,8 +66,8 @@ export function held(voice, subject, slot, guess = null) {
|
|
|
67
66
|
voice.subjects.set(subject, held);
|
|
68
67
|
waits(voice, held, now);
|
|
69
68
|
// A subject a voice saw while it shared one record was counted then.
|
|
70
|
-
if (sighted(voice, slot))
|
|
71
|
-
inherit(voice, held, slot);
|
|
69
|
+
if (voice.sighted !== null && this.share?.sighted(voice, slot))
|
|
70
|
+
this.share.inherit(voice, held, slot);
|
|
72
71
|
else
|
|
73
72
|
voice.seen++;
|
|
74
73
|
if (delay > voice.latest) {
|
package/dist/hosts.d.ts
CHANGED
|
@@ -4,6 +4,13 @@ import type { Booker, BookOptions, Handle } from './types.js';
|
|
|
4
4
|
import type { Voice } from './voice.js';
|
|
5
5
|
export declare function book<I, O>(mix: Mixer<I, O>, opts: BookOptions<unknown, I>): Booker;
|
|
6
6
|
export declare function laneHost<I, O>(mix: Mixer<I, O>): LaneHost<I, O>;
|
|
7
|
+
/**
|
|
8
|
+
* Whether a laned voice belongs in a crowd: one naming a single subject, which shares nothing
|
|
9
|
+
* across subjects for a lane to save. A motion voice writes one channel; a keys or fn voice may
|
|
10
|
+
* write several, and joins the crowd of voices writing those same channels. A motion going round
|
|
11
|
+
* an `ink` color's hue stays out, since a crowd solves its stretches straight across each axis.
|
|
12
|
+
*/
|
|
13
|
+
export declare function crowdable<I, O>(v: Voice<I, O>): boolean;
|
|
7
14
|
/**
|
|
8
15
|
* Whether a voice's patch and spec can run on a lane, its channels aside. A voice whose patch has
|
|
9
16
|
* kept state on a record through `setting.keep` is stateful from then on, and leaves its lane;
|
package/dist/hosts.js
CHANGED
|
@@ -3,9 +3,7 @@ import { Book } from './book.js';
|
|
|
3
3
|
import { headOf } from './chain.js';
|
|
4
4
|
import { numericOf } from './channels.js';
|
|
5
5
|
import { stepOf } from './clock.js';
|
|
6
|
-
import { crowdable } from './crowd.js';
|
|
7
6
|
import { schedule } from './due.js';
|
|
8
|
-
import { unshare, unsight, weightAt } from './everyone.js';
|
|
9
7
|
import { beginFade, beginRise, fadeAt, fadeSubject } from './fade.js';
|
|
10
8
|
import { goneIndex } from './gone.js';
|
|
11
9
|
import { VoiceHandle } from './handle.js';
|
|
@@ -67,7 +65,7 @@ export function laneHost(mix) {
|
|
|
67
65
|
for (const voice of mix.general) {
|
|
68
66
|
unreach(voice, slot, false);
|
|
69
67
|
if (voice.sighted !== null)
|
|
70
|
-
unsight(voice, slot);
|
|
68
|
+
mix.share?.unsight(voice, slot);
|
|
71
69
|
}
|
|
72
70
|
for (const voice of goneIndex(mix).general)
|
|
73
71
|
unreach(voice, slot, false);
|
|
@@ -110,6 +108,19 @@ export function laneHost(mix) {
|
|
|
110
108
|
kept: (voice) => stateful(mix, voice),
|
|
111
109
|
};
|
|
112
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
* Whether a laned voice belongs in a crowd: one naming a single subject, which shares nothing
|
|
113
|
+
* across subjects for a lane to save. A motion voice writes one channel; a keys or fn voice may
|
|
114
|
+
* write several, and joins the crowd of voices writing those same channels. A motion going round
|
|
115
|
+
* an `ink` color's hue stays out, since a crowd solves its stretches straight across each axis.
|
|
116
|
+
*/
|
|
117
|
+
export function crowdable(v) {
|
|
118
|
+
return (v.named !== null &&
|
|
119
|
+
v.named.size === 1 &&
|
|
120
|
+
v.spec.role === undefined &&
|
|
121
|
+
(v.slots.length === 1 || v.motion === undefined) &&
|
|
122
|
+
v.motion?.round !== true);
|
|
123
|
+
}
|
|
113
124
|
/**
|
|
114
125
|
* Whether a voice's patch and spec can run on a lane, its channels aside. A voice whose patch has
|
|
115
126
|
* kept state on a record through `setting.keep` is stateful from then on, and leaves its lane;
|
|
@@ -181,7 +192,7 @@ export function stateful(mix, voice) {
|
|
|
181
192
|
voice.keeping = true;
|
|
182
193
|
// The call that kept state was for the subject last sent to, whose record the state is on.
|
|
183
194
|
if (voice.sharing)
|
|
184
|
-
unshare(mix, voice, true, mix.sending.subject);
|
|
195
|
+
mix.share?.unshare(mix, voice, true, mix.sending.subject);
|
|
185
196
|
mix.lanes?.invalidate();
|
|
186
197
|
}
|
|
187
198
|
export function handle(mix, voice) {
|
|
@@ -248,7 +259,9 @@ function handleHost(mix) {
|
|
|
248
259
|
? undefined
|
|
249
260
|
: voice.subjects.get(subject);
|
|
250
261
|
// A voice that stopped sharing makes a subject's record at its next read, from what it kept.
|
|
251
|
-
|
|
262
|
+
if (held !== undefined)
|
|
263
|
+
return held.weight;
|
|
264
|
+
return mix.share === null ? 0 : mix.share.weightAt(voice, slot);
|
|
252
265
|
},
|
|
253
266
|
taping: () => taping(mix),
|
|
254
267
|
record: (h, label, again) => record(mix, label, (stage) => {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export type { LastOptions, NumberOptions, NumberTuple, Vec } from './channels.js';
|
|
2
2
|
export { kit, last, max, mul, sum, vec } from './channels.js';
|
|
3
3
|
export type { ColorOptions } from './color.js';
|
|
4
|
-
export { color, css, mixHex, oklab, toHex } from './color.js';
|
|
4
|
+
export { color, css, ink, mixHex, oklab, toHex } from './color.js';
|
|
5
5
|
export type { Curve } from './easing.js';
|
|
6
6
|
export { curve } from './easing.js';
|
|
7
7
|
export type { Claim, Fit, FitPlan, Layout, Order, OverrunOptions, SpanClaim, Strength, } from './fit.js';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { kit, last, max, mul, sum, vec } from './channels.js';
|
|
2
|
-
export { color, css, mixHex, oklab, toHex } from './color.js';
|
|
2
|
+
export { color, css, ink, mixHex, oklab, toHex } from './color.js';
|
|
3
3
|
export { curve } from './easing.js';
|
|
4
4
|
export { conclude, condense, lax, layout, overrun, pipe, plain, shed, } from './fit.js';
|
|
5
5
|
export { mix, mixer } from './mixer.js';
|
package/dist/lanes.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { flush, pullRun, writeLater } from './columns.js';
|
|
2
2
|
import { type Copier, copy } from './copyout.js';
|
|
3
3
|
import { type Crowd, row } from './crowd.js';
|
|
4
4
|
import { call, foldKeys, one, parting, readKeyed, reset, run, runEveryone, signalled, subjectAt } from './fill.js';
|
|
@@ -7,6 +7,8 @@ import { type Lane, type Laned, type Role } from './lane.js';
|
|
|
7
7
|
import { absent, Numbers } from './numbers.js';
|
|
8
8
|
import { Owed } from './owed.js';
|
|
9
9
|
import { Placed } from './placed.js';
|
|
10
|
+
import type { Column } from './pull.js';
|
|
11
|
+
import { renumber } from './renumber.js';
|
|
10
12
|
import { type Seat } from './seat.js';
|
|
11
13
|
import type { Watcher } from './stretch.js';
|
|
12
14
|
import type { Subject } from './subject.js';
|
|
@@ -64,6 +66,29 @@ export interface LaneHost<I, O> {
|
|
|
64
66
|
*/
|
|
65
67
|
export declare class Lanes<I, O> implements Watcher {
|
|
66
68
|
readonly host: LaneHost<I, O>;
|
|
69
|
+
/** What the general path calls on a sharing voice, given to a mix by its engine so a lean bundle leaves it out. */
|
|
70
|
+
static readonly share: {
|
|
71
|
+
shares: typeof import("./everyone.js").shares;
|
|
72
|
+
outgrow: typeof import("./everyone.js").outgrow;
|
|
73
|
+
everyoneOf: typeof import("./everyone.js").everyoneOf;
|
|
74
|
+
sighted: typeof import("./everyone.js").sighted;
|
|
75
|
+
sight: typeof import("./everyone.js").sight;
|
|
76
|
+
weightAt: typeof import("./everyone.js").weightAt;
|
|
77
|
+
weighAt: typeof import("./everyone.js").weighAt;
|
|
78
|
+
open: typeof import("./everyone.js").open;
|
|
79
|
+
shut: typeof import("./everyone.js").shut;
|
|
80
|
+
restamp: typeof import("./everyone.js").restamp;
|
|
81
|
+
unsight: typeof import("./everyone.js").unsight;
|
|
82
|
+
unshare: typeof import("./everyone.js").unshare;
|
|
83
|
+
inherit: typeof import("./everyone.js").inherit;
|
|
84
|
+
};
|
|
85
|
+
/** What `pull` calls on lanes alone. */
|
|
86
|
+
readonly pulls: {
|
|
87
|
+
pullRun: typeof pullRun;
|
|
88
|
+
writeLater: typeof writeLater;
|
|
89
|
+
flush: typeof flush;
|
|
90
|
+
renumber: typeof renumber;
|
|
91
|
+
};
|
|
67
92
|
readonly numbers: Numbers<I>;
|
|
68
93
|
lanes: Lane<I, O>[];
|
|
69
94
|
/** The lanes over every subject that have started playing, by epoch. */
|
package/dist/lanes.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { lit } from './bound.js';
|
|
2
|
+
import { flush, pullRun, writeLater } from './columns.js';
|
|
2
3
|
import { copy } from './copyout.js';
|
|
3
4
|
import { row } from './crowd.js';
|
|
5
|
+
import { share } from './everyone.js';
|
|
4
6
|
import { call, fillAll, foldKeys, one, parting, readKeyed, reset, run, runEveryone, signalled, subjectAt, } from './fill.js';
|
|
5
7
|
import { fold, foldDelta, foldInto, foldRun, gate, gather, unplain } from './gather.js';
|
|
6
8
|
import { meet, reach } from './meet.js';
|
|
@@ -9,6 +11,7 @@ import { Owed } from './owed.js';
|
|
|
9
11
|
import { Placed } from './placed.js';
|
|
10
12
|
import { requalify, retouch } from './qualify.js';
|
|
11
13
|
import { reading } from './reading.js';
|
|
14
|
+
import { renumber } from './renumber.js';
|
|
12
15
|
import { reportedRow, unplace } from './rows.js';
|
|
13
16
|
import { seatOf } from './seat.js';
|
|
14
17
|
/**
|
|
@@ -18,6 +21,10 @@ import { seatOf } from './seat.js';
|
|
|
18
21
|
// biome-ignore lint/suspicious/noUnsafeDeclarationMerging: every member of `Methods` is installed below
|
|
19
22
|
export class Lanes {
|
|
20
23
|
host;
|
|
24
|
+
/** What the general path calls on a sharing voice, given to a mix by its engine so a lean bundle leaves it out. */
|
|
25
|
+
static share = share;
|
|
26
|
+
/** What `pull` calls on lanes alone. */
|
|
27
|
+
pulls = { pullRun, writeLater, flush, renumber };
|
|
21
28
|
numbers;
|
|
22
29
|
lanes = [];
|
|
23
30
|
/** The lanes over every subject that have started playing, by epoch. */
|
package/dist/lch.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Curve } from './easing.js';
|
|
2
|
+
/** Below this chroma a color is gray and its hue is noise, so it takes the other end's. */
|
|
3
|
+
export declare const GRAY = 0.0001;
|
|
4
|
+
/** Where `shortWay` leaves the hue a way starts from and how far it turns. */
|
|
5
|
+
export declare const HUES: number[];
|
|
6
|
+
/** The way from hue `ah` to `bh` the short way round into `HUES`, a gray end taking the other's. */
|
|
7
|
+
export declare function shortWay(ah: number, ac: number, bh: number, bc: number): void;
|
|
8
|
+
/**
|
|
9
|
+
* Two premultiplied OKLab colors, `[w·L, w·a, w·b, w]` read from `x` at `i` and `y` at `j`, into
|
|
10
|
+
* `out` as `[L, C, h, w]` each, `y`'s hue the short way round from `x`'s. A color with no coverage
|
|
11
|
+
* has none of its own to keep, so it takes the other end's.
|
|
12
|
+
*/
|
|
13
|
+
export declare function lchPair(x: ArrayLike<number>, i: number, y: ArrayLike<number>, j: number, out: Float64Array): void;
|
|
14
|
+
/**
|
|
15
|
+
* `closed` for a stretch of a color traveling round the hue, as `ink` does: its ends and velocity,
|
|
16
|
+
* premultiplied OKLab as the patch keeps them, moved into `[L, C, h, w]`, solved there axis by
|
|
17
|
+
* axis, and the position and
|
|
18
|
+
* velocity moved back into `xo` and `vo`. A spring heads round the hue the short way from where
|
|
19
|
+
* the stretch starts, so a retarget bends the path rather than restarting it, and one that
|
|
20
|
+
* overshoots its target overshoots in hue too. A glide comes to rest `v·τ` along each of the four,
|
|
21
|
+
* so it coasts round the hue rather than off along a tangent.
|
|
22
|
+
*/
|
|
23
|
+
export declare function closedLch(law: Float64Array, ease: Curve | undefined, 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;
|
package/dist/lch.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { COAST, closed } from './closed.js';
|
|
2
|
+
/** Below this chroma a color is gray and its hue is noise, so it takes the other end's. */
|
|
3
|
+
export const GRAY = 1e-4;
|
|
4
|
+
/** Where `shortWay` leaves the hue a way starts from and how far it turns. */
|
|
5
|
+
export const HUES = [0, 0];
|
|
6
|
+
/** The way from hue `ah` to `bh` the short way round into `HUES`, a gray end taking the other's. */
|
|
7
|
+
export function shortWay(ah, ac, bh, bc) {
|
|
8
|
+
const from = ac < GRAY ? bh : ah;
|
|
9
|
+
const to = bc < GRAY ? ah : bh;
|
|
10
|
+
let turn = to - from;
|
|
11
|
+
if (turn > Math.PI)
|
|
12
|
+
turn -= 2 * Math.PI;
|
|
13
|
+
else if (turn < -Math.PI)
|
|
14
|
+
turn += 2 * Math.PI;
|
|
15
|
+
HUES[0] = from;
|
|
16
|
+
HUES[1] = turn;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Two premultiplied OKLab colors, `[w·L, w·a, w·b, w]` read from `x` at `i` and `y` at `j`, into
|
|
20
|
+
* `out` as `[L, C, h, w]` each, `y`'s hue the short way round from `x`'s. A color with no coverage
|
|
21
|
+
* has none of its own to keep, so it takes the other end's.
|
|
22
|
+
*/
|
|
23
|
+
export function lchPair(x, i, y, j, out) {
|
|
24
|
+
const xw = x[i + 3] ?? 0;
|
|
25
|
+
const yw = y[j + 3] ?? 0;
|
|
26
|
+
const ys = yw > 0 ? 1 / yw : 0;
|
|
27
|
+
const yL = (y[j] ?? 0) * ys;
|
|
28
|
+
const yA = (y[j + 1] ?? 0) * ys;
|
|
29
|
+
const yB = (y[j + 2] ?? 0) * ys;
|
|
30
|
+
const xs = xw > 0 ? 1 / xw : 0;
|
|
31
|
+
const xL = xw > 0 ? (x[i] ?? 0) * xs : yL;
|
|
32
|
+
const xA = xw > 0 ? (x[i + 1] ?? 0) * xs : yA;
|
|
33
|
+
const xB = xw > 0 ? (x[i + 2] ?? 0) * xs : yB;
|
|
34
|
+
const toL = yw > 0 ? yL : xL;
|
|
35
|
+
const toA = yw > 0 ? yA : xA;
|
|
36
|
+
const toB = yw > 0 ? yB : xB;
|
|
37
|
+
const xc = Math.sqrt(xA * xA + xB * xB);
|
|
38
|
+
const yc = Math.sqrt(toA * toA + toB * toB);
|
|
39
|
+
shortWay(Math.atan2(xB, xA), xc, Math.atan2(toB, toA), yc);
|
|
40
|
+
out[0] = xL;
|
|
41
|
+
out[1] = xc;
|
|
42
|
+
out[2] = HUES[0];
|
|
43
|
+
out[3] = xw;
|
|
44
|
+
out[4] = toL;
|
|
45
|
+
out[5] = yc;
|
|
46
|
+
out[6] = HUES[0] + HUES[1];
|
|
47
|
+
out[7] = yw;
|
|
48
|
+
}
|
|
49
|
+
const PAIR = new Float64Array(8);
|
|
50
|
+
const RATES = new Float64Array(4);
|
|
51
|
+
const REST = new Float64Array(4);
|
|
52
|
+
const XS = new Float64Array(4);
|
|
53
|
+
const VS = new Float64Array(4);
|
|
54
|
+
/**
|
|
55
|
+
* `closed` for a stretch of a color traveling round the hue, as `ink` does: its ends and velocity,
|
|
56
|
+
* premultiplied OKLab as the patch keeps them, moved into `[L, C, h, w]`, solved there axis by
|
|
57
|
+
* axis, and the position and
|
|
58
|
+
* velocity moved back into `xo` and `vo`. A spring heads round the hue the short way from where
|
|
59
|
+
* the stretch starts, so a retarget bends the path rather than restarting it, and one that
|
|
60
|
+
* overshoots its target overshoots in hue too. A glide comes to rest `v·τ` along each of the four,
|
|
61
|
+
* so it coasts round the hue rather than off along a tangent.
|
|
62
|
+
*/
|
|
63
|
+
export function closedLch(law, ease, at, ms, x0, x, v0, v, to, g, t, xo, vo) {
|
|
64
|
+
const p = PAIR;
|
|
65
|
+
lchPair(x0, x, to, g, p);
|
|
66
|
+
const L = p[0];
|
|
67
|
+
const C = p[1];
|
|
68
|
+
const h = p[2];
|
|
69
|
+
const w = p[3];
|
|
70
|
+
// OKLab's rates of change at the start, its coverage's share divided out, turned onto L, C and h.
|
|
71
|
+
const dw = v0[v + 3];
|
|
72
|
+
let dL = 0;
|
|
73
|
+
let dC = 0;
|
|
74
|
+
let dh = 0;
|
|
75
|
+
if (w > 0) {
|
|
76
|
+
const cos = Math.cos(h);
|
|
77
|
+
const sin = Math.sin(h);
|
|
78
|
+
dL = (v0[v] - dw * L) / w;
|
|
79
|
+
const da = (v0[v + 1] - dw * C * cos) / w;
|
|
80
|
+
const db = (v0[v + 2] - dw * C * sin) / w;
|
|
81
|
+
dC = da * cos + db * sin;
|
|
82
|
+
dh = C < GRAY ? 0 : (db * cos - da * sin) / C;
|
|
83
|
+
}
|
|
84
|
+
RATES[0] = dL;
|
|
85
|
+
RATES[1] = dC;
|
|
86
|
+
RATES[2] = dh;
|
|
87
|
+
RATES[3] = dw;
|
|
88
|
+
let goal = p;
|
|
89
|
+
let o = 4;
|
|
90
|
+
if (law[0] === COAST) {
|
|
91
|
+
const tau = law[2];
|
|
92
|
+
for (let i = 0; i < 4; i++)
|
|
93
|
+
REST[i] = p[i] + RATES[i] * tau;
|
|
94
|
+
goal = REST;
|
|
95
|
+
o = 0;
|
|
96
|
+
}
|
|
97
|
+
const still = closed(law, ease, 4, at, ms, p, 0, RATES, 0, goal, o, t, XS, VS);
|
|
98
|
+
if (still && o === 4) {
|
|
99
|
+
for (let i = 0; i < 4; i++) {
|
|
100
|
+
xo[i] = to[g + i];
|
|
101
|
+
vo[i] = 0;
|
|
102
|
+
}
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
const nL = XS[0];
|
|
106
|
+
const nC = XS[1];
|
|
107
|
+
const nh = XS[2];
|
|
108
|
+
const nw = XS[3];
|
|
109
|
+
const cos = Math.cos(nh);
|
|
110
|
+
const sin = Math.sin(nh);
|
|
111
|
+
const a = nC * cos;
|
|
112
|
+
const b = nC * sin;
|
|
113
|
+
const rL = VS[0];
|
|
114
|
+
const rC = VS[1];
|
|
115
|
+
const rh = VS[2];
|
|
116
|
+
const rw = VS[3];
|
|
117
|
+
xo[0] = nL * nw;
|
|
118
|
+
xo[1] = a * nw;
|
|
119
|
+
xo[2] = b * nw;
|
|
120
|
+
xo[3] = nw;
|
|
121
|
+
vo[0] = rL * nw + nL * rw;
|
|
122
|
+
vo[1] = (rC * cos - nC * rh * sin) * nw + a * rw;
|
|
123
|
+
vo[2] = (rC * sin + nC * rh * cos) * nw + b * rw;
|
|
124
|
+
vo[3] = rw;
|
|
125
|
+
return still;
|
|
126
|
+
}
|
package/dist/mixer.d.ts
CHANGED
|
@@ -4,11 +4,11 @@ import { blended, laneRead, shareKept } from './blend.js';
|
|
|
4
4
|
import type { Book } from './book.js';
|
|
5
5
|
import { aims, chain, linkable, relink } from './chain.js';
|
|
6
6
|
import { type LerpInto } from './channels.js';
|
|
7
|
-
import type { Column } from './columns.js';
|
|
8
7
|
import { baseFor, contribution, isRest, keyed, read, slopeFor, tick } from './contribution.js';
|
|
9
8
|
import { DepartedIndex } from './departed.js';
|
|
10
9
|
import { drop, forgetIn, recordDrop, releaseIn } from './drop.js';
|
|
11
10
|
import { DueQueue } from './due.js';
|
|
11
|
+
import type { Share } from './everyone.js';
|
|
12
12
|
import { parting } from './fade.js';
|
|
13
13
|
import { apply, clamp, fold, foldDetour, folded, foldSharers, foldWith, type Key, linked, owedBy, passes, shared } from './fold.js';
|
|
14
14
|
import { GoneIndex } from './gone.js';
|
|
@@ -20,6 +20,7 @@ import type { Pace } from './pace.js';
|
|
|
20
20
|
import { Keys } from './paging.js';
|
|
21
21
|
import type { Places } from './places.js';
|
|
22
22
|
import { moved, place, plot, put } from './plot.js';
|
|
23
|
+
import type { Column } from './pull.js';
|
|
23
24
|
import { keep } from './pull.js';
|
|
24
25
|
import { Steps } from './relink.js';
|
|
25
26
|
import { atRest, restful, rests, restsKey, restsLaned, still } from './rests.js';
|
|
@@ -209,6 +210,8 @@ export declare class Mixer<I, O> implements Mix<I, O> {
|
|
|
209
210
|
roleDepth: number;
|
|
210
211
|
readonly slotOf: Map<string, number>;
|
|
211
212
|
lanes: Lanes<I, O> | null;
|
|
213
|
+
/** The sharing hooks of the lanes this entry was built with, which a projection's copy keeps. */
|
|
214
|
+
share: Share | null;
|
|
212
215
|
handles: HandleHost<I, O> | null;
|
|
213
216
|
/** What `book` made, still booking; null while there is none. */
|
|
214
217
|
bookers: Book<I, O>[] | null;
|
package/dist/mixer.js
CHANGED
|
@@ -235,6 +235,8 @@ export class Mixer {
|
|
|
235
235
|
roleDepth = 0;
|
|
236
236
|
slotOf = new Map();
|
|
237
237
|
lanes;
|
|
238
|
+
/** The sharing hooks of the lanes this entry was built with, which a projection's copy keeps. */
|
|
239
|
+
share;
|
|
238
240
|
handles = null;
|
|
239
241
|
/** What `book` made, still booking; null while there is none. */
|
|
240
242
|
bookers = null;
|
|
@@ -266,6 +268,7 @@ export class Mixer {
|
|
|
266
268
|
});
|
|
267
269
|
if (lanesOf === null && opts.lanes === true)
|
|
268
270
|
throw new Error("blits: '@msb235/blits/lean' has no lanes; take mix from '@msb235/blits'");
|
|
271
|
+
this.share = lanesOf?.share ?? null;
|
|
269
272
|
this.lanes =
|
|
270
273
|
lanesOf !== null && (opts.lanes ?? defaults.lanes) ? new lanesOf(laneHost(this)) : null;
|
|
271
274
|
this.name = opts.name;
|
package/dist/motions.d.ts
CHANGED
|
@@ -64,11 +64,14 @@ export declare class Motions<I> {
|
|
|
64
64
|
/** Whether the channel it was cued on holds a number; undefined until it is cued. */
|
|
65
65
|
private holdsNumber;
|
|
66
66
|
private channel;
|
|
67
|
+
/** Whether the channel it was cued on travels round the hue, as `ink` does, and its stretches too. */
|
|
68
|
+
round: boolean;
|
|
67
69
|
/**
|
|
68
70
|
* Records what the channel the patch is cued on holds, refusing a value of the other kind: at once
|
|
69
71
|
* where every subject's value is one kind, else on the first sample of a subject whose value is not.
|
|
72
|
+
* `round` for a channel that travels round the hue, as `ink` does.
|
|
70
73
|
*/
|
|
71
|
-
cuedOn(channel: string, holdsNumber: boolean): void;
|
|
74
|
+
cuedOn(channel: string, holdsNumber: boolean, round?: boolean): void;
|
|
72
75
|
frame(subject: I): number;
|
|
73
76
|
constructor(shape: Shape<I>);
|
|
74
77
|
/** The patch's number for `subject`, made with its first stretch on first ask. */
|