@msb235/blits 0.10.0 → 0.12.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 +248 -0
- package/README.md +15 -4
- package/dist/arcs.d.ts +40 -0
- package/dist/arcs.js +239 -0
- package/dist/blend.js +1 -5
- package/dist/book.d.ts +2 -0
- package/dist/book.js +27 -3
- package/dist/chain.d.ts +17 -1
- package/dist/chain.js +57 -15
- package/dist/channels.d.ts +2 -0
- package/dist/channels.js +12 -1
- package/dist/clock.d.ts +14 -0
- package/dist/clock.js +9 -1
- package/dist/clone.js +16 -4
- package/dist/columns.d.ts +4 -5
- package/dist/columns.js +11 -5
- package/dist/crowd.d.ts +1 -1
- package/dist/crowd.js +4 -1
- package/dist/cue.js +63 -7
- package/dist/departed.d.ts +8 -3
- package/dist/departed.js +76 -29
- package/dist/due.d.ts +4 -0
- package/dist/due.js +16 -3
- package/dist/easing.d.ts +12 -1
- package/dist/easing.js +7 -1
- package/dist/everyone.d.ts +14 -1
- package/dist/everyone.js +27 -2
- package/dist/fade.d.ts +12 -5
- package/dist/fade.js +57 -19
- package/dist/fill.js +16 -9
- package/dist/fit.d.ts +8 -1
- package/dist/fit.js +7 -3
- package/dist/fold.d.ts +1 -1
- package/dist/fold.js +112 -9
- package/dist/frames.d.ts +2 -0
- package/dist/frames.js +17 -0
- package/dist/gather.js +38 -7
- package/dist/handle.d.ts +7 -2
- package/dist/handle.js +28 -12
- package/dist/held.d.ts +13 -2
- package/dist/held.js +43 -9
- package/dist/history.d.ts +25 -2
- package/dist/history.js +163 -35
- package/dist/hosts.js +45 -17
- package/dist/index.d.ts +5 -2
- package/dist/index.js +3 -1
- package/dist/keyfill.js +3 -1
- package/dist/lane.d.ts +1 -1
- package/dist/lane.js +3 -1
- package/dist/lanes.d.ts +31 -7
- package/dist/lanes.js +57 -6
- package/dist/lean.d.ts +15 -0
- package/dist/lean.js +23 -0
- package/dist/leavings.d.ts +6 -1
- package/dist/leavings.js +16 -2
- package/dist/marks.d.ts +7 -3
- package/dist/marks.js +105 -27
- package/dist/meet.js +1 -0
- package/dist/mixer.d.ts +35 -6
- package/dist/mixer.js +113 -45
- package/dist/motion.d.ts +4 -1
- package/dist/motion.js +16 -2
- package/dist/motions.d.ts +4 -0
- package/dist/motions.js +45 -11
- package/dist/move.js +35 -12
- package/dist/numbers.d.ts +5 -1
- package/dist/numbers.js +4 -0
- package/dist/owner.d.ts +18 -2
- package/dist/owner.js +44 -3
- package/dist/pack.d.ts +1 -0
- package/dist/pack.js +3 -0
- package/dist/place.d.ts +8 -0
- package/dist/place.js +16 -8
- package/dist/placed.d.ts +19 -0
- package/dist/placed.js +54 -0
- package/dist/project.d.ts +5 -2
- package/dist/project.js +238 -34
- package/dist/pull.js +37 -8
- package/dist/qualify.d.ts +10 -0
- package/dist/qualify.js +60 -3
- package/dist/reading.d.ts +8 -1
- package/dist/reading.js +8 -1
- package/dist/record.d.ts +6 -0
- package/dist/record.js +2 -0
- package/dist/restored.d.ts +69 -17
- package/dist/restored.js +163 -50
- package/dist/revive.d.ts +6 -3
- package/dist/revive.js +11 -3
- package/dist/roster.js +2 -1
- package/dist/rows.js +15 -5
- package/dist/seek.d.ts +7 -2
- package/dist/seek.js +152 -43
- package/dist/shared.d.ts +5 -0
- package/dist/shared.js +5 -0
- package/dist/signals.d.ts +10 -0
- package/dist/signals.js +17 -0
- package/dist/spans.d.ts +5 -0
- package/dist/spans.js +75 -5
- package/dist/store.d.ts +13 -0
- package/dist/store.js +23 -0
- package/dist/strays.js +50 -2
- package/dist/tape.d.ts +29 -4
- package/dist/tape.js +49 -11
- package/dist/touch.js +3 -2
- package/dist/transport.d.ts +11 -2
- package/dist/transport.js +26 -10
- package/dist/types/arc.d.ts +55 -0
- package/dist/types/arc.js +1 -0
- package/dist/types/mix.d.ts +57 -14
- package/dist/types/patch.d.ts +5 -1
- package/dist/types/place.d.ts +11 -4
- package/dist/types/transport.d.ts +12 -3
- package/dist/types/voice.d.ts +72 -5
- package/dist/types/watch.d.ts +126 -0
- package/dist/types/watch.js +1 -0
- package/dist/types.d.ts +2 -0
- package/dist/unpage.d.ts +6 -1
- package/dist/unpage.js +34 -2
- package/dist/voice.d.ts +93 -16
- package/dist/voice.js +60 -3
- package/dist/watch.d.ts +26 -0
- package/dist/watch.js +441 -0
- package/dist/weigh.d.ts +13 -2
- package/dist/weigh.js +10 -3
- package/docs/schema.html +106 -38
- package/package.json +10 -4
package/dist/owner.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { arcShare } from './arcs.js';
|
|
1
2
|
import { backWith, clampWeight, elapsedWith, envelope, timeWith } from './clock.js';
|
|
2
3
|
/** What an owner is cued with in place of a patch: it writes nothing, so no fold ever meets it. */
|
|
3
4
|
export const ownerPatch = Object.freeze({
|
|
@@ -13,6 +14,35 @@ export class Holding {
|
|
|
13
14
|
/** How many it has held, and how many of those finished their passes. */
|
|
14
15
|
kids = 0;
|
|
15
16
|
played = 0;
|
|
17
|
+
/**
|
|
18
|
+
* When the children that left coast, as pairs of the frame one left in and the latest coast so
|
|
19
|
+
* far, mix time: a pair only where the latest grew, so a seek back cuts it to a prefix.
|
|
20
|
+
*/
|
|
21
|
+
coasts = [];
|
|
22
|
+
/** The frame the first child to leave before its passes ended left in; Infinity for none. */
|
|
23
|
+
cutSeq = Number.POSITIVE_INFINITY;
|
|
24
|
+
/** The latest coast of a child that left; -Infinity for none. */
|
|
25
|
+
get coast() {
|
|
26
|
+
const n = this.coasts.length;
|
|
27
|
+
return n === 0 ? Number.NEGATIVE_INFINITY : this.coasts[n - 1];
|
|
28
|
+
}
|
|
29
|
+
/** A child left in frame `seq`, coasting at `coast`, or before its passes ended for undefined. */
|
|
30
|
+
left(coast, seq) {
|
|
31
|
+
if (coast === undefined) {
|
|
32
|
+
if (seq < this.cutSeq)
|
|
33
|
+
this.cutSeq = seq;
|
|
34
|
+
}
|
|
35
|
+
else if (coast > this.coast)
|
|
36
|
+
this.coasts.push(seq, coast);
|
|
37
|
+
}
|
|
38
|
+
/** Forgets the children that left after frame `seq`, for a seek or read back to it. */
|
|
39
|
+
back(seq) {
|
|
40
|
+
const c = this.coasts;
|
|
41
|
+
while (c.length > 0 && c[c.length - 2] > seq)
|
|
42
|
+
c.length -= 2;
|
|
43
|
+
if (this.cutSeq > seq)
|
|
44
|
+
this.cutSeq = Number.POSITIVE_INFINITY;
|
|
45
|
+
}
|
|
16
46
|
}
|
|
17
47
|
/**
|
|
18
48
|
* What an owner's clock reads at mix time `now`, through every owner above it: -Infinity before it
|
|
@@ -99,12 +129,19 @@ export function ownWeight(owner, now, reduced, base) {
|
|
|
99
129
|
/** What every owner above a voice multiplies into its weight. */
|
|
100
130
|
export function ownersWeight(voice, now, reduced, base) {
|
|
101
131
|
let w = 1;
|
|
102
|
-
|
|
132
|
+
let child = voice;
|
|
133
|
+
for (let o = voice.owner; o !== null; child = o, o = o.owner) {
|
|
103
134
|
w *= ownWeight(o, now, reduced, base);
|
|
135
|
+
if (o.arc !== null)
|
|
136
|
+
w *= arcShare(o, child, now, reduced);
|
|
137
|
+
}
|
|
104
138
|
return w;
|
|
105
139
|
}
|
|
106
|
-
/**
|
|
107
|
-
|
|
140
|
+
/**
|
|
141
|
+
* Points a projection's copies at each other's owners, each owner holding only copies; for a read
|
|
142
|
+
* back to frame `seq`, as its children that had left by then left it.
|
|
143
|
+
*/
|
|
144
|
+
export function relink(copies, seq) {
|
|
108
145
|
const byId = new Map();
|
|
109
146
|
for (const v of copies) {
|
|
110
147
|
byId.set(v.id, v);
|
|
@@ -112,6 +149,10 @@ export function relink(copies) {
|
|
|
112
149
|
const h = new Holding();
|
|
113
150
|
h.kids = v.holding.kids;
|
|
114
151
|
h.played = v.holding.played;
|
|
152
|
+
h.coasts = v.holding.coasts.slice();
|
|
153
|
+
h.cutSeq = v.holding.cutSeq;
|
|
154
|
+
if (seq !== undefined)
|
|
155
|
+
h.back(seq);
|
|
115
156
|
v.holding = h;
|
|
116
157
|
}
|
|
117
158
|
}
|
package/dist/pack.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export interface PackedRecord {
|
|
|
12
12
|
stepped: number;
|
|
13
13
|
ticks: number;
|
|
14
14
|
rebuilt: number;
|
|
15
|
+
copied?: true;
|
|
15
16
|
/**
|
|
16
17
|
* What `setting.keep` held, in the order its owners first kept it. An owner is code, which no
|
|
17
18
|
* store keeps, and a voice revived from a descriptor has new ones; the same code keeps in the same
|
package/dist/pack.js
CHANGED
|
@@ -18,6 +18,8 @@ export function packHeld(voice, h) {
|
|
|
18
18
|
rebuilt: h.rebuilt,
|
|
19
19
|
kept: kept.length === 0 ? null : kept.map(clone),
|
|
20
20
|
};
|
|
21
|
+
if (h.copied)
|
|
22
|
+
p.copied = true;
|
|
21
23
|
if (h.base !== undefined)
|
|
22
24
|
p.base = clone(h.base);
|
|
23
25
|
if (h.slope !== undefined)
|
|
@@ -42,6 +44,7 @@ export function unpackHeld(voice, p) {
|
|
|
42
44
|
h.stepped = p.stepped;
|
|
43
45
|
h.ticks = p.ticks;
|
|
44
46
|
h.rebuilt = p.rebuilt;
|
|
47
|
+
h.copied = p.copied === true;
|
|
45
48
|
if (p.kept !== null)
|
|
46
49
|
h.unkept = p.kept;
|
|
47
50
|
if (p.base !== undefined)
|
package/dist/place.d.ts
CHANGED
|
@@ -10,6 +10,8 @@ export declare function mixAt<I, O>(mix: Mixer<I, O>, u: number): number;
|
|
|
10
10
|
export declare function pin<I, O>(mix: Mixer<I, O>, voice: Voice<I, O>, u: number): void;
|
|
11
11
|
/** Puts each pending voice's start, given in host time, where the mix's rate now puts it. */
|
|
12
12
|
export declare function repin<I, O>(mix: Mixer<I, O>): void;
|
|
13
|
+
/** Moves a pending voice's start, its clock with it; false where it is already there. */
|
|
14
|
+
export declare function startAt<I, O>(mix: Mixer<I, O>, voice: Voice<I, O>, start: number): boolean;
|
|
13
15
|
/** Refuses a placement that names a mark twice on one side, or that waits on itself. */
|
|
14
16
|
export declare function checkPlacement<I, O>(mix: Mixer<I, O>, spec: VoiceSpec<I, O>, anchor: Placement, owner: Voice<I, O> | null): void;
|
|
15
17
|
/**
|
|
@@ -18,3 +20,9 @@ export declare function checkPlacement<I, O>(mix: Mixer<I, O>, spec: VoiceSpec<I
|
|
|
18
20
|
* last gave. Repeated so a chain of anchors settles in one sync.
|
|
19
21
|
*/
|
|
20
22
|
export declare function place<I, O>(mix: Mixer<I, O>): void;
|
|
23
|
+
/**
|
|
24
|
+
* The time an anchor answers on its voice's owner's clock, or undefined while its target has none.
|
|
25
|
+
* A time before the owner starts answers `before`: undefined, so a start waits, or -Infinity for a
|
|
26
|
+
* floor, which is no bound at all.
|
|
27
|
+
*/
|
|
28
|
+
export declare function resolve<I, O>(mix: Mixer<I, O>, a: number | NonNullable<Placement['start']>, self: Voice<I, O>, before?: number): number | undefined;
|
package/dist/place.js
CHANGED
|
@@ -5,6 +5,7 @@ import { noted } from './history.js';
|
|
|
5
5
|
import { markOf } from './marks.js';
|
|
6
6
|
import { mixTime, ownerReading } from './owner.js';
|
|
7
7
|
import { holders, scored, scoredGone, scoreVersion, unhold } from './scored.js';
|
|
8
|
+
import { refloor } from './spans.js';
|
|
8
9
|
import { none } from './voice.js';
|
|
9
10
|
import { warnOnce } from './warn.js';
|
|
10
11
|
/** What a voice's own owner's clock reads now: the mix clock for a voice no owner holds. */
|
|
@@ -35,7 +36,7 @@ export function repin(mix) {
|
|
|
35
36
|
}
|
|
36
37
|
}
|
|
37
38
|
/** Moves a pending voice's start, its clock with it; false where it is already there. */
|
|
38
|
-
function startAt(mix, voice, start) {
|
|
39
|
+
export function startAt(mix, voice, start) {
|
|
39
40
|
if (start === voice.start)
|
|
40
41
|
return false;
|
|
41
42
|
voice.start = start;
|
|
@@ -145,18 +146,23 @@ export function place(mix) {
|
|
|
145
146
|
}
|
|
146
147
|
}
|
|
147
148
|
if (!moved)
|
|
148
|
-
|
|
149
|
+
break;
|
|
149
150
|
}
|
|
151
|
+
refloor(mix);
|
|
150
152
|
}
|
|
151
|
-
/**
|
|
152
|
-
|
|
153
|
+
/**
|
|
154
|
+
* The time an anchor answers on its voice's owner's clock, or undefined while its target has none.
|
|
155
|
+
* A time before the owner starts answers `before`: undefined, so a start waits, or -Infinity for a
|
|
156
|
+
* floor, which is no bound at all.
|
|
157
|
+
*/
|
|
158
|
+
export function resolve(mix, a, self, before) {
|
|
153
159
|
const o = self.owner;
|
|
154
160
|
if (typeof a === 'number')
|
|
155
161
|
return o === null ? mixAt(mix, a - mix.offset) : a;
|
|
156
162
|
if ('all' in a) {
|
|
157
163
|
let latest = Number.NEGATIVE_INFINITY;
|
|
158
164
|
for (const m of a.all) {
|
|
159
|
-
const t = member(mix, m, self);
|
|
165
|
+
const t = member(mix, m, self, before);
|
|
160
166
|
if (t === undefined)
|
|
161
167
|
return undefined;
|
|
162
168
|
latest = Math.max(latest, t);
|
|
@@ -169,7 +175,7 @@ function resolve(mix, a, self) {
|
|
|
169
175
|
let earliest = Number.POSITIVE_INFINITY;
|
|
170
176
|
let unknown = false;
|
|
171
177
|
for (const m of a.any) {
|
|
172
|
-
const t = member(mix, m, self);
|
|
178
|
+
const t = member(mix, m, self, before);
|
|
173
179
|
if (t === undefined)
|
|
174
180
|
unknown = true;
|
|
175
181
|
else
|
|
@@ -205,14 +211,16 @@ function resolve(mix, a, self) {
|
|
|
205
211
|
if (o === null)
|
|
206
212
|
return t + by;
|
|
207
213
|
const local = ownerReading(o, t);
|
|
214
|
+
if (local === Number.NEGATIVE_INFINITY)
|
|
215
|
+
return before;
|
|
208
216
|
return Number.isFinite(local) ? local + by : undefined;
|
|
209
217
|
}
|
|
210
218
|
/**
|
|
211
219
|
* What one member of a join answers, or the time it last gave once its target has left, as a lone
|
|
212
220
|
* anchor keeps its voice where its target last put it.
|
|
213
221
|
*/
|
|
214
|
-
function member(mix, a, self) {
|
|
215
|
-
const t = resolve(mix, a, self);
|
|
222
|
+
function member(mix, a, self, before) {
|
|
223
|
+
const t = resolve(mix, a, self, before);
|
|
216
224
|
if (t === undefined)
|
|
217
225
|
return self.answers?.get(a);
|
|
218
226
|
if (!mix.projecting) {
|
package/dist/placed.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* By subject number, the crowd voices whose rows are placed on it, so letting a number go reaches
|
|
3
|
+
* its rows without walking every crowd's. Kept by voice id, which a row keeps as a crowd closes up
|
|
4
|
+
* or is rebuilt around it.
|
|
5
|
+
*/
|
|
6
|
+
export declare class Placed {
|
|
7
|
+
/** By subject number, one voice placed on it; 0, which is no voice's id, for none. */
|
|
8
|
+
private one;
|
|
9
|
+
/** The others, for a subject with several; null until some subject has two. */
|
|
10
|
+
private rest;
|
|
11
|
+
/** Makes room for subject numbers below `cap`. */
|
|
12
|
+
grow(cap: number): void;
|
|
13
|
+
/** Some voice placed on the subject at `slot`, 0 for none. */
|
|
14
|
+
any(slot: number): number;
|
|
15
|
+
/** Every voice placed on the subject at `slot`, in no order: for a test to read. */
|
|
16
|
+
all(slot: number): number[];
|
|
17
|
+
add(slot: number, id: number): void;
|
|
18
|
+
remove(slot: number, id: number): void;
|
|
19
|
+
}
|
package/dist/placed.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* By subject number, the crowd voices whose rows are placed on it, so letting a number go reaches
|
|
3
|
+
* its rows without walking every crowd's. Kept by voice id, which a row keeps as a crowd closes up
|
|
4
|
+
* or is rebuilt around it.
|
|
5
|
+
*/
|
|
6
|
+
export class Placed {
|
|
7
|
+
/** By subject number, one voice placed on it; 0, which is no voice's id, for none. */
|
|
8
|
+
one = new Int32Array(0);
|
|
9
|
+
/** The others, for a subject with several; null until some subject has two. */
|
|
10
|
+
rest = null;
|
|
11
|
+
/** Makes room for subject numbers below `cap`. */
|
|
12
|
+
grow(cap) {
|
|
13
|
+
const one = new Int32Array(cap);
|
|
14
|
+
one.set(this.one);
|
|
15
|
+
this.one = one;
|
|
16
|
+
}
|
|
17
|
+
/** Some voice placed on the subject at `slot`, 0 for none. */
|
|
18
|
+
any(slot) {
|
|
19
|
+
return this.one[slot] | 0;
|
|
20
|
+
}
|
|
21
|
+
/** Every voice placed on the subject at `slot`, in no order: for a test to read. */
|
|
22
|
+
all(slot) {
|
|
23
|
+
const one = this.any(slot);
|
|
24
|
+
return one === 0 ? [] : [one, ...(this.rest?.get(slot) ?? [])];
|
|
25
|
+
}
|
|
26
|
+
add(slot, id) {
|
|
27
|
+
if (this.one[slot] === 0) {
|
|
28
|
+
this.one[slot] = id;
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
this.rest ??= new Map();
|
|
32
|
+
const more = this.rest.get(slot);
|
|
33
|
+
if (more === undefined)
|
|
34
|
+
this.rest.set(slot, [id]);
|
|
35
|
+
else
|
|
36
|
+
more.push(id);
|
|
37
|
+
}
|
|
38
|
+
remove(slot, id) {
|
|
39
|
+
const more = this.rest?.get(slot);
|
|
40
|
+
if (this.one[slot] === id)
|
|
41
|
+
this.one[slot] = more === undefined ? 0 : more.pop();
|
|
42
|
+
else if (more !== undefined) {
|
|
43
|
+
const i = more.indexOf(id);
|
|
44
|
+
if (i < 0)
|
|
45
|
+
return;
|
|
46
|
+
more[i] = more[more.length - 1];
|
|
47
|
+
more.pop();
|
|
48
|
+
}
|
|
49
|
+
else
|
|
50
|
+
return;
|
|
51
|
+
if (more !== undefined && more.length === 0)
|
|
52
|
+
this.rest.delete(slot);
|
|
53
|
+
}
|
|
54
|
+
}
|
package/dist/project.d.ts
CHANGED
|
@@ -4,9 +4,12 @@ import type { TransportProjection } from './types.js';
|
|
|
4
4
|
import type { Subject, Voice } from './voice.js';
|
|
5
5
|
/**
|
|
6
6
|
* Every mix on a transport read at mix time `t`, through copies of them on a transport of their
|
|
7
|
-
* own, moved together so an anchor across mixes answers as it would live.
|
|
7
|
+
* own, moved together so an anchor across mixes answers as it would live. Ahead, they stop at each
|
|
8
|
+
* known event on the way, and a subject asked about is read at each before `t`.
|
|
8
9
|
*/
|
|
9
|
-
export declare function projectAll(transport: Transport,
|
|
10
|
+
export declare function projectAll(transport: Transport, at: number | {
|
|
11
|
+
readonly frame: number;
|
|
12
|
+
}): TransportProjection;
|
|
10
13
|
/** Sets each copied voice's state to what its clock and fade make it at `t`. */
|
|
11
14
|
export declare function stateAt<I, O>(c: Mixer<I, O>, t: number): void;
|
|
12
15
|
/** Gives a projection's copy what it reads of the live mix as it is, before its voices are copied. */
|