中化加油站项目
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.
 
 
 
 
 
 

973 lines
28 KiB

import {
AbstractMesh,
AnimationGroup,
ArcRotateCamera,
BoundingBoxGizmo,
Color3,
Color4,
CubeTexture,
DirectionalLight,
Engine,
EventState,
HemisphericLight,
HighlightLayer,
IParticleSystem,
Mesh,
MeshBuilder,
Observable,
PickingInfo,
PointerEventTypes,
Quaternion,
Scene,
ShadowGenerator,
Skeleton,
StandardMaterial,
Texture,
TransformNode,
Vector3,
} from '@babylonjs/core';
import '@babylonjs/core/Debug/debugLayer';
import '@babylonjs/inspector';
import { GridMaterial } from '@babylonjs/materials';
import { ModelData, ModelType } from '../model/data/model-data/model-data';
import { ModelInfo } from '../model/info/model/model-info';
import { ModelInfo_building } from '../model/info/model/model-info-building';
import { MyArcRotateCameraPointersInput } from '../tool/myArcRotateCameraPointersInput';
import { BabylonTool } from '../tool/babylon-tool';
import { GizmoTool } from '../tool/gizmo-tool';
import { TsTool } from '../tool/ts-tool';
import { FacilityWindow } from '../view/facility-window/facility-window';
import { FacilityInfoInSceneWindow } from '../view/facilityinfoinscene-window/facilityinfoinscene-window';
import { InfoManager } from './info-manager';
import { ModeManager } from './mode-manager';
import { MarkWindow } from '../view/mark-window/mark-window';
import { ModelInfo_facility } from '../model/info/model/model-info-facility';
import { ModelInfo_mark } from '../model/info/mark/model-info-mark';
import { MarkData, MarkType } from '../model/data/mark/mark-data';
import { Event_KeyboardInput } from './event-manager/events/event-keyboard-input';
import { ModelInfo_mark_area } from '../model/info/mark/other/mark-plan-area-info';
import { classToClass, plainToClass } from 'class-transformer';
import { MarkData_Area } from '../model/data/mark/other/mark-data-area';
import { MarkData_Line } from '../model/data/mark/other/mark-data-line';
import { ModelInfo_mark_line } from '../model/info/mark/other/mark-plan-line-info';
import { MarkData_multiLine } from '../model/data/mark/other/mark-data-multi-line';
import { ModelInfo_mark_multiLine } from '../model/info/mark/other/mark-plan-multi-line-info';
import { MarkData_multiArrow_CT, MarkData_multiArrow_JG } from '../model/data/mark/other/mark-data-multi-arrow';
import { ModelInfo_mark_multiArrow } from '../model/info/mark/other/mark-plan-multi-arrow';
import { ModelInfo_mark_particle } from '../model/info/mark/other/mark-plan-particle-info';
import { FacilityPosType, ModelData_facility } from '../model/data/model-data/model-data-facility';
import { LoadTool } from '../tool/load-tool';
//场景管理器
export class SceneManager {
//----------------Camera-----------------\\
public engine: Engine;
public canvas: HTMLCanvasElement;
public scene: Scene;
public defaultCamera: ArcRotateCamera;
private hemisphericLight: HemisphericLight;
public shadowGenerator: ShadowGenerator;//阴影
public sunLight: DirectionalLight;//太阳光,用于产生阴影
public skyBox: Mesh;//天空球
public ground3D: Mesh;//无天空盒时的背景地面
static s_openLight: boolean = true;//开启光照效果(关闭是要同时关闭阴影)
static s_openShadow: boolean = true;//开启阴影(必须开启阴影)
static s_openSkyBox: boolean = true;//使用天空盒
static s_environmentCubeTexture: CubeTexture;//环境所用的cubeTexture
static s_openEnvironmentReflection: boolean = true;//使用环境反射
static s_allModelInfo: ModelInfo[] = []; //所有建筑模型信息
static s_facilityInfoInSceneWindow: FacilityInfoInSceneWindow; //场景中设备 界面
static s_facilityWindow: FacilityWindow; //可用设备 界面
static s_markWindow: MarkWindow;//可用的标绘素材 界面
//#region 单例
private static instance: SceneManager;
public static get Instance() {
if (SceneManager.instance == null) {
throw new Error('Method not implemented.');
}
return SceneManager.instance;
}
//#endregion
//#region 初始化
//初始化
public static init(scene: Scene, canvas: HTMLCanvasElement, engine: Engine): SceneManager {
if (SceneManager.instance != null) {
throw new Error("sceneManager can't be reinitialized");
} else {
SceneManager.instance = new SceneManager();
SceneManager.instance.engine;
SceneManager.instance.scene = scene;
SceneManager.instance.canvas = canvas;
scene.onBeforeRenderObservable.add(() => {
if (SceneManager.instance != null) {
SceneManager.instance.onUpdate();
}
});
}
return SceneManager.instance;
}
//#endregion
onUpdate() {
if (SceneManager.s_openSkyBox && this.skyBox != null) {
let skyMat = this.skyBox.material;
let skyTexture = ((skyMat as StandardMaterial).reflectionTexture as CubeTexture);
if (skyTexture != null) {
let addSpeed = SceneManager.instance.scene.deltaTime * 0.001 * 0.003;//天空盒旋转速度
if (addSpeed > 0) {
skyTexture.rotationY += addSpeed;
}
while (skyTexture.rotationY > Math.PI * 2) {
skyTexture.rotationY -= Math.PI * 2;
}
}
}
}
dispose() {
SceneManager.instance = null;
}
//#region 摄像机
/**
* 摄像机模式-是正交状态
*/
public cameraMode_Is2D = false;
//初始化自由旋转相机
public initArcRotateCamera() {
let camera = new ArcRotateCamera(
'Camera', //名称
0, //alpha: 定义相机沿垂直轴的旋转
1.2, //beta: 定义相机沿水平轴的旋转
10, //摄像机与目标位置的距离
Vector3.Zero(), //目标位置
this.scene //定义摄像机所属的场景
);
camera.minZ = 0;//最近拍摄距离
camera.maxZ = 6000; //摄像机拍摄的最远距离
// camera.upperBetaLimit = 1.5; //beta方向上的旋转限制(防止看到模型底面)
camera.lowerRadiusLimit = 1; //相机距离拍摄目标的最小距离(防止穿插)
camera.setTarget(Vector3.Zero()); //设置拍摄目标
camera.radius = 100;
camera.attachControl(this.canvas, true); //把相机连接到画布
this.defaultCamera = camera;
camera.inputs.removeByType("ArcRotateCameraPointersInput");
camera.inputs.removeByType("ArcRotateCameraKeyboardMoveInput"); //为了配合快捷键,屏蔽了
camera.inputs.add(new MyArcRotateCameraPointersInput());
}
/**
* 改变摄像机模式(正交还是透视)
* @param is2D true表示正交
*/
public changeCameraMode(is2D: boolean) {
this.cameraMode_Is2D = is2D;
BabylonTool.changeCameraMode(this.defaultCamera, is2D);
}
//#endregion
//#region 光照与背景
//默认的半球光
public initLight() {
this.hemisphericLight = new HemisphericLight(
'light1',
new Vector3(0, 1, 0),
this.scene
);
this.updateLightSetting();
this.updateShadow();
}
/**
* 更新光照设置
*/
updateLightSetting() {
if (SceneManager.s_openLight) {
if (this.sunLight == null) {
this.sunLight = new DirectionalLight("sun", new Vector3(0.49, -0.79, 0.38), this.scene);
}
else {
this.sunLight.setEnabled(true);
}
if (SceneManager.s_openEnvironmentReflection) {
this.hemisphericLight.intensity = 0.1;//有环境反射时,本身会比较亮(跟当前使用的环境贴图有关)
this.sunLight.intensity = 3;
}
else {
this.hemisphericLight.intensity = 0.25;
this.sunLight.intensity = 3;
}
}
else {
if (this.sunLight == null) {
this.sunLight.setEnabled(false);
}
this.hemisphericLight.intensity = 10;
}
}
/**
* 初始化阴影
*/
public updateShadow() {
if (SceneManager.s_openShadow) {
if (this.shadowGenerator == null) {
this.shadowGenerator = new ShadowGenerator(2048, this.sunLight);
}
this.shadowGenerator.usePercentageCloserFiltering = true;
this.shadowGenerator.filteringQuality = ShadowGenerator.QUALITY_MEDIUM;
// this.shadowGenerator.blurKernel = 32;
if (this.sunLight != null) {
this.sunLight.autoCalcShadowZBounds = true; //投影矩阵距离自适应
}
}
else {
if (this.shadowGenerator != null) {
this.shadowGenerator.usePercentageCloserFiltering = false;
}
if (this.sunLight != null) {
this.sunLight.autoCalcShadowZBounds = false; //投影矩阵距离自适应
}
}
}
//#endregion
//#region 高亮层
/**
* 高亮层
*/
highLightLayer: HighlightLayer;
/**
* 添加到高亮层
* @param mesh
* @param color
*/
addToHighLight(mesh: Mesh, color: Color3) {
if (this.highLightLayer == null) {
this.highLightLayer = new HighlightLayer("highLight", this.scene,
{
mainTextureRatio: 2,
blurVerticalSize: 1.5,
blurHorizontalSize: 1.5,
});
this.openInnerGlow(true);
// this.highLightLayer.innerGlow = true;
this.highLightLayer.outerGlow = true;
}
let allMesh = mesh.getChildMeshes();
allMesh.push(mesh);
for (let i = 0; i < allMesh.length; i++) {
let childMesh = allMesh[i];
if (childMesh instanceof Mesh) {
this.highLightLayer.addMesh(childMesh, color);
// childMesh.material.alphaMode =
this.highLightNum++;
}
}
}
/**
* 开启内发光
*/
openInnerGlow(open: boolean) {
if (this.highLightLayer != null) {
this.highLightLayer.innerGlow = open;
}
}
highLightNum = 0;
/**
* 移除出高亮层
* @param mesh
*/
removeFromHighLight(mesh: Mesh) {
if (this.highLightLayer == null) {
return;
}
let allMesh = mesh.getChildMeshes();
allMesh.push(mesh);
for (let i = 0; i < allMesh.length; i++) {
let childMesh = allMesh[i];
if (childMesh instanceof Mesh) {
this.highLightLayer.removeMesh(childMesh);
this.highLightNum--;
}
}
}
// /**
// * 清空高亮层
// */
// clearHighLight() {
// this.highLightLayer.removeAllMeshes();
// }
//#endregion
//#region 三维场景的背景
public updateSceneBG() {
this.scene.clearColor = new Color4(0, 0, 0, 1);//0.51, 0.63, 0.89
this.scene.ambientColor = new Color3(1, 1, 1);
if (SceneManager.s_openSkyBox) {
if (this.skyBox == null) {
this.skyBox = Mesh.CreateBox("skyBox", 4000.0, this.scene);
let skyboxMaterial = new StandardMaterial("skyBox", this.scene);
skyboxMaterial.backFaceCulling = false;
skyboxMaterial.reflectionTexture = new CubeTexture("assets/skybox/default/default", this.scene);
skyboxMaterial.reflectionTexture.coordinatesMode = Texture.SKYBOX_MODE;
(skyboxMaterial.reflectionTexture as CubeTexture).rotationY = 0;
skyboxMaterial.diffuseColor = new Color3(0, 0, 0);
skyboxMaterial.specularColor = new Color3(0, 0, 0);
skyboxMaterial.disableLighting = true;
this.skyBox.material = skyboxMaterial;
this.skyBox.renderingGroupId = -1;
}
else {
this.skyBox.setEnabled(true);
}
if (this.ground3D != null) {
this.ground3D.setEnabled(false);
}
}
else {
if (this.ground3D == null) {
this.ground3D = MeshBuilder.CreateGround("ground", { width: 10000, height: 10000 });
this.ground3D.position.y = -1.5;
let mat_grid = new GridMaterial("mat_ground", SceneManager.Instance.scene);
mat_grid.gridRatio = 10;
mat_grid.mainColor = new Color3(0, 0, 0);
mat_grid.lineColor = new Color3(0, 0.4, 1);
this.ground3D.material = mat_grid;
this.ground3D.renderingGroupId = -1;
}
else {
this.ground3D.setEnabled(true);
}
}
//环境反射
if (SceneManager.s_openEnvironmentReflection) {
this.scene.environmentTexture = new CubeTexture("assets/skybox/city/city.env", this.scene);
SceneManager.s_environmentCubeTexture = this.scene.environmentTexture as CubeTexture;
}
}
//#endregion
//#region 场景声明周期与事件
public initSceneEvent() {
this.scene.onBeforeRenderObservable.add(SceneManager.onBeforeRender);
this.scene.onPointerDown = SceneManager.onPointerDown;
this.scene.onPointerUp = SceneManager.onPointerUp;
this.scene.onPointerMove = SceneManager.onPointerMove;
document.onkeydown = SceneManager.onKeyDown;
}
static showDebug = false;
//按键按下
static onKeyDown(this: GlobalEventHandlers, ev: KeyboardEvent) {
if (ev.altKey && ev.key == 'd' && ModeManager.isDebug) {
SceneManager.showDebug = !SceneManager.showDebug;
if (SceneManager.showDebug) {
SceneManager.Instance.scene.debugLayer.show({ embedMode: true });
} else {
SceneManager.Instance.scene.debugLayer.hide();
}
}
Event_KeyboardInput.dispatch(ev); //派发给其他
}
//场景渲染前
static onBeforeRender(eventData: Scene, eventState: EventState) {
if (SceneManager.s_isPointerDown) {
SceneManager.s_downTime += SceneManager.Instance.scene.deltaTime;
}
}
static s_isPointerDrag: boolean = false; //拖拽中
static s_isPointerDown = false; //按下中
static s_downTime = 0;//按下的时间
static readonly c_dragTime = 200;//超过则表示拖拽
//焦点按下
private static onPointerDown(
evt: PointerEvent,
pickInfo: PickingInfo,
type: PointerEventTypes
) {
SceneManager.s_isPointerDown = true;
SceneManager.s_downTime = 0;
}
//焦点移动
private static onPointerMove(
evt: PointerEvent,
pickInfo: PickingInfo,
type: PointerEventTypes
) {
if (SceneManager.s_isPointerDown && SceneManager.s_downTime > SceneManager.c_dragTime) {
SceneManager.s_isPointerDrag = true;
}
}
//焦点抬起
private static onPointerUp(evt: PointerEvent, pickInfo: PickingInfo) {
SceneManager.s_isPointerDown = false;
SceneManager.s_isPointerDrag = false;
SceneManager.s_downTime = 0;
}
//#endregion
//#region 操作模型
//创建模型
/**
* 加载模型
* @param modelType
* @param modelData
* @param needBox
* @param isNew
* @param tag 加载的原因
* @param onSuccess
* @param onError
* @param index 重试次数,超过五次就停止
*/
static createModel(
modelType: ModelType,
modelData: ModelData,
needBox: boolean,
isNew: boolean,
tag: string,
onSuccess?: (
meshes: AbstractMesh[],
box: AbstractMesh,
modelInfo: ModelInfo
) => void,
onError?: (
message: string
) => void,
index = 0
) {
// console.log("准备加载");
let defaultMesh = MeshBuilder.CreateBox(modelData.key + "Box", { size: 0.01 });
defaultMesh.scaling.y = 0.01;
defaultMesh.visibility = 0;
let modelInfo: ModelInfo;
if (modelType == ModelType.Building) {
modelInfo = InfoManager.newModelInfo_building(
modelData.key,
modelData,
null,
defaultMesh
);
}
else if (modelType == ModelType.Facility) {
modelInfo = new ModelInfo_facility(modelData.key, modelData, null, defaultMesh, null, isNew);
modelInfo.showFollowUI(false);
}
else if (modelType == ModelType.Mark) {
switch ((modelData as MarkData).type) {
case MarkType.QYSDA:
case MarkType.QYSDB:
modelData = plainToClass(MarkData_Area, modelData);
modelInfo = new ModelInfo_mark_area(modelData as MarkData, null, defaultMesh, null, isNew);
break;
case MarkType.JJX:
modelData = plainToClass(MarkData_Line, modelData);
modelInfo = new ModelInfo_mark_line(modelData as MarkData, null, defaultMesh, null, isNew);
break;
case MarkType.JGLX:
modelData = plainToClass(MarkData_multiArrow_JG, modelData);
modelInfo = new ModelInfo_mark_multiArrow(modelData as MarkData, null, defaultMesh, null, isNew);
break;
case MarkType.CT:
modelData = plainToClass(MarkData_multiArrow_CT, modelData);
modelInfo = new ModelInfo_mark_multiArrow(modelData as MarkData, null, defaultMesh, null, isNew);
break;
case MarkType.H:
case MarkType.SNH:
case MarkType.YWA:
case MarkType.YWB:
modelInfo = new ModelInfo_mark_particle(modelData as MarkData, null, defaultMesh, null, isNew);
break;
default: modelInfo = new ModelInfo_mark(modelData as MarkData, null, defaultMesh, null, isNew);
break;
}
modelInfo.showFollowUI(false);
}
if (modelData.isModel) {
let importMeshSyncData = SceneManager.getImportMeshSyncData(modelData.resPath, modelData.resName);
if (importMeshSyncData != null) //已经在加载了
{
importMeshSyncData.onsuccessObservable.add((eventData: ImportMeshSyncCallBack) => {
let box = SceneManager.importMeshSuccess(eventData.newMeshes, eventData.particleSystems, eventData.skeletons, eventData.animationGroups, eventData.modelInfo, eventData.needBox, eventData.modelData);
onSuccess(eventData.newMeshes, box, eventData.modelInfo);
})
}
else {
importMeshSyncData = SceneManager.startLoadMesh(modelData.resPath, modelData.resName);
BabylonTool.importMeshSync(
'',
modelData.resPath,
modelData.resName,
SceneManager.Instance.scene,
tag,
function (newMeshes: AbstractMesh[], particleSystems: IParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[]) {
let callBack = new ImportMeshSyncCallBack(newMeshes, particleSystems, skeletons, animationGroups, modelInfo, needBox, modelData);
let allImportMeshSyncDatas = SceneManager.getAllImportMeshSyncData(modelData.resPath, modelData.resName);
for (let i = 0; i < allImportMeshSyncDatas.length; i++) {
allImportMeshSyncDatas[i].onsuccessObservable.notifyObservers(callBack);
}
SceneManager.endLoadMesh(modelData.resPath, modelData.resName);
let box = SceneManager.importMeshSuccess(newMeshes, particleSystems, skeletons, animationGroups, modelInfo, needBox, modelData);
//console.log("加载模型完成", modelData.resName);
onSuccess(newMeshes, box, modelInfo);
}, null,
function (scene: Scene, message: string, exception?: any) {
if (index < 5) {
let l_index = index + 1;
modelInfo.dispose();
importMeshSyncData.isBreak = true;//中断
SceneManager.createModel(modelType, modelData, needBox, isNew, tag, onSuccess, onError, l_index);
//console.log("重新开始加载" + l_index, modelData);
console.log(exception);
}
else {
modelInfo.dispose();
LoadTool.remove(modelData.resPath + modelData.resName);
console.log(message, exception);
alert("模型加载失败,请刷新页面重试: " + message + "==" + exception);
// alert(exception);
if (onError) {
onError(message)
}
}
}
);
}
}
else {
onSuccess([], defaultMesh, modelInfo);
}
}
/**
* 加载完成的回调
* @param newMeshes
* @param particleSystems
* @param skeletons
* @param animationGroups
*/
static importMeshSuccess(newMeshes: AbstractMesh[], particleSystems: IParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[], modelInfo: ModelInfo, needBox: boolean, modelData: ModelData) {
SceneManager.addModel(modelInfo);
let box: AbstractMesh = null;
if (needBox) {
box = BoundingBoxGizmo.MakeNotPickableAndWrapInBoundingBox(
newMeshes[0] as Mesh
);
box.isPickable = false;
box.name = modelData.key;
box.rotationQuaternion = undefined;
modelInfo.models = newMeshes;
modelInfo.modelBox = box;
modelInfo.animationGroups = animationGroups;
if (animationGroups != null && animationGroups.length > 0) {
animationGroups[0].stop();
}
let canPick = false;
for (let i = 0; i < newMeshes.length; i++) {
//if (newMeshes[i].name.match("Floor") || newMeshes[i].name.match("floor") || newMeshes[i].name.match("Terrain")) {
newMeshes[i].isPickable = true;
canPick = true;
//}
if (SceneManager.s_openShadow) {
newMeshes[i].receiveShadows = true;
// let mat = newMeshes[i].material;
//if (mat instanceof PBRMaterial && TsTool.stringContain(mat.name, "glass")) {
// mat.refractionTexture = SceneManager.s_environmentCubeTexture;//折射
// mat.reflectionTexture = SceneManager.s_prefabSkyBoxCubeTexture;//反射
// mat.invertRefractionY = true;
//}
}
}
if (!SceneManager.s_openLight) {
BabylonTool.setMatToUnlit(newMeshes, true, "Color"); //无光材质
BabylonTool.setMatSheen(newMeshes, true, true);
}
// SceneManager.instance.shadowGenerator.addShadowCaster(newMeshes[0], true);
//如果是建筑,内部还没找到可接受pick的特定mesh,则整体可接受pick
if (modelInfo instanceof ModelInfo_building && !canPick) {
//box.isPickable = true;
let ground = MeshBuilder.CreateBox("ground", { size: 1 });
ground.scaling = new Vector3(box.scaling.x, 0.1, box.scaling.z);
ground.setParent(box);
ground.rotationQuaternion = Quaternion.Zero();
ground.position = new Vector3(0, -0.5, 0);
ground.visibility = 0.01;
}
// if (modelInfo instanceof ModelInfo_building) {
// for (let i = 0; i < newMeshes.length; i++) {
// newMeshes[i].receiveShadows = true;
// }
// }
}
return box
}
/**
* 正在加载的模型数据
*/
static s_ImportMeshSyncData: ImportMeshSyncData[] = [];
/**
* 开始加载模型
*/
static startLoadMesh(path: string, name: string) {
let importMeshSyncData = new ImportMeshSyncData(path, name);
SceneManager.s_ImportMeshSyncData.push(importMeshSyncData);
return importMeshSyncData
}
/**
* 结束加载模型
* @param path
* @param name
*/
static endLoadMesh(path: string, name: string) {
let datas = SceneManager.getAllImportMeshSyncData(path, name);
for (let i = 0; i < datas.length; i++) {
TsTool.arrayRemove(SceneManager.s_ImportMeshSyncData, datas[i]);
}
}
/**
* 查询加载模型的数据(确实在加载的)
* @param path
* @param name
*/
static getImportMeshSyncData(path: string, name: string) {
let result: ImportMeshSyncData = null;
for (let i = 0; i < SceneManager.s_ImportMeshSyncData.length; i++) {
let data = SceneManager.s_ImportMeshSyncData[i];
if (data.path == path && data.name == name && data.isBreak == false) {
result = data;
break;
}
}
return result;
}
/**
* 获取所有的加载信息(失败时,会产生多份)
* @param path
* @param name
*/
static getAllImportMeshSyncData(path: string, name: string) {
let result: ImportMeshSyncData[] = [];
for (let i = 0; i < SceneManager.s_ImportMeshSyncData.length; i++) {
let data = SceneManager.s_ImportMeshSyncData[i];
if (data.path == path && data.name == name) {
result.push(data);
}
}
return result;
}
//克隆模型
static cloneMesh(
key,
modelInfo: ModelInfo,
prefab: Mesh,
name?: string
): Mesh {
let result = BabylonTool.cloneMesh(prefab);
if (SceneManager.s_openShadow) {
SceneManager.Instance.shadowGenerator.addShadowCaster(result);
}
SceneManager.addModel(modelInfo);
return result;
}
//获取模型
static getModel(modelKey: string): ModelInfo {
let result = null;
if (SceneManager.s_allModelInfo != null) {
for (let i = 0; i < SceneManager.s_allModelInfo.length; i++) {
let l_modelInfo = SceneManager.s_allModelInfo[i];
if (l_modelInfo.key == modelKey) {
return l_modelInfo;
}
}
}
return result;
}
//获取模型
static getModelById(uniqueId: number): ModelInfo {
let result = null;
if (SceneManager.s_allModelInfo != null) {
for (let i = 0; i < SceneManager.s_allModelInfo.length; i++) {
let l_modelInfo = SceneManager.s_allModelInfo[i];
if (l_modelInfo.modelBox.uniqueId == uniqueId) {
return l_modelInfo;
}
}
}
console.log('没找到:' + uniqueId);
return result;
}
//删除模型
static destroyModel(model: string | ModelInfo) {
let modelInfo: ModelInfo;
if (model instanceof ModelInfo) {
modelInfo = model;
} else {
modelInfo = SceneManager.getModel(model);
}
if (modelInfo == null) {
return;
} else {
if (modelInfo.modelData instanceof ModelData_facility && modelInfo.modelData.posType == FacilityPosType.In) {
//来自建筑模型中的设备
modelInfo.dispose(false);
}
else {
TsTool.arrayRemove(SceneManager.s_allModelInfo, modelInfo);
modelInfo.dispose();
}
}
}
//添加模型
private static addModel(modelInfo: ModelInfo) {
SceneManager.s_allModelInfo.push(modelInfo);
}
/**
* 聚焦当前选中的目标
*/
public static lookAtCurrentSelect() {
if (GizmoTool.s_nowPickAim_mesh != null) {
BabylonTool.changeCameraTarget(SceneManager.Instance.defaultCamera, GizmoTool.s_nowPickAim_mesh, true);
}
else {
ModeManager.log("没有选中的目标");
}
}
/**
* 模型的Y方向吸附
* @param mover 行动者
* @param target 吸附的目标物
*/
public static meshAdsorbY(mover: AbstractMesh, target: AbstractMesh, pickPos: Vector3) {
ModeManager.log("吸附模型" + target);
let targetRoot = SceneManager.getRootTransformNode(target);
if (mover == targetRoot) {
return;
}
let aimPos_y: number = 0;
let direction = 0.5;
if (mover.absolutePosition.y < pickPos.y) {
direction = -0.5;
}
aimPos_y += mover.scaling.y * direction;
let newPos = new Vector3(mover.absolutePosition.x, pickPos.y + aimPos_y, mover.absolutePosition.z)
mover.setAbsolutePosition(newPos);
}
//获取根节点
public static getRootTransformNode(mesh: AbstractMesh): TransformNode {
let result: TransformNode = mesh;
let parent: any = mesh;
while (true) {
if (parent.id == "ground" || parent.id.match("Floor")) {
result = parent;
return result;
}
parent = parent.parent;
if (parent == null) {
return mesh;
}
else if (parent.id == "box") {
result = parent;
return result;
}
else {
result = parent;
}
}
}
//#endregion
}
/**
* 正在异步导入模型的数据
*/
class ImportMeshSyncData {
path: string;
name: string;
isBreak: boolean; //中断了
onsuccessObservable: Observable<ImportMeshSyncCallBack>;
constructor(path: string,
name: string) {
this.isBreak = false;
this.path = path;
this.name = name;
this.onsuccessObservable = new Observable();
}
}
/**
* 异步导入模型的回调
*/
class ImportMeshSyncCallBack {
newMeshes: AbstractMesh[];
particleSystems: IParticleSystem[];
skeletons: Skeleton[];
animationGroups: AnimationGroup[];
modelInfo: ModelInfo;
needBox: boolean;
modelData: ModelData;
constructor(newMeshes: AbstractMesh[],
particleSystems: IParticleSystem[],
skeletons: Skeleton[],
animationGroups: AnimationGroup[],
modelInfo: ModelInfo,
needBox: boolean,
modelData: ModelData) {
this.newMeshes = newMeshes;
this.particleSystems = particleSystems;
this.skeletons = skeletons;
this.animationGroups = animationGroups;
this.modelInfo = modelInfo;
this.needBox = needBox;
this.modelData = modelData;
}
}