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

1673 lines
54 KiB

import { AbstractMesh, Vector3 } from "@babylonjs/core";
import { PointerEventTypes, PointerInfo } from "@babylonjs/core/Events/pointerEvents";
import { EventState, Observer } from "@babylonjs/core/Misc/observable";
import { classToClass, plainToClass } from "class-transformer";
import { PlanComponent } from "src/app/pages/plan/plan.component";
import { DataManager } from "../../controller/data-manager";
import { EventManager } from "../../controller/event-manager/event-manager";
import { Event_GetAllMarkPlanData } from "../../controller/event-manager/events/event-get-markplandata-success";
import { Event_KeyboardInput } from "../../controller/event-manager/events/event-keyboard-input";
import { Event_MarkInfoChange, MarkInfoChangeType } from "../../controller/event-manager/events/event-mark-info-change";
import { InputController } from "../../controller/inputController";
import { ModeManager, ModeType } from "../../controller/mode-manager";
import { SceneManager } from "../../controller/scene-manager";
import { ServeManager } from "../../controller/serve-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 { ArcRotateCameraData } from "../../model/data/camera-data";
import { BuildingType } from "../../model/data/institution/building/building-data";
import { MarkData, MarkKindType, MarkTagPos, MarkType } from "../../model/data/mark/mark-data";
import { AllMarkPlanData, MarkNodeData, MarkPlanData, WeatherType, WindDirectionType, EnvironmentData, NatureData } from "../../model/data/mark/mark-plan-data";
import { MarkTemplate } from "../../model/data/mark/mark-template-data";
import { ModelType } from "../../model/data/model-data/model-data";
import { FacilityType } from "../../model/data/model-data/model-data-facility";
import { BuildingInfo } from "../../model/info/building/building-info";
import { MarkNodeInfo } from "../../model/info/mark/mark-plan-info";
import { ModelInfo_mark } from "../../model/info/mark/model-info-mark";
import { ModelInfo_building } from "../../model/info/model/model-info-building";
import { ModelInfo_facility } from "../../model/info/model/model-info-facility";
import { LoadTool } from "../../tool/load-tool";
import { MeshPool, MeshPoolInfo } from "../../tool/mesh-pool";
import { ParticleSystemTool } from "../../tool/particle-system-tool";
import { SpeakingTool } from "../../tool/speaking-tool";
import { BuildingUIItem } from "../building-window/building-ui-item";
import { BuildingWindow } from "../building-window/building-window";
import { IndoorFloorUIItem } from "../indoor-window/indoor-floorui-item";
import { UIBase } from "../window-base/ui-base";
import { WeatherTool } from "./weather-tool";
export class MarkWindow extends UIBase {
/**
* 游离节点特殊名称
*/
readonly c_leaveNodeName: string = "";
static instance: MarkWindow;
static s_cameraData: ArcRotateCameraData = null;//预定义的相机数据
static s_preLoadMesh: boolean = false;//预加载所有标绘物(如果是false,则在选中每个标绘物的时候,进行预加载单个)
/**
* 天气工具
*/
weatherTool: WeatherTool;
/**
* 喷水特效路径
*/
static readonly c_water_particlePath = "assets/particlesystem/water/water.json";
enterIndoorObserver: Observer<IndoorFloorUIItem>; //进入室内的监听者(一次性,用于选中节点切换时)
enterOutDoorObserver: Observer<BuildingUIItem>;//进入室外的监听者(一次性,用于选中节点切换时)
s_startEnterIndoorObserver: Observer<IndoorFloorUIItem>; //开始进入室内的监听者(因UI操作切换)
s_enterIndoorObserver: Observer<IndoorFloorUIItem>; //进入室内的监听者(因UI操作切换)
s_starteEnterOutDoorObserver: Observer<BuildingUIItem>;//开始进入室外的监听者(因UI操作切换)
s_enterOutDoorObserver: Observer<BuildingUIItem>;//进入室外的监听者(因UI操作切换)
/**
* 中断一次线的创建 ,0表示可以开始创建,1-表示正在绘制, -1 表示阻止绘制
*/
markLineIsBreak: number = -1;
/**
* 进攻路线 0-表示可以开始,1-表示正在绘制,-1 表示阻止绘制
*/
mulArrowIsBreak_JG: number = -1;
/**
* 撤退路线 0-表示可以开始,1-表示正在绘制,-1 表示阻止绘制
*/
mulArrowIsBreak_CT: number = -1;
/**
* 输油管 0-表示可以开始,1-表示正在绘制,-1 表示阻止绘制
*/
mulLineIsBreak_SYG: number = -1;
/**
* 所有的标绘方案数据
*/
allMarkPlanData: AllMarkPlanData = null;
/**
* 当前节点的拷贝信息,用于还原
*/
currentMarkNodeDataCopy: MarkNodeData;
/**
* 当前节点的信息
*/
currentMarkNodeInfo: MarkNodeInfo;
/**
* 当前选中的素材实例(运行时数据)
*/
currentMarkInfo: ModelInfo_mark;
/**
* 当前选中的素材预制体
*/
currentMarkDataPrefab: MarkData;
// /**
// * 所有标绘物的预制体
// */
// allMarkPrefabInfo: AllMarkInfo = new AllMarkInfo();
isPickDown: boolean = false; //按下了
/**
* 是否显示名称
*/
isShowProperty3d: boolean = true;
/**
* 是否显示水源
*/
isShowWaterSource = false;
//#region 生命周期
onInit() {
super.onInit();
MarkWindow.instance = this;
let instance = this;
instance.initPickEvent();
instance.initKeyboardInput();
ParticleSystemTool.Init(SceneManager.Instance.scene);
ParticleSystemTool.instance.loadPrefab("water", MarkWindow.c_water_particlePath, false); //预加载喷水
this.preLoadMesh();
// 创建输入控制器
const control = new InputController(SceneManager.Instance.scene);
this.weatherTool = new WeatherTool(SceneManager.Instance.defaultCamera, SceneManager.Instance.scene);
SceneManager.Instance.scene.onBeforeRenderObservable.add(() => {
instance.onUpdateShow();
})
}
onOpen() {
super.onOpen();
this.onShow();
}
onClose() {
super.onClose();
}
onHide() {
super.onHide();
this.selectMarkNode(null, null);
SpeakingTool.Instance.clear();
}
onShow() {
super.onShow();
let instance = this;
instance.getAllSandBoxTemplate();//获取模板
if (this.allMarkPlanData == null) {
DataManager.initMarkData((data: AllMarkPlanData) => {
instance.onGetAllMarkPlanData(data);
MarkWindow.instance.selectMarkNode(null, null, true); //模拟选中空节点,创建游离节点
// console.log("标绘信息", data);
// console.log(JSON.stringify(data));
});
}
else {
MarkWindow.instance.selectMarkNode(null, null, true); //模拟选中空节点,创建游离节点
}
}
/**
* 不同单位,释放数据,下次重新请求
*/
dispose() {
this.allMarkPlanData = null;
}
//#endregion
//#region 与前端通信
//请先监听 Event_GetAllMarkPlanData 事件,获取单位的标绘方案数据成功的事件。
// 注意EventManager 的引用路径: import { EventManager } from "src/babylon/controller/event-manager/event-manager";
// EventManager.addListener(Event_GetAllMarkPlanData,(data:Event_GetAllMarkPlanData)=>
// {
// //从服务器获取到方案数据
// })
//开启界面后,直接使用 MarkWindow.instance 访问实例对象
/**
* 开启界面
*/
static openWindow(): MarkWindow {
// console.log("进入沙盘");
if (MarkWindow.instance == null) {
SceneManager.s_markWindow = UIManager.open(MarkWindow);
}
else {
UIManager.show(MarkWindow.instance);
MarkWindow.instance.selectMarkNode(null, null, true); //模拟选中空节点,创建游离节点
}
return MarkWindow.instance;
}
/**
* 关闭界面
*/
static closeWindow() {
if (MarkWindow.instance != null) {
MarkWindow.instance.shouWaterSource(false);
UIManager.hide(MarkWindow.instance);
}
// console.log("退出沙盘");
}
/**
* 整体保存当前单位的标绘数据
* 先整体保存
*/
saveAllMarkPlanData() {
// this.savCurrentNodeData();
DataManager.saveallMarkPlanData();
// if (this.currentMarkNodeInfo != null) {
// this.currentMarkNodeDataCopy = classToClass(this.currentMarkNodeInfo.nodeData); //更新备份数据
// }
}
/**
* 保存至已有节点
* @param markPlanId 方案id,一级节点ID
* @param nodeId 节点id,二级节点id
* @param newName 是否要覆盖原有的名字
*/
saveToOldNode(markPlanId: number, nodeId: number, newName?: string) {
let markPlaneData = DataManager.allMarkPlanData.getMarkPlanById(markPlanId);
if (markPlaneData == null) {
console.error("没找到标绘方案:" + markPlanId)
return null;
}
this.savCurrentNodeData(this.currentMarkNodeDataCopy);
let oldNodeData = markPlaneData.getNodeById(nodeId);
let copyNodeData = classToClass(this.currentMarkNodeDataCopy);//覆盖数据
copyNodeData.id = oldNodeData.id;
copyNodeData.index = oldNodeData.index;
if (newName != null && newName != this.c_leaveNodeName) {
copyNodeData.name = newName;
}
if (copyNodeData.name == this.c_leaveNodeName) //如果来自空节点,则保留原名
{
copyNodeData.name = oldNodeData.name;
}
//console.log("记录的数据", copyNodeData.texture, this.currentMarkNodeInfo.nodeData.texture);
markPlaneData.setNodeData(nodeId, copyNodeData);//覆盖数据
this.saveAllMarkPlanData();
}
/**
* 新建新节点并保存
* @param markPlanId 方案id,一级节点ID
* @param name 新节点名称
*/
createNewNodeAndSave(markPlanId: number, name: string) {
let newNode = this.createMarkNodeData(markPlanId, name);
this.saveToOldNode(markPlanId, newNode.id, name);
}
/**
* 在沙盘节点中点击UI、 切换楼层或室内外,相当于清空
*/
changeBuilding(isOutdoor: boolean = false, buildingId: string = null, floorId: string = null) {
// console.log("沙盘内切换", isOutdoor, buildingId, floorId);
if (this.currentMarkNodeInfo == null) {
this.selectMarkNode(null, null, true);
return;
}
else {
let environmentData = this.currentMarkNodeInfo.nodeData.getEnvironmentDataByValue(isOutdoor, buildingId, floorId);
if (environmentData == null) {
//新增环境
environmentData = this.currentMarkNodeInfo.nodeData.addEnvironment(buildingId, isOutdoor, floorId);
}
else {
//已有环境
}
environmentData.isNow = true;
this.currentMarkNodeInfo.nodeData.changeNowEnvironmentData(environmentData.id);
let belongToPlanID = null;
if (this.currentMarkNodeInfo.belongToPlanData != null) {
belongToPlanID = this.currentMarkNodeInfo.belongToPlanData.id;
}
this.selectMarkNode(belongToPlanID, this.currentMarkNodeInfo.nodeData.id, true);
}
}
/**
* 选中具体的方案子节点
* @param planId 方案
* @param nodeId 节点
* @param changeBuildingByUI 是否在沙盘状态下,点UI切层、建筑
* @param readDescribe 朗读描述
*/
selectMarkNode(planId: number, nodeId: number, changeBuildingByUI: boolean = false, readDescribe = false) {
// //还原数据
// if (this.currentMarkNodeDataCopy != null && reData) {
// let oldPlaneData = this.currentMarkNodeInfo.belongToPlanData;
// oldPlaneData.setNodeData(this.currentMarkNodeDataCopy.id, this.currentMarkNodeDataCopy);
// this.currentMarkNodeDataCopy = null;
// }
let nodeCopy: MarkNodeData;
if (changeBuildingByUI) //从ui点击切层,
{
// console.log(this.currentMarkNodeInfo);
if (this.currentMarkNodeInfo == null)//没有当前的markInfo,创建一个游离的节点
{
// console.log("拷贝游离节点");
nodeCopy = this.createLeaveNode();
this.savCurrentNodeData(nodeCopy);
}
else //并且当前有拷贝的markinfo
{
nodeCopy = classToClass(this.currentMarkNodeInfo.nodeData);
}
}
this.clearNodeInfo();
let markPlanData: MarkPlanData = null;
if (DataManager.allMarkPlanData == null) {
return;
}
//更新新节点
markPlanData = DataManager.allMarkPlanData.getMarkPlanById(planId);
if (markPlanData != null) { //表示不是取消选中
if (nodeCopy == null) {
nodeCopy = classToClass(markPlanData.getNodeById(nodeId));
}
}
else {
if (nodeCopy == null) {
// console.log("拷贝游离节点 2");
nodeCopy = this.createLeaveNode();
this.savCurrentNodeData(nodeCopy);
}
}
if (nodeCopy != null) {
//清空
this.currentMarkNodeDataCopy = nodeCopy;//更新备份数据
this.currentMarkNodeInfo = new MarkNodeInfo(markPlanData, this.currentMarkNodeDataCopy);
//this.currentMarkNodeDataCopy = classToClass(this.currentMarkNodeInfo.nodeData); //更新备份数据
this.updateNodeInfo(readDescribe);
PlanComponent.instance.updateBeforePlanNode();
// let instance = this;
// if (readDescribe) { //镜头移动完,开始说话
// setTimeout(() => {
// instance.readDescribe(nodeCopy.describe);
// }, MarkNodeData.speakWaitTime * 1000);
// }
}
}
/**
* 新建方案(一级节点)
* @param name 新方案名称
*/
createMarkPlaneData(name: string): MarkPlanData {
let result = DataManager.allMarkPlanData.createPlanData(name);
return result;
}
/**
* 删除方案
* @param id
*/
deleteMarkPlaneData(id: number) {
if (this.currentMarkNodeInfo != null) {
this.currentMarkNodeInfo.clearAllMarkDataAndInfo();
}
this.currentMarkNodeInfo = null;
this.currentMarkNodeDataCopy = null;
DataManager.allMarkPlanData.deletePlanData(id);
this.saveAllMarkPlanData();
}
/**
* 新建标绘节点(二级节点)
* @param markPlanId 要在哪个方案下新建节点
* @param name 新建的节点名称
*/
createMarkNodeData(markPlanId: number, name: string) {
let markPlaneData = DataManager.allMarkPlanData.getMarkPlanById(markPlanId);
if (markPlaneData == null) {
console.error("没找到标绘方案:" + markPlanId)
return null;
}
let result = markPlaneData.createMarkNode(name);
this.savCurrentNodeData(result);
return result;
}
/**
* 删除标绘节点(二级节点)
* @param markPlanId 要删哪个方案下的节点
* @param id 节点的id
*/
deleteMarkNodeData(markPlanId: number, id: number) {
let markPlan = DataManager.allMarkPlanData.getMarkPlanById(markPlanId);
if (markPlan == null) {
console.error("没找到方案:" + markPlanId + "==无法删除节点" + id);
}
else {
// if (this.currentMarkNodeInfo != null && this.currentMarkNodeInfo.nodeData.id == id) {
// this.currentMarkNodeInfo.clearAllMarkDataAndInfo();
// this.currentMarkNodeInfo = null;
// this.currentMarkNodeDataCopy = null;
// }
markPlan.deleteMarkNode(id);
this.saveAllMarkPlanData();
}
}
/**
* 选中标记素材模板(由前端调用)
* @param select
*/
selectMarkDataPrefab(select: boolean, data: MarkData) {
if (select) {
this.currentMarkDataPrefab = data;
this.preLoadOneMesh(data);
}
else {
this.currentMarkDataPrefab = null;
}
this.setMultiPointOnSelectPrefab(select, data)
}
/**
* 选中标绘素材模板 (从前端通知3d)
* @param markData
* @param select
*/
selectMarkDataPrefabFrom3d(markData: MarkData, select: boolean) {
//通知前端 (一般是右键取消) 最后需要其调用 selectMarkDataPrefab
if (select) {
}
else {
if (markData != null) {
this.selectMarkDataPrefab(false, markData)
//ThreeDimensionalHomeComponent.instance.beforeOneIcon = null
}
this.markLineIsBreak = -1;
this.mulArrowIsBreak_JG = -1;
this.mulArrowIsBreak_CT = -1;
this.mulLineIsBreak_SYG = -1;
}
}
/**
* 选中标绘素材实例(由前端调用)
* @param markData
* @param select
*/
selectMarkData(markData: MarkData, select: boolean) {
if (select) {
let markInfo = this.currentMarkNodeInfo.getMarkInfo(markData.tagPos, markData.type, markData.key);
if (this.currentMarkInfo != null && this.currentMarkInfo != markInfo) {
this.currentMarkInfo.onSelect(false);
}
this.currentMarkInfo = markInfo;
markInfo.onSelect(select);
}
else {
if (this.currentMarkInfo != null) {
this.currentMarkInfo.onSelect(false);
}
this.currentMarkInfo = null;
}
}
/**
* 选中标绘素材实例 (从3d通知前端)
* @param markData
* @param select
*/
// markInfo.markData //通知前端 最后需要其调用 selectMarkData
selectMarkDataFrom3d(markInfo: ModelInfo_mark, select: boolean) {
if (select) {
PlanComponent.instance.selectSandTableMark(markInfo.markData, select)
}
else {
if (markInfo != null) {
PlanComponent.instance.selectSandTableMark(markInfo.markData, select)
}
}
}
/**
* 打开属性界面
*/
openProperty(markInfo: ModelInfo_mark) {
if (markInfo != null) {
PlanComponent.instance.getSandTableNature(markInfo.markData);
}
}
/**
* 更新属性
* @param markInfo
*/
updateProperty() {
if (this.currentMarkInfo != null) {
this.currentMarkInfo.updateProperty();
}
}
/**
* 显示三维属性
* @param show
*/
showProperty3d(show: boolean) {
this.currentMarkNodeInfo.markInfos.forEach((value: ModelInfo_mark[], key: MarkTagPos) => {
for (let i = 0; i < value.length; i++) {
value[i].showFollowUI(show);
}
});
this.isShowProperty3d = show;
}
/**
* 清空力量
*/
clearForce() {
if (this.currentMarkNodeInfo != null) {
this.currentMarkNodeInfo.clearAllMarkDataAndInfo();
}
this.saveAllMarkPlanData();
}
/**显示水源 */
shouWaterSource(show: boolean) {
this.isShowWaterSource = show;
let facility_water: ModelInfo_facility[] = [];
let buildingWindow = StatusManager.getStatus<BuildingStatus>(BuildingStatus).buildingWindow;
let buildingUIItems = buildingWindow.buildingUIItems;
if (buildingUIItems != null) {
for (let i = 0; i < buildingUIItems.length; i++) {
let l_item = buildingUIItems[i];
facility_water = facility_water.concat(this.getAllWaterSource(l_item.buildingInfo.ModelInfo));
}
}
if (StatusManager.s_currentStatus instanceof IndoorStatus) {
let indoorWindow = StatusManager.s_currentStatus.indoorWindow;
let indoorUIItem = indoorWindow.currentFloorUIItem;
// console.log(indoorUIItem.buildingInfo);
if (indoorUIItem.buildingInfo != null) {
facility_water = facility_water.concat(this.getAllWaterSource(indoorUIItem.buildingInfo.ModelInfo));
}
}
for (let i = 0; i < facility_water.length; i++) {
facility_water[i].showFollowUI(show);
}
}
/**
* 获取当前节点的原数据
*/
getCurrentNodeData() {
if (this.currentMarkNodeInfo == null) {
return null;
}
else {
return this.currentMarkNodeInfo.nodeData;
}
}
/**
* 改变自然-天气
*/
changeNature_weater(weather: WeatherType) {
if (this.currentMarkNodeInfo == null) {
return;
}
this.currentMarkNodeInfo.nodeData.natureData.weather = weather;
this.changeNatureEffect(true, this.currentMarkNodeInfo.nodeData.natureData);
}
/**
* 改变温度
* @param temperature
*/
changeNature_temperature(temperature: number) {
if (this.currentMarkNodeInfo == null) {
return;
}
this.currentMarkNodeInfo.nodeData.natureData.temperature = temperature;
this.changeNatureEffect(true, this.currentMarkNodeInfo.nodeData.natureData);
}
/**
* 改变风向
* @param temperature
*/
changeNature_windDirection(windDirection: WindDirectionType) {
if (this.currentMarkNodeInfo == null) {
return;
}
this.currentMarkNodeInfo.nodeData.natureData.windDirection = windDirection;
this.changeNatureEffect(true, this.currentMarkNodeInfo.nodeData.natureData);
}
/**
* 改变风速
* @param temperature
*/
changeNature_windPower(windPower: number) {
if (this.currentMarkNodeInfo == null) {
return;
}
this.currentMarkNodeInfo.nodeData.natureData.windPower = windPower;
}
/**
* 播放或暂停演出系统
* @param play false 表示暂停
*/
playOrPauseShow(play: boolean) {
}
/**
* 跳至某一节点
*/
skipToNode(nodeID: string) {
}
//#endregion
//#region 演出系统
/**
* 当前演出剩余时间
*/
currentShowTime: number;
/**
* 当前节点的完整演出时间
*/
totalShowTime: number;
/**
* 是否正在演出
*/
isPlayingShow: boolean = false;
/**
* 播放
* @param id
*/
playMarkNode(id: number) {
//通知前端
}
/**
* 每帧更新
*/
onUpdateShow() {
if (this.isPlayingShow) {
if (this.currentShowTime > 0) {
this.currentShowTime -= SceneManager.Instance.scene.deltaTime * 0.001;
if (this.currentShowTime <= 0) {
let l_currentMarkNodeData: MarkNodeData = this.currentMarkNodeInfo.nodeData;
//播放下一个节点
let l_nextNode = this.getNextNode(l_currentMarkNodeData.id);
}
}
}
}
//#endregion
//#region 事件、回调类
//初始化pick事件
initPickEvent() {
let instance = this;
SceneManager.Instance.scene.onPointerObservable.add(
instance.onPointerObservable
);
}
/**
* 点击事件的监听
* @param eventData
* @param eventState
*/
onPointerObservable(eventData: PointerInfo, eventState: EventState) {
let instance = MarkWindow.instance;
if (!instance.isShow || ModeManager.currentMode != ModeType.Edit) { //查看模式不能调整预案
return;
}
let pickMesh: AbstractMesh = null;
let readyCreateMark = false;//准备创建标绘物 如果点在了标绘物上,就不创建(除了水带)
let pickPos: Vector3 = null;
switch (eventData.type) {
case PointerEventTypes.POINTERUP:
instance.isPickDown = false;
if (eventData.event.button == 0) { //左键正常
if (eventData.pickInfo.hit && !SceneManager.s_isPointerDrag) {
if (instance.currentMarkDataPrefab != null) {
let worldPos = eventData.pickInfo.pickedPoint;
if (instance.currentMarkDataPrefab.type == MarkType.JJX) {
if (instance.markLineIsBreak > 0) {
instance.markLineIsBreak = 0;
return;
}
else {
instance.markLineIsBreak = 1;
}
}
else if (instance.currentMarkDataPrefab.type == MarkType.JGLX) {
if (instance.mulArrowIsBreak_JG > 0) {
return;
}
else {
instance.mulArrowIsBreak_JG = 1;
}
}
else if (instance.currentMarkDataPrefab.type == MarkType.CT) {
if (instance.mulArrowIsBreak_CT > 0) {
return;
}
else {
instance.mulArrowIsBreak_CT = 1;
}
}
else if (instance.currentMarkDataPrefab.type == MarkType.SYG) {
if (instance.mulLineIsBreak_SYG > 0) {
return;
}
else {
instance.mulLineIsBreak_SYG = 1;
}
}
readyCreateMark = true;
pickPos = worldPos;
pickMesh = eventData.pickInfo.pickedMesh;
// return;
}
}
// if (!SceneManager.s_isPointerDrag && !ToolbarWindow.instance.isMeshAdsorb) {
// GizmoTool.onPickMeshInfoObservable.notifyObservers(null);//取消之前选择
// }
}
else { //右键取消
// instance.selectMarkDataFrom3d(instance.currentMarkInfo, false); //暂时没有右键取消选中实例的功能
if (!SceneManager.s_isPointerDrag) {
instance.selectMarkDataPrefabFrom3d(instance.currentMarkDataPrefab, false)
if (instance.currentMarkNodeInfo != null) {
//取消选中
instance.selectMarkDataFrom3d(instance.currentMarkInfo, false);
}
}
}
break;
case PointerEventTypes.POINTERDOWN:
if (eventData.pickInfo.hit && !instance.isPickDown) {
pickMesh = eventData.pickInfo.pickedMesh;
instance.isPickDown = true;
}
break;
case PointerEventTypes.POINTERPICK:
if (eventData.pickInfo.hit) {
pickMesh = eventData.pickInfo.pickedMesh;
}
break;
case PointerEventTypes.POINTERDOUBLETAP:
if (eventData.pickInfo.hit) {
pickMesh = eventData.pickInfo.pickedMesh;
}
break;
}
if (pickMesh != null) {
//是标绘物
let l_markInfo = instance.getMarkInfoFromMesh(eventData.pickInfo.pickedMesh);
if (l_markInfo != null) {
if (instance.currentMarkDataPrefab != null && instance.currentMarkDataPrefab.markKindType != MarkKindType.Effect
&& instance.currentMarkDataPrefab.type != MarkType.MHTK && instance.currentMarkDataPrefab.type != MarkType.SYG) //特效可以放在标绘物上
{
readyCreateMark = false;
}
if (eventData.type == PointerEventTypes.POINTERDOUBLETAP) {
//双击标绘物,打开任务界面
// console.log("打开属性面板");
instance.openProperty(l_markInfo);
readyCreateMark = false; //双击,必然不创建标绘物
}
else if (eventData.type == PointerEventTypes.POINTERDOWN) {
if (eventData.event.button == 0)//左键
{
if (!instance.isCreateMultiPointMark()) {
// console.log("选中标绘物", l_markInfo);
instance.selectMarkDataFrom3d(l_markInfo, true);
}
}
}
else if (eventData.type == PointerEventTypes.POINTERPICK) {
if (eventData.event.button == 0)//左键
{
if (!instance.isCreateMultiPointMark()) {
//instance.selectMarkDataFrom3d(l_markInfo, true);
}
}
else if (eventData.event.button == 1) {//中键
//聚焦
l_markInfo.lookAt();
}
else {
}
}
}
else {
// console.log("不是标绘物", pickMesh);
}
}
//创建标绘物
if (readyCreateMark) {
instance.createNewMark(pickPos, instance.currentMarkDataPrefab, true);
}
}
/**
* 从服务器获取到所有的标绘信息
* @param data
*/
onGetAllMarkPlanData(data: AllMarkPlanData) {
this.allMarkPlanData = data;
//DisposalPlanComponent.instance.allMarkPlanData = this.allMarkPlanData
Event_GetAllMarkPlanData.dispatch(true, data);
}
/**
* 初始化键盘输入
*/
initKeyboardInput() {
let instance = this;
EventManager.addListener(Event_KeyboardInput, (eventData: Event_KeyboardInput) => {
instance.onKeyboardInput(eventData);
})
}
/**
* 接收到键盘事件
* @param eventData
*/
onKeyboardInput(eventData: Event_KeyboardInput) {
if (eventData.data != null && eventData.data.key == "Delete") // 删除。 后期看是否加入 Backspace 退格
{
this.deleteMarkInfo(this.currentMarkInfo);
}
}
//#endregion
//#region 查询类
//获取当前选中的建筑信息
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;
}
/**
* 根据mesh,查找
* @param mesh
*/
getMarkInfoFromMesh(mesh: AbstractMesh) {
if (mesh == null) {
return null;
}
let result: ModelInfo_mark = null;
if (this.currentMarkNodeInfo == null || this.currentMarkNodeInfo.markInfos == null) {
return null;
}
this.currentMarkNodeInfo.markInfos.forEach((value: ModelInfo_mark[], key: MarkTagPos) => {
for (let i = 0; i < value.length; i++) {
if (mesh.uniqueId == value[i].modelBox.uniqueId) {
result = value[i];
break;
}
let children = value[i].modelBox.getChildMeshes();
for (let j = 0; j < children.length; j++) {
if (children != null) {
if (mesh.uniqueId == children[j].uniqueId) {
result = value[i];
break;
}
}
}
}
})
return result;
}
/**
* 获取当前方案下,下一个节点,null表示没有了
*/
getNextNode(id: number) {
let result: MarkNodeInfo = null;
return result;
}
//#endregion
//#region 修改类
/**
* 创建一个游离的节点,用于没有选中已经创建的节点时,存放标绘信息
*/
createLeaveNode() {
let result = new MarkNodeData(0, this.c_leaveNodeName);
return result;
}
/**
* 保存当前节点的数据(主要是环境数据和相机数据)
*/
savCurrentNodeData(markNodeData: MarkNodeData = null, environId: number = null) {
if (markNodeData == null) {
if (this.currentMarkNodeInfo == null) {
return;
}
else {
markNodeData = this.currentMarkNodeInfo.nodeData;
environId = markNodeData.getCurrentEnvironmentData().id;
}
}
let environmentData: EnvironmentData = markNodeData.getEnvironmentData(environId)
if (environmentData == null) {
environmentData = markNodeData.addEnvironment(null, false, null);
}
if (StatusManager.s_currentStatus instanceof BuildingStatus) {
environmentData.isOutdoor = true;
}
else {
environmentData.isOutdoor = false;
let indoorStatus = StatusManager.s_currentStatus as IndoorStatus;
environmentData.buildingId = indoorStatus.buildingInfo.buildingData.normalData.key;
environmentData.floorId = indoorStatus.indoorWindow.currentFloorUIItem.getIndoorKey();
}
if (markNodeData.cameraData == null) {
markNodeData.cameraData = new ArcRotateCameraData();
}
markNodeData.cameraData.getDataFromCamera(SceneManager.Instance.defaultCamera);
markNodeData.showZP = BuildingWindow.instance.currentZPShow;
// console.log("记录节点", markNodeData);
}
/**
* 创建新标记物
* @param pickedPoint
* @param currentMarkInstanceData
* @param isNew 新放置的
*/
createNewMark(worldPosition: Vector3, currentMarkDataPrefab: MarkData, isNew: boolean) {
if (this.currentMarkNodeInfo == null) {
//现在,取消选中节点时会创建并选中一个游离节点,用于承接标绘物,以允许不选节点就标绘,所以此处应永远不会走进来
//ThreeDimensionalHomeComponent.instance.openSnackBar("请创建或选择方案的节点后,再进行标绘");
// alert("请创建或选择方案的节点后,再进行标绘");
return;
}
let markDataId = this.currentMarkNodeInfo.getNextMarkDataId();
let instance = this;
//设置位置等
let newMarkInfo = this.createMark(markDataId, currentMarkDataPrefab, true, worldPosition, null, false, true, (modelInfo: ModelInfo_mark) => {
instance.selectMarkDataFrom3d(modelInfo, true);
});
return newMarkInfo;
}
//创建设备
createMark(
markId: number,//用于新建
markData: MarkData,//新创建时,这是模板; 有数据是,即为元数据
isNew = false, //新创建、还是还原旧数据
position: Vector3,//新创建的位置
buildingInfo: BuildingInfo = null,//所属建筑
isLocalPos = false,//是否是局部坐标
select = false,
onSuccess?: (modelInfo: ModelInfo_mark) => void
): ModelInfo_mark {
let instance = this;
if (buildingInfo == null) {
buildingInfo = this.getCurrentBuildingInfo();
}
let markInfo: ModelInfo_mark;
let newMarkData: MarkData = null;
if (isNew) {
newMarkData = classToClass(markData);
newMarkData.key = markId.toString();
newMarkData.belongtoBuildingId = buildingInfo.ModelInfo.key;
newMarkData.transformData.position = position.clone();
}
else {
newMarkData = markData;
}
let startEnvironmentData = instance.currentMarkNodeInfo.nodeData.getCurrentEnvironmentData();//加载发起时的环境信息
let createTag = isNew ? LoadTool.c_tag_createMark : undefined;
MeshPool.importMesh(ModelType.Mark, newMarkData, isNew, true, createTag, (box, meshes, meshPoolInfo: MeshPoolInfo) => {
let currentEnvironmentData = instance.currentMarkNodeInfo.nodeData.getCurrentEnvironmentData();//加载发起时的环境信息
if (startEnvironmentData != currentEnvironmentData) {
meshPoolInfo.dispose();
return;
}
markInfo = meshPoolInfo.modelInfo as ModelInfo_mark;
markInfo.belongToBuilding = buildingInfo;
instance.setMarkTransform(isLocalPos, isNew, buildingInfo, markInfo.modelBox, markInfo);
// markInfo.modelBox.isPickable = true; //避免超大的透明选中区
// console.log("成功创建模型", markInfo);
instance.currentMarkNodeInfo.addMarkInfo(markInfo, isNew);
markInfo.onCreate(isNew);
Event_MarkInfoChange.dispatch(MarkInfoChangeType.Create, markInfo);
// console.log("测试播放动画", markInfo.animationGroups);
// if (markInfo.animationGroups != null && markInfo.animationGroups.length > 0) {
// markInfo.animationGroups[0].play();//完善正式逻辑时,注释掉此行
// }
if (onSuccess) {
onSuccess(markInfo);
}
})
return markInfo;
}
/**
* 清空节点的运行时数据
* 清空标记物
*/
clearNodeInfo() {
if (this.currentMarkInfo != null) {
this.selectMarkDataFrom3d(this.currentMarkInfo, false);
}
if (this.currentMarkNodeInfo != null) {
this.currentMarkNodeInfo.disposeInfo();
this.currentMarkNodeInfo = null;
}
this.changeNatureEffect(false, null);
this.shouWaterSource(false);
//ThreeDimensionalHomeComponent.instance.toggleHeadwaters = false;
}
/**
* 更新节点数据至表现层
* 摄像机、楼层、室内外的更新
* 标记物的重新创建
* @param readDescribe: 是否阅读介绍
*/
updateNodeInfo(readDescribe = false) {
let environmentData = this.currentMarkNodeInfo.nodeData.getCurrentEnvironmentData();
let cameraData = this.currentMarkNodeInfo.nodeData.cameraData;
let showZP = this.currentMarkNodeInfo.nodeData.showZP;
let instance = this;
if (environmentData.isOutdoor) //要在室外
{
if (StatusManager.s_currentStatus instanceof IndoorStatus) {
//设置相机信息//相机位置设置问题 异步、动画冲突问题
MarkWindow.s_cameraData = cameraData;
instance.clearEnterObserver(true);
instance.enterOutDoorObserver = BuildingStatus.enterSuccessObservable.add((eventData: BuildingUIItem) => {
//记录不分建筑,但初始化分建筑
//if (eventData.buildingInfo.buildingData.normalData.key == environmentData.buildingId) {
instance.onEnterSuccess(eventData.buildingInfo, eventData.buildingInfo.buildingData.normalData.key);
//}
})
//切到室外
StatusManager.s_currentStatus.indoorWindow.onBtnToOutDoor(false);
}
else if (StatusManager.s_currentStatus instanceof BuildingStatus) {
//this.currentMarkNodeInfo.nodeData.cameraData.setDataToCamera(SceneManager.Instance.defaultCamera);
// let camera = SceneManager.Instance.defaultCamera;
// if (cameraData != null) {
// BabylonTool.AnimMoveCameraTargetAB(camera, 60, cameraData.target, cameraData.radius, cameraData.alpha, cameraData.beta);
// }
//仅此分支生效
//动画还原相机,结束后开始阅读
BuildingWindow.instance.revoverCamera(cameraData, showZP, (() => {
if (readDescribe) {
instance.readDescribe(instance.currentMarkNodeInfo.nodeData.describe);
}
}));
instance.clearEnterObserver(true);
let updateMark = false;//更新了标绘物 //为了复制功能,不再匹配key,而是在第一个主建筑进入时更新标绘物
for (let i = 0; i < StatusManager.s_currentStatus.buildingWindow.buildingUIItems.length; i++) {
let buildingInfo = StatusManager.s_currentStatus.buildingWindow.buildingUIItems[i].buildingInfo
if (!updateMark && buildingInfo.buildingData.buildingType == BuildingType.Normal) {
updateMark = true;
instance.onEnterSuccess(buildingInfo, buildingInfo.buildingData.normalData.key);
}
}
}
else {
console.log("非法状态切换", StatusManager.s_currentStatus);
return;
}
}
else { //要在室内
if (StatusManager.s_currentStatus instanceof BuildingStatus) {
//相机位置设置问题 异步、动画冲突问题
MarkWindow.s_cameraData = cameraData;
//切到室内
let buildingUIItem: BuildingUIItem = StatusManager.s_currentStatus.buildingWindow.getBuildingUIItem(environmentData.buildingId);
instance.clearEnterObserver(false);
instance.enterIndoorObserver = IndoorStatus.enterSuccessObservable.add((eventData: IndoorFloorUIItem) => {
if (eventData.getIndoorKey() == environmentData.floorId) {
instance.onEnterSuccess(eventData.buildingInfo, eventData.buildingInfo.ModelInfo.key);
}
})
buildingUIItem.enterIndoor(environmentData.floorId, false);
}
else if (StatusManager.s_currentStatus instanceof IndoorStatus) {
//相机位置设置问题 异步、动画冲突问题
MarkWindow.s_cameraData = cameraData;
let buildingUIItem = StatusManager.getStatus<BuildingStatus>(BuildingStatus).buildingWindow.getBuildingUIItem(environmentData.buildingId);
instance.clearEnterObserver(false);
instance.enterIndoorObserver = IndoorStatus.enterSuccessObservable.add((eventData: IndoorFloorUIItem) => {
if (eventData.getIndoorKey() == environmentData.floorId) {
instance.onEnterSuccess(eventData.buildingInfo, eventData.buildingInfo.ModelInfo.key);
}
})
buildingUIItem.enterIndoor(environmentData.floorId, false);
}
else {
console.log("非法状态切换", StatusManager.s_currentStatus);
return;
}
}
this.changeNatureEffect(true, this.currentMarkNodeInfo.nodeData.natureData);
}
enterSuccessKey: Map<string, BuildingInfo> = new Map();
/**
* 进入建筑成功
* @param buildingInfo
*/
onEnterSuccess(buildingInfo: BuildingInfo, key: string) {
if (!this.isShow) {
return;
}
let instance = this;
let environmentData = this.currentMarkNodeInfo.nodeData.getCurrentEnvironmentData();
if (instance.enterSuccessKey.has(key)) {
return;
}
instance.enterSuccessKey.set(key, buildingInfo);
for (let i = 0; i < environmentData.markDatas.length; i++) {
let markData = environmentData.markDatas[i];
//if (markData.belongtoBuildingId == key) { //为了复制功能,不再匹配key
this.createMark(0, markData, false, null, buildingInfo, true, null, (modelInfo: ModelInfo_mark) => {
modelInfo.showFollowUI(instance.isShowProperty3d);
});
//}
}
this.shouWaterSource(this.isShowWaterSource);
}
/**
* 删除标记物
*/
deleteMarkInfo(markInfo: ModelInfo_mark) {
if (markInfo == null) {
return;
}
else {
if (markInfo == this.currentMarkInfo) {
this.selectMarkDataFrom3d(markInfo, false);
}
this.currentMarkNodeInfo.removeMarkInfo(markInfo);
}
}
//#endregion
//#region 工具类
/**
* 根据原数据,查找运行时数据 - 标记元素
* @param data
*/
getMarkInfoByMarkData(data: AllMarkPlanData) {
}
//设置设备transform信息
setMarkTransform(isLocalPos: boolean, isNew: boolean, buildingInfo: BuildingInfo, newMark: AbstractMesh, markInfo?: ModelInfo_mark) {
//如果是局部坐标,要先设置父节点
if (isLocalPos) {
buildingInfo.ModelInfo.steMarkParent(markInfo);
}
let markData = markInfo.markData;
let halfY = newMark.scaling.y * 0.5;
if (!isNew) {
halfY = 0;
}
let originalScaling = markData.transformData.originalScaling.clone();
if (!originalScaling.equals(newMark.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 = markData.transformData.scaling.divide(markData.transformData.originalScaling);
markData.transformData.originalScaling = newMark.absoluteScaling.clone();
markData.transformData.scaling = markData.transformData.originalScaling.multiply(scaleSize);
}
newMark.position = markData.transformData.position.add(
new Vector3(0, halfY, 0)
);
newMark.scaling = markData.transformData.scaling;
newMark.rotation = markData.transformData.rotation;
if (markData.transformData.rotationQuaternion != null) {
newMark.rotationQuaternion =
markData.transformData.rotationQuaternion;
}
//如果是世界坐标,则最后设置父节点
if (!isLocalPos) {
buildingInfo.ModelInfo.steMarkParent(markInfo);
}
markData.transformData.position = newMark.position;
}
/**
* 清空进入场景的监听者
* @param outDoor
*/
clearEnterObserver(outDoor: boolean) {
this.enterSuccessKey.clear();
if (outDoor) {
if (this.enterOutDoorObserver != null) {
BuildingStatus.enterSuccessObservable.remove(this.enterOutDoorObserver);
this.enterOutDoorObserver = null;
}
}
else {
if (this.enterIndoorObserver != null) {
IndoorStatus.enterSuccessObservable.remove(this.enterIndoorObserver);
this.enterIndoorObserver = null;
}
}
}
/**
* 正在创建多点的标绘物
*/
isCreateMultiPointMark() {
return !(this.markLineIsBreak < 0 && this.mulArrowIsBreak_JG < 0 && this.mulArrowIsBreak_CT)
}
/**
* 当选中预设时,设置多点创建物的状态
* @param select
*/
setMultiPointOnSelectPrefab(select: boolean, data: MarkData) {
if (select == false) {
return;
}
if (data.type == MarkType.JJX) {
this.markLineIsBreak = 0;
}
else {
this.markLineIsBreak = -1;
}
if (data.type == MarkType.JGLX) {
this.mulArrowIsBreak_JG = 0;
}
else {
this.mulArrowIsBreak_JG = -1;
}
if (data.type == MarkType.CT) {
this.mulArrowIsBreak_CT = 0;
}
else {
this.mulArrowIsBreak_CT = -1
}
}
/**
* 查找建筑内所有水源
* @param buildingInfo
*/
getAllWaterSource(buildingInfo: ModelInfo_building) {
let result = [];
for (let i = 0; i < buildingInfo.facilityInfos.length; i++) {
let item = buildingInfo.facilityInfos[i];
if (this.isWaterSouce(item.type)) {
result = result.concat(item.facilityInfo);
}
}
return result;
}
/**
* 是水源类型
* @param type
*/
isWaterSouce(type: FacilityType) {
let result = false;
return result;
}
/**
* 改变自然效果
* @param show
* @param natureData
*/
changeNatureEffect(show: boolean, natureData: NatureData) {
if (show) {
this.weatherTool.changeWeatherEffect(natureData.weather);
this.weatherTool.changeWindDirection(natureData.windDirection);
this.weatherTool.changeWindPower(natureData.windPower);
}
else {
this.weatherTool.show(show);
}
}
/**
* 预加载模型
*/
preLoadMesh() {
if (MarkWindow.s_preLoadMesh) {
for (let i = 0; i < DataManager.allMarkData.marks_Disaster.length; i++) {
MeshPool.importMesh(ModelType.Mark, DataManager.allMarkData.marks_Disaster[i], true, false, LoadTool.c_tag_preloadMark, (meshBox: AbstractMesh, meshes: AbstractMesh[], result: MeshPoolInfo) => {
MeshPool.disposeMesh(result);
});
}
for (let i = 0; i < DataManager.allMarkData.marks_Outside.length; i++) {
MeshPool.importMesh(ModelType.Mark, DataManager.allMarkData.marks_Outside[i], true, false, LoadTool.c_tag_preloadMark, (meshBox: AbstractMesh, meshes: AbstractMesh[], result: MeshPoolInfo) => {
MeshPool.disposeMesh(result);
});
}
for (let i = 0; i < DataManager.allMarkData.marks_Inside.length; i++) {
MeshPool.importMesh(ModelType.Mark, DataManager.allMarkData.marks_Inside[i], true, false, LoadTool.c_tag_preloadMark, (meshBox: AbstractMesh, meshes: AbstractMesh[], result: MeshPoolInfo) => {
MeshPool.disposeMesh(result);
});
}
for (let i = 0; i < DataManager.allMarkData.marks_Other.length; i++) {
MeshPool.importMesh(ModelType.Mark, DataManager.allMarkData.marks_Other[i], true, false, LoadTool.c_tag_preloadMark, (meshBox: AbstractMesh, meshes: AbstractMesh[], result: MeshPoolInfo) => {
MeshPool.disposeMesh(result);
});
}
}
}
/**
* 预加载一个标绘物
* @param data
*/
preLoadOneMesh(data: MarkData) {
if (!MarkWindow.s_preLoadMesh && MeshPool.Instance.getMeshPrefab(data.resPath, data.resName) == null) {
MeshPool.importMesh(ModelType.Mark, data, true, true, LoadTool.c_tag_preloadMark, (meshBox: AbstractMesh, meshes: AbstractMesh[], result: MeshPoolInfo) => {
MeshPool.disposeMesh(result);
}, true);
}
}
/**
* 朗读描述
* @param describe
*/
readDescribe(describe: string) {
if (describe != null) {
SpeakingTool.Instance.clear();
SpeakingTool.Instance.speak(describe);
}
}
//#endregion
//#region 应急模板
/**
* 所有应急模板
*/
allSandBoxTemplate: MarkTemplate[];
/**
* 获取所有沙盒模板
*/
getAllSandBoxTemplate() {
let instance = this;
this.allSandBoxTemplate = [];
ServeManager.instance.getAllMarkTemplate((data: any) => {
if (data == null) {
instance.allSandBoxTemplate = [];
}
else {
// console.log("getAllSandBoxTemplate", data);
instance.allSandBoxTemplate = data;
}
});
}
/**
* 根据模板创建一个应急预案
* @param id
*/
addMarkPlanByTemplate(id: number) {
let instance = this;
ServeManager.instance.getOneMarkTemplate(id, (data: any) => {
let value = plainToClass(MarkPlanData, data);
instance.allMarkPlanData.createPlanDataByTemplate(value);
instance.saveAllMarkPlanData();
})
}
/**
* 保存为模板
* @param id
* @param name
* @param data
*/
saveToSandBoxTemplate(data: MarkPlanData) {
let name: string = data.name;
let id: number = Math.ceil(new Date().getTime() * 0.001);
let instance = this;
ServeManager.instance.saveOneMarkTemplate(id, name, data, (data: string) => {
instance.getAllSandBoxTemplate();
});
}
/**
* 删除模板
* @param id
*/
deleteSandBoxTemplate(id: number) {
let instance = this;
ServeManager.instance.deleteSandBoxTemplate(id, () => {
instance.getAllSandBoxTemplate();
});
}
//#endregion
}