@lute-lang/player-web 0.0.0-stage → 0.41.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.
Files changed (63) hide show
  1. package/README.md +50 -2
  2. package/dist/assets/pixiAssets.d.ts +47 -0
  3. package/dist/assets/pixiAssetsBackend.d.ts +3 -0
  4. package/dist/audio/pixiAudio.d.ts +77 -0
  5. package/dist/audio/pixiSoundBackend.d.ts +3 -0
  6. package/dist/choice/choiceMenu.d.ts +56 -0
  7. package/dist/effects/catalogue.d.ts +55 -0
  8. package/dist/engine/app.d.ts +14 -0
  9. package/dist/engine/behaviours.d.ts +35 -0
  10. package/dist/engine/easing.d.ts +24 -0
  11. package/dist/engine/types.d.ts +70 -0
  12. package/dist/engine/world.d.ts +10 -0
  13. package/dist/index.d.ts +4 -0
  14. package/dist/index.js +3409 -0
  15. package/dist/input/gamepad.d.ts +22 -0
  16. package/dist/input/index.d.ts +7 -0
  17. package/dist/input/map.d.ts +42 -0
  18. package/dist/mount.d.ts +31 -0
  19. package/dist/presenter/index.d.ts +1 -0
  20. package/dist/presenter/pixiPresenter.d.ts +75 -0
  21. package/dist/scene/actor.d.ts +26 -0
  22. package/dist/scene/background.d.ts +24 -0
  23. package/dist/scene/camera.d.ts +37 -0
  24. package/dist/scene/cgLayer.d.ts +21 -0
  25. package/dist/scene/index.d.ts +7 -0
  26. package/dist/scene/shared.d.ts +36 -0
  27. package/dist/scene/vfx.d.ts +14 -0
  28. package/dist/scene/videoLayer.d.ts +21 -0
  29. package/dist/text/dialogueWindow.d.ts +52 -0
  30. package/dist/text/richText.d.ts +37 -0
  31. package/dist/text/segments.d.ts +31 -0
  32. package/dist/theme.d.ts +7 -0
  33. package/dist/ui/index.d.ts +3 -0
  34. package/dist/ui/screens/backlog-screen.d.ts +1 -0
  35. package/dist/ui/screens/backlog.d.ts +25 -0
  36. package/dist/ui/screens/common.d.ts +68 -0
  37. package/dist/ui/screens/confirm.d.ts +1 -0
  38. package/dist/ui/screens/ended.d.ts +1 -0
  39. package/dist/ui/screens/halted.d.ts +1 -0
  40. package/dist/ui/screens/hud.d.ts +1 -0
  41. package/dist/ui/screens/idle.d.ts +1 -0
  42. package/dist/ui/screens/index.d.ts +4 -0
  43. package/dist/ui/screens/loading.d.ts +1 -0
  44. package/dist/ui/screens/menu.d.ts +1 -0
  45. package/dist/ui/screens/save-load-screen.d.ts +1 -0
  46. package/dist/ui/screens/save-load.d.ts +14 -0
  47. package/dist/ui/screens/settings-screen.d.ts +1 -0
  48. package/dist/ui/screens/settings.d.ts +13 -0
  49. package/dist/ui/screens/title.d.ts +1 -0
  50. package/dist/ui/ui.d.ts +65 -0
  51. package/dist/ui/widgets/base.d.ts +54 -0
  52. package/dist/ui/widgets/button.d.ts +15 -0
  53. package/dist/ui/widgets/controls.d.ts +47 -0
  54. package/dist/ui/widgets/focus-manager.d.ts +1 -0
  55. package/dist/ui/widgets/index.d.ts +4 -0
  56. package/dist/ui/widgets/label.d.ts +1 -0
  57. package/dist/ui/widgets/list.d.ts +50 -0
  58. package/dist/ui/widgets/panel.d.ts +1 -0
  59. package/dist/ui/widgets/scroll-list.d.ts +1 -0
  60. package/dist/ui/widgets/segmented.d.ts +1 -0
  61. package/dist/ui/widgets/slider.d.ts +1 -0
  62. package/dist/ui/widgets/toggle.d.ts +1 -0
  63. package/package.json +48 -4
