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.
604 lines
22 KiB
604 lines
22 KiB
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>(BuildingStatus).buildingWindow; |
|
return (buildingWindow != null && buildingWindow.currentBuidngItem != null && buildingWindow.currentBuidngItem.buildingInfo == belongToBuilding) |
|
} |
|
else if (StatusManager.s_currentStatus instanceof IndoorStatus) { |
|
let indoorKey = StatusManager.getStatus<IndoorStatus>(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[]; |
|
} |