|
|
|
@ -6,6 +6,12 @@ import { SceneType } from "@/enums/SceneType"; |
|
|
|
import { BaseScene } from "./BaseScene"; |
|
|
|
import type { SceneConfig, IBaseScene } from "./types"; |
|
|
|
|
|
|
|
declare global { |
|
|
|
interface Container { |
|
|
|
_isHolderLast?: boolean; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
type StageChangeCallback = ( |
|
|
|
current: IBaseScene, |
|
|
|
previous: IBaseScene | undefined |
|
|
|
@ -56,6 +62,11 @@ class SceneManager { |
|
|
|
|
|
|
|
/** 注册场景 */ |
|
|
|
registerScene(scene: IBaseScene): void { |
|
|
|
if (!scene.name) { |
|
|
|
logger.warn("SceneManager: scene name cannot be empty"); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (this.scenes.has(scene.name)) { |
|
|
|
logger.warn(`SceneManager: scene "${scene.name}" already registered`); |
|
|
|
} |
|
|
|
@ -76,6 +87,11 @@ class SceneManager { |
|
|
|
|
|
|
|
/** 初始化入口场景 */ |
|
|
|
initScene(name: string): void { |
|
|
|
if (!name) { |
|
|
|
logger.warn("SceneManager: scene name cannot be empty"); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
const scene = this.getSceneOrThrow(name); |
|
|
|
this._currentScene = scene; |
|
|
|
|
|
|
|
@ -89,6 +105,11 @@ class SceneManager { |
|
|
|
|
|
|
|
/** 切换场景 */ |
|
|
|
async changeScene(name: string, options?: { isHolderLast?: boolean }): Promise<void> { |
|
|
|
if (!name) { |
|
|
|
logger.warn("SceneManager: scene name cannot be empty"); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
const previous = this._currentScene; |
|
|
|
if (!previous) { |
|
|
|
throw new Error(`SceneManager: no current scene, call initScene first`); |
|
|
|
@ -100,7 +121,6 @@ class SceneManager { |
|
|
|
if (previous.type === SceneType.Normal) { |
|
|
|
if (options?.isHolderLast) { |
|
|
|
previous.stage.visible = false; |
|
|
|
// @ts-ignore 标记保留
|
|
|
|
previous.stage._isHolderLast = true; |
|
|
|
} else { |
|
|
|
// 销毁场景
|
|
|
|
@ -123,11 +143,12 @@ class SceneManager { |
|
|
|
|
|
|
|
// 处理目标场景
|
|
|
|
if (target.type === SceneType.Normal) { |
|
|
|
// @ts-ignore
|
|
|
|
if (target.stage._isHolderLast) { |
|
|
|
target.stage.visible = true; |
|
|
|
} else { |
|
|
|
this.game.stage.addChild(target.stage); |
|
|
|
if (!this.game.stage.children.includes(target.stage)) { |
|
|
|
this.game.stage.addChild(target.stage); |
|
|
|
} |
|
|
|
} |
|
|
|
} else if (target.type === SceneType.Resident) { |
|
|
|
target.stage.visible = true; |
|
|
|
@ -139,7 +160,7 @@ class SceneManager { |
|
|
|
target._assetsLoaded = true; |
|
|
|
} |
|
|
|
|
|
|
|
if (!target._layoutDone || target.stage !== this.getSceneOrThrow(name).stage) { |
|
|
|
if (!target._layoutDone) { |
|
|
|
await target.layout?.(); |
|
|
|
target._layoutDone = true; |
|
|
|
} |
|
|
|
@ -149,15 +170,25 @@ class SceneManager { |
|
|
|
// 触发回调
|
|
|
|
await this.emitStageChange(target, previous); |
|
|
|
|
|
|
|
logger.debug(`SceneManager: changed from "${previous?.name}" to "${name}"`); |
|
|
|
logger.debug(`SceneManager: changed from "${previous.name}" to "${name}"`); |
|
|
|
} |
|
|
|
|
|
|
|
/** 获取已注册场景 */ |
|
|
|
getScene(name: string): IBaseScene | undefined { |
|
|
|
if (!name) { |
|
|
|
logger.warn("SceneManager: scene name cannot be empty"); |
|
|
|
return undefined; |
|
|
|
} |
|
|
|
|
|
|
|
return this.scenes.get(name); |
|
|
|
} |
|
|
|
|
|
|
|
getSceneOrThrow(name: string): IBaseScene { |
|
|
|
if (!name) { |
|
|
|
logger.warn("SceneManager: scene name cannot be empty"); |
|
|
|
throw new Error("SceneManager: scene name cannot be empty"); |
|
|
|
} |
|
|
|
|
|
|
|
const scene = this.scenes.get(name); |
|
|
|
if (!scene) { |
|
|
|
throw new Error(`SceneManager: scene "${name}" not registered`); |
|
|
|
@ -167,6 +198,11 @@ class SceneManager { |
|
|
|
|
|
|
|
/** 确保场景存在,不存在则创建容器 */ |
|
|
|
ensureSceneExists(name: string, type: SceneType = SceneType.Normal): Container { |
|
|
|
if (!name) { |
|
|
|
logger.warn("SceneManager: scene name cannot be empty"); |
|
|
|
return new Container(); |
|
|
|
} |
|
|
|
|
|
|
|
if (this.scenes.has(name)) { |
|
|
|
return this.getSceneOrThrow(name).stage; |
|
|
|
} |
|
|
|
@ -187,6 +223,11 @@ class SceneManager { |
|
|
|
} |
|
|
|
|
|
|
|
hasScene(name: string): boolean { |
|
|
|
if (!name) { |
|
|
|
logger.warn("SceneManager: scene name cannot be empty"); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
return this.scenes.has(name); |
|
|
|
} |
|
|
|
} |
|
|
|
|