Skip to content

Commit a1a6b6a

Browse files
committed
Merge branch 'dev' into feat/editor-preview-sync-v1-runtime
2 parents 1d265ed + 8cb39d9 commit a1a6b6a

9 files changed

Lines changed: 100 additions & 22 deletions

File tree

packages/webgal/public/game/template/Stage/TextBox/textbox.scss

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,10 @@
177177
overflow: hidden;
178178
}
179179

180-
.read {
180+
.readTextOuter {
181+
background-image: none;
182+
background-clip: border-box;
183+
-webkit-background-clip: border-box;
181184
color: #C0C0C0;
185+
-webkit-text-fill-color: #C0C0C0;
182186
}

packages/webgal/src/Core/Modules/readHistory.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,15 @@ import { setReadHistory } from "@/store/userDataReducer";
88
import { setStorage } from "../controller/storage/storageController";
99
import { stageStateManager } from '@/Core/Modules/stage/stageStateManager';
1010

11+
let debugTextReadMode: boolean | null = null;
12+
13+
export function setDebugTextReadMode(isRead: boolean | null) {
14+
debugTextReadMode = isRead;
15+
if (isRead !== null) {
16+
stageStateManager.setStageAndCommit('isRead', isRead);
17+
}
18+
}
19+
1120
export class ReadHistoryManager {
1221
private history: Map<string, Uint8Array> = new Map();
1322

@@ -107,7 +116,7 @@ export class ReadHistoryManager {
107116
const bitset = this.history.get(scenarioName)!;
108117
isRead = (bitset[index >> 3] & (1 << (index & 7))) !== 0;
109118
}
110-
stageStateManager.setStage('isRead', isRead);
119+
stageStateManager.setStage('isRead', debugTextReadMode ?? isRead);
111120
if (!isRead) {
112121
this.addReadHistory();
113122
}

packages/webgal/src/Core/util/syncWithEditor/previewSyncRuntime.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ interface ActiveModuleState {
9191
getCalculationStageState: ReturnType<typeof vi.fn>;
9292
updateEffectAndCommit: ReturnType<typeof vi.fn>;
9393
};
94+
setDebugTextReadMode: ReturnType<typeof vi.fn>;
9495
loggerInfo: ReturnType<typeof vi.fn>;
9596
loggerWarn: ReturnType<typeof vi.fn>;
9697
loggerError: ReturnType<typeof vi.fn>;
@@ -114,6 +115,7 @@ interface WebSocketRuntimeHarness {
114115
}>;
115116
layers: Array<{ id: string }>;
116117
};
118+
setDebugTextReadMode: ReturnType<typeof vi.fn>;
117119
updateEffectAndCommit: ReturnType<typeof vi.fn>;
118120
webgalParserParse: ReturnType<typeof vi.fn>;
119121
WebGAL: Record<string, any>;
@@ -196,6 +198,11 @@ vi.doMock('@/Core/Modules/stage/stageStateManager', () => ({
196198
return getActiveModuleState().stageStateManager;
197199
},
198200
}));
201+
vi.doMock('@/Core/Modules/readHistory', () => ({
202+
get setDebugTextReadMode() {
203+
return getActiveModuleState().setDebugTextReadMode;
204+
},
205+
}));
199206
vi.doMock('@/Core/Modules/stage/stageInterface', () => ({
200207
baseTransform: {
201208
position: { x: 0, y: 0 },
@@ -300,6 +307,7 @@ async function setupWebSocketRuntimeHarness(): Promise<WebSocketRuntimeHarness>
300307
const nextSentence = vi.fn();
301308
const resetStage = vi.fn();
302309
const updateEffectAndCommit = stageStateManager.updateEffectAndCommit;
310+
const setDebugTextReadMode = vi.fn();
303311

304312
activeModuleState = {
305313
webgalStore,
@@ -315,6 +323,7 @@ async function setupWebSocketRuntimeHarness(): Promise<WebSocketRuntimeHarness>
315323
resetStage,
316324
updateEffectAndCommit,
317325
stageStateManager,
326+
setDebugTextReadMode,
318327
loggerInfo: vi.fn(),
319328
loggerWarn: vi.fn(),
320329
loggerError: vi.fn(),
@@ -341,6 +350,7 @@ async function setupWebSocketRuntimeHarness(): Promise<WebSocketRuntimeHarness>
341350
runScript,
342351
socket,
343352
stageState,
353+
setDebugTextReadMode,
344354
updateEffectAndCommit,
345355
webgalParserParse,
346356
WebGAL,
@@ -601,6 +611,29 @@ describe('startPreviewSyncRuntime runtime behavior', () => {
601611
});
602612
});
603613

614+
it('applies text read mode updates through the v1 protocol and replies with a success envelope', async () => {
615+
const harness = await setupWebSocketRuntimeHarness();
616+
617+
await completeRegisterPreviewHandshake(harness);
618+
619+
harness.socket.emitMessage(
620+
JSON.stringify(
621+
createRequestEnvelope('preview.command.set-text-read-mode', 'req-set-text-read-mode', {
622+
isRead: true,
623+
}),
624+
),
625+
);
626+
await flushMicrotasks();
627+
628+
expect(harness.setDebugTextReadMode).toHaveBeenCalledWith(true);
629+
expect(parseSentEnvelope(harness.socket, 3)).toEqual({
630+
kind: 'response',
631+
type: 'preview.command.set-text-read-mode',
632+
requestId: 'req-set-text-read-mode',
633+
payload: {},
634+
});
635+
});
636+
604637
it('re-registers with the same identity and re-publishes ready plus snapshot after reconnect', async () => {
605638
const harness = await setupWebSocketRuntimeHarness();
606639

packages/webgal/src/Core/util/syncWithEditor/previewSyncRuntime.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
SetComponentVisibilityPayload,
1414
SetEffectPayload,
1515
SetFontOptimizationPayload,
16+
SetTextReadModePayload,
1617
StageSnapshotUpdatedPayload,
1718
SyncScenePayload,
1819
FastPreviewTimeoutPayload,
@@ -36,6 +37,7 @@ import {
3637
PreviewSyncTransportSocket,
3738
} from './runtime/previewSyncTransport';
3839
import { executePreviewSyncSceneCommand } from './runtime/previewSyncSceneCommand';
40+
import { setDebugTextReadMode } from '@/Core/Modules/readHistory';
3941

4042
let previewSyncRuntimeStarted = false;
4143
type StageStateSnapshot = IStageState;
@@ -217,6 +219,10 @@ export const startPreviewSyncRuntime = () => {
217219
applyComponentVisibility(payload);
218220
};
219221

222+
const handleSetTextReadMode = (payload: SetTextReadModePayload) => {
223+
setDebugTextReadMode(payload.isRead);
224+
};
225+
220226
const handleSetEffect = (payload: SetEffectPayload) => {
221227
const targetEffect = stageStateManager
222228
.getCalculationStageState()
@@ -272,6 +278,10 @@ export const startPreviewSyncRuntime = () => {
272278
handleSetFontOptimization(payload);
273279
return {};
274280
},
281+
'preview.command.set-text-read-mode': (payload: SetTextReadModePayload) => {
282+
handleSetTextReadMode(payload);
283+
return {};
284+
},
275285
};
276286

277287
const handlePreviewRequest = <TType extends PreviewRequestType>(

packages/webgal/src/Stage/TextBox/IMSSTextbox.tsx

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ export default function IMSSTextbox(props: ITextboxProps) {
3030
} = props;
3131

3232
const applyStyle = useApplyStyle('textbox');
33+
const readTextClassName = isRead ? ` ${applyStyle('readText', styles.readText)}` : '';
34+
const readTextOuterClassName = isRead
35+
? ` ${applyStyle('readTextOuter', styles.readTextOuter)}`
36+
: '';
37+
const readTextInnerClassName = isRead ? ` ${applyStyle('readTextInner', styles.readTextInner)}` : '';
3338

3439
useEffect(() => {
3540
function settleText() {
@@ -146,14 +151,18 @@ export default function IMSSTextbox(props: ITextboxProps) {
146151
<span
147152
// data-text={e}
148153
id={`${delay}`}
149-
className={applyStyle('TextBox_textElement_Settled', styles.TextBox_textElement_Settled)}
154+
className={applyStyle('TextBox_textElement_Settled', styles.TextBox_textElement_Settled) + readTextClassName}
150155
key={currentDialogKey + index}
151156
style={{ animationDelay: `${delay}ms`, animationDuration: `${textDuration}ms` }}
152157
>
153158
<span className={styles.zhanwei + styleAllText}>
154159
{e}
155-
<span className={applyStyle('outer', styles.outer) + styleClassName + styleAllText}>{e}</span>
156-
{isUseStroke && <span className={applyStyle('inner', styles.inner) + styleAllText}>{e}</span>}
160+
<span className={applyStyle('outer', styles.outer) + readTextOuterClassName + styleClassName + styleAllText}>
161+
{e}
162+
</span>
163+
{isUseStroke && (
164+
<span className={applyStyle('inner', styles.inner) + readTextInnerClassName + styleAllText}>{e}</span>
165+
)}
157166
</span>
158167
</span>
159168
);
@@ -162,14 +171,21 @@ export default function IMSSTextbox(props: ITextboxProps) {
162171
<span
163172
// data-text={e}
164173
id={`${delay}`}
165-
className={`${applyStyle('TextBox_textElement_start', styles.TextBox_textElement_start)} Textelement_start`}
174+
className={`${applyStyle(
175+
'TextBox_textElement_start',
176+
styles.TextBox_textElement_start,
177+
)}${readTextClassName} Textelement_start`}
166178
key={currentDialogKey + index}
167179
style={{ animationDelay: `${delay}ms`, position: 'relative' }}
168180
>
169181
<span className={styles.zhanwei + styleAllText}>
170182
{e}
171-
<span className={applyStyle('outer', styles.outer) + `${isRead ? ` ${applyStyle('read', styles.read)}` : ''}` + styleClassName + styleAllText}>{e}</span>
172-
{isUseStroke && <span className={applyStyle('inner', styles.inner) + styleAllText}>{e}</span>}
183+
<span className={applyStyle('outer', styles.outer) + readTextOuterClassName + styleClassName + styleAllText}>
184+
{e}
185+
</span>
186+
{isUseStroke && (
187+
<span className={applyStyle('inner', styles.inner) + readTextInnerClassName + styleAllText}>{e}</span>
188+
)}
173189
</span>
174190
</span>
175191
);

packages/webgal/src/Stage/TextBox/textbox.module.scss

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,18 @@ $height: 330px;
235235
overflow: hidden;
236236
}
237237

238-
.read {
238+
.readText {
239+
--webgal-read-text: 1;
240+
}
241+
242+
.readTextOuter {
243+
background-image: none;
244+
background-clip: border-box;
245+
-webkit-background-clip: border-box;
239246
color: #C0C0C0;
247+
-webkit-text-fill-color: #C0C0C0;
248+
}
249+
250+
.readTextInner {
251+
--webgal-read-text-inner: 1;
240252
}

packages/webgal/src/types/editorPreviewProtocol.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ describe('editorPreviewProtocol artifacts', () => {
1818
it('exposes a preview command type guard', () => {
1919
expect(isPreviewCommandType('preview.command.sync-scene')).toBe(true);
2020
expect(isPreviewCommandType('preview.command.run-snippet')).toBe(true);
21+
expect(isPreviewCommandType('preview.command.set-text-read-mode')).toBe(true);
2122
expect(isPreviewCommandType('preview.command.unknown')).toBe(false);
2223
expect(isPreviewCommandType('session.register-preview')).toBe(false);
2324
});

packages/webgal/src/types/editorPreviewProtocol.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ export interface SetFontOptimizationPayload {
3434
enabled: boolean;
3535
}
3636

37+
export interface SetTextReadModePayload {
38+
isRead: boolean;
39+
}
40+
3741
export interface PreviewCommandPayloadByType {
3842
'preview.command.sync-scene': SyncScenePayload;
3943
'preview.command.run-scene-content': RunSceneContentPayload;
@@ -42,6 +46,7 @@ export interface PreviewCommandPayloadByType {
4246
'preview.command.set-effect': SetEffectPayload;
4347
'preview.command.set-component-visibility': SetComponentVisibilityPayload;
4448
'preview.command.set-font-optimization': SetFontOptimizationPayload;
49+
'preview.command.set-text-read-mode': SetTextReadModePayload;
4550
}
4651

4752
export type PreviewCommandType = keyof PreviewCommandPayloadByType;
@@ -54,6 +59,7 @@ const PREVIEW_COMMAND_TYPES = [
5459
'preview.command.set-effect',
5560
'preview.command.set-component-visibility',
5661
'preview.command.set-font-optimization',
62+
'preview.command.set-text-read-mode',
5763
] as const satisfies readonly PreviewCommandType[];
5864

5965
export interface PreviewRequestPayloadByType extends PreviewCommandPayloadByType {}

release-to-server.sh

Lines changed: 0 additions & 13 deletions
This file was deleted.

0 commit comments

Comments
 (0)