@roobscoob/vibes 0.1.0 → 0.2.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/README.md +29 -7
- package/dist/color.d.ts +3 -0
- package/dist/color.d.ts.map +1 -1
- package/dist/color.js +2 -1
- package/dist/here.d.ts +2 -0
- package/dist/here.d.ts.map +1 -1
- package/dist/here.js +2 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/sketch.d.ts +22 -14
- package/dist/sketch.d.ts.map +1 -1
- package/dist/sketch.js +81 -29
- package/package.json +1 -1
- package/src/color.ts +7 -3
- package/src/here.ts +2 -0
- package/src/index.ts +1 -1
- package/src/sketch.ts +102 -46
package/README.md
CHANGED
|
@@ -32,19 +32,41 @@ A sketch says what each light should make, a hundred times a second.
|
|
|
32
32
|
| `at({ x, y, t })` | the same light, looking from somewhere else or at another time |
|
|
33
33
|
|
|
34
34
|
Return a color (anything that says one: see below), or `null` to leave the
|
|
35
|
-
light as the layers below have it. `sketch("#f80")` makes every light
|
|
36
|
-
color; `sketch(palettes.dusk)` lays a palette across the room.
|
|
35
|
+
light as the layers below have it. `sketch("#f80")` makes every color light
|
|
36
|
+
one color; `sketch(palettes.dusk)` lays a palette across the room.
|
|
37
37
|
|
|
38
38
|
- `light.rail` is `{ id, along, t, index, count }`: how far along its rail
|
|
39
39
|
(meters, and 0 to 1), its place on it, and how many share it.
|
|
40
40
|
- `light.random` is a number from 0 to 1 of its own, the same every time.
|
|
41
|
-
- `light.below` is what the layers below this sketch make it, as a color
|
|
41
|
+
- `light.below` is what the layers below this sketch make it, as a color, and
|
|
42
|
+
`light.belowOn` whether that's on at all.
|
|
42
43
|
- `light.state` is the light's own memory, kept from tick to tick.
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
Something that isn't a color leaves its light as it is, with a warning in
|
|
46
|
+
the console, so one slip doesn't stop the sketch.
|
|
47
|
+
|
|
48
|
+
## Old bulbs
|
|
49
|
+
|
|
50
|
+
The old bulbs only switch, and look nothing like the color lights, so they
|
|
51
|
+
have a look of their own, apart from color's. Each look is named for the
|
|
52
|
+
kind of light it's for, as `light.kind` names them:
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
export const update = sketch({
|
|
56
|
+
color: osc(3).color(palettes.dusk), // the color bulbs and panels
|
|
57
|
+
switch: osc(1, 0.25).thresh(), // the old bulbs: on or off
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
`sketch(look)` is `sketch({ color: look })`: a color look is never asked
|
|
62
|
+
about old bulbs, and never switches them. Without a `switch` look they're
|
|
63
|
+
left as they are; `sketch(look, { switch })` gives one beside a color look.
|
|
64
|
+
|
|
65
|
+
A `switch` look gives `true` or `false`, a number (on at 0.5 or more, as
|
|
66
|
+
arclamp's own `on` channel: a field from 0 to 1 works, like
|
|
67
|
+
`noise(4).thresh(0.6)` or `clock(96).every(1).env()`), `"on"` or `"off"`, or
|
|
68
|
+
`null` to leave the bulb as it is. It can be a function of `here`, a field,
|
|
69
|
+
or one answer for every old bulb: `sketch({ switch: true })`.
|
|
48
70
|
|
|
49
71
|
## Colors
|
|
50
72
|
|
package/dist/color.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type Vec3 } from "./lemtone.ts";
|
|
2
|
+
import type { Here } from "./here.ts";
|
|
2
3
|
/** Anything that says a color: see the top of color.ts. */
|
|
3
4
|
export type ColorInput = Color | string | number | readonly number[] | {
|
|
4
5
|
readonly [key: string]: unknown;
|
|
@@ -151,6 +152,8 @@ export declare function xy(x: number, y: number, lm?: number): Color;
|
|
|
151
152
|
/** Colors along a line from 0 to 1: palette(x) is the color at x. */
|
|
152
153
|
export interface Palette {
|
|
153
154
|
(x: number): Color;
|
|
155
|
+
/** Given a here instead, the palette laid across the room, left to right: its color at here.u. */
|
|
156
|
+
(here: Here): Color;
|
|
154
157
|
readonly stops: readonly Color[];
|
|
155
158
|
/** Where each stop is, 0 to 1. */
|
|
156
159
|
readonly positions: readonly number[];
|
package/dist/color.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"color.d.ts","sourceRoot":"","sources":["../src/color.ts"],"names":[],"mappings":"AAiBA,OAAO,EAWL,KAAK,IAAI,EACV,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"color.d.ts","sourceRoot":"","sources":["../src/color.ts"],"names":[],"mappings":"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"}
|
package/dist/color.js
CHANGED
|
@@ -433,7 +433,8 @@ export function palette(...given) {
|
|
|
433
433
|
const stops = Object.freeze(placed.map((p) => Object.freeze(p.c)));
|
|
434
434
|
const positions = Object.freeze(placed.map((p) => p.at));
|
|
435
435
|
const at = (x) => {
|
|
436
|
-
const
|
|
436
|
+
const along = typeof x === "number" ? x : x?.u;
|
|
437
|
+
const v = typeof along === "number" && Number.isFinite(along) ? along : 0;
|
|
437
438
|
if (v <= positions[0])
|
|
438
439
|
return stops[0];
|
|
439
440
|
for (let i = 1; i < stops.length; i++) {
|
package/dist/here.d.ts
CHANGED
|
@@ -38,6 +38,8 @@ export declare class Light {
|
|
|
38
38
|
readonly random: number;
|
|
39
39
|
/** What the layers below this sketch are making it do. */
|
|
40
40
|
below: Color;
|
|
41
|
+
/** Whether the layers below have it on (for an old bulb), or lit at all (for a color light). */
|
|
42
|
+
belowOn: boolean;
|
|
41
43
|
/** Its own memory, kept from one tick to the next. */
|
|
42
44
|
state: Record<string, any>;
|
|
43
45
|
constructor(p: PrevLight, x: number, y: number);
|
package/dist/here.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"here.d.ts","sourceRoot":"","sources":["../src/here.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"here.d.ts","sourceRoot":"","sources":["../src/here.ts"],"names":[],"mappings":"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"}
|
package/dist/here.js
CHANGED
|
@@ -30,6 +30,8 @@ export class Light {
|
|
|
30
30
|
random;
|
|
31
31
|
/** What the layers below this sketch are making it do. */
|
|
32
32
|
below = off;
|
|
33
|
+
/** Whether the layers below have it on (for an old bulb), or lit at all (for a color light). */
|
|
34
|
+
belowOn = false;
|
|
33
35
|
/** Its own memory, kept from one tick to the next. */
|
|
34
36
|
state = {};
|
|
35
37
|
constructor(p, x, y) {
|
package/dist/index.d.ts
CHANGED
|
@@ -4,5 +4,5 @@ export { Here, Light, Room, type Rail, type RailSpot } from "./here.ts";
|
|
|
4
4
|
export { delay, field, gradient, isField, kaleid, move, noise, osc, rings, rotate, scale, solid, speed, voronoi, warp, type ColorParam, type Field, type Param, } from "./field.ts";
|
|
5
5
|
export { clock, type Clock, type Every } from "./signal.ts";
|
|
6
6
|
export { chance, clamp, decay, ease, fract, hash, lerp, noiseAt, remap, saw, smoothstep, square, tri, wave } from "./shape.ts";
|
|
7
|
-
export { sketch, type Look, type LookResult, type SketchOptions } from "./sketch.ts";
|
|
7
|
+
export { sketch, type Look, type LookResult, type Looks, type SketchOptions, type SwitchLook, type SwitchResult } from "./sketch.ts";
|
|
8
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,YAAY,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,EACL,IAAI,EACJ,KAAK,EACL,KAAK,EACL,GAAG,EACH,GAAG,EACH,SAAS,EACT,OAAO,EACP,GAAG,EACH,KAAK,EACL,KAAK,EACL,OAAO,EACP,QAAQ,EACR,GAAG,EACH,SAAS,EACT,KAAK,EACL,EAAE,EACF,KAAK,IAAI,EACT,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,OAAO,EACZ,KAAK,IAAI,GACV,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AACxE,OAAO,EACL,KAAK,EACL,KAAK,EACL,QAAQ,EACR,OAAO,EACP,MAAM,EACN,IAAI,EACJ,KAAK,EACL,GAAG,EACH,KAAK,EACL,MAAM,EACN,KAAK,EACL,KAAK,EACL,KAAK,EACL,OAAO,EACP,IAAI,EACJ,KAAK,UAAU,EACf,KAAK,KAAK,EACV,KAAK,KAAK,GACX,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,KAAK,EAAE,KAAK,KAAK,EAAE,KAAK,KAAK,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAC/H,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,EAAE,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,YAAY,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,EACL,IAAI,EACJ,KAAK,EACL,KAAK,EACL,GAAG,EACH,GAAG,EACH,SAAS,EACT,OAAO,EACP,GAAG,EACH,KAAK,EACL,KAAK,EACL,OAAO,EACP,QAAQ,EACR,GAAG,EACH,SAAS,EACT,KAAK,EACL,EAAE,EACF,KAAK,IAAI,EACT,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,OAAO,EACZ,KAAK,IAAI,GACV,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AACxE,OAAO,EACL,KAAK,EACL,KAAK,EACL,QAAQ,EACR,OAAO,EACP,MAAM,EACN,IAAI,EACJ,KAAK,EACL,GAAG,EACH,KAAK,EACL,MAAM,EACN,KAAK,EACL,KAAK,EACL,KAAK,EACL,OAAO,EACP,IAAI,EACJ,KAAK,UAAU,EACf,KAAK,KAAK,EACV,KAAK,KAAK,GACX,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,KAAK,EAAE,KAAK,KAAK,EAAE,KAAK,KAAK,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAC/H,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,EAAE,KAAK,UAAU,EAAE,KAAK,KAAK,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/sketch.d.ts
CHANGED
|
@@ -1,21 +1,29 @@
|
|
|
1
|
-
import { type ColorInput
|
|
1
|
+
import { type ColorInput } from "./color.ts";
|
|
2
2
|
import type { Update } from "./arclamp.ts";
|
|
3
3
|
import { Here } from "./here.ts";
|
|
4
|
-
/** What a light should make, here and now; null, undefined or false leaves it as it is below. */
|
|
4
|
+
/** What a color light should make, here and now; null, undefined or false leaves it as it is below. */
|
|
5
5
|
export type LookResult = ColorInput | null | undefined | false | void;
|
|
6
|
-
/**
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
/** The color lights' look: a function of here giving a color, one color for every light, or a palette, laid across the room. */
|
|
7
|
+
export type Look = ((here: Here) => LookResult) | ColorInput;
|
|
8
|
+
/** Whether an old bulb should be on: true or false, a number (on at 0.5 or more), "on" or "off"; null or undefined leaves it as it is. */
|
|
9
|
+
export type SwitchResult = boolean | number | string | null | undefined | void;
|
|
10
|
+
/** The old bulbs' look: a function of here (a field too) saying whether each is on, or one answer for them all. */
|
|
11
|
+
export type SwitchLook = ((here: Here) => SwitchResult) | boolean | number | string;
|
|
12
|
+
/** A look for each kind of light (light.kind); either may be left out, and its lights are left as they are. */
|
|
13
|
+
export interface Looks {
|
|
14
|
+
/** For the color bulbs and panels. */
|
|
15
|
+
color?: Look;
|
|
16
|
+
/** For the old bulbs, which only switch. */
|
|
17
|
+
switch?: SwitchLook;
|
|
18
|
+
}
|
|
11
19
|
export interface SketchOptions {
|
|
12
|
-
/**
|
|
13
|
-
|
|
14
|
-
/** And off when asked for fewer than this (default 70). */
|
|
15
|
-
switchOff?: number;
|
|
20
|
+
/** The old bulbs' look, beside a color look given on its own. */
|
|
21
|
+
switch?: SwitchLook;
|
|
16
22
|
}
|
|
17
|
-
/** Your look (a function of here, or a field) as arclamp's update()
|
|
23
|
+
/** Your color look (a function of here, or a field) as arclamp's update(); old bulbs are left alone, unless given `switch`. */
|
|
18
24
|
export declare function sketch(look: (here: Here) => LookResult, options?: SketchOptions): Update;
|
|
19
|
-
/**
|
|
20
|
-
export declare function sketch(
|
|
25
|
+
/** A look for each kind of light: { color, switch }. */
|
|
26
|
+
export declare function sketch(looks: Looks): Update;
|
|
27
|
+
/** One color for every color light, or a palette laid across the room, as arclamp's update(). */
|
|
28
|
+
export declare function sketch(look: ColorInput, options?: SketchOptions): Update;
|
|
21
29
|
//# sourceMappingURL=sketch.d.ts.map
|
package/dist/sketch.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sketch.d.ts","sourceRoot":"","sources":["../src/sketch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sketch.d.ts","sourceRoot":"","sources":["../src/sketch.ts"],"names":[],"mappings":"AAuBA,OAAO,EAA2B,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,KAAK,EAAa,MAAM,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAW,IAAI,EAAiC,MAAM,WAAW,CAAC;AAKzE,uGAAuG;AACvG,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK,GAAG,IAAI,CAAC;AAEtE,gIAAgI;AAChI,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,IAAI,KAAK,UAAU,CAAC,GAAG,UAAU,CAAC;AAE7D,0IAA0I;AAC1I,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,CAAC;AAE/E,mHAAmH;AACnH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,IAAI,EAAE,IAAI,KAAK,YAAY,CAAC,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAEpF,+GAA+G;AAC/G,MAAM,WAAW,KAAK;IACpB,sCAAsC;IACtC,KAAK,CAAC,EAAE,IAAI,CAAC;IACb,4CAA4C;IAC5C,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,iEAAiE;IACjE,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAKD,+HAA+H;AAC/H,wBAAgB,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,UAAU,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC;AAC1F,wDAAwD;AACxD,wBAAgB,MAAM,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC;AAC7C,iGAAiG;AACjG,wBAAgB,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC"}
|
package/dist/sketch.js
CHANGED
|
@@ -1,28 +1,37 @@
|
|
|
1
|
-
// sketch(): your
|
|
1
|
+
// sketch(): your looks as arclamp's update().
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
// sketch() asks it what every light should make now, and turns that into
|
|
6
|
-
// channels: lemtone channels for color lights, and on or off for old bulbs
|
|
7
|
-
// (on at `switchOn` lumens or more, off below `switchOff`, and left as they
|
|
8
|
-
// were between, so a pattern hovering near the line doesn't chatter).
|
|
3
|
+
// Color lights and old bulbs are controlled apart, each by a look of its own,
|
|
4
|
+
// named for the kind of light it's for (light.kind):
|
|
9
5
|
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
6
|
+
// sketch({ color: osc(3).color(palettes.dusk), switch: osc(1, 0.25).thresh() })
|
|
7
|
+
//
|
|
8
|
+
// The color look is asked about the color bulbs and panels only: a function
|
|
9
|
+
// of here (your own, or a field) giving a color, one color for every light,
|
|
10
|
+
// or a palette laid across the room. Anything that says a color will do (a
|
|
11
|
+
// Color, "#f80", "2700K", { r, g, b }, …). sketch(look) is
|
|
12
|
+
// sketch({ color: look }).
|
|
13
|
+
//
|
|
14
|
+
// The switch look is asked about the old bulbs only, which just switch: true or
|
|
15
|
+
// false, a number (on at 0.5 or more, as arclamp's own `on` channel), "on" or
|
|
16
|
+
// "off", or a function of here (a field too) giving one. Without one, the old
|
|
17
|
+
// bulbs are left as they are; a color never switches them.
|
|
18
|
+
//
|
|
19
|
+
// Null or undefined from either leaves the light as it is below (so does
|
|
20
|
+
// false from a color look). Something that can't be read leaves it as it is
|
|
21
|
+
// too, with a warning (once for each kind of mistake), so one slip doesn't
|
|
22
|
+
// stop the sketch.
|
|
15
23
|
import { Color, color, isPalette } from "./color.js";
|
|
16
24
|
import { colorOf, Here, roomOf, sameLayout } from "./here.js";
|
|
17
25
|
// A tick after a long gap (the sketch paused, or held up) counts as at most this long.
|
|
18
26
|
const MAX_DT = 0.25;
|
|
19
|
-
export function sketch(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const
|
|
27
|
+
export function sketch(given, options = {}) {
|
|
28
|
+
if (options && typeof options === "object" && "on" in options)
|
|
29
|
+
throw new Error(ON_KEY);
|
|
30
|
+
const looks = isLooks(given) ? { switch: options.switch, ...given } : { color: given, switch: options.switch };
|
|
31
|
+
const askColor = looks.color === undefined ? null : lookOf(looks.color);
|
|
32
|
+
const askSwitch = looks.switch === undefined ? null : switchLookOf(looks.switch);
|
|
23
33
|
let room = null;
|
|
24
34
|
let last = null;
|
|
25
|
-
const on = new Map();
|
|
26
35
|
const warned = new Set();
|
|
27
36
|
const warn = (kind, text) => {
|
|
28
37
|
if (warned.has(kind))
|
|
@@ -41,7 +50,20 @@ export function sketch(look, options = {}) {
|
|
|
41
50
|
for (let i = 0; i < list.length; i++) {
|
|
42
51
|
const light = room.lights[i];
|
|
43
52
|
light.below = colorOf(list[i], light.kind);
|
|
53
|
+
light.belowOn = light.below.lm > 0;
|
|
54
|
+
const ask = light.kind === "switch" ? askSwitch : askColor;
|
|
55
|
+
if (!ask)
|
|
56
|
+
continue;
|
|
44
57
|
const v = ask(new Here(light.x, light.y, t, dt, nowMs, light, room));
|
|
58
|
+
if (light.kind === "switch") {
|
|
59
|
+
const on = readOn(v);
|
|
60
|
+
if (on === "unreadable") {
|
|
61
|
+
warn("on", `light ${light.id} is an old bulb, which only switches: its look gives true or false, a number (on at 0.5 or more), or "on" or "off", not ${describe(v)}; give old bulbs a look of their own, sketch({ color, switch })`);
|
|
62
|
+
}
|
|
63
|
+
else if (on !== null)
|
|
64
|
+
lights.push({ id: light.id, channels: { on: on ? 1 : 0 } });
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
45
67
|
if (v === null || v === undefined || v === false)
|
|
46
68
|
continue;
|
|
47
69
|
let c;
|
|
@@ -57,17 +79,6 @@ export function sketch(look, options = {}) {
|
|
|
57
79
|
}
|
|
58
80
|
continue;
|
|
59
81
|
}
|
|
60
|
-
if (light.kind === "switch") {
|
|
61
|
-
if (!Number.isFinite(c.lm)) {
|
|
62
|
-
warn("nan", `light ${light.id} was given a color that isn't all numbers, ${JSON.stringify(c)}, so it's left as it is`);
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
const was = on.get(light.id) ?? c.lm >= switchOn;
|
|
66
|
-
const now = c.lm >= switchOn ? true : c.lm < switchOff ? false : was;
|
|
67
|
-
on.set(light.id, now);
|
|
68
|
-
lights.push({ id: light.id, channels: { on: now ? 1 : 0 } });
|
|
69
|
-
continue;
|
|
70
|
-
}
|
|
71
82
|
const channels = c.channels;
|
|
72
83
|
if (!Number.isFinite(channels.a) || !Number.isFinite(channels.b) || !Number.isFinite(channels.brightness) || !Number.isFinite(channels.fidelity)) {
|
|
73
84
|
warn("nan", `light ${light.id} was given a color that isn't all numbers, ${JSON.stringify(c)}, so it's left as it is`);
|
|
@@ -78,7 +89,18 @@ export function sketch(look, options = {}) {
|
|
|
78
89
|
return { lights };
|
|
79
90
|
};
|
|
80
91
|
}
|
|
81
|
-
|
|
92
|
+
const ON_KEY = 'old bulbs\' look is `switch`, for the kind of light it\'s for: sketch({ color, switch }), or sketch(look, { switch })';
|
|
93
|
+
/** Whether a sketch was given a look for each kind of light ({ color, switch }) rather than one look. */
|
|
94
|
+
function isLooks(v) {
|
|
95
|
+
if (!v || typeof v !== "object" || v instanceof Color || Array.isArray(v))
|
|
96
|
+
return false;
|
|
97
|
+
const keys = Object.keys(v);
|
|
98
|
+
// { on } would read as an old bulb's channels, a color: say what's meant instead.
|
|
99
|
+
if (keys.includes("on"))
|
|
100
|
+
throw new Error(ON_KEY);
|
|
101
|
+
return keys.length > 0 && keys.every((k) => k === "color" || k === "switch");
|
|
102
|
+
}
|
|
103
|
+
/** The color look as a function of here. One color is the same everywhere (and said wrong, an error now, not each tick). */
|
|
82
104
|
function lookOf(look) {
|
|
83
105
|
if (isPalette(look))
|
|
84
106
|
return (here) => look(here.u);
|
|
@@ -87,3 +109,33 @@ function lookOf(look) {
|
|
|
87
109
|
const c = color(look);
|
|
88
110
|
return () => c;
|
|
89
111
|
}
|
|
112
|
+
/** The switch look as a function of here. One answer is the same everywhere (and said wrong, an error now). */
|
|
113
|
+
function switchLookOf(look) {
|
|
114
|
+
if (typeof look === "function")
|
|
115
|
+
return look;
|
|
116
|
+
const on = readOn(look);
|
|
117
|
+
if (on === "unreadable")
|
|
118
|
+
throw new Error(`${describe(look)} isn't on or off: give true or false, a number (on at 0.5 or more), or "on" or "off"`);
|
|
119
|
+
return () => on;
|
|
120
|
+
}
|
|
121
|
+
/** On (true), off (false), leave it (null), or can't tell. */
|
|
122
|
+
function readOn(v) {
|
|
123
|
+
if (v === null || v === undefined)
|
|
124
|
+
return null;
|
|
125
|
+
if (typeof v === "boolean")
|
|
126
|
+
return v;
|
|
127
|
+
if (typeof v === "number")
|
|
128
|
+
return Number.isFinite(v) ? v >= 0.5 : "unreadable";
|
|
129
|
+
if (typeof v === "string") {
|
|
130
|
+
const s = v.trim().toLowerCase();
|
|
131
|
+
if (s === "on" || s === "true" || s === "yes")
|
|
132
|
+
return true;
|
|
133
|
+
if (s === "off" || s === "false" || s === "no")
|
|
134
|
+
return false;
|
|
135
|
+
return s !== "" && Number.isFinite(Number(s)) ? Number(s) >= 0.5 : "unreadable";
|
|
136
|
+
}
|
|
137
|
+
if (typeof v === "object" && !(v instanceof Color) && "on" in v)
|
|
138
|
+
return readOn(v.on);
|
|
139
|
+
return "unreadable";
|
|
140
|
+
}
|
|
141
|
+
const describe = (v) => (v instanceof Color ? `a color (${v})` : typeof v === "string" ? `"${v}"` : JSON.stringify(v) ?? String(v));
|
package/package.json
CHANGED
package/src/color.ts
CHANGED
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
xyzToOklab,
|
|
29
29
|
type Vec3,
|
|
30
30
|
} from "./lemtone.ts";
|
|
31
|
+
import type { Here } from "./here.ts";
|
|
31
32
|
import { parseColor, type Spec } from "./parse.ts";
|
|
32
33
|
import { clamp, lerp } from "./shape.ts";
|
|
33
34
|
import {
|
|
@@ -484,6 +485,8 @@ function fromObject(o: Record<string, unknown>): Color {
|
|
|
484
485
|
/** Colors along a line from 0 to 1: palette(x) is the color at x. */
|
|
485
486
|
export interface Palette {
|
|
486
487
|
(x: number): Color;
|
|
488
|
+
/** Given a here instead, the palette laid across the room, left to right: its color at here.u. */
|
|
489
|
+
(here: Here): Color;
|
|
487
490
|
readonly stops: readonly Color[];
|
|
488
491
|
/** Where each stop is, 0 to 1. */
|
|
489
492
|
readonly positions: readonly number[];
|
|
@@ -512,8 +515,9 @@ export function palette(...given: Stop[] | [readonly Stop[]]): Palette {
|
|
|
512
515
|
.sort((x, y) => x.at - y.at);
|
|
513
516
|
const stops = Object.freeze(placed.map((p) => Object.freeze(p.c)));
|
|
514
517
|
const positions = Object.freeze(placed.map((p) => p.at));
|
|
515
|
-
const at = (x: number): Color => {
|
|
516
|
-
const
|
|
518
|
+
const at = (x: number | Here): Color => {
|
|
519
|
+
const along = typeof x === "number" ? x : (x as Partial<Here> | null)?.u;
|
|
520
|
+
const v = typeof along === "number" && Number.isFinite(along) ? along : 0;
|
|
517
521
|
if (v <= positions[0]!) return stops[0]!;
|
|
518
522
|
for (let i = 1; i < stops.length; i++) {
|
|
519
523
|
if (v <= positions[i]!) {
|
|
@@ -523,7 +527,7 @@ export function palette(...given: Stop[] | [readonly Stop[]]): Palette {
|
|
|
523
527
|
}
|
|
524
528
|
return stops[stops.length - 1]!;
|
|
525
529
|
};
|
|
526
|
-
return Object.assign(at, { stops, positions });
|
|
530
|
+
return Object.assign(at, { stops, positions }) as Palette;
|
|
527
531
|
}
|
|
528
532
|
|
|
529
533
|
/** A palette from anything that says one: a palette, a list of stops, or one color (from dark at 0 to it at 1). */
|
package/src/here.ts
CHANGED
|
@@ -55,6 +55,8 @@ export class Light {
|
|
|
55
55
|
readonly random: number;
|
|
56
56
|
/** What the layers below this sketch are making it do. */
|
|
57
57
|
below: Color = off;
|
|
58
|
+
/** Whether the layers below have it on (for an old bulb), or lit at all (for a color light). */
|
|
59
|
+
belowOn = false;
|
|
58
60
|
/** Its own memory, kept from one tick to the next. */
|
|
59
61
|
state: Record<string, any> = {};
|
|
60
62
|
|
package/src/index.ts
CHANGED
|
@@ -49,4 +49,4 @@ export {
|
|
|
49
49
|
} from "./field.ts";
|
|
50
50
|
export { clock, type Clock, type Every } from "./signal.ts";
|
|
51
51
|
export { chance, clamp, decay, ease, fract, hash, lerp, noiseAt, remap, saw, smoothstep, square, tri, wave } from "./shape.ts";
|
|
52
|
-
export { sketch, type Look, type LookResult, type SketchOptions } from "./sketch.ts";
|
|
52
|
+
export { sketch, type Look, type LookResult, type Looks, type SketchOptions, type SwitchLook, type SwitchResult } from "./sketch.ts";
|
package/src/sketch.ts
CHANGED
|
@@ -1,55 +1,74 @@
|
|
|
1
|
-
// sketch(): your
|
|
1
|
+
// sketch(): your looks as arclamp's update().
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
// sketch() asks it what every light should make now, and turns that into
|
|
6
|
-
// channels: lemtone channels for color lights, and on or off for old bulbs
|
|
7
|
-
// (on at `switchOn` lumens or more, off below `switchOff`, and left as they
|
|
8
|
-
// were between, so a pattern hovering near the line doesn't chatter).
|
|
3
|
+
// Color lights and old bulbs are controlled apart, each by a look of its own,
|
|
4
|
+
// named for the kind of light it's for (light.kind):
|
|
9
5
|
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
6
|
+
// sketch({ color: osc(3).color(palettes.dusk), switch: osc(1, 0.25).thresh() })
|
|
7
|
+
//
|
|
8
|
+
// The color look is asked about the color bulbs and panels only: a function
|
|
9
|
+
// of here (your own, or a field) giving a color, one color for every light,
|
|
10
|
+
// or a palette laid across the room. Anything that says a color will do (a
|
|
11
|
+
// Color, "#f80", "2700K", { r, g, b }, …). sketch(look) is
|
|
12
|
+
// sketch({ color: look }).
|
|
13
|
+
//
|
|
14
|
+
// The switch look is asked about the old bulbs only, which just switch: true or
|
|
15
|
+
// false, a number (on at 0.5 or more, as arclamp's own `on` channel), "on" or
|
|
16
|
+
// "off", or a function of here (a field too) giving one. Without one, the old
|
|
17
|
+
// bulbs are left as they are; a color never switches them.
|
|
18
|
+
//
|
|
19
|
+
// Null or undefined from either leaves the light as it is below (so does
|
|
20
|
+
// false from a color look). Something that can't be read leaves it as it is
|
|
21
|
+
// too, with a warning (once for each kind of mistake), so one slip doesn't
|
|
22
|
+
// stop the sketch.
|
|
15
23
|
|
|
16
|
-
import { Color, color, isPalette, type ColorInput
|
|
24
|
+
import { Color, color, isPalette, type ColorInput } from "./color.ts";
|
|
17
25
|
import type { Out, Prev, Update } from "./arclamp.ts";
|
|
18
26
|
import { colorOf, Here, roomOf, sameLayout, type Room } from "./here.ts";
|
|
19
27
|
|
|
20
28
|
// Plain V8 (arclamp's sandbox) has only what arclamp's prelude gives it.
|
|
21
29
|
declare const console: { warn(...data: unknown[]): void };
|
|
22
30
|
|
|
23
|
-
/** What a light should make, here and now; null, undefined or false leaves it as it is below. */
|
|
31
|
+
/** What a color light should make, here and now; null, undefined or false leaves it as it is below. */
|
|
24
32
|
export type LookResult = ColorInput | null | undefined | false | void;
|
|
25
33
|
|
|
26
|
-
/**
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
*/
|
|
30
|
-
export type
|
|
34
|
+
/** The color lights' look: a function of here giving a color, one color for every light, or a palette, laid across the room. */
|
|
35
|
+
export type Look = ((here: Here) => LookResult) | ColorInput;
|
|
36
|
+
|
|
37
|
+
/** Whether an old bulb should be on: true or false, a number (on at 0.5 or more), "on" or "off"; null or undefined leaves it as it is. */
|
|
38
|
+
export type SwitchResult = boolean | number | string | null | undefined | void;
|
|
39
|
+
|
|
40
|
+
/** The old bulbs' look: a function of here (a field too) saying whether each is on, or one answer for them all. */
|
|
41
|
+
export type SwitchLook = ((here: Here) => SwitchResult) | boolean | number | string;
|
|
42
|
+
|
|
43
|
+
/** A look for each kind of light (light.kind); either may be left out, and its lights are left as they are. */
|
|
44
|
+
export interface Looks {
|
|
45
|
+
/** For the color bulbs and panels. */
|
|
46
|
+
color?: Look;
|
|
47
|
+
/** For the old bulbs, which only switch. */
|
|
48
|
+
switch?: SwitchLook;
|
|
49
|
+
}
|
|
31
50
|
|
|
32
51
|
export interface SketchOptions {
|
|
33
|
-
/**
|
|
34
|
-
|
|
35
|
-
/** And off when asked for fewer than this (default 70). */
|
|
36
|
-
switchOff?: number;
|
|
52
|
+
/** The old bulbs' look, beside a color look given on its own. */
|
|
53
|
+
switch?: SwitchLook;
|
|
37
54
|
}
|
|
38
55
|
|
|
39
56
|
// A tick after a long gap (the sketch paused, or held up) counts as at most this long.
|
|
40
57
|
const MAX_DT = 0.25;
|
|
41
58
|
|
|
42
|
-
/** Your look (a function of here, or a field) as arclamp's update()
|
|
59
|
+
/** Your color look (a function of here, or a field) as arclamp's update(); old bulbs are left alone, unless given `switch`. */
|
|
43
60
|
export function sketch(look: (here: Here) => LookResult, options?: SketchOptions): Update;
|
|
44
|
-
/**
|
|
45
|
-
export function sketch(
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
61
|
+
/** A look for each kind of light: { color, switch }. */
|
|
62
|
+
export function sketch(looks: Looks): Update;
|
|
63
|
+
/** One color for every color light, or a palette laid across the room, as arclamp's update(). */
|
|
64
|
+
export function sketch(look: ColorInput, options?: SketchOptions): Update;
|
|
65
|
+
export function sketch(given: Looks | Look, options: SketchOptions = {}): Update {
|
|
66
|
+
if (options && typeof options === "object" && "on" in options) throw new Error(ON_KEY);
|
|
67
|
+
const looks: Looks = isLooks(given) ? { switch: options.switch, ...given } : { color: given as Look, switch: options.switch };
|
|
68
|
+
const askColor = looks.color === undefined ? null : lookOf(looks.color);
|
|
69
|
+
const askSwitch = looks.switch === undefined ? null : switchLookOf(looks.switch);
|
|
50
70
|
let room: Room | null = null;
|
|
51
71
|
let last: number | null = null;
|
|
52
|
-
const on = new Map<number, boolean>();
|
|
53
72
|
const warned = new Set<string>();
|
|
54
73
|
|
|
55
74
|
const warn = (kind: string, text: string) => {
|
|
@@ -69,9 +88,23 @@ export function sketch(look: Look, options: SketchOptions = {}): Update {
|
|
|
69
88
|
for (let i = 0; i < list.length; i++) {
|
|
70
89
|
const light = room.lights[i]!;
|
|
71
90
|
light.below = colorOf(list[i]!, light.kind);
|
|
91
|
+
light.belowOn = light.below.lm > 0;
|
|
92
|
+
const ask = light.kind === "switch" ? askSwitch : askColor;
|
|
93
|
+
if (!ask) continue;
|
|
72
94
|
const v = ask(new Here(light.x, light.y, t, dt, nowMs, light, room));
|
|
73
|
-
if (v === null || v === undefined || v === false) continue;
|
|
74
95
|
|
|
96
|
+
if (light.kind === "switch") {
|
|
97
|
+
const on = readOn(v);
|
|
98
|
+
if (on === "unreadable") {
|
|
99
|
+
warn(
|
|
100
|
+
"on",
|
|
101
|
+
`light ${light.id} is an old bulb, which only switches: its look gives true or false, a number (on at 0.5 or more), or "on" or "off", not ${describe(v)}; give old bulbs a look of their own, sketch({ color, switch })`,
|
|
102
|
+
);
|
|
103
|
+
} else if (on !== null) lights.push({ id: light.id, channels: { on: on ? 1 : 0 } });
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (v === null || v === undefined || v === false) continue;
|
|
75
108
|
let c: Color;
|
|
76
109
|
try {
|
|
77
110
|
c = v instanceof Color ? v : color(v as ColorInput);
|
|
@@ -83,19 +116,6 @@ export function sketch(look: Look, options: SketchOptions = {}): Update {
|
|
|
83
116
|
}
|
|
84
117
|
continue;
|
|
85
118
|
}
|
|
86
|
-
|
|
87
|
-
if (light.kind === "switch") {
|
|
88
|
-
if (!Number.isFinite(c.lm)) {
|
|
89
|
-
warn("nan", `light ${light.id} was given a color that isn't all numbers, ${JSON.stringify(c)}, so it's left as it is`);
|
|
90
|
-
continue;
|
|
91
|
-
}
|
|
92
|
-
const was = on.get(light.id) ?? c.lm >= switchOn;
|
|
93
|
-
const now = c.lm >= switchOn ? true : c.lm < switchOff ? false : was;
|
|
94
|
-
on.set(light.id, now);
|
|
95
|
-
lights.push({ id: light.id, channels: { on: now ? 1 : 0 } });
|
|
96
|
-
continue;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
119
|
const channels = c.channels;
|
|
100
120
|
if (!Number.isFinite(channels.a) || !Number.isFinite(channels.b) || !Number.isFinite(channels.brightness) || !Number.isFinite(channels.fidelity)) {
|
|
101
121
|
warn("nan", `light ${light.id} was given a color that isn't all numbers, ${JSON.stringify(c)}, so it's left as it is`);
|
|
@@ -107,10 +127,46 @@ export function sketch(look: Look, options: SketchOptions = {}): Update {
|
|
|
107
127
|
};
|
|
108
128
|
}
|
|
109
129
|
|
|
110
|
-
|
|
130
|
+
const ON_KEY = 'old bulbs\' look is `switch`, for the kind of light it\'s for: sketch({ color, switch }), or sketch(look, { switch })';
|
|
131
|
+
|
|
132
|
+
/** Whether a sketch was given a look for each kind of light ({ color, switch }) rather than one look. */
|
|
133
|
+
function isLooks(v: unknown): v is Looks {
|
|
134
|
+
if (!v || typeof v !== "object" || v instanceof Color || Array.isArray(v)) return false;
|
|
135
|
+
const keys = Object.keys(v);
|
|
136
|
+
// { on } would read as an old bulb's channels, a color: say what's meant instead.
|
|
137
|
+
if (keys.includes("on")) throw new Error(ON_KEY);
|
|
138
|
+
return keys.length > 0 && keys.every((k) => k === "color" || k === "switch");
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** The color look as a function of here. One color is the same everywhere (and said wrong, an error now, not each tick). */
|
|
111
142
|
function lookOf(look: Look): (here: Here) => unknown {
|
|
112
143
|
if (isPalette(look)) return (here) => look(here.u);
|
|
113
144
|
if (typeof look === "function") return look as (here: Here) => unknown;
|
|
114
145
|
const c = color(look);
|
|
115
146
|
return () => c;
|
|
116
147
|
}
|
|
148
|
+
|
|
149
|
+
/** The switch look as a function of here. One answer is the same everywhere (and said wrong, an error now). */
|
|
150
|
+
function switchLookOf(look: SwitchLook): (here: Here) => unknown {
|
|
151
|
+
if (typeof look === "function") return look as (here: Here) => unknown;
|
|
152
|
+
const on = readOn(look);
|
|
153
|
+
if (on === "unreadable") throw new Error(`${describe(look)} isn't on or off: give true or false, a number (on at 0.5 or more), or "on" or "off"`);
|
|
154
|
+
return () => on;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** On (true), off (false), leave it (null), or can't tell. */
|
|
158
|
+
function readOn(v: unknown): boolean | null | "unreadable" {
|
|
159
|
+
if (v === null || v === undefined) return null;
|
|
160
|
+
if (typeof v === "boolean") return v;
|
|
161
|
+
if (typeof v === "number") return Number.isFinite(v) ? v >= 0.5 : "unreadable";
|
|
162
|
+
if (typeof v === "string") {
|
|
163
|
+
const s = v.trim().toLowerCase();
|
|
164
|
+
if (s === "on" || s === "true" || s === "yes") return true;
|
|
165
|
+
if (s === "off" || s === "false" || s === "no") return false;
|
|
166
|
+
return s !== "" && Number.isFinite(Number(s)) ? Number(s) >= 0.5 : "unreadable";
|
|
167
|
+
}
|
|
168
|
+
if (typeof v === "object" && !(v instanceof Color) && "on" in v) return readOn((v as { on: unknown }).on);
|
|
169
|
+
return "unreadable";
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const describe = (v: unknown) => (v instanceof Color ? `a color (${v})` : typeof v === "string" ? `"${v}"` : JSON.stringify(v) ?? String(v));
|