0.2.5-dev: official battlefield scenes on the 3D board — a local fetch / extract step for the season scene bundles, per-field scene rendering with the metal board as fallback, the full bundle can include the extracted scenes and setup can fetch them (--scenes); nothing official is stored in the repository (PR #533 by @andrew05060414, ported; the owner's decision of 2026-10-12); golden: unchanged

This commit is contained in:
sganggs committed 2026-10-12 14:59:20 +08:00
1 parent 7fd0478dc0
commit d482fbb8ba
19 files changed
+1659 -22

No files matched your search

+11 -3
View File
@@ -125,7 +125,7 @@ import { backdropTextures, shadowTexture, refreshTierChips, refreshDownLabels, s
import { TILE_H, TIER_COLORS, COLORS } from './style.js';
import { loadBoardArt } from './boardArt.js';
import { ImpostorAtlas } from './impostor.js';
import { loadThree, loadBoardPack, webgl2Available, boardArtListed } from './board3d/load.js';
import { loadThree, loadBoardPack, loadScenePack, webgl2Available, boardArtListed } from './board3d/load.js';
import { BoardScene } from './board3d/scene.js';
import { unionAreas } from './board3d/layout.js';
import { layoutPen, penSignature } from './pen.js';
@@ -361,6 +361,14 @@ export async function createFieldView(host, options = {}) {
// lost-context recovery: the THREE module + art pack of the last 3D board, the pending retry, failures so far
const recover = { THREE: null, pack: null, timer: 0, tries: 0, since: 0, off: false, count: 0 };
setupCleanup.push(() => { clearTimeout(recover.timer); disable3d(); });
/** The stage's official scene, once loaded (the procedural board shows meanwhile and when there is none). */
function useOfficialScene(st) {
const id = st && typeof st.id === 'string' ? st.id : '';
if (!id || !board3d) return;
loadScenePack(assets, id).then((scene) => {
if (scene && !destroyed && board3d && stageRec && stageRec.id === id) board3d.setScenePack(id, scene);
}).catch(() => {});
}
function enable3d(THREE, pack) {
if (destroyed || board3d || !THREE || !pack) return false;
recover.THREE = THREE; recover.pack = pack;
@@ -380,7 +388,7 @@ export async function createFieldView(host, options = {}) {
tiles.setExternal(true);
backdrop.visible = false;
b.setArea(boardArea(viewKind(camKind, camOpts)));
if (stageRec) b.setStage(stageRec);
if (stageRec) { b.setStage(stageRec); useOfficialScene(stageRec); }
b.setFocus(camRect());
b.setBattleRect(mode === 'battle' && battleMeta ? battleMeta.rect : null);
tiles.project(cam, true);
@@ -630,7 +638,7 @@ export async function createFieldView(host, options = {}) {
stageRec = st;
tiles.setStage(st);
tiles.setBattleRect(mode === 'battle' && battleMeta ? battleMeta.rect : null);
if (board3d) { board3d.setStage(st); board3d.setBattleRect(mode === 'battle' && battleMeta ? battleMeta.rect : null); }
if (board3d) { board3d.setStage(st); board3d.setBattleRect(mode === 'battle' && battleMeta ? battleMeta.rect : null); useOfficialScene(st); }
tiles.project(cam, true);
// a pen laid out before the stage arrived (setPrep / a scouting board first) used the default zones and the old
// tile heights: lay it out again on this stage