@msb235/blits 0.9.0 → 0.11.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 +167 -0
- package/README.md +16 -5
- package/dist/blend.js +1 -5
- package/dist/book.d.ts +8 -5
- package/dist/book.js +47 -19
- package/dist/chain.d.ts +11 -0
- package/dist/chain.js +24 -2
- package/dist/clock.d.ts +14 -0
- package/dist/clock.js +9 -1
- 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 +52 -5
- package/dist/departed.d.ts +3 -2
- package/dist/departed.js +7 -4
- package/dist/due.d.ts +4 -0
- package/dist/due.js +16 -3
- package/dist/fade.d.ts +12 -5
- package/dist/fade.js +55 -17
- package/dist/fold.d.ts +1 -1
- package/dist/fold.js +53 -6
- package/dist/frames.d.ts +2 -0
- package/dist/frames.js +17 -0
- package/dist/handle.d.ts +5 -2
- package/dist/handle.js +20 -12
- package/dist/held.d.ts +8 -0
- package/dist/held.js +37 -6
- package/dist/history.d.ts +6 -0
- package/dist/history.js +15 -5
- package/dist/hosts.d.ts +1 -1
- package/dist/hosts.js +18 -6
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -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 +8 -0
- package/dist/lanes.js +21 -4
- 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 +102 -27
- package/dist/meet.js +1 -0
- package/dist/mixer.d.ts +23 -7
- package/dist/mixer.js +73 -29
- 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 +28 -10
- package/dist/owner.d.ts +18 -2
- package/dist/owner.js +38 -2
- package/dist/pack.d.ts +1 -0
- package/dist/pack.js +3 -0
- package/dist/placed.d.ts +19 -0
- package/dist/placed.js +54 -0
- package/dist/project.d.ts +5 -2
- package/dist/project.js +236 -32
- package/dist/pull.js +37 -8
- package/dist/qualify.js +8 -2
- package/dist/reading.d.ts +6 -0
- package/dist/reading.js +6 -0
- package/dist/record.js +1 -0
- package/dist/restored.d.ts +7 -4
- package/dist/restored.js +13 -10
- package/dist/revive.d.ts +5 -3
- package/dist/revive.js +10 -3
- package/dist/rows.js +15 -5
- package/dist/seek.d.ts +7 -2
- package/dist/seek.js +90 -35
- 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/store.d.ts +11 -0
- package/dist/store.js +19 -0
- package/dist/strays.js +50 -2
- package/dist/tape.d.ts +29 -4
- package/dist/tape.js +49 -11
- package/dist/transport.d.ts +11 -2
- package/dist/transport.js +20 -9
- package/dist/types/mix.d.ts +42 -15
- package/dist/types/patch.d.ts +5 -1
- package/dist/types/place.d.ts +25 -11
- package/dist/types/transport.d.ts +12 -3
- package/dist/types/voice.d.ts +62 -4
- package/dist/unpage.d.ts +6 -1
- package/dist/unpage.js +34 -2
- package/dist/voice.d.ts +57 -11
- package/dist/voice.js +43 -3
- package/docs/schema.html +75 -40
- package/package.json +7 -2
package/dist/voice.d.ts
CHANGED
|
@@ -12,7 +12,8 @@ import { Store } from './store.js';
|
|
|
12
12
|
import type { Anchor, Channel, FadeSpec, Handle, Patch, Setting, VoiceSpec } from './types.js';
|
|
13
13
|
/**
|
|
14
14
|
* A subject's record as it left a voice, faded out of it or dropped: the mix time and frame it
|
|
15
|
-
* left at, and `sync` where the frame's sync
|
|
15
|
+
* left at, and `sync` where it shows in its own frame: left in the frame's sync, or before anything
|
|
16
|
+
* read the mix that frame.
|
|
16
17
|
*/
|
|
17
18
|
export interface Left<I> {
|
|
18
19
|
subject: I;
|
|
@@ -20,8 +21,40 @@ export interface Left<I> {
|
|
|
20
21
|
seq: number;
|
|
21
22
|
sync: boolean;
|
|
22
23
|
held: Subject<unknown>;
|
|
24
|
+
/**
|
|
25
|
+
* The voice's fade of the subject as it stood on leaving, which a seek or read back to before
|
|
26
|
+
* puts back: its ramp out, while running, or its having faded out.
|
|
27
|
+
*/
|
|
28
|
+
ramp: Parting | null;
|
|
29
|
+
parted: Parted | null;
|
|
30
|
+
}
|
|
31
|
+
/** A subject's ramp out of one voice: when it began, how long it runs, and the frame it was asked in. */
|
|
32
|
+
export interface Parting {
|
|
33
|
+
at: number;
|
|
34
|
+
over: number;
|
|
35
|
+
seq: number;
|
|
36
|
+
}
|
|
37
|
+
export interface Parted {
|
|
38
|
+
at: number;
|
|
39
|
+
seq: number;
|
|
40
|
+
ramp: Parting | undefined;
|
|
23
41
|
}
|
|
24
42
|
export declare const none: readonly string[];
|
|
43
|
+
/**
|
|
44
|
+
* What a copy of a record keeps for the seeks that put a record back from it: the copy's state
|
|
45
|
+
* stepped on to `ticks`, as it stood near `at`, a moment one of them sought.
|
|
46
|
+
*/
|
|
47
|
+
export interface Ahead<S> {
|
|
48
|
+
/** The record the last seek put back, and the moment it sought, until that record steps. */
|
|
49
|
+
put: Subject<S> | null;
|
|
50
|
+
sought: number;
|
|
51
|
+
/** The `since` of the record put back, which the steps in `state` were counted from. */
|
|
52
|
+
since: number;
|
|
53
|
+
at: number;
|
|
54
|
+
ticks: number;
|
|
55
|
+
/** Undefined until a record has stepped on from the copy. */
|
|
56
|
+
state: S | undefined;
|
|
57
|
+
}
|
|
25
58
|
/** Everything one voice holds for one subject, chained through the next voice that reaches it. */
|
|
26
59
|
export interface Subject<S> {
|
|
27
60
|
/** The voice's `target` answer, fixed on first sight. */
|
|
@@ -56,6 +89,8 @@ export interface Subject<S> {
|
|
|
56
89
|
seeks: number;
|
|
57
90
|
/** The voice's `rebuilds` when its state was last made, so a seek's rebuild reaches it once. */
|
|
58
91
|
rebuilt: number;
|
|
92
|
+
/** Its kept signal state was stepped on in one go from a copy history kept, by a seek. */
|
|
93
|
+
copied: boolean;
|
|
59
94
|
/** Stop 0 for a `from: 'current'` voice, taken the first frame this subject is seen. */
|
|
60
95
|
base?: Record<string, unknown>;
|
|
61
96
|
/** The pose's velocity per channel at that moment, units per ms, so the first segment leaves at it. */
|
|
@@ -69,6 +104,7 @@ export interface Subject<S> {
|
|
|
69
104
|
at: number;
|
|
70
105
|
seq: number;
|
|
71
106
|
held: Subject<S>;
|
|
107
|
+
ahead?: Ahead<S>;
|
|
72
108
|
}[];
|
|
73
109
|
/** In a projection: where this record started from, and whether nothing known could be. */
|
|
74
110
|
from?: number;
|
|
@@ -203,16 +239,12 @@ export declare class Voice<I, O> {
|
|
|
203
239
|
/** Whether its patch has kept state on a record through `setting.keep`, which makes it stateful. */
|
|
204
240
|
keeping: boolean;
|
|
205
241
|
/** Subjects fading out of this voice alone, by the ramp each started; null while none are. */
|
|
206
|
-
parts: Map<I,
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
parted: Map<I, {
|
|
213
|
-
at: number;
|
|
214
|
-
seq: number;
|
|
215
|
-
}> | null;
|
|
242
|
+
parts: Map<I, Parting> | null;
|
|
243
|
+
/**
|
|
244
|
+
* Subjects faded out of this voice, by the mix time and frame each left at, and the ramp that
|
|
245
|
+
* took it out, which a seek or a read back into it puts back; null while none have.
|
|
246
|
+
*/
|
|
247
|
+
parted: Map<I, Parted> | null;
|
|
216
248
|
/**
|
|
217
249
|
* Under history, the records of subjects that left this voice, by the mix time and frame each
|
|
218
250
|
* left at, while a seek or a read back may reach them; null while none have.
|
|
@@ -237,6 +269,8 @@ export declare class Voice<I, O> {
|
|
|
237
269
|
readonly freezesAfter: boolean;
|
|
238
270
|
/** The mix time it first showed: when it was cued, or the first sync after. */
|
|
239
271
|
opened: number;
|
|
272
|
+
/** Whether no delta its patch's `at` returned has been checked against `writes` yet. */
|
|
273
|
+
unchecked: boolean;
|
|
240
274
|
/** Which of its entries in the mix's due queue is current; older ones are skipped when popped. */
|
|
241
275
|
dueToken: number;
|
|
242
276
|
/**
|
|
@@ -255,6 +289,8 @@ export declare class Voice<I, O> {
|
|
|
255
289
|
/** The least stagger of any subject seen, 0 or below, which a voice running back ends at. */
|
|
256
290
|
soonest: number;
|
|
257
291
|
restedCount: number;
|
|
292
|
+
/** Whether a seek back to before its cue has it out of the mix, until the mix plays the cue again. */
|
|
293
|
+
parked: boolean;
|
|
258
294
|
/** The mix time it was cued at; -Infinity before the first sync. */
|
|
259
295
|
cuedAt: number;
|
|
260
296
|
/** The frame it was cued in. */
|
|
@@ -411,6 +447,11 @@ export declare class Voice<I, O> {
|
|
|
411
447
|
* fading out from where it ran back to its start, as one fading from its end shows its last.
|
|
412
448
|
*/
|
|
413
449
|
get holdsFirst(): boolean;
|
|
450
|
+
/**
|
|
451
|
+
* Whether a subject past the end of its passes shows nothing: its clock runs back, so it has yet
|
|
452
|
+
* to reach them, and it does not freeze after.
|
|
453
|
+
*/
|
|
454
|
+
get hidesPast(): boolean;
|
|
414
455
|
/** A subject's voice time at `raw` once the voice's freezes apply; NaN where it shows nothing. */
|
|
415
456
|
shownAt(raw: number): number;
|
|
416
457
|
/** Records this voice's controls as they stand, from mix time `at` in frame `seq`. */
|
|
@@ -426,3 +467,8 @@ export declare class Voice<I, O> {
|
|
|
426
467
|
/** Moves the anchor to `now`, carrying what is left of a ramp. */
|
|
427
468
|
rebase(now: number): void;
|
|
428
469
|
}
|
|
470
|
+
/**
|
|
471
|
+
* Warns, once a patch outside production, of a key the first delta `voice` read returns outside its
|
|
472
|
+
* patch's `writes`, which the mix drops.
|
|
473
|
+
*/
|
|
474
|
+
export declare function checkWrites<I, O>(voice: Voice<I, O>, delta: object | null): void;
|
package/dist/voice.js
CHANGED
|
@@ -6,6 +6,7 @@ import { childPlayed, Holding, mixTime, ownedElapsed, ownerPatch, ownerReading,
|
|
|
6
6
|
import { builtOf, intosOf } from './patch.js';
|
|
7
7
|
import { reading } from './reading.js';
|
|
8
8
|
import { Store } from './store.js';
|
|
9
|
+
import { warnOnce } from './warn.js';
|
|
9
10
|
export const none = Object.freeze([]);
|
|
10
11
|
/**
|
|
11
12
|
* A voice's `setting.keep`, one per voice: a setting is valid only during its call, so the state
|
|
@@ -62,19 +63,26 @@ class VoiceSetting {
|
|
|
62
63
|
/** A store that fills a missing entry from `make` on first ask. */
|
|
63
64
|
class Filled extends Store {
|
|
64
65
|
make;
|
|
66
|
+
/** Keys deleted here, which are made afresh by whoever asks and never again by `make`. */
|
|
67
|
+
gone = null;
|
|
65
68
|
constructor(make) {
|
|
66
69
|
super();
|
|
67
70
|
this.make = make;
|
|
68
71
|
}
|
|
69
72
|
get(key) {
|
|
70
73
|
let v = super.get(key);
|
|
71
|
-
if (v === undefined) {
|
|
74
|
+
if (v === undefined && this.gone?.get(key) !== true) {
|
|
72
75
|
v = this.make(key);
|
|
73
76
|
if (v !== undefined)
|
|
74
77
|
super.set(key, v);
|
|
75
78
|
}
|
|
76
79
|
return v;
|
|
77
80
|
}
|
|
81
|
+
delete(key) {
|
|
82
|
+
super.delete(key);
|
|
83
|
+
this.gone ??= new Store();
|
|
84
|
+
this.gone.set(key, true);
|
|
85
|
+
}
|
|
78
86
|
}
|
|
79
87
|
const noSend = () => { };
|
|
80
88
|
export class Voice {
|
|
@@ -139,7 +147,10 @@ export class Voice {
|
|
|
139
147
|
keeping = false;
|
|
140
148
|
/** Subjects fading out of this voice alone, by the ramp each started; null while none are. */
|
|
141
149
|
parts = null;
|
|
142
|
-
/**
|
|
150
|
+
/**
|
|
151
|
+
* Subjects faded out of this voice, by the mix time and frame each left at, and the ramp that
|
|
152
|
+
* took it out, which a seek or a read back into it puts back; null while none have.
|
|
153
|
+
*/
|
|
143
154
|
parted = null;
|
|
144
155
|
/**
|
|
145
156
|
* Under history, the records of subjects that left this voice, by the mix time and frame each
|
|
@@ -165,6 +176,8 @@ export class Voice {
|
|
|
165
176
|
freezesAfter;
|
|
166
177
|
/** The mix time it first showed: when it was cued, or the first sync after. */
|
|
167
178
|
opened = Number.NaN;
|
|
179
|
+
/** Whether no delta its patch's `at` returned has been checked against `writes` yet. */
|
|
180
|
+
unchecked = true;
|
|
168
181
|
/** Which of its entries in the mix's due queue is current; older ones are skipped when popped. */
|
|
169
182
|
dueToken = 0;
|
|
170
183
|
/**
|
|
@@ -183,6 +196,8 @@ export class Voice {
|
|
|
183
196
|
/** The least stagger of any subject seen, 0 or below, which a voice running back ends at. */
|
|
184
197
|
soonest = 0;
|
|
185
198
|
restedCount = 0;
|
|
199
|
+
/** Whether a seek back to before its cue has it out of the mix, until the mix plays the cue again. */
|
|
200
|
+
parked = false;
|
|
186
201
|
/** The mix time it was cued at; -Infinity before the first sync. */
|
|
187
202
|
cuedAt = Number.NEGATIVE_INFINITY;
|
|
188
203
|
/** The frame it was cued in. */
|
|
@@ -362,6 +377,7 @@ export class Voice {
|
|
|
362
377
|
park() {
|
|
363
378
|
this.reopen(Number.NEGATIVE_INFINITY);
|
|
364
379
|
this.take(this.first);
|
|
380
|
+
this.parked = true;
|
|
365
381
|
this.log = null;
|
|
366
382
|
this.state = 'pending';
|
|
367
383
|
this.subjects = new Store();
|
|
@@ -529,9 +545,20 @@ export class Voice {
|
|
|
529
545
|
get holdsFirst() {
|
|
530
546
|
return this.freezesBefore || this.out?.back === true;
|
|
531
547
|
}
|
|
548
|
+
/**
|
|
549
|
+
* Whether a subject past the end of its passes shows nothing: its clock runs back, so it has yet
|
|
550
|
+
* to reach them, and it does not freeze after.
|
|
551
|
+
*/
|
|
552
|
+
get hidesPast() {
|
|
553
|
+
return !this.freezesAfter && this.backs !== (this.owner !== null && turnedBack(this));
|
|
554
|
+
}
|
|
532
555
|
/** A subject's voice time at `raw` once the voice's freezes apply; NaN where it shows nothing. */
|
|
533
556
|
shownAt(raw) {
|
|
534
|
-
|
|
557
|
+
if (this.beginless)
|
|
558
|
+
return raw;
|
|
559
|
+
if (raw > this.span && this.hidesPast)
|
|
560
|
+
return Number.NaN;
|
|
561
|
+
return frozenTime(raw, this.holdsFirst, this.freezesAfter, this.span);
|
|
535
562
|
}
|
|
536
563
|
/** Records this voice's controls as they stand, from mix time `at` in frame `seq`. */
|
|
537
564
|
note(at, seq, sync = false) {
|
|
@@ -600,3 +627,16 @@ export class Voice {
|
|
|
600
627
|
rebaseWith(this, now);
|
|
601
628
|
}
|
|
602
629
|
}
|
|
630
|
+
/**
|
|
631
|
+
* Warns, once a patch outside production, of a key the first delta `voice` read returns outside its
|
|
632
|
+
* patch's `writes`, which the mix drops.
|
|
633
|
+
*/
|
|
634
|
+
export function checkWrites(voice, delta) {
|
|
635
|
+
voice.unchecked = false;
|
|
636
|
+
if (delta === null || typeof delta !== 'object')
|
|
637
|
+
return;
|
|
638
|
+
const writes = voice.patch.writes;
|
|
639
|
+
for (const key in delta)
|
|
640
|
+
if (!writes.includes(key))
|
|
641
|
+
warnOnce(voice.patch, `${voice.spec.name ?? `voice ${voice.id}`}'s patch returns ${key} from at(), which is not in its writes, so the mix drops it`);
|
|
642
|
+
}
|