narraleaf-react 0.41.2 → 0.42.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/game/nlcore/action/actionTypes.d.ts +2 -2
- package/dist/game/nlcore/elements/sound.d.ts +7 -1
- package/dist/game/nlcore/elements/type.d.ts +12 -0
- package/dist/game/nlcore/gameTypes.d.ts +15 -0
- package/dist/game/player/elements/preload/preloadPlan.d.ts +14 -2
- package/dist/game/player/lib/AudioManager.d.ts +11 -2
- package/dist/game/player/lib/ImageCacheManager.d.ts +10 -1
- package/dist/main.js +35 -35
- package/dist/util/data.d.ts +15 -1
- package/package.json +1 -1
|
@@ -11,7 +11,7 @@ import type { Script } from "../elements/script";
|
|
|
11
11
|
import type { Sentence } from "../elements/character/sentence";
|
|
12
12
|
import type { TransformDefinitions } from "../elements/transform/type";
|
|
13
13
|
import type { Image, TagGroupDefinition } from "../elements/displayable/image";
|
|
14
|
-
import type { FadeOptions } from "../elements/type";
|
|
14
|
+
import type { FadeOptions, SoundPlayOptions } from "../elements/type";
|
|
15
15
|
import type { Transition } from "../elements/transition/transition";
|
|
16
16
|
import type { ImageTransition } from "../elements/transition/transitions/image/imageTransition";
|
|
17
17
|
import type { Layer } from "../elements/layer";
|
|
@@ -107,7 +107,7 @@ export declare const SoundActionTypes: {
|
|
|
107
107
|
readonly seek: "sound:seek";
|
|
108
108
|
};
|
|
109
109
|
export type SoundActionContentType = {
|
|
110
|
-
[K in typeof SoundActionTypes[keyof typeof SoundActionTypes]]: K extends "sound:play" ? [
|
|
110
|
+
[K in typeof SoundActionTypes[keyof typeof SoundActionTypes]]: K extends "sound:play" ? [SoundPlayOptions] : K extends "sound:stop" ? [FadeOptions] : K extends "sound:setVolume" ? [volume: number, duration: number] : K extends "sound:setRate" ? [number] : K extends "sound:pause" ? [FadeOptions] : K extends "sound:resume" ? [FadeOptions] : K extends "sound:mute" ? [boolean] : K extends "sound:seek" ? [time: number] : any;
|
|
111
111
|
};
|
|
112
112
|
export declare const ControlActionTypes: {
|
|
113
113
|
readonly action: "control:action";
|
|
@@ -152,14 +152,20 @@ export declare class Sound extends Actionable<SoundDataRaw, Sound> {
|
|
|
152
152
|
* It is *not* the same as {@link Scene.setBackgroundMusic}: a clip played here is not in the
|
|
153
153
|
* scene's background-music slot, so leaving the scene will not stop it and no cross-fade is
|
|
154
154
|
* arranged for it. That is true of every clip played this way, on any bus.
|
|
155
|
+
* The script carries on as soon as the clip is playing. A clip that is meant to hold the script
|
|
156
|
+
* until it finishes says so: `sound.play(0, {waitForEnd: true})`.
|
|
157
|
+
*
|
|
155
158
|
* @param duration - Optional fade duration in milliseconds.
|
|
159
|
+
* @param options.waitForEnd - Hold the script until the clip finishes. Ignored for a looping clip.
|
|
156
160
|
* @chainable
|
|
157
161
|
* @example
|
|
158
162
|
* ```ts
|
|
159
163
|
* sound.play(1000);
|
|
160
164
|
* ```
|
|
161
165
|
*/
|
|
162
|
-
play(duration?: number
|
|
166
|
+
play(duration?: number, options?: {
|
|
167
|
+
waitForEnd?: boolean;
|
|
168
|
+
}): ChainedSound;
|
|
163
169
|
/**
|
|
164
170
|
* Stop the sound and optionally fade out.
|
|
165
171
|
* @param duration - Fade duration in milliseconds.
|
|
@@ -11,6 +11,18 @@ export type FadeOptions = {
|
|
|
11
11
|
end: number;
|
|
12
12
|
duration: number;
|
|
13
13
|
};
|
|
14
|
+
/**
|
|
15
|
+
* What {@link AudioManager.play} is asked for, on top of the fade.
|
|
16
|
+
*
|
|
17
|
+
* `waitForEnd` is what decides whether the action that started the clip holds the script until the
|
|
18
|
+
* clip finishes. A sound effect written between two lines is not a wait the author asked for - a
|
|
19
|
+
* seven-second chime stopped the script for seven seconds with nothing on screen saying why - so
|
|
20
|
+
* {@link Sound.play} leaves it off and a row that means "hold here" turns it on.
|
|
21
|
+
*/
|
|
22
|
+
export type SoundPlayOptions = FadeOptions & {
|
|
23
|
+
/** Resolve only once the clip has finished playing. Ignored for a looping clip. */
|
|
24
|
+
waitForEnd?: boolean;
|
|
25
|
+
};
|
|
14
26
|
export type ChainedActions = (Proxied<LogicAction.GameElement, Chained<LogicAction.Actions>> | LogicAction.Actions)[];
|
|
15
27
|
export type ActionStatements = ChainedActions | string[];
|
|
16
28
|
export type { TransitionAnimationType, TransitionTask, };
|
|
@@ -185,6 +185,21 @@ export type GameConfig = {
|
|
|
185
185
|
* @default true
|
|
186
186
|
*/
|
|
187
187
|
waitForPreload: boolean;
|
|
188
|
+
/**
|
|
189
|
+
* How much of a scene has to be warm before the game is shown.
|
|
190
|
+
*
|
|
191
|
+
* `"firstFrame"` waits for the scene's opening background and nothing else, then keeps fetching
|
|
192
|
+
* the rest behind the game. `"scene"` waits for every image the scene registers anywhere in it,
|
|
193
|
+
* which is what this always did.
|
|
194
|
+
*
|
|
195
|
+
* The two differ by an order of magnitude on a real project: a chapter's registered set is
|
|
196
|
+
* every pose of every character it shows and every background it cuts to, while its first frame
|
|
197
|
+
* is one picture. Choose `"scene"` when a game would rather open late than risk an image
|
|
198
|
+
* arriving after the frame that wanted it.
|
|
199
|
+
*
|
|
200
|
+
* @default "firstFrame"
|
|
201
|
+
*/
|
|
202
|
+
preloadGate: "firstFrame" | "scene";
|
|
188
203
|
/**
|
|
189
204
|
* Preload all possible images in the scene
|
|
190
205
|
*
|
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
import type { Scene } from "../../../nlcore/elements/scene";
|
|
2
2
|
import type { Sound } from "../../../nlcore/elements/sound";
|
|
3
3
|
export type ScenePreloadPlan = {
|
|
4
|
+
/**
|
|
5
|
+
* The image the scene's own first painted frame cannot do without: its opening background.
|
|
6
|
+
*
|
|
7
|
+
* Split out of {@link ScenePreloadPlan.critical} because those two answer different questions.
|
|
8
|
+
* "What does this scene use anywhere in it" is a whole chapter's artwork - every pose of every
|
|
9
|
+
* character it shows, every background it cuts to - and on a real project that is most of the
|
|
10
|
+
* library. "What is on screen when it opens" is one picture. A host that holds its loading
|
|
11
|
+
* screen up until the scene is warm was holding it for the first of those; this tier is the
|
|
12
|
+
* second, and it is what {@link GameConfig.preloadGate} lets a game wait on instead.
|
|
13
|
+
*/
|
|
14
|
+
firstFrame: string[];
|
|
4
15
|
/**
|
|
5
16
|
* Image urls the scene that is about to paint registers directly: its own backgrounds and
|
|
6
|
-
* images, plus the immediate background of any scene it jumps to
|
|
7
|
-
*
|
|
17
|
+
* images, plus the immediate background of any scene it jumps to, minus anything already in
|
|
18
|
+
* {@link ScenePreloadPlan.firstFrame}. Fetched unpaced, because the player is a click away
|
|
19
|
+
* from needing it.
|
|
8
20
|
*/
|
|
9
21
|
critical: string[];
|
|
10
22
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Sound as SoundElement, SoundBusId } from "../../nlcore/elements/sound";
|
|
2
2
|
import { SoundToken } from "@narraleaf/sound";
|
|
3
|
-
import { FadeOptions } from "../../nlcore/elements/type";
|
|
3
|
+
import { FadeOptions, SoundPlayOptions } from "../../nlcore/elements/type";
|
|
4
4
|
import { Awaitable } from "../../../util/data";
|
|
5
5
|
import { GameState } from "../gameState";
|
|
6
6
|
import { LogicAction } from "../../nlcore/action/logicAction";
|
|
@@ -139,7 +139,16 @@ export declare class AudioManager {
|
|
|
139
139
|
* back to whatever the author first wrote down.
|
|
140
140
|
*/
|
|
141
141
|
private static defaultFade;
|
|
142
|
-
|
|
142
|
+
/**
|
|
143
|
+
* Start `sound`, and resolve when it is playing.
|
|
144
|
+
*
|
|
145
|
+
* `options.waitForEnd` moves the resolution to the end of the clip. It defaults to ON here and
|
|
146
|
+
* OFF at {@link Sound.play}, and the asymmetry is deliberate: the callers inside the engine - a
|
|
147
|
+
* voice line, a text-event effect - are tracking a clip's whole life and were written against
|
|
148
|
+
* that, while an authored sound-effect row is not asking the script to stop for the length of
|
|
149
|
+
* the file. A looping clip never ends, so it is always resolved once it is playing.
|
|
150
|
+
*/
|
|
151
|
+
play(sound: SoundElement, options?: SoundPlayOptions): Awaitable<void>;
|
|
143
152
|
/**
|
|
144
153
|
* Start a clip and hand the token back once playback is under way.
|
|
145
154
|
*
|
|
@@ -31,6 +31,15 @@ export declare class ImageCacheManager {
|
|
|
31
31
|
*/
|
|
32
32
|
private decoded;
|
|
33
33
|
constructor(game: Game);
|
|
34
|
+
/**
|
|
35
|
+
* Release the object URL an entry holds.
|
|
36
|
+
*
|
|
37
|
+
* Every path that drops an entry goes through this. An object URL pins its blob for the
|
|
38
|
+
* lifetime of the document, so a cache that forgets an entry without revoking leaks the whole
|
|
39
|
+
* image - which on a scene change is most of a scene's artwork.
|
|
40
|
+
*/
|
|
41
|
+
private release;
|
|
42
|
+
private releaseAll;
|
|
34
43
|
has(name: string): boolean;
|
|
35
44
|
add(name: string, src: string): this;
|
|
36
45
|
remove(name: string): this;
|
|
@@ -44,7 +53,7 @@ export declare class ImageCacheManager {
|
|
|
44
53
|
size(): number;
|
|
45
54
|
isPreloading(src: string): boolean;
|
|
46
55
|
/**
|
|
47
|
-
* Fetch `url`, cache it as
|
|
56
|
+
* Fetch `url`, cache it as an object URL and decode it, resolving the returned token's
|
|
48
57
|
* `onFinished` only once the decode has settled.
|
|
49
58
|
*
|
|
50
59
|
* @param options.retainDecoded keep the decoded bitmap alive until this source leaves the
|