effect-motion 0.2.0 → 0.3.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/dist/Camera.d.ts +50 -28
- package/dist/Camera.js +71 -19
- package/dist/CameraHelpers.d.ts +70 -0
- package/dist/CameraHelpers.js +239 -0
- package/dist/CanvasExporter.d.ts +12 -0
- package/dist/CanvasExporter.js +40 -0
- package/dist/Color.d.ts +428 -0
- package/dist/Color.js +535 -0
- package/dist/EffectMotionError.d.ts +10 -0
- package/dist/EffectMotionError.js +6 -0
- package/dist/Entity.d.ts +9 -8
- package/dist/Entity.js +1 -4
- package/dist/Fonts.d.ts +10 -0
- package/dist/Fonts.js +16 -0
- package/dist/Images.d.ts +33 -0
- package/dist/Images.js +24 -0
- package/dist/Instance.d.ts +4 -4
- package/dist/Motion.d.ts +24 -7
- package/dist/Motion.js +54 -9
- package/dist/Phaser.d.ts +1 -1
- package/dist/Phaser.js +13 -9
- package/dist/Physics.d.ts +3 -3
- package/dist/Physics.js +4 -4
- package/dist/PngExporter.d.ts +6 -0
- package/dist/PngExporter.js +85 -0
- package/dist/Projection.d.ts +225 -0
- package/dist/Projection.js +473 -0
- package/dist/Renderer.d.ts +102 -53
- package/dist/Renderer.js +369 -78
- package/dist/Runner.d.ts +126 -42
- package/dist/Runner.js +42 -17
- package/dist/Scene.d.ts +88 -59
- package/dist/Scene.js +24 -15
- package/dist/Shapes.d.ts +11 -0
- package/dist/Shapes.js +11 -0
- package/dist/demo.d.ts +3 -186
- package/dist/demo.js +24 -35
- package/dist/index.d.ts +14 -13
- package/dist/index.js +14 -13
- package/dist/particles/Particle.d.ts +4 -3
- package/dist/particles/ParticleField.d.ts +11 -48
- package/dist/particles/ParticleField.js +5 -4
- package/dist/particles/constructors.d.ts +8 -7
- package/dist/particles/constructors.js +2 -2
- package/dist/particles/index.d.ts +5 -6
- package/dist/particles/index.js +5 -6
- package/dist/particles/overLife.d.ts +1 -1
- package/dist/particles/overLife.js +1 -1
- package/dist/particles/simulate.d.ts +2 -2
- package/dist/particles/simulate.js +6 -6
- package/dist/particles/step.d.ts +2 -2
- package/dist/particles/step.js +5 -3
- package/dist/render/dof.d.ts +27 -0
- package/dist/render/dof.js +37 -0
- package/dist/render/paint.d.ts +30 -0
- package/dist/render/paint.js +36 -0
- package/dist/render/shapes.d.ts +42 -0
- package/dist/render/shapes.js +310 -0
- package/dist/shapes/Circle.d.ts +10 -15
- package/dist/shapes/Circle.js +2 -2
- package/dist/shapes/Ellipse.d.ts +10 -16
- package/dist/shapes/Ellipse.js +2 -2
- package/dist/shapes/Group.d.ts +5 -39
- package/dist/shapes/Group.js +4 -4
- package/dist/shapes/Hud.d.ts +38 -0
- package/dist/shapes/Hud.js +35 -0
- package/dist/shapes/Image.d.ts +45 -0
- package/dist/shapes/Image.js +28 -0
- package/dist/shapes/Line.d.ts +12 -12
- package/dist/shapes/Line.js +11 -6
- package/dist/shapes/Path.d.ts +87 -18
- package/dist/shapes/Path.js +25 -6
- package/dist/shapes/Rect.d.ts +33 -23
- package/dist/shapes/Rect.js +14 -2
- package/dist/shapes/Shape2D.d.ts +13 -4
- package/dist/shapes/Shape2D.js +16 -5
- package/dist/shapes/Shapes.d.ts +11 -0
- package/dist/shapes/Shapes.js +11 -0
- package/dist/shapes/Square.d.ts +10 -15
- package/dist/shapes/Square.js +2 -2
- package/dist/shapes/Text.d.ts +10 -19
- package/dist/shapes/Text.js +2 -2
- package/package.json +13 -3
- package/dist/particles/render.d.ts +0 -13
- package/dist/particles/render.js +0 -33
- package/dist/shapes/Layer.d.ts +0 -9
- package/dist/shapes/Layer.js +0 -23
- package/dist/shapes/index.d.ts +0 -10
- package/dist/shapes/index.js +0 -10
- package/dist/svg/SvgDomRenderer.d.ts +0 -28
- package/dist/svg/SvgDomRenderer.js +0 -50
- package/dist/svg/SvgNode.d.ts +0 -13
- package/dist/svg/SvgNode.js +0 -18
- package/dist/svg/SvgRenderer.d.ts +0 -22
- package/dist/svg/SvgRenderer.js +0 -20
- package/dist/svg/camera.d.ts +0 -21
- package/dist/svg/camera.js +0 -43
- package/dist/svg/index.d.ts +0 -6
- package/dist/svg/index.js +0 -6
- package/dist/svg/layers.d.ts +0 -18
- package/dist/svg/layers.js +0 -13
- package/dist/svg/shapes.d.ts +0 -1089
- package/dist/svg/shapes.js +0 -119
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
export * as Camera from "./
|
|
2
|
-
export * as
|
|
3
|
-
export * as
|
|
4
|
-
export * as
|
|
5
|
-
export * as
|
|
6
|
-
export * as
|
|
7
|
-
export * as
|
|
8
|
-
export * as
|
|
9
|
-
export * as
|
|
10
|
-
export * as
|
|
11
|
-
export * as
|
|
12
|
-
export * as
|
|
13
|
-
export * as
|
|
1
|
+
export * as Camera from "./CameraHelpers.js";
|
|
2
|
+
export * as Color from "./Color.js";
|
|
3
|
+
export * as Entity from "./Entity.js";
|
|
4
|
+
export * as Fonts from "./Fonts.js";
|
|
5
|
+
export * as Images from "./Images.js";
|
|
6
|
+
export * as Instance from "./Instance.js";
|
|
7
|
+
export * as Motion from "./Motion.js";
|
|
8
|
+
export * as Phaser from "./Phaser.js";
|
|
9
|
+
export * as Physics from "./Physics.js";
|
|
10
|
+
export * as Particles from "./particles/index.js";
|
|
11
|
+
export * as Renderer from "./Renderer.js";
|
|
12
|
+
export * as Scene from "./Scene.js";
|
|
13
|
+
export * as Shapes from "./Shapes.js";
|
|
14
|
+
export * as Timing from "./Timing.js";
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
export * as Camera from "./
|
|
2
|
-
export * as
|
|
3
|
-
export * as
|
|
4
|
-
export * as
|
|
5
|
-
export * as
|
|
6
|
-
export * as
|
|
7
|
-
export * as
|
|
8
|
-
export * as
|
|
9
|
-
export * as
|
|
10
|
-
export * as
|
|
11
|
-
export * as
|
|
12
|
-
export * as
|
|
13
|
-
export * as
|
|
1
|
+
export * as Camera from "./CameraHelpers.js";
|
|
2
|
+
export * as Color from "./Color.js";
|
|
3
|
+
export * as Entity from "./Entity.js";
|
|
4
|
+
export * as Fonts from "./Fonts.js";
|
|
5
|
+
export * as Images from "./Images.js";
|
|
6
|
+
export * as Instance from "./Instance.js";
|
|
7
|
+
export * as Motion from "./Motion.js";
|
|
8
|
+
export * as Phaser from "./Phaser.js";
|
|
9
|
+
export * as Physics from "./Physics.js";
|
|
10
|
+
export * as Particles from "./particles/index.js";
|
|
11
|
+
export * as Renderer from "./Renderer.js";
|
|
12
|
+
export * as Scene from "./Scene.js";
|
|
13
|
+
export * as Shapes from "./Shapes.js";
|
|
14
|
+
export * as Timing from "./Timing.js";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type * as
|
|
1
|
+
import type * as Color from "../Color.js";
|
|
2
|
+
import type * as Prng from "./Prng.js";
|
|
2
3
|
/**
|
|
3
4
|
* A single particle's live state. Held in a flat buffer on the
|
|
4
5
|
* ParticleField instance — never its own entity/instance/fiber. Position
|
|
@@ -25,7 +26,7 @@ export interface Particle {
|
|
|
25
26
|
size: number;
|
|
26
27
|
/** baseline opacity drawn at birth; the over-life curve multiplies it */
|
|
27
28
|
opacity: number;
|
|
28
|
-
color:
|
|
29
|
+
color: Color.Color;
|
|
29
30
|
rng: Prng.PrngState;
|
|
30
31
|
/** false = dead slot, reusable by the next emission */
|
|
31
32
|
alive: boolean;
|
|
@@ -68,7 +69,7 @@ export interface EmitterConfig {
|
|
|
68
69
|
/** shared downward acceleration (px/sec²); not ranged */
|
|
69
70
|
readonly gravity: number;
|
|
70
71
|
/** colors drawn from uniformly at birth */
|
|
71
|
-
readonly palette: ReadonlyArray<
|
|
72
|
+
readonly palette: ReadonlyArray<Color.Color>;
|
|
72
73
|
/**
|
|
73
74
|
* fill mode only — the rectangular region particles scatter across and
|
|
74
75
|
* wrap around, in the field's local coordinates. The animator defaults
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import * as Schema from "effect/Schema";
|
|
2
|
-
import * as
|
|
2
|
+
import * as Color from "../Color.js";
|
|
3
|
+
import * as Entity from "../Entity.js";
|
|
3
4
|
export declare const ParticleField: Entity.Entity<"particles/ParticleField", Schema.Struct<{
|
|
4
5
|
x: Schema.withConstructorDefault<Schema.Number>;
|
|
5
6
|
y: Schema.withConstructorDefault<Schema.Number>;
|
|
7
|
+
z: Schema.withConstructorDefault<Schema.Number>;
|
|
6
8
|
opacity: Schema.withConstructorDefault<Schema.Number>;
|
|
7
9
|
speed: Schema.withConstructorDefault<Schema.Tuple<readonly [Schema.Number, Schema.Number]>>;
|
|
8
10
|
angle: Schema.withConstructorDefault<Schema.Tuple<readonly [Schema.Number, Schema.Number]>>;
|
|
@@ -10,7 +12,7 @@ export declare const ParticleField: Entity.Entity<"particles/ParticleField", Sch
|
|
|
10
12
|
size: Schema.withConstructorDefault<Schema.Tuple<readonly [Schema.Number, Schema.Number]>>;
|
|
11
13
|
opacityRange: Schema.withConstructorDefault<Schema.Tuple<readonly [Schema.Number, Schema.Number]>>;
|
|
12
14
|
gravity: Schema.withConstructorDefault<Schema.Number>;
|
|
13
|
-
palette: Schema.withConstructorDefault<Schema.$Array<
|
|
15
|
+
palette: Schema.withConstructorDefault<Schema.$Array<typeof Color.Color>>;
|
|
14
16
|
region: Schema.optionalKey<Schema.Struct<{
|
|
15
17
|
readonly w: Schema.Number;
|
|
16
18
|
readonly h: Schema.Number;
|
|
@@ -36,7 +38,7 @@ export declare const ParticleField: Entity.Entity<"particles/ParticleField", Sch
|
|
|
36
38
|
readonly life: Schema.Number;
|
|
37
39
|
readonly size: Schema.Number;
|
|
38
40
|
readonly opacity: Schema.Number;
|
|
39
|
-
readonly color:
|
|
41
|
+
readonly color: typeof Color.Color;
|
|
40
42
|
readonly rng: Schema.Number;
|
|
41
43
|
readonly alive: Schema.Boolean;
|
|
42
44
|
readonly wrap: Schema.Boolean;
|
|
@@ -45,6 +47,7 @@ export declare const ParticleField: Entity.Entity<"particles/ParticleField", Sch
|
|
|
45
47
|
readonly "~position": Entity.TraitLens<{
|
|
46
48
|
readonly x: number;
|
|
47
49
|
readonly y: number;
|
|
50
|
+
readonly z: number;
|
|
48
51
|
readonly opacity: number;
|
|
49
52
|
readonly speed: readonly [number, number];
|
|
50
53
|
readonly angle: readonly [number, number];
|
|
@@ -52,7 +55,7 @@ export declare const ParticleField: Entity.Entity<"particles/ParticleField", Sch
|
|
|
52
55
|
readonly size: readonly [number, number];
|
|
53
56
|
readonly opacityRange: readonly [number, number];
|
|
54
57
|
readonly gravity: number;
|
|
55
|
-
readonly palette: readonly
|
|
58
|
+
readonly palette: readonly Color.Color[];
|
|
56
59
|
readonly region?: Schema.Struct.ReadonlySide<{
|
|
57
60
|
readonly w: Schema.Number;
|
|
58
61
|
readonly h: Schema.Number;
|
|
@@ -78,7 +81,7 @@ export declare const ParticleField: Entity.Entity<"particles/ParticleField", Sch
|
|
|
78
81
|
readonly life: Schema.Number;
|
|
79
82
|
readonly size: Schema.Number;
|
|
80
83
|
readonly opacity: Schema.Number;
|
|
81
|
-
readonly color:
|
|
84
|
+
readonly color: typeof Color.Color;
|
|
82
85
|
readonly rng: Schema.Number;
|
|
83
86
|
readonly alive: Schema.Boolean;
|
|
84
87
|
readonly wrap: Schema.Boolean;
|
|
@@ -87,6 +90,7 @@ export declare const ParticleField: Entity.Entity<"particles/ParticleField", Sch
|
|
|
87
90
|
readonly "~opacity": Entity.TraitLens<{
|
|
88
91
|
readonly x: number;
|
|
89
92
|
readonly y: number;
|
|
93
|
+
readonly z: number;
|
|
90
94
|
readonly opacity: number;
|
|
91
95
|
readonly speed: readonly [number, number];
|
|
92
96
|
readonly angle: readonly [number, number];
|
|
@@ -94,7 +98,7 @@ export declare const ParticleField: Entity.Entity<"particles/ParticleField", Sch
|
|
|
94
98
|
readonly size: readonly [number, number];
|
|
95
99
|
readonly opacityRange: readonly [number, number];
|
|
96
100
|
readonly gravity: number;
|
|
97
|
-
readonly palette: readonly
|
|
101
|
+
readonly palette: readonly Color.Color[];
|
|
98
102
|
readonly region?: Schema.Struct.ReadonlySide<{
|
|
99
103
|
readonly w: Schema.Number;
|
|
100
104
|
readonly h: Schema.Number;
|
|
@@ -120,51 +124,10 @@ export declare const ParticleField: Entity.Entity<"particles/ParticleField", Sch
|
|
|
120
124
|
readonly life: Schema.Number;
|
|
121
125
|
readonly size: Schema.Number;
|
|
122
126
|
readonly opacity: Schema.Number;
|
|
123
|
-
readonly color:
|
|
127
|
+
readonly color: typeof Color.Color;
|
|
124
128
|
readonly rng: Schema.Number;
|
|
125
129
|
readonly alive: Schema.Boolean;
|
|
126
130
|
readonly wrap: Schema.Boolean;
|
|
127
131
|
}, "Type">[];
|
|
128
132
|
}, number>;
|
|
129
|
-
}, {
|
|
130
|
-
readonly x?: number;
|
|
131
|
-
readonly y?: number;
|
|
132
|
-
readonly opacity?: number;
|
|
133
|
-
readonly speed?: readonly [number, number];
|
|
134
|
-
readonly angle?: readonly [number, number];
|
|
135
|
-
readonly life?: readonly [number, number];
|
|
136
|
-
readonly size?: readonly [number, number];
|
|
137
|
-
readonly opacityRange?: readonly [number, number];
|
|
138
|
-
readonly gravity?: number;
|
|
139
|
-
readonly palette?: readonly string[];
|
|
140
|
-
readonly region?: Schema.Struct.ReadonlyMakeIn<{
|
|
141
|
-
readonly w: Schema.Number;
|
|
142
|
-
readonly h: Schema.Number;
|
|
143
|
-
}>;
|
|
144
|
-
readonly drift?: readonly [number, number];
|
|
145
|
-
readonly sizeOverLife?: {
|
|
146
|
-
readonly from: number;
|
|
147
|
-
readonly to: number;
|
|
148
|
-
readonly ease?: string;
|
|
149
|
-
};
|
|
150
|
-
readonly opacityOverLife?: {
|
|
151
|
-
readonly from: number;
|
|
152
|
-
readonly to: number;
|
|
153
|
-
readonly ease?: string;
|
|
154
|
-
};
|
|
155
|
-
readonly capacity?: number;
|
|
156
|
-
readonly buffer?: readonly Schema.Struct.ReadonlyMakeIn<{
|
|
157
|
-
readonly x: Schema.Number;
|
|
158
|
-
readonly y: Schema.Number;
|
|
159
|
-
readonly vx: Schema.Number;
|
|
160
|
-
readonly vy: Schema.Number;
|
|
161
|
-
readonly age: Schema.Number;
|
|
162
|
-
readonly life: Schema.Number;
|
|
163
|
-
readonly size: Schema.Number;
|
|
164
|
-
readonly opacity: Schema.Number;
|
|
165
|
-
readonly color: Schema.String;
|
|
166
|
-
readonly rng: Schema.Number;
|
|
167
|
-
readonly alive: Schema.Boolean;
|
|
168
|
-
readonly wrap: Schema.Boolean;
|
|
169
|
-
}>[];
|
|
170
133
|
}>;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as Effect from "effect/Effect";
|
|
2
2
|
import * as Schema from "effect/Schema";
|
|
3
|
-
import * as
|
|
4
|
-
import * as
|
|
3
|
+
import * as Color from "../Color.js";
|
|
4
|
+
import * as Entity from "../Entity.js";
|
|
5
|
+
import * as Shape2D from "../shapes/Shape2D.js";
|
|
5
6
|
/**
|
|
6
7
|
* A ParticleField is ONE entity/instance backing many particles. Its data
|
|
7
8
|
* holds the emitter config plus a fixed-capacity buffer of live particle
|
|
@@ -31,7 +32,7 @@ const ParticleSchema = Schema.Struct({
|
|
|
31
32
|
life: Schema.Number,
|
|
32
33
|
size: Schema.Number,
|
|
33
34
|
opacity: Schema.Number,
|
|
34
|
-
color:
|
|
35
|
+
color: Color.Color,
|
|
35
36
|
rng: Schema.Number,
|
|
36
37
|
alive: Schema.Boolean,
|
|
37
38
|
wrap: Schema.Boolean,
|
|
@@ -53,7 +54,7 @@ export const ParticleField = Entity.make("particles/ParticleField", {
|
|
|
53
54
|
// `opacity` (the ~opacity trait above, which fades the whole field).
|
|
54
55
|
opacityRange: defaultedRange([1, 1]),
|
|
55
56
|
gravity: Shape2D.defaultedNumber(0),
|
|
56
|
-
palette: Schema.Array(
|
|
57
|
+
palette: Schema.Array(Color.Color).pipe(Schema.withConstructorDefault(Effect.sync(() => [Color.white]))),
|
|
57
58
|
// fill mode: the region particles spread across and wrap within
|
|
58
59
|
// (defaults to the frame in `simulate`) and their drift speed range
|
|
59
60
|
region: Schema.optionalKey(Schema.Struct({ w: Schema.Number, h: Schema.Number })),
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type * as Effect from "effect/Effect";
|
|
2
|
-
import type * as
|
|
3
|
-
import type * as
|
|
4
|
-
import type
|
|
5
|
-
import {
|
|
2
|
+
import type * as Color from "../Color.js";
|
|
3
|
+
import type * as Instance from "../Instance.js";
|
|
4
|
+
import type * as Runner from "../Runner.js";
|
|
5
|
+
import type { Range } from "./Particle.js";
|
|
6
|
+
import { ParticleField } from "./ParticleField.js";
|
|
6
7
|
/**
|
|
7
8
|
* Two typed front doors onto the SAME `ParticleField` entity. The field's
|
|
8
9
|
* emission model is chosen at `simulate`, but the properties that make sense
|
|
@@ -38,7 +39,7 @@ interface CommonInput {
|
|
|
38
39
|
/** per-particle birth opacity range (0..1); over-life curve multiplies it */
|
|
39
40
|
readonly opacityRange?: Range;
|
|
40
41
|
/** colors drawn from uniformly at birth */
|
|
41
|
-
readonly palette?: ReadonlyArray<
|
|
42
|
+
readonly palette?: ReadonlyArray<Color.Color>;
|
|
42
43
|
/** shared downward acceleration (px/sec²) */
|
|
43
44
|
readonly gravity?: number;
|
|
44
45
|
readonly sizeOverLife?: OverLifeInput;
|
|
@@ -69,10 +70,10 @@ export interface FieldInput extends CommonInput {
|
|
|
69
70
|
* Create a source emitter field. Simulate it with `{ burst: n }` (all at
|
|
70
71
|
* once) or `{ rate: n }` (a continuous stream).
|
|
71
72
|
*/
|
|
72
|
-
export declare const emitter: (props: EmitterInput) => Effect.Effect<EmitterField,
|
|
73
|
+
export declare const emitter: (props: EmitterInput) => Effect.Effect<EmitterField, never, Runner.Runner>;
|
|
73
74
|
/**
|
|
74
75
|
* Create a floating field: particles spread evenly across the region,
|
|
75
76
|
* drifting and wrapping at the edges. Simulate it with `{ fill: n }`.
|
|
76
77
|
*/
|
|
77
|
-
export declare const field: (props: FieldInput) => Effect.Effect<FloatField,
|
|
78
|
+
export declare const field: (props: FieldInput) => Effect.Effect<FloatField, never, Runner.Runner>;
|
|
78
79
|
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as Scene from "../Scene";
|
|
2
|
-
import { ParticleField } from "./ParticleField";
|
|
1
|
+
import * as Scene from "../Scene.js";
|
|
2
|
+
import { ParticleField } from "./ParticleField.js";
|
|
3
3
|
/**
|
|
4
4
|
* Create a source emitter field. Simulate it with `{ burst: n }` (all at
|
|
5
5
|
* once) or `{ rate: n }` (a continuous stream).
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
export * from "./constructors";
|
|
2
|
-
export * from "./Particle";
|
|
3
|
-
export * from "./ParticleField";
|
|
4
|
-
export * as Prng from "./Prng";
|
|
5
|
-
export
|
|
6
|
-
export * from "./simulate";
|
|
1
|
+
export * from "./constructors.js";
|
|
2
|
+
export * from "./Particle.js";
|
|
3
|
+
export * from "./ParticleField.js";
|
|
4
|
+
export * as Prng from "./Prng.js";
|
|
5
|
+
export * from "./simulate.js";
|
package/dist/particles/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
export * from "./constructors";
|
|
2
|
-
export * from "./Particle";
|
|
3
|
-
export * from "./ParticleField";
|
|
4
|
-
export * as Prng from "./Prng";
|
|
5
|
-
export
|
|
6
|
-
export * from "./simulate";
|
|
1
|
+
export * from "./constructors.js";
|
|
2
|
+
export * from "./Particle.js";
|
|
3
|
+
export * from "./ParticleField.js";
|
|
4
|
+
export * as Prng from "./Prng.js";
|
|
5
|
+
export * from "./simulate.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type * as Duration from "effect/Duration";
|
|
2
2
|
import * as Effect from "effect/Effect";
|
|
3
|
-
import * as Runner from "../Runner";
|
|
4
|
-
import type { EmitterField, FloatField } from "./constructors";
|
|
3
|
+
import * as Runner from "../Runner.js";
|
|
4
|
+
import type { EmitterField, FloatField } from "./constructors.js";
|
|
5
5
|
/**
|
|
6
6
|
* Emission model for a single `simulate` call:
|
|
7
7
|
* - `{ burst: n }` — birth `n` particles on the FIRST frame, then none
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import * as Effect from "effect/Effect";
|
|
2
2
|
import { dual } from "effect/Function";
|
|
3
3
|
import * as Random from "effect/Random";
|
|
4
|
-
import * as Instance from "../Instance";
|
|
5
|
-
import * as Runner from "../Runner";
|
|
6
|
-
import * as Scene from "../Scene";
|
|
7
|
-
import * as Time from "../Time";
|
|
8
|
-
import * as Prng from "./Prng";
|
|
9
|
-
import { step } from "./step";
|
|
4
|
+
import * as Instance from "../Instance.js";
|
|
5
|
+
import * as Runner from "../Runner.js";
|
|
6
|
+
import * as Scene from "../Scene.js";
|
|
7
|
+
import * as Time from "../Time.js";
|
|
8
|
+
import * as Prng from "./Prng.js";
|
|
9
|
+
import { step } from "./step.js";
|
|
10
10
|
// how many particles to birth on frame `i` (1-based) of this call
|
|
11
11
|
const birthsForFrame = (emission, i, fps) => {
|
|
12
12
|
if ("burst" in emission) {
|
package/dist/particles/step.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { EmitterConfig, Particle } from "./Particle";
|
|
2
|
-
import * as Prng from "./Prng";
|
|
1
|
+
import type { EmitterConfig, Particle } from "./Particle.js";
|
|
2
|
+
import * as Prng from "./Prng.js";
|
|
3
3
|
/** birth one particle from a seed + config (fixed draw order). */
|
|
4
4
|
export declare const birth: (seed: Prng.PrngState, config: EmitterConfig) => Particle;
|
|
5
5
|
/**
|
package/dist/particles/step.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
/** biome-ignore-all lint/style/useConst: let declaration is necessary for destructuring assignment */
|
|
2
|
+
import * as Color from "../Color.js";
|
|
3
|
+
import * as Prng from "./Prng.js";
|
|
2
4
|
/**
|
|
3
5
|
* The per-frame simulation as a PURE fold: `(buffer, dt, births) → buffer`.
|
|
4
6
|
* No external entropy — the only randomness is each particle's own carried
|
|
@@ -41,7 +43,7 @@ export const birth = (seed, config) => {
|
|
|
41
43
|
[rng, opacity] = drawOpacity(rng, config);
|
|
42
44
|
// angle 0 = straight up; clockwise-positive
|
|
43
45
|
const rad = angle * DEG;
|
|
44
|
-
const color = config.palette[Math.min(config.palette.length - 1, Math.floor(colorPick))] ??
|
|
46
|
+
const color = config.palette[Math.min(config.palette.length - 1, Math.floor(colorPick))] ?? Color.white;
|
|
45
47
|
return {
|
|
46
48
|
x: config.x,
|
|
47
49
|
y: config.y,
|
|
@@ -85,7 +87,7 @@ export const birthFill = (seed, config) => {
|
|
|
85
87
|
let opacity;
|
|
86
88
|
[rng, opacity] = drawOpacity(rng, config);
|
|
87
89
|
const rad = dir * DEG;
|
|
88
|
-
const color = config.palette[Math.min(config.palette.length - 1, Math.floor(colorPick))] ??
|
|
90
|
+
const color = config.palette[Math.min(config.palette.length - 1, Math.floor(colorPick))] ?? Color.white;
|
|
89
91
|
return {
|
|
90
92
|
// scattered across the region, offset by the field's own origin
|
|
91
93
|
x: config.x + px,
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type * as Projection from "../Projection.js";
|
|
2
|
+
/**
|
|
3
|
+
* Depth-of-field circle of confusion (design D2 of camera-depth-of-field):
|
|
4
|
+
* how much gaussian blur a paintable at `depth` receives under `camera`.
|
|
5
|
+
* Pure arithmetic on frame data — deterministic by construction.
|
|
6
|
+
*/
|
|
7
|
+
/** defensive ceiling: no author intends a 100px blur; huge sigmas are bugs */
|
|
8
|
+
export declare const MAX_SIGMA = 64;
|
|
9
|
+
/** quantization step (px): paintables within a step share one blur pass */
|
|
10
|
+
export declare const SIGMA_STEP = 0.5;
|
|
11
|
+
/** below this, blur is visually nil — treat as sharp (no blur pass at all) */
|
|
12
|
+
export declare const SHARP_THRESHOLD = 0.25;
|
|
13
|
+
/**
|
|
14
|
+
* Blur sigma for a paintable at view-space `depth`: zero at the focus plane,
|
|
15
|
+
* growing with distance from it, scaled by aperture and focal length (longer
|
|
16
|
+
* lens = shallower field). AE-flavored, not thin-lens-accurate — the contract
|
|
17
|
+
* is the shape of the curve, not the constants.
|
|
18
|
+
*/
|
|
19
|
+
export declare const circleOfConfusion: (depth: number, camera: Projection.CameraView) => number;
|
|
20
|
+
/**
|
|
21
|
+
* Quantize a sigma so contiguous depth-sorted runs share blur passes: 0 for
|
|
22
|
+
* visually-sharp values, otherwise the nearest step (never above the ceiling).
|
|
23
|
+
* ponytail: 0.5px steps keep pass counts low and banding invisible; the
|
|
24
|
+
* upgrade path is per-paintable exact sigma (one blur pass each) if a smooth
|
|
25
|
+
* depth gradient ever shows stepping.
|
|
26
|
+
*/
|
|
27
|
+
export declare const quantizeSigma: (sigma: number) => number;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Depth-of-field circle of confusion (design D2 of camera-depth-of-field):
|
|
3
|
+
* how much gaussian blur a paintable at `depth` receives under `camera`.
|
|
4
|
+
* Pure arithmetic on frame data — deterministic by construction.
|
|
5
|
+
*/
|
|
6
|
+
/** defensive ceiling: no author intends a 100px blur; huge sigmas are bugs */
|
|
7
|
+
export const MAX_SIGMA = 64;
|
|
8
|
+
/** quantization step (px): paintables within a step share one blur pass */
|
|
9
|
+
export const SIGMA_STEP = 0.5;
|
|
10
|
+
/** below this, blur is visually nil — treat as sharp (no blur pass at all) */
|
|
11
|
+
export const SHARP_THRESHOLD = 0.25;
|
|
12
|
+
/**
|
|
13
|
+
* Blur sigma for a paintable at view-space `depth`: zero at the focus plane,
|
|
14
|
+
* growing with distance from it, scaled by aperture and focal length (longer
|
|
15
|
+
* lens = shallower field). AE-flavored, not thin-lens-accurate — the contract
|
|
16
|
+
* is the shape of the curve, not the constants.
|
|
17
|
+
*/
|
|
18
|
+
export const circleOfConfusion = (depth, camera) => {
|
|
19
|
+
if (camera.aperture <= 0 || depth <= 0 || camera.focusDistance <= 0) {
|
|
20
|
+
return 0;
|
|
21
|
+
}
|
|
22
|
+
const sigma = (camera.aperture *
|
|
23
|
+
camera.focalLength *
|
|
24
|
+
Math.abs(depth - camera.focusDistance)) /
|
|
25
|
+
(depth * camera.focusDistance);
|
|
26
|
+
return Math.min(sigma, MAX_SIGMA);
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Quantize a sigma so contiguous depth-sorted runs share blur passes: 0 for
|
|
30
|
+
* visually-sharp values, otherwise the nearest step (never above the ceiling).
|
|
31
|
+
* ponytail: 0.5px steps keep pass counts low and banding invisible; the
|
|
32
|
+
* upgrade path is per-paintable exact sigma (one blur pass each) if a smooth
|
|
33
|
+
* depth gradient ever shows stepping.
|
|
34
|
+
*/
|
|
35
|
+
export const quantizeSigma = (sigma) => sigma < SHARP_THRESHOLD
|
|
36
|
+
? 0
|
|
37
|
+
: Math.min(Math.round(sigma / SIGMA_STEP) * SIGMA_STEP, MAX_SIGMA);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { OwnedPaint, ThorvgException } from "@effect-motion/thorvg";
|
|
2
|
+
import * as Tvg from "@effect-motion/thorvg";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import type * as Scope from "effect/Scope";
|
|
5
|
+
import * as Color from "../Color.js";
|
|
6
|
+
import type { PaintProjection } from "../Renderer.js";
|
|
7
|
+
/**
|
|
8
|
+
* Shared paint helpers: style application, projection, and the attach step
|
|
9
|
+
* every leaf paint function runs. Keeping the ThorVG call sequence in one
|
|
10
|
+
* place means each shape's paint function is just "make geometry, then
|
|
11
|
+
* `finishPaint`".
|
|
12
|
+
*/
|
|
13
|
+
/** The style fields a filled/stroked shape carries in its data. */
|
|
14
|
+
export interface StyleData {
|
|
15
|
+
readonly fill?: Color.Color;
|
|
16
|
+
readonly stroke?: Color.Color;
|
|
17
|
+
readonly strokeWidth?: number;
|
|
18
|
+
readonly opacity: number;
|
|
19
|
+
}
|
|
20
|
+
/** Apply fill/stroke/opacity from shape data onto a ThorVG shape paint. */
|
|
21
|
+
export declare const applyStyle: (shape: OwnedPaint, data: StyleData) => Effect.Effect<void, ThorvgException, Tvg.ThorvgWasm>;
|
|
22
|
+
/**
|
|
23
|
+
* Apply the billboard projection affine to a shape, then add it to the scene.
|
|
24
|
+
* The identity affine (resting camera, z=0) is skipped so plain-2D scenes
|
|
25
|
+
* issue the minimal draw calls. Ownership transfers to the scene on add.
|
|
26
|
+
*
|
|
27
|
+
* Callers must NOT have applied any translate/rotate/scale to the shape —
|
|
28
|
+
* `setTransform` is the single, final transform (design D3).
|
|
29
|
+
*/
|
|
30
|
+
export declare const finishPaint: (shape: OwnedPaint, scene: OwnedPaint, projection: PaintProjection) => Effect.Effect<void, ThorvgException, Tvg.ThorvgWasm | Scope.Scope>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as Tvg from "@effect-motion/thorvg";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as Color from "../Color.js";
|
|
4
|
+
/** Apply fill/stroke/opacity from shape data onto a ThorVG shape paint. */
|
|
5
|
+
export const applyStyle = (shape, data) => Effect.gen(function* () {
|
|
6
|
+
if (data.fill !== undefined) {
|
|
7
|
+
const { r, g, b, a } = Color.bytes(data.fill);
|
|
8
|
+
yield* Tvg.Shape.setFillColor(shape, r, g, b, a);
|
|
9
|
+
}
|
|
10
|
+
if (data.stroke !== undefined) {
|
|
11
|
+
const { r, g, b, a } = Color.bytes(data.stroke);
|
|
12
|
+
yield* Tvg.Shape.setStrokeColor(shape, r, g, b, a);
|
|
13
|
+
}
|
|
14
|
+
if (data.strokeWidth !== undefined) {
|
|
15
|
+
yield* Tvg.Shape.setStrokeWidth(shape, data.strokeWidth);
|
|
16
|
+
}
|
|
17
|
+
// opacity 1 is the ThorVG default; only set when it changes something
|
|
18
|
+
if (data.opacity !== 1) {
|
|
19
|
+
yield* Tvg.Paint.setOpacity(shape, Math.round(data.opacity * 255));
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
const isIdentity = (m) => m.a === 1 && m.b === 0 && m.c === 0 && m.d === 1 && m.e === 0 && m.f === 0;
|
|
23
|
+
/**
|
|
24
|
+
* Apply the billboard projection affine to a shape, then add it to the scene.
|
|
25
|
+
* The identity affine (resting camera, z=0) is skipped so plain-2D scenes
|
|
26
|
+
* issue the minimal draw calls. Ownership transfers to the scene on add.
|
|
27
|
+
*
|
|
28
|
+
* Callers must NOT have applied any translate/rotate/scale to the shape —
|
|
29
|
+
* `setTransform` is the single, final transform (design D3).
|
|
30
|
+
*/
|
|
31
|
+
export const finishPaint = (shape, scene, projection) => Effect.gen(function* () {
|
|
32
|
+
if (!isIdentity(projection.screen)) {
|
|
33
|
+
yield* Tvg.Paint.setTransform(shape, projection.screen);
|
|
34
|
+
}
|
|
35
|
+
yield* Tvg.Scene.add(scene, shape);
|
|
36
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ParticleField } from "../particles/ParticleField.js";
|
|
2
|
+
import type { PaintFunction, PaintFunctions } from "../Renderer.js";
|
|
3
|
+
import * as Circle from "../shapes/Circle.js";
|
|
4
|
+
import * as Ellipse from "../shapes/Ellipse.js";
|
|
5
|
+
import * as Group from "../shapes/Group.js";
|
|
6
|
+
import * as Hud from "../shapes/Hud.js";
|
|
7
|
+
import * as Image from "../shapes/Image.js";
|
|
8
|
+
import * as Line from "../shapes/Line.js";
|
|
9
|
+
import * as Path from "../shapes/Path.js";
|
|
10
|
+
import * as Rect from "../shapes/Rect.js";
|
|
11
|
+
import * as Square from "../shapes/Square.js";
|
|
12
|
+
import * as Text from "../shapes/Text.js";
|
|
13
|
+
/**
|
|
14
|
+
* ThorVG paint functions for the built-in shapes — this file is the coverage
|
|
15
|
+
* manifest: `paints` is typed `PaintFunctions<...>`, so a built-in missing a
|
|
16
|
+
* paint function is a type error, not a runtime surprise.
|
|
17
|
+
*/
|
|
18
|
+
export declare const circle: PaintFunction<typeof Circle.Circle>;
|
|
19
|
+
export declare const rect: PaintFunction<typeof Rect.Rect>;
|
|
20
|
+
export declare const square: PaintFunction<typeof Square.Square>;
|
|
21
|
+
export declare const ellipse: PaintFunction<typeof Ellipse.Ellipse>;
|
|
22
|
+
export declare const line: PaintFunction<typeof Line.Line>;
|
|
23
|
+
export declare const path: PaintFunction<typeof Path.Path>;
|
|
24
|
+
export declare const group: PaintFunction<typeof Group.Group>;
|
|
25
|
+
export declare const hud: PaintFunction<typeof Hud.Hud>;
|
|
26
|
+
export declare const image: PaintFunction<typeof Image.Image>;
|
|
27
|
+
export declare const text: PaintFunction<typeof Text.Text>;
|
|
28
|
+
/**
|
|
29
|
+
* ParticleField: live particles batched into one shape PER (color, opacity)
|
|
30
|
+
* bucket — ThorVG fills a shape uniformly, so particles that share a color and
|
|
31
|
+
* (quantized) over-life opacity are appended into the same shape and filled
|
|
32
|
+
* once. Sized/faded by the over-life curves; dead slots emit nothing.
|
|
33
|
+
* ponytail: one shape per distinct (color, opacity-bucket) — far fewer than one
|
|
34
|
+
* per particle, but a fully instanced path is the upgrade if this is a wall.
|
|
35
|
+
*/
|
|
36
|
+
export declare const particleField: PaintFunction<typeof ParticleField>;
|
|
37
|
+
/**
|
|
38
|
+
* The exhaustive paint-function map for every built-in entity. Typed
|
|
39
|
+
* `PaintFunctions<...>` so a missing built-in fails to type-check (the old
|
|
40
|
+
* "coverage manifest" guarantee, without a Context registry).
|
|
41
|
+
*/
|
|
42
|
+
export declare const builtinPaints: PaintFunctions<typeof Circle.Circle | typeof Rect.Rect | typeof Square.Square | typeof Ellipse.Ellipse | typeof Line.Line | typeof Path.Path | typeof Group.Group | typeof Hud.Hud | typeof Text.Text | typeof Image.Image | typeof ParticleField>;
|