effect-motion 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 +40 -0
- package/dist/Camera.d.ts +49 -0
- package/dist/Camera.js +33 -0
- package/dist/Entity.d.ts +40 -0
- package/dist/Entity.js +32 -0
- package/dist/Fonts.d.ts +31 -0
- package/dist/Fonts.js +11 -0
- package/dist/Instance.d.ts +16 -0
- package/dist/Instance.js +18 -0
- package/dist/Motion.d.ts +74 -0
- package/dist/Motion.js +125 -0
- package/dist/Phaser.d.ts +65 -0
- package/dist/Phaser.js +170 -0
- package/dist/Physics.d.ts +78 -0
- package/dist/Physics.js +117 -0
- package/dist/Renderer.d.ts +69 -0
- package/dist/Renderer.js +90 -0
- package/dist/Runner.d.ts +360 -0
- package/dist/Runner.js +257 -0
- package/dist/Scene.d.ts +241 -0
- package/dist/Scene.js +454 -0
- package/dist/Time.d.ts +38 -0
- package/dist/Time.js +43 -0
- package/dist/Timing.d.ts +96 -0
- package/dist/Timing.js +151 -0
- package/dist/demo.d.ts +186 -0
- package/dist/demo.js +76 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +13 -0
- package/dist/particles/Particle.d.ts +91 -0
- package/dist/particles/Particle.js +1 -0
- package/dist/particles/ParticleField.d.ts +170 -0
- package/dist/particles/ParticleField.js +69 -0
- package/dist/particles/Prng.d.ts +28 -0
- package/dist/particles/Prng.js +43 -0
- package/dist/particles/constructors.d.ts +78 -0
- package/dist/particles/constructors.js +15 -0
- package/dist/particles/index.d.ts +6 -0
- package/dist/particles/index.js +6 -0
- package/dist/particles/overLife.d.ts +16 -0
- package/dist/particles/overLife.js +21 -0
- package/dist/particles/render.d.ts +13 -0
- package/dist/particles/render.js +33 -0
- package/dist/particles/simulate.d.ts +39 -0
- package/dist/particles/simulate.js +81 -0
- package/dist/particles/step.d.ts +24 -0
- package/dist/particles/step.js +167 -0
- package/dist/shapes/Circle.d.ts +37 -0
- package/dist/shapes/Circle.js +9 -0
- package/dist/shapes/Ellipse.d.ts +41 -0
- package/dist/shapes/Ellipse.js +10 -0
- package/dist/shapes/Group.d.ts +150 -0
- package/dist/shapes/Group.js +82 -0
- package/dist/shapes/Layer.d.ts +9 -0
- package/dist/shapes/Layer.js +23 -0
- package/dist/shapes/Line.d.ts +47 -0
- package/dist/shapes/Line.js +30 -0
- package/dist/shapes/Path.d.ts +38 -0
- package/dist/shapes/Path.js +13 -0
- package/dist/shapes/Rect.d.ts +41 -0
- package/dist/shapes/Rect.js +10 -0
- package/dist/shapes/Shape2D.d.ts +40 -0
- package/dist/shapes/Shape2D.js +41 -0
- package/dist/shapes/Square.d.ts +37 -0
- package/dist/shapes/Square.js +11 -0
- package/dist/shapes/Text.d.ts +60 -0
- package/dist/shapes/Text.js +24 -0
- package/dist/shapes/index.d.ts +10 -0
- package/dist/shapes/index.js +10 -0
- package/dist/svg/SvgDomRenderer.d.ts +28 -0
- package/dist/svg/SvgDomRenderer.js +50 -0
- package/dist/svg/SvgNode.d.ts +13 -0
- package/dist/svg/SvgNode.js +18 -0
- package/dist/svg/SvgRenderer.d.ts +22 -0
- package/dist/svg/SvgRenderer.js +20 -0
- package/dist/svg/camera.d.ts +21 -0
- package/dist/svg/camera.js +43 -0
- package/dist/svg/index.d.ts +6 -0
- package/dist/svg/index.js +6 -0
- package/dist/svg/layers.d.ts +18 -0
- package/dist/svg/layers.js +13 -0
- package/dist/svg/shapes.d.ts +1089 -0
- package/dist/svg/shapes.js +119 -0
- package/package.json +51 -0
package/dist/Scene.d.ts
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { Context } from "effect";
|
|
2
|
+
import * as Cause from "effect/Cause";
|
|
3
|
+
import type * as Duration from "effect/Duration";
|
|
4
|
+
import * as Effect from "effect/Effect";
|
|
5
|
+
import * as Fiber from "effect/Fiber";
|
|
6
|
+
import type * as Schedule from "effect/Schedule";
|
|
7
|
+
import type * as Schema from "effect/Schema";
|
|
8
|
+
import type * as Scope from "effect/Scope";
|
|
9
|
+
import * as Stream from "effect/Stream";
|
|
10
|
+
import type * as Entity from "./Entity";
|
|
11
|
+
import type * as Instance from "./Instance";
|
|
12
|
+
import * as Phaser from "./Phaser";
|
|
13
|
+
import * as Runner from "./Runner";
|
|
14
|
+
export declare const TypeId: "~motion/Scene";
|
|
15
|
+
export interface Scene<E, R, Entities> {
|
|
16
|
+
readonly [TypeId]: typeof TypeId;
|
|
17
|
+
readonly runner: Effect.Effect<void, E, R | Scope.Scope>;
|
|
18
|
+
readonly "~entities": Entities;
|
|
19
|
+
/** tooling-facing metadata; never read by the runtime */
|
|
20
|
+
readonly annotations: Context.Context<never>;
|
|
21
|
+
annotate<I, S>(key: Context.Key<I, S>, value: S): Scene<E, R, Entities>;
|
|
22
|
+
annotateMerge(context: Context.Context<never>): Scene<E, R, Entities>;
|
|
23
|
+
}
|
|
24
|
+
type MakeEffect<Eff extends Effect.Effect<any, any, any>, AEff> = Effect.Effect<AEff, [
|
|
25
|
+
Eff
|
|
26
|
+
] extends [never] ? never : [Eff] extends [Effect.Effect<infer _A, infer E, infer _R>] ? E : never, [
|
|
27
|
+
Eff
|
|
28
|
+
] extends [never] ? never : [Eff] extends [Effect.Effect<infer _A, infer _E, infer R>] ? R : never>;
|
|
29
|
+
export declare const make: <const Eff extends Effect.Effect<any, any, any>, AEff>(f: () => Generator<Eff, void, never>) => MakeEffect<Eff, AEff> extends Effect.Effect<AEff, infer E, infer R> ? Scene<E, Exclude<R, {
|
|
30
|
+
readonly [Entity.TypeId]: typeof Entity.TypeId;
|
|
31
|
+
}> | Scope.Scope, Extract<R, {
|
|
32
|
+
readonly [Entity.TypeId]: typeof Entity.TypeId;
|
|
33
|
+
}>> : never;
|
|
34
|
+
export declare const instantiate: <Name extends string, Data extends Schema.Top, Traits extends Partial<Entity.EntityTraits<Data["Type"]>>, MakeInput>(entity: Entity.Entity<Name, Data, Traits, MakeInput>, props: Runner.InstantiateProps<MakeInput>) => Effect.Effect<Instance.Instance<Name, Data, Traits>, unknown, Entity.Entity<Name, Data, Traits, MakeInput> | Runner.Runner>;
|
|
35
|
+
export declare const tick: Effect.Effect<void, never, Runner.Runner>;
|
|
36
|
+
/**
|
|
37
|
+
* Hold the scene for `duration` of scene time (frames at the runner's
|
|
38
|
+
* frame rate) — `Effect.sleep`'s sibling, but in frames, not wall time.
|
|
39
|
+
* A zero-length duration is a no-op.
|
|
40
|
+
*/
|
|
41
|
+
export declare const sleep: (duration: Duration.Input) => Effect.Effect<void, never, Runner.Runner>;
|
|
42
|
+
export interface FrameEntry<Entity extends Entity.AnyEntity> {
|
|
43
|
+
data: Entity["data"]["Type"];
|
|
44
|
+
entity: Entity;
|
|
45
|
+
/**
|
|
46
|
+
* builtin visibility, held beside the data; renderers skip `false`.
|
|
47
|
+
* Optional in the frame type (a hand-built frame or external producer
|
|
48
|
+
* may omit it) — absent means visible; the runner always sets it.
|
|
49
|
+
*/
|
|
50
|
+
$visible?: boolean;
|
|
51
|
+
}
|
|
52
|
+
export type EntriesFromEntities<Entities> = Entities extends Entity.AnyEntity ? {
|
|
53
|
+
[K in Entities as K["name"]]: FrameEntry<K>;
|
|
54
|
+
}[Entities["name"]] : never;
|
|
55
|
+
export interface Frame<Entities extends Entity.AnyEntity> {
|
|
56
|
+
instances: Record<string, EntriesFromEntities<Entities>>;
|
|
57
|
+
/** id of the root group (conventionally "root"); never rendered itself */
|
|
58
|
+
root: string;
|
|
59
|
+
/** render metadata from the runner settings — a frame is self-describing */
|
|
60
|
+
frameRate: number;
|
|
61
|
+
width: number;
|
|
62
|
+
height: number;
|
|
63
|
+
backgroundColor: string;
|
|
64
|
+
/** the active camera's view; identity `{0,0,1}` when unused */
|
|
65
|
+
camera: {
|
|
66
|
+
x: number;
|
|
67
|
+
y: number;
|
|
68
|
+
zoom: number;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export declare const step: <E, R, Entities extends Entity.AnyEntity>(runningScene: RunningScene<E, R, Entities>) => Effect.Effect<Frame<Entities> | null, E, never>;
|
|
72
|
+
interface RunningScene<E, R, Entities> {
|
|
73
|
+
readonly runner: Runner.Runner["Service"];
|
|
74
|
+
readonly scene: Scene<E, R, Entities>;
|
|
75
|
+
readonly fiber: Fiber.Fiber<void, E>;
|
|
76
|
+
readonly done: boolean;
|
|
77
|
+
/** frames delivered so far — mutated by `step` for the maxFrames cap */
|
|
78
|
+
framesDelivered: number;
|
|
79
|
+
}
|
|
80
|
+
export declare const run: <E, R, Entities>(scene: Scene<E, R, Entities>, settings?: Partial<Runner.Settings>) => Effect.Effect<RunningScene<E, R, Entities>, never, Exclude<Exclude<Exclude<Exclude<R, Scope.Scope>, never>, Phaser.Phaser>, Runner.Runner>>;
|
|
81
|
+
export declare const stream: <E, R, Entities extends Entity.AnyEntity>(scene: Scene<E, R, Entities>, settings?: Partial<Runner.Settings>) => Stream.Stream<Frame<Entities>, Exclude<E, Cause.Done<any>>, Exclude<Exclude<Exclude<Exclude<Exclude<R, Scope.Scope>, never>, Phaser.Phaser>, Runner.Runner>, Scope.Scope>>;
|
|
82
|
+
type Updater<Data> = Data | ((data: Data) => Data);
|
|
83
|
+
export declare const data: <Name extends string, Data extends Schema.Top>(instance: Instance.Instance<Name, Data>) => Effect.Effect<Data["Type"] & ({} | undefined), never, Runner.Runner>;
|
|
84
|
+
export declare const update: <Name extends string, Data extends Schema.Top>(instance: Instance.Instance<Name, Data>, props: Updater<Data["Type"]>) => Effect.Effect<void | false, never, Runner.Runner>;
|
|
85
|
+
/**
|
|
86
|
+
* Move `child` under `parent`, detaching it from its current parent first
|
|
87
|
+
* (so it is never double-referenced). Instances are born mounted under the
|
|
88
|
+
* ambient parent; `appendChild` is the explicit reparent — the door to
|
|
89
|
+
* placing a lazily-created node into an existing group.
|
|
90
|
+
*/
|
|
91
|
+
export declare const appendChild: (parent: Runner.GroupInstance, child: Instance.Instance) => Effect.Effect<void, never, Runner.Runner>;
|
|
92
|
+
/** Detach `child` from `parent` (no-op unless it is currently its child). */
|
|
93
|
+
export declare const removeChild: (parent: Runner.GroupInstance, child: Instance.Instance) => Effect.Effect<void, never, Runner.Runner>;
|
|
94
|
+
export declare const settings: () => Effect.Effect<{
|
|
95
|
+
frameRate: number;
|
|
96
|
+
width: number;
|
|
97
|
+
height: number;
|
|
98
|
+
backgroundColor: string;
|
|
99
|
+
seed: Runner.Seed;
|
|
100
|
+
maxFrames: number;
|
|
101
|
+
}, never, Runner.Runner>;
|
|
102
|
+
/**
|
|
103
|
+
* The active camera instance — an ordinary instance carrying `~position`
|
|
104
|
+
* (x/y pan) and a `zoom` field, so the existing animators drive it:
|
|
105
|
+
* `Scene.make(function* () { const cam = yield* Scene.camera; yield*
|
|
106
|
+
* cam.pipe(Motion.moveTo({ x: 400 })) })`. A default identity camera is
|
|
107
|
+
* always present; animate it directly, or `Scene.setCamera` to swap in
|
|
108
|
+
* another instance. The camera is never drawn.
|
|
109
|
+
*/
|
|
110
|
+
export declare const camera: Effect.Effect<Instance.Instance<"Camera", Schema.Struct<{
|
|
111
|
+
x: Schema.withConstructorDefault<Schema.Number>;
|
|
112
|
+
y: Schema.withConstructorDefault<Schema.Number>;
|
|
113
|
+
zoom: Schema.withConstructorDefault<Schema.Number>;
|
|
114
|
+
}>, {
|
|
115
|
+
readonly "~position": {
|
|
116
|
+
get: (data: Schema.Struct.ReadonlySide<{
|
|
117
|
+
x: Schema.withConstructorDefault<Schema.Number>;
|
|
118
|
+
y: Schema.withConstructorDefault<Schema.Number>;
|
|
119
|
+
zoom: Schema.withConstructorDefault<Schema.Number>;
|
|
120
|
+
}, "Type">) => {
|
|
121
|
+
x: number;
|
|
122
|
+
y: number;
|
|
123
|
+
};
|
|
124
|
+
set: (data: Schema.Struct.ReadonlySide<{
|
|
125
|
+
x: Schema.withConstructorDefault<Schema.Number>;
|
|
126
|
+
y: Schema.withConstructorDefault<Schema.Number>;
|
|
127
|
+
zoom: Schema.withConstructorDefault<Schema.Number>;
|
|
128
|
+
}, "Type">, value: Entity.Position) => Schema.Struct.ReadonlySide<{
|
|
129
|
+
x: Schema.withConstructorDefault<Schema.Number>;
|
|
130
|
+
y: Schema.withConstructorDefault<Schema.Number>;
|
|
131
|
+
zoom: Schema.withConstructorDefault<Schema.Number>;
|
|
132
|
+
}, "Type">;
|
|
133
|
+
};
|
|
134
|
+
}>, never, Runner.Runner>;
|
|
135
|
+
/** Swap the active camera to `instance`; its live data becomes the view. */
|
|
136
|
+
export declare const setCamera: (instance: Instance.Instance) => Effect.Effect<void, never, Runner.Runner>;
|
|
137
|
+
/**
|
|
138
|
+
* Handle to a branch of animation (a fork, background, or played scene).
|
|
139
|
+
* `finished` resolves at the branch's SEMANTIC end — `Scene.finish` or
|
|
140
|
+
* completion, whichever comes first. Awaiting it from scene code HOLDS
|
|
141
|
+
* the scene (the waiter keeps ticking frames, like `Scene.sleep`), so
|
|
142
|
+
* the rest of the scene stays live while you wait. `fiber` is the
|
|
143
|
+
* branch's physical execution — interrupt it to bound a tail.
|
|
144
|
+
*/
|
|
145
|
+
export interface BranchHandle<A = unknown, E = unknown> {
|
|
146
|
+
readonly finished: Effect.Effect<void, never, Runner.Runner>;
|
|
147
|
+
readonly fiber: Fiber.Fiber<A, E>;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Finish the innermost enclosing branch (the current fork, played scene,
|
|
151
|
+
* or the scene body itself): whoever awaits the branch's `finished`
|
|
152
|
+
* proceeds, the branch stops blocking its parent's end, and the code
|
|
153
|
+
* after `finish` keeps running as a TAIL — bounded by the parent, which
|
|
154
|
+
* interrupts it at scene end like a background. Idempotent; completion
|
|
155
|
+
* implies finish. NOTE: a failure in the tail (after finish) is NOT
|
|
156
|
+
* reported — by then nothing is listening.
|
|
157
|
+
*/
|
|
158
|
+
export declare const finish: Effect.Effect<undefined, never, never>;
|
|
159
|
+
/**
|
|
160
|
+
* Run `effect`, then repeat it as long as `schedule` recurs, with the
|
|
161
|
+
* schedule evaluated in scene time (frames at the runner's frame rate) —
|
|
162
|
+
* `Effect.repeat`'s sibling, but paced by frames instead of the wall
|
|
163
|
+
* clock. The first run is immediate; the schedule paces the gaps after
|
|
164
|
+
* runs; each run's result is fed to the schedule as input. Resolves with
|
|
165
|
+
* the schedule's final output once it is done; a failed run fails
|
|
166
|
+
* immediately without consulting the schedule again.
|
|
167
|
+
*/
|
|
168
|
+
export declare const repeat: <A, E, R, Output, ScheduleE, ScheduleR>(effect: Effect.Effect<A, E, R>, schedule: Schedule.Schedule<Output, A, ScheduleE, ScheduleR>) => Effect.Effect<Output, E | ScheduleE, R | ScheduleR | Runner.Runner>;
|
|
169
|
+
/**
|
|
170
|
+
* Run `effect` concurrently with the rest of the scene, sharing frame
|
|
171
|
+
* phases, and return its fiber immediately.
|
|
172
|
+
*
|
|
173
|
+
* NOTE: this inverts Effect's own `fork` semantics — the scene's end
|
|
174
|
+
* WAITS for forked work. A scene whose body returns while forks are
|
|
175
|
+
* still animating keeps producing frames until the last fork finishes
|
|
176
|
+
* (so a scene containing only a fork still plays). Use
|
|
177
|
+
* {@link background} for work that should be cut off at scene end
|
|
178
|
+
* instead. Forks are supervised by the fiber that spawned them: a fork
|
|
179
|
+
* made inside another fork is interrupted when its spawner completes.
|
|
180
|
+
*/
|
|
181
|
+
export declare const fork: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<BranchHandle<A, E>, never, Runner.Runner | Exclude<Exclude<R, never>, Phaser.Phaser>>;
|
|
182
|
+
/**
|
|
183
|
+
* Like {@link fork}, but the fiber is INTERRUPTED at scene end instead
|
|
184
|
+
* of awaited — for indefinite work (`Scene.repeat(…, Schedule.forever)`)
|
|
185
|
+
* that should play for the duration of the scene without keeping it
|
|
186
|
+
* alive. "Scene end" includes the fork drain: backgrounds keep animating
|
|
187
|
+
* while awaited forks finish, and are stopped after the last one.
|
|
188
|
+
*/
|
|
189
|
+
export declare const background: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<BranchHandle<A, E>, never, Runner.Runner | Exclude<Exclude<R, never>, Phaser.Phaser>>;
|
|
190
|
+
export interface PlayOptions {
|
|
191
|
+
/** group to mount the scene's instances under (default: the root) */
|
|
192
|
+
readonly parent?: Runner.GroupInstance;
|
|
193
|
+
/** seed for this evaluation (default: the movie's seed) */
|
|
194
|
+
readonly seed?: Runner.Seed;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Play a scene as a branch of the current scene — the explicit door to
|
|
198
|
+
* nesting. The child shares the movie's runner, phaser, frame rate, and
|
|
199
|
+
* frame cap, and gets its own scope, branch handle, mount parent, and a
|
|
200
|
+
* FRESH seeded Random stream: `play(scene)` inside a movie seeded `S`
|
|
201
|
+
* animates exactly like `run(scene, { seed: S })` standalone. Awaited
|
|
202
|
+
* like a fork — `yield* handle.finished` for sequential nesting, or
|
|
203
|
+
* don't await for concurrent scenes.
|
|
204
|
+
*/
|
|
205
|
+
export declare const play: <E, R, Entities>(scene: Scene<E, R, Entities>, options?: PlayOptions) => Effect.Effect<BranchHandle<void, E>, never, Runner.Runner | Exclude<R, Scope.Scope>>;
|
|
206
|
+
/**
|
|
207
|
+
* Run effects in lockstep parallel, sharing frame phases — the public
|
|
208
|
+
* counterpart to the low-level `Phaser.all`. Takes no schedule: pacing a
|
|
209
|
+
* list sequentially belongs to {@link chain}, overlapping staggered
|
|
210
|
+
* starts to {@link stagger}.
|
|
211
|
+
*/
|
|
212
|
+
export declare const all: typeof Phaser.all;
|
|
213
|
+
/**
|
|
214
|
+
* Run items one at a time, in order — items NEVER overlap, mirroring
|
|
215
|
+
* Effect's guarantee for scheduled effects. The first item runs
|
|
216
|
+
* immediately; after each item completes, `schedule` is stepped once
|
|
217
|
+
* (with the item's result as input) to pace the next start. `fixed`
|
|
218
|
+
* gives a start cadence with catch-up, `spaced` gives rests between
|
|
219
|
+
* items. When the schedule ends early, the remaining items are skipped —
|
|
220
|
+
* it is the release policy, including how many. Without a schedule,
|
|
221
|
+
* plain sequential composition. Resolves with how many items completed.
|
|
222
|
+
* For overlapping runs, reach for {@link stagger} or {@link fork}
|
|
223
|
+
* explicitly.
|
|
224
|
+
*/
|
|
225
|
+
export declare const chain: <Eff extends Effect.Effect<any, any, any>, ScheduleE = never, ScheduleR = never>(effects: Iterable<Eff>, schedule?: Schedule.Schedule<unknown, Eff extends Effect.Effect<infer A, any, any> ? A : never, ScheduleE, ScheduleR>) => Effect.Effect<{
|
|
226
|
+
completed: number;
|
|
227
|
+
}, (Eff extends Effect.Effect<any, infer E, any> ? E : never) | ScheduleE, (Eff extends Effect.Effect<any, any, infer R> ? R : never) | Runner.Runner | ScheduleR>;
|
|
228
|
+
/**
|
|
229
|
+
* Release effects on `schedule` with OVERLAP: the first starts
|
|
230
|
+
* immediately, each next one on the schedule's next emission, and
|
|
231
|
+
* released effects run concurrently — semantically
|
|
232
|
+
* `chain(effects.map(Scene.fork))`, but resolving when all released
|
|
233
|
+
* effects finish rather than at the last release. When the schedule ends
|
|
234
|
+
* early, the remaining effects are skipped. Overlap is this
|
|
235
|
+
* combinator's purpose; the schedule-paced default ({@link chain})
|
|
236
|
+
* never overlaps.
|
|
237
|
+
*/
|
|
238
|
+
export declare const stagger: <Eff extends Effect.Effect<any, any, any>, ScheduleE = never, ScheduleR = never>(effects: Iterable<Eff>, schedule: Schedule.Schedule<unknown, void, ScheduleE, ScheduleR>) => Effect.Effect<{
|
|
239
|
+
released: number;
|
|
240
|
+
}, (Eff extends Effect.Effect<any, infer E, any> ? E : never) | ScheduleE, (Eff extends Effect.Effect<any, any, infer R> ? R : never) | Phaser.Phaser | Runner.Runner | ScheduleR>;
|
|
241
|
+
export {};
|