@msb235/blits 0.15.1 → 0.16.1
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 +184 -0
- package/README.md +1 -1
- package/dist/ahead.js +11 -13
- package/dist/chain.js +2 -3
- package/dist/clock.d.ts +11 -1
- package/dist/clock.js +28 -9
- 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/contribution.js +11 -4
- package/dist/crowd.d.ts +0 -6
- package/dist/crowd.js +0 -11
- package/dist/cue.js +19 -7
- package/dist/due.d.ts +18 -0
- package/dist/due.js +101 -2
- package/dist/everyone.d.ts +17 -6
- package/dist/everyone.js +17 -8
- package/dist/fade.d.ts +22 -1
- package/dist/fade.js +81 -12
- package/dist/fill.js +2 -1
- package/dist/fit.js +8 -0
- package/dist/fold.js +4 -7
- package/dist/gone.js +1 -0
- package/dist/handle.d.ts +1 -1
- package/dist/handle.js +3 -1
- package/dist/held.d.ts +2 -1
- package/dist/held.js +17 -10
- package/dist/hosts.d.ts +7 -0
- package/dist/hosts.js +23 -6
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lane.d.ts +2 -0
- package/dist/lane.js +2 -0
- package/dist/lanes.d.ts +26 -1
- package/dist/lanes.js +9 -1
- package/dist/lch.d.ts +23 -0
- package/dist/lch.js +126 -0
- package/dist/meet.js +9 -0
- package/dist/mixer.d.ts +6 -1
- package/dist/mixer.js +5 -0
- package/dist/motion.js +6 -6
- package/dist/motions.d.ts +4 -1
- package/dist/motions.js +16 -2
- package/dist/move.js +311 -79
- package/dist/origin.d.ts +2 -0
- package/dist/origin.js +4 -0
- package/dist/owner.d.ts +7 -2
- package/dist/owner.js +17 -5
- package/dist/paging.d.ts +5 -1
- package/dist/paging.js +13 -3
- package/dist/patch.js +24 -4
- package/dist/place.js +67 -31
- package/dist/project.d.ts +5 -2
- package/dist/project.js +9 -11
- package/dist/pull.d.ts +11 -0
- package/dist/pull.js +10 -6
- package/dist/qualify.js +7 -2
- package/dist/rests.js +9 -1
- package/dist/revive.d.ts +11 -1
- package/dist/revive.js +7 -0
- package/dist/roles.js +6 -5
- package/dist/roster.d.ts +6 -0
- package/dist/roster.js +8 -1
- package/dist/rows.js +4 -1
- package/dist/sample.js +2 -1
- package/dist/seat.d.ts +5 -1
- package/dist/seat.js +5 -1
- package/dist/seek.js +6 -16
- package/dist/shared.d.ts +1 -1
- package/dist/shared.js +1 -1
- package/dist/spans.d.ts +13 -4
- package/dist/spans.js +125 -32
- package/dist/touch.js +1 -2
- package/dist/trace.js +7 -2
- package/dist/turns.js +2 -1
- package/dist/types/transport.d.ts +2 -1
- package/dist/types/voice.d.ts +3 -2
- package/dist/voice.d.ts +59 -2
- package/dist/voice.js +76 -2
- package/dist/weigh.js +1 -1
- package/docs/schema.html +38 -12
- package/package.json +3 -1
package/dist/everyone.d.ts
CHANGED
|
@@ -65,11 +65,22 @@ export declare function unsight<I, O>(voice: Voice<I, O>, slot: number): void;
|
|
|
65
65
|
* positions take their own records now, since each held the one.
|
|
66
66
|
*/
|
|
67
67
|
export declare function unshare<I, O>(mix: Mixer<I, O>, voice: Voice<I, O>, kept?: boolean, keeper?: I): void;
|
|
68
|
-
/**
|
|
69
|
-
* Counts what makes a mix's fold more than a walk of each chain: a role, a voice sharing one
|
|
70
|
-
* record, a voice that stopped sharing this frame. Called wherever one of the three changes, so
|
|
71
|
-
* `foldWith` asks one number.
|
|
72
|
-
*/
|
|
73
|
-
export declare function detour<I, O>(mix: Mixer<I, O>): void;
|
|
74
68
|
/** Gives a record just made for a subject a sharing voice had seen what the voice kept for it. */
|
|
75
69
|
export declare function inherit<I, O>(voice: Voice<I, O>, held: Subject<unknown>, slot: number): void;
|
|
70
|
+
/** What the general path calls on a sharing voice, reached through `Lanes`, so a lean bundle leaves it out. */
|
|
71
|
+
export declare const share: {
|
|
72
|
+
shares: typeof shares;
|
|
73
|
+
outgrow: typeof outgrow;
|
|
74
|
+
everyoneOf: typeof everyoneOf;
|
|
75
|
+
sighted: typeof sighted;
|
|
76
|
+
sight: typeof sight;
|
|
77
|
+
weightAt: typeof weightAt;
|
|
78
|
+
weighAt: typeof weighAt;
|
|
79
|
+
open: typeof open;
|
|
80
|
+
shut: typeof shut;
|
|
81
|
+
restamp: typeof restamp;
|
|
82
|
+
unsight: typeof unsight;
|
|
83
|
+
unshare: typeof unshare;
|
|
84
|
+
inherit: typeof inherit;
|
|
85
|
+
};
|
|
86
|
+
export type Share = typeof share;
|
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
|
@@ -3,7 +3,11 @@ import type { Left, Parted, Parting } from './subject.js';
|
|
|
3
3
|
import type { Voice } from './voice.js';
|
|
4
4
|
/** Starts one subject's ramp out of a voice, or takes it out at once for a ramp of 0. */
|
|
5
5
|
export declare function fadeSubject<I, O>(mix: Mixer<I, O>, voice: Voice<I, O>, subject: I, over?: number): void;
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* What a subject's own ramp out of a voice leaves of its weight this frame. It also holds the
|
|
8
|
+
* voice's fade in where the ramp began, as a fade out of the whole voice does, so it is a ratio to
|
|
9
|
+
* the fade in the voice's envelope gives.
|
|
10
|
+
*/
|
|
7
11
|
export declare function parting<I, O>(this: Mixer<I, O>, voice: Voice<I, O>, subject: I, now: number): number;
|
|
8
12
|
/**
|
|
9
13
|
* Takes a subject out of one voice for good, as of mix time `at`: the voice forgets its record,
|
|
@@ -30,7 +34,19 @@ export declare function beginFade<I, O>(mix: Mixer<I, O>, voice: Voice<I, O>, op
|
|
|
30
34
|
at?: 'rest';
|
|
31
35
|
deadline?: number;
|
|
32
36
|
back?: boolean;
|
|
37
|
+
stays?: boolean;
|
|
33
38
|
}, at?: number): void;
|
|
39
|
+
/**
|
|
40
|
+
* Keeps a voice faded at the end of its passes with its owner, live and quiet, rather than letting
|
|
41
|
+
* it leave; the owner, where it holds no child still playing, leaves at `at`, or stays quiet in
|
|
42
|
+
* turn where an owner holds it.
|
|
43
|
+
*/
|
|
44
|
+
export declare function stay<I, O>(mix: Mixer<I, O>, voice: Voice<I, O>, at: number): void;
|
|
45
|
+
/**
|
|
46
|
+
* Lets an owner holding no child still playing leave at `at`; under history one an owner holds
|
|
47
|
+
* stays with it instead, quiet while its children are.
|
|
48
|
+
*/
|
|
49
|
+
export declare function release<I, O>(mix: Mixer<I, O>, owner: Voice<I, O>, at: number): void;
|
|
34
50
|
/**
|
|
35
51
|
* Turns a fading voice around: it climbs back from where its fade out had got to, up the same
|
|
36
52
|
* curve, at the whole curve per `over` ms. A fade waiting for rest is taken back at once. A voice
|
|
@@ -44,5 +60,10 @@ export declare function beginRise<I, O>(mix: Mixer<I, O>, voice: Voice<I, O>, op
|
|
|
44
60
|
* exactly there; at or behind now, the fade began then and is partway.
|
|
45
61
|
*/
|
|
46
62
|
export declare function fadeAt<I, O>(mix: Mixer<I, O>, voice: Voice<I, O>, at: number, over: number | undefined): void;
|
|
63
|
+
/**
|
|
64
|
+
* Brings back a voice kept quiet past its passes, its clock back in them by mix time `now`: it
|
|
65
|
+
* climbs from nothing over the fade it left over, from when its clock reached them.
|
|
66
|
+
*/
|
|
67
|
+
export declare function rouse<I, O>(mix: Mixer<I, O>, voice: Voice<I, O>, now: number): void;
|
|
47
68
|
/** Removes a voice, recording that it left at `at`, default now. */
|
|
48
69
|
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,10 @@
|
|
|
1
1
|
import { changed, headOf, unlink } from './chain.js';
|
|
2
|
-
import { envelope } from './clock.js';
|
|
2
|
+
import { envelope, fadeInAt } 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 {
|
|
6
|
+
import { startedAt } from './origin.js';
|
|
7
|
+
import { orphan, ownerReading, plays } from './owner.js';
|
|
8
8
|
import { startOf } from './place.js';
|
|
9
9
|
import { isRested } from './record.js';
|
|
10
10
|
import { scoreTouched } from './scored.js';
|
|
@@ -14,7 +14,7 @@ import { unreach } from './unreached.js';
|
|
|
14
14
|
export function fadeSubject(mix, voice, subject, over) {
|
|
15
15
|
if (voice.state === 'done' || voice.parted?.has(subject) || voice.parts?.has(subject))
|
|
16
16
|
return;
|
|
17
|
-
unshare(mix, voice);
|
|
17
|
+
mix.share?.unshare(mix, voice);
|
|
18
18
|
mix.stir();
|
|
19
19
|
const ms = mix.reduced ? 0 : (over ?? voice.fade.out ?? 0);
|
|
20
20
|
const at = Number.isNaN(mix.now) ? startOf(voice) : mix.now;
|
|
@@ -28,12 +28,26 @@ export function fadeSubject(mix, voice, subject, over) {
|
|
|
28
28
|
schedule(mix, voice);
|
|
29
29
|
mix.lanes?.refill();
|
|
30
30
|
}
|
|
31
|
-
/**
|
|
31
|
+
/**
|
|
32
|
+
* What a subject's own ramp out of a voice leaves of its weight this frame. It also holds the
|
|
33
|
+
* voice's fade in where the ramp began, as a fade out of the whole voice does, so it is a ratio to
|
|
34
|
+
* the fade in the voice's envelope gives.
|
|
35
|
+
*/
|
|
32
36
|
export function parting(voice, subject, now) {
|
|
33
37
|
const r = voice.parts?.get(subject);
|
|
34
38
|
if (r === undefined)
|
|
35
39
|
return 1;
|
|
36
|
-
|
|
40
|
+
const reduced = this.reducedNow;
|
|
41
|
+
const w = envelope(0, { at: r.at, over: r.over, rest: false }, voice.ease, reduced, now, 0);
|
|
42
|
+
const fadeIn = voice.fade.in ?? 0;
|
|
43
|
+
const since = voice.subjects.get(subject)?.shown;
|
|
44
|
+
if (!(fadeIn > 0) || reduced || since === undefined || !(r.at < now))
|
|
45
|
+
return w;
|
|
46
|
+
const out = voice.out;
|
|
47
|
+
const climbing = fadeInAt(fadeIn, out, voice.ease, now, since, voice.stalls);
|
|
48
|
+
if (!(climbing > 0))
|
|
49
|
+
return w;
|
|
50
|
+
return w * (fadeInAt(fadeIn, out, voice.ease, now, since, voice.stalls, r.at) / climbing);
|
|
37
51
|
}
|
|
38
52
|
/**
|
|
39
53
|
* Takes a subject out of one voice for good, as of mix time `at`: the voice forgets its record,
|
|
@@ -104,7 +118,7 @@ function forgetIn(mix, voice, subject) {
|
|
|
104
118
|
if (head !== undefined && head.slot >= 0) {
|
|
105
119
|
unreach(voice, head.slot, false);
|
|
106
120
|
// What the voice kept for the subject while it shared one record, which `weightOf` reads.
|
|
107
|
-
unsight(voice, head.slot);
|
|
121
|
+
mix.share?.unsight(voice, head.slot);
|
|
108
122
|
}
|
|
109
123
|
const held = voice.subjects.get(subject);
|
|
110
124
|
if (held !== undefined) {
|
|
@@ -135,7 +149,7 @@ export function beginFade(mix, voice, opts, at) {
|
|
|
135
149
|
// A fade at rest marks each subject's record as it comes to rest, at its next read: one already
|
|
136
150
|
// read this frame is read again, as after `touch`.
|
|
137
151
|
if (opts.at === 'rest') {
|
|
138
|
-
unshare(mix, voice);
|
|
152
|
+
mix.share?.unshare(mix, voice);
|
|
139
153
|
voice.seeks++;
|
|
140
154
|
}
|
|
141
155
|
voice.state = 'fading';
|
|
@@ -148,14 +162,49 @@ export function beginFade(mix, voice, opts, at) {
|
|
|
148
162
|
};
|
|
149
163
|
if (opts.back)
|
|
150
164
|
voice.out.back = true;
|
|
165
|
+
if (opts.stays)
|
|
166
|
+
voice.out.stays = true;
|
|
151
167
|
noted(mix, voice);
|
|
152
168
|
// A fade at rest, from a voice's start, or of a voice yet to start takes it off its lane.
|
|
153
169
|
if (opts.at === 'rest' || opts.back || waiting)
|
|
154
170
|
mix.lanes?.invalidate();
|
|
155
171
|
else
|
|
156
172
|
mix.lanes?.refill();
|
|
157
|
-
if (over === 0 && opts.at !== 'rest')
|
|
158
|
-
|
|
173
|
+
if (over === 0 && opts.at !== 'rest') {
|
|
174
|
+
if (opts.stays)
|
|
175
|
+
stay(mix, voice, voice.out.at);
|
|
176
|
+
else
|
|
177
|
+
retire(mix, voice, voice.out.at);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Keeps a voice faded at the end of its passes with its owner, live and quiet, rather than letting
|
|
182
|
+
* it leave; the owner, where it holds no child still playing, leaves at `at`, or stays quiet in
|
|
183
|
+
* turn where an owner holds it.
|
|
184
|
+
*/
|
|
185
|
+
export function stay(mix, voice, at) {
|
|
186
|
+
voice.state = 'live';
|
|
187
|
+
mix.lanes?.refill();
|
|
188
|
+
const owner = voice.owner;
|
|
189
|
+
if (owner.state === 'done')
|
|
190
|
+
return;
|
|
191
|
+
const now = Number.isNaN(mix.now) ? Number.NEGATIVE_INFINITY : mix.now;
|
|
192
|
+
if (plays(owner, now) || lingers(owner, at)) {
|
|
193
|
+
if (owner.fitting !== null && !voice.skipped)
|
|
194
|
+
refit(mix, owner, at);
|
|
195
|
+
}
|
|
196
|
+
else
|
|
197
|
+
release(mix, owner, at);
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Lets an owner holding no child still playing leave at `at`; under history one an owner holds
|
|
201
|
+
* stays with it instead, quiet while its children are.
|
|
202
|
+
*/
|
|
203
|
+
export function release(mix, owner, at) {
|
|
204
|
+
if (owner.owner !== null && owner.state === 'live' && mix.opts.history !== undefined)
|
|
205
|
+
beginFade(mix, owner, { over: 0, stays: true }, at);
|
|
206
|
+
else
|
|
207
|
+
retire(mix, owner, at);
|
|
159
208
|
}
|
|
160
209
|
/**
|
|
161
210
|
* Turns a fading voice around: it climbs back from where its fade out had got to, up the same
|
|
@@ -184,7 +233,12 @@ export function beginRise(mix, voice, opts) {
|
|
|
184
233
|
voice.out = null;
|
|
185
234
|
voice.outAt = Number.POSITIVE_INFINITY;
|
|
186
235
|
voice.state = waiting ? 'pending' : 'live';
|
|
236
|
+
if (waiting)
|
|
237
|
+
voice.begunSeq = Number.POSITIVE_INFINITY;
|
|
187
238
|
voice.back = over > 0 && from < 1 ? { from, at, over } : null;
|
|
239
|
+
// Its fade in stood still from where the fade out began, and climbs on from where it stood.
|
|
240
|
+
if (!out.rest && out.at < at)
|
|
241
|
+
voice.stalls = [...(voice.stalls ?? []), out.at, at];
|
|
188
242
|
if (waiting)
|
|
189
243
|
changed(mix, voice);
|
|
190
244
|
noted(mix, voice);
|
|
@@ -202,7 +256,7 @@ export function fadeAt(mix, voice, at, over) {
|
|
|
202
256
|
return;
|
|
203
257
|
const now = Number.isNaN(mix.now) ? startOf(voice) : mix.now;
|
|
204
258
|
if (at <= now) {
|
|
205
|
-
beginFade(mix, voice, { over }, Math.max(
|
|
259
|
+
beginFade(mix, voice, { over }, Math.max(startedAt(voice), at));
|
|
206
260
|
mix.stir();
|
|
207
261
|
return;
|
|
208
262
|
}
|
|
@@ -211,6 +265,21 @@ export function fadeAt(mix, voice, at, over) {
|
|
|
211
265
|
voice.outSet = true;
|
|
212
266
|
noted(mix, voice);
|
|
213
267
|
}
|
|
268
|
+
/**
|
|
269
|
+
* Brings back a voice kept quiet past its passes, its clock back in them by mix time `now`: it
|
|
270
|
+
* climbs from nothing over the fade it left over, from when its clock reached them.
|
|
271
|
+
*/
|
|
272
|
+
export function rouse(mix, voice, now) {
|
|
273
|
+
const out = voice.out;
|
|
274
|
+
const edge = out.back === true ? voice.soonest : voice.span + voice.latest;
|
|
275
|
+
const reached = voice.reaches(edge);
|
|
276
|
+
const at = Math.max(out.at + out.over, reached <= now ? reached : now);
|
|
277
|
+
const over = mix.reduced ? 0 : out.over;
|
|
278
|
+
voice.out = null;
|
|
279
|
+
voice.back = over > 0 ? { from: 0, at, over } : null;
|
|
280
|
+
noted(mix, voice);
|
|
281
|
+
mix.lanes?.refill();
|
|
282
|
+
}
|
|
214
283
|
/** Whether a motion patch still asks this voice of this mix for its time. */
|
|
215
284
|
function asks(mix, motion, voice) {
|
|
216
285
|
return motion.owner === mix.owner && motion.ownerId === voice.id;
|
|
@@ -248,7 +317,7 @@ export function retire(mix, voice, at) {
|
|
|
248
317
|
if (voice.owner !== null) {
|
|
249
318
|
const span = voice.owner;
|
|
250
319
|
leaving(mix, voice);
|
|
251
|
-
const owner = orphan(voice);
|
|
320
|
+
const owner = orphan(voice, now);
|
|
252
321
|
if (owner !== null && !lingers(owner, voice.doneAt))
|
|
253
322
|
retire(mix, owner, voice.doneAt);
|
|
254
323
|
// A child the fit skipped had no time in it, so the rest of the fit stands: fitting again
|
package/dist/fill.js
CHANGED
|
@@ -472,7 +472,8 @@ export function call(voice, chans, rec, slot) {
|
|
|
472
472
|
rec.delta = null;
|
|
473
473
|
rec.probed = this.now;
|
|
474
474
|
rec.seeks = voice.seeks;
|
|
475
|
-
|
|
475
|
+
// A role member is one at weight 0 too, unasked, and holds its role's place as on the general path.
|
|
476
|
+
return voice.spec.role !== undefined;
|
|
476
477
|
}
|
|
477
478
|
const kept = reading.kept;
|
|
478
479
|
host.ready(voice, subject, rec);
|
package/dist/fit.js
CHANGED
|
@@ -50,6 +50,14 @@ function least(lo, hi, ok) {
|
|
|
50
50
|
return lo;
|
|
51
51
|
if (!ok(hi))
|
|
52
52
|
return hi;
|
|
53
|
+
// An unbounded `hi`, as an `Infinity` hint gives, is brought to a finite one before halving.
|
|
54
|
+
if (hi === Number.POSITIVE_INFINITY) {
|
|
55
|
+
hi = Math.max(lo, 1) * 2;
|
|
56
|
+
while (!ok(hi)) {
|
|
57
|
+
lo = hi;
|
|
58
|
+
hi *= 2;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
53
61
|
for (let i = 0; i < 60; i++) {
|
|
54
62
|
const mid = (lo + hi) / 2;
|
|
55
63
|
if (ok(mid))
|
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/gone.js
CHANGED
|
@@ -77,6 +77,7 @@ export function goneIndex(mix) {
|
|
|
77
77
|
/** Hands voices let go of from `gone` to the departed index, noting the latest that left. */
|
|
78
78
|
function forgot(mix, out) {
|
|
79
79
|
for (const v of out) {
|
|
80
|
+
mix.parters.delete(v);
|
|
80
81
|
mix.departed.add(mix, v);
|
|
81
82
|
if (v.doneAt > mix.transport.forgotTo)
|
|
82
83
|
mix.transport.forgotTo = v.doneAt;
|
package/dist/handle.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export interface HandleHost<I, O> {
|
|
|
11
11
|
* The voice's clock jumped: for an owner, so did every clock it holds. With `rebuild`, their
|
|
12
12
|
* state is made again for where they now are. How sure that leaves it.
|
|
13
13
|
*/
|
|
14
|
-
sought(voice: Voice<I, O>, rebuild: boolean): Doubt;
|
|
14
|
+
sought(voice: Voice<I, O>, rebuild: boolean, ahead: boolean): Doubt;
|
|
15
15
|
fade(voice: Voice<I, O>, opts: FadeOptions<I> | undefined): void;
|
|
16
16
|
rise(voice: Voice<I, O>, opts: {
|
|
17
17
|
over?: number;
|
package/dist/handle.js
CHANGED
|
@@ -115,14 +115,16 @@ export class VoiceHandle {
|
|
|
115
115
|
return 'exact';
|
|
116
116
|
voice.written = true;
|
|
117
117
|
// A pending voice's clock is anchored at its start, so it starts there on time.
|
|
118
|
+
let ahead = false;
|
|
118
119
|
if (voice.state !== 'pending') {
|
|
119
120
|
const u = this.#host.nowFor(voice);
|
|
120
121
|
leave(voice, u, true);
|
|
121
122
|
voice.rebase(u);
|
|
123
|
+
ahead = elapsed > voice.anchorElapsed;
|
|
122
124
|
}
|
|
123
125
|
voice.anchorElapsed = elapsed;
|
|
124
126
|
voice.seeks++;
|
|
125
|
-
const doubt = this.#host.sought(voice, opts?.state !== 'keep');
|
|
127
|
+
const doubt = this.#host.sought(voice, opts?.state !== 'keep', ahead);
|
|
126
128
|
this.#host.changed(voice);
|
|
127
129
|
if (this.#host.taping())
|
|
128
130
|
this.#host.record(this, 'seek', (h) => h.seek(elapsed, opts));
|
package/dist/held.d.ts
CHANGED
|
@@ -22,7 +22,8 @@ export declare function sinceOf<I, O>(this: Mixer<I, O>, voice: Voice<I, O>, del
|
|
|
22
22
|
/**
|
|
23
23
|
* The mix time a subject's fade in counts from: `since`, but no earlier than its voice starts,
|
|
24
24
|
* where a voice sought ahead of its start has a subject's delay run out before it; and from when
|
|
25
|
-
* the voice first showed, for one freezing before.
|
|
25
|
+
* the voice first showed, for one freezing before. Its start is where its owners' clocks first
|
|
26
|
+
* read it, as `since` is, not where they would by their controls now.
|
|
26
27
|
*/
|
|
27
28
|
export declare function shownOf<I, O>(this: Mixer<I, O>, voice: Voice<I, O>, since: number): number;
|
|
28
29
|
/** Lists a record whose origin is still ahead of `now`, for a later change to the clock to move. */
|
package/dist/held.js
CHANGED
|
@@ -2,9 +2,7 @@ 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 {
|
|
6
|
-
import { originOf } from './origin.js';
|
|
7
|
-
import { startOf } from './place.js';
|
|
5
|
+
import { originOf, startedAt } from './origin.js';
|
|
8
6
|
import { record } from './record.js';
|
|
9
7
|
import { unreach, unreached } from './unreached.js';
|
|
10
8
|
/** The record a voice gives every subject it does not reach. */
|
|
@@ -24,7 +22,7 @@ export function unreachedOf(voice, now) {
|
|
|
24
22
|
*/
|
|
25
23
|
export function held(voice, subject, slot, guess = null) {
|
|
26
24
|
if (voice.sharing) {
|
|
27
|
-
const all = everyoneOf(this, voice);
|
|
25
|
+
const all = this.share.everyoneOf(this, voice);
|
|
28
26
|
if (all !== null)
|
|
29
27
|
return all;
|
|
30
28
|
}
|
|
@@ -67,8 +65,8 @@ export function held(voice, subject, slot, guess = null) {
|
|
|
67
65
|
voice.subjects.set(subject, held);
|
|
68
66
|
waits(voice, held, now);
|
|
69
67
|
// A subject a voice saw while it shared one record was counted then.
|
|
70
|
-
if (sighted(voice, slot))
|
|
71
|
-
inherit(voice, held, slot);
|
|
68
|
+
if (voice.sighted !== null && this.share?.sighted(voice, slot))
|
|
69
|
+
this.share.inherit(voice, held, slot);
|
|
72
70
|
else
|
|
73
71
|
voice.seen++;
|
|
74
72
|
if (delay > voice.latest) {
|
|
@@ -119,13 +117,21 @@ export function sinceOf(voice, delay) {
|
|
|
119
117
|
/**
|
|
120
118
|
* The mix time a subject's fade in counts from: `since`, but no earlier than its voice starts,
|
|
121
119
|
* where a voice sought ahead of its start has a subject's delay run out before it; and from when
|
|
122
|
-
* the voice first showed, for one freezing before.
|
|
120
|
+
* the voice first showed, for one freezing before. Its start is where its owners' clocks first
|
|
121
|
+
* read it, as `since` is, not where they would by their controls now.
|
|
123
122
|
*/
|
|
124
123
|
export function shownOf(voice, since) {
|
|
125
|
-
const start =
|
|
124
|
+
const start = startedAt(voice);
|
|
126
125
|
const from = since < start ? start : since;
|
|
127
126
|
return voice.freezesBefore && voice.opened < from ? voice.opened : from;
|
|
128
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* Whether a listed record stays listed at `now`: its origin is ahead, or it is a motion voice's,
|
|
130
|
+
* unread since its origin, which `still` asks after since the motion has no run for it yet.
|
|
131
|
+
*/
|
|
132
|
+
function stillEarly(voice, held, now) {
|
|
133
|
+
return !(held.since <= now) || (voice.motion !== undefined && !(held.probed >= held.since));
|
|
134
|
+
}
|
|
129
135
|
/** Lists a record whose origin is still ahead of `now`, for a later change to the clock to move. */
|
|
130
136
|
export function waits(voice, held, now) {
|
|
131
137
|
if (held.since <= now)
|
|
@@ -136,7 +142,7 @@ export function waits(voice, held, now) {
|
|
|
136
142
|
if (early.length >= 64 && (early.length & (early.length - 1)) === 0) {
|
|
137
143
|
let kept = 0;
|
|
138
144
|
for (const h of early)
|
|
139
|
-
if (
|
|
145
|
+
if (stillEarly(voice, h, now))
|
|
140
146
|
early[kept++] = h;
|
|
141
147
|
early.length = kept;
|
|
142
148
|
}
|
|
@@ -148,6 +154,7 @@ export function waits(voice, held, now) {
|
|
|
148
154
|
*/
|
|
149
155
|
export function begin(mix, voice, now) {
|
|
150
156
|
voice.state = 'live';
|
|
157
|
+
voice.begunSeq = mix.transport.seq;
|
|
151
158
|
if (voice.anchorElapsed !== 0) {
|
|
152
159
|
voice.seeks++;
|
|
153
160
|
voice.rebuilds++;
|
|
@@ -179,7 +186,7 @@ export function reorigin(mix, voice, now) {
|
|
|
179
186
|
let kept = 0;
|
|
180
187
|
for (const held of early) {
|
|
181
188
|
origin(mix, voice, held);
|
|
182
|
-
if (
|
|
189
|
+
if (stillEarly(voice, held, now))
|
|
183
190
|
early[kept++] = held;
|
|
184
191
|
}
|
|
185
192
|
early.length = kept;
|
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) {
|
|
@@ -205,7 +216,11 @@ function handleHost(mix) {
|
|
|
205
216
|
mix.lanes?.refill();
|
|
206
217
|
},
|
|
207
218
|
// A delta read before an owner's seek, or a hit booked, is not taken as standing after it.
|
|
208
|
-
sought: (voice, rebuild) => {
|
|
219
|
+
sought: (voice, rebuild, ahead) => {
|
|
220
|
+
if (ahead && voice.holding !== null && !mix.projecting) {
|
|
221
|
+
mix.leapt ??= new Set();
|
|
222
|
+
mix.leapt.add(voice);
|
|
223
|
+
}
|
|
209
224
|
if (rebuild)
|
|
210
225
|
voice.rebuilds++;
|
|
211
226
|
let doubt = seekDoubt(mix, voice, rebuild);
|
|
@@ -248,7 +263,9 @@ function handleHost(mix) {
|
|
|
248
263
|
? undefined
|
|
249
264
|
: voice.subjects.get(subject);
|
|
250
265
|
// A voice that stopped sharing makes a subject's record at its next read, from what it kept.
|
|
251
|
-
|
|
266
|
+
if (held !== undefined)
|
|
267
|
+
return held.weight;
|
|
268
|
+
return mix.share === null ? 0 : mix.share.weightAt(voice, slot);
|
|
252
269
|
},
|
|
253
270
|
taping: () => taping(mix),
|
|
254
271
|
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/lane.d.ts
CHANGED
|
@@ -185,6 +185,8 @@ export declare class Lane<I, O> implements Positions<I, O> {
|
|
|
185
185
|
* checked against every lane up to some epoch has met this one if this one's is no later.
|
|
186
186
|
*/
|
|
187
187
|
epoch: number;
|
|
188
|
+
/** The lanes' probe count when it was made: a probe no later read its subject elsewhere. */
|
|
189
|
+
made: number;
|
|
188
190
|
/**
|
|
189
191
|
* Per position, `STRIDE` numbers side by side, so one subject's are one read from memory: its
|
|
190
192
|
* delay, its `since`, its weight at the last fill, its weight at the last fill a probe read, a
|
package/dist/lane.js
CHANGED
|
@@ -37,6 +37,8 @@ export class Lane {
|
|
|
37
37
|
* checked against every lane up to some epoch has met this one if this one's is no later.
|
|
38
38
|
*/
|
|
39
39
|
epoch = 0;
|
|
40
|
+
/** The lanes' probe count when it was made: a probe no later read its subject elsewhere. */
|
|
41
|
+
made = 0;
|
|
40
42
|
/**
|
|
41
43
|
* Per position, `STRIDE` numbers side by side, so one subject's are one read from memory: its
|
|
42
44
|
* delay, its `since`, its weight at the last fill, its weight at the last fill a probe read, a
|
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. */
|