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

524 lines
19 KiB

import {
EventState,
Mesh,
MeshBuilder,
PointerEventTypes,
PointerInfo,
Vector3,
} from '@babylonjs/core';
import {
Control,
Image,
Rectangle,
} from '@babylonjs/gui';
import { ConfigManager } from '../../controller/config-manager';
import { DataManager, ModelChangeType } from '../../controller/data-manager';
import { Event_ChangeFacility } from '../../controller/event-manager/events/event-change-facility';
import { InfoManager } from '../../controller/info-manager';
import { ModeManager, ModeType } from '../../controller/mode-manager';
import { SceneManager } from '../../controller/scene-manager';
import { BuildingStatus } from '../../controller/status/building-status';
import { IndoorStatus } from '../../controller/status/indoor-status';
import { StatusManager } from '../../controller/status/status-manager';
import { UIManager } from '../../controller/ui-manager';
import { FacilityPosType, ModelData_facility, FacilityShowType } from '../../model/data/model-data/model-data-facility';
import { BuildingInfo } from '../../model/info/building/building-info';
import { AreaInfo } from '../../model/info/model/facilityinfo-tool/facility-area';
import { GdInfo } from '../../model/info/model/facilityinfo-tool/facility-gd';
import { ModelInfo_facility } from '../../model/info/model/model-info-facility';
import { BabylonTool } from '../../tool/babylon-tool';
import { BabylonUIStyleTool } from '../../tool/babylon-ui-style-tool';
import { GizmoTool } from '../../tool/gizmo-tool';
import { CopyFacilityInfo, FacilityInfoInSceneWindow } from '../facilityinfoinscene-window/facilityinfoinscene-window';
import { ToolbarWindow } from '../toolbar-window/toobar-window';
import { UIBase } from '../window-base/ui-base';
import { FacilityUIItem } from './facility-ui-item';
//设备界面
export class FacilityWindow extends UIBase {
// three: ThreeDimensionalHomeComponent;//前端组件
allFacilityUIItemes: FacilityUIItem[] = [];
static s_currentFacilityItem: FacilityUIItem;
static instance: FacilityWindow;
createIconRoot: Rectangle;//创建状态的跟随icon
createIcon: Image;
static readonly c_createIcon_width = 40;
createIndex = 0; //临时的创建序号
onInit() {
FacilityWindow.instance = this;
super.onInit();
SceneManager.Instance.scene.onBeforeRenderObservable.add(this.onUpdate);
this.initPickEvent();
}
onOpen() {
super.onOpen();
}
onClose() {
super.onClose();
}
onUpdate() {
FacilityWindow.instance.createIconFollow();
}
/**
* icon
*/
updateCreateIcon() {
if (ModeManager.currentMode == ModeType.Look)//查看模式无效
{
return;
}
if (this.createIconRoot == null) {
this.createIconRoot = new Rectangle("CreateFacilityIcon");
this.createIconRoot.clipChildren = false;
UIManager.Instance.uiRoot.addControl(this.createIconRoot);
this.createIconRoot.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
this.createIconRoot.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
BabylonUIStyleTool.setStyle_size(this.createIconRoot, FacilityWindow.c_createIcon_width + "px", "70px");
this.createIconRoot.thickness = 0;
let line = new Rectangle("line");
this.createIconRoot.addControl(line);
line.width = "3px";
line.thickness = 0;
line.background = BabylonUIStyleTool.c_color_blue;
line.shadowBlur = 5;
line.shadowColor = BabylonUIStyleTool.c_color_blue;
this.createIcon = new Image("createIcon");
this.createIconRoot.addControl(this.createIcon);
this.createIcon.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
BabylonUIStyleTool.setStyle_size(this.createIcon, FacilityWindow.c_createIcon_width + "px", FacilityWindow.c_createIcon_width + "px");
}
if (FacilityWindow.s_currentFacilityItem != null) {
let imageURL = FacilityWindow.s_currentFacilityItem.getIconURL();
if (this.createIcon.source != imageURL) {
this.createIcon.source = imageURL;
// this.createIcon.sourceLeft = 50.5;
}
}
}
/**
*
*/
createIconFollow() {
if (this.createIconRoot != null) {
if (FacilityWindow.s_currentFacilityItem == null) {
this.createIconRoot.isVisible = false;
}
else {
this.createIconRoot.isVisible = true;
this.createIconRoot.left = SceneManager.Instance.scene.pointerX - FacilityWindow.c_createIcon_width * 0.5;
this.createIconRoot.top = SceneManager.Instance.scene.pointerY - 40 - ConfigManager.c_size_facilityIconSize;
}
}
}
//更新室内或室外的设备信息
updateAllFacilities(facilityPosType: FacilityPosType) {
this.clearAllFacilityUIItemes();
this.clearCurrentFacility();
let facilities: ModelData_facility[];
if (facilityPosType == FacilityPosType.Indoor) {
facilities = DataManager.allFacilityData.indoor;
} else {
// console.log("=====updateAllFacilities=====");
// console.log(DataManager.allFacilityData);
facilities = DataManager.allFacilityData.outdoor;
}
let instance = this;
//为了避免多个模型同时加载、导致indexDB创建冲突,所以先加载一个,保证indexDB创建完成
3 years ago
BabylonTool.importMeshSync(null, "mesh/indexdb/gd/", "GD.gltf", undefined, "GD_indexDB", (meshes) => {
meshes[0].dispose();
for (let i = 0; i < facilities.length; i++) {
let facilityUIItem: FacilityUIItem = new FacilityUIItem(
facilities[i],
null,
null
);
instance.allFacilityUIItemes.push(facilityUIItem);
}
console.log("所有可用的设备", instance.allFacilityUIItemes);
// ThreeDimensionalHomeComponent.instance.getAllIcons(instance)
})
// instance.three = ThreeDimensionalHomeComponent.instance
}
//清空可用设施列表
clearAllFacilityUIItemes() {
for (let i = 0; i < this.allFacilityUIItemes.length; i++) {
this.allFacilityUIItemes[i].dispose();
}
this.allFacilityUIItemes = [];
}
//清空当前选中的设施
clearCurrentFacility() {
if (FacilityWindow.s_currentFacilityItem != null) {
FacilityWindow.s_currentFacilityItem.onSelect(null);
FacilityWindow.s_currentFacilityItem = null;
}
}
//点击了消防设施按钮
onClickFacilityBtn(select: FacilityUIItem) {
let oldItem = FacilityWindow.s_currentFacilityItem;
FacilityWindow.s_currentFacilityItem = select;
FacilityWindow.s_currentFacilityItem.onSelect(true);
if (oldItem != null) {
oldItem.onSelect(false);
if (FacilityWindow.s_currentFacilityItem == oldItem) {
FacilityWindow.s_currentFacilityItem = null;
}
}
this.updateCreateIcon();
}
//初始化pick事件
initPickEvent() {
SceneManager.Instance.scene.onPointerObservable.add(
this.onPointerObservable
);
}
//鼠标交互监听
onPointerObservable(eventData: PointerInfo, eventState: EventState) {
if (ModeManager.currentMode == ModeType.Look)//查看模式无效
{
return;
}
let instance = FacilityWindow.instance;
switch (eventData.type) {
case PointerEventTypes.POINTERUP:
if (eventData.event.button == 0) { //左键正常
if (eventData.pickInfo.hit && !SceneManager.s_isPointerDrag) {
if (FacilityWindow.s_currentFacilityItem != null) {
instance.createNewFacility(eventData.pickInfo.pickedPoint);
return;
}
}
if (!SceneManager.s_isPointerDrag && !ToolbarWindow.instance.isMeshAdsorb) {
GizmoTool.onPickMeshInfoObservable.notifyObservers(null);//取消之前选择
}
}
else { //右键取消
// instance.three.unSelectBottomIcon();
}
break;
case PointerEventTypes.POINTERPICK:
// console.log(eventData.event);
break;
}
}
//寻找设备预设
getFacilityPrefab(resName: string): Mesh {
let result = null;
// console.log("查找设备" + resName);
for (let i = 0; i < this.allFacilityUIItemes.length; i++) {
if (this.allFacilityUIItemes[i].facilityData.resName == resName) {
result = this.allFacilityUIItemes[i].meshPrefab as Mesh;
// console.log("设备找到" + resName);
break;
}
}
// console.log(result);
return result;
}
//异步获取预制
getFacilityPrefabSync(resName: string): Promise<Mesh> {
let thisWindow = this; //为了方便调用其方法
let myPromise = new Promise<Mesh>(function (resolve, reject) {
let result: Mesh = thisWindow.getFacilityPrefab(resName);//先获取已经加载好的
if (result == null) {//没获取到,则开始轮询
let intervalid = setInterval(function () { //轮询方法
let l_result: Mesh = thisWindow.getFacilityPrefab(resName);
if (l_result != null) {
clearInterval(intervalid);//停止轮询intervalid
resolve(l_result); //成功返回结果
}
}, 500);
} else {
resolve(result);//成功返回结果
}
});
return myPromise;
}
//创建新的设施(用世界坐标)
createNewFacility(worldPosition: Vector3) {
let facilityData = FacilityWindow.s_currentFacilityItem.facilityData.clone(
this.createIndex.toString()
);
facilityData.transformData.position = worldPosition.clone();
let currentBuidngItem = StatusManager.getStatus<BuildingStatus>(BuildingStatus)
.buildingWindow.currentBuidngItem;
if (currentBuidngItem == null) {
// alert("请先选中目标建筑");
// ThreeDimensionalHomeComponent.instance.openSnackBar("请先选中目标建筑");
return
}
Event_ChangeFacility.dispatch(facilityData, ModelChangeType.Add, null);
this.createFacility(facilityData, true, undefined, false, true, (modelInfo) => {
GizmoTool.onPickMeshInfoObservable.notifyObservers(modelInfo);
});
}
/**
*
* @param copyFacilityInfo
*/
pasteFacility(copyFacilityInfo: CopyFacilityInfo) {
let isSameFloor = true;//同层内粘贴
if (StatusManager.s_currentStatus instanceof BuildingStatus) {
if (!copyFacilityInfo.outDoor) {
isSameFloor = false;
}
}
else if (StatusManager.s_currentStatus instanceof IndoorStatus) {
if (copyFacilityInfo.outDoor) {
isSameFloor = false;
}
else if (copyFacilityInfo.buildingKey != StatusManager.s_currentStatus.indoorWindow.currentFloorUIItem.getIndoorKey()) {
isSameFloor = false;
}
}
//取消之前的所有选中
FacilityInfoInSceneWindow.instance.cancleAllCurrectFacilityItem();
for (let i = 0; i < copyFacilityInfo.facilityData.length; i++) {
let facilityData = copyFacilityInfo.facilityData[i].clone(this.createIndex.toString());
if (isSameFloor)//同层粘贴,略作偏移
{
facilityData.transformData.position.x += 5;
}
Event_ChangeFacility.dispatch(facilityData, ModelChangeType.Add, null);
this.createFacility(facilityData, false, undefined, true, true, (modelInfo) => {
//GizmoTool.onPickMeshInfoObservable.notifyObservers(modelInfo);
modelInfo.onStopLongPress(null, null);
});
}
}
//移除设备(等待UI调用)
disposeFacility(modelInfo_facility: ModelInfo_facility) {
let modelData = modelInfo_facility.modelData;
let buildingInfo: BuildingInfo = modelInfo_facility.belongToBuilding;
buildingInfo.ModelInfo.removeFacilityInfo(modelInfo_facility, true);
InfoManager.removeModelInfo(modelInfo_facility);
// GizmoTool.leaveTheGizmoAim(modelInfo_facility); // 看是否取消对坐标轴位置的标注
Event_ChangeFacility.dispatch(modelData, ModelChangeType.Remove, null);
}
//创建设备
createFacility(
facilityData: ModelData_facility,
isNew = false,
buildingInfo: BuildingInfo = null,
isLocalPos = false,
select = false,
onSuccess?: (modelInfo: ModelInfo_facility) => void
): ModelInfo_facility {
if (buildingInfo == null) {
buildingInfo = this.getCurrentBuildingInfo();
}
let defaultMesh = MeshBuilder.CreateBox(facilityData.key, { size: 1 });
defaultMesh.isVisible = false;
let facilityInfo = InfoManager.newModelInfo_facility(
facilityData.key,
facilityData,
null,
defaultMesh,
buildingInfo,
isNew
);
if (facilityInfo.facilityShowType == FacilityShowType.ModelAndTag) {
//模型类的,等加载完模型再设置transform信息,因为要把模型的position等数值和数据层的position等数据指向同一引用,方便后续调整后的同步
}
else {
this.setFacilityTransform(isLocalPos, isNew, facilityData, buildingInfo, defaultMesh, facilityInfo);
}
facilityInfo.belongToBuilding = buildingInfo;
if (facilityInfo.facilityShowType == FacilityShowType.ModelAndTag) {
this.getFacilityPrefabSync(facilityData.resName).then((mesh) => {
let prefab = mesh;
let newFacility = SceneManager.cloneMesh(
facilityData.key,
facilityInfo,
prefab
);
facilityInfo.modelBox = newFacility;
this.setFacilityTransform(isLocalPos, isNew, facilityData, buildingInfo, newFacility, facilityInfo);
if (onSuccess) {
onSuccess(facilityInfo);
}
});
}
else if (facilityInfo.facilityShowType == FacilityShowType.AreaAndTag) {
let facilityData = facilityInfo.modelData as ModelData_facility;
if (facilityData.areaPoints.length == 0) {
facilityData.areaPoints = facilityData.newAreapPoints();
}
facilityInfo.areaInfo = new AreaInfo(facilityData.areaPoints, facilityInfo);
if (onSuccess) {
onSuccess(facilityInfo);
}
}
else if (facilityInfo.facilityShowType == FacilityShowType.GdAndTag) {
if (facilityData.areaPoints.length == 0) {
facilityData.areaPoints = [];
facilityData.areaPoints.push(new Vector3(0, 0, 0));
facilityData.areaPoints.push(new Vector3(0, 10, 0));
}
facilityInfo.gdInfo = new GdInfo(facilityData.areaPoints[0], facilityData.areaPoints[1], facilityInfo);
if (onSuccess) {
onSuccess(facilityInfo);
}
}
// if (select) {
// GizmoTool.onPickMeshInfoObservable.notifyObservers(facilityInfo);
// }
//添加到建筑信息
let oldCreateNum = Number(facilityData.key);
if (oldCreateNum >= this.createIndex) {
this.createIndex = oldCreateNum + 1;
}
return facilityInfo;
}
//设置设备transform信息
setFacilityTransform(isLocalPos: boolean, isNew: boolean, facilityData: ModelData_facility, buildingInfo: BuildingInfo, newFacility: Mesh, facilityInfo?: ModelInfo_facility) {
//如果是局部坐标,要先设置父节点
if (isLocalPos) {
buildingInfo.ModelInfo.setFacilityParent(facilityInfo);
}
let halfY = newFacility.scaling.y * 0.5;
if (!isNew) {
halfY = 0;
}
let originalScaling = facilityData.transformData.originalScaling.clone();
if (!originalScaling.equals(newFacility.absoluteScaling))//原始缩放不同,表示换了模型
{
// let scaleSize = new Vector3(facilityData.transformData.scaling.x / facilityData.transformData.originalScaling.x, facilityData.transformData.scaling.y / facilityData.transformData.originalScaling.y, facilityData.transformData.scaling.z / facilityData.transformData.originalScaling.z);
let scaleSize = facilityData.transformData.scaling.divide(facilityData.transformData.originalScaling);
facilityData.transformData.originalScaling = newFacility.absoluteScaling.clone();
facilityData.transformData.scaling = facilityData.transformData.originalScaling.multiply(scaleSize);
}
newFacility.position = facilityData.transformData.position.add(
new Vector3(0, halfY, 0)
);
newFacility.position = facilityData.transformData.position;
newFacility.position.y += halfY;
// newFacility.scaling = facilityData.transformData.scaling;
// newFacility.rotation = facilityData.transformData.rotation;
if (facilityData.transformData.rotationQuaternion != null) {
newFacility.rotationQuaternion =
facilityData.transformData.rotationQuaternion;
}
//如果是世界坐标,则最后设置父节点
if (!isLocalPos) {
buildingInfo.ModelInfo.setFacilityParent(facilityInfo);
}
}
//获取当前选中的建筑信息
getCurrentBuildingInfo(): BuildingInfo {
let buildingInfo: BuildingInfo = null;
if (StatusManager.s_currentStatus instanceof BuildingStatus) {
buildingInfo = StatusManager.getStatus<BuildingStatus>(BuildingStatus)
.buildingWindow.currentBuidngItem.buildingInfo;
} else if (StatusManager.s_currentStatus instanceof IndoorStatus) {
buildingInfo = StatusManager.getStatus<IndoorStatus>(IndoorStatus)
.indoorWindow.currentFloorUIItem.buildingInfo;
}
return buildingInfo;
}
}