//mesh对象池 //为避免重复加载、销毁mesh对象 import { AbstractMesh, MeshBuilder, Observable, TransformNode, Vector3 } from "@babylonjs/core"; import { SceneManager } from "../controller/scene-manager"; import { ModelData, ModelType } from "../model/data/model-data/model-data"; import { ModelInfo } from "../model/info/model/model-info"; import { TsTool } from "./ts-tool"; export class MeshPool { //#region 单例 private static instance: MeshPool; static get Instance() { if (MeshPool.instance == null) { MeshPool.instance = new MeshPool(); } return MeshPool.instance; } //#endregion root: TransformNode; prefabPool: Map = new Map();//预制体池 idlePool: Map = new Map();//空闲池 workingPool: Map = new Map();//工作池 constructor() { this.root = new TransformNode("MeshPoolRoot", SceneManager.Instance.scene); this.root.setEnabled(false);//隐藏起来 } //#region 外部方法 /** * 从对象池导入模型(经过包装盒包装) */ static importMesh(modeltype: ModelType, modelData: ModelData, isNew: boolean = true, fromClone: boolean = true, tag?: string, onSuccess?: (meshBox: AbstractMesh, meshes: AbstractMesh[], result: MeshPoolInfo) => void, onlyPrefab = false,): MeshPoolInfo { let result = MeshPool.Instance.getMesh(modelData.resPath, modelData.resName, fromClone); if (result == null) { //console.log("对象池中没有,要加载:" + path + name); let prefab = MeshPool.Instance.getMeshPrefab(modelData.resPath, modelData.resName); result = new MeshPoolInfo(modelData.resPath, modelData.resName, fromClone); if (prefab == null) { prefab = new MeshPoolInfo(modelData.resPath, modelData.resName, false); prefab.onSuccessObserver = new Observable(); MeshPool.Instance.addPool(MeshPool.Instance.prefabPool, prefab); SceneManager.createModel(modeltype, modelData, true, isNew, tag, (meshes: AbstractMesh[], box: AbstractMesh, modelInfo: ModelInfo) => { prefab.meshes = meshes; prefab.meshBox = box; prefab.modelInfo = modelInfo; prefab.setActive(false); modelInfo.showFollowUI(false); prefab.success(); MeshPool.Instance.addPool(MeshPool.Instance.prefabPool, prefab); if (!onlyPrefab) { if (fromClone) { result.cloneMeshFrom(prefab, modelData, isNew); result.setActive(true); MeshPool.Instance.addPool(MeshPool.Instance.workingPool, result); result.success(); if (onSuccess) { onSuccess(result.meshBox, result.meshes, result); } } else { SceneManager.createModel(modeltype, modelData, true, isNew, tag, (meshes: AbstractMesh[], box: AbstractMesh, modelInfo: ModelInfo) => { result.meshBox = box; result.meshes = meshes; result.modelInfo = modelInfo; result.setActive(true); modelInfo.showFollowUI(false); result.success(); MeshPool.Instance.addPool(MeshPool.Instance.workingPool, result); if (onSuccess) { onSuccess(result.meshBox, result.meshes, result); } }) } } }) return result; } else { if (fromClone) { if (prefab.meshBox == null) { // console.log("找到了预制体,但是还没加载完") prefab.onSuccessObserver.add((eventData: MeshPoolInfo) => { // console.log("加载回调"); result.cloneMeshFrom(prefab, modelData, isNew); result.setActive(true); MeshPool.Instance.addPool(MeshPool.Instance.workingPool, result); result.success(); if (onSuccess) { onSuccess(result.meshBox, result.meshes, result); } }) return result; } else { result.cloneMeshFrom(prefab, modelData, isNew); result.setActive(true); MeshPool.Instance.addPool(MeshPool.Instance.workingPool, result); result.success(); if (onSuccess) { onSuccess(result.meshBox, result.meshes, result); } return result; } } else { SceneManager.createModel(modeltype, modelData, true, isNew, tag, (meshes: AbstractMesh[], box: AbstractMesh, modelInfo: ModelInfo) => { result.meshBox = box; result.meshes = meshes; result.modelInfo = modelInfo; result.setActive(true); modelInfo.showFollowUI(false); MeshPool.Instance.addPool(MeshPool.Instance.workingPool, result); result.success(); if (onSuccess) { onSuccess(result.meshBox, result.meshes, result); } }) return result; } } } else { // console.log("从对象池取出" + result.key); MeshPool.Instance.removePool(MeshPool.Instance.idlePool, result); MeshPool.instance.addPool(MeshPool.Instance.workingPool, result); result.setActive(true); result.success(); if (onSuccess && result.meshBox != null) { onSuccess(result.meshBox, result.meshes, result); } } return result; } /** * 放回到对象池(从工作池放入空闲池) * @param meshPoolInfo */ static disposeMesh(meshPoolInfo: MeshPoolInfo) { MeshPool.Instance.removePool(MeshPool.Instance.workingPool, meshPoolInfo); MeshPool.Instance.addPool(MeshPool.Instance.idlePool, meshPoolInfo); meshPoolInfo.setActive(false); } //#endregion //#region 内部方法 getMesh(path: string, name: string, fromClone: boolean = true): MeshPoolInfo { let result: MeshPoolInfo = null; let resKey = path + name; let poolList = MeshPool.Instance.idlePool.get(resKey); if (poolList != null && poolList.length > 0) { for (let i = 0; i < poolList.length; i++) { if (poolList[i].fromClone == fromClone) { result = poolList[i]; break; } } } else { //console.log("对象池取出失败" + name); } return result; } //放入某池 addPool(pool: Map, value: MeshPoolInfo) { let poolInfo = pool.get(value.key); if (poolInfo == null) { poolInfo = []; pool.set(value.key, poolInfo); } poolInfo.push(value); } //移除池 removePool(pool: Map, value: MeshPoolInfo) { let poolInfo = pool.get(value.key); if (poolInfo == null) { console.error("removePool no key" + value.key); return; } TsTool.arrayRemove(poolInfo, value); } /** * 从预制体池中取出 */ getMeshPrefab(path: string, name: string): MeshPoolInfo { let result: MeshPoolInfo = null; let resKey = path + name; let poolList = MeshPool.Instance.prefabPool.get(resKey); if (poolList != null && poolList.length > 0) { result = poolList[0]; } else { } return result; } //#endregion } /** * 对象池元数据 */ export class MeshPoolInfo { key: string; resPath: string;//资源路径, resName: string; meshBox: AbstractMesh;//对象 fromClone: boolean;//来自克隆 meshes: AbstractMesh[];//所有mesh节点 active: boolean; modelInfo: ModelInfo; onSuccessObserver: Observable; constructor(resPath: string, resName: string, fromClone: boolean = true, mesh?: AbstractMesh, meshes?: AbstractMesh[], modelInfo?: ModelInfo) { this.key = resPath + resName; this.resPath = resPath; this.resName = resName; this.fromClone = fromClone; this.meshBox = mesh; this.meshes = meshes; this.modelInfo = modelInfo; } setActive(active: boolean) { if (this.meshBox != null) { if (active) { this.meshBox.setParent(null); let allNode = this.meshBox.getChildTransformNodes(); for (let i = 0; i < allNode.length; i++) { allNode[i].setEnabled(true); } this.meshBox.setEnabled(true); } else { this.meshBox.setParent(MeshPool.Instance.root); this.meshBox.position = Vector3.Zero(); // this.meshBox.setEnabled(false); // console.log("放入对象池" + this.meshBox.name); } } } /** * 导入完成 */ success() { if (this.onSuccessObserver != null) { // console.log("导入完成", this.onSuccessObserver.observers); this.onSuccessObserver.notifyObservers(this); this.onSuccessObserver.clear(); } } clone() { let modelInfo = this.modelInfo.clone(); let newMesh = new MeshPoolInfo(this.resPath, this.resName, true, modelInfo.modelBox, modelInfo.models, modelInfo); return newMesh; } /** * 从预制体克隆mesh * @param prefab */ cloneMeshFrom(prefab: MeshPoolInfo, modelData?: ModelData, isNew: boolean = true) { let modelInfo = prefab.modelInfo.clone(modelData, isNew); this.meshBox = modelInfo.modelBox; this.modelInfo = modelInfo; // let box = MeshBuilder.CreateBox("box", { size: 1 }); //用于测试阴影 // box.setParent(modelInfo.modelBox); // box.position = new Vector3(0, 2, 0); if (SceneManager.s_openShadow) { SceneManager.Instance.shadowGenerator.addShadowCaster(modelInfo.modelBox, true); // console.log("添加到阴影", modelInfo.modelBox.name); } } dispose() { this.modelInfo.dispose(); } }