package/README.md CHANGED
@@ -1,3 +1,51 @@
1
- # Temporary Holding Version
1
+ # @lute-lang/player-web
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ The Lute 0.41 browser visual-novel player. It supplies PixiJS 8 rendering, Web Audio, screens, and keyboard/mouse/touch/gamepad input for the renderer-free `@lute-lang/player` core.
4
+
5
+ ## Install
6
+
7
+ ```sh
8
+ bun add @lute-lang/player-web@0.41.0 @lute-lang/player@0.41.0 @lute-lang/runtime@0.41.0 effect@4.0.2 @effect/platform-browser@4.0.2 pixi.js@8.22.0 @pixi/sound@6.0.1
9
+ # npm install @lute-lang/player-web@0.41.0 @lute-lang/player@0.41.0 @lute-lang/runtime@0.41.0 effect@4.0.2 @effect/platform-browser@4.0.2 pixi.js@8.22.0 @pixi/sound@6.0.1
10
+ ```
11
+
12
+ The package requires exact `effect@4.0.2` and `@effect/platform-browser@4.0.2` peers. Runtime and player packages are released in lockstep.
13
+
14
+ ## Minimal usage
15
+
16
+ Serve a `lute compile --all` bundle, the runtime wasm file, the bindings file, and its assets. Then mount into an element:
17
+
18
+ ```ts
19
+ import { mountPlayer } from "@lute-lang/player-web"
20
+
21
+ const player = await mountPlayer(document.querySelector("#player")!, {
22
+ bindings: { url: "/player.bindings.yaml" },
23
+ bundleUrl: "/bundle/",
24
+ wasmUrl: "/wasm/lute_runtime_wasm_bg.wasm",
25
+ assetsUrl: "/assets/",
26
+ storageKey: "my-game"
27
+ })
28
+
29
+ await player.act({ type: "newGame" })
30
+ const view = await player.view()
31
+ // Later:
32
+ await player.unmount()
33
+ ```
34
+
35
+ `bindings` accepts a decoded `Bindings` object, YAML text, or `{ url }`. `assetsUrl` overrides the file's `assetsBase`; `host` is the core's `PlayerHost`: `bridge` handlers return a `BridgeAnswer` (`{ fields, writes? }`), `plugin` handlers run as waiting cues, and `idle` answers idle waits. `mountPlayer` returns Promise methods `act`, `view`, and `unmount`. The Effect-native `LuteWeb.mount` is available when the application already manages an Effect scope; its handle is the core's `LutePlayerHandle` (`actions`, `view`, `send`, `restore`, `shutdown`, plus the runtime `session` and its `program`).
36
+
37
+ ## Cue handling
38
+
39
+ - **Names.** The dialogue name plate and backlog rows show `speakerName`, the cast display name from the bundle index (`cast: { id: name }`); name colours stay keyed by the speaker id.
40
+ - **Music.** `PixiAudio` honours `AudioPlay.restart`: `restart: true` plays the file from its start; without it, the music file already playing only changes volume, fading over `fade`, and a different file crossfades.
41
+ - **Custom vfx.** A `StageCue.Vfx` whose `effect.effect` is `"custom"` (a project vfx bound as `{ effect: custom }`, or a vfx type with no binding) has no Pixi effect: the presenter plays nothing and logs `effect.name` once at debug level (`PresenterOptions.debug`, default `console.debug`). Render project effects with your own `Presenter`.
42
+
43
+ ## API and guides
44
+
45
+ - [Web architecture](../../docs/player/web-architecture.md)
46
+ - [Getting started](/player/getting-started/)
47
+ - [Controls](/player/controls/)
48
+ - [Bindings reference](/player/bindings/)
49
+ - [Demo game](../../examples/player-demo/)
50
+
51
+ Source and releases: [github.com/journeyWorker/lute](https://github.com/journeyWorker/lute).
@@ -0,0 +1,47 @@
1
+ import { Texture } from "pixi.js";
2
+ import { Effect, Scope, Stream } from "effect";
3
+ import { AssetMissing, type AssetLoader } from "@lute-lang/player";
4
+ /** Backend seam for PixiAssets; tests can use an in-memory loader. */
5
+ export interface AssetBackend {
6
+ readonly loadTexture: (url: string) => Effect.Effect<Texture, unknown>;
7
+ readonly unloadTexture: (url: string, texture: Texture) => Effect.Effect<void, never>;
8
+ readonly loadAudio: (url: string) => Effect.Effect<void, unknown>;
9
+ readonly unloadAudio: (url: string) => Effect.Effect<void, never>;
10
+ }
11
+ /** Constructor options for {@link PixiAssets}. */
12
+ export interface PixiAssetsOptions {
13
+ readonly assetsBase?: string;
14
+ readonly backend: AssetBackend;
15
+ readonly concurrency?: number;
16
+ readonly graceSeconds?: number;
17
+ }
18
+ /**
19
+ * Pixi-backed, scoped and ref-counted AssetLoader. A scope that calls ensure owns
20
+ * one reference to every requested file; the references are released by its finalizer.
21
+ */
22
+ export declare class PixiAssets implements AssetLoader {
23
+ readonly progress: Stream.Stream<number>;
24
+ private readonly backend;
25
+ private readonly base;
26
+ private readonly maxConcurrency;
27
+ private readonly graceSeconds;
28
+ private readonly progressRef;
29
+ private readonly records;
30
+ private readonly unloadFibers;
31
+ constructor(options: PixiAssetsOptions);
32
+ /** Ensure all files are loaded and retain them until the caller's scope closes. */
33
+ readonly ensure: (files: ReadonlyArray<string>) => Effect.Effect<void, AssetMissing, Scope.Scope>;
34
+ /** Return a loaded image/video texture, or undefined before ensure. */
35
+ readonly texture: (file: string) => Texture | undefined;
36
+ /** Return a loaded video texture, or undefined before ensure. */
37
+ readonly video: (file: string) => Texture | undefined;
38
+ private readonly acquire;
39
+ private readonly release;
40
+ private readonly unload;
41
+ }
42
+ /**
43
+ * Collect binding-referenced files in stable insertion order. Dynamic keys such
44
+ * as effect names, colours, labels and flow occasions are intentionally ignored.
45
+ * Voice patterns are deliberately excluded because they are generated per line.
46
+ */
47
+ export declare const assetsFromBindings: (bindings: unknown) => ReadonlyArray<string>;
@@ -0,0 +1,3 @@
1
+ import type { AssetBackend } from "./pixiAssets.js";
2
+ /** Real Pixi/@pixi-sound asset backend used by the browser player. */
3
+ export declare const pixiAssetsBackend: AssetBackend;
@@ -0,0 +1,77 @@
1
+ import { Effect, SubscriptionRef } from "effect";
2
+ import type { AudioChannel, AudioPlay, AudioPort, Volumes } from "@lute-lang/player";
3
+ /** A typed failure raised by the sound backend while decoding or starting media. */
4
+ export declare class AudioDecodeError extends Error {
5
+ readonly file: string;
6
+ readonly _tag = "AudioDecodeError";
7
+ constructor(file: string, cause: unknown);
8
+ }
9
+ /** The playback object required by {@link PixiAudio}; useful for deterministic unit tests. */
10
+ export interface AudioPlayback {
11
+ readonly setVolume: (volume: number) => void;
12
+ readonly stop: () => void;
13
+ readonly ended: Effect.Effect<void>;
14
+ }
15
+ /** Backend seam for PixiAudio. The default implementation delegates to @pixi/sound. */
16
+ export interface AudioBackend {
17
+ readonly load: (file: string) => Effect.Effect<void, AudioDecodeError>;
18
+ readonly play: (file: string, options: {
19
+ readonly loop: boolean;
20
+ readonly volume: number;
21
+ }) => Effect.Effect<AudioPlayback, AudioDecodeError>;
22
+ readonly unlock: Effect.Effect<void, AudioDecodeError>;
23
+ }
24
+ /** Constructor options for {@link PixiAudio}. */
25
+ export interface PixiAudioOptions {
26
+ readonly backend: AudioBackend;
27
+ readonly logger?: (message: string, error?: unknown) => void;
28
+ readonly initialVolumes?: Volumes;
29
+ }
30
+ /**
31
+ * PixiJS/@pixi-sound implementation of the player AudioPort.
32
+ *
33
+ * Playback is deliberately best-effort: an absent optional file is logged and does
34
+ * not stop the story. Fade jobs run in detached Effect fibers so superseding a
35
+ * channel interrupts the old Clock-driven fade without interrupting the caller.
36
+ */
37
+ export declare class PixiAudio implements AudioPort {
38
+ readonly unlocked: SubscriptionRef.SubscriptionRef<boolean>;
39
+ readonly unlock: Effect.Effect<void, AudioDecodeError>;
40
+ private readonly backend;
41
+ private readonly logger;
42
+ private readonly active;
43
+ private currentVolumes;
44
+ private readonly gate;
45
+ constructor(options: PixiAudioOptions);
46
+ /**
47
+ * Play a channel sound, waiting for finite sounds to end. Music without
48
+ * `restart` whose file is the one already playing only changes its volume,
49
+ * fading over `fade`, without restarting it (spec 0.41.0 §7.7).
50
+ */
51
+ readonly play: (channel: AudioChannel, soundToPlay: AudioPlay) => Effect.Effect<void>;
52
+ /** Fade and stop every playback currently in a channel. */
53
+ readonly stop: (channel: AudioChannel, fade: number) => Effect.Effect<void>;
54
+ /** Set master/channel gains and apply them immediately to every active instance. */
55
+ readonly setVolumes: (volumes: Volumes) => Effect.Effect<void>;
56
+ private effectiveVolume;
57
+ private removeRecord;
58
+ private readonly interruptFade;
59
+ private applyVolume;
60
+ /** Fade `record`'s live factor to `to` over `duration` seconds, starting from wherever it is now. */
61
+ private readonly startFade;
62
+ /**
63
+ * Step `record` through `advance(progress)` over `duration` seconds on a
64
+ * detached fiber, applying its volume after each step.
65
+ */
66
+ private readonly ramp;
67
+ /**
68
+ * Move a playing record to a new input volume, fading over `fade` seconds
69
+ * from its current level (finishing an interrupted fade-in); it keeps playing.
70
+ */
71
+ private readonly changeVolume;
72
+ private readonly fadeOutAndStop;
73
+ private readonly stopVoiceImmediately;
74
+ private readonly replaceMusic;
75
+ }
76
+ /** Construct a PixiAudio from an injected backend. */
77
+ export declare const makePixiAudio: (options: PixiAudioOptions) => PixiAudio;
@@ -0,0 +1,3 @@
1
+ import { type AudioBackend } from "./pixiAudio.js";
2
+ /** Real @pixi/sound backend used by the browser player. */
3
+ export declare const pixiSoundBackend: AudioBackend;
@@ -0,0 +1,56 @@
1
+ import { Effect, Stream } from "effect";
2
+ import { Container } from "pixi.js";
3
+ import type { ChoiceView } from "@lute-lang/player";
4
+ import type { Theme } from "../engine/types.js";
5
+ /** A menu option with the runtime's visibility verdict and authored display text. */
6
+ export interface ChoiceOption {
7
+ readonly id: string;
8
+ readonly verdict: string;
9
+ readonly text?: string;
10
+ readonly once?: boolean;
11
+ readonly exit?: boolean;
12
+ }
13
+ type ChoiceInput = ChoiceView;
14
+ /** Whether a runtime verdict leaves an option selectable. */
15
+ export declare const isChoiceEnabled: (verdict: string) => boolean;
16
+ /** Immutable keyboard/pointer navigation state. */
17
+ export interface ChoiceNavigationState {
18
+ readonly ids: ReadonlyArray<string>;
19
+ readonly enabled: ReadonlyArray<boolean>;
20
+ readonly focused: number;
21
+ }
22
+ /** Creates navigation state, selecting the first enabled option. */
23
+ export declare const choiceNavigation: (options: ReadonlyArray<ChoiceOption>) => ChoiceNavigationState;
24
+ /** Applies a navigation key or a one-based digit to a menu state. */
25
+ export declare const navigateChoice: (state: ChoiceNavigationState, key: "up" | "down" | "enter" | string) => ChoiceNavigationState | string | undefined;
26
+ /** A vertical, keyboard and pointer accessible choice menu. */
27
+ export declare class ChoiceMenu {
28
+ readonly target: Container;
29
+ private readonly theme;
30
+ private readonly panel;
31
+ private readonly prompt;
32
+ private readonly optionsLayer;
33
+ private readonly countdown;
34
+ private readonly rendered;
35
+ private navigation;
36
+ private deferred;
37
+ private resolveChoice;
38
+ private maxRemaining;
39
+ private remainingValue;
40
+ private pulsePhase;
41
+ constructor(parent: Container, theme: Theme);
42
+ /** Shows a menu and resolves with the selected option id. */
43
+ show: (choice: ChoiceInput, remaining: Stream.Stream<number>) => Effect.Effect<string>;
44
+ /** Hides the menu and removes all option children. */
45
+ readonly hide: Effect.Effect<void>;
46
+ /** Updates the countdown from a test or host without consuming a stream. */
47
+ readonly setRemaining: (seconds: number) => void;
48
+ /** Advances the countdown pulse by seconds; called by a ticker if desired. */
49
+ readonly tick: (dt: number) => void;
50
+ private readonly keydown;
51
+ private pointerAt;
52
+ private renderOptions;
53
+ private updateFocus;
54
+ private drawCountdown;
55
+ }
56
+ export {};
@@ -0,0 +1,55 @@
1
+ import { Effect, Schema } from "effect";
2
+ import { Container } from "pixi.js";
3
+ import type { Behaviour } from "../engine/types.js";
4
+ /**
5
+ * Names in the player effect catalogue. `custom` (a project vfx, spec 0.41.0
6
+ * §7.7) is not one: the presenter handles it before reaching the catalogue.
7
+ */
8
+ export type EffectName = "fade" | "dissolve" | "wipeLeft" | "wipeRight" | "wipeUp" | "wipeDown" | "slideLeft" | "slideRight" | "cut" | "fadeIn" | "fadeOut" | "slideIn" | "slideOut" | "hop" | "shake" | "none" | "zoom" | "pan" | "flash" | "blur" | "tint";
9
+ /** Values accepted in a binding effect parameter object. */
10
+ export type EffectParams = Readonly<Record<string, number | string | boolean>>;
11
+ /** Optional scene context needed by camera and full-screen effects. */
12
+ export interface EffectContext {
13
+ readonly design?: {
14
+ readonly width: number;
15
+ readonly height: number;
16
+ };
17
+ readonly overlay?: Container;
18
+ readonly camera?: Container;
19
+ }
20
+ declare const EffectDecodeError_base: Schema.Class<EffectDecodeError, Schema.TaggedStruct<"EffectDecodeError", {
21
+ readonly effect: Schema.String;
22
+ readonly parameter: Schema.String;
23
+ readonly message: Schema.String;
24
+ }>, import("effect/Cause").YieldableError>;
25
+ /** Typed decoding failure for an effect name, parameter name, or parameter value. */
26
+ export declare class EffectDecodeError extends EffectDecodeError_base {
27
+ }
28
+ declare const UnknownEffect_base: Schema.Class<UnknownEffect, Schema.TaggedStruct<"UnknownEffect", {
29
+ readonly name: Schema.String;
30
+ }>, import("effect/Cause").YieldableError>;
31
+ /** Compatibility error for callers that distinguish unknown names. */
32
+ export declare class UnknownEffect extends UnknownEffect_base {
33
+ }
34
+ declare const UnknownEffectParameter_base: Schema.Class<UnknownEffectParameter, Schema.TaggedStruct<"UnknownEffectParameter", {
35
+ readonly effect: Schema.String;
36
+ readonly parameter: Schema.String;
37
+ }>, import("effect/Cause").YieldableError>;
38
+ /** Compatibility error for callers that distinguish unknown parameters. */
39
+ export declare class UnknownEffectParameter extends UnknownEffectParameter_base {
40
+ }
41
+ declare const InvalidEffectParameter_base: Schema.Class<InvalidEffectParameter, Schema.TaggedStruct<"InvalidEffectParameter", {
42
+ readonly effect: Schema.String;
43
+ readonly parameter: Schema.String;
44
+ readonly message: Schema.String;
45
+ }>, import("effect/Cause").YieldableError>;
46
+ /** Compatibility error for callers that distinguish malformed parameter values. */
47
+ export declare class InvalidEffectParameter extends InvalidEffectParameter_base {
48
+ }
49
+ /** Build behaviours for one catalogue effect, returning typed decoding failures. */
50
+ export declare const build: (name: string, target: Container, params?: EffectParams, duration?: number, ctx?: EffectContext) => Effect.Effect<ReadonlyArray<Behaviour>, EffectDecodeError>;
51
+ /** Catalogue facade for callers that prefer an object. */
52
+ export declare const EffectCatalogue: {
53
+ build: typeof build;
54
+ };
55
+ export {};
@@ -0,0 +1,14 @@
1
+ import { Context, Layer } from "effect";
2
+ import type { PixiAppShape } from "./types.js";
3
+ /** Design resolution used to lay out the stage. */
4
+ export interface DesignSize {
5
+ readonly width: number;
6
+ readonly height: number;
7
+ }
8
+ declare const PixiApp_base: Context.ServiceClass<PixiApp, "Lute.Web.PixiApp", PixiAppShape>;
9
+ /** Scoped PixiJS application and stage graph. */
10
+ export declare class PixiApp extends PixiApp_base {
11
+ /** Initialize an application and attach its canvas to `element`. */
12
+ static layer: (element: HTMLElement, design: DesignSize, background?: number) => Layer.Layer<PixiApp, unknown>;
13
+ }
14
+ export {};
@@ -0,0 +1,35 @@
1
+ import { Container } from "pixi.js";
2
+ import type { Behaviour } from "./types.js";
3
+ import type { Easing } from "./easing.js";
4
+ /** Properties supported by a tween. */
5
+ export interface TweenProps {
6
+ readonly x?: number;
7
+ readonly y?: number;
8
+ readonly alpha?: number;
9
+ readonly scaleX?: number;
10
+ readonly scaleY?: number;
11
+ readonly rotation?: number;
12
+ readonly tint?: number;
13
+ }
14
+ /** Wipe direction. */
15
+ export type WipeDirection = "left" | "right" | "up" | "down";
16
+ /** Create a pooled property tween. */
17
+ export declare const tween: (target: Container, props: TweenProps, to: TweenProps, duration: number, easing?: Easing) => Behaviour;
18
+ /** Create a pooled alpha tween. */
19
+ export declare const fade: (target: Container, to: number, duration: number) => Behaviour;
20
+ /** Crossfade two containers over a duration. */
21
+ export declare const crossfade: (from: Container, to: Container, duration: number) => Behaviour;
22
+ /** Shake a container around its original position. */
23
+ export declare const shake: (target: Container, strength: number, duration: number, frequency?: number) => Behaviour;
24
+ /** Lift a container in a single hop and return it to its baseline. */
25
+ export declare const hop: (target: Container, height: number, duration: number) => Behaviour;
26
+ /** Slide a container from one x coordinate to another. */
27
+ export declare const slide: (target: Container, fromX: number, toX: number, duration: number) => Behaviour;
28
+ /** Reveal or conceal a target with a reusable Graphics mask. */
29
+ export declare const wipe: (target: Container, direction: WipeDirection, duration: number, reveal?: boolean) => Behaviour;
30
+ /** Flash an overlay container and then hide it. */
31
+ export declare const flash: (overlay: Container, colour: number, duration: number) => Behaviour;
32
+ /** Pulse a target forever until cancelled. */
33
+ export declare const pulse: (target: Container, scale: number, period: number) => Behaviour;
34
+ /** Create a pooled timer behaviour. */
35
+ export declare const delay: (seconds: number) => Behaviour;
@@ -0,0 +1,24 @@
1
+ /** Easing functions used by the pooled scene behaviours. */
2
+ export type Easing = (progress: number) => number;
3
+ /** Linear interpolation progress. */
4
+ export declare const linear: Easing;
5
+ /** Quadratic ease in. */
6
+ export declare const quadIn: Easing;
7
+ /** Quadratic ease out. */
8
+ export declare const quadOut: Easing;
9
+ /** Quadratic ease in and out. */
10
+ export declare const quadInOut: Easing;
11
+ /** Cubic ease in. */
12
+ export declare const cubicIn: Easing;
13
+ /** Cubic ease out. */
14
+ export declare const cubicOut: Easing;
15
+ /** Cubic ease in and out. */
16
+ export declare const cubicInOut: Easing;
17
+ /** Sine ease in and out. */
18
+ export declare const sineInOut: Easing;
19
+ /** Back ease out. */
20
+ export declare const backOut: Easing;
21
+ /** Elastic ease out. */
22
+ export declare const elasticOut: Easing;
23
+ /** Named easing lookup used by bindings and tests. */
24
+ export declare const easings: Readonly<Record<string, Easing>>;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Shared engine contracts of the web player (docs/player/web-architecture.md):
3
+ * the Pixi application service, the scene layers, and the entity–behaviour
4
+ * model every module builds on.
5
+ */
6
+ import type { Context, Deferred, Effect, Stream } from "effect";
7
+ import type { Application, Container } from "pixi.js";
8
+ /** Fixed scene layers, back to front. `camera` holds the actors and is what framing/moves transform. */
9
+ export interface Layers {
10
+ readonly background: Container;
11
+ readonly cg: Container;
12
+ readonly camera: Container;
13
+ readonly actors: Container;
14
+ readonly video: Container;
15
+ readonly dialogue: Container;
16
+ readonly choice: Container;
17
+ readonly overlay: Container;
18
+ readonly transition: Container;
19
+ }
20
+ /** The Pixi application as a scoped service (initialized with WebGL, destroyed on scope close). */
21
+ export interface PixiAppShape {
22
+ readonly app: Application;
23
+ readonly layers: Layers;
24
+ /** Design resolution from `bindings.canvas`; the stage is letterboxed into the element. */
25
+ readonly design: {
26
+ readonly width: number;
27
+ readonly height: number;
28
+ };
29
+ /** Seconds elapsed per tick. */
30
+ readonly frames: Stream.Stream<number>;
31
+ }
32
+ export type PixiAppTag = Context.Service<PixiAppShape, PixiAppShape>;
33
+ /**
34
+ * A unit of per-frame behaviour attached to an entity (tween, fade, shake,
35
+ * typewriter, …). `update` advances by `dt` seconds and reports whether it
36
+ * is finished; `finish` jumps to the end state. `done` is completed by the
37
+ * world when the behaviour ends either way.
38
+ */
39
+ export interface Behaviour {
40
+ readonly update: (dt: number) => "running" | "done";
41
+ readonly finish: () => void;
42
+ /** Release resources (masks, filters) after the behaviour ended. */
43
+ readonly dispose: () => void;
44
+ }
45
+ /** Owns every running behaviour; stepped once per frame by the ticker. */
46
+ export interface WorldShape {
47
+ /** Run `behaviour` on `target`; completes when it finished (or was finished by `finishAll`). */
48
+ readonly run: (target: Container, behaviour: Behaviour) => Effect.Effect<void>;
49
+ /** Finish every behaviour on `target` (or all) at once. */
50
+ readonly finishAll: (target?: Container) => Effect.Effect<void>;
51
+ /** Cancel behaviours on `target` without finishing them (e.g. superseded tweens). */
52
+ readonly cancel: (target: Container) => Effect.Effect<void>;
53
+ /** Number of running behaviours (tests, debug overlay). */
54
+ readonly size: Effect.Effect<number>;
55
+ }
56
+ /** A running behaviour's completion signal, as stored by the world. */
57
+ export interface Running {
58
+ readonly target: Container;
59
+ readonly behaviour: Behaviour;
60
+ readonly done: Deferred.Deferred<void>;
61
+ }
62
+ /** UI theme derived from `bindings.ui` (colours as 0xRRGGBB numbers). */
63
+ export interface Theme {
64
+ readonly font: string;
65
+ readonly text: number;
66
+ readonly accent: number;
67
+ readonly panel: number;
68
+ readonly panelAlpha: number;
69
+ readonly readText: number;
70
+ }
@@ -0,0 +1,10 @@
1
+ import { Context, Layer } from "effect";
2
+ import type { WorldShape } from "./types.js";
3
+ import { PixiApp } from "./app.js";
4
+ declare const World_base: Context.ServiceClass<World, "Lute.Web.World", WorldShape>;
5
+ /** The scene behaviour scheduler. */
6
+ export declare class World extends World_base {
7
+ /** Build a world and run it from the Pixi application ticker. */
8
+ static readonly layer: Layer.Layer<World, never, PixiApp>;
9
+ }
10
+ export {};
@@ -0,0 +1,4 @@
1
+ /** Browser visual-novel player built on PixiJS and Effect. */
2
+ export * from "./mount.js";
3
+ export { themeFromBindings, parseColour, defaultTheme } from "./theme.js";
4
+ export { Input } from "./input/index.js";