packages/core/src/features/textures/lib/electric-shared.ts
This is the source snapshot used to build these API details. View this revision on GitHub.
1 import type { ElectricSource } from './electric-sources.js';
2 import type { LightningMessage, LightningOptions } from './lightning.js';
3 import type { TendrilsMessage, TendrilsOptions } from './tendrils.js';
4 import type { TextureContext } from "@pibbl/core";
5 import { validateSeed } from "./palette.js";
6
7 /**
8 * Coordinates are normalized to the complete texture, including its halo padding.
9 *
10 * @see {@link ElectricSource}
11 * @see {@link LightningOptions}
12 * @see {@link TendrilsOptions}
13 * @see {@link LightningMessage}
14 */
15 export interface ElectricPoint {
16 /**
17 * Horizontal coordinate or displacement in the containing coordinate system. See
18 * {@link ElectricPoint}.
19 */
20 readonly x: number;
21 /**
22 * Vertical coordinate or displacement in the containing coordinate system. See
23 * {@link ElectricPoint}.
24 */
25 readonly y: number;
26 }
27 /**
28 * Deterministic seed, branching, and glow shared by electrical texture recipes.
29 *
30 * @see {@link TendrilsOptions}
31 * @see {@link LightningOptions}
32 */
33 export interface ElectricOptions {
34 /**
35 * Seed used for deterministic sampling or simulation initialization. See {@link ElectricOptions}
36 * .
37 */
38 readonly seed?: number;
39 /** 0..1, controls the number of secondary branches. */
40 readonly branching?: number;
41 /** 0..2, scales the soft halo without widening the white core. */
42 readonly glow?: number;
43 }
44 /**
45 * Pause or reseed/reset commands shared by electrical textures.
46 *
47 * @see {@link TendrilsMessage}
48 * @see {@link LightningMessage}
49 */
50 export type ElectricControl =
51 | {
52 /** The literal "pause" identifying this variant. See {@link ElectricControl}. */
53 readonly type: "pause";
54 /** Whether simulation or playback advancement is suspended. See {@link ElectricControl}. */
55 readonly paused: boolean;
56 }
57 | {
58 /** The literal "reset" identifying this variant. See {@link ElectricControl}. */
59 readonly type: "reset";
60 /**
61 * Seed used for deterministic sampling or simulation initialization. See
62 * {@link ElectricControl}.
63 */
64 readonly seed?: number;
65 };
66 export function range(value: number, min: number, max: number, name: string) {
67 if (!Number.isFinite(value) || value < min || value > max)
68 throw new RangeError(`${name} must be ${min}..${max}.`);
69 return value;
70 }
71 export function point(p: ElectricPoint): ElectricPoint {
72 return { x: range(p.x, 0, 1, "Point x"), y: range(p.y, 0, 1, "Point y") };
73 }
74 export function electricOptions(o: ElectricOptions) {
75 return {
76 seed: validateSeed(o.seed),
77 branching: range(o.branching ?? 0.6, 0, 1, "Branching"),
78 glow: range(o.glow ?? 1, 0, 2, "Glow"),
79 };
80 }
81 export function drawCore(
82 context: TextureContext,
83 p: ElectricPoint,
84 strength: number,
85 glow: number,
86 radius = 0.038,
87 ) {
88 if (strength <= 0) return;
89 const ctx = context.canvas.getContext("2d")!,
90 scale = Math.min(context.canvas.width, context.canvas.height);
91 const x = p.x * context.canvas.width,
92 y = p.y * context.canvas.height;
93 const r = scale * radius * (0.5 + glow);
94 const gradient = ctx.createRadialGradient(x, y, 0, x, y, r);
95 gradient.addColorStop(0, `rgba(255,249,255,${strength})`);
96 gradient.addColorStop(0.1, `rgba(239,191,255,${strength * 0.95})`);
97 gradient.addColorStop(
98 0.35,
99 `rgba(179,60,255,${(strength * 0.4 * glow) / 2})`,
100 );
101 gradient.addColorStop(1, "rgba(91,30,255,0)");
102 ctx.fillStyle = gradient;
103 ctx.fillRect(x - r, y - r, r * 2, r * 2);
104 ctx.fillStyle = `rgba(255,250,255,${strength})`;
105 ctx.beginPath();
106 ctx.arc(x, y, Math.max(0.65, scale * 0.004), 0, Math.PI * 2);
107 ctx.fill();
108 }
109
Documentation version
Section titled “Documentation version”Documentation built with @pibbl/core 0.0.2, revision 2dccb19. ALPHA — NOT FOR PRODUCTION USE.