Implement WebGL page reserve navigation

This commit is contained in:
2026-06-08 10:25:54 +02:00
parent 3e28d7db23
commit efd1e6cfff
13 changed files with 571 additions and 52 deletions
+71 -2
View File
@@ -6,13 +6,15 @@ import { BaseModule } from './base-module.js';
const DEFAULT_BOOK_PAGE_COUNT = 300;
const DEFAULT_BOOK_PROGRESS = 0;
const DEFAULT_PAGE_RESERVE = 50;
class WebGLBookSceneModule extends BaseModule {
constructor() {
super('webgl-book-scene', 'WebGL Book Scene');
this.dependencies = ['persistence-manager', 'localization', 'book-texture-renderer'];
this.dependencies = ['persistence-manager', 'localization', 'game-config', 'book-texture-renderer'];
this.persistenceManager = null;
this.localization = null;
this.gameConfig = null;
this.mode = '2d';
this.is3dSupported = false;
this.labImportPromise = null;
@@ -29,6 +31,9 @@ class WebGLBookSceneModule extends BaseModule {
'ensureShell',
'initializeScene',
'detectWebGLSupport',
'getMetadataNumber',
'getFixedBookPageCount',
'getFixedPageReserve',
'createLabHost',
'installPreferenceBridge',
'installTextureEventBridge',
@@ -49,6 +54,7 @@ class WebGLBookSceneModule extends BaseModule {
async initialize() {
this.persistenceManager = this.getModule('persistence-manager');
this.localization = this.getModule('localization');
this.gameConfig = this.getModule('game-config');
this.reportProgress(15, 'Checking WebGL support');
this.is3dSupported = this.detectWebGLSupport();
@@ -76,14 +82,42 @@ class WebGLBookSceneModule extends BaseModule {
initializeScenePreferences() {
if (!this.persistenceManager) return;
const fixedPageCount = this.getFixedBookPageCount();
const fixedPageReserve = this.getFixedPageReserve();
const scenePrefs = this.persistenceManager.getPreference('webgl', 'bookPageCount', null);
if (!Number.isFinite(Number(scenePrefs))) {
if (Number.isFinite(fixedPageCount)) {
this.persistenceManager.updatePreference('webgl', 'bookPageCount', fixedPageCount);
} else if (!Number.isFinite(Number(scenePrefs))) {
this.persistenceManager.updatePreference('webgl', 'bookPageCount', DEFAULT_BOOK_PAGE_COUNT);
}
const progress = this.persistenceManager.getPreference('webgl', 'bookProgress', null);
if (!Number.isFinite(Number(progress))) {
this.persistenceManager.updatePreference('webgl', 'bookProgress', DEFAULT_BOOK_PROGRESS);
}
const pageReserve = this.persistenceManager.getPreference('webgl', 'pageReserve', null);
if (Number.isFinite(fixedPageReserve)) {
this.persistenceManager.updatePreference('webgl', 'pageReserve', fixedPageReserve);
} else if (!Number.isFinite(Number(pageReserve))) {
this.persistenceManager.updatePreference('webgl', 'pageReserve', DEFAULT_PAGE_RESERVE);
}
}
getMetadataNumber(keys = []) {
const metadata = this.gameConfig?.getMetadata?.() || {};
for (const key of keys) {
if (!Object.prototype.hasOwnProperty.call(metadata, key)) continue;
const value = Number(metadata[key]);
if (Number.isFinite(value)) return value;
}
return null;
}
getFixedBookPageCount() {
return this.getMetadataNumber(['bookPageCount', 'defaultBookPageCount', 'webglBookPageCount']);
}
getFixedPageReserve() {
return this.getMetadataNumber(['pageReserve', 'defaultPageReserve', 'webglPageReserve']);
}
resolveInitialMode() {
@@ -166,10 +200,15 @@ class WebGLBookSceneModule extends BaseModule {
const pageCount = this.persistenceManager?.getPreference?.('webgl', 'bookPageCount', DEFAULT_BOOK_PAGE_COUNT) ?? DEFAULT_BOOK_PAGE_COUNT;
const progress = this.persistenceManager?.getPreference?.('webgl', 'bookProgress', DEFAULT_BOOK_PROGRESS) ?? DEFAULT_BOOK_PROGRESS;
const pageReserve = this.persistenceManager?.getPreference?.('webgl', 'pageReserve', DEFAULT_PAGE_RESERVE) ?? DEFAULT_PAGE_RESERVE;
window.WebGLBookInitialState = {
appMode: true,
pageCount,
progress,
pageReserve,
fixedPageCount: this.getFixedBookPageCount(),
fixedPageReserve: this.getFixedPageReserve(),
t: (key, params = {}) => this.t(key, params),
reportProgress: (percent, message) => {
this.reportProgress(percent, message);
}
@@ -283,6 +322,34 @@ class WebGLBookSceneModule extends BaseModule {
this.preferenceWriteGuard = true;
this.persistenceManager?.updatePreference?.('webgl', 'bookPageCount', value);
this.preferenceWriteGuard = false;
},
updatePageReserve: (value) => {
if (this.preferenceWriteGuard) return;
this.preferenceWriteGuard = true;
this.persistenceManager?.updatePreference?.('webgl', 'pageReserve', value);
this.preferenceWriteGuard = false;
},
getBookState: () => window.BookLabDebug?.getBookState?.() || {
pageCount: this.persistenceManager?.getPreference?.('webgl', 'bookPageCount', DEFAULT_BOOK_PAGE_COUNT) ?? DEFAULT_BOOK_PAGE_COUNT,
pageReserve: this.persistenceManager?.getPreference?.('webgl', 'pageReserve', DEFAULT_PAGE_RESERVE) ?? DEFAULT_PAGE_RESERVE,
progress: this.persistenceManager?.getPreference?.('webgl', 'bookProgress', DEFAULT_BOOK_PROGRESS) ?? DEFAULT_BOOK_PROGRESS
},
applyBookState: (state = {}) => {
const pageCount = Number(state.pageCount);
const pageReserve = Number(state.pageReserve);
const progress = Number(state.progress);
if (Number.isFinite(pageCount)) {
this.persistenceManager?.updatePreference?.('webgl', 'bookPageCount', pageCount);
window.BookLabDebug?.setBookPageCount?.(pageCount);
}
if (Number.isFinite(pageReserve)) {
this.persistenceManager?.updatePreference?.('webgl', 'pageReserve', pageReserve);
window.BookLabDebug?.setPageReserve?.(pageReserve);
}
if (Number.isFinite(progress)) {
this.persistenceManager?.updatePreference?.('webgl', 'bookProgress', progress);
window.BookLabDebug?.setReadingProgress?.(progress);
}
}
};
}
@@ -456,6 +523,8 @@ class WebGLBookSceneModule extends BaseModule {
window.BookLabDebug?.setReadingProgress?.(value);
} else if (key === 'bookPageCount' && !this.preferenceWriteGuard) {
window.BookLabDebug?.setBookPageCount?.(value);
} else if (key === 'pageReserve' && !this.preferenceWriteGuard) {
window.BookLabDebug?.setPageReserve?.(value);
}
}