Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/webgal/src/Core/Modules/stage/stageInterface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ export interface IStageState {
showText: string; // 文字
showTextSize: number; // 文字
showName: string; // 人物名
textboxTheme: string; // 对话框主题
command: string; // 语句指令
choose: Array<IChooseItem>; // 选项列表
vocal: string; // 语音 文件地址(相对或绝对)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export const initState: IStageState = {
showText: '',
showTextSize: -1,
showName: '',
textboxTheme: '',
command: '',
choose: [],
vocal: '',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { describe, expect, it } from 'vitest';
import { resolveDialogDisplayState } from './resolveDialogDisplayState';

describe('resolveDialogDisplayState', () => {
it('uses speaker as the default show name and textbox theme', () => {
expect(
resolveDialogDisplayState({
previousShowName: '',
previousTextboxTheme: '',
speaker: 'anon',
textboxThemeOverride: null,
clear: false,
}),
).toEqual({
showName: 'anon',
textboxTheme: 'anon',
});
});

it('keeps the speaker name and lets textboxTheme override the default theme', () => {
expect(
resolveDialogDisplayState({
previousShowName: '',
previousTextboxTheme: '',
speaker: 'anon',
textboxThemeOverride: 'system',
clear: false,
}),
).toEqual({
showName: 'anon',
textboxTheme: 'system',
});
});

it('inherits the previous state when the sentence does not provide a new speaker or theme', () => {
expect(
resolveDialogDisplayState({
previousShowName: 'anon',
previousTextboxTheme: 'system',
speaker: null,
textboxThemeOverride: null,
clear: false,
}),
).toEqual({
showName: 'anon',
textboxTheme: 'system',
});
});

it('resets the textbox theme to the new speaker when the previous sentence used an override', () => {
expect(
resolveDialogDisplayState({
previousShowName: 'anon',
previousTextboxTheme: 'system',
speaker: 'heroine',
textboxThemeOverride: null,
clear: false,
}),
).toEqual({
showName: 'heroine',
textboxTheme: 'heroine',
});
});

it('clears both show name and textbox theme by default', () => {
expect(
resolveDialogDisplayState({
previousShowName: 'anon',
previousTextboxTheme: 'system',
speaker: null,
textboxThemeOverride: null,
clear: true,
}),
).toEqual({
showName: '',
textboxTheme: '',
});
});

it('allows textboxTheme to override the cleared default', () => {
expect(
resolveDialogDisplayState({
previousShowName: 'anon',
previousTextboxTheme: 'anon',
speaker: null,
textboxThemeOverride: 'system',
clear: true,
}),
).toEqual({
showName: '',
textboxTheme: 'system',
});
});
});
24 changes: 24 additions & 0 deletions packages/webgal/src/Core/gameScripts/resolveDialogDisplayState.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
interface ResolveDialogDisplayStateOptions {
previousShowName: string;
previousTextboxTheme: string;
speaker: string | null;
textboxThemeOverride: string | null;
clear: boolean;
}

interface DialogDisplayState {
showName: string;
textboxTheme: string;
}

export function resolveDialogDisplayState(options: ResolveDialogDisplayStateOptions): DialogDisplayState {
const { previousShowName, previousTextboxTheme, speaker, textboxThemeOverride, clear } = options;

const showName = clear ? '' : (speaker ?? previousShowName);
const textboxTheme = textboxThemeOverride ?? (clear ? '' : (speaker ?? previousTextboxTheme));

return {
showName,
textboxTheme,
};
}
20 changes: 11 additions & 9 deletions packages/webgal/src/Core/gameScripts/say.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { compileSentence } from '@/Stage/TextBox/TextBox';
import { performMouthAnimation } from '@/Core/gameScripts/vocal/vocalAnimation';
import { match } from '@/Core/util/match';
import { stageStateManager } from '@/Core/Modules/stage/stageStateManager';
import { resolveDialogDisplayState } from './resolveDialogDisplayState';

/**
* 进行普通对话的显示
Expand All @@ -29,6 +30,7 @@ export const say = (sentence: ISentence): IPerform => {
const isNotend = getBooleanArgByKey(sentence, 'notend') ?? false; // 是否有 notend 参数
const speaker = getStringArgByKey(sentence, 'speaker'); // 获取说话者
const clear = getBooleanArgByKey(sentence, 'clear') ?? false; // 是否清除说话者
const textboxThemeOverride = getStringArgByKey(sentence, 'theme'); // 覆盖本句对话框主题
const vocal = getStringArgByKey(sentence, 'vocal'); // 是否播放语音

// 如果是concat,那么就继承上一句的key,并且继承上一句对话。
Expand Down Expand Up @@ -75,15 +77,15 @@ export const say = (sentence: ISentence): IPerform => {
break;
}

// 设置显示的角色名称
let showName = stageState.showName; // 先默认继承
if (speaker !== null) {
showName = speaker;
}
if (clear) {
showName = '';
}
stageStateManager.setStage('showName', showName);
const dialogDisplayState = resolveDialogDisplayState({
previousShowName: stageState.showName,
previousTextboxTheme: stageState.textboxTheme,
speaker,
textboxThemeOverride,
clear,
});
stageStateManager.setStage('showName', dialogDisplayState.showName);
stageStateManager.setStage('textboxTheme', dialogDisplayState.textboxTheme);

// 模拟说话
let performSimulateVocalTimeout: ReturnType<typeof setTimeout> | null = null;
Expand Down
3 changes: 2 additions & 1 deletion packages/webgal/src/Stage/TextBox/IMSSTextbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export default function IMSSTextbox(props: ITextboxProps) {
miniAvatar,
isHasName,
showName,
textboxTheme,
font,
textDuration,
isUseStroke,
Expand Down Expand Up @@ -214,7 +215,7 @@ export default function IMSSTextbox(props: ITextboxProps) {
return (
<>
{isText && (
<div className={styles.TextBox_Container}>
<div className={styles.TextBox_Container} data-textbox-theme={textboxTheme || undefined}>
<div
className={
applyStyle('TextBox_main', styles.TextBox_main) +
Expand Down
2 changes: 2 additions & 0 deletions packages/webgal/src/Stage/TextBox/TextBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export const TextBox = () => {
const textArray = compileSentence(stageState.showText, lineLimit);
const isHasName = stageState.showName !== '';
const showName = compileSentence(stageState.showName, lineLimit);
const textboxTheme = stageState.textboxTheme;
const currentConcatDialogPrev = stageState.currentConcatDialogPrev;
const currentDialogKey = stageState.currentDialogKey;
const miniAvatar = stageState.miniAvatar;
Expand Down Expand Up @@ -95,6 +96,7 @@ export const TextBox = () => {
textDelay={textDelay}
showName={showName}
isHasName={isHasName}
textboxTheme={textboxTheme}
currentConcatDialogPrev={currentConcatDialogPrev}
fontSize={size}
currentDialogKey={currentDialogKey}
Expand Down
1 change: 1 addition & 0 deletions packages/webgal/src/Stage/TextBox/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface ITextboxProps {
miniAvatar: string;
showName: EnhancedNode[][];
isHasName: boolean;
textboxTheme: string;
font: string;
textDuration: number;
textSizeState: number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export const TextPreview = (props: any) => {
textDelay: textDelay,
isHasName: isHasName,
showName: showNameArray,
textboxTheme: '',
currentConcatDialogPrev: '',
fontSize: size,
currentDialogKey: String(previewKey),
Expand Down
Loading