narraleaf-react 0.19.2 → 0.20.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/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,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The seam a host uses to draw something the engine does not understand.
|
|
3
|
+
*
|
|
4
|
+
* A puppet is a box on the stage. The engine owns the outside of that box — where it sits, which
|
|
5
|
+
* layer it belongs to, its transform, its opacity, and its place in a saved game — and hands the
|
|
6
|
+
* inside to a backend the host registered. The engine never looks in: `src`, `options`, command
|
|
7
|
+
* names and payloads are opaque values it stores, serialises and forwards untouched.
|
|
8
|
+
*
|
|
9
|
+
* There is exactly one thing the engine will assume about `src`, and only when it is asked to.
|
|
10
|
+
* {@link PuppetMountContext.resolveSibling} reads `src` as a *location* — it takes the part before
|
|
11
|
+
* the last `/` and resolves a path against it. It still does not know what `src` **means**: not the
|
|
12
|
+
* format, not the contents, not which files it will pull in. A backend whose `src` is not a
|
|
13
|
+
* location simply never calls it, and nothing else in the engine does.
|
|
14
|
+
*
|
|
15
|
+
* That is why this module imports nothing but its own string arithmetic. The contract below is the
|
|
16
|
+
* whole of what a renderer has to satisfy, so a host can take these types on their own, and the
|
|
17
|
+
* engine stays free of any renderer's code.
|
|
18
|
+
*/
|
|
19
|
+
/** Logical pixel size of the box a puppet is drawn into. */
|
|
20
|
+
export type PuppetSize = {
|
|
21
|
+
width: number;
|
|
22
|
+
height: number;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* What an editor host sees of a puppet's backend instance.
|
|
26
|
+
*
|
|
27
|
+
* - `unmounted` — the element is not on the stage, or its component has not mounted yet.
|
|
28
|
+
* - `missing-backend` — the element is on the stage, but nothing answers to its `backend` name.
|
|
29
|
+
* The box still takes part in transforms, layers and saves; it simply draws nothing.
|
|
30
|
+
* - `loading` — the backend was mounted and its {@link PuppetInstance.ready} has not resolved.
|
|
31
|
+
* - `ready` — the first frame has been drawn.
|
|
32
|
+
* - `error` — mounting, applying state, or loading threw. The stage stays alive regardless.
|
|
33
|
+
*/
|
|
34
|
+
export type PuppetStatus = "unmounted" | "missing-backend" | "loading" | "ready" | "error";
|
|
35
|
+
/**
|
|
36
|
+
* The persistent state of a puppet — and the whole of what a saved game carries about one.
|
|
37
|
+
*
|
|
38
|
+
* One-shot actions are deliberately absent: they go through {@link PuppetInstance.command}, so that
|
|
39
|
+
* restoring a puppet is a single {@link PuppetInstance.apply} of a complete state rather than a
|
|
40
|
+
* replay of everything that ever happened to it.
|
|
41
|
+
*
|
|
42
|
+
* None of these names belong to any particular renderer. `motion` / `expression` / `skin` are the
|
|
43
|
+
* three ideas every 2D character renderer has; anything genuinely proprietary belongs in `params`,
|
|
44
|
+
* `slots`, or a command.
|
|
45
|
+
*
|
|
46
|
+
* **What `null` means, field by field.** Every field is a request; `null` is the *absence* of one,
|
|
47
|
+
* and never "leave whatever is there". A state is applied whole, so a field that has been cleared
|
|
48
|
+
* has to visibly clear — otherwise loading a saved game would not reproduce what it recorded, and
|
|
49
|
+
* neither would an undo.
|
|
50
|
+
*
|
|
51
|
+
* A name the model does not have is a {@link PuppetMountContext.warn}, not a throw: throwing out of
|
|
52
|
+
* {@link PuppetInstance.apply} puts the whole element in `"error"` over what is usually one typo.
|
|
53
|
+
*/
|
|
54
|
+
export type PuppetState = {
|
|
55
|
+
/**
|
|
56
|
+
* The named action currently requested — usually the loop the model settles into.
|
|
57
|
+
*
|
|
58
|
+
* `null` means nothing is playing: the model rests at whatever it looks like with no motion
|
|
59
|
+
* applied — its setup / rest / bind pose, or the backend's own default where the format has no
|
|
60
|
+
* such thing.
|
|
61
|
+
*/
|
|
62
|
+
motion: string | null;
|
|
63
|
+
/**
|
|
64
|
+
* The named expression currently requested.
|
|
65
|
+
*
|
|
66
|
+
* `null` means no expression is applied, and the face is whatever the motion and the skin make
|
|
67
|
+
* it. Clear the expression rather than substituting a model's own named "neutral": if the
|
|
68
|
+
* author wants that one, they can name it, and then `null` and `"neutral"` still differ.
|
|
69
|
+
*/
|
|
70
|
+
expression: string | null;
|
|
71
|
+
/**
|
|
72
|
+
* The named skin / costume currently requested.
|
|
73
|
+
*
|
|
74
|
+
* `null` means the model's default skin — the one it shows before anybody picks one.
|
|
75
|
+
*/
|
|
76
|
+
skin: string | null;
|
|
77
|
+
/**
|
|
78
|
+
* Free numeric parameters.
|
|
79
|
+
*
|
|
80
|
+
* There is no `null` here: a parameter the map does not mention keeps the model's own default
|
|
81
|
+
* for it, so clearing one means dropping the key rather than nulling it.
|
|
82
|
+
*/
|
|
83
|
+
params: Record<string, number>;
|
|
84
|
+
/**
|
|
85
|
+
* Free string slots, for whatever the three names above do not cover.
|
|
86
|
+
*
|
|
87
|
+
* A slot set to `null` is cleared — exactly the same state as a key that is not there at all.
|
|
88
|
+
* The key survives only because `setSlot(id, null)` merges over what is already in the map.
|
|
89
|
+
*/
|
|
90
|
+
slots: Record<string, string | null>;
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* A model describing itself to an editor host.
|
|
94
|
+
*
|
|
95
|
+
* This is what spares a host from parsing model files: it can fill its inspector's dropdowns from
|
|
96
|
+
* the live instance instead. Backends that cannot answer simply do not implement
|
|
97
|
+
* {@link PuppetInstance.describe}, and the host falls back to letting the author type names.
|
|
98
|
+
*/
|
|
99
|
+
export type PuppetDescription = {
|
|
100
|
+
motions: string[];
|
|
101
|
+
expressions: string[];
|
|
102
|
+
skins: string[];
|
|
103
|
+
params: {
|
|
104
|
+
id: string;
|
|
105
|
+
min: number;
|
|
106
|
+
max: number;
|
|
107
|
+
default: number;
|
|
108
|
+
}[];
|
|
109
|
+
/** The model's own canvas size, or null when it does not report one. */
|
|
110
|
+
size: PuppetSize | null;
|
|
111
|
+
};
|
|
112
|
+
/** Everything the engine tells a backend when it mounts one. */
|
|
113
|
+
export interface PuppetMountContext {
|
|
114
|
+
/**
|
|
115
|
+
* The resource descriptor the puppet declared, passed through verbatim.
|
|
116
|
+
*
|
|
117
|
+
* Whatever this string means is the backend's business. The engine stores it, saves it and
|
|
118
|
+
* hands it over; the only structure it will ever read out of it is the directory `src` sits in,
|
|
119
|
+
* and only through {@link PuppetMountContext.resolveSibling}.
|
|
120
|
+
*/
|
|
121
|
+
readonly src: string;
|
|
122
|
+
/** The author's options for this backend, passed through verbatim. */
|
|
123
|
+
readonly options: Readonly<Record<string, unknown>>;
|
|
124
|
+
/** The logical size of the box, in pixels. Later changes arrive via {@link PuppetInstance.resize}. */
|
|
125
|
+
readonly size: PuppetSize;
|
|
126
|
+
/**
|
|
127
|
+
* Resolve a source to a URL by the same rules images use: a data URI is returned unchanged, and
|
|
128
|
+
* anything else is looked up in the preload cache before being handed back untouched.
|
|
129
|
+
*
|
|
130
|
+
* So this serves whatever the author warmed with `scene.preloadImage()`, and nothing else.
|
|
131
|
+
* **A puppet's own `src` is not registered for preloading** — it is a model manifest, not an
|
|
132
|
+
* image, and the engine has no idea what textures it will pull in. A backend that wants its
|
|
133
|
+
* textures warmed has to have the author warm them by hand; everything not in the cache is a
|
|
134
|
+
* plain URL the backend fetches itself.
|
|
135
|
+
*/
|
|
136
|
+
resolveSrc(src: string): string;
|
|
137
|
+
/**
|
|
138
|
+
* Resolve a path that is relative to this puppet's own `src` — a sibling in the same bundle.
|
|
139
|
+
*
|
|
140
|
+
* No real 2D character model is one file. It is a manifest plus an atlas plus texture pages, or
|
|
141
|
+
* a model file plus motions plus physics plus textures, and **which siblings exist is only
|
|
142
|
+
* knowable after parsing the first one**: the manifest names them. So a backend cannot be given
|
|
143
|
+
* a list up front, and asking the author to enumerate one would move parsing to the party least
|
|
144
|
+
* able to do it. It is given the arithmetic instead.
|
|
145
|
+
*
|
|
146
|
+
* The path is resolved against everything in `src` before its last `/`, `.` and `..` are
|
|
147
|
+
* folded, and the result goes through the same rules as {@link PuppetMountContext.resolveSrc} —
|
|
148
|
+
* so a texture the author warmed with `scene.preloadImage()` is served from the preload cache
|
|
149
|
+
* here, and everything else comes back as a plain URL to fetch.
|
|
150
|
+
*
|
|
151
|
+
* ```ts
|
|
152
|
+
* // src: "models/alice/alice.model.json"
|
|
153
|
+
* ctx.resolveSibling("alice.atlas"); // -> "models/alice/alice.atlas"
|
|
154
|
+
* ctx.resolveSibling("textures/page-0.png"); // -> "models/alice/textures/page-0.png"
|
|
155
|
+
* ctx.resolveSibling("../shared/eyes.png"); // -> "models/shared/eyes.png"
|
|
156
|
+
* ctx.resolveSibling("https://cdn/x.png"); // -> unchanged; absolute wins
|
|
157
|
+
* ```
|
|
158
|
+
*
|
|
159
|
+
* A path that is already absolute — a scheme, a leading `/`, a protocol-relative `//host/…`, a
|
|
160
|
+
* data URI — is returned as it stands, because that is what a manifest naming a remote texture
|
|
161
|
+
* means. An empty path resolves to `src` itself. `\` is read as `/`, so a host handing over a
|
|
162
|
+
* native Windows path still gets a usable answer, and the answer always comes back with `/`.
|
|
163
|
+
*
|
|
164
|
+
* The one assumption: that `src` is a location. A backend whose `src` is an opaque key, or a
|
|
165
|
+
* data URI, has no directory to resolve against and gets the path back untouched — such a
|
|
166
|
+
* backend should be reading its own `options` instead, which the engine forwards just as
|
|
167
|
+
* verbatim and where a host can put a map, a base URL, or anything else it likes.
|
|
168
|
+
*/
|
|
169
|
+
resolveSibling(relativePath: string): string;
|
|
170
|
+
/** Report a non-fatal problem. The engine logs it and keeps the stage alive; it never throws. */
|
|
171
|
+
warn(message: string, detail?: unknown): void;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* One mounted model. The engine holds this handle and nothing else.
|
|
175
|
+
*
|
|
176
|
+
* Every member below that is not marked optional is **required**: implement all of them. The engine
|
|
177
|
+
* nevertheless checks `ready` and `resize` for existence before calling them, because this object
|
|
178
|
+
* crosses a boundary no compiler watches — it is built by the host, and a plain JavaScript host, or
|
|
179
|
+
* a `PuppetBackend` cast into place, can hand over an object that does not satisfy this contract.
|
|
180
|
+
* Those checks are damage control for a broken backend, not permission to leave the two out.
|
|
181
|
+
*
|
|
182
|
+
* **The order the engine calls these in**, because the first step of it surprises everybody:
|
|
183
|
+
*
|
|
184
|
+
* 1. `mount()` returns this object.
|
|
185
|
+
* 2. `apply()` is called at once with the complete initial state — **before `ready()` is called at
|
|
186
|
+
* all**, never mind resolved. The first pose therefore arrives while the model is still loading.
|
|
187
|
+
* 3. `ready()` is called once whatever `apply()` returned has settled, and the element reaches
|
|
188
|
+
* `"ready"` when it resolves.
|
|
189
|
+
* 4. `apply()`, `command()` and `resize()` follow for as long as the element is on stage. Any of
|
|
190
|
+
* them can arrive before `ready()` has resolved.
|
|
191
|
+
* 5. `dispose()` ends it, at any point, loading included. The engine calls nothing on this object
|
|
192
|
+
* afterwards.
|
|
193
|
+
*
|
|
194
|
+
* Step 2 is deliberate and is not going to change. A backend wants the pose it is meant to load
|
|
195
|
+
* into *at* load time; gating it on `ready` would buy a tidier contract at the price of every model
|
|
196
|
+
* visibly snapping from its setup pose to the author's pose a frame after it appears. There are two
|
|
197
|
+
* ways to take it and both are fine: hold the state and re-apply it once the model is up, or return
|
|
198
|
+
* a promise from `apply()` that waits for the load — which also holds `ready()` back until the pose
|
|
199
|
+
* has landed, so the element is not called ready before it looks right.
|
|
200
|
+
*/
|
|
201
|
+
export interface PuppetInstance {
|
|
202
|
+
/** Resolves once the model is loaded and its first frame has been drawn. */
|
|
203
|
+
ready(): Promise<void>;
|
|
204
|
+
/**
|
|
205
|
+
* Apply a **complete** state. Called once on mount, then on every change.
|
|
206
|
+
*
|
|
207
|
+
* The first call comes before `ready()` — see the lifecycle above.
|
|
208
|
+
*/
|
|
209
|
+
apply(state: Readonly<PuppetState>): void | Promise<void>;
|
|
210
|
+
/**
|
|
211
|
+
* Run a named command. The engine never interprets `name` or `payload`.
|
|
212
|
+
*
|
|
213
|
+
* Returning a promise lets a caller that opted in wait for the command — playing a motion to
|
|
214
|
+
* its end, for instance. Nothing waits by default.
|
|
215
|
+
*
|
|
216
|
+
* `payload` is optional on the authoring side (`puppet.command("wave")`), so it arrives as
|
|
217
|
+
* `undefined` whenever the story omitted it. Treat a missing payload as valid input.
|
|
218
|
+
*/
|
|
219
|
+
command(name: string, payload?: unknown): void | Promise<void>;
|
|
220
|
+
/** The box changed size. */
|
|
221
|
+
resize(size: PuppetSize): void;
|
|
222
|
+
/**
|
|
223
|
+
* Optional: describe the model to an editor host. See {@link PuppetDescription}.
|
|
224
|
+
*
|
|
225
|
+
* **Nothing gates this on status.** `DevTools.describePuppet` forwards it the moment it is
|
|
226
|
+
* asked, which is any time between `mount` and `dispose` — before `ready()` has resolved, and
|
|
227
|
+
* more than once. That is the design, not an oversight: an editor opens an inspector when the
|
|
228
|
+
* author clicks, not when a model happens to have finished loading, and a backend knows better
|
|
229
|
+
* than the engine what it can answer and when. So a backend that can only describe a loaded
|
|
230
|
+
* model awaits its own load in here. Rejecting is safe too — the host logs it and falls back to
|
|
231
|
+
* letting the author type names.
|
|
232
|
+
*/
|
|
233
|
+
describe?(): Promise<PuppetDescription>;
|
|
234
|
+
dispose(): void;
|
|
235
|
+
}
|
|
236
|
+
/** A drawing backend registered by the host. The engine knows nothing of its internals. */
|
|
237
|
+
export interface PuppetBackend {
|
|
238
|
+
/** The key a puppet's `backend` config refers to. */
|
|
239
|
+
readonly name: string;
|
|
240
|
+
/**
|
|
241
|
+
* Create an instance bound to a host element.
|
|
242
|
+
*
|
|
243
|
+
* The engine owns the box (position / scale / opacity / rotation / layer); the backend owns
|
|
244
|
+
* what is inside it. The container is emptied when the instance is disposed.
|
|
245
|
+
*/
|
|
246
|
+
mount(container: HTMLDivElement, ctx: PuppetMountContext): PuppetInstance;
|
|
247
|
+
}
|
|
@@ -5,6 +5,7 @@ import { LiveGame } from "./game/liveGame";
|
|
|
5
5
|
import { Preference } from "./game/preference";
|
|
6
6
|
import { GameState } from "../player/gameState";
|
|
7
7
|
import { Plugins, IGamePluginRegistry } from "./game/plugin/plugin";
|
|
8
|
+
import { PuppetBackend } from "./game/puppet/puppetBackend";
|
|
8
9
|
import { LayoutRouter } from "../player/lib/PageRouter/router";
|
|
9
10
|
import { KeyMap } from "./game/keyMap";
|
|
10
11
|
import type { Storable } from "./elements/persistent/storable";
|
|
@@ -69,6 +70,7 @@ export declare class Game {
|
|
|
69
70
|
plugins: Plugins;
|
|
70
71
|
router: LayoutRouter;
|
|
71
72
|
private readonly lifecycleEvents;
|
|
73
|
+
private readonly puppetBackends;
|
|
72
74
|
private preloadCompleteContext;
|
|
73
75
|
private firstSceneReadyContext;
|
|
74
76
|
/**
|
|
@@ -99,6 +101,47 @@ export declare class Game {
|
|
|
99
101
|
* @param plugin - The plugin to use
|
|
100
102
|
*/
|
|
101
103
|
use(plugin: IGamePluginRegistry): this;
|
|
104
|
+
/**
|
|
105
|
+
* Register a backend that draws {@link import("./elements/displayable/puppet").Puppet}
|
|
106
|
+
* elements.
|
|
107
|
+
*
|
|
108
|
+
* The engine ships no renderer and understands none: a puppet is a box it positions, layers,
|
|
109
|
+
* transforms and saves, and the backend registered here draws whatever belongs inside that box.
|
|
110
|
+
* Register before the game mounts — a puppet whose backend is missing keeps its place on the
|
|
111
|
+
* stage and draws nothing, warning once.
|
|
112
|
+
*
|
|
113
|
+
* Registering under a name already taken replaces the previous backend.
|
|
114
|
+
*
|
|
115
|
+
* This lives on `Game` rather than in the config on purpose: the config is deep-merged and can
|
|
116
|
+
* be frozen, and a backend is a live object with methods, not serialisable data. A plugin can
|
|
117
|
+
* call this from its own `register(game)`.
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```ts
|
|
121
|
+
* game.registerPuppetBackend({
|
|
122
|
+
* name: "my-renderer",
|
|
123
|
+
* mount(container, ctx) {
|
|
124
|
+
* const model = MyRenderer.create(container, ctx.resolveSrc(ctx.src), ctx.size);
|
|
125
|
+
* return {
|
|
126
|
+
* ready: () => model.loaded,
|
|
127
|
+
* apply: (state) => model.setPose(state),
|
|
128
|
+
* command: (name, payload) => model.run(name, payload),
|
|
129
|
+
* resize: (size) => model.resize(size.width, size.height),
|
|
130
|
+
* dispose: () => model.destroy(),
|
|
131
|
+
* };
|
|
132
|
+
* },
|
|
133
|
+
* });
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
registerPuppetBackend(backend: PuppetBackend): this;
|
|
137
|
+
/**
|
|
138
|
+
* The backend registered under the given name, or null.
|
|
139
|
+
*/
|
|
140
|
+
getPuppetBackend(name: string): PuppetBackend | null;
|
|
141
|
+
/**
|
|
142
|
+
* The names of every registered puppet backend, in registration order.
|
|
143
|
+
*/
|
|
144
|
+
listPuppetBackends(): string[];
|
|
102
145
|
/**
|
|
103
146
|
* Listen for the initial preload pass completing.
|
|
104
147
|
*
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export interface EventfulDisplayable {
|
|
2
|
+
}
|
|
@@ -1 +1,9 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
declare const AspectScaleImage: React.ForwardRefExoticComponent<{
|
|
3
|
+
onSizeChanged?: (width: number, height: number) => void;
|
|
4
|
+
onLoad?: () => void;
|
|
5
|
+
autoFit?: boolean;
|
|
6
|
+
src?: string;
|
|
7
|
+
style?: React.CSSProperties;
|
|
8
|
+
} & React.RefAttributes<HTMLImageElement>>;
|
|
1
9
|
export default AspectScaleImage;
|
|
@@ -1,7 +1,13 @@
|
|
|
1
|
+
import { Image as GameImage } from "../../../nlcore/elements/displayable/image";
|
|
1
2
|
import React from "react";
|
|
3
|
+
import { GameState } from "../../gameState";
|
|
2
4
|
export type ImageEvents = {
|
|
3
5
|
"event:image.onLoad": [];
|
|
4
6
|
};
|
|
5
7
|
export declare function stackStyle(darkness: number): React.CSSProperties;
|
|
8
|
+
declare function ImageComponent({ image, state, }: Readonly<{
|
|
9
|
+
image: GameImage;
|
|
10
|
+
state: GameState;
|
|
11
|
+
}>): React.JSX.Element;
|
|
6
12
|
declare const Image: React.MemoExoticComponent<typeof ImageComponent>;
|
|
7
13
|
export default Image;
|
|
@@ -131,6 +131,11 @@ export type PresentationSnapshot = {
|
|
|
131
131
|
scenes: SceneSnapshot[];
|
|
132
132
|
nvlState: NvlState;
|
|
133
133
|
};
|
|
134
|
+
export type PlayerStateElementSnapshot = {
|
|
135
|
+
scene: Scene;
|
|
136
|
+
layers: Map<Layer, [LogicAction.DisplayableElements, Record<string, any>][]>;
|
|
137
|
+
};
|
|
138
|
+
export type PlayerAction = CalledActionResult;
|
|
134
139
|
interface StageUtils {
|
|
135
140
|
update: () => void;
|
|
136
141
|
forceUpdate: () => void;
|
|
@@ -1 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
import { Character } from "../nlcore/elements/character";
|
|
2
|
+
import { Choice } from "../nlcore/elements/menu";
|
|
3
|
+
import { Sentence } from "../nlcore/elements/character/sentence";
|
|
4
|
+
import { Word } from "../nlcore/elements/character/word";
|
|
5
|
+
import { Pausing } from "../nlcore/elements/character/pause";
|
|
6
|
+
import { TextEvent } from "../nlcore/elements/character/textEvent";
|
|
7
|
+
export type Clickable<T, U = undefined> = {
|
|
8
|
+
action: T;
|
|
9
|
+
onClick: U extends undefined ? () => void : (arg0: U) => void;
|
|
10
|
+
};
|
|
11
|
+
export type TextElement = {
|
|
12
|
+
character: Character | null;
|
|
13
|
+
sentence: Sentence;
|
|
14
|
+
id: string;
|
|
15
|
+
words: Word<Pausing | string | TextEvent>[];
|
|
16
|
+
};
|
|
17
|
+
export type MenuElement = {
|
|
18
|
+
prompt: Sentence | null;
|
|
19
|
+
choices: Choice[];
|
|
20
|
+
words: Word<Pausing | string | TextEvent>[] | null;
|
|
21
|
+
};
|
|
@@ -12,6 +12,7 @@ import { Scene } from "../nlcore/elements/scene";
|
|
|
12
12
|
import { Sound } from "../nlcore/elements/sound";
|
|
13
13
|
import { Video } from "../nlcore/elements/video";
|
|
14
14
|
import { Vfx, VfxFadeOptions } from "../nlcore/elements/vfx";
|
|
15
|
+
import { Puppet } from "../nlcore/elements/displayable/puppet";
|
|
15
16
|
import { Timeline } from "./Tasks";
|
|
16
17
|
export * from "./elements/type";
|
|
17
18
|
export type Chosen = Choice & {
|
|
@@ -24,7 +25,8 @@ export declare enum ExposedStateType {
|
|
|
24
25
|
scene = "narraleaf:scene",
|
|
25
26
|
video = "narraleaf:video",
|
|
26
27
|
vfx = "narraleaf:vfx",
|
|
27
|
-
camera = "narraleaf:camera"
|
|
28
|
+
camera = "narraleaf:camera",
|
|
29
|
+
puppet = "narraleaf:puppet"
|
|
28
30
|
}
|
|
29
31
|
export type ExposedState = {
|
|
30
32
|
[ExposedStateType.image]: {
|
|
@@ -56,6 +58,13 @@ export type ExposedState = {
|
|
|
56
58
|
applyTransition: (transition: Transition<any>, onResolve: () => void) => Timeline;
|
|
57
59
|
updateStyleSync: () => void;
|
|
58
60
|
};
|
|
61
|
+
[ExposedStateType.puppet]: {
|
|
62
|
+
initDisplayable: (onResolve: () => void) => Timeline;
|
|
63
|
+
applyTransform: (transform: Transform, onResolve: () => void) => Timeline;
|
|
64
|
+
applyTransition: (transition: Transition<any>, onResolve: () => void) => Timeline;
|
|
65
|
+
updateStyleSync: () => void;
|
|
66
|
+
flush: () => void;
|
|
67
|
+
};
|
|
59
68
|
[ExposedStateType.scene]: {
|
|
60
69
|
setBackgroundMusic: (music: Sound | null, fade: number) => Promise<void>;
|
|
61
70
|
};
|
|
@@ -81,6 +90,7 @@ export type ExposedKeys = {
|
|
|
81
90
|
[ExposedStateType.text]: Text | Displayable<any, any>;
|
|
82
91
|
[ExposedStateType.layer]: Layer | Displayable<any, any>;
|
|
83
92
|
[ExposedStateType.camera]: Camera | Displayable<any, any>;
|
|
93
|
+
[ExposedStateType.puppet]: Puppet | Displayable<any, any>;
|
|
84
94
|
[ExposedStateType.scene]: Scene;
|
|
85
95
|
[ExposedStateType.video]: Video;
|
|
86
96
|
[ExposedStateType.vfx]: Vfx;
|