@msb235/blits 0.15.0 → 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 +79 -0
- package/README.md +1 -1
- package/dist/ahead.js +5 -4
- package/dist/bare.js +22 -7
- package/dist/chain.js +2 -3
- package/dist/color.d.ts +36 -14
- package/dist/color.js +186 -58
- package/dist/columns.d.ts +3 -12
- package/dist/columns.js +56 -41
- package/dist/crowd.d.ts +8 -10
- package/dist/crowd.js +17 -18
- package/dist/cue.js +7 -4
- package/dist/delay.d.ts +3 -0
- package/dist/delay.js +7 -0
- package/dist/due.js +1 -1
- package/dist/easing.d.ts +2 -0
- package/dist/easing.js +4 -0
- package/dist/everyone.d.ts +22 -6
- package/dist/everyone.js +47 -8
- package/dist/fade.d.ts +11 -0
- package/dist/fade.js +44 -8
- package/dist/fill.js +1 -1
- package/dist/fold.js +4 -7
- package/dist/held.js +5 -5
- package/dist/hosts.d.ts +7 -0
- package/dist/hosts.js +18 -5
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/lane.d.ts +2 -5
- package/dist/lane.js +14 -10
- package/dist/lanes.d.ts +33 -5
- package/dist/lanes.js +34 -28
- package/dist/lch.d.ts +23 -0
- package/dist/lch.js +126 -0
- package/dist/meet.js +5 -3
- package/dist/mixer.d.ts +6 -2
- package/dist/mixer.js +7 -0
- package/dist/motions.d.ts +4 -1
- package/dist/motions.js +16 -2
- package/dist/move.js +15 -10
- package/dist/named.d.ts +6 -1
- package/dist/named.js +29 -1
- package/dist/numbers.d.ts +5 -0
- package/dist/numbers.js +29 -0
- 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 +18 -4
- package/dist/qualify.js +10 -11
- package/dist/renumber.d.ts +10 -0
- package/dist/renumber.js +75 -0
- package/dist/roles.js +1 -3
- package/dist/roster.d.ts +6 -0
- package/dist/roster.js +8 -1
- package/dist/rows.js +27 -19
- package/dist/sample.js +2 -1
- package/dist/seat.d.ts +17 -0
- package/dist/seat.js +25 -0
- 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/strays.js +3 -2
- package/dist/touch.js +1 -2
- package/dist/trace.d.ts +4 -0
- package/dist/trace.js +255 -0
- package/dist/turns.js +2 -1
- package/dist/types/mix.d.ts +15 -0
- package/dist/types/trace.d.ts +51 -0
- package/dist/types/trace.js +1 -0
- package/dist/types/voice.d.ts +13 -7
- package/dist/types.d.ts +1 -0
- package/dist/unreached.d.ts +2 -0
- package/dist/unreached.js +7 -0
- package/dist/voice.d.ts +22 -0
- package/dist/voice.js +44 -4
- package/docs/schema.html +48 -11
- package/package.json +1 -1
package/dist/held.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { changed } from './chain.js';
|
|
2
2
|
import { stepOf } from './clock.js';
|
|
3
|
+
import { delayOf } from './delay.js';
|
|
3
4
|
import { schedule } from './due.js';
|
|
4
|
-
import { everyoneOf, inherit, sighted } from './everyone.js';
|
|
5
5
|
import { originOf } from './origin.js';
|
|
6
6
|
import { startOf } from './place.js';
|
|
7
7
|
import { record } from './record.js';
|
|
@@ -23,7 +23,7 @@ export function unreachedOf(voice, now) {
|
|
|
23
23
|
*/
|
|
24
24
|
export function held(voice, subject, slot, guess = null) {
|
|
25
25
|
if (voice.sharing) {
|
|
26
|
-
const all = everyoneOf(this, voice);
|
|
26
|
+
const all = this.share.everyoneOf(this, voice);
|
|
27
27
|
if (all !== null)
|
|
28
28
|
return all;
|
|
29
29
|
}
|
|
@@ -50,7 +50,7 @@ export function held(voice, subject, slot, guess = null) {
|
|
|
50
50
|
voice.keyed ??= new Set();
|
|
51
51
|
voice.keyed.add(this.keys.key(subject));
|
|
52
52
|
}
|
|
53
|
-
const delay = voice
|
|
53
|
+
const delay = delayOf(voice, subject);
|
|
54
54
|
const since = this.sinceOf(voice, delay);
|
|
55
55
|
const shown = this.shownOf(voice, since);
|
|
56
56
|
held = record(voice, true, voice.patch.state ? voice.patch.state(subject) : undefined);
|
|
@@ -66,8 +66,8 @@ export function held(voice, subject, slot, guess = null) {
|
|
|
66
66
|
voice.subjects.set(subject, held);
|
|
67
67
|
waits(voice, held, now);
|
|
68
68
|
// A subject a voice saw while it shared one record was counted then.
|
|
69
|
-
if (sighted(voice, slot))
|
|
70
|
-
inherit(voice, held, slot);
|
|
69
|
+
if (voice.sighted !== null && this.share?.sighted(voice, slot))
|
|
70
|
+
this.share.inherit(voice, held, slot);
|
|
71
71
|
else
|
|
72
72
|
voice.seen++;
|
|
73
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';
|
|
@@ -20,7 +20,7 @@ export { fold } from './stack.js';
|
|
|
20
20
|
export type { Ticked, Ticker, TickerOptions } from './ticker.js';
|
|
21
21
|
export { ticker } from './ticker.js';
|
|
22
22
|
export { transport } from './transport.js';
|
|
23
|
-
export type { Anchor, AnnounceOptions, ArcHandle, ArcPart, ArcSpec, ArcVoice, Band, BlendMember, BookedHit, Booker, BookOptions, Channel, Circle, Columns, Described, Doubt, Easing, Engine, FadeOptions, FadeSpec, Finder, FitResult, GlideSpec, Handle, HistoryOptions, HistoryStore, Hit, Hold, Keyframe, Kit, Mark, Marked, MarkName, Mix, MixOptions, MotionSpec, OwnerSpec, Paged, PagedStream, Patch, Placement, Probed, Projection, Pulled, Query, Registry, RegistryChange, SeekOptions, Sent, Setting, Signal, SpanHandle, SpanHints, SpanSpec, SpringSpec, SubjectFade, Taken, Tape, TapeBranch, TapeMaker, TapeOp, TapeOptions, Transport, TransportOptions, TransportProjection, TweenSpec, VoiceFade, VoiceSpec, Watched, WatchedFrame, WatchedHistory, WatchedVoice, } from './types.js';
|
|
23
|
+
export type { Anchor, AnnounceOptions, ArcHandle, ArcPart, ArcSpec, ArcVoice, Band, BlendMember, BookedHit, Booker, BookOptions, Channel, Circle, Columns, Described, Doubt, Easing, Engine, FadeOptions, FadeSpec, Finder, FitResult, GlideSpec, Handle, HistoryOptions, HistoryStore, Hit, Hold, Keyframe, Kit, Mark, Marked, MarkName, Mix, MixOptions, MotionSpec, NumberChannel, OwnerSpec, Paged, PagedStream, Patch, Placement, Probed, Projection, Pulled, Query, Registry, RegistryChange, Run, SeekOptions, Sent, Setting, Signal, SpanHandle, SpanHints, SpanSpec, SpringSpec, SubjectFade, Taken, Tape, TapeBranch, TapeMaker, TapeOp, TapeOptions, Trace, TraceOptions, Transport, TransportOptions, TransportProjection, TweenSpec, VoiceFade, VoiceSpec, Watched, WatchedFrame, WatchedHistory, WatchedVoice, } from './types.js';
|
|
24
24
|
export { watched } from './watch.js';
|
|
25
25
|
export type { WaveOptions, WaveShape } from './wave.js';
|
|
26
26
|
export { wave, waveAt } from './wave.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
|
@@ -260,11 +260,8 @@ export declare class Lane<I, O> implements Positions<I, O> {
|
|
|
260
260
|
reserve(n: number, cap: number): void;
|
|
261
261
|
/** Gives a subject the voice reaches a position, from what its record fixed on first sight. */
|
|
262
262
|
add(slot: number, held: Subject<unknown>): void;
|
|
263
|
+
/** The subject numbered `from` is numbered `to` now, a number no position holds: same position. */
|
|
264
|
+
renumber(from: number, to: number): void;
|
|
263
265
|
/** A subject lost its number: the last position moves into its place. */
|
|
264
266
|
remove(slot: number): void;
|
|
265
267
|
}
|
|
266
|
-
/**
|
|
267
|
-
* A subject's voice time once its voice's freezes apply: frozen at 0 before it starts and at the end
|
|
268
|
-
* of its passes after, and NaN where it shows nothing, as past its end running back.
|
|
269
|
-
*/
|
|
270
|
-
export declare function frozenAt<I, O>(voice: Voice<I, O>, elapsed: number): number;
|
package/dist/lane.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { unbareLane } from './bare.js';
|
|
2
|
-
import { frozenTime } from './clock.js';
|
|
3
2
|
import { motionOf } from './motion.js';
|
|
4
3
|
/**
|
|
5
4
|
* Keeps the weight a probe read from the last fill as `Row.PROBED`, for `weightOf`, before a fill
|
|
@@ -185,6 +184,20 @@ export class Lane {
|
|
|
185
184
|
this.records[p] = held;
|
|
186
185
|
this.deltas[p] = null;
|
|
187
186
|
}
|
|
187
|
+
/** The subject numbered `from` is numbered `to` now, a number no position holds: same position. */
|
|
188
|
+
renumber(from, to) {
|
|
189
|
+
const p = this.positionOf(from);
|
|
190
|
+
if (p < 0)
|
|
191
|
+
return;
|
|
192
|
+
if (to >= this.at.length) {
|
|
193
|
+
const at = new Int32Array(Math.max(to + 1, this.at.length * 2, 64));
|
|
194
|
+
at.set(this.at);
|
|
195
|
+
this.at = at;
|
|
196
|
+
}
|
|
197
|
+
this.list[p] = to;
|
|
198
|
+
this.at[to] = p + 1;
|
|
199
|
+
this.at[from] = 0;
|
|
200
|
+
}
|
|
188
201
|
/** A subject lost its number: the last position moves into its place. */
|
|
189
202
|
remove(slot) {
|
|
190
203
|
const p = this.positionOf(slot);
|
|
@@ -214,12 +227,3 @@ export class Lane {
|
|
|
214
227
|
this.deltas[last] = null;
|
|
215
228
|
}
|
|
216
229
|
}
|
|
217
|
-
/**
|
|
218
|
-
* A subject's voice time once its voice's freezes apply: frozen at 0 before it starts and at the end
|
|
219
|
-
* of its passes after, and NaN where it shows nothing, as past its end running back.
|
|
220
|
-
*/
|
|
221
|
-
export function frozenAt(voice, elapsed) {
|
|
222
|
-
if (elapsed > voice.span && voice.hidesPast)
|
|
223
|
-
return Number.NaN;
|
|
224
|
-
return frozenTime(elapsed, voice.freezesBefore, voice.freezesAfter, voice.span);
|
|
225
|
-
}
|
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,9 @@ 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';
|
|
12
|
+
import { type Seat } from './seat.js';
|
|
10
13
|
import type { Watcher } from './stretch.js';
|
|
11
14
|
import type { Subject } from './subject.js';
|
|
12
15
|
import type { Channel } from './types.js';
|
|
@@ -63,6 +66,29 @@ export interface LaneHost<I, O> {
|
|
|
63
66
|
*/
|
|
64
67
|
export declare class Lanes<I, O> implements Watcher {
|
|
65
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
|
+
};
|
|
66
92
|
readonly numbers: Numbers<I>;
|
|
67
93
|
lanes: Lane<I, O>[];
|
|
68
94
|
/** The lanes over every subject that have started playing, by epoch. */
|
|
@@ -70,7 +96,7 @@ export declare class Lanes<I, O> implements Watcher {
|
|
|
70
96
|
readonly byId: Map<number, Lane<I, O>>;
|
|
71
97
|
/** The crowds of single-subject voices, one per list of channels, and which holds each voice. */
|
|
72
98
|
crowds: Crowd<I, O>[];
|
|
73
|
-
readonly
|
|
99
|
+
readonly seats: Map<number, Seat<I, O>>;
|
|
74
100
|
/** Which crowd voices' rows are placed on each subject. */
|
|
75
101
|
readonly placed: Placed;
|
|
76
102
|
/**
|
|
@@ -161,14 +187,16 @@ export declare class Lanes<I, O> implements Watcher {
|
|
|
161
187
|
*/
|
|
162
188
|
readonly late: number[];
|
|
163
189
|
/**
|
|
164
|
-
* What `writeLater` and `pullRun` have queued, for one set of columns, as runs: each
|
|
165
|
-
*
|
|
190
|
+
* What `writeLater` and `pullRun` have queued, for one set of columns, as runs of rows: each
|
|
191
|
+
* run's first row and how many follow, and its first lane slot where its slots follow one apart
|
|
192
|
+
* too, else -1, when each row's slot is read from `queueFrom` by row.
|
|
166
193
|
*/
|
|
167
194
|
queueSlots: Int32Array<ArrayBuffer>;
|
|
168
195
|
queueRows: Int32Array<ArrayBuffer>;
|
|
169
196
|
queueCounts: Int32Array<ArrayBuffer>;
|
|
170
197
|
queued: number;
|
|
171
198
|
queuedFor: readonly Column[] | null;
|
|
199
|
+
queueFrom: Int32Array | null;
|
|
172
200
|
keeps: boolean;
|
|
173
201
|
now: number;
|
|
174
202
|
filledAt: number;
|
|
@@ -285,7 +313,7 @@ export declare class Lanes<I, O> implements Watcher {
|
|
|
285
313
|
/** A voice's clock moved the `shown` of records it had already placed: copies them again. */
|
|
286
314
|
reshown(id: number): void;
|
|
287
315
|
/** Something on a voice changed: a crowd copies it again at the next fill. */
|
|
288
|
-
voiceChanged(
|
|
316
|
+
voiceChanged(voice: Voice<I, O>): void;
|
|
289
317
|
}
|
|
290
318
|
declare const methods: {
|
|
291
319
|
copy: typeof copy;
|
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,7 +11,9 @@ 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';
|
|
16
|
+
import { seatOf } from './seat.js';
|
|
13
17
|
/**
|
|
14
18
|
* The lanes of one mix: subject numbers, which channels and voices run on lanes, and the values a
|
|
15
19
|
* frame's fill leaves for probes to copy.
|
|
@@ -17,6 +21,10 @@ import { reportedRow, unplace } from './rows.js';
|
|
|
17
21
|
// biome-ignore lint/suspicious/noUnsafeDeclarationMerging: every member of `Methods` is installed below
|
|
18
22
|
export class Lanes {
|
|
19
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 };
|
|
20
28
|
numbers;
|
|
21
29
|
lanes = [];
|
|
22
30
|
/** The lanes over every subject that have started playing, by epoch. */
|
|
@@ -24,7 +32,7 @@ export class Lanes {
|
|
|
24
32
|
byId = new Map();
|
|
25
33
|
/** The crowds of single-subject voices, one per list of channels, and which holds each voice. */
|
|
26
34
|
crowds = [];
|
|
27
|
-
|
|
35
|
+
seats = new Map();
|
|
28
36
|
/** Which crowd voices' rows are placed on each subject. */
|
|
29
37
|
placed = new Placed();
|
|
30
38
|
/**
|
|
@@ -115,14 +123,16 @@ export class Lanes {
|
|
|
115
123
|
*/
|
|
116
124
|
late = [];
|
|
117
125
|
/**
|
|
118
|
-
* What `writeLater` and `pullRun` have queued, for one set of columns, as runs: each
|
|
119
|
-
*
|
|
126
|
+
* What `writeLater` and `pullRun` have queued, for one set of columns, as runs of rows: each
|
|
127
|
+
* run's first row and how many follow, and its first lane slot where its slots follow one apart
|
|
128
|
+
* too, else -1, when each row's slot is read from `queueFrom` by row.
|
|
120
129
|
*/
|
|
121
130
|
queueSlots = new Int32Array(0);
|
|
122
131
|
queueRows = new Int32Array(0);
|
|
123
132
|
queueCounts = new Int32Array(0);
|
|
124
133
|
queued = 0;
|
|
125
134
|
queuedFor = null;
|
|
135
|
+
queueFrom = null;
|
|
126
136
|
keeps = false;
|
|
127
137
|
now = Number.NaN;
|
|
128
138
|
filledAt = Number.NaN;
|
|
@@ -233,10 +243,9 @@ export class Lanes {
|
|
|
233
243
|
lane.remove(slot);
|
|
234
244
|
return;
|
|
235
245
|
}
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
unplace(this, c, p);
|
|
246
|
+
const s = this.seats.get(id);
|
|
247
|
+
if (s !== undefined && s.crowd.list[s.row] === slot)
|
|
248
|
+
unplace(this, s.crowd, s.row);
|
|
240
249
|
}
|
|
241
250
|
/** A voice brought a subject back: its next probe meets every lane again, as it met them first. */
|
|
242
251
|
rejoin(slot) {
|
|
@@ -254,9 +263,8 @@ export class Lanes {
|
|
|
254
263
|
const lane = this.byId.get(id);
|
|
255
264
|
if (lane !== undefined)
|
|
256
265
|
return this.reported(lane, slot);
|
|
257
|
-
const
|
|
258
|
-
|
|
259
|
-
return c === undefined || p === undefined ? undefined : reportedRow(this, c, p, slot);
|
|
266
|
+
const s = this.seats.get(id);
|
|
267
|
+
return s === undefined ? undefined : reportedRow(this, s.crowd, s.row, slot);
|
|
260
268
|
}
|
|
261
269
|
reported(lane, slot) {
|
|
262
270
|
const o = slot * 6 /* Per.SLOT */;
|
|
@@ -439,10 +447,9 @@ export class Lanes {
|
|
|
439
447
|
lane.remove(slot);
|
|
440
448
|
const placed = this.placed;
|
|
441
449
|
for (let id = placed.any(slot); id !== 0; id = placed.any(slot)) {
|
|
442
|
-
const
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
unplace(this, c, p);
|
|
450
|
+
const s = this.seats.get(id);
|
|
451
|
+
if (s !== undefined && s.crowd.list[s.row] === slot)
|
|
452
|
+
unplace(this, s.crowd, s.row);
|
|
446
453
|
else
|
|
447
454
|
placed.remove(slot, id);
|
|
448
455
|
}
|
|
@@ -474,10 +481,10 @@ export class Lanes {
|
|
|
474
481
|
* next fill, and a lane keeps the sample the old one gave.
|
|
475
482
|
*/
|
|
476
483
|
stretchChanged(id, s) {
|
|
477
|
-
const
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
c.restale(
|
|
484
|
+
const seat = this.seats.get(id);
|
|
485
|
+
if (seat !== undefined) {
|
|
486
|
+
const c = seat.crowd;
|
|
487
|
+
c.restale(seat.row, c.hot[seat.row * c.stride + 0 /* Hot.FLAGS */]);
|
|
481
488
|
return;
|
|
482
489
|
}
|
|
483
490
|
const lane = this.byId.get(id);
|
|
@@ -502,12 +509,11 @@ export class Lanes {
|
|
|
502
509
|
}
|
|
503
510
|
/** A voice's clock moved the `shown` of records it had already placed: copies them again. */
|
|
504
511
|
reshown(id) {
|
|
505
|
-
const
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
const held = c.records[p];
|
|
512
|
+
const s = this.seats.get(id);
|
|
513
|
+
if (s !== undefined) {
|
|
514
|
+
const held = s.crowd.records[s.row];
|
|
509
515
|
if (held !== undefined)
|
|
510
|
-
|
|
516
|
+
s.crowd.data[s.row * 8 /* Row.STRIDE */ + 1 /* Row.SINCE */] = held.shown;
|
|
511
517
|
}
|
|
512
518
|
const lane = this.byId.get(id);
|
|
513
519
|
if (lane === undefined)
|
|
@@ -519,12 +525,12 @@ export class Lanes {
|
|
|
519
525
|
}
|
|
520
526
|
}
|
|
521
527
|
/** Something on a voice changed: a crowd copies it again at the next fill. */
|
|
522
|
-
voiceChanged(
|
|
523
|
-
const
|
|
524
|
-
|
|
525
|
-
if (c === undefined || p === undefined)
|
|
528
|
+
voiceChanged(voice) {
|
|
529
|
+
const s = seatOf(this, voice);
|
|
530
|
+
if (s === null)
|
|
526
531
|
return;
|
|
527
|
-
const
|
|
532
|
+
const c = s.crowd;
|
|
533
|
+
const f = s.row * c.stride + 0 /* Hot.FLAGS */;
|
|
528
534
|
c.hot[f] = c.hot[f] | 64 /* Flag.VOICE */;
|
|
529
535
|
}
|
|
530
536
|
}
|
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/meet.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { open, shut } from './everyone.js';
|
|
2
|
+
import { seatOf } from './seat.js';
|
|
2
3
|
/**
|
|
3
4
|
* Whether the lanes a probe of the subject at `slot` just met (`met`) can be folded on the general
|
|
4
5
|
* path after the lanes' values: none is in a role or a crowd, the subject owes none already this
|
|
@@ -183,10 +184,11 @@ function foldNow(lanes, slot, subject, again) {
|
|
|
183
184
|
}
|
|
184
185
|
/** Places a crowd voice's row on the subject a probe met, as `Lane.add` adds a position. */
|
|
185
186
|
function place(lanes, voice, slot, subject, from, head) {
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
if (c === undefined || p === undefined)
|
|
187
|
+
const s = seatOf(lanes, voice);
|
|
188
|
+
if (s === null)
|
|
189
189
|
return false;
|
|
190
|
+
const c = s.crowd;
|
|
191
|
+
const p = s.row;
|
|
190
192
|
const h = p * c.stride;
|
|
191
193
|
const flags = c.hot[h + 0 /* Hot.FLAGS */];
|
|
192
194
|
if (c.hot[h + 6 /* Hot.EPOCH */] <= from || (flags & 16 /* Flag.PLACED */) !== 0)
|
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';
|
|
@@ -32,7 +33,7 @@ import { Store } from './store.js';
|
|
|
32
33
|
import type { MotionOwner } from './stretch.js';
|
|
33
34
|
import type { Subject } from './subject.js';
|
|
34
35
|
import { type Announced, Transport } from './transport.js';
|
|
35
|
-
import type { ArcHandle, ArcSpec, BlendMember, Booker, BookOptions, Channel, Columns, Engine, Handle, Kit, Marked, Mix, MixOptions, OwnerSpec, Patch, Projection, Sent, Signal, SpanHandle, SpanSpec, Tape, VoiceSpec } from './types.js';
|
|
36
|
+
import type { ArcHandle, ArcSpec, BlendMember, Booker, BookOptions, Channel, Columns, Engine, Handle, Kit, Marked, Mix, MixOptions, OwnerSpec, Patch, Projection, Sent, Signal, SpanHandle, SpanSpec, Tape, Trace, TraceOptions, VoiceSpec } from './types.js';
|
|
36
37
|
import { type Voice } from './voice.js';
|
|
37
38
|
import { base, capped, fadeOf, horizonFor, ownedBy, ownerBase, prime, primeLaned, weigh, weighOwned } from './weigh.js';
|
|
38
39
|
/**
|
|
@@ -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;
|
|
@@ -266,6 +269,7 @@ export declare class Mixer<I, O> implements Mix<I, O> {
|
|
|
266
269
|
project(at: number | {
|
|
267
270
|
readonly frame: number;
|
|
268
271
|
}): Projection<I, O>;
|
|
272
|
+
trace(from: number, to: number, opts?: TraceOptions): Trace<I, O>;
|
|
269
273
|
announce(name: string, opts?: {
|
|
270
274
|
at?: number;
|
|
271
275
|
score?: string;
|