Fix UI camera split going stale after a scene restart
A jump cut destroys all cameras and rebuilds a fresh main, leaving the stored split pointing at dead cameras. Worse, `main.ignore()` on the old main sets the id bit that the new main reuses, so objects assigned to the UI pass get ignored by the only live pass — rendering nowhere (the "clip plays in the background" bug). - Add `liveSplit()` which validates the stored split against the scene's live camera list and clears it when stale - Route `ensureUiCameras`, `assignUi`, and `assignWorld` through `liveSplit()` so a stale split is dropped and the pipeline falls back to a single pass
This commit is contained in:
parent
332431ecb5
commit
098b41b2fc
|
|
@ -55,6 +55,44 @@ export function isScreenPinned(obj) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The stored split, validated against the LIVE camera list — or null
|
||||||
|
* (and cleared) when it is stale.
|
||||||
|
*
|
||||||
|
* A scene restart (the jump cut — GameScene._finishJump) runs the
|
||||||
|
* camera manager's shutdown, which DESTROYS every camera (fx-ui
|
||||||
|
* included) and re-adds a single fresh main. The stored split would
|
||||||
|
* then point at dead cameras, and worse: a later `main.ignore()` sets
|
||||||
|
* the OLD main's id bit on the object, and the re-created main reuses
|
||||||
|
* id 1 — so an object "assigned to the UI pass" is ignored by the ONLY
|
||||||
|
* live pass and drawn by no camera at all. That is the jump-clip
|
||||||
|
* "plays in the background" bug: after leaving an effects system, the
|
||||||
|
* next system's clip + opaque backdrop rendered nowhere while the world
|
||||||
|
* stayed fully visible. A split whose cameras are no longer in the
|
||||||
|
* scene's list is invalid — drop it so the pipeline falls back to a
|
||||||
|
* single pass (depth order restores the clip's topness) and a fresh
|
||||||
|
* split can be created if/when one is needed.
|
||||||
|
*
|
||||||
|
* @param {object} scene Phaser scene
|
||||||
|
* @returns {{ main: object, ui: object } | null} the live split, or null
|
||||||
|
*/
|
||||||
|
function liveSplit(scene) {
|
||||||
|
const split = scene._fxUiCameras;
|
||||||
|
const cams = scene.cameras?.cameras;
|
||||||
|
if (
|
||||||
|
split &&
|
||||||
|
split.ui &&
|
||||||
|
split.main &&
|
||||||
|
Array.isArray(cams) &&
|
||||||
|
cams.includes(split.main) &&
|
||||||
|
cams.includes(split.ui)
|
||||||
|
) {
|
||||||
|
return split;
|
||||||
|
}
|
||||||
|
if (split) scene._fxUiCameras = null; // stale (a restart rebuilt the cameras) — forget it
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create (once) the fixed UI camera and partition the scene's
|
* Create (once) the fixed UI camera and partition the scene's
|
||||||
* top-level objects between the two passes. Idempotent — subsequent
|
* top-level objects between the two passes. Idempotent — subsequent
|
||||||
|
|
@ -65,7 +103,7 @@ export function isScreenPinned(obj) {
|
||||||
* the scene has no camera plugin (defensive).
|
* the scene has no camera plugin (defensive).
|
||||||
*/
|
*/
|
||||||
export function ensureUiCameras(scene) {
|
export function ensureUiCameras(scene) {
|
||||||
if (scene._fxUiCameras) return scene._fxUiCameras;
|
if (liveSplit(scene)) return scene._fxUiCameras;
|
||||||
const cameras = scene.cameras;
|
const cameras = scene.cameras;
|
||||||
if (!cameras?.cameras || cameras.cameras.length === 0) return null;
|
if (!cameras?.cameras || cameras.cameras.length === 0) return null;
|
||||||
|
|
||||||
|
|
@ -98,7 +136,7 @@ export function ensureUiCameras(scene) {
|
||||||
* @param {object} child object to attach to the UI pass
|
* @param {object} child object to attach to the UI pass
|
||||||
*/
|
*/
|
||||||
export function assignUi(scene, child) {
|
export function assignUi(scene, child) {
|
||||||
const split = scene._fxUiCameras;
|
const split = liveSplit(scene);
|
||||||
if (split && child) split.main.ignore(child);
|
if (split && child) split.main.ignore(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,6 +150,6 @@ export function assignUi(scene, child) {
|
||||||
* @param {object} child object to keep on the world pass
|
* @param {object} child object to keep on the world pass
|
||||||
*/
|
*/
|
||||||
export function assignWorld(scene, child) {
|
export function assignWorld(scene, child) {
|
||||||
const split = scene._fxUiCameras;
|
const split = liveSplit(scene);
|
||||||
if (split && child) split.ui.ignore(child);
|
if (split && child) split.ui.ignore(child);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue