import { EventManager } from "@angular/platform-browser"; import { AbstractMesh, Ray, RayHelper, Vector3 } from "@babylonjs/core"; import { classToClass } from "class-transformer"; import { PlanComponent } from "src/app/pages/plan/plan.component"; import { ModelChangeType } from "../../controller/data-manager"; import { Event_KeyboardInput } from "../../controller/event-manager/events/event-keyboard-input"; import { Event_ModelInfoChange } from "../../controller/event-manager/events/event-modelinfo-change"; import { ModeManager, ModeType } from "../../controller/mode-manager"; import { BuildingStatus } from "../../controller/status/building-status"; import { IndoorStatus } from "../../controller/status/indoor-status"; import { StatusManager } from "../../controller/status/status-manager"; import { Game } from "../../game"; import { ModelData_facility, FacilityType } from "../../model/data/model-data/model-data-facility"; import { BuildingInfo } from "../../model/info/building/building-info"; import { ModelInfo } from "../../model/info/model/model-info"; import { ModelInfo_facility, FacilityInfoByType } from "../../model/info/model/model-info-facility"; import { GizmoTool } from "../../tool/gizmo-tool"; import { TsTool } from "../../tool/ts-tool"; import { BuildingWindow } from "../building-window/building-window"; import { UIBase } from "../window-base/ui-base"; import { FacilityInfoUIItem } from "./facilityinfo-ui-item"; //所有放在场景中的设备 信息界面 export class FacilityInfoInSceneWindow extends UIBase { static instance: FacilityInfoInSceneWindow; three: PlanComponent;//前端组件 // scrollView: ScrollViewer; // content: StackPanel; /** * 当前选中的所有设备UI */ currentFacility: FacilityInfoUIItem[] = []; /** * 当前显示的所有设备UI */ facilityInfoUIItemes: FacilityInfoUIItem[] = []; copyFacilityInfo: CopyFacilityInfo = new CopyFacilityInfo(); isMultiselect: boolean = false;//多选状态 //#region 前端对接 /** * 更新UI显示 */ updateUI() { //this.three.getAllCensusList(this.facilityInfoUIItemes || []); } /** * 改变多选状态 * @param isMultiselect true表示多选。 默认是false */ changeMultiSelect(isMultiselect: boolean) { this.isMultiselect = isMultiselect; } /** * 复制选中的设备 */ copyFacility() { this.copyFacilityInfo.facilityData = []; for (let i = 0; i < this.currentFacility.length; i++) { let data = classToClass(this.currentFacility[i].modelInfo.modelData); this.copyFacilityInfo.facilityData.push(data as ModelData_facility); } if (StatusManager.s_currentStatus instanceof IndoorStatus) { this.copyFacilityInfo.outDoor = false; this.copyFacilityInfo.buildingKey = StatusManager.s_currentStatus.indoorWindow.currentFloorUIItem.getIndoorKey(); } else if (StatusManager.s_currentStatus instanceof BuildingStatus) { this.copyFacilityInfo.outDoor = true; this.copyFacilityInfo.buildingKey = StatusManager.s_currentStatus.currentBuildingInfo.buildingData.normalData.key; } return this.copyFacilityInfo; } /** * 单选设备 * @param facilityInfoUIItem null表示取消选中 */ selectFacilityItem(facilityInfoUIItem: FacilityInfoUIItem) { if (facilityInfoUIItem == null)//取消选中 { if (this.currentFacility != null) { for (let i = 0; i < this.currentFacility.length; i++) { this.currentFacility[i].onSelect(false); } this.currentFacility = []; } } else { if (this.currentFacility != null) { for (let i = 0; i < this.currentFacility.length; i++) { this.currentFacility[i].onSelect(false); } this.currentFacility = []; this.currentFacility.push(facilityInfoUIItem); facilityInfoUIItem.onSelect(true); } } } /** * 多选设备 * @param items * @param select true表示选中,false表示取消选中 */ multiSelectFacilityItem(items: FacilityInfoUIItem[], select: boolean) { if (items == null) { return; } for (let i = 0; i < items.length; i++) { if (select) { items[i].onSelect(true); let isRepet = false;//重复的 for (let j = 0; j < this.currentFacility.length; j++) { if (this.currentFacility[j] == items[i]) { isRepet = true; break; } } if (!isRepet) { this.currentFacility.push(items[i]); // console.log("添加进选中"); } } else { items[i].onSelect(false); TsTool.arrayRemove(this.currentFacility, items[i]) // console.log("取消选中", items[i].getID(), this.currentFacility); } } } //选中,通知前端 selectFacilityItemToThree(facilityInfoUIItem: FacilityInfoUIItem[], isChecked?: boolean) { this.three = PlanComponent.instance; // if (this.isMultiselect) { // 多选 // if (isChecked) { //选中 // facilityInfoUIItem.forEach(element => { // element.isChecked = isChecked // let isFind = this.three.beforeOnefacilityInfoList.find(item => { return item === element.getID() }) // isFind == undefined || isFind == null ? this.three.beforeOnefacilityInfoList.push(element.getID()) : null // }) // } else { //取消选中 // this.three.isShowRightNature = false // facilityInfoUIItem.forEach(element => { // element.isChecked = isChecked // let index = this.three.beforeOnefacilityInfoList.findIndex(value => value === element.getID()) // index != undefined && index != null ? this.three.beforeOnefacilityInfoList.splice(index, 1) : null // }) // } // } else { // 单选 // if (isChecked) { //选中 // this.three.beforeOnefacilityInfo = facilityInfoUIItem[0].getID(); // this.three.getPropertyData(facilityInfoUIItem[0]) // } else { //取消选中 // this.three.isShowRightNature = false // this.three.beforeOnefacilityInfo = null // } // } } /** * 显示某种type的消防设备,null表示全都 * @param facilityType */ showFacilityByType(facilityType: FacilityType, show: boolean) { if (ModeManager.currentMode == ModeType.Look) { // for (let i = 0; i < this.facilityInfoUIItemes.length; i++) { // let l_facilityData = (this.facilityInfoUIItemes[i].modelInfo.modelData) as ModelData_facility; // if (facilityType == null || facilityType == l_facilityData.facilityType) { // this.facilityInfoUIItemes[i].modelInfo.setEnable(show); // } // else if (show) { // this.facilityInfoUIItemes[i].modelInfo.setEnable(false); // } // } for (let i = 0; i < this.facilityInfoUIItemes.length; i++) { let l_facilityData = (this.facilityInfoUIItemes[i].modelInfo.modelData) as ModelData_facility; if (facilityType == null || facilityType == l_facilityData.facilityType) { this.facilityInfoUIItemes[i].modelInfo.setIconEnable(show); } } } else { for (let i = 0; i < this.facilityInfoUIItemes.length; i++) { let l_facilityData = (this.facilityInfoUIItemes[i].modelInfo.modelData) as ModelData_facility; if (facilityType == null || facilityType == l_facilityData.facilityType) { this.facilityInfoUIItemes[i].modelInfo.setIconEnable(show); } } } } /** * 根据类型获取设备在UI中的显示状态 * @param facilityType */ getFacilityUIShowType(facilityType: FacilityType): boolean { // for (let i = 0; i < this.three.allFacilityInfoUIItemes.length; i++) { // let item = this.three.allFacilityInfoUIItemes[i]; // if (item.type == facilityType) { // return item.isShow; // } // } return true; } /** * 删除某一类设备 * @param facilityType */ deleteFacilityByType(facilityType: FacilityType) { let needDelete: FacilityInfoUIItem[] = []; for (let i = 0; i < this.facilityInfoUIItemes.length; i++) { if ((this.facilityInfoUIItemes[i].modelInfo.modelData as ModelData_facility).facilityType == facilityType) { needDelete.push(this.facilityInfoUIItemes[i]); } } for (let i = 0; i < needDelete.length; i++) { needDelete[i].askDelete(false);//不再单独询问 } } //#endregion //#region 生命周期 onInit() { super.onInit(); FacilityInfoInSceneWindow.instance = this; // this.three = ThreeDimensionalHomeComponent.instance; // EventManager.addListener(Event_ModelInfoChange, this.onModelInfoChange); GizmoTool.onPickMeshInfoObservable.add(this.onClickModel); this.currentFacility = []; this.initKeyboardInput(); this.initDragInput(); } onClose() { super.onClose(); //EventManager.removeCallback(Event_ModelInfoChange, this.onModelInfoChange); GizmoTool.onPickMeshInfoObservable.removeCallback(this.onClickModel); } //#region 键盘输入 /** * 初始化键盘输入 */ initKeyboardInput() { let instance = this; // EventManager.addListener(Event_KeyboardInput, (eventData: Event_KeyboardInput) => { // instance.onKeyboardInput(eventData); // }) } /** * 接收到键盘事件 * @param eventData */ onKeyboardInput(eventData: Event_KeyboardInput) { if (eventData.data.key == "Delete") // 删除。 后期看是否加入 Backspace 退格 { //改由前端完成快捷键删除 // if (this.currentFacility != null) { // for (let i = 0; i < this.currentFacility.length; i++) { // this.currentFacility[i].askDelete(false); // } // this.currentFacility = []; // this.three.getAllCensusList(this.facilityInfoUIItemes || []); // } } else if (eventData.data.key == "X") //室内消火栓吸附墙 { // 没做完,先搁置 // let testNum = 5;//检测次数 // let distance = 1;//检测距离 // if (this.currentFacility != null) { // for (let i = 0; i < this.currentFacility.length; i++) { // let l_facility = this.currentFacility[i]; // if (l_facility.modelInfo.modelBox == null) { // continue; // } // if (l_facility.getType() == FacilityType.SNXHS) //室内消火栓 // { // let start = l_facility.modelInfo.modelBox.absolutePosition.clone(); // for (let x = -1; i < 2; i += 2) //x取1或-1 // { // for (let z = -testNum; z < testNum; z++) { // let dir = new Vector3(x, 0, z); // let ray = new Ray(start, dir, distance); // let rayHelper = new RayHelper(ray);//射线辅助器 // rayHelper.show(SceneManager.Instance.scene);//debug射线,用于调试 // let pickingInfo = SceneManager.Instance.scene.pickWithRay(ray, (mesh: AbstractMesh) => { // if (TsTool.stringContain(mesh.name, "SNXHS")) { // return false; // } // else { // return true; // } // }); // let normal = pickingInfo.getNormal(true); // console.log(pickingInfo); // } // } // } // } // } } } //#endregion //#region gizmo拖拽输入 /** * gizmo拖拽输入 */ isGizmoDrag_pos: boolean = false; lastGizmoMesh_Pos: Vector3 = Vector3.Zero(); /** * 初始化拖拽输入 * 当多选时,移动一个要同时移动其他设备 */ initDragInput() { let instance = this; GizmoTool.s_gizmoManager.gizmos.positionGizmo.onDragStartObservable.add((eventData) => { instance.isGizmoDrag_pos = true; instance.saveLastGizmoMeshInfo(); }); GizmoTool.s_gizmoManager.gizmos.positionGizmo.onDragEndObservable.add((eventData) => { instance.isGizmoDrag_pos = false; }); Game.instance.scene.onBeforeRenderObservable.add(() => { if (!instance.isGizmoDrag_pos) { return; } if (instance.isDragFacility()) { let offset = GizmoTool.s_nowPickAim.modelBox.position.subtract(instance.lastGizmoMesh_Pos); for (let i = 0; i < instance.currentFacility.length; i++) { if (instance.currentFacility[i].modelInfo != (GizmoTool.s_nowPickAim as ModelInfo_facility)) { // instance.currentFacility[i].modelInfo.modelData.transformData.position.x += offset.x; // instance.currentFacility[i].modelInfo.modelData.transformData.position.y += offset.y; // instance.currentFacility[i].modelInfo.modelData.transformData.position.z += offset.z; instance.currentFacility[i].modelInfo.modelBox.position.x += offset.x; instance.currentFacility[i].modelInfo.modelBox.position.y += offset.y; instance.currentFacility[i].modelInfo.modelBox.position.z += offset.z; } else { //console.log("移动的本体", i); } } instance.saveLastGizmoMeshInfo(); } }) } /** * 保存上一帧的数据 * @param facilityInfoInSceneWindow */ saveLastGizmoMeshInfo() { if (GizmoTool.s_nowPickAim != null && GizmoTool.s_nowPickAim instanceof ModelInfo_facility) { this.lastGizmoMesh_Pos = GizmoTool.s_nowPickAim.modelBox.position.clone(); } } /** * 是否拖拽选中的设备 */ isDragFacility() { if (this.currentFacility == null || this.currentFacility.length < 2) { return false; } if (GizmoTool.s_nowPickAim != null && GizmoTool.s_nowPickAim instanceof ModelInfo_facility) { for (let i = 0; i < this.currentFacility.length; i++) { if (this.currentFacility[i].modelInfo == GizmoTool.s_nowPickAim) { return true; } } return false; } else { return false; } } //#endregion //创建所有设备UI createAllFacilities(facilityByType: FacilityInfoByType[]) { this.clearFacilityInfoUIItemes(); for (let i = 0; i < facilityByType.length; i++) { for (let j = 0; j < facilityByType[i].facilityInfo.length; j++) { this.addFacilityItem(facilityByType[i].facilityInfo[j]); } } //通知ui更新 //this.three.getAllCensusList(this.facilityInfoUIItemes || []); } //清空设备UI item clearFacilityInfoUIItemes() { this.facilityInfoUIItemes.length = 0; this.currentFacility = []; //this.three.getAllCensusList(this.facilityInfoUIItemes || []); } //模型变化 onModelInfoChange(modelInfoChange: Event_ModelInfoChange) { let instance: FacilityInfoInSceneWindow = FacilityInfoInSceneWindow.instance; if (modelInfoChange.modeleInfo instanceof ModelInfo_facility) { if (instance.isCurrentBuildingOrIndoor(modelInfoChange.modeleInfo.belongToBuilding)) {//严格隶属当前选中的建筑 if (modelInfoChange.modelChangeType == ModelChangeType.Add) { instance.addFacilityItem(modelInfoChange.modeleInfo); //console.log("此建筑中添加", modelInfoChange.modeleInfo); } else if (modelInfoChange.modelChangeType == ModelChangeType.Remove) { instance.removeFacilityItem(modelInfoChange.modeleInfo); //console.log("此建筑中移除", modelInfoChange.modeleInfo); } } else { // console.log("不是此建筑"); } // instance.three = ThreeDimensionalHomeComponent.instance; //instance.three.getAllCensusList(instance.facilityInfoUIItemes || []); } else { // 无设备 时 // instance.three = ThreeDimensionalHomeComponent.instance; //instance.three.getAllCensusList(instance.facilityInfoUIItemes || []); } } //添加一个设备到UI addFacilityItem(facilityInfo: ModelInfo_facility) { let facilityInfoUIItem = new FacilityInfoUIItem(facilityInfo, this); this.facilityInfoUIItemes.push(facilityInfoUIItem); if (facilityInfo.isNew) { if (this.isMultiselect) { this.multiSelectFacilityItem([facilityInfoUIItem], true); } else { this.selectFacilityItem(facilityInfoUIItem); } // facilityInfo.setSelectEnable(true); // this.selectFacilityItemToThree(facilityInfoUIItem); } //this.onClickModel(facilityInfoUIItem); } //移除设备Item removeFacilityItem(facilityInfo: ModelInfo_facility) { let value = this.getFacilityItem(facilityInfo); TsTool.arrayRemove(this.currentFacility, value); if (value != null) { value.dispose(); } } //获取item getFacilityItem(facilityInfo: ModelInfo_facility): FacilityInfoUIItem { let result: FacilityInfoUIItem; if (this.facilityInfoUIItemes == undefined && this.facilityInfoUIItemes == null) { result = null; } else { for (let i = 0; i < this.facilityInfoUIItemes.length; i++) { if (this.facilityInfoUIItemes[i].modelInfo == facilityInfo) { result = this.facilityInfoUIItemes[i]; break; } } } return result; } //根据info找到相应的item,然后模拟选中 selectFacilityInfo(facilityInfo: ModelInfo_facility) { let item: FacilityInfoUIItem = null; for (let i = 0; i < this.facilityInfoUIItemes.length; i++) { if (this.facilityInfoUIItemes[i].modelInfo == facilityInfo) { item = this.facilityInfoUIItemes[i]; break; } } if (item == null) { item = new FacilityInfoUIItem(facilityInfo, this); } if (this.isMultiselect) { this.multiSelectFacilityItem([item], !item.isSelect); } else { // if (item.isSelect) { // //this.selectFacilityItem(null);//取消选中 // } // else { this.selectFacilityItem(item); // } } } //当点击了模型 onClickModel(model: ModelInfo | FacilityInfoUIItem) { } /** * 设备是否属于当前选中的建筑 * @param belongToBuilding */ isCurrentBuildingOrIndoor(belongToBuilding: BuildingInfo) { if (StatusManager.s_currentStatus instanceof BuildingStatus) { let buildingWindow = StatusManager.getStatus(BuildingStatus).buildingWindow; return (buildingWindow != null && buildingWindow.currentBuidngItem != null && buildingWindow.currentBuidngItem.buildingInfo == belongToBuilding) } else if (StatusManager.s_currentStatus instanceof IndoorStatus) { let indoorKey = StatusManager.getStatus(IndoorStatus).indoorWindow.currentFloorUIItem.getIndoorKey(); return belongToBuilding.ModelInfo.key == indoorKey; } } /** * 取消选中当前选中的所有设备 * @param select */ cancleAllCurrectFacilityItem() { if (this.currentFacility == null) { return; } this.selectFacilityItemToThree(this.currentFacility, false); for (let i = 0; i < this.currentFacility.length; i++) { this.currentFacility[i].onSelect(false); } this.currentFacility = []; } } /** * 复制的设备信息 */ export class CopyFacilityInfo { outDoor: boolean;//室外 buildingKey: String; facilityData: ModelData_facility[]; }