@luna-editor/engine 0.2.0 → 0.3.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/Player.d.ts +1 -1
- package/dist/Player.js +676 -95
- package/dist/api/conversationBranch.d.ts +4 -0
- package/dist/api/conversationBranch.js +83 -0
- package/dist/components/BackgroundLayer.d.ts +19 -0
- package/dist/components/BackgroundLayer.js +220 -0
- package/dist/components/ClickWaitIndicator.d.ts +10 -0
- package/dist/components/ClickWaitIndicator.js +31 -0
- package/dist/components/ConversationBranchBox.d.ts +2 -0
- package/dist/components/ConversationBranchBox.js +29 -0
- package/dist/components/DialogueBox.js +16 -1
- package/dist/components/FontSettingsPanel.d.ts +10 -0
- package/dist/components/FontSettingsPanel.js +30 -0
- package/dist/components/FullscreenTextBox.d.ts +6 -0
- package/dist/components/FullscreenTextBox.js +70 -0
- package/dist/components/GameScreen.d.ts +9 -2
- package/dist/components/GameScreen.js +396 -80
- package/dist/components/OverlayUI.d.ts +2 -3
- package/dist/components/OverlayUI.js +3 -14
- package/dist/components/PluginComponentProvider.d.ts +3 -3
- package/dist/components/PluginComponentProvider.js +22 -4
- package/dist/components/TimeWaitIndicator.d.ts +15 -0
- package/dist/components/TimeWaitIndicator.js +17 -0
- package/dist/contexts/AudioContext.d.ts +1 -0
- package/dist/contexts/AudioContext.js +1 -0
- package/dist/contexts/DataContext.d.ts +3 -1
- package/dist/contexts/DataContext.js +104 -17
- package/dist/contexts/PlaybackTextContext.d.ts +32 -0
- package/dist/contexts/PlaybackTextContext.js +29 -0
- package/dist/data-api-types.d.ts +251 -0
- package/dist/data-api-types.js +6 -0
- package/dist/emotion-effect-types.d.ts +86 -0
- package/dist/emotion-effect-types.js +6 -0
- package/dist/hooks/useBacklog.js +3 -1
- package/dist/hooks/useConversationBranch.d.ts +16 -0
- package/dist/hooks/useConversationBranch.js +125 -0
- package/dist/hooks/useFontLoader.d.ts +30 -0
- package/dist/hooks/useFontLoader.js +192 -0
- package/dist/hooks/useFullscreenText.d.ts +17 -0
- package/dist/hooks/useFullscreenText.js +120 -0
- package/dist/hooks/useImagePreloader.d.ts +5 -0
- package/dist/hooks/useImagePreloader.js +53 -0
- package/dist/hooks/usePlayerLogic.d.ts +10 -3
- package/dist/hooks/usePlayerLogic.js +115 -18
- package/dist/hooks/usePluginAPI.js +1 -1
- package/dist/hooks/usePluginEvents.d.ts +4 -1
- package/dist/hooks/usePluginEvents.js +16 -11
- package/dist/hooks/usePreloadImages.js +27 -7
- package/dist/hooks/useSoundPlayer.d.ts +15 -0
- package/dist/hooks/useSoundPlayer.js +209 -0
- package/dist/hooks/useTypewriter.d.ts +6 -2
- package/dist/hooks/useTypewriter.js +42 -6
- package/dist/hooks/useVoice.js +4 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.js +3 -1
- package/dist/plugin/PluginManager.d.ts +86 -5
- package/dist/plugin/PluginManager.js +427 -94
- package/dist/sdk.d.ts +133 -162
- package/dist/sdk.js +39 -4
- package/dist/types.d.ts +300 -4
- package/dist/utils/branchBlockConverter.d.ts +2 -0
- package/dist/utils/branchBlockConverter.js +21 -0
- package/dist/utils/branchNavigator.d.ts +14 -0
- package/dist/utils/branchNavigator.js +55 -0
- package/dist/utils/facePositionCalculator.js +0 -1
- package/dist/utils/variableManager.d.ts +18 -0
- package/dist/utils/variableManager.js +159 -0
- package/package.json +6 -6
- package/dist/components/ConversationLogUI.d.ts +0 -2
- package/dist/components/ConversationLogUI.js +0 -115
- package/dist/hooks/useConversationLog.d.ts +0 -14
- package/dist/hooks/useConversationLog.js +0 -82
- package/dist/hooks/useUIVisibility.d.ts +0 -9
- package/dist/hooks/useUIVisibility.js +0 -19
|
@@ -4,31 +4,59 @@ export const useTypewriter = (options = {}) => {
|
|
|
4
4
|
const [displayText, setDisplayText] = useState("");
|
|
5
5
|
const [isTyping, setIsTyping] = useState(false);
|
|
6
6
|
const typingTimeoutRef = useRef(null);
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
// 連続表示用の蓄積テキスト(refに変更して無限ループを防止)
|
|
8
|
+
const accumulatedTextRef = useRef("");
|
|
9
|
+
// タイピング中のターゲットテキスト(スキップ時に使用)
|
|
10
|
+
const targetTextRef = useRef("");
|
|
11
|
+
const startTyping = useCallback((text, continueMode = false) => {
|
|
10
12
|
if (typingTimeoutRef.current) {
|
|
11
13
|
clearTimeout(typingTimeoutRef.current);
|
|
12
14
|
}
|
|
15
|
+
// 連続表示の場合は前のテキストを保持
|
|
16
|
+
let prefix = "";
|
|
17
|
+
if (continueMode && accumulatedTextRef.current) {
|
|
18
|
+
// continueWithNewline: 改行ありで連続、continue: 改行なしで連続
|
|
19
|
+
prefix =
|
|
20
|
+
continueMode === "continueWithNewline"
|
|
21
|
+
? `${accumulatedTextRef.current}\n`
|
|
22
|
+
: accumulatedTextRef.current;
|
|
23
|
+
}
|
|
24
|
+
const fullText = prefix + text;
|
|
25
|
+
// ターゲットテキストを保存(スキップ時に使用)
|
|
26
|
+
targetTextRef.current = fullText;
|
|
27
|
+
// speed <= 0 の場合は即座に全テキストを表示
|
|
28
|
+
if (speed <= 0) {
|
|
29
|
+
setDisplayText(fullText);
|
|
30
|
+
accumulatedTextRef.current = fullText;
|
|
31
|
+
setIsTyping(false);
|
|
32
|
+
onComplete === null || onComplete === void 0 ? void 0 : onComplete();
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
// 蓄積テキストから開始
|
|
36
|
+
setDisplayText(prefix);
|
|
37
|
+
setIsTyping(true);
|
|
13
38
|
let index = 0;
|
|
14
39
|
const typeChar = () => {
|
|
15
40
|
if (index < text.length) {
|
|
16
|
-
setDisplayText(text.slice(0, index + 1));
|
|
41
|
+
setDisplayText(prefix + text.slice(0, index + 1));
|
|
17
42
|
index++;
|
|
18
43
|
typingTimeoutRef.current = setTimeout(typeChar, speed);
|
|
19
44
|
}
|
|
20
45
|
else {
|
|
46
|
+
accumulatedTextRef.current = fullText;
|
|
21
47
|
setIsTyping(false);
|
|
22
48
|
onComplete === null || onComplete === void 0 ? void 0 : onComplete();
|
|
23
49
|
}
|
|
24
50
|
};
|
|
25
51
|
typeChar();
|
|
26
52
|
}, [speed, onComplete]);
|
|
27
|
-
const skipTyping = useCallback((
|
|
53
|
+
const skipTyping = useCallback(() => {
|
|
28
54
|
if (typingTimeoutRef.current) {
|
|
29
55
|
clearTimeout(typingTimeoutRef.current);
|
|
30
56
|
}
|
|
31
|
-
|
|
57
|
+
const fullText = targetTextRef.current;
|
|
58
|
+
setDisplayText(fullText);
|
|
59
|
+
accumulatedTextRef.current = fullText;
|
|
32
60
|
setIsTyping(false);
|
|
33
61
|
onComplete === null || onComplete === void 0 ? void 0 : onComplete();
|
|
34
62
|
}, [onComplete]);
|
|
@@ -37,8 +65,14 @@ export const useTypewriter = (options = {}) => {
|
|
|
37
65
|
clearTimeout(typingTimeoutRef.current);
|
|
38
66
|
}
|
|
39
67
|
setDisplayText("");
|
|
68
|
+
accumulatedTextRef.current = "";
|
|
69
|
+
targetTextRef.current = "";
|
|
40
70
|
setIsTyping(false);
|
|
41
71
|
}, []);
|
|
72
|
+
// 蓄積テキストのみをリセット(次のブロックが連続でない場合に呼び出し)
|
|
73
|
+
const resetAccumulated = useCallback(() => {
|
|
74
|
+
accumulatedTextRef.current = "";
|
|
75
|
+
}, []);
|
|
42
76
|
useEffect(() => {
|
|
43
77
|
return () => {
|
|
44
78
|
if (typingTimeoutRef.current) {
|
|
@@ -52,5 +86,7 @@ export const useTypewriter = (options = {}) => {
|
|
|
52
86
|
startTyping,
|
|
53
87
|
skipTyping,
|
|
54
88
|
reset,
|
|
89
|
+
resetAccumulated,
|
|
90
|
+
accumulatedText: accumulatedTextRef.current,
|
|
55
91
|
};
|
|
56
92
|
};
|
package/dist/hooks/useVoice.js
CHANGED
|
@@ -4,13 +4,16 @@ export const useVoice = () => {
|
|
|
4
4
|
const audioRef = useRef(null);
|
|
5
5
|
const audioSettings = useAudioSettings();
|
|
6
6
|
const playVoice = useCallback((voiceUrl) => {
|
|
7
|
+
// ミュート中は再生しない
|
|
8
|
+
if (audioSettings.muteAudio)
|
|
9
|
+
return;
|
|
7
10
|
if (!audioRef.current) {
|
|
8
11
|
audioRef.current = new Audio();
|
|
9
12
|
}
|
|
10
13
|
audioRef.current.src = voiceUrl;
|
|
11
14
|
audioRef.current.volume = audioSettings.voiceVolume;
|
|
12
15
|
audioRef.current.play().catch(console.error);
|
|
13
|
-
}, [audioSettings.voiceVolume]);
|
|
16
|
+
}, [audioSettings.voiceVolume, audioSettings.muteAudio]);
|
|
14
17
|
const stopVoice = useCallback(() => {
|
|
15
18
|
if (audioRef.current) {
|
|
16
19
|
audioRef.current.pause();
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
export { useScreenSizeAtom } from "./atoms/screen-size";
|
|
2
|
+
export { FontSettingsPanel } from "./components/FontSettingsPanel";
|
|
2
3
|
export { OverlayUI } from "./components/OverlayUI";
|
|
3
4
|
export { aspectRatio, BasisHeight, BasisWidth } from "./constants/screen-size";
|
|
4
5
|
export type { AudioSettings } from "./contexts/AudioContext";
|
|
5
6
|
export { useAudioSettings } from "./contexts/AudioContext";
|
|
6
7
|
export { useDataAPI } from "./contexts/DataContext";
|
|
8
|
+
export { getFontFamilyStyle, getUIFontFamilyStyle, } from "./hooks/useFontLoader";
|
|
7
9
|
export { setGlobalUIAPI, usePluginAPI, useUIVisibility, } from "./hooks/usePluginAPI";
|
|
8
10
|
export { useScreenScale, useScreenSize, useToPixel, } from "./hooks/useScreenSize";
|
|
9
11
|
export { Player } from "./Player";
|
|
10
|
-
export type { BacklogData, DataAPI, DataContext, PlayerSettingsData, ScenarioPlaybackData, } from "./sdk";
|
|
11
|
-
export { ComponentType } from "./sdk";
|
|
12
|
-
export type { ActionNode, BacklogEntry, Character, DisplayedCharacter, EntityState, PlayerProps, PlayerSettings, PlayerState, PluginConfig, PublishedScenario, ScenarioBlock, ScenarioBlockAttributeValue, ScenarioBlockCharacter, ScenarioBlockEntityAttributeValue, ScenarioBlockType, } from "./types";
|
|
12
|
+
export type { BacklogData, BlockChangeContext, DataAPI, DataContext, FontsData, PlayerSettingsData, ScenarioPlaybackData, TransitionSource, } from "./sdk";
|
|
13
|
+
export { ComponentType, renderTextWithLineBreaks } from "./sdk";
|
|
14
|
+
export type { ActionNode, BacklogEntry, Character, DisplayedCharacter, EntityState, FontType, PlayerProps, PlayerSettings, PlayerState, PluginConfig, PublishedScenario, ScenarioBlock, ScenarioBlockAttributeValue, ScenarioBlockCharacter, ScenarioBlockEntityAttributeValue, ScenarioBlockType, WorkFont, WorkSound, } from "./types";
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
// Screen size system
|
|
2
2
|
export { useScreenSizeAtom } from "./atoms/screen-size";
|
|
3
|
+
export { FontSettingsPanel } from "./components/FontSettingsPanel";
|
|
3
4
|
export { OverlayUI } from "./components/OverlayUI";
|
|
4
5
|
export { aspectRatio, BasisHeight, BasisWidth } from "./constants/screen-size";
|
|
5
6
|
export { useAudioSettings } from "./contexts/AudioContext";
|
|
6
7
|
export { useDataAPI } from "./contexts/DataContext";
|
|
8
|
+
export { getFontFamilyStyle, getUIFontFamilyStyle, } from "./hooks/useFontLoader";
|
|
7
9
|
export { setGlobalUIAPI, usePluginAPI, useUIVisibility, } from "./hooks/usePluginAPI";
|
|
8
10
|
export { useScreenScale, useScreenSize, useToPixel, } from "./hooks/useScreenSize";
|
|
9
11
|
export { Player } from "./Player";
|
|
10
|
-
export { ComponentType } from "./sdk";
|
|
12
|
+
export { ComponentType, renderTextWithLineBreaks } from "./sdk";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { type ActionExecutionContext, type ActionNodeDefinition, type BlockChangeContext, type CharacterContext, type CharacterSpeakContext, ComponentType, type DialogueContext, type LunaPlugin, type ScenarioContext, type ScenarioReadyContext, type UIAPI } from "../sdk";
|
|
2
|
+
import { type ActionExecutionContext, type ActionNodeDefinition, type BlockChangeContext, type CharacterContext, type CharacterSpeakContext, ComponentType, type DataAPI, type DialogueContext, type LunaPlugin, type ScenarioContext, type ScenarioReadyContext, type UIAPI } from "../sdk";
|
|
3
3
|
export interface LoadedPlugin {
|
|
4
4
|
plugin: LunaPlugin;
|
|
5
5
|
instance: PluginInstance;
|
|
@@ -11,12 +11,15 @@ interface PluginHooksImpl {
|
|
|
11
11
|
onScenarioReady?: (context: ScenarioReadyContext) => void;
|
|
12
12
|
onBlockChange?: (context: BlockChangeContext) => void;
|
|
13
13
|
onCharacterEnter?: (context: CharacterContext) => void;
|
|
14
|
-
onCharacterExit?: (context: CharacterContext) => void;
|
|
15
14
|
onDialogueShow?: (context: DialogueContext) => void;
|
|
16
15
|
characterSpeakHandler?: (context: CharacterSpeakContext) => void;
|
|
17
16
|
onActionExecute?: (context: ActionExecutionContext) => void;
|
|
18
17
|
onScenarioStart?: (context: ScenarioContext) => void;
|
|
19
18
|
onScenarioEnd?: (context: ScenarioContext) => void;
|
|
19
|
+
onBranchStart?: (context: import("../sdk").BranchStartContext) => void;
|
|
20
|
+
onChoiceSelected?: (context: import("../sdk").ChoiceSelectedContext) => void;
|
|
21
|
+
onBranchEnd?: () => void;
|
|
22
|
+
onBranchBlockChange?: (context: import("../sdk").BranchBlockChangeContext) => void;
|
|
20
23
|
}
|
|
21
24
|
export interface PluginInstance {
|
|
22
25
|
actionNodes: Map<string, ActionNodeDefinition>;
|
|
@@ -24,23 +27,46 @@ export interface PluginInstance {
|
|
|
24
27
|
styles: Map<string, string[]>;
|
|
25
28
|
effects: Map<string, HTMLElement>;
|
|
26
29
|
overlays: Map<string, HTMLElement>;
|
|
27
|
-
components: Map<ComponentType, React.ComponentType<
|
|
30
|
+
components: Map<ComponentType, React.ComponentType<{
|
|
31
|
+
dataAPI?: DataAPI;
|
|
32
|
+
}>>;
|
|
28
33
|
assetUrls: Map<string, string>;
|
|
29
34
|
}
|
|
30
35
|
export declare class PluginManager {
|
|
31
36
|
private plugins;
|
|
32
37
|
private styleElements;
|
|
38
|
+
private originalClassNames;
|
|
33
39
|
private injectedStyles;
|
|
34
40
|
private storage;
|
|
35
41
|
private componentRegistry;
|
|
36
42
|
private uiVisibilityState;
|
|
37
43
|
private uiVisibilityListeners;
|
|
44
|
+
private selectChoiceCallback;
|
|
45
|
+
private getBranchStateCallback;
|
|
46
|
+
private emotionEffectUpdaterCallback;
|
|
47
|
+
private dataContextGetter;
|
|
48
|
+
private preloadPromises;
|
|
49
|
+
private muteAudio;
|
|
50
|
+
private workSounds;
|
|
51
|
+
private clickSoundUrl;
|
|
52
|
+
private clickSoundVolume;
|
|
53
|
+
private clickSoundOverridden;
|
|
38
54
|
constructor();
|
|
55
|
+
/**
|
|
56
|
+
* 開発環境かどうかを判定
|
|
57
|
+
* localhost、127.0.0.1、またはポート3000で実行されている場合に true を返す
|
|
58
|
+
*/
|
|
59
|
+
private isDevelopment;
|
|
39
60
|
/**
|
|
40
61
|
* グローバルReactランタイムを初期化(クライアントサイドのみ)
|
|
62
|
+
* 既に初期化済みの場合はスキップ
|
|
41
63
|
*/
|
|
42
64
|
private initializeReactRuntime;
|
|
43
|
-
loadPlugin(packageName: string, bundleUrl: string, config?: unknown
|
|
65
|
+
loadPlugin(packageName: string, bundleUrl: string, config?: unknown, assets?: {
|
|
66
|
+
filename: string;
|
|
67
|
+
url: string;
|
|
68
|
+
}[]): Promise<void>;
|
|
69
|
+
private doLoadPlugin;
|
|
44
70
|
private loadPluginScript;
|
|
45
71
|
private createPluginAPI;
|
|
46
72
|
private applyStyles;
|
|
@@ -52,7 +78,9 @@ export declare class PluginManager {
|
|
|
52
78
|
setPluginEnabled(packageName: string, enabled: boolean): void;
|
|
53
79
|
cleanup(): void;
|
|
54
80
|
private findPluginByComponentType;
|
|
55
|
-
getComponent(type: ComponentType): React.ComponentType
|
|
81
|
+
getComponent(type: ComponentType): React.ComponentType<{
|
|
82
|
+
dataAPI?: DataAPI;
|
|
83
|
+
}> | null;
|
|
56
84
|
hasComponent(type: ComponentType): boolean;
|
|
57
85
|
getRegisteredComponents(): ComponentType[];
|
|
58
86
|
/**
|
|
@@ -104,5 +132,58 @@ export declare class PluginManager {
|
|
|
104
132
|
* @param type - コンポーネントタイプ
|
|
105
133
|
*/
|
|
106
134
|
hideUI(type: ComponentType): void;
|
|
135
|
+
setSelectChoiceCallback(callback: (choiceId: string) => void): void;
|
|
136
|
+
setGetBranchStateCallback(callback: () => import("../types").ConversationBranchState | null): void;
|
|
137
|
+
setEmotionEffectUpdaterCallback(callback: (state: import("../sdk").EmotionEffectState | null) => void): void;
|
|
138
|
+
setDataContextGetter(callback: () => import("../sdk").DataContext | null): void;
|
|
139
|
+
/**
|
|
140
|
+
* 全てのアセットプリロードが完了するまで待機
|
|
141
|
+
* @returns プリロード完了時にresolveするPromise
|
|
142
|
+
*/
|
|
143
|
+
waitForPreloads(): Promise<void>;
|
|
144
|
+
/**
|
|
145
|
+
* 音声のミュート状態を設定
|
|
146
|
+
* @param mute - ミュートするかどうか
|
|
147
|
+
*/
|
|
148
|
+
setMuteAudio(mute: boolean): void;
|
|
149
|
+
/**
|
|
150
|
+
* 作品のサウンドデータを設定
|
|
151
|
+
* @param sounds - サウンドIDをキーとしたURL/名前のマップ
|
|
152
|
+
*/
|
|
153
|
+
setWorkSounds(sounds: Array<{
|
|
154
|
+
id: string;
|
|
155
|
+
url: string;
|
|
156
|
+
name: string;
|
|
157
|
+
}>): void;
|
|
158
|
+
/**
|
|
159
|
+
* 作品のサウンドURLを取得
|
|
160
|
+
* @param soundId - サウンドID
|
|
161
|
+
*/
|
|
162
|
+
getWorkSoundUrl(soundId: string): string | null;
|
|
163
|
+
/**
|
|
164
|
+
* ビルトインのクリック音を設定
|
|
165
|
+
* @param url - サウンドファイルのURL(nullで無効化)
|
|
166
|
+
* @param volume - 音量(0.0 - 1.0)
|
|
167
|
+
*/
|
|
168
|
+
setClickSound(url: string | null, volume?: number): void;
|
|
169
|
+
/**
|
|
170
|
+
* プラグインがクリック音を上書きする
|
|
171
|
+
* これを呼び出すと、ビルトインのクリック音は再生されなくなる
|
|
172
|
+
*/
|
|
173
|
+
overrideClickSound(): void;
|
|
174
|
+
/**
|
|
175
|
+
* プラグインのクリック音上書きをリセット
|
|
176
|
+
* 各ブロック遷移の前に呼び出す
|
|
177
|
+
*/
|
|
178
|
+
resetClickSoundOverride(): void;
|
|
179
|
+
/**
|
|
180
|
+
* クリック音が上書きされているかを取得
|
|
181
|
+
*/
|
|
182
|
+
isClickSoundOverridden(): boolean;
|
|
183
|
+
/**
|
|
184
|
+
* ビルトインのクリック音を再生
|
|
185
|
+
* プラグインで上書きされている場合やミュート中は再生しない
|
|
186
|
+
*/
|
|
187
|
+
playClickSound(): void;
|
|
107
188
|
}
|
|
108
189
|
export {};
|