@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/lanes.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { lit } from './bound.js';
|
|
2
|
+
import { flush, pullRun, writeLater } from './columns.js';
|
|
2
3
|
import { copy } from './copyout.js';
|
|
3
4
|
import { row } from './crowd.js';
|
|
5
|
+
import { share } from './everyone.js';
|
|
4
6
|
import { call, fillAll, foldKeys, one, parting, readKeyed, reset, run, runEveryone, signalled, subjectAt, } from './fill.js';
|
|
5
7
|
import { fold, foldDelta, foldInto, foldRun, gate, gather, unplain } from './gather.js';
|
|
6
8
|
import { meet, reach } from './meet.js';
|
|
@@ -9,6 +11,7 @@ import { Owed } from './owed.js';
|
|
|
9
11
|
import { Placed } from './placed.js';
|
|
10
12
|
import { requalify, retouch } from './qualify.js';
|
|
11
13
|
import { reading } from './reading.js';
|
|
14
|
+
import { renumber } from './renumber.js';
|
|
12
15
|
import { reportedRow, unplace } from './rows.js';
|
|
13
16
|
import { seatOf } from './seat.js';
|
|
14
17
|
/**
|
|
@@ -18,6 +21,10 @@ import { seatOf } from './seat.js';
|
|
|
18
21
|
// biome-ignore lint/suspicious/noUnsafeDeclarationMerging: every member of `Methods` is installed below
|
|
19
22
|
export class Lanes {
|
|
20
23
|
host;
|
|
24
|
+
/** What the general path calls on a sharing voice, given to a mix by its engine so a lean bundle leaves it out. */
|
|
25
|
+
static share = share;
|
|
26
|
+
/** What `pull` calls on lanes alone. */
|
|
27
|
+
pulls = { pullRun, writeLater, flush, renumber };
|
|
21
28
|
numbers;
|
|
22
29
|
lanes = [];
|
|
23
30
|
/** The lanes over every subject that have started playing, by epoch. */
|
|
@@ -261,7 +268,8 @@ export class Lanes {
|
|
|
261
268
|
}
|
|
262
269
|
reported(lane, slot) {
|
|
263
270
|
const o = slot * 6 /* Per.SLOT */;
|
|
264
|
-
|
|
271
|
+
const probe = this.per[o + 3 /* Per.LANE_PROBE */];
|
|
272
|
+
if (!(probe > this.per[o + 4 /* Per.GENERAL_PROBE */]) || !(probe > lane.made))
|
|
265
273
|
return undefined;
|
|
266
274
|
const p = lane.positionOf(slot);
|
|
267
275
|
if (p < 0)
|
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
|
@@ -86,6 +86,15 @@ export function meet(lanes, slot, subject, head, lane) {
|
|
|
86
86
|
}
|
|
87
87
|
if (!met)
|
|
88
88
|
return lane;
|
|
89
|
+
// Met newest first; folded, as the general path folds them, in voice order.
|
|
90
|
+
const ids = lanes.met;
|
|
91
|
+
for (let i = 1; i < lanes.metN; i++) {
|
|
92
|
+
const id = ids[i];
|
|
93
|
+
let j = i - 1;
|
|
94
|
+
for (; j >= 0 && ids[j] > id; j--)
|
|
95
|
+
ids[j + 1] = ids[j];
|
|
96
|
+
ids[j + 1] = id;
|
|
97
|
+
}
|
|
89
98
|
// The fill ran before the subject had these positions. Where every voice it just met folds
|
|
90
99
|
// after every other laned voice, the general path folds just those onto the lanes' values;
|
|
91
100
|
// otherwise it reads the general path all frame.
|
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';
|
|
@@ -105,6 +106,8 @@ export declare class Mixer<I, O> implements Mix<I, O> {
|
|
|
105
106
|
retired: Voice<I, O>[];
|
|
106
107
|
/** Visit every voice each sync, as before the due queue; for tests that compare the two. */
|
|
107
108
|
walkAll: boolean;
|
|
109
|
+
/** Owners sought forward since the last frame, which passes what each seek went past in order. */
|
|
110
|
+
leapt: Set<Voice<I, O>> | null;
|
|
108
111
|
/** The last array `pull` read, by position, with each subject's chain head, to skip the lookup. */
|
|
109
112
|
pulled: I[];
|
|
110
113
|
pulledHeads: (Subject<unknown> | undefined)[];
|
|
@@ -209,6 +212,8 @@ export declare class Mixer<I, O> implements Mix<I, O> {
|
|
|
209
212
|
roleDepth: number;
|
|
210
213
|
readonly slotOf: Map<string, number>;
|
|
211
214
|
lanes: Lanes<I, O> | null;
|
|
215
|
+
/** The sharing hooks of the lanes this entry was built with, which a projection's copy keeps. */
|
|
216
|
+
share: Share | null;
|
|
212
217
|
handles: HandleHost<I, O> | null;
|
|
213
218
|
/** What `book` made, still booking; null while there is none. */
|
|
214
219
|
bookers: Book<I, O>[] | null;
|
package/dist/mixer.js
CHANGED
|
@@ -95,6 +95,8 @@ export class Mixer {
|
|
|
95
95
|
retired = [];
|
|
96
96
|
/** Visit every voice each sync, as before the due queue; for tests that compare the two. */
|
|
97
97
|
walkAll = false;
|
|
98
|
+
/** Owners sought forward since the last frame, which passes what each seek went past in order. */
|
|
99
|
+
leapt = null;
|
|
98
100
|
/** The last array `pull` read, by position, with each subject's chain head, to skip the lookup. */
|
|
99
101
|
pulled = [];
|
|
100
102
|
pulledHeads = [];
|
|
@@ -235,6 +237,8 @@ export class Mixer {
|
|
|
235
237
|
roleDepth = 0;
|
|
236
238
|
slotOf = new Map();
|
|
237
239
|
lanes;
|
|
240
|
+
/** The sharing hooks of the lanes this entry was built with, which a projection's copy keeps. */
|
|
241
|
+
share;
|
|
238
242
|
handles = null;
|
|
239
243
|
/** What `book` made, still booking; null while there is none. */
|
|
240
244
|
bookers = null;
|
|
@@ -266,6 +270,7 @@ export class Mixer {
|
|
|
266
270
|
});
|
|
267
271
|
if (lanesOf === null && opts.lanes === true)
|
|
268
272
|
throw new Error("blits: '@msb235/blits/lean' has no lanes; take mix from '@msb235/blits'");
|
|
273
|
+
this.share = lanesOf?.share ?? null;
|
|
269
274
|
this.lanes =
|
|
270
275
|
lanesOf !== null && (opts.lanes ?? defaults.lanes) ? new lanesOf(laneHost(this)) : null;
|
|
271
276
|
this.name = opts.name;
|
package/dist/motion.js
CHANGED
|
@@ -241,8 +241,8 @@ export function spring(writes, opts) {
|
|
|
241
241
|
const k = opts.stiffness ?? 170;
|
|
242
242
|
const c = opts.damping ?? 26;
|
|
243
243
|
const m = opts.mass ?? 1;
|
|
244
|
-
if (!(k > 0) || !(m > 0) || !(c >= 0))
|
|
245
|
-
throw new RangeError('blits: a spring takes a positive stiffness and mass, and damping of 0 or more');
|
|
244
|
+
if (!(k > 0 && k < Infinity) || !(m > 0 && m < Infinity) || !(c >= 0 && c < Infinity))
|
|
245
|
+
throw new RangeError('blits: a spring takes a finite positive stiffness and mass, and finite damping of 0 or more');
|
|
246
246
|
const settle = opts.settle ?? 1e-4;
|
|
247
247
|
const w0 = Math.sqrt(k / m);
|
|
248
248
|
const zeta = c / (2 * Math.sqrt(k * m));
|
|
@@ -273,11 +273,11 @@ export function spring(writes, opts) {
|
|
|
273
273
|
*/
|
|
274
274
|
export function glide(writes, opts) {
|
|
275
275
|
const ms = opts.ms ?? 325;
|
|
276
|
-
if (!(ms > 0))
|
|
277
|
-
throw new RangeError('blits: a glide takes a positive ms');
|
|
276
|
+
if (!(ms > 0 && ms < Infinity))
|
|
277
|
+
throw new RangeError('blits: a glide takes a finite positive ms');
|
|
278
278
|
const k = opts.stiffness ?? 170;
|
|
279
|
-
if (!(k > 0))
|
|
280
|
-
throw new RangeError('blits: a glide takes a positive stiffness');
|
|
279
|
+
if (!(k > 0 && k < Infinity))
|
|
280
|
+
throw new RangeError('blits: a glide takes a finite positive stiffness');
|
|
281
281
|
const tau = ms / 1000;
|
|
282
282
|
const settle = opts.settle ?? 1e-4;
|
|
283
283
|
const bounded = opts.bounds !== undefined;
|
package/dist/motions.d.ts
CHANGED
|
@@ -64,11 +64,14 @@ export declare class Motions<I> {
|
|
|
64
64
|
/** Whether the channel it was cued on holds a number; undefined until it is cued. */
|
|
65
65
|
private holdsNumber;
|
|
66
66
|
private channel;
|
|
67
|
+
/** Whether the channel it was cued on travels round the hue, as `ink` does, and its stretches too. */
|
|
68
|
+
round: boolean;
|
|
67
69
|
/**
|
|
68
70
|
* Records what the channel the patch is cued on holds, refusing a value of the other kind: at once
|
|
69
71
|
* where every subject's value is one kind, else on the first sample of a subject whose value is not.
|
|
72
|
+
* `round` for a channel that travels round the hue, as `ink` does.
|
|
70
73
|
*/
|
|
71
|
-
cuedOn(channel: string, holdsNumber: boolean): void;
|
|
74
|
+
cuedOn(channel: string, holdsNumber: boolean, round?: boolean): void;
|
|
72
75
|
frame(subject: I): number;
|
|
73
76
|
constructor(shape: Shape<I>);
|
|
74
77
|
/** The patch's number for `subject`, made with its first stretch on first ask. */
|
package/dist/motions.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { applied, change, commit, cut, dueTo, insert, peek, queue, rewind } from './changes.js';
|
|
2
|
-
import { closed } from './closed.js';
|
|
2
|
+
import { BOUND, closed } from './closed.js';
|
|
3
|
+
import { closedLch } from './lch.js';
|
|
3
4
|
import { made, pack, prune, reclaim, release, restretch, runAt, runThen, unpack, unrelease, } from './lives.js';
|
|
4
5
|
import { absent, Numbers } from './numbers.js';
|
|
5
6
|
import { reading } from './reading.js';
|
|
@@ -16,6 +17,7 @@ const PENDING = 2 /* RunFlag.PENDING */;
|
|
|
16
17
|
const OLDER = 4 /* RunFlag.OLDER */;
|
|
17
18
|
const LANDED = 8 /* RunFlag.LANDED */;
|
|
18
19
|
const wrongKind = (channel, holdsNumber) => new Error(`blits: channel ${channel} holds ${holdsNumber ? 'a number' : 'an array'}, and this motion patch gives a subject ${holdsNumber ? 'an array' : 'a number'}`);
|
|
20
|
+
const notOklab = (channel) => new Error(`blits: channel ${channel} goes round the hue, and a motion on it moves oklab() values, four numbers each`);
|
|
19
21
|
/**
|
|
20
22
|
* A motion patch's subjects: the stretch each is playing, in one flat array by a number the patch
|
|
21
23
|
* gives it, with earlier stretches a read back may reach and changes not yet applied beside them.
|
|
@@ -68,11 +70,18 @@ export class Motions {
|
|
|
68
70
|
/** Whether the channel it was cued on holds a number; undefined until it is cued. */
|
|
69
71
|
holdsNumber = undefined;
|
|
70
72
|
channel = '';
|
|
73
|
+
/** Whether the channel it was cued on travels round the hue, as `ink` does, and its stretches too. */
|
|
74
|
+
round = false;
|
|
71
75
|
/**
|
|
72
76
|
* Records what the channel the patch is cued on holds, refusing a value of the other kind: at once
|
|
73
77
|
* where every subject's value is one kind, else on the first sample of a subject whose value is not.
|
|
78
|
+
* `round` for a channel that travels round the hue, as `ink` does.
|
|
74
79
|
*/
|
|
75
|
-
cuedOn(channel, holdsNumber) {
|
|
80
|
+
cuedOn(channel, holdsNumber, round = false) {
|
|
81
|
+
if (round && this.shape.law[0] === BOUND)
|
|
82
|
+
throw new Error(`blits: channel ${channel} goes round the hue, and a glide's bounds are a box on its OKLab axes; glide it without bounds`);
|
|
83
|
+
if (round && this.n >= 0 && this.n !== 4)
|
|
84
|
+
throw notOklab(channel);
|
|
76
85
|
const every = this.shape.scalarEvery();
|
|
77
86
|
if (every !== undefined && every !== holdsNumber)
|
|
78
87
|
throw wrongKind(channel, holdsNumber);
|
|
@@ -82,6 +91,7 @@ export class Motions {
|
|
|
82
91
|
throw wrongKind(channel, holdsNumber);
|
|
83
92
|
this.holdsNumber = holdsNumber;
|
|
84
93
|
this.channel = channel;
|
|
94
|
+
this.round = round;
|
|
85
95
|
}
|
|
86
96
|
frame(subject) {
|
|
87
97
|
return this.owner === null ? Number.NaN : this.owner.frame(this.ownerId, subject);
|
|
@@ -127,6 +137,8 @@ export class Motions {
|
|
|
127
137
|
}
|
|
128
138
|
/** Sets the axes every subject moves on, at the first. */
|
|
129
139
|
size(n) {
|
|
140
|
+
if (this.round && n !== 4)
|
|
141
|
+
throw notOklab(this.channel);
|
|
130
142
|
this.n = n;
|
|
131
143
|
this.stride = 3 + 3 * n;
|
|
132
144
|
if (shared.xs.length < n)
|
|
@@ -426,6 +438,8 @@ export class Motions {
|
|
|
426
438
|
this.evaluate(seg.at, seg.ms, seg.x0, 0, seg.v0, 0, seg.to, 0, t, xo, vo);
|
|
427
439
|
}
|
|
428
440
|
evaluate(at, ms, x0, x, v0, v, to, g, t, xo, vo) {
|
|
441
|
+
if (this.round)
|
|
442
|
+
return closedLch(this.runs, this.shape.ease, at, ms, x0, x, v0, v, to, g, t, xo, vo);
|
|
429
443
|
return closed(this.runs, this.shape.ease, this.n, at, ms, x0, x, v0, v, to, g, t, xo, vo);
|
|
430
444
|
}
|
|
431
445
|
}
|