narraleaf-react 0.15.0 → 0.16.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 +15 -1
- package/dist/game/nlcore/action/actions/controlAction.d.ts +2 -0
- package/dist/game/nlcore/action/actions/vfxAction.d.ts +24 -0
- package/dist/game/nlcore/action/logicAction.d.ts +16 -13
- package/dist/game/nlcore/action/stackModel.d.ts +28 -0
- package/dist/game/nlcore/common/elements.d.ts +6 -1
- package/dist/game/nlcore/common/game.d.ts +2 -1
- package/dist/game/nlcore/common/transition.d.ts +10 -9
- package/dist/game/nlcore/elements/camera.d.ts +71 -0
- package/dist/game/nlcore/elements/character/sentence.d.ts +2 -1
- package/dist/game/nlcore/elements/character/textEvent.d.ts +75 -0
- package/dist/game/nlcore/elements/character/word.d.ts +2 -1
- package/dist/game/nlcore/elements/control.d.ts +62 -0
- package/dist/game/nlcore/elements/displayable/image.d.ts +2 -2
- package/dist/game/nlcore/elements/scene.d.ts +2 -2
- package/dist/game/nlcore/elements/story.d.ts +21 -1
- package/dist/game/nlcore/elements/transition/transitions/image/darkness.d.ts +20 -9
- package/dist/game/nlcore/elements/transition/transitions/image/dissolve.d.ts +9 -6
- package/dist/game/nlcore/elements/transition/transitions/image/fadeIn.d.ts +9 -8
- package/dist/game/nlcore/elements/transition/transitions/image/mask.d.ts +162 -0
- package/dist/game/nlcore/elements/transition/transitions/image/push.d.ts +13 -4
- package/dist/game/nlcore/elements/transition/transitions/image/reveal.d.ts +33 -0
- package/dist/game/nlcore/elements/transition/transitions/image/throughColor.d.ts +34 -36
- package/dist/game/nlcore/elements/transition/transitions/image/transitionMaskUtils.d.ts +5 -16
- package/dist/game/nlcore/elements/transition/transitions/text/fontSize.d.ts +9 -2
- package/dist/game/nlcore/elements/vfx.d.ts +85 -0
- package/dist/game/nlcore/game/liveGame.d.ts +44 -5
- package/dist/game/player/elements/menu/type.d.ts +3 -2
- package/dist/game/player/elements/nvl/type.d.ts +2 -1
- package/dist/game/player/elements/nvl/useNvlDialogState.d.ts +2 -1
- package/dist/game/player/elements/player/Camera.d.ts +1 -0
- package/dist/game/player/elements/say/Sentence.d.ts +3 -2
- package/dist/game/player/elements/say/UIDialog.d.ts +9 -1
- package/dist/game/player/elements/say/textEventEffect.d.ts +33 -0
- package/dist/game/player/elements/say/type.d.ts +4 -3
- package/dist/game/player/elements/scene/SceneDialogs.d.ts +1 -0
- package/dist/game/player/elements/vfx/Vfx.d.ts +1 -0
- package/dist/game/player/gameState.d.ts +16 -0
- package/dist/game/player/type.d.ts +20 -1
- package/dist/main.js +44 -42
- package/package.json +1 -1
- package/dist/game/nlcore/elements/transition/transitions/image/blinds.d.ts +0 -28
- package/dist/game/nlcore/elements/transition/transitions/image/maskTransition.d.ts +0 -38
- package/dist/game/nlcore/elements/transition/transitions/image/softIris.d.ts +0 -28
- package/dist/game/nlcore/elements/transition/transitions/image/softWipe.d.ts +0 -28
|
@@ -3,10 +3,11 @@ import { GameState } from "../../gameState";
|
|
|
3
3
|
import type { NvlDialogEntry } from "../../gameState";
|
|
4
4
|
import type { Word } from "../../../nlcore/elements/character/word";
|
|
5
5
|
import type { Pausing } from "../../../nlcore/elements/character/pause";
|
|
6
|
+
import type { TextEvent } from "../../../nlcore/elements/character/textEvent";
|
|
6
7
|
type UseNvlDialogStateParams = {
|
|
7
8
|
entry: NvlDialogEntry;
|
|
8
9
|
gameState: GameState;
|
|
9
|
-
words: Word<Pausing | string>[];
|
|
10
|
+
words: Word<Pausing | string | TextEvent>[];
|
|
10
11
|
isActive: boolean;
|
|
11
12
|
useTypeEffect: boolean;
|
|
12
13
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Pausing } from "../../../nlcore/elements/character/pause";
|
|
2
|
+
import { TextEvent } from "../../../nlcore/elements/character/textEvent";
|
|
2
3
|
import { Sentence, type StaticWord } from "../../../nlcore/elements/character/sentence";
|
|
3
4
|
import { Word } from "../../../nlcore/elements/character/word";
|
|
4
5
|
import { GameState } from "../../../../game/nlcore/common/game";
|
|
@@ -47,7 +48,7 @@ export interface TextsPreviewProps extends Omit<React.HTMLAttributes<HTMLDivElem
|
|
|
47
48
|
/**
|
|
48
49
|
* Already-evaluated words, useful when previewing dynamic sentence content.
|
|
49
50
|
*/
|
|
50
|
-
words?: Word<Pausing | string>[];
|
|
51
|
+
words?: Word<Pausing | string | TextEvent>[];
|
|
51
52
|
/**
|
|
52
53
|
* Whether the preview should use the rolling type effect.
|
|
53
54
|
* @default true
|
|
@@ -92,7 +93,7 @@ export interface TextsPreviewProps extends Omit<React.HTMLAttributes<HTMLDivElem
|
|
|
92
93
|
export type EntryTextsProps = BaseTextsProps & {
|
|
93
94
|
entry: NvlDialogEntry;
|
|
94
95
|
gameState: GameState;
|
|
95
|
-
words: Word<Pausing | string>[];
|
|
96
|
+
words: Word<Pausing | string | TextEvent>[];
|
|
96
97
|
useTypeEffect: boolean;
|
|
97
98
|
isActive: boolean;
|
|
98
99
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Pausing } from "../../../nlcore/elements/character/pause";
|
|
2
|
+
import { TextEvent } from "../../../nlcore/elements/character/textEvent";
|
|
2
3
|
import { Word } from "../../../nlcore/elements/character/word";
|
|
3
4
|
import { GameState } from "../../../../game/nlcore/common/game";
|
|
4
5
|
import { EventDispatcher, EventToken } from "../../../../util/data";
|
|
@@ -14,9 +15,16 @@ type DialogEvents = {
|
|
|
14
15
|
type DialogStateConfig = {
|
|
15
16
|
useTypeEffect: boolean;
|
|
16
17
|
action: DialogAction;
|
|
17
|
-
evaluatedWords: Word<Pausing | string>[];
|
|
18
|
+
evaluatedWords: Word<Pausing | string | TextEvent>[];
|
|
18
19
|
gameState: GameState;
|
|
19
20
|
suppressInitialAnimation?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Persistent per-reveal text-event fire guard. When supplied (NVL entries pass the set stored on
|
|
23
|
+
* their long-lived {@link NvlDialogEntry}), a re-mount of the same line reuses it and so replays
|
|
24
|
+
* neither the sound effects nor the stale expression. Left undefined for ADV, whose dialog state
|
|
25
|
+
* is already memoized per action and falls back to a per-run set.
|
|
26
|
+
*/
|
|
27
|
+
firedTextEvents?: Set<TextEvent>;
|
|
20
28
|
};
|
|
21
29
|
export declare class DialogState {
|
|
22
30
|
static Events: {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { GameState } from "../../gameState";
|
|
2
|
+
import type { TextEvent } from "../../../nlcore/elements/character/textEvent";
|
|
3
|
+
import type { Word } from "../../../nlcore/elements/character/word";
|
|
4
|
+
import type { Pausing } from "../../../nlcore/elements/character/pause";
|
|
5
|
+
/**
|
|
6
|
+
* Apply a {@link TextEvent}'s effect directly to element state — no transition, no action history,
|
|
7
|
+
* no stack model. This is the "reveal semantics" seam: the typewriter calls it the moment it
|
|
8
|
+
* uncovers a token. Because the effect lands on ordinary element state (which IS serialized) and
|
|
9
|
+
* never enters the stack model, it adds no save burden and re-fires naturally when the owning
|
|
10
|
+
* `say` action is re-evaluated.
|
|
11
|
+
*
|
|
12
|
+
* Mirrors {@link ImageAction}'s non-transition branch for the repaint (layered image → `flush`,
|
|
13
|
+
* otherwise → `updateStyleSync`).
|
|
14
|
+
*/
|
|
15
|
+
export declare function dispatchTextEvent(event: TextEvent, state: GameState): void;
|
|
16
|
+
/**
|
|
17
|
+
* Fire a {@link TextEvent} at most once for a given typewriter run. `fired` is the per-run guard
|
|
18
|
+
* (contract 5): a render re-entry that re-visits the same token is a no-op, but a fresh run —
|
|
19
|
+
* a replay of the same `say` — starts with an empty set and fires again (contract 4).
|
|
20
|
+
*/
|
|
21
|
+
export declare function fireTextEventOnce(event: TextEvent, fired: Set<TextEvent>, state: GameState): void;
|
|
22
|
+
/**
|
|
23
|
+
* Land the final state of an instantly-revealed sentence: every {@link TextEvent} token in `words`
|
|
24
|
+
* fires once, in source order — the same "final state" a typewriter skip produces (contract 3).
|
|
25
|
+
*
|
|
26
|
+
* `fired` is the persistent per-reveal guard. Pass the SAME set across re-mounts of one dialog line
|
|
27
|
+
* (e.g. an NVL entry re-keyed on a phase/active change, or the whole container re-mounting) so the
|
|
28
|
+
* re-mount replays neither the sound effects nor the — now stale — expression writes. A genuinely
|
|
29
|
+
* fresh reveal (a new line, or a `say` re-evaluated on load) passes its own empty set and fires
|
|
30
|
+
* again, preserving replay safety (contract 4). Returns the tokens that actually fired this call
|
|
31
|
+
* (empty on a guarded re-mount), for tests.
|
|
32
|
+
*/
|
|
33
|
+
export declare function fireInstantRevealEvents(words: readonly Word<string | Pausing | TextEvent>[], fired: Set<TextEvent>, state: GameState): TextEvent[];
|
|
@@ -3,13 +3,14 @@ import type { GameState } from "../../gameState";
|
|
|
3
3
|
import { Sentence } from "../../../nlcore/elements/character/sentence";
|
|
4
4
|
import { Word } from "../../../nlcore/elements/character/word";
|
|
5
5
|
import { Pausing } from "../../../nlcore/elements/character/pause";
|
|
6
|
+
import { TextEvent } from "../../../nlcore/elements/character/textEvent";
|
|
6
7
|
import React from "react";
|
|
7
8
|
import type { HTMLMotionProps } from "motion/react";
|
|
8
9
|
export interface SayElementProps {
|
|
9
10
|
action: {
|
|
10
11
|
sentence: Sentence | null;
|
|
11
12
|
character: Character | null;
|
|
12
|
-
words: Word<Pausing | string>[] | null;
|
|
13
|
+
words: Word<Pausing | string | TextEvent>[] | null;
|
|
13
14
|
id?: string;
|
|
14
15
|
};
|
|
15
16
|
/**
|
|
@@ -43,13 +44,13 @@ export interface DialogContext {
|
|
|
43
44
|
action: {
|
|
44
45
|
sentence: Sentence | null;
|
|
45
46
|
character: Character | null;
|
|
46
|
-
words: Word<Pausing | string>[] | null;
|
|
47
|
+
words: Word<Pausing | string | TextEvent>[] | null;
|
|
47
48
|
};
|
|
48
49
|
state: DialogStateType;
|
|
49
50
|
}
|
|
50
51
|
export type DialogAction = {
|
|
51
52
|
sentence: Sentence | null;
|
|
52
53
|
character: Character | null;
|
|
53
|
-
words: Word<Pausing | string>[] | null;
|
|
54
|
+
words: Word<Pausing | string | TextEvent>[] | null;
|
|
54
55
|
id?: string;
|
|
55
56
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -10,6 +10,7 @@ import { Storable } from "../nlcore/elements/persistent/storable";
|
|
|
10
10
|
import { Game } from "../nlcore/game";
|
|
11
11
|
import { Clickable, MenuElement, TextElement } from "./gameState.type";
|
|
12
12
|
import { Sentence } from "../nlcore/elements/character/sentence";
|
|
13
|
+
import type { TextEvent } from "../nlcore/elements/character/textEvent";
|
|
13
14
|
import { type SceneSnapshot } from "../nlcore/action/actions/sceneAction";
|
|
14
15
|
import { Logger } from "../../util/logger";
|
|
15
16
|
import { Story } from "../nlcore/elements/story";
|
|
@@ -21,6 +22,7 @@ import { GameStateGuard } from "./guard";
|
|
|
21
22
|
import { LiveGameEventToken } from "../nlcore/types";
|
|
22
23
|
import * as htmlToImage from "html-to-image";
|
|
23
24
|
import { Video, VideoStateRaw } from "../nlcore/elements/video";
|
|
25
|
+
import { Vfx, VfxStateRaw } from "../nlcore/elements/vfx";
|
|
24
26
|
import { Timelines } from "./Tasks";
|
|
25
27
|
import { Notification, NotificationManager } from "./lib/notification";
|
|
26
28
|
import { ActionHistoryManager } from "../../game/nlcore/action/actionHistory";
|
|
@@ -35,6 +37,13 @@ export type NvlDialogEntry = {
|
|
|
35
37
|
character: Character | null;
|
|
36
38
|
sentence: Sentence;
|
|
37
39
|
text: string;
|
|
40
|
+
/**
|
|
41
|
+
* Runtime-only, per-line text-event fire guard. Lives on the long-lived entry (not the React
|
|
42
|
+
* dialog state, which is re-created on every re-mount) so the tokens a line reveals fire once and
|
|
43
|
+
* a re-mount replays nothing. Absent from {@link NvlDialogEntryData}, so a load starts a fresh
|
|
44
|
+
* reveal that fires again (replay safety). See {@link fireInstantRevealEvents}.
|
|
45
|
+
*/
|
|
46
|
+
firedTextEvents?: Set<TextEvent>;
|
|
38
47
|
};
|
|
39
48
|
export type NvlDialogPhase = "idle" | "typing" | "awaitAdvance";
|
|
40
49
|
/**
|
|
@@ -71,6 +80,7 @@ type ScheduleHandle = {
|
|
|
71
80
|
export type PlayerState = {
|
|
72
81
|
sounds: Sound[];
|
|
73
82
|
videos: Video[];
|
|
83
|
+
vfx: Vfx[];
|
|
74
84
|
srcManagers: SrcManager[];
|
|
75
85
|
elements: PlayerStateElement[];
|
|
76
86
|
};
|
|
@@ -113,6 +123,8 @@ export type PlayerStateData = {
|
|
|
113
123
|
}[];
|
|
114
124
|
audio: AudioManagerDataRaw;
|
|
115
125
|
videos: [videoId: string, videoState: VideoStateRaw][];
|
|
126
|
+
/** Absent in saves created before 0.16.0; readers must tolerate the missing key. */
|
|
127
|
+
vfx?: [vfxId: string, vfxState: VfxStateRaw][];
|
|
116
128
|
nvlState?: NvlStateData;
|
|
117
129
|
};
|
|
118
130
|
export type PresentationSnapshot = {
|
|
@@ -185,6 +197,10 @@ export declare class GameState {
|
|
|
185
197
|
removeVideo(video: Video): this;
|
|
186
198
|
isVideoAdded(video: Video): boolean;
|
|
187
199
|
getVideos(): Video[];
|
|
200
|
+
addVfx(vfx: Vfx): this;
|
|
201
|
+
removeVfx(vfx: Vfx): this;
|
|
202
|
+
isVfxAdded(vfx: Vfx): boolean;
|
|
203
|
+
getVfx(): Vfx[];
|
|
188
204
|
findElementByScene(scene: Scene): PlayerStateElement | null;
|
|
189
205
|
findElementByDisplayable(displayable: LogicAction.DisplayableElements, layer?: Layer | null): PlayerStateElement | null;
|
|
190
206
|
getLiveGame(): LiveGame;
|
|
@@ -5,11 +5,13 @@ import { ImageEvents } from "./elements/image/Image";
|
|
|
5
5
|
import { Transform } from "../nlcore/elements/transform/transform";
|
|
6
6
|
import { Transition } from "../nlcore/elements/transition/transition";
|
|
7
7
|
import { Layer } from "../nlcore/elements/layer";
|
|
8
|
+
import { Camera } from "../nlcore/elements/camera";
|
|
8
9
|
import { Text } from "../nlcore/elements/displayable/text";
|
|
9
10
|
import { Displayable } from "../nlcore/elements/displayable/displayable";
|
|
10
11
|
import { Scene } from "../nlcore/elements/scene";
|
|
11
12
|
import { Sound } from "../nlcore/elements/sound";
|
|
12
13
|
import { Video } from "../nlcore/elements/video";
|
|
14
|
+
import { Vfx, VfxFadeOptions } from "../nlcore/elements/vfx";
|
|
13
15
|
import { Timeline } from "./Tasks";
|
|
14
16
|
export * from "./elements/type";
|
|
15
17
|
export type Chosen = Choice & {
|
|
@@ -20,7 +22,9 @@ export declare enum ExposedStateType {
|
|
|
20
22
|
text = "narraleaf:text",
|
|
21
23
|
layer = "narraleaf:layer",
|
|
22
24
|
scene = "narraleaf:scene",
|
|
23
|
-
video = "narraleaf:video"
|
|
25
|
+
video = "narraleaf:video",
|
|
26
|
+
vfx = "narraleaf:vfx",
|
|
27
|
+
camera = "narraleaf:camera"
|
|
24
28
|
}
|
|
25
29
|
export type ExposedState = {
|
|
26
30
|
[ExposedStateType.image]: {
|
|
@@ -46,6 +50,12 @@ export type ExposedState = {
|
|
|
46
50
|
applyTransition: (transition: Transition<any>, onResolve: () => void) => Timeline;
|
|
47
51
|
updateStyleSync: () => void;
|
|
48
52
|
};
|
|
53
|
+
[ExposedStateType.camera]: {
|
|
54
|
+
initDisplayable: (onResolve: () => void) => Timeline;
|
|
55
|
+
applyTransform: (transform: Transform, onResolve: () => void) => Timeline;
|
|
56
|
+
applyTransition: (transition: Transition<any>, onResolve: () => void) => Timeline;
|
|
57
|
+
updateStyleSync: () => void;
|
|
58
|
+
};
|
|
49
59
|
[ExposedStateType.scene]: {
|
|
50
60
|
setBackgroundMusic: (music: Sound | null, fade: number) => Promise<void>;
|
|
51
61
|
};
|
|
@@ -58,12 +68,21 @@ export type ExposedState = {
|
|
|
58
68
|
stop: () => void;
|
|
59
69
|
seek: (time: number) => void;
|
|
60
70
|
};
|
|
71
|
+
[ExposedStateType.vfx]: {
|
|
72
|
+
show: (options?: VfxFadeOptions) => Promise<void>;
|
|
73
|
+
hide: (options?: VfxFadeOptions) => Promise<void>;
|
|
74
|
+
pause: () => void;
|
|
75
|
+
resume: () => void;
|
|
76
|
+
setRate: (rate: number) => void;
|
|
77
|
+
};
|
|
61
78
|
};
|
|
62
79
|
export type ExposedKeys = {
|
|
63
80
|
[ExposedStateType.image]: Image | Displayable<any, any>;
|
|
64
81
|
[ExposedStateType.text]: Text | Displayable<any, any>;
|
|
65
82
|
[ExposedStateType.layer]: Layer | Displayable<any, any>;
|
|
83
|
+
[ExposedStateType.camera]: Camera | Displayable<any, any>;
|
|
66
84
|
[ExposedStateType.scene]: Scene;
|
|
67
85
|
[ExposedStateType.video]: Video;
|
|
86
|
+
[ExposedStateType.vfx]: Vfx;
|
|
68
87
|
};
|
|
69
88
|
export type { INotificationsProps } from "./elements/notification/type";
|