narraleaf-react 0.19.2 → 0.20.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/dist/built-in.d.ts +1 -1
- package/dist/game/nlcore/action/actionTypes.d.ts +13 -0
- package/dist/game/nlcore/action/actions/puppetAction.d.ts +59 -0
- package/dist/game/nlcore/action/logicAction.d.ts +15 -13
- package/dist/game/nlcore/common/elements.d.ts +4 -1
- package/dist/game/nlcore/elements/built-in/DevTools.d.ts +53 -0
- package/dist/game/nlcore/elements/built-in/screenEffects.d.ts +2 -2
- package/dist/game/nlcore/elements/camera.d.ts +3 -0
- package/dist/game/nlcore/elements/character/pause.d.ts +1 -1
- package/dist/game/nlcore/elements/character.d.ts +3 -0
- package/dist/game/nlcore/elements/condition.d.ts +13 -0
- package/dist/game/nlcore/elements/control.d.ts +29 -24
- package/dist/game/nlcore/elements/displayable/image.d.ts +4 -0
- package/dist/game/nlcore/elements/displayable/puppet.d.ts +230 -0
- package/dist/game/nlcore/elements/displayable/text.d.ts +4 -0
- package/dist/game/nlcore/elements/layer.d.ts +4 -0
- package/dist/game/nlcore/elements/persistent/serialize.d.ts +1 -0
- package/dist/game/nlcore/elements/persistent/storable.d.ts +11 -0
- package/dist/game/nlcore/elements/persistent/type.d.ts +51 -2
- package/dist/game/nlcore/elements/persistent.d.ts +12 -3
- package/dist/game/nlcore/elements/scene.d.ts +3 -0
- package/dist/game/nlcore/elements/script.d.ts +1 -0
- package/dist/game/nlcore/elements/sound.d.ts +3 -0
- package/dist/game/nlcore/elements/story.d.ts +1 -0
- package/dist/game/nlcore/elements/transform/position.d.ts +46 -0
- package/dist/game/nlcore/elements/vfx.d.ts +14 -5
- package/dist/game/nlcore/elements/video.d.ts +15 -7
- package/dist/game/nlcore/game/liveGame.d.ts +47 -0
- package/dist/game/nlcore/game/puppet/puppetBackend.d.ts +247 -0
- package/dist/game/nlcore/game.d.ts +43 -0
- package/dist/game/player/elements/displayable/Puppet.d.ts +1 -0
- package/dist/game/player/elements/displayable/type.d.ts +2 -1
- package/dist/game/player/elements/image/AspectScaleImage.d.ts +8 -0
- package/dist/game/player/elements/image/Image.d.ts +6 -0
- package/dist/game/player/gameState.d.ts +5 -0
- package/dist/game/player/gameState.type.d.ts +21 -1
- package/dist/game/player/type.d.ts +11 -1
- package/dist/main.js +52 -43
- package/package.json +3 -2
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import type { TransformDefinitions } from "../../elements/transform/type";
|
|
2
|
+
import { Displayable } from "../../elements/displayable/displayable";
|
|
3
|
+
import { EventfulDisplayable } from "../../../player/elements/displayable/type";
|
|
4
|
+
import { Chained, Proxied } from "../../action/chain";
|
|
5
|
+
import { LogicAction } from "../../action/logicAction";
|
|
6
|
+
import { Layer } from "../../elements/layer";
|
|
7
|
+
import type { LiveGameEventToken } from "../../types";
|
|
8
|
+
import type { PuppetSize, PuppetStatus } from "../../game/puppet/puppetBackend";
|
|
9
|
+
export type PuppetConfig = {
|
|
10
|
+
backend: string;
|
|
11
|
+
src: string;
|
|
12
|
+
options: Record<string, unknown>;
|
|
13
|
+
size: PuppetSize | null;
|
|
14
|
+
className?: string;
|
|
15
|
+
layer: Layer | undefined;
|
|
16
|
+
};
|
|
17
|
+
export interface IPuppetUserConfig extends TransformDefinitions.ImageTransformProps {
|
|
18
|
+
/**
|
|
19
|
+
* Name of the registered backend that draws this puppet.
|
|
20
|
+
*
|
|
21
|
+
* See {@link import("../../game").Game.registerPuppetBackend}.
|
|
22
|
+
*/
|
|
23
|
+
backend: string;
|
|
24
|
+
/**
|
|
25
|
+
* The resource descriptor handed to the backend, passed through verbatim.
|
|
26
|
+
*
|
|
27
|
+
* **A puppet cannot change its `src`.** The backend's instance lives for as long as the element
|
|
28
|
+
* is on stage, and swapping the model underneath it would mean tearing that instance down while
|
|
29
|
+
* the engine's box, transform and saved state stay put. Use a second element instead.
|
|
30
|
+
*/
|
|
31
|
+
src: string;
|
|
32
|
+
/** Backend-specific options, passed through verbatim. */
|
|
33
|
+
options: Record<string, unknown>;
|
|
34
|
+
/**
|
|
35
|
+
* The logical size of the box, in pixels. Defaults to the stage size.
|
|
36
|
+
*
|
|
37
|
+
* The backend scales its own content inside the box; the element's transform (position, zoom,
|
|
38
|
+
* scale, rotation) applies on top of it, exactly as it would to an image.
|
|
39
|
+
*/
|
|
40
|
+
size: PuppetSize | null;
|
|
41
|
+
/**
|
|
42
|
+
* Class names for the box, applied to the element the transition wrapper renders — the one
|
|
43
|
+
* carrying the box's `position: relative` and its width and height.
|
|
44
|
+
*
|
|
45
|
+
* That is the **parent** of the container handed to
|
|
46
|
+
* {@link import("../../game/puppet/puppetBackend").PuppetBackend.mount}, not the container
|
|
47
|
+
* itself: the backend owns the inside of the box and the engine empties it on dispose, so
|
|
48
|
+
* anything styled here has to sit outside it. Note also that the wrapper above it — the one the
|
|
49
|
+
* transform is written to — is not this element, so a class that sets `transform` here will be
|
|
50
|
+
* overwritten frame by frame.
|
|
51
|
+
*/
|
|
52
|
+
className?: string;
|
|
53
|
+
/** Layer of the puppet. */
|
|
54
|
+
layer?: Layer;
|
|
55
|
+
/** Initial motion. Part of the saved state, so it survives a save/load round trip. */
|
|
56
|
+
motion: string | null;
|
|
57
|
+
/** Initial expression. */
|
|
58
|
+
expression: string | null;
|
|
59
|
+
/** Initial skin. */
|
|
60
|
+
skin: string | null;
|
|
61
|
+
/** Initial numeric parameters. */
|
|
62
|
+
params: Record<string, number>;
|
|
63
|
+
/** Initial string slots. */
|
|
64
|
+
slots: Record<string, string | null>;
|
|
65
|
+
}
|
|
66
|
+
/** How the story treats a one-shot {@link Puppet.command}. */
|
|
67
|
+
export type PuppetCommandOptions = {
|
|
68
|
+
/**
|
|
69
|
+
* Wait for the backend to finish the command before the story moves on.
|
|
70
|
+
*
|
|
71
|
+
* Off by default. The engine cannot tell a motion worth a beat from a parameter nudge, and a
|
|
72
|
+
* backend that never resolves would otherwise park the story forever; opting in makes the wait
|
|
73
|
+
* the author's decision, and only where they meant it. A waiting command is skippable like any
|
|
74
|
+
* other timed action.
|
|
75
|
+
*
|
|
76
|
+
* @default false
|
|
77
|
+
*/
|
|
78
|
+
await?: boolean;
|
|
79
|
+
};
|
|
80
|
+
export type PuppetDataRaw = {
|
|
81
|
+
state: Record<string, any>;
|
|
82
|
+
transformState: Record<string, any>;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* A displayable whose interior is drawn by a backend the host registered.
|
|
86
|
+
*
|
|
87
|
+
* The engine gives a puppet everything a displayable has — a position on a layer, a transform, an
|
|
88
|
+
* opacity, an entry in the saved game — and nothing else. What appears inside its box is decided
|
|
89
|
+
* entirely by {@link import("../../game/puppet/puppetBackend").PuppetBackend}, which the engine
|
|
90
|
+
* neither ships nor understands.
|
|
91
|
+
*
|
|
92
|
+
* When no backend answers to `config.backend`, the element degrades quietly: it keeps its place,
|
|
93
|
+
* its transform and its state, warns once, and draws nothing.
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```ts
|
|
97
|
+
* const alice = new Puppet({
|
|
98
|
+
* backend: "my-renderer",
|
|
99
|
+
* src: "models/alice/alice.model.json",
|
|
100
|
+
* size: {width: 900, height: 1200},
|
|
101
|
+
* position: {xalign: 0.3},
|
|
102
|
+
* });
|
|
103
|
+
*
|
|
104
|
+
* scene.action([
|
|
105
|
+
* alice.show({duration: 400}),
|
|
106
|
+
* alice.setMotion("idle"),
|
|
107
|
+
* alice.setExpression("smile"),
|
|
108
|
+
* alice.command("playMotion", {id: "wave"}, {await: true}),
|
|
109
|
+
* ]);
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
export declare class Puppet extends Displayable<PuppetDataRaw, Puppet, TransformDefinitions.ImageTransformProps> implements EventfulDisplayable {
|
|
113
|
+
constructor(config: Partial<IPuppetUserConfig> & {
|
|
114
|
+
backend: string;
|
|
115
|
+
src: string;
|
|
116
|
+
});
|
|
117
|
+
/**
|
|
118
|
+
* Request a named motion — usually the loop the model settles into.
|
|
119
|
+
*
|
|
120
|
+
* This is persistent state, not a one-shot: it is saved, and re-applied in full the next time
|
|
121
|
+
* the model mounts. Pass `null` to clear it. A motion meant to play once and end belongs in
|
|
122
|
+
* {@link Puppet.command}.
|
|
123
|
+
*
|
|
124
|
+
* The story does not wait for the backend to take the pose.
|
|
125
|
+
* @chainable
|
|
126
|
+
* @example
|
|
127
|
+
* ```ts
|
|
128
|
+
* alice.setMotion("idle");
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
setMotion(motion: string | null): Proxied<Puppet, Chained<LogicAction.Actions>>;
|
|
132
|
+
/**
|
|
133
|
+
* Request a named expression, or `null` to clear it. Persistent state, like the motion.
|
|
134
|
+
* @chainable
|
|
135
|
+
* @example
|
|
136
|
+
* ```ts
|
|
137
|
+
* alice.setExpression("smile");
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
setExpression(expression: string | null): Proxied<Puppet, Chained<LogicAction.Actions>>;
|
|
141
|
+
/**
|
|
142
|
+
* Request a named skin or costume, or `null` to clear it. Persistent state, like the motion.
|
|
143
|
+
* @chainable
|
|
144
|
+
* @example
|
|
145
|
+
* ```ts
|
|
146
|
+
* alice.setSkin("winter");
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
setSkin(skin: string | null): Proxied<Puppet, Chained<LogicAction.Actions>>;
|
|
150
|
+
/**
|
|
151
|
+
* Set one numeric parameter, leaving every other parameter as it stands.
|
|
152
|
+
*
|
|
153
|
+
* What an id means is the backend's business — a rig parameter, a bone override, a blend weight.
|
|
154
|
+
* The engine only remembers it, saves it, and hands the whole map back on a load.
|
|
155
|
+
* @chainable
|
|
156
|
+
* @example
|
|
157
|
+
* ```ts
|
|
158
|
+
* alice.setParam("ParamAngleX", 12);
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
161
|
+
setParam(id: string, value: number): Proxied<Puppet, Chained<LogicAction.Actions>>;
|
|
162
|
+
/**
|
|
163
|
+
* Set one free string slot, leaving every other slot as it stands. `null` clears that slot.
|
|
164
|
+
*
|
|
165
|
+
* Slots are for the named things `motion` / `expression` / `skin` do not cover — an attachment
|
|
166
|
+
* point, a swapped-in prop, whatever a particular renderer calls its own.
|
|
167
|
+
* @chainable
|
|
168
|
+
* @example
|
|
169
|
+
* ```ts
|
|
170
|
+
* alice.setSlot("prop", "umbrella");
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
setSlot(id: string, value: string | null): Proxied<Puppet, Chained<LogicAction.Actions>>;
|
|
174
|
+
/**
|
|
175
|
+
* Send the backend a command the engine neither models nor interprets.
|
|
176
|
+
*
|
|
177
|
+
* `name` and `payload` are forwarded verbatim. This is the escape hatch for everything
|
|
178
|
+
* {@link import("../../game/puppet/puppetBackend").PuppetState} deliberately leaves out — a
|
|
179
|
+
* motion that plays once and ends, a hit test, lip sync. None of it is saved, so a command is
|
|
180
|
+
* not restored by a load and not taken back by an undo; anything that has to survive either
|
|
181
|
+
* belongs in the state, through the `set*` methods above.
|
|
182
|
+
*
|
|
183
|
+
* **The story does not wait unless it is asked to.** See {@link PuppetCommandOptions}.
|
|
184
|
+
* @chainable
|
|
185
|
+
* @example
|
|
186
|
+
* ```ts
|
|
187
|
+
* alice.command("playMotion", {id: "wave"}); // the story moves straight on
|
|
188
|
+
* alice.command("playMotion", {id: "bow"}, {await: true}); // ...and here it waits for it
|
|
189
|
+
* ```
|
|
190
|
+
*/
|
|
191
|
+
command(name: string, payload?: unknown, options?: PuppetCommandOptions): Proxied<Puppet, Chained<LogicAction.Actions>>;
|
|
192
|
+
/**
|
|
193
|
+
* What the backend drawing this puppet is currently doing.
|
|
194
|
+
*
|
|
195
|
+
* Two of the five are worth acting on. `"missing-backend"` means nothing answers to
|
|
196
|
+
* `config.backend`, and `"error"` means the backend threw or the model failed to load; in both
|
|
197
|
+
* cases the element is still on stage, still transforming and still saving — it is simply not
|
|
198
|
+
* being drawn. The engine cannot decide what that should mean for a game, so it reports rather
|
|
199
|
+
* than intervenes.
|
|
200
|
+
*
|
|
201
|
+
* The status describes the live instance and is not part of the saved game: a load re-mounts,
|
|
202
|
+
* and the status starts over from `"unmounted"`.
|
|
203
|
+
* @example
|
|
204
|
+
* ```ts
|
|
205
|
+
* if (alice.getStatus() === "missing-backend") {
|
|
206
|
+
* // the renderer this project depends on was never registered
|
|
207
|
+
* }
|
|
208
|
+
* ```
|
|
209
|
+
*/
|
|
210
|
+
getStatus(): PuppetStatus;
|
|
211
|
+
/**
|
|
212
|
+
* Listen for this puppet's status changing, receiving the new status.
|
|
213
|
+
*
|
|
214
|
+
* A backend fails asynchronously — the element mounts, then the model does or does not load — so
|
|
215
|
+
* {@link Puppet.getStatus} alone cannot answer "did my renderer come up". Subscribe to be told.
|
|
216
|
+
* Dispose the returned token to stop listening.
|
|
217
|
+
* @example
|
|
218
|
+
* ```ts
|
|
219
|
+
* const token = alice.onStatusChange((status) => {
|
|
220
|
+
* if (status === "error") console.warn("Alice is not being drawn");
|
|
221
|
+
* });
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
224
|
+
onStatusChange(listener: (status: PuppetStatus) => void): LiveGameEventToken;
|
|
225
|
+
/**
|
|
226
|
+
* Override the layer used to render this puppet.
|
|
227
|
+
* @param layer - The layer to assign to the puppet.
|
|
228
|
+
*/
|
|
229
|
+
useLayer(layer: Layer): this;
|
|
230
|
+
}
|
|
@@ -49,6 +49,10 @@ export interface ITextUserConfig extends TransformDefinitions.TextTransformProps
|
|
|
49
49
|
*/
|
|
50
50
|
layer?: Layer;
|
|
51
51
|
}
|
|
52
|
+
export type TextDataRaw = {
|
|
53
|
+
state: Record<string, any>;
|
|
54
|
+
transformState: Record<string, any>;
|
|
55
|
+
};
|
|
52
56
|
export declare class Text extends Displayable<TextDataRaw, Text, TransformDefinitions.TextTransformProps> implements EventfulDisplayable {
|
|
53
57
|
constructor(config: Partial<ITextUserConfig>);
|
|
54
58
|
constructor(text: string, config?: Partial<ITextUserConfig>);
|
|
@@ -13,6 +13,10 @@ export interface ILayerUserConfig extends TransformDefinitions.ImageTransformPro
|
|
|
13
13
|
*/
|
|
14
14
|
zIndex: number;
|
|
15
15
|
}
|
|
16
|
+
export type LayerDataRaw = {
|
|
17
|
+
state: Record<string, any>;
|
|
18
|
+
transformState: Record<string, any>;
|
|
19
|
+
};
|
|
16
20
|
export declare class Layer extends Displayable<LayerDataRaw, Layer, TransformDefinitions.ImageTransformProps> implements EventfulDisplayable {
|
|
17
21
|
/**
|
|
18
22
|
* Create a layer that can host displayables.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -26,7 +26,18 @@ export type StorableRestore = {
|
|
|
26
26
|
/** The namespace keys whose contents were replaced. */
|
|
27
27
|
namespaces: string[];
|
|
28
28
|
};
|
|
29
|
+
export type StorableEvents = {
|
|
30
|
+
"event:storable.change": [StorableChange];
|
|
31
|
+
"event:storable.restore": [StorableRestore];
|
|
32
|
+
};
|
|
29
33
|
export declare class Namespace<T extends NameSpaceContent<keyof T>> {
|
|
34
|
+
/**
|
|
35
|
+
* Whether a value can be written to a save.
|
|
36
|
+
*
|
|
37
|
+
* Plain objects and arrays may nest freely; the leaves have to be a primitive, `null`,
|
|
38
|
+
* `undefined` or a `Date`. A value that refers back to itself, or one that nests past 64
|
|
39
|
+
* levels, is not serializable — both report `false` rather than recursing forever.
|
|
40
|
+
*/
|
|
30
41
|
static isSerializable(value: any): boolean;
|
|
31
42
|
name: string;
|
|
32
43
|
constructor(name: string, initContent: T, key?: string);
|
|
@@ -1,10 +1,52 @@
|
|
|
1
1
|
export type StorableData<K extends string = string> = {
|
|
2
2
|
[key in K]: number | boolean | string | StorableData | StorableData[] | undefined | null | Date;
|
|
3
3
|
};
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* A value that stands on its own, with nothing inside it: a JSON primitive, or a `Date`.
|
|
6
|
+
*/
|
|
7
|
+
export type BaseStorableType = number | boolean | string | undefined | null | Date;
|
|
8
|
+
export type BaseStorableTypeName = "any" | "date";
|
|
9
|
+
/**
|
|
10
|
+
* Anything a namespace can hold.
|
|
11
|
+
*
|
|
12
|
+
* Plain objects and arrays nest freely — `{party: [{name: "yuko", metAt: new Date()}]}` is a
|
|
13
|
+
* single stored value, and a `Date` buried anywhere inside it comes back as a `Date`. Only the
|
|
14
|
+
* leaves are constrained, to {@link BaseStorableType}: a save file is JSON, and a class
|
|
15
|
+
* instance, a `Map`, a function or a symbol has no representation in it.
|
|
16
|
+
*
|
|
17
|
+
* Two limits are enforced when the value is written to a save rather than when it is assigned,
|
|
18
|
+
* because that is when they start to matter:
|
|
19
|
+
*
|
|
20
|
+
* - nesting is capped at 64 levels;
|
|
21
|
+
* - a value that refers back to itself is rejected outright. A save is a tree; a cycle has no
|
|
22
|
+
* place in one, and cutting the back-edge would silently save a different object graph than
|
|
23
|
+
* the one the author built.
|
|
24
|
+
*
|
|
25
|
+
* Reference identity is not part of the value. Storing the same object at two positions saves
|
|
26
|
+
* two copies, and loading produces two independent objects — the same bargain `JSON.stringify`
|
|
27
|
+
* makes.
|
|
28
|
+
*/
|
|
29
|
+
export type StorableType = BaseStorableType | {
|
|
30
|
+
[key: string]: StorableType;
|
|
31
|
+
} | StorableType[];
|
|
32
|
+
/**
|
|
33
|
+
* A position inside a stored value: the property keys walked from its root. `[]` is the value
|
|
34
|
+
* itself, `["party", 0, "metAt"]` is the `metAt` of the first element of `party`.
|
|
35
|
+
*
|
|
36
|
+
* Array indices are written as numbers and object keys as strings, but both are read back with
|
|
37
|
+
* plain property access, so the distinction is presentational.
|
|
38
|
+
*/
|
|
39
|
+
export type StorablePath = (string | number)[];
|
|
5
40
|
/**
|
|
6
41
|
* A single stored value as it appears in a saved game. Values are tagged on the way out so
|
|
7
|
-
* that types JSON cannot express (currently `Date`) survive the
|
|
42
|
+
* that types JSON cannot express (currently `Date`, and a nested `undefined`) survive the
|
|
43
|
+
* round-trip.
|
|
44
|
+
*
|
|
45
|
+
* `data` is plain JSON. The two types JSON loses are not encoded in-band — no sentinel object
|
|
46
|
+
* is inserted that a stored value could collide with — but named by position in `dates` and
|
|
47
|
+
* `undefineds`, which the loader walks to put the real values back. Both are absent when there
|
|
48
|
+
* is nothing to name, so a value holding neither serializes exactly as it did before this
|
|
49
|
+
* scheme existed, and a save written before it loads unchanged.
|
|
8
50
|
*
|
|
9
51
|
* This is part of the on-disk save format rather than an implementation detail: it is what
|
|
10
52
|
* {@link SavedGame}'s `store` actually contains. Read it through `Namespace`, never by hand.
|
|
@@ -12,6 +54,10 @@ export type StorableType = BaseStorableType | Record<string, BaseStorableType> |
|
|
|
12
54
|
export type WrappedStorableData<T extends StorableType = any> = {
|
|
13
55
|
type: BaseStorableTypeName;
|
|
14
56
|
data: T;
|
|
57
|
+
/** Positions in `data` that held a `Date`, stored as an ISO 8601 string. */
|
|
58
|
+
dates?: StorablePath[];
|
|
59
|
+
/** Positions in `data` that held `undefined`, stored as `null`. */
|
|
60
|
+
undefineds?: StorablePath[];
|
|
15
61
|
};
|
|
16
62
|
/**
|
|
17
63
|
* One namespace's contents in a saved game: every value wrapped by {@link WrappedStorableData}.
|
|
@@ -19,3 +65,6 @@ export type WrappedStorableData<T extends StorableType = any> = {
|
|
|
19
65
|
export type SerializedNamespaceData = {
|
|
20
66
|
[key: string]: WrappedStorableData;
|
|
21
67
|
};
|
|
68
|
+
export type NameSpaceContent<T extends string | number | symbol> = {
|
|
69
|
+
[K in T]?: StorableType;
|
|
70
|
+
};
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import { Actionable } from "../action/actionable";
|
|
2
|
+
import { StorableType } from "../elements/persistent/type";
|
|
3
|
+
import { Chained, Proxied } from "../action/chain";
|
|
4
|
+
import { LogicAction } from "../game";
|
|
2
5
|
import { BooleanValueKeyOf, StringKeyOf } from "../../../util/data";
|
|
3
6
|
import { Lambda } from "../elements/condition";
|
|
4
7
|
import { Word } from "../elements/character/word";
|
|
5
8
|
import { DynamicWord, DynamicWordResult } from "../elements/character/sentence";
|
|
6
9
|
import { LambdaHandler } from "../elements/type";
|
|
10
|
+
export type PersistentContent = {
|
|
11
|
+
[K in string]: StorableType;
|
|
12
|
+
};
|
|
13
|
+
export type DynamicPersistentData = {
|
|
14
|
+
[K in string]: StorableType;
|
|
15
|
+
};
|
|
7
16
|
export declare class Persistent<T extends PersistentContent> extends Actionable<null> {
|
|
8
17
|
constructor(namespace: string, defaultContent: T);
|
|
9
18
|
/**
|
|
@@ -13,15 +22,15 @@ export declare class Persistent<T extends PersistentContent> extends Actionable<
|
|
|
13
22
|
* @param value - The value to set
|
|
14
23
|
* @returns A chainable persistent action
|
|
15
24
|
*/
|
|
16
|
-
set<K extends StringKeyOf<T>>(key: K, value: T[K]):
|
|
17
|
-
set<K extends StringKeyOf<T>>(key: K, handler: (value: T[K]) => T[K]):
|
|
25
|
+
set<K extends StringKeyOf<T>>(key: K, value: T[K]): Proxied<Persistent<T>, Chained<LogicAction.Actions>>;
|
|
26
|
+
set<K extends StringKeyOf<T>>(key: K, handler: (value: T[K]) => T[K]): Proxied<Persistent<T>, Chained<LogicAction.Actions>>;
|
|
18
27
|
/**
|
|
19
28
|
* Create an action to assign a value to the persistent storage
|
|
20
29
|
* @chainable
|
|
21
30
|
* @param value - The value to assign
|
|
22
31
|
* @returns A chainable persistent action
|
|
23
32
|
*/
|
|
24
|
-
assign(value: Partial<T> | ((value: T) => Partial<T>)):
|
|
33
|
+
assign(value: Partial<T> | ((value: T) => Partial<T>)): Proxied<Persistent<T>, Chained<LogicAction.Actions>>;
|
|
25
34
|
/**
|
|
26
35
|
* Determine whether the values are equal, can be used in {@link Condition}
|
|
27
36
|
* @example
|
|
@@ -37,6 +37,9 @@ export type JumpConfig = {
|
|
|
37
37
|
};
|
|
38
38
|
type ChainableAction = Proxied<LogicAction.GameElement, Chained<LogicAction.Actions>> | LogicAction.Actions;
|
|
39
39
|
type ChainedScene = Proxied<Scene, Chained<LogicAction.Actions>>;
|
|
40
|
+
export type SceneDataRaw = {
|
|
41
|
+
state: Record<string, any>;
|
|
42
|
+
};
|
|
40
43
|
export declare class Scene extends Constructable<LogicAction.Actions, Scene> {
|
|
41
44
|
get local(): Persistent<any>;
|
|
42
45
|
get background(): Image;
|
|
@@ -15,6 +15,7 @@ export interface ScriptCtx {
|
|
|
15
15
|
$: NamespaceGetter;
|
|
16
16
|
}
|
|
17
17
|
type ScriptRun = (ctx: ScriptCtx) => ScriptCleaner | void;
|
|
18
|
+
export type ScriptCleaner = () => void;
|
|
18
19
|
export declare class Script extends Actionable<object> {
|
|
19
20
|
/**
|
|
20
21
|
* Create a script action from a handler.
|
|
@@ -7,6 +7,9 @@ export declare enum SoundType {
|
|
|
7
7
|
Bgm = "bgm",
|
|
8
8
|
Sound = "sound"
|
|
9
9
|
}
|
|
10
|
+
export type SoundDataRaw = {
|
|
11
|
+
state: Record<string, any>;
|
|
12
|
+
};
|
|
10
13
|
export type VoiceIdMap = Record<string | number, string | Sound>;
|
|
11
14
|
export type VoiceSrcGenerator = (id: string | number) => string | Sound;
|
|
12
15
|
export interface ISoundUserConfig {
|
|
@@ -18,6 +18,7 @@ export interface IStoryConfig {
|
|
|
18
18
|
*/
|
|
19
19
|
camera?: Camera;
|
|
20
20
|
}
|
|
21
|
+
export type ElementStateRaw = Record<string, any>;
|
|
21
22
|
export declare class Story extends Constructable<SceneAction<"scene:action">, Story> {
|
|
22
23
|
constructor(name: string, config?: Partial<IStoryConfig>);
|
|
23
24
|
/**
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CSSProps } from "../../elements/transition/type";
|
|
1
2
|
export declare enum CommonPositionType {
|
|
2
3
|
Left = "left",
|
|
3
4
|
Center = "center",
|
|
@@ -19,6 +20,12 @@ export type OffsetPosition = {
|
|
|
19
20
|
xoffset: number;
|
|
20
21
|
yoffset: number;
|
|
21
22
|
};
|
|
23
|
+
export type D2Position<X = any, Y = any> = {
|
|
24
|
+
x: UnknownAble<X>;
|
|
25
|
+
y: UnknownAble<Y>;
|
|
26
|
+
xoffset: UnknownAble<number>;
|
|
27
|
+
yoffset: UnknownAble<number>;
|
|
28
|
+
};
|
|
22
29
|
export type RawPosition = CommonPositionType | (Partial<Coord2DPosition> & {
|
|
23
30
|
xalign?: never;
|
|
24
31
|
yalign?: never;
|
|
@@ -28,6 +35,45 @@ export type RawPosition = CommonPositionType | (Partial<Coord2DPosition> & {
|
|
|
28
35
|
});
|
|
29
36
|
type Unknown = typeof PositionUtils.Unknown;
|
|
30
37
|
type UnknownAble<T> = T | Unknown;
|
|
38
|
+
export declare class PositionUtils {
|
|
39
|
+
static readonly Unknown: unique symbol;
|
|
40
|
+
static isUnknown(arg: any): arg is typeof PositionUtils.Unknown;
|
|
41
|
+
static D2PositionToCSS(pos: D2Position, invertX?: boolean, invertY?: boolean, dimensions?: {
|
|
42
|
+
width: number;
|
|
43
|
+
height: number;
|
|
44
|
+
}): CSSProps;
|
|
45
|
+
/**
|
|
46
|
+
* Resolve a position component (base position + pixel offset) to a CSS length.
|
|
47
|
+
*
|
|
48
|
+
* When the design {@link dimension} (the game's base width or height for this axis) is
|
|
49
|
+
* known, the base position and its offset are folded into a single percentage of that
|
|
50
|
+
* dimension. This keeps offsets resolution-independent — they scale with the stage just
|
|
51
|
+
* like sizes do — and lets `motion` interpolate the result: a mixed `calc(% + px)` value
|
|
52
|
+
* cannot be animated on its percentage part, so the offset would otherwise be the only
|
|
53
|
+
* animatable piece and any align change would be silently dropped.
|
|
54
|
+
*
|
|
55
|
+
* Without a dimension it falls back to the legacy `calc(<pos> + <offset>px)` form.
|
|
56
|
+
*/
|
|
57
|
+
static calc(pos: number | string, offset?: UnknownAble<number>, dimension?: number): string;
|
|
58
|
+
/**
|
|
59
|
+
* Express a position component as a percentage of the given design dimension.
|
|
60
|
+
* Accepts an existing percentage string (e.g. `"50%"`) or a pixel number, and returns
|
|
61
|
+
* `null` for any other form so the caller can fall back to the legacy representation.
|
|
62
|
+
*/
|
|
63
|
+
static toPercent(pos: number | string, dimension: number): number | null;
|
|
64
|
+
static toCoord2D(pos: IPosition | D2Position): Coord2D;
|
|
65
|
+
static orUnknown<T>(arg: T | UnknownAble<T> | undefined): T | Unknown;
|
|
66
|
+
static mergePosition(a: IPosition, b: IPosition): Coord2D;
|
|
67
|
+
static serializePosition(pos: IPosition): D2Position;
|
|
68
|
+
static isRawCommonPositionType(arg: any): arg is CommonPositionType;
|
|
69
|
+
static isRawCoord2DPosition(arg: any): arg is Partial<Coord2DPosition>;
|
|
70
|
+
static isRawAlignPosition(arg: any): arg is Partial<AlignPosition>;
|
|
71
|
+
static isRawPosition(arg: any): arg is RawPosition;
|
|
72
|
+
static isPosition(arg: any): arg is IPosition;
|
|
73
|
+
static rawPositionToCoord2D(arg: any): Coord2D;
|
|
74
|
+
static tryParsePosition(arg: any): IPosition;
|
|
75
|
+
static wrap(def: CSSProps): CSSProps;
|
|
76
|
+
}
|
|
31
77
|
export declare class CommonPosition implements IPosition {
|
|
32
78
|
static Positions: typeof CommonPositionType;
|
|
33
79
|
static isCommonPositionType(arg: any): arg is CommonPosition;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { Actionable } from "../action/actionable";
|
|
2
|
+
import { Chained, Proxied } from "../action/chain";
|
|
3
|
+
import { LogicAction } from "../game";
|
|
2
4
|
import type { TransformDefinitions } from "../elements/transform/type";
|
|
3
5
|
/**
|
|
4
6
|
* How the overlay video is composited onto the stage.
|
|
@@ -25,6 +27,13 @@ export type VfxFadeOptions = {
|
|
|
25
27
|
duration?: number;
|
|
26
28
|
easing?: TransformDefinitions.EasingDefinition;
|
|
27
29
|
};
|
|
30
|
+
export type VfxState = {
|
|
31
|
+
display: boolean;
|
|
32
|
+
paused: boolean;
|
|
33
|
+
};
|
|
34
|
+
export type VfxStateRaw = {
|
|
35
|
+
state: VfxState;
|
|
36
|
+
};
|
|
28
37
|
/**
|
|
29
38
|
* A full-screen looping video overlay for particle and ambience effects
|
|
30
39
|
* (falling petals, light dust, rain, snow, fog, light flares).
|
|
@@ -55,7 +64,7 @@ export declare class Vfx extends Actionable<VfxStateRaw> {
|
|
|
55
64
|
* already shown is idempotent (the fade-in is re-applied).
|
|
56
65
|
* @chainable
|
|
57
66
|
*/
|
|
58
|
-
show(options?: VfxFadeOptions):
|
|
67
|
+
show(options?: VfxFadeOptions): Proxied<Vfx, Chained<LogicAction.Actions>>;
|
|
59
68
|
/**
|
|
60
69
|
* Fade the overlay out, then stop playback and remove it from the stage.
|
|
61
70
|
*
|
|
@@ -63,17 +72,17 @@ export declare class Vfx extends Actionable<VfxStateRaw> {
|
|
|
63
72
|
* not shown is a no-op (a weak warning is logged).
|
|
64
73
|
* @chainable
|
|
65
74
|
*/
|
|
66
|
-
hide(options?: VfxFadeOptions):
|
|
75
|
+
hide(options?: VfxFadeOptions): Proxied<Vfx, Chained<LogicAction.Actions>>;
|
|
67
76
|
/**
|
|
68
77
|
* Freeze the overlay on its current frame.
|
|
69
78
|
* @chainable
|
|
70
79
|
*/
|
|
71
|
-
pause():
|
|
80
|
+
pause(): Proxied<Vfx, Chained<LogicAction.Actions>>;
|
|
72
81
|
/**
|
|
73
82
|
* Continue playback from the current frame.
|
|
74
83
|
* @chainable
|
|
75
84
|
*/
|
|
76
|
-
resume():
|
|
85
|
+
resume(): Proxied<Vfx, Chained<LogicAction.Actions>>;
|
|
77
86
|
/**
|
|
78
87
|
* Adjust the playback speed (e.g. `0.5` for slow drifting).
|
|
79
88
|
*
|
|
@@ -81,5 +90,5 @@ export declare class Vfx extends Actionable<VfxStateRaw> {
|
|
|
81
90
|
* returns to `config.playbackRate`.
|
|
82
91
|
* @chainable
|
|
83
92
|
*/
|
|
84
|
-
setPlaybackRate(rate: number):
|
|
93
|
+
setPlaybackRate(rate: number): Proxied<Vfx, Chained<LogicAction.Actions>>;
|
|
85
94
|
}
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { Actionable } from "../action/actionable";
|
|
2
|
+
import { Chained, Proxied } from "../action/chain";
|
|
3
|
+
import { LogicAction } from "../game";
|
|
2
4
|
export type VideoConfig = {
|
|
3
5
|
src: string;
|
|
4
6
|
muted: boolean;
|
|
5
7
|
};
|
|
8
|
+
export type VideoState = {
|
|
9
|
+
display: boolean;
|
|
10
|
+
};
|
|
11
|
+
export type VideoStateRaw = {
|
|
12
|
+
state: VideoState;
|
|
13
|
+
};
|
|
6
14
|
export declare class Video extends Actionable<VideoStateRaw> {
|
|
7
15
|
/**
|
|
8
16
|
* Create a video element with source and optional mute flag.
|
|
@@ -17,12 +25,12 @@ export declare class Video extends Actionable<VideoStateRaw> {
|
|
|
17
25
|
* Show the video element.
|
|
18
26
|
* @chainable
|
|
19
27
|
*/
|
|
20
|
-
show():
|
|
28
|
+
show(): Proxied<Video, Chained<LogicAction.Actions>>;
|
|
21
29
|
/**
|
|
22
30
|
* Hide the video element.
|
|
23
31
|
* @chainable
|
|
24
32
|
*/
|
|
25
|
-
hide():
|
|
33
|
+
hide(): Proxied<Video, Chained<LogicAction.Actions>>;
|
|
26
34
|
/**
|
|
27
35
|
* Play the video and wait until it finishes.
|
|
28
36
|
* @chainable
|
|
@@ -31,24 +39,24 @@ export declare class Video extends Actionable<VideoStateRaw> {
|
|
|
31
39
|
* video.play();
|
|
32
40
|
* ```
|
|
33
41
|
*/
|
|
34
|
-
play():
|
|
42
|
+
play(): Proxied<Video, Chained<LogicAction.Actions>>;
|
|
35
43
|
/**
|
|
36
44
|
* Pause the video, keeping its current position.
|
|
37
45
|
* @chainable
|
|
38
46
|
*/
|
|
39
|
-
pause():
|
|
47
|
+
pause(): Proxied<Video, Chained<LogicAction.Actions>>;
|
|
40
48
|
/**
|
|
41
49
|
* Resume playback from the current position.
|
|
42
50
|
*
|
|
43
51
|
* Unlike {@link play}, this does not wait for the video to finish.
|
|
44
52
|
* @chainable
|
|
45
53
|
*/
|
|
46
|
-
resume():
|
|
54
|
+
resume(): Proxied<Video, Chained<LogicAction.Actions>>;
|
|
47
55
|
/**
|
|
48
56
|
* Stop the video: pause it and end any pending {@link play} so the story continues.
|
|
49
57
|
* @chainable
|
|
50
58
|
*/
|
|
51
|
-
stop():
|
|
59
|
+
stop(): Proxied<Video, Chained<LogicAction.Actions>>;
|
|
52
60
|
/**
|
|
53
61
|
* Seek to a specific time (in seconds).
|
|
54
62
|
* @chainable
|
|
@@ -57,5 +65,5 @@ export declare class Video extends Actionable<VideoStateRaw> {
|
|
|
57
65
|
* video.seek(3);
|
|
58
66
|
* ```
|
|
59
67
|
*/
|
|
60
|
-
seek(time: number):
|
|
68
|
+
seek(time: number): Proxied<Video, Chained<LogicAction.Actions>>;
|
|
61
69
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { Character } from "../elements/character";
|
|
2
|
+
import { Sentence } from "../elements/character/sentence";
|
|
1
3
|
import { Storable } from "../elements/persistent/storable";
|
|
2
4
|
import { Story } from "../elements/story";
|
|
3
5
|
import { Game } from "../game";
|
|
@@ -9,6 +11,51 @@ import { EventDispatcher } from "../../../util/data";
|
|
|
9
11
|
import { GameState } from "../../player/gameState";
|
|
10
12
|
import { GameHistory } from "../action/gameHistory";
|
|
11
13
|
import { StackModel, StackSnapshot } from "../action/stackModel";
|
|
14
|
+
export type LiveGameEvent = {
|
|
15
|
+
"event:character.prompt": [
|
|
16
|
+
{
|
|
17
|
+
/**
|
|
18
|
+
* The character who says the sentence
|
|
19
|
+
*/
|
|
20
|
+
character: Character | null;
|
|
21
|
+
/**
|
|
22
|
+
* The sentence said by the character
|
|
23
|
+
*/
|
|
24
|
+
sentence: Sentence;
|
|
25
|
+
/**
|
|
26
|
+
* The text of the sentence
|
|
27
|
+
*/
|
|
28
|
+
text: string;
|
|
29
|
+
}
|
|
30
|
+
];
|
|
31
|
+
"event:menu.choose": [
|
|
32
|
+
{
|
|
33
|
+
/**
|
|
34
|
+
* The sentence selected by the player
|
|
35
|
+
*/
|
|
36
|
+
sentence: Sentence;
|
|
37
|
+
/**
|
|
38
|
+
* The text of the sentence
|
|
39
|
+
*/
|
|
40
|
+
text: string;
|
|
41
|
+
}
|
|
42
|
+
];
|
|
43
|
+
"event:action.current": [
|
|
44
|
+
{
|
|
45
|
+
/**
|
|
46
|
+
* The id of the action that just began executing (as assigned by the story compiler),
|
|
47
|
+
* or null for an action with no id. Fires for every executed action, including those
|
|
48
|
+
* inside parallel/async branches — subscribers that only care about top-level lines
|
|
49
|
+
* should filter by their own id set.
|
|
50
|
+
*/
|
|
51
|
+
actionId: string | null;
|
|
52
|
+
/**
|
|
53
|
+
* The action's type (e.g. `"character:say"`).
|
|
54
|
+
*/
|
|
55
|
+
actionType: string | null;
|
|
56
|
+
}
|
|
57
|
+
];
|
|
58
|
+
};
|
|
12
59
|
export declare class LiveGame {
|
|
13
60
|
static DefaultNamespaces: {
|
|
14
61
|
game: {};
|