中化加油站项目
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

322 lines
11 KiB

//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<string, MeshPoolInfo[]> = new Map();//预制体池
idlePool: Map<string, MeshPoolInfo[]> = new Map();//空闲池
workingPool: Map<string, MeshPoolInfo[]> = 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<MeshPoolInfo>();
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<string, MeshPoolInfo[]>, value: MeshPoolInfo) {
let poolInfo = pool.get(value.key);
if (poolInfo == null) {
poolInfo = [];
pool.set(value.key, poolInfo);
}
poolInfo.push(value);
}
//移除池
removePool(pool: Map<string, MeshPoolInfo[]>, 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<MeshPoolInfo>;
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();
}
}