Browse Source

合并代码

dev
陈鹏飞 3 years ago
parent
commit
df4ce32114
  1. 9
      package.json
  2. 23
      src/app/app.component.ts
  3. 232
      src/app/babylon/controller/config-manager.ts
  4. 646
      src/app/babylon/controller/data-manager.ts
  5. 12
      src/app/babylon/controller/event-manager/event-base.ts
  6. 138
      src/app/babylon/controller/event-manager/event-manager.ts
  7. 30
      src/app/babylon/controller/event-manager/events/event-change-facility.ts
  8. 23
      src/app/babylon/controller/event-manager/events/event-get-markplandata-success.ts
  9. 17
      src/app/babylon/controller/event-manager/events/event-keyboard-input.ts
  10. 43
      src/app/babylon/controller/event-manager/events/event-mark-info-change.ts
  11. 32
      src/app/babylon/controller/event-manager/events/event-modelinfo-change.ts
  12. 228
      src/app/babylon/controller/info-manager.ts
  13. 1436
      src/app/babylon/controller/inputController.ts
  14. 79
      src/app/babylon/controller/mode-manager.ts
  15. 915
      src/app/babylon/controller/scene-manager.ts
  16. 242
      src/app/babylon/controller/serve-manager.ts
  17. 164
      src/app/babylon/controller/status/building-status.ts
  18. 127
      src/app/babylon/controller/status/indoor-status.ts
  19. 219
      src/app/babylon/controller/status/login-status.ts
  20. 28
      src/app/babylon/controller/status/main-status.ts
  21. 74
      src/app/babylon/controller/status/status-manager.ts
  22. 43
      src/app/babylon/controller/ui-manager.ts
  23. 58
      src/app/babylon/game.ts
  24. 37
      src/app/babylon/model/data/camera-data.ts
  25. 70
      src/app/babylon/model/data/institution/building/building-data.ts
  26. 78
      src/app/babylon/model/data/institution/facility/all-facility-data.ts
  27. 30
      src/app/babylon/model/data/institution/facility/property-data/base/property-data-base-img.ts
  28. 27
      src/app/babylon/model/data/institution/facility/property-data/base/property-data-base-lt.ts
  29. 31
      src/app/babylon/model/data/institution/facility/property-data/base/property-data-base-sbjhq.ts
  30. 34
      src/app/babylon/model/data/institution/facility/property-data/base/property-data-base-xfb.ts
  31. 32
      src/app/babylon/model/data/institution/facility/property-data/base/property-data-base-xhs.ts
  32. 27
      src/app/babylon/model/data/institution/facility/property-data/indoor/property-data-dwbz.ts
  33. 31
      src/app/babylon/model/data/institution/facility/property-data/indoor/property-data-fhfq.ts
  34. 26
      src/app/babylon/model/data/institution/facility/property-data/indoor/property-data-sslt.ts
  35. 24
      src/app/babylon/model/data/institution/facility/property-data/indoor/property-data-xfdt.ts
  36. 42
      src/app/babylon/model/data/institution/facility/property-data/indoor/property-data-zdqy.ts
  37. 31
      src/app/babylon/model/data/institution/facility/property-data/outdoor/property-data-aqck.ts
  38. 26
      src/app/babylon/model/data/institution/facility/property-data/outdoor/property-data-gd.ts
  39. 36
      src/app/babylon/model/data/institution/facility/property-data/outdoor/property-data-pl.ts
  40. 37
      src/app/babylon/model/data/institution/facility/property-data/outdoor/property-data-q.ts
  41. 38
      src/app/babylon/model/data/institution/facility/property-data/property-data-base.ts
  42. 14
      src/app/babylon/model/data/institution/facility/property-data/property-data-public.ts
  43. 5
      src/app/babylon/model/data/institution/institution-data-simple.ts
  44. 87
      src/app/babylon/model/data/institution/institution-data.ts
  45. 226
      src/app/babylon/model/data/mark/all-mark-data.ts
  46. 597
      src/app/babylon/model/data/mark/mark-data.ts
  47. 491
      src/app/babylon/model/data/mark/mark-plan-data.ts
  48. 50
      src/app/babylon/model/data/mark/mark-property.ts
  49. 19
      src/app/babylon/model/data/mark/other/mark-data-area.ts
  50. 21
      src/app/babylon/model/data/mark/other/mark-data-line.ts
  51. 41
      src/app/babylon/model/data/mark/other/mark-data-multi-arrow.ts
  52. 31
      src/app/babylon/model/data/mark/other/mark-data-multi-line.ts
  53. 18
      src/app/babylon/model/data/model-data/model-data-building.ts
  54. 279
      src/app/babylon/model/data/model-data/model-data-facility.ts
  55. 71
      src/app/babylon/model/data/model-data/model-data.ts
  56. 78
      src/app/babylon/model/data/model-data/model-edit-data.ts
  57. 42
      src/app/babylon/model/data/transform-data.ts
  58. 8
      src/app/babylon/model/info/building/building-info-chemicalplant.ts
  59. 54
      src/app/babylon/model/info/building/building-info-environment.ts
  60. 11
      src/app/babylon/model/info/building/building-info-normal.ts
  61. 118
      src/app/babylon/model/info/building/building-info.ts
  62. 73
      src/app/babylon/model/info/mark/all-mark-info.ts
  63. 130
      src/app/babylon/model/info/mark/mark-plan-info.ts
  64. 534
      src/app/babylon/model/info/mark/model-info-mark.ts
  65. 270
      src/app/babylon/model/info/mark/other/mark-plan-area-info.ts
  66. 182
      src/app/babylon/model/info/mark/other/mark-plan-line-info.ts
  67. 322
      src/app/babylon/model/info/mark/other/mark-plan-multi-arrow.ts
  68. 184
      src/app/babylon/model/info/mark/other/mark-plan-multi-line-info.ts
  69. 148
      src/app/babylon/model/info/mark/other/mark-plan-particle-info.ts
  70. 368
      src/app/babylon/model/info/model/facilityinfo-tool/facility-area.ts
  71. 266
      src/app/babylon/model/info/model/facilityinfo-tool/facility-gd.ts
  72. 231
      src/app/babylon/model/info/model/model-info-building.ts
  73. 196
      src/app/babylon/model/info/model/model-info-facility.ts
  74. 264
      src/app/babylon/model/info/model/model-info.ts
  75. 534
      src/app/babylon/tool/babylon-tool.ts
  76. 522
      src/app/babylon/tool/babylon-ui-style-tool.ts
  77. 9
      src/app/babylon/tool/game-object.ts
  78. 615
      src/app/babylon/tool/gizmo-tool.ts
  79. 65
      src/app/babylon/tool/load-tool.ts
  80. 476
      src/app/babylon/tool/measure-tool.ts
  81. 322
      src/app/babylon/tool/mesh-pool.ts
  82. 262
      src/app/babylon/tool/myArcRotateCameraPointersInput.ts
  83. 113
      src/app/babylon/tool/particle-system-tool.ts
  84. 112
      src/app/babylon/tool/photo360-tool.ts
  85. 112
      src/app/babylon/tool/pos-point-tool.ts
  86. 6
      src/app/babylon/tool/time-tool.ts
  87. 26
      src/app/babylon/tool/ts-tool.ts
  88. 351
      src/app/babylon/view/building-window/building-create-window.ts
  89. 212
      src/app/babylon/view/building-window/building-ui-item.ts
  90. 499
      src/app/babylon/view/building-window/building-window.ts
  91. 131
      src/app/babylon/view/dialog-window/dialog-window.ts
  92. 90
      src/app/babylon/view/facility-window/facility-ui-item.ts
  93. 521
      src/app/babylon/view/facility-window/facility-window.ts
  94. 202
      src/app/babylon/view/facilityinfoinscene-window/facilityinfo-ui-item.ts
  95. 603
      src/app/babylon/view/facilityinfoinscene-window/facilityinfoinscene-window.ts
  96. 234
      src/app/babylon/view/indoor-window/indoor-create-window.ts
  97. 278
      src/app/babylon/view/indoor-window/indoor-floorui-item.ts
  98. 281
      src/app/babylon/view/indoor-window/indoor-window.ts
  99. 190
      src/app/babylon/view/institution/institution-create-window.ts
  100. 59
      src/app/babylon/view/institution/institution-item.ts
  101. Some files were not shown because too many files have changed in this diff Show More

9
package.json

@ -22,19 +22,28 @@
"@angular/platform-browser": "~9.0.0",
"@angular/platform-browser-dynamic": "~9.0.0",
"@angular/router": "~9.0.0",
"@babylonjs/core": "^4.2.0",
"@babylonjs/gui": "^4.2.0",
"@babylonjs/inspector": "^4.2.0",
"@babylonjs/loaders": "^4.2.0",
"@babylonjs/materials": "^4.2.0",
"@types/cesium": "^1.59.5",
"@types/react-dom": "^17.0.10",
"@types/swiper": "^5.2.1",
"angular-calendar": "^0.28.2",
"bson-objectid": "^1.3.1",
"cesium": "^1.64.0",
"class-transformer": "^0.4.0",
"e-ngx-cesium": "^6.3.2",
"echarts": "^4.6.0",
"firebase": "^7.6.2",
"install": "^0.13.0",
"ng-zorro-antd": "^9.3.0",
"ngx-cookie-service": "^3.0.2",
"ngx-countdown": "^11.0.0",
"ngx-echarts": "^4.2.2",
"ngx-perfect-scrollbar": "^8.0.0",
"reflect-metadata": "^0.1.13",
"rxjs": "~6.5.4",
"swiper": "^5.3.6",
"tslib": "^1.10.0",

23
src/app/app.component.ts

@ -1,9 +1,10 @@
import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http'
import { Data } from './interface'
import { Router,ActivatedRoute } from '@angular/router'
import {CacheTokenService} from './service/cache-token.service'//引入服务
import { Router, ActivatedRoute } from '@angular/router'
import { CacheTokenService } from './service/cache-token.service'//引入服务
import { CookieService } from 'ngx-cookie-service';
import "reflect-metadata";
@ -14,17 +15,17 @@ import { CookieService } from 'ngx-cookie-service';
})
export class AppComponent {
constructor(private http:HttpClient,private router:Router,public token:CacheTokenService,private cookieService: CookieService) { }
constructor(private http: HttpClient, private router: Router, public token: CacheTokenService, private cookieService: CookieService) { }
ngOnInit(): void {
var token = this.cookieService.get("token")
var refreshToken = this.cookieService.get("refreshToken");
if(token && refreshToken) {
this.http.post('/api/CompanyAccount/RefreshToken',{token: token,refreshToken: refreshToken}).subscribe((data: Data) => {
sessionStorage.setItem("token",data.token);
this.cookieService.set("token",data.token,null,'/');
this.cookieService.set("refreshToken",data.refreshToken,null,'/');
this.token.startUp()
var token = this.cookieService.get("token")
var refreshToken = this.cookieService.get("refreshToken");
if (token && refreshToken) {
this.http.post('/api/CompanyAccount/RefreshToken', { token: token, refreshToken: refreshToken }).subscribe((data: Data) => {
sessionStorage.setItem("token", data.token);
this.cookieService.set("token", data.token, null, '/');
this.cookieService.set("refreshToken", data.refreshToken, null, '/');
this.token.startUp()
})
}
}

232
src/app/babylon/controller/config-manager.ts

@ -0,0 +1,232 @@
import { MarkKindType, MarkType, MarkTagPos } from "../model/data/mark/mark-data";
import { FacilityPosType, FacilityType } from "../model/data/model-data/model-data-facility";
//配置、常量管理器
export class ConfigManager {
static readonly c_resPath_assetsRoot = 'assets/'; //资源根目录
static readonly c_resPath_institutionsRoot = 'institutions/'; //单位
static readonly c_reaPath_facilityProperty = "facilityProperty";//设备属性资源(一般是图片)
static readonly c_resPath_facilitiesRoot = 'facilities/'; //设备资源
static readonly c_resPath_facilityIcon = "images/facility/";// 设备icon
static readonly c_size_facilityIconSize = 40;//设备icon的大小
static readonly c_time_longPress = 500;//长按时间(毫秒)
/**
* icon的url
* @param type
* @param pos
*/
static getFacilityIconUrl(type: FacilityType, pos: FacilityPosType): string {
let result = ConfigManager.c_resPath_assetsRoot + "images/facility/" + pos + "/" + type + ".png";
return result;
}
/**
*
* @param type
*/
static getFacilityTypeName(type: FacilityType): string {
let result = "未知";
switch (type) {
case FacilityType.AQCK: result = "安全出口"; break;
case FacilityType.DSXHS: result = "地上消火栓"; break;
case FacilityType.DXXHS: result = "地下消火栓"; break;
case FacilityType.SZDSXHS: result = "市政地上消火栓"; break;
case FacilityType.SZDXXHS: result = "市政地下消火栓"; break;
case FacilityType.DSSBJHQ: result = "地上水泵接合器"; break;
case FacilityType.DXSBJHQ: result = "地下水泵接合器"; break;
case FacilityType.QBSBJHQ: result = "墙壁式接合器"; break;
case FacilityType.DGNSBJHQ: result = "多功能接合器"; break;
case FacilityType.GD: result = "高度"; break;
case FacilityType.PL: result = "毗邻"; break;
case FacilityType.JTQ: result = "禁停区"; break;
case FacilityType.JJQ: result = "集结区"; break;
case FacilityType.TPBZ: result = "图片标注"; break;
case FacilityType.XKS: result = "消控室"; break;
case FacilityType.BF: result = "泵房"; break;
case FacilityType.SX: result = "水箱"; break;
case FacilityType.LSXFB: result = "立式消防泵"; break;
case FacilityType.WSXFB: result = "卧式消防泵"; break;
case FacilityType.CYXFB: result = "柴油消防泵"; break;
case FacilityType.FHFQ: result = "防火分区"; break;
case FacilityType.SNXHS: result = "室内消火栓"; break;
case FacilityType.FHM: result = "防火门"; break;
case FacilityType.FHJL: result = "防火卷帘"; break;
case FacilityType.SSLT: result = "疏散楼梯"; break;
case FacilityType.XFDT: result = "消防电梯"; break;
case FacilityType.PTDT: result = "普通电梯"; break;
case FacilityType.WXY: result = "危险源"; break;
case FacilityType.ZDQY: result = "重点区域"; break;
case FacilityType.DWBZ: result = "点位标注"; break;
case FacilityType.HT: result = "货梯"; break;
case FacilityType.BNC: result = "避难层"; break;//特殊
}
return result;
}
/**
*
* @param facilityType
*/
static getPosType(facilityType: FacilityType): FacilityPosType {
let result = FacilityPosType.Indoor;
switch (facilityType) {
case FacilityType.AQCK:
case FacilityType.DSXHS:
case FacilityType.DXXHS:
case FacilityType.SZDXXHS:
case FacilityType.SZDSXHS:
case FacilityType.DSSBJHQ:
case FacilityType.DXSBJHQ:
case FacilityType.QBSBJHQ:
case FacilityType.DGNSBJHQ:
case FacilityType.GD:
case FacilityType.PL:
case FacilityType.JTQ:
case FacilityType.JJQ:
case FacilityType.TPBZ: result = FacilityPosType.Outdoor; break;
case FacilityType.DWBZ:
case FacilityType.ZDQY:
case FacilityType.WXY: result = FacilityPosType.Public; break;
}
return result;
}
//#region 事态标绘
/**
*
*/
static s_markName = new Map<MarkType, string>([
[MarkType.SYA, "伤员"],
[MarkType.SYB, "伤员"],
[MarkType.SYC, "伤员"],
[MarkType.SYD, "伤员"],
[MarkType.ZQR, "知情人"],
[MarkType.WXP, "危险品"],
[MarkType.ZWD, "杂物堆"],
[MarkType.PCD, "破拆点"],
[MarkType.H, "火"],
[MarkType.TPH, "突破火"],
[MarkType.SNH, "室内火"],
[MarkType.YWA, "烟雾"],
[MarkType.YWB, "烟雾"],
[MarkType.YWC, "烟雾"],
[MarkType.MHF, "灭火服"],
[MarkType.JYF, "救援服"],
[MarkType.GRF, "隔热服"],
[MarkType.FHF, "防化服"],
[MarkType.BHF, "避火服"],
[MarkType.YWXFY, "义务消防员"],
[MarkType.AQS, "安全哨"],
[MarkType.MTC, "摩托车"],
[MarkType.XLC, "巡逻车"],
[MarkType.SGC, "水罐车"],
[MarkType.PMC, "泡沫车"],
[MarkType.GPC, "高喷车"],
[MarkType.DGPTC, "登高平台车"],
[MarkType.YTC, "云梯车"],
[MarkType.QXJYC, "抢险救援车"],
[MarkType.QCC, "器材车"],
[MarkType.ZMC, "照明车"],
[MarkType.PCC, "破拆车"],
[MarkType.PYC, "排烟车"],
[MarkType.ZHC, "指挥车"],
[MarkType.GCGSC, "高层供水车"],
[MarkType.KQHXCQC, "空气呼吸充气车"],
[MarkType.GA, "公安"],
[MarkType.JJ, "交警"],
[MarkType.YS, "医生"],
[MarkType.QXRY, "抢修人员"],
[MarkType.JHC, "救护车"],
[MarkType.JC, "警车"],
[MarkType.DLQXC, "电力抢修车"],
[MarkType.RQQXC, "燃气抢修车"],
[MarkType.GSQXC, "供水抢修车"],
[MarkType.HBJCC, "环保检测车"],
[MarkType.JTYSC, "交通运输车"],
[MarkType.WSFYC, "卫生防疫车"],
[MarkType.YJTXC, "应急通信车"],
[MarkType.JCA, "轿车"],
[MarkType.JCB, "轿车"],
[MarkType.JCC, "轿车"],
[MarkType.DSZ, "董事长"],
[MarkType.JL, "经理"],
[MarkType.FZ, "副总"],
[MarkType.MS, "秘书"],
[MarkType.ZJ, "总监"],
[MarkType.ZG, "主管"],
[MarkType.ZZ, "组长"],
[MarkType.QT, "前台"],
[MarkType.SJS, "设计师"],
[MarkType.CXY, "程序员"],
[MarkType.ZYA, "职员"],
[MarkType.ZYB, "职员"],
[MarkType.JG, "技工"],
[MarkType.BA, "保安"],
[MarkType.JJX, "警戒线"],
[MarkType.SD, "水带"],
[MarkType.JGLX, "进攻路线"],
[MarkType.CT, "撤退"],
[MarkType.ZHB, "指挥部"],
[MarkType.LT6, "6米拉梯"],
[MarkType.LT15, "15米拉梯"],
[MarkType.FSQ, "分水器"],
[MarkType.STB, "手抬泵"],
[MarkType.SP, "水炮"],
[MarkType.WZ, "文字"],
[MarkType.JJQ, "集结区"],
[MarkType.QYSDA, "区域设定"],
[MarkType.QYSDB, "区域设定"],
]);
/**
*
* @param type
*/
static getMarkName(type: MarkType) {
if (ConfigManager.s_markName.has(type)) {
return ConfigManager.s_markName.get(type);
}
else {
return "未知";
}
}
/**
*
* @param type
* @param pos
*/
static getMarkModelPath(pos: MarkTagPos, type: MarkType): string {
let result = ConfigManager.c_resPath_assetsRoot + "mark/" + pos.toLocaleLowerCase() + "/" + type.toLocaleLowerCase() + "/";
return result;
}
/**
*
* @param type
* @param pos
*/
static getMarkIconUrl(pos: MarkTagPos, type: MarkType): string {
let result = ConfigManager.c_resPath_assetsRoot + "images/mark/" + pos.toLocaleLowerCase() + "/" + type.toLocaleLowerCase() + ".png";
return result;
}
//#endregion
}

646
src/app/babylon/controller/data-manager.ts

@ -0,0 +1,646 @@
import { Quaternion, Vector3 } from '@babylonjs/core';
import {
BuildingData,
BuildingData_ChemicalPlant,
BuildingData_Environment,
BuildingData_Normal,
BuildingType,
} from '../model/data/institution/building/building-data';
import {
FacilityPosType,
FacilityType,
ModelData_facility,
} from '../model/data/model-data/model-data-facility';
import {
InstitutionData,
NormalData,
} from '../model/data/institution/institution-data';
import {
BuildingPosType,
ModelData,
} from '../model/data/model-data/model-data';
import { ModelData_building } from '../model/data/model-data/model-data-building';
import { TransformData } from '../model/data/transform-data';
import { BabylonTool } from '../tool/babylon-tool';
import { AllFacilityData } from '../model/data/institution/facility/all-facility-data';
import { plainToClass } from 'class-transformer';
import { ConfigManager } from './config-manager';
import { ModelEditData } from '../model/data/model-data/model-edit-data';
import { ServeManager } from './serve-manager';
import { InsitutionDataSimple } from '../model/data/institution/institution-data-simple';
import { PropertyData_Base } from '../model/data/institution/facility/property-data/property-data-base';
import { PropertyData_AQCK } from '../model/data/institution/facility/property-data/outdoor/property-data-aqck';
import { PropertyData_public } from '../model/data/institution/facility/property-data/property-data-public';
import { TsTool } from '../tool/ts-tool';
import { PropertyData_Base_XHS } from '../model/data/institution/facility/property-data/base/property-data-base-xhs';
import { PropertyData_Base_SBJHQ } from '../model/data/institution/facility/property-data/base/property-data-base-sbjhq';
import { PropertyData_PL } from '../model/data/institution/facility/property-data/outdoor/property-data-pl';
import { PropertyData_Base_IMG } from '../model/data/institution/facility/property-data/base/property-data-base-img';
import { PropertyData_Base_XFB } from '../model/data/institution/facility/property-data/base/property-data-base-xfb';
import { PropertyData_FHFQ } from '../model/data/institution/facility/property-data/indoor/property-data-fhfq';
import { PropertyData_SSLT } from '../model/data/institution/facility/property-data/indoor/property-data-sslt';
import { PropertyData_XFDT } from '../model/data/institution/facility/property-data/indoor/property-data-xfdt';
import { PropertyData_ZDQY } from '../model/data/institution/facility/property-data/indoor/property-data-zdqy';
import { PropertyData_DWBZ } from '../model/data/institution/facility/property-data/indoor/property-data-dwbz';
import { PropertyData_GD } from '../model/data/institution/facility/property-data/outdoor/property-data-gd';
import { ModeManager, ModeType } from './mode-manager';
import { AllMarkData } from '../model/data/mark/all-mark-data';
import { AllMarkPlanData } from '../model/data/mark/mark-plan-data';
import { HttpErrorResponse } from '@angular/common/http';
import { PropertyData_Q } from '../model/data/institution/facility/property-data/outdoor/property-data-q';
class Test {
id: string;
}
//数据管理器
export class DataManager {
static institutionData_simple: InsitutionDataSimple;//当前单位简易信息
static institutionData: InstitutionData; //当前单位信息
static allFacilityData: AllFacilityData; //所有可用的设备数据(将来读取自配置表)
/**
*
*/
static allMarkData: AllMarkData;
/**
*
*/
static allMarkPlanData: AllMarkPlanData;
static initDebugData(institutionKey: string, onSuccess?: (key: string) => void, onError?: (key: string, error: string) => void) {
//本地捏造消防设备列表信息
DataManager.initDebugData_facility();
if (ModeManager.currentMode == ModeType.Look) {
DataManager.initDebugData_mark();
}
let dataFromServe = true;//true-表示数据来自服务器,false-表示来自本地捏造
if (dataFromServe) {
ServeManager.instance.getInstitutionData(institutionKey, (key, result) => {
if (onSuccess) {
DataManager.institutionData = plainToClass(InstitutionData, result);
DataManager.institutionData.normalData.name = DataManager.institutionData_simple.name;
// console.log(DataManager.institutionData);
onSuccess(key);
}
}, (key, error) => {
if (onError) {
console.error("获取单位信息失败" + key);
onError(key, error);
}
console.error("获取单位信息失败,本地捏造数据");
DataManager.initDebugData_institution();
if (onSuccess) {
onSuccess(key);
}
});
}
else {
//本地捏造测试数据
DataManager.initDebugData_institution();
onSuccess(DataManager.institutionData.normalData.key);
}
}
//初始化单位数据
static initDebugData_institution() {
DataManager.institutionData = new InstitutionData();
DataManager.institutionData.normalData = new NormalData();
DataManager.institutionData.normalData.key = 'Institution001';
DataManager.institutionData.normalData.name = '单位001';
DataManager.institutionData.environmentDatas = [
new BuildingData_Environment(),
];
DataManager.institutionData.environmentDatas[0].normalData = new NormalData();
DataManager.institutionData.environmentDatas[0].normalData.key =
'environment001';
DataManager.institutionData.environmentDatas[0].normalData.name = '环境001';
let environmentTransform = new TransformData(); //用于测试建筑的数据还原效果
environmentTransform.originalScaling = new Vector3(961.66, 5.17, 962.6);
environmentTransform.position = new Vector3(0, -2.939, 0);
environmentTransform.scaling = environmentTransform.originalScaling.clone();
DataManager.institutionData.environmentDatas[0].outdoorData = new ModelEditData();
DataManager.institutionData.environmentDatas[0].outdoorData.index = 1;
let resPath_en = DataManager.getResPath_building(
DataManager.institutionData.normalData.key.toLowerCase(),
DataManager.institutionData.environmentDatas[0].normalData.key.toLocaleLowerCase(),
BuildingPosType.Environment,
'modelEn001'
);
DataManager.institutionData.environmentDatas[0].outdoorData.modelData = new ModelData_building(
'modelEn001',
'环境001',
BuildingPosType.Environment,
'Terrain.gltf',
environmentTransform,
resPath_en
);
DataManager.institutionData.environmentDatas[0].describe = '这是环境';
let facilityTransform = new TransformData();
facilityTransform.position = new Vector3(-137, 3.3, 150);
facilityTransform.rotationQuaternion = Quaternion.FromEulerAngles(
0,
80 / BabylonTool.c_radian1,
0
);
facilityTransform.originalScaling = new Vector3(0.39, 0.7, 0.37);
facilityTransform.scaling = facilityTransform.originalScaling.multiplyByFloats(
2,
2,
2
);
// let facilityData = new ModelData_facility(
// 'facility001',
// FacilityType.DSXHS,
// '地上消火栓',
// 'DXXHS.gltf',
// facilityTransform,
// FacilityPosType.Outdoor
// );
// DataManager.institutionData.environmentDatas[0].outdoorData.facilities = [
// facilityData,
// ];
DataManager.institutionData.normalBuildingDatas = [
new BuildingData_Normal(),
];
DataManager.institutionData.normalBuildingDatas[0].normalData = new NormalData();
DataManager.institutionData.normalBuildingDatas[0].buildingType =
BuildingType.Normal;
DataManager.institutionData.normalBuildingDatas[0].normalData.key =
'building001';
DataManager.institutionData.normalBuildingDatas[0].normalData.name =
'大楼001';
DataManager.institutionData.normalBuildingDatas[0].describe =
'一个普通大楼';
DataManager.institutionData.normalBuildingDatas[0].outdoorData = new ModelEditData();
DataManager.institutionData.normalBuildingDatas[0].outdoorData.index = 1;
let resPath_out = DataManager.getResPath_building(
DataManager.institutionData.normalData.key.toLowerCase(),
DataManager.institutionData.normalBuildingDatas[0].normalData.key.toLocaleLowerCase(),
BuildingPosType.OutDoor,
'modelOut001'
);
DataManager.institutionData.normalBuildingDatas[0].outdoorData.modelData = new ModelData_building(
'modelOut001',
'外观模型1',
BuildingPosType.OutDoor,
'ZhuTi.gltf',
new TransformData(),
resPath_out
);
DataManager.institutionData.normalBuildingDatas[0].indoorsData = [];
let indoorData1 = new ModelEditData();
DataManager.institutionData.normalBuildingDatas[0].indoorsData.push(
indoorData1
);
indoorData1.index = 1;
let resPath_inDoor1 = DataManager.getResPath_building(
DataManager.institutionData.normalData.key.toLowerCase(),
DataManager.institutionData.normalBuildingDatas[0].normalData.key.toLocaleLowerCase(),
BuildingPosType.Indoor,
'nei1'
);
indoorData1.modelData = new ModelData_building(
'nei1',
'室内模型1层',
BuildingPosType.Indoor,
'nei1.gltf',
null,
resPath_inDoor1
);
let indoorData2 = new ModelEditData();
DataManager.institutionData.normalBuildingDatas[0].indoorsData.push(
indoorData2
);
indoorData2.index = 2;
let resPath_inDoor2 = DataManager.getResPath_building(
DataManager.institutionData.normalData.key.toLowerCase(),
DataManager.institutionData.normalBuildingDatas[0].normalData.key.toLocaleLowerCase(),
BuildingPosType.Indoor,
'nei2'
);
indoorData2.modelData = new ModelData_building(
'nei2',
'室内模型2层',
BuildingPosType.Indoor,
'nei2.gltf',
null,
resPath_inDoor2
);
indoorData2.facilities = [];
let indoorData2FacilityTransform = new TransformData();
indoorData2FacilityTransform.position = new Vector3(-6, -3.1, 29);
indoorData2FacilityTransform.rotationQuaternion = Quaternion.FromEulerAngles(
0,
30 / BabylonTool.c_radian1,
0
);
// let indoorData2FacilityData = new ModelData_facility(
// 'indoor2_facility001',
// FacilityType.DSXHS,
// '地下消火栓1',
// 'DSXHS.gltf',
// indoorData2FacilityTransform,
// FacilityPosType.Indoor
// );
// indoorData2.facilities.push(indoorData2FacilityData);
}
//获取建筑资源完整路径
static getResPath_building(
institutionKey: string,
buildingKey: string,
buildingPosType: BuildingPosType,
key: string
): string {
let result =
ConfigManager.c_resPath_institutionsRoot +
institutionKey.toLocaleLowerCase() +
'/' +
buildingKey.toLocaleLowerCase() +
'/' +
buildingPosType +
'/' +
key +
'/';
return result;
}
//获取属性所需文件的路径
static getResPath_facilityProperty(institutionKey: string,
buildingKey: string, facilityType: FacilityType, facilityKey: string, key: string) {
let result =
ConfigManager.c_resPath_institutionsRoot +
institutionKey.toLocaleLowerCase() +
'/' +
buildingKey.toLocaleLowerCase() +
'/' +
ConfigManager.c_reaPath_facilityProperty +
"/" +
facilityType.toLocaleLowerCase() +
'/' +
facilityKey.toLocaleLowerCase() +
"/";
return result;
}
//获取设备资源完整路径
static getResPath_facility(facilityPosType: FacilityPosType, type: FacilityType): string {
let result = "facilities/";
result += facilityPosType.toString() + "/";
result += DataManager.getResName_facility(type).toLocaleLowerCase();
result += "/";
return result;
}
//获取设备的资源名(有些是公用的)
static getResName_facility(type: FacilityType): string {
let result = type.toString();
switch (type) {
case FacilityType.XKS:
case FacilityType.BF:
case FacilityType.SX:
case FacilityType.FHM:
case FacilityType.FHJL:
case FacilityType.SSLT:
case FacilityType.XFDT:
case FacilityType.PTDT:
case FacilityType.HT:
case FacilityType.WXY: result = "Location"; break;
}
return result;
}
//初始化设备信息
static initDebugData_facility() {
DataManager.allFacilityData = AllFacilityData.CreateAllFacilityData();
}
/**
*
*/
static initDebugData_mark() {
DataManager.allMarkData = AllMarkData.CreateAllMarkData();
console.log(DataManager.allMarkData, "态势标会");
}
static init(simpleData: InsitutionDataSimple, onSuccess?: (key: string) => void) {
DataManager.institutionData_simple = simpleData;
DataManager.initDebugData(simpleData.key, onSuccess);
}
/**
*
*/
static initAllMarkPlaneData() {
DataManager.allMarkPlanData = new AllMarkPlanData();
DataManager.allMarkPlanData.institutionID = DataManager.institutionData.normalData.key;
DataManager.allMarkPlanData.datas = [];
return DataManager.allMarkPlanData;
}
/**
*
*/
static initMarkData(onSuccess?: (data: AllMarkPlanData) => void) {
ServeManager.instance.getMarkData(DataManager.institutionData.normalData.key, (institutionID: string, data: string) => {
if (data == null) //新建单位的标绘信息
{
DataManager.initAllMarkPlaneData();
}
else //读取已有的标绘信息
{
DataManager.allMarkPlanData = plainToClass(AllMarkPlanData, data);
}
if (onSuccess != null) {
onSuccess(DataManager.allMarkPlanData);
}
}, (institutionID: string, data: any) => {
if (data instanceof HttpErrorResponse && data.status == 404) {
//404,新增单位标绘数据,不算错误
}
else {
ModeManager.log("获取态势标会失败" + institutionID, data);
}
})
}
//#region 创建类方法
/**
*
* @param key
* @param name
* @param buildingType
*/
static createBuilding(key: string, name: string, buildingType: BuildingType): BuildingData {
let result = false;
if (buildingType == null) {
throw new Error('create building buildingType is null');
}
if (key == null) {
throw new Error('create building key is null');
}
if (name == null || name == "") {
throw new Error('create building name is null');
}
let normalData = new NormalData(key, name);
let newBuilding: BuildingData_Normal | BuildingData_Environment | BuildingData_ChemicalPlant;
switch (buildingType) {
case BuildingType.Normal:
newBuilding = new BuildingData_Normal();
DataManager.institutionData.normalBuildingDatas.push(newBuilding as BuildingData_Normal);
break;
case BuildingType.Environment:
newBuilding = new BuildingData_Environment();
DataManager.institutionData.environmentDatas.push(newBuilding as BuildingData_Environment);
break;
case BuildingType.ChemicalPlant:
newBuilding = new BuildingData_ChemicalPlant();
DataManager.institutionData.chemicalPlantData.push(newBuilding as BuildingData_ChemicalPlant);
break;
}
newBuilding.normalData = normalData;
return newBuilding;
}
/**
*
* @param key
* @param facilityType
*/
static createPropertyData(key: string, facilityType: FacilityType): PropertyData_Base {
let result: PropertyData_Base = null;
switch (facilityType) {
case FacilityType.AQCK: result = new PropertyData_AQCK(key, "", false, "安全出口", ""); break; //安全出口
case FacilityType.DSXHS:
case FacilityType.DXXHS:
case FacilityType.SZDSXHS:
case FacilityType.SZDXXHS: result = new PropertyData_Base_XHS(key, "", false, "", "", "", facilityType); break;
case FacilityType.DSSBJHQ:
case FacilityType.DXSBJHQ:
case FacilityType.QBSBJHQ:
case FacilityType.DGNSBJHQ: result = new PropertyData_Base_SBJHQ(key, "", "", "", "", facilityType); break;
case FacilityType.GD: result = new PropertyData_GD(key, "-"); break;
case FacilityType.PL: result = new PropertyData_PL(key, 0, "", []); break;
case FacilityType.JTQ:
case FacilityType.JJQ: result = new PropertyData_Q(key, "", "", "", null, facilityType); break;
case FacilityType.TPBZ:
case FacilityType.XKS:
case FacilityType.BF:
case FacilityType.SX: result = new PropertyData_Base_IMG(key, "", "", "", facilityType); break;
case FacilityType.LSXFB:
case FacilityType.WSXFB:
case FacilityType.CYXFB: result = new PropertyData_Base_XFB(key, "", "", "", "", "", "", facilityType); break;
case FacilityType.FHFQ: result = new PropertyData_FHFQ(key, "", ""); break;
case FacilityType.SSLT: result = new PropertyData_SSLT(key, "", "", ""); break;
case FacilityType.XFDT: result = new PropertyData_XFDT(key, "", "", ""); break;
case FacilityType.WXY: result = new PropertyData_Base_IMG(key, "", "", "", facilityType); break;
case FacilityType.ZDQY: result = new PropertyData_ZDQY(key, "", "", "", "", "", []); break;
case FacilityType.DWBZ: result = new PropertyData_DWBZ(key, "", ""); break;
//其他在表格中显示无
}
if (result == null) {
result = new PropertyData_public(key, facilityType);
}
return result;
}
/**
*
* @param name
*/
static createMarkPlane(name: string) {
if (DataManager.allMarkPlanData == null) {
console.error("当前单位没有标绘方案,无法新建");
return;
}
let index = 0;
}
//#endregion
//#region 查询类方法
/**
*
* @param buildingType
*/
static getBuildingDataListByType(buildingType: BuildingType): BuildingData_Normal[] | BuildingData_Environment[] | BuildingData_ChemicalPlant[] {
let buildingDatas: BuildingData_Normal[] | BuildingData_Environment[] | BuildingData_ChemicalPlant[];
switch (buildingType) {
case BuildingType.Normal:
buildingDatas = DataManager.institutionData.normalBuildingDatas;
break;
case BuildingType.Environment:
buildingDatas = DataManager.institutionData.environmentDatas;
break;
case BuildingType.ChemicalPlant:
buildingDatas = DataManager.institutionData.chemicalPlantData;
break;
}
return buildingDatas;
}
//#endregion
//#region 修改和删除类方法
//删除一个当前单位的buildingData
static deleteOneBuildingData(buildingType: BuildingType, key: string) {
let buildingDatas = DataManager.getBuildingDataListByType(buildingType);
for (let i = 0; i < buildingDatas.length; i++) {
if (buildingDatas[i].normalData.key == key) {
TsTool.arrayRemove(buildingDatas, buildingDatas[i]);
break;
}
}
}
/**
*
*/
static saveallMarkPlanData() {
console.log("当前标绘", DataManager.allMarkPlanData);
ServeManager.instance.saveMarkData(DataManager.allMarkPlanData);
}
//#endregion
//#region 文件修改类
/**
* manifest
* @param fileName //资源文件名,例如 zhuti.gltf
* @param version //版本号
*/
static createFile_manifest(fileName: string, version: number): File {
let file;
let data = [];
let info = {
"version": version,
"enableSceneOffline": true,
"enableTexturesOffline": true
};
data.push(JSON.stringify(info));
let properties = { type: 'text/cache-manifest' }; // 设置文件的 mime-type.
try {
// 使用文件构造函数指定文件名,如果 ...
file = new File(data, fileName + ".manifest", properties);
} catch (e) {
// ... 如果不支持Blob构造函数,请退回到Blob构造函数。
file = new Blob(data, properties);
}
console.log("创建版本号" + version);
return file;
}
/**
* (+1)
* @param indoorData
*/
static createManifestFile(modelData: ModelData): File {
modelData.version += 1;
let manifestFile = DataManager.createFile_manifest(modelData.resName, modelData.version);
return manifestFile;
}
/**
*
* @param file
*/
static readFile_manifest(file: File, onLoad: (result) => void): number {
let version = 1;
var reader = new FileReader();
reader.onload = function (evt) { // 指定异步读写后触发的函数
ModeManager.log(evt.target.result);
let object = JSON.parse(evt.target.result as string);
onLoad(object.version);
};
reader.readAsText(file);
return version;
}
//#endregion
}
//模型信息变化类型
export enum ModelChangeType {
Add,
Remove,
Update,
}

12
src/app/babylon/controller/event-manager/event-base.ts

@ -0,0 +1,12 @@
/**
*
*/
export class Event_Base {
//属性 自定义
}

138
src/app/babylon/controller/event-manager/event-manager.ts

@ -0,0 +1,138 @@
import { EventState, Observable, Observer, TransformNode } from "@babylonjs/core";
import { Event_Base } from "./event-base";
/**
*
*/
export class EventManager {
//#region 单例
private static instance: EventManager;
public static get Instcane() {
if (EventManager.instance == null) {
EventManager.instance = new EventManager();
}
return EventManager.instance;
}
//#endregion
//#region event 实例管理
//所有实例化的event
private static s_allEventContainer: any[];
//创建event实例
private static createEvent<T extends Event_Base>(c: { new(): T }): EventContainer<T> {
let newEvent = null;
if (newEvent == null) {
newEvent = new EventContainer<T>(c);
EventManager.s_allEventContainer.push(newEvent);
}
return newEvent;
}
//获取event实例
private static getEvent<T extends Event_Base>(c: { new(): T }): EventContainer<T> {
if (EventManager.s_allEventContainer == null) {
EventManager.s_allEventContainer = [];
}
let result = null;
for (let i = 0; i < EventManager.s_allEventContainer.length; i++) {
if (EventManager.s_allEventContainer[i].key == c.name) {
result = (EventManager.s_allEventContainer[i]);
// console.log("找到已有的event" + (c.name));
return result;
}
}
result = EventManager.createEvent<T>(c);
// console.log("新建event" + result);
return result;
}
//#endregion
/**
*
* @param callback
*/
static addListener<T extends Event_Base>(c: { new(): T }, callback: (eventData: T, eventState: EventState) => void,
mask?: number,
insertFirst?: boolean,
scope?: any,
unregisterOnFirstCall?: boolean): Observer<T> {
let instance = EventManager.getEvent<T>(c);
return instance.observable.add(callback, mask, insertFirst, scope, unregisterOnFirstCall);
}
/**
*
* @param observer
*/
static removeListener<T extends Event_Base>(c: { new(): T }, observer: Observer<T>) {
let instance = EventManager.getEvent<T>(c);
if (instance == null) {
return;
}
instance.observable.remove(observer);
}
/**
*
* @param callback
*/
static removeCallback<T extends Event_Base>(c: { new(): T }, callback: (eventData: T, eventState: EventState) => void,
mask?: number,
insertFirst?: boolean,
scope?: any,
unregisterOnFirstCall?: boolean) {
let instance = EventManager.getEvent<T>(c);
if (instance == null) {
return;
}
instance.observable.removeCallback(callback);
}
/**
*
* @param eventData
*/
static dispatch<T extends Event_Base>(c: { new(): T }, eventData: T) {
let instance = EventManager.getEvent<T>(c);
if (instance == null) {
return;
}
instance.observable.notifyObservers(eventData);
}
}
/**
*
*/
class EventContainer<T extends Event_Base> {
key: string;
observable: Observable<T>;
constructor(c: { new(): T }) {
this.key = c.name;
// console.log("EventContainer===" + this.key);
this.observable = new Observable<T>();
}
}

30
src/app/babylon/controller/event-manager/events/event-change-facility.ts

@ -0,0 +1,30 @@
import { ModelData } from "src/babylon/model/data/model-data/model-data";
import { BuildingInfo } from "src/babylon/model/info/building/building-info";
import { ModelChangeType } from "../../data-manager";
import { Event_Base } from "../event-base";
import { EventManager } from "../event-manager";
export class Event_ChangeFacility extends Event_Base {
modeleData: ModelData;
modelChangeType: ModelChangeType;
belongtoBuilding: BuildingInfo;//属于哪个建筑
initInfo(modeleData: ModelData,
modelChangeType: ModelChangeType,
belongtoBuilding: BuildingInfo) {
this.modeleData = modeleData;
this.modelChangeType = modelChangeType;
this.belongtoBuilding = belongtoBuilding;
}
static dispatch(modeleData: ModelData,
modelChangeType: ModelChangeType,
belongtoBuilding: BuildingInfo) {
let eventInfo = new Event_ChangeFacility();
eventInfo.initInfo(modeleData, modelChangeType, belongtoBuilding);
EventManager.dispatch(Event_ChangeFacility, eventInfo);
}
}

23
src/app/babylon/controller/event-manager/events/event-get-markplandata-success.ts

@ -0,0 +1,23 @@
import { AllMarkPlanData } from "src/babylon/model/data/mark/mark-plan-data";
import { Event_Base } from "../event-base";
import { EventManager } from "../event-manager";
/**
*
*/
export class Event_GetAllMarkPlanData extends Event_Base {
success: boolean;
data: AllMarkPlanData;
static dispatch(success: boolean, data: AllMarkPlanData) {
let info = new Event_GetAllMarkPlanData();
info.success = success;
info.data = data;
EventManager.dispatch(Event_GetAllMarkPlanData, info);
}
}

17
src/app/babylon/controller/event-manager/events/event-keyboard-input.ts

@ -0,0 +1,17 @@
import { Event_Base } from "../event-base";
import { EventManager } from "../event-manager";
/**
*
*/
export class Event_KeyboardInput extends Event_Base {
data: KeyboardEvent;
static dispatch(ev: KeyboardEvent) {
let eventData = new Event_KeyboardInput();
eventData.data = ev;
EventManager.dispatch<Event_KeyboardInput>(Event_KeyboardInput, eventData);
}
}

43
src/app/babylon/controller/event-manager/events/event-mark-info-change.ts

@ -0,0 +1,43 @@
import { ModelInfo_mark } from "src/babylon/model/info/mark/model-info-mark";
import { Event_Base } from "../event-base";
import { EventManager } from "../event-manager";
/**
* MarkInfo()
*/
export class Event_MarkInfoChange extends Event_Base {
eventType: MarkInfoChangeType;
markInfo: ModelInfo_mark;
static dispatch(eventType: MarkInfoChangeType, markInfo: ModelInfo_mark) {
let eventInfo = new Event_MarkInfoChange();
eventInfo.eventType = eventType;
eventInfo.markInfo = markInfo;
EventManager.dispatch(Event_MarkInfoChange, eventInfo);
}
}
/**
*
*/
export enum MarkInfoChangeType {
/**
*
*/
Create,
/**
*
*/
Select,
/**
*
*/
UnSelect,
}

32
src/app/babylon/controller/event-manager/events/event-modelinfo-change.ts

@ -0,0 +1,32 @@
import { ModelInfo } from "src/babylon/model/info/model/model-info";
import { ModelChangeType } from "../../data-manager";
import { Event_Base } from "../event-base";
import { EventManager } from "../event-manager";
/**
* modelInfo发生变化
*/
export class Event_ModelInfoChange extends Event_Base {
//属性
modeleInfo: ModelInfo;
modelChangeType: ModelChangeType;
setInfo(modelInfo: ModelInfo, modelChangeType: ModelChangeType) {
this.modeleInfo = modelInfo;
this.modelChangeType = modelChangeType;
}
/**
*
* @param modeleInfo
* @param modelChangeType
*/
static dispatch(modeleInfo: ModelInfo, modelChangeType: ModelChangeType) {
let eventData = new Event_ModelInfoChange();
eventData.setInfo(modeleInfo, modelChangeType);
EventManager.dispatch<Event_ModelInfoChange>(Event_ModelInfoChange, eventData);
}
}

228
src/app/babylon/controller/info-manager.ts

@ -0,0 +1,228 @@
import { AbstractMesh } from "@babylonjs/core";
import { MarkData } from "../model/data/mark/mark-data";
import { ModelData } from "../model/data/model-data/model-data";
import { FacilityType, ModelData_facility } from "../model/data/model-data/model-data-facility";
import { ModelEditData } from "../model/data/model-data/model-edit-data";
import { TransformData } from "../model/data/transform-data";
import { BuildingInfo } from "../model/info/building/building-info";
import { ModelInfo_mark } from "../model/info/mark/model-info-mark";
import { ModelInfo } from "../model/info/model/model-info";
import { ModelInfo_building } from "../model/info/model/model-info-building";
import { FacilityInfoByType, ModelInfo_facility } from "../model/info/model/model-info-facility";
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 { ModelChangeType } from "./data-manager";
import { Event_ModelInfoChange } from "./event-manager/events/event-modelinfo-change";
import { ModeManager, ModeType } from "./mode-manager";
import { SceneManager } from "./scene-manager";
//运行时数据管理器
export class InfoManager {
static s_currentTransformData: TransformData; //当前模型的transform信息
static s_currentMesh: AbstractMesh; //当前选中的mesh
// static s_allBuildingInfos: ModelInfo_building[] = []; //所有实例化的建筑(室外)
// static s_allFactivityInfos_outdoor: FacilityInfoByType[] = []; //所有实例化的设备(室外)
// static s_allFactivityInfos_indoor: FacilityInfoByType[] = []; //所有实例化的设备(室内)
// static s_onModelInfoChangeObservable: Observable<ModelInfoChange>; //模型信息变化事件
// static s_onModelEnableChangeObservable: Observable<AbstractMesh>; //模型状态变化事件
static init() {
SceneManager.Instance.scene.onBeforeRenderObservable.add(InfoManager.onBeforeRender);
GizmoTool.onPickMeshInfoObservable.add(InfoManager.onPickMesh);
}
static onBeforeRender() {
if (InfoManager.s_currentTransformData != null) {
InfoManager.s_currentTransformData.position =
InfoManager.s_currentMesh.position;
InfoManager.s_currentTransformData.rotation =
InfoManager.s_currentMesh.rotation;
InfoManager.s_currentTransformData.rotationQuaternion =
InfoManager.s_currentMesh.rotationQuaternion;
InfoManager.s_currentTransformData.scaling =
InfoManager.s_currentMesh.scaling;
InfoManager.s_currentMesh.absoluteScaling;
}
}
static onPickMesh(modelInfo: ModelInfo) {
if (modelInfo != null) {
InfoManager.s_currentMesh = modelInfo.modelBox;
InfoManager.s_currentTransformData = modelInfo.modelData.transformData;
}
}
//加入管理
static addModelInfo(modelInfo: ModelInfo) {
Event_ModelInfoChange.dispatch(modelInfo, ModelChangeType.Add);
}
/**
* info
* @param key
* @param modelData
* @param models
* @param modelBox
*/
static newModelInfo_building(key: string,
modelData: ModelData,
models: AbstractMesh[],
modelBox: AbstractMesh): ModelInfo_building {
let result = new ModelInfo_building(key,
modelData,
models,
modelBox);
InfoManager.addModelInfo(result);
return result;
}
/**
* info
* @param key
* @param modelData
* @param models
* @param modelBox
*/
static newModelInfo_facility(key: string,
modelData: ModelData,
models: AbstractMesh[],
modelBox: AbstractMesh,
belongToBuilding: BuildingInfo,
isNew: boolean): ModelInfo_facility {
let result = new ModelInfo_facility(key,
modelData,
models,
modelBox,
belongToBuilding,
isNew
);
if (belongToBuilding != null) //表示游离态的设备
{
InfoManager.addFacilityInfoToTypeList(result, belongToBuilding.ModelInfo.facilityInfos);
}
InfoManager.addModelInfo(result);
return result;
}
/**
* info
* @param key
* @param modelData
* @param models
* @param modelBox
*/
static newModelInfo_mark(
markData: MarkData,
models: AbstractMesh[],
modelBox: AbstractMesh,
belongToBuilding: BuildingInfo,
isNew: boolean): ModelInfo_mark {
let result = new ModelInfo_mark(
markData,
models,
modelBox,
belongToBuilding,
isNew
);
// if (belongToBuilding != null) //表示游离态的设备
// {
// InfoManager.addFacilityInfoToTypeList(result, belongToBuilding.ModelInfo.facilityInfos);
// }
if (isNew) {
InfoManager.addModelInfo(result);
}
return result;
}
//移除model info
static removeModelInfo(modelInfo: ModelInfo) {
Event_ModelInfoChange.dispatch(modelInfo, ModelChangeType.Remove);
}
//创建建筑中的设备
static createFacilityInfos(
modelEditData: ModelEditData,
buildingInfo: BuildingInfo = null
) {
let facilities = modelEditData.facilities;
for (let i = 0; i < facilities.length; i++) {
for (let j = 0; j < facilities[i].facilities.length; j++) {
FacilityWindow.instance.createFacility(
modelEditData.facilities[i].facilities[j],
false,
buildingInfo,
true,
false,
(modelInfo: ModelInfo_facility) => {
if (ModeManager.currentMode == ModeType.Look) {
modelInfo.setIconEnable(false);//查看模式下隐藏所有设备ui
}
}
);
}
}
}
//将某设备info,加入到相应的列表中
static addFacilityInfoToTypeList(facilityInfo: ModelInfo_facility, facilityInfosByType: FacilityInfoByType[]) {
let facilityType = (facilityInfo.modelData as ModelData_facility).facilityType;
let facilityInfoByType = InfoManager.getFacilityInfoByType(facilityType, facilityInfosByType);
if (facilityInfoByType == null) {
facilityInfoByType = new FacilityInfoByType(facilityType);
facilityInfosByType.push(facilityInfoByType);
}
facilityInfoByType.facilityInfo.push(facilityInfo);
}
//将某设备info,从相应的列表中移除
static removeFacilityInfoToTypeList(facilityInfo: ModelInfo_facility, facilityInfosByType: FacilityInfoByType[]) {
let facilityType = (facilityInfo.modelData as ModelData_facility).facilityType;
let facilityInfoByType = InfoManager.getFacilityInfoByType(facilityType, facilityInfosByType);
TsTool.arrayRemove(facilityInfoByType.facilityInfo, facilityInfo);
}
//根据类型获取
static getFacilityInfoByType(facilityType: FacilityType, facilityInfosByType: FacilityInfoByType[]) {
let result: FacilityInfoByType = null;
for (let i = 0; i < facilityInfosByType.length; i++) {
if (facilityInfosByType[i].type == facilityType) {
result = facilityInfosByType[i];
break;
}
}
return result;
}
}

1436
src/app/babylon/controller/inputController.ts

File diff suppressed because it is too large Load Diff

79
src/app/babylon/controller/mode-manager.ts

@ -0,0 +1,79 @@
/**
*
*/
export enum ModeType {
Look = "Look",//查看模式
Edit = "Edit",//编辑模式
}
/**
*
*/
export class ModeManager {
/**
*
*/
private static s_currentMode: ModeType = ModeType.Edit;
/**
*
*/
public static isDebug = true;
//#region 演示单单位
//未指定演示单位,正常打开
static readonly c_demoKey_null = null;
// 上海国际会议中心 测试
static readonly c_demoKey_shanghai = "shanghai";
//测试
static readonly c_demoKey_test = "test";
/**
* key
*/
public static institutionDemoKey = ModeManager.c_demoKey_null;
//#endregion
/**
*
*/
static get currentMode(): ModeType {
return ModeManager.s_currentMode;
}
/**
*
*/
static set currentMode(modeType: ModeType) {
ModeManager.s_currentMode = modeType;
ModeManager.log("currentMode" + modeType);
}
//封装打印
static log(data: any, ...optionalParams: any[]) {
if (ModeManager.isDebug) {
console.log(data, optionalParams);
}
}
/**
*
*/
static trace(message?: any, ...optionalParams: any[]) {
if (ModeManager.isDebug) {
console.trace(message, optionalParams);
}
}
}

915
src/app/babylon/controller/scene-manager.ts

@ -0,0 +1,915 @@
import {
AbstractMesh,
AnimationGroup,
ArcRotateCamera,
BoundingBoxGizmo,
Color3,
Color4,
CubeTexture,
DirectionalLight,
Engine,
EventState,
HemisphericLight,
HighlightLayer,
IParticleSystem,
Mesh,
MeshBuilder,
Observable,
Observer,
PBRMaterial,
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';
//场景管理器
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;
}
return SceneManager.instance;
}
//#endregion
//#region 摄像机
/**
* -
*/
public cameraMode_Is2D = false;
//初始化自由旋转相机
public initArcRotateCamera() {
let camera = new ArcRotateCamera(
'Camera', //名称
0, //alpha: 定义相机沿垂直轴的旋转
1.2, //beta: 定义相机沿水平轴的旋转
10, //摄像机与目标位置的距离
Vector3.Zero(), //目标位置
this.scene //定义摄像机所属的场景
);
camera.maxZ = 6000; //摄像机拍摄的最远距离
camera.upperBetaLimit = 1.5; //beta方向上的旋转限制(防止看到模型底面)
camera.lowerRadiusLimit = 3; //相机距离拍摄目标的最小距离(防止穿插)
camera.setTarget(Vector3.Zero()); //设置拍摄目标
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);
this.highLightLayer.innerGlow = false;
}
let allMesh = mesh.getChildMeshes();
this.highLightLayer.addMesh(mesh, color);
for (let i = 0; i < allMesh.length; i++) {
let childMesh = allMesh[i];
if (childMesh instanceof Mesh) {
this.highLightLayer.addMesh(childMesh, color);
}
}
}
/**
*
* @param mesh
*/
removeFromHighLight(mesh: Mesh) {
if (this.highLightLayer == null) {
return;
}
let allMesh = mesh.getChildMeshes();
for (let i = 0; i < allMesh.length; i++) {
let childMesh = allMesh[i];
if (childMesh instanceof Mesh) {
this.highLightLayer.removeMesh(childMesh);
}
}
}
/**
*
*/
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.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();
} 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, { 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.JJQ:
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.SD:
modelData = plainToClass(MarkData_multiLine, modelData);
modelInfo = new ModelInfo_mark_multiLine(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.TPH:
case MarkType.SNH:
case MarkType.YWA:
case MarkType.YWB:
case MarkType.YWC:
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();
console.log(message);
console.log(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 {
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;
}
}

242
src/app/babylon/controller/serve-manager.ts

@ -0,0 +1,242 @@
import { HttpErrorResponse } from "@angular/common/http";
import { classToPlain } from "class-transformer";
import { BuildingBasicInfosService } from "src/app/service/babylon/building-basic-infos.service";
import { ObjectsService } from "src/app/service/babylon/objects.service";
import { InsitutionDataSimple } from "../model/data/institution/institution-data-simple";
import { AllMarkPlanData } from "../model/data/mark/mark-plan-data";
import { ModeManager } from "./mode-manager";
//服务器通信
export class ServeManager {
static ngAssetsPath = "assets/";//资源根目录
static instance: ServeManager = null;
postFilePath: string;//上传文件的相对路径
static Init(buildingBISrv: BuildingBasicInfosService, objectsSrv: ObjectsService) {
ServeManager.instance = new ServeManager(buildingBISrv, objectsSrv);
}
constructor(
private buildingBISrv: BuildingBasicInfosService,
private objectsSrv: ObjectsService
) {
//this.fileInput = document.getElementById("file");
}
//从服务器获取单位信息
getInstitutionData(key: string = 'test', onSuccess?: (key: string,
data: string
) => void, onError?: (key: string, error: any) => void) {
this.buildingBISrv.getBuildingBasicInfos(key)
.subscribe(data => {
if (onSuccess) {
onSuccess(key, data);
}
}, error => {
console.error("From serve" + key + "===" + error);
if (onError) {
onError(key, error);
}
})
}
//保存单位信息
saveInstitutionData(institutionData: any, key: string = 'test', onSuccess?: (key: string,
result: string
) => void, onError?: (key: string, error: string) => void) {
let data = classToPlain(institutionData);
console.log(data);
this.buildingBISrv.postBuildingBasicInfos(key, data)
.subscribe(data => {
ModeManager.log("保存单位成功:" + key);
if (onSuccess) {
onSuccess(key, data);
}
if (key != "InsList") {
//ThreeDimensionalHomeComponent.instance.openSnackBar("保存单位成功");
// alert("保存单位成功");
}
//暂时没有失败的回调 onError
})
}
//保存单位列表
saveInstitutionListData(institutionList: InsitutionDataSimple[], onSucess?: () => void) {
// console.log("======保存单位");
ServeManager.instance.saveInstitutionData(institutionList, "InsList", () => {
//alert("保存单位列表成功");
if (onSucess) {
onSucess();
}
})
}
//#region 态势标会
/**
*
* @param institutionID
* @param onSuccess
* @param onError
*/
getMarkData(institutionID: string,
onSuccess?: (institutionID: string, data: string) => void,
onError?: (institutionID: string, error: any) => void) {
this.buildingBISrv.getMarkData(institutionID)
.subscribe(data => {
ModeManager.log(data);
if (onSuccess) {
onSuccess(institutionID, data);
}
}, (error) => {
if (error instanceof HttpErrorResponse) {
if (error.status === 404) {
ModeManager.log("没有标绘数据,新建:" + error.error);
onSuccess(institutionID, null); //data 为null ,表示新建
}
else {
if (onError) {
onError(institutionID, error);
}
}
}
if (onError) {
onError(institutionID, error);
}
})
}
/**
*
*/
saveMarkData(allMarkPlanData: AllMarkPlanData,
onSuccess?: (key: string, result: string) => void,
onError?: (key: string, error: string) => void) {
if (allMarkPlanData == null) {
console.error("标绘信息为空,无法保存");
}
else {
let data = classToPlain(allMarkPlanData);
this.buildingBISrv.postMarkData(allMarkPlanData.institutionID, data)
.subscribe(data => {
ModeManager.log("保存标绘信息成功:" + allMarkPlanData.institutionID);
if (onSuccess) {
onSuccess(allMarkPlanData.institutionID, data);
}
// ThreeDimensionalHomeComponent.instance.openSnackBar("保存标绘信息成功");
// alert("保存标绘信息成功");
//暂时没有失败的回调 onError
})
}
}
//#endregion
//#region 文件上传
//队列性,批量上传
uploadFile(index: number, files: File[], resPath_out, onOneSuccess: (name: string, path: string, file: File) => void, onEnd: () => void) {
if (index < files.length) {
ServeManager.instance.openFileSelect(files[index], resPath_out, (name: string, path: string, file: File) => {
onOneSuccess(name, path, file);
this.uploadFile(index + 1, files, resPath_out, onOneSuccess, onEnd);
});
}
else {
onEnd();
}
}
//设置文件路径并上传
openFileSelect(file: File, extensionPath: string, onSuccess?: (name: string, path: string, file: File) => void) {
this.postFilePath = extensionPath;
this.onPostFileSuccess = onSuccess;
let fileSize = file.size || null //上传文件的总大小
let shardSize = 5 * 1024 * 1024 //5MB 超过5MB要分块上传
if (fileSize >= shardSize) // 超过5MB要分块上传
{
this.postFileByMul(file);
}
else //普通上传
{
this.postFile(file);
}
}
//上传成功
onPostFileSuccess?: (name: string, path: string, file: File) => void;
//上传文件
async postFile(file: File) {
await new Promise((resolve, reject) => {
ServeManager.instance.objectsSrv.postFile(ServeManager.ngAssetsPath + this.postFilePath, file).subscribe(data => {
let dataObj = data as any;
let fileName = dataObj.fileName;
let filePath: string = dataObj.objectName;
filePath = filePath.replace(fileName, "");
filePath = ObjectsService.baseUrl + filePath;
ServeManager.instance.onGetPostFileResult(fileName, filePath, file);
resolve('success')
});
})
}
/**
*
* @param data
* @param file
*/
onGetPostFileResult(fileName: string, filePath: string, file: File) {
if (ServeManager.instance.onPostFileSuccess) {
ServeManager.instance.onPostFileSuccess(fileName, filePath, file);
}
}
/**
*
* @param file
*/
postFileByMul(file: File) {
ServeManager.instance.objectsSrv.postFile_MultipartUpload(ServeManager.ngAssetsPath + this.postFilePath, file).then((value) => {
let dataObj = value as any;
ServeManager.instance.onGetPostFileResult(dataObj.fileName, dataObj.filePath, file);
});
}
//#endregion
}

164
src/app/babylon/controller/status/building-status.ts

@ -0,0 +1,164 @@
import { Observable, Observer } from "@babylonjs/core";
import { Game } from "../../game";
import { BuildingType, BuildingData } from "../../model/data/institution/building/building-data";
import { FacilityPosType, ModelData_facility } from "../../model/data/model-data/model-data-facility";
import { ModelEditData } from "../../model/data/model-data/model-edit-data";
import { BuildingInfo } from "../../model/info/building/building-info";
import { GizmoTool } from "../../tool/gizmo-tool";
import { BuildingUIItem } from "../../view/building-window/building-ui-item";
import { BuildingWindow } from "../../view/building-window/building-window";
import { FacilityWindow } from "../../view/facility-window/facility-window";
import { FacilityInfoInSceneWindow } from "../../view/facilityinfoinscene-window/facilityinfoinscene-window";
import { MarkWindow } from "../../view/mark-window/mark-window";
import { ToolbarWindow } from "../../view/toolbar-window/toobar-window";
import { DataManager, ModelChangeType } from "../data-manager";
import { EventManager } from "../event-manager/event-manager";
import { Event_ChangeFacility } from "../event-manager/events/event-change-facility";
import { InfoManager } from "../info-manager";
import { ModeManager, ModeType } from "../mode-manager";
import { SceneManager } from "../scene-manager";
import { UIManager } from "../ui-manager";
import { StatusBase, StatusManager } from "./status-manager";
//建筑物外观模式
export class BuildingStatus extends StatusBase {
buildingWindow: BuildingWindow;
currentBuildingInfo: BuildingInfo; //当前的建筑
onChangeFacilityObserver: Observer<Event_ChangeFacility>;
static changeStatusFromUI: boolean = false;//因为ui而切换
static startEnterObservable: Observable<BuildingUIItem> = new Observable<BuildingUIItem>();//开始切入
static enterSuccessObservable: Observable<BuildingUIItem> = new Observable<BuildingUIItem>();//进入成功的事件
//#region
/**
*
* @param key key
* @param name
* @param buildingType
*/
createOneBuildingInData(key: string, name: string, buildingType: BuildingType): BuildingData {
return DataManager.createBuilding(key, name, buildingType);
}
//#endregion
//#region 生命周期
//初始化
onCreate() {
super.onCreate();
// this.enterSuccessObservable = new Observable<BuildingUIItem>();
GizmoTool.init(SceneManager.Instance.scene, UIManager.Instance.uiRoot, SceneManager.Instance.defaultCamera);
InfoManager.init();
//UIManager.open<InputHintWindow>(InputHintWindow);
UIManager.open<ToolbarWindow>(ToolbarWindow);
}
//进入状态
onEnter() {
super.onEnter();
Game.instance.engine.resize();
//首次进入
if (this.buildingWindow == null) {
SceneManager.s_facilityWindow = UIManager.open<FacilityWindow>(FacilityWindow);
if (ModeManager.currentMode == ModeType.Look) {
//此处应改为由前端调用, 退出编辑状态时应调用hide
// SceneManager.s_markWindow = MarkWindow.openWindow();
}
this.buildingWindow = UIManager.open<BuildingWindow>(BuildingWindow);
SceneManager.s_facilityInfoInSceneWindow = UIManager.open<FacilityInfoInSceneWindow>(FacilityInfoInSceneWindow);
}
else { //从室内返回
UIManager.show<BuildingWindow>(this.buildingWindow);
if (this.buildingWindow.currentBuidngItem != null) {
this.buildingWindow.currentBuidngItem.select();
BuildingStatus.startEnterObservable.notifyObservers(this.buildingWindow.currentBuidngItem);
BuildingStatus.enterSuccessObservable.notifyObservers(this.buildingWindow.currentBuidngItem)
if (MarkWindow.s_cameraData == null) {
this.buildingWindow.currentBuidngItem.lookAt();
}
else {
MarkWindow.s_cameraData.setDataToCamera(SceneManager.Instance.defaultCamera);
MarkWindow.s_cameraData = null;
}
FacilityInfoInSceneWindow.instance.createAllFacilities(this.buildingWindow.currentBuidngItem.buildingInfo.ModelInfo.facilityInfos);
if (ModeManager.currentMode == ModeType.Look) {
FacilityInfoInSceneWindow.instance.showFacilityByType(null, false);
}
}
}
SceneManager.s_facilityWindow.updateAllFacilities(FacilityPosType.Outdoor);
let instance = this;
this.onChangeFacilityObserver = EventManager.addListener<Event_ChangeFacility>(Event_ChangeFacility, ((eventInfo) => {
instance.onChangeFacility(eventInfo);
}));
SceneManager.Instance.sunLight.intensity = 3;
}
//退出状态
onExit() {
UIManager.hide<BuildingWindow>(this.buildingWindow);
// console.log("==退出buildingStatus==");
EventManager.removeListener(Event_ChangeFacility, this.onChangeFacilityObserver);
super.onExit();
}
//#endregion
//改变当前选中的建筑
changeCurrentBuilding(buildingInfo: BuildingInfo) {
if (buildingInfo == this.currentBuildingInfo) {
return;
}
// console.log("改变当前建筑" + buildingInfo.buildingData.normalData.key);
//FacilityInfoInSceneWindow.instance.clearFacilityInfoUIItemes();
if (this.currentBuildingInfo != null) {
// this.buildingWindow.clearFacilityInfos(this.currentBuildingInfo);
//隐藏
this.buildingWindow.showFacilityInfosIcon(this.currentBuildingInfo, false);
}
this.currentBuildingInfo = buildingInfo;
FacilityInfoInSceneWindow.instance.createAllFacilities(buildingInfo.ModelInfo.facilityInfos);
if (this.currentBuildingInfo.ModelInfo.facilityInfos != null && ModeManager.currentMode == ModeType.Edit) {
//判断已经有了就不创建了
// InfoManager.createFacilityInfos(buildingInfo.buildingData.outdoorData, buildingInfo);
//显示
this.buildingWindow.showFacilityInfosIcon(this.currentBuildingInfo, true);
}
}
//模型变化
onChangeFacility(eventInfo: Event_ChangeFacility) {
if (eventInfo.modeleData instanceof ModelData_facility) {
let modelEditData: ModelEditData;
if (StatusManager.s_currentStatus instanceof BuildingStatus) {
modelEditData = this.currentBuildingInfo.buildingData.outdoorData;
}
if (eventInfo.modelChangeType == ModelChangeType.Add) {
modelEditData.addFacility(eventInfo.modeleData);
// console.log("添加设备数据" + eventInfo.modeleData.key);
}
else if (eventInfo.modelChangeType == ModelChangeType.Remove) {
modelEditData.removeFacility(eventInfo.modeleData);
// console.log("移除设备数据" + eventInfo.modeleData.key);
}
}
}
}

127
src/app/babylon/controller/status/indoor-status.ts

@ -0,0 +1,127 @@
import { Observable, Observer } from "@babylonjs/core";
import { BuildingData_Normal } from "../../model/data/institution/building/building-data";
import { ModelData } from "../../model/data/model-data/model-data";
import { FacilityPosType, ModelData_facility } from "../../model/data/model-data/model-data-facility";
import { ModelEditData } from "../../model/data/model-data/model-edit-data";
import { BuildingInfo_Normal } from "../../model/info/building/building-info-normal";
import { GizmoTool } from "../../tool/gizmo-tool";
import { IndoorFloorUIItem } from "../../view/indoor-window/indoor-floorui-item";
import { IndoorWindow } from "../../view/indoor-window/indoor-window";
import { ModelChangeType } from "../data-manager";
import { EventManager } from "../event-manager/event-manager";
import { Event_ChangeFacility } from "../event-manager/events/event-change-facility";
import { SceneManager } from "../scene-manager";
import { UIManager } from "../ui-manager";
import { StatusBase, StatusManager } from "./status-manager";
//室内模式
export class IndoorStatus extends StatusBase {
buildingInfo: BuildingInfo_Normal;
indoorWindow: IndoorWindow;
//indoorInfos:BuildingInfo[];//室内信息(运行时)
indoorData: BuildingData_Normal; //室内信息(纯数据)
onChangeFacilityObserver: Observer<Event_ChangeFacility>;
static changeStatusFromUI: boolean = false;//因为ui而切换
static startEnterObservable: Observable<IndoorFloorUIItem> = new Observable<IndoorFloorUIItem>();//开始切入
static enterSuccessObservable: Observable<IndoorFloorUIItem> = new Observable<IndoorFloorUIItem>();//进入成功的事件
//初始化
onCreate() {
super.onCreate();
// this.enterSuccessObservable = new Observable<IndoorFloorUIItem>();
}
//进入状态
onEnter() {
super.onEnter();
if (this.indoorWindow == null) {
this.indoorWindow = UIManager.open<IndoorWindow>(IndoorWindow);
} else {
UIManager.show<IndoorWindow>(this.indoorWindow);
}
let instance = this;
this.onChangeFacilityObserver = EventManager.addListener<Event_ChangeFacility>(Event_ChangeFacility, (eventInfo) => {
instance.onChangeFacility(eventInfo);
})
GizmoTool.onPickMeshInfoObservable.notifyObservers(null);//取消之前的选中
SceneManager.s_facilityInfoInSceneWindow.clearFacilityInfoUIItemes();//先清空
SceneManager.s_facilityWindow.updateAllFacilities(FacilityPosType.Indoor);
SceneManager.Instance.sunLight.intensity = 1;
}
//退出状态
onExit() {
EventManager.removeListener(Event_ChangeFacility, this.onChangeFacilityObserver);
UIManager.hide<IndoorWindow>(this.indoorWindow);
this.clearIndoorInfo();
super.onExit();
}
init(buildingInfo: BuildingInfo_Normal, key: string) {
this.buildingInfo = buildingInfo;
this.indoorData = buildingInfo.buildingData as BuildingData_Normal;
this.indoorWindow.initAllFloor(this.indoorData.indoorsData, key);
}
//清空室内运行时信息
clearIndoorInfo() {
console.log('清空室内');
this.indoorWindow.clearAllFloorUIItem();
if (this.indoorWindow.currentFloorUIItem != null &&
this.indoorWindow.currentFloorUIItem.buildingInfo != null) {
GizmoTool.leaveTheGizmoAim(this.indoorWindow.currentFloorUIItem.buildingInfo.ModelInfo);
}
this.indoorWindow.currentFloorUIItem = null;
}
//模型Data数据变化
onChangeFacility(eventInfo: Event_ChangeFacility) {
if (eventInfo.modeleData instanceof ModelData_facility) {
let modelEditData: ModelEditData;
modelEditData = (StatusManager.s_currentStatus as IndoorStatus)
.indoorWindow.currentFloorUIItem.modelEditData;
if (eventInfo.modelChangeType == ModelChangeType.Add) {
modelEditData.addFacility(eventInfo.modeleData);
} else if (eventInfo.modelChangeType == ModelChangeType.Remove) {
modelEditData.removeFacility(eventInfo.modeleData);
}
}
}
//创建新的室内数据
newIndoorData(key: string, name: string, isRefugeFloor: boolean): ModelEditData {
let newIndoorData = new ModelEditData();
newIndoorData.modelData = new ModelData();
newIndoorData.modelData.key = key;
newIndoorData.modelData.name = name;
newIndoorData.isRefugeFloor = isRefugeFloor;
return newIndoorData;
}
//将新的室内添加到当前建筑中
addNewIndoorToBuilding(newIndoorData: ModelEditData) {
let buildingData = this.buildingInfo.buildingData as BuildingData_Normal;
if (buildingData.indoorsData == null) {
buildingData.indoorsData = [];
}
newIndoorData.index = buildingData.getNextIndoorIndex();
//设置index为最大+1
buildingData.indoorsData.push(newIndoorData);
}
}

219
src/app/babylon/controller/status/login-status.ts

@ -0,0 +1,219 @@
import { HttpErrorResponse } from "@angular/common/http";
import { plainToClass } from "class-transformer";
import { InstitutionData, NormalData } from "../../model/data/institution/institution-data";
import { InsitutionDataSimple } from "../../model/data/institution/institution-data-simple";
import { InstitutionCreateWindow } from "../../view/institution/institution-create-window";
import { InstitutionSelectWindow } from "../../view/institution/institution-select-window";
import { TopbarWindow } from "../../view/topbar-window/topbar-window";
import { DataManager } from "../data-manager";
import { SceneManager } from "../scene-manager";
import { ServeManager } from "../serve-manager";
import { UIManager } from "../ui-manager";
import { MainStatus } from "./main-status";
import { StatusBase, StatusManager } from "./status-manager";
export class LoginSatus extends StatusBase {
institutionSelectWindow: InstitutionSelectWindow;
institutionCreateWindow: InstitutionCreateWindow;
institutionList: InsitutionDataSimple[];//单位简易信息列表
//#region 前端对接
/**
*
* @param insData
*/
createInsitution(key: string, name: string, onSuccess?: (insDataSimple: InsitutionDataSimple) => void) {
if (key == null) {
console.error("创建单位key为null");
return;
}
let insData = new InstitutionData();
insData.normalData = new NormalData(key, name);
this.saveNewIns(this, insData, key, onSuccess);
}
//#endregion
//#region 外部方法
/**
*
* @param onSuccess
*/
getInstitutionListFromServe(onSuccess?: (result: InsitutionDataSimple[], data?: any) => void, onFail?: (error: string) => void) {
let debugList: any | InsitutionDataSimple[] = [];
// let testIns1 = new InsitutionDataSimple();
// testIns1.key = "test";
// testIns1.name = "测试单位1";
// debugList.push(testIns1);
ServeManager.instance.getInstitutionData("InsList", (key, data) => {
debugList = plainToClass(InsitutionDataSimple, data);
this.institutionList = debugList;
if (onSuccess) {
onSuccess(debugList, data);
}
}, (key: string, error: any) => {
console.error("获取单位列表失败");
console.log(error);
if (error instanceof HttpErrorResponse && error.status === 404) {
//数据库没有数据,新建
this.institutionList = [];
if (onSuccess) {
onSuccess(this.institutionList, this.institutionList);
}
console.log("新建数据列表");
}
else {
if (onFail) {
onFail(error);
}
}
return;
})
}
/**
* ,
* @param simpleData
*/
onSelectInsSuccess(simpleData: InsitutionDataSimple) {
let status: LoginSatus = StatusManager.getStatus<LoginSatus>(LoginSatus);
if (status.institutionSelectWindow != null) {
UIManager.close(status.institutionSelectWindow);
status.institutionSelectWindow = null;
}
DataManager.init(simpleData, (resultkey) => {
StatusManager.enterStatus<MainStatus>(MainStatus);
});
}
//#endregion
//#region 生命周期
//初始化
onCreate() {
super.onCreate();
}
//进入状态
onEnter() {
super.onEnter();
console.log("进入 logins");
//UIManager.open<TopbarWindow>(TopbarWindow);
// this.openSelectWindow();//可以开启选择、新建单位
}
//退出状态
onExit() {
super.onEnter();
}
//开启选择界面
openSelectWindow() {
console.log("=======开启选择界面");
this.institutionSelectWindow = UIManager.open<InstitutionSelectWindow>(InstitutionSelectWindow);
console.log(this.institutionSelectWindow);
let status = this;
this.institutionSelectWindow.getInsList(status.onSelectInsSuccess);
}
//关闭选择界面
closeSelectWindow() {
if (this.institutionSelectWindow != null) {
UIManager.close(this.institutionSelectWindow);
this.institutionSelectWindow = null;
}
}
//新建完成
onCreateInsSuccess(insData: InsitutionDataSimple) {
this.closeCreateWindow();
let isOverWrite = false;
for (let i = 0; i < this.institutionList.length; i++) {
if (this.institutionList[i].key == insData.key) {
this.institutionList[i].name = insData.name;
isOverWrite = true;
break;
}
}
if (!isOverWrite) {
this.institutionList.push(insData);
}
let status = this;
ServeManager.instance.saveInstitutionListData(this.institutionList, () => {
//进入新单位
status.onSelectInsSuccess(insData);
});
}
//#endregion
//#region babylonGUI 新建单位
//开启新建界面
onNewIns() {
this.closeSelectWindow();
this.institutionCreateWindow = UIManager.open<InstitutionCreateWindow>(InstitutionCreateWindow);
let status = this;
this.institutionCreateWindow.startCreate();
}
//关闭创建界面
closeCreateWindow() {
if (this.institutionCreateWindow != null) {
UIManager.close(this.institutionCreateWindow);
}
this.institutionCreateWindow = null;
}
//保存新单位信息至服务器
saveNewIns(status: LoginSatus, insData: InstitutionData, key: string, onSuccess?: (insDataSimple: InsitutionDataSimple) => void) {
ServeManager.instance.saveInstitutionData(insData, key, (key, result) => {
console.log("在服务器新建单位" + key);
let insDataSimple = new InsitutionDataSimple();
insDataSimple.key = key;
insDataSimple.name = insData.normalData.name;
status.onCreateInsSuccess(insDataSimple);
if (onSuccess != null) {
onSuccess(insDataSimple);
}
});
}
//#endregion
}

28
src/app/babylon/controller/status/main-status.ts

@ -0,0 +1,28 @@
import { DataManager } from "../data-manager";
import { BuildingStatus } from "./building-status";
import { StatusBase, StatusManager } from "./status-manager";
//主状态
export class MainStatus extends StatusBase {
//初始化
onCreate() {
super.onCreate();
}
//进入状态
onEnter() {
super.onEnter();
if (DataManager.institutionData == null) {
//新建单位信息、开启上传建筑模型的界面
} else {
//已有信息,进入建筑物模式
StatusManager.enterStatus<BuildingStatus>(BuildingStatus);
}
}
//退出状态
onExit() {
super.onExit();
}
}

74
src/app/babylon/controller/status/status-manager.ts

@ -0,0 +1,74 @@
//状态管理
export class StatusManager {
//所有已经实例化的status
static s_allStatus: StatusBase[] = [];
//当前状态
static s_currentStatus: StatusBase;
//获取已经有的目标类型status
static getStatus<T extends StatusBase>(c: { new(): T; }): T {
if (StatusManager.s_allStatus == null) {
return null;
}
for (let i = 0; i < StatusManager.s_allStatus.length; i++) {
if ((StatusManager.s_allStatus[i]) instanceof c) {
let result = <T>StatusManager.s_allStatus[i];
return result;
}
}
return null;
}
//创建status
static createStatus<T extends StatusBase>(c: { new(): T }): T {
let newStatus = StatusManager.getStatus<T>(c);
if (newStatus == null) {
newStatus = new c();
newStatus.onCreate();
StatusManager.s_allStatus.push(newStatus);
}
return newStatus;
}
//进入某状态
static enterStatus<T extends StatusBase>(c: { new(): T }): T {
if (StatusManager.s_currentStatus != null) {
// console.log("退出status");
// console.log(StatusManager.s_currentStatus);
StatusManager.s_currentStatus.onExit();
}
let newStatus = <T>StatusManager.getStatus<T>(c);
if (newStatus == null) {
newStatus = new c();
newStatus.onCreate();
StatusManager.s_allStatus.push(newStatus);
}
// console.log("进入status");
// console.log(newStatus);
StatusManager.s_currentStatus = newStatus;
newStatus.onEnter();
return newStatus;
}
}
//状态基类
export class StatusBase {
//初始化
onCreate() {
}
//进入状态
onEnter() {
}
//退出状态
onExit() {
}
}

43
src/app/babylon/controller/ui-manager.ts

@ -0,0 +1,43 @@
import { AdvancedDynamicTexture } from "@babylonjs/gui";
import { UIBase } from "../view/window-base/ui-base";
export class UIManager {
public static _instance: UIManager;
static get Instance(): UIManager {
if (UIManager._instance == null) {
UIManager._instance = new UIManager();
}
return UIManager._instance;
}
public uiRoot: AdvancedDynamicTexture;
public init() {
this.uiRoot = AdvancedDynamicTexture.CreateFullscreenUI("UIRoot", undefined);//UtilityLayerRenderer.DefaultUtilityLayer.utilityLayerScene
}
static open<T extends UIBase>(c: { new(): T }): T {
let ui: T = new c();
ui.onInit();
ui.onOpen();
return ui;
}
static close<T extends UIBase>(ui: T) {
ui.onClose();
ui.root.dispose();
}
static hide<T extends UIBase>(ui: T) {
ui.onHide();
}
static show<T extends UIBase>(ui: T) {
ui.onShow();
}
}

58
src/app/babylon/game.ts

@ -0,0 +1,58 @@
import { Database, Engine, RenderingManager, Scene } from "@babylonjs/core";
import { AdvancedDynamicTexture } from "@babylonjs/gui";
import { SceneManager } from "./controller/scene-manager";
import { LoginSatus } from "./controller/status/login-status";
import { StatusManager } from "./controller/status/status-manager";
import { UIManager } from "./controller/ui-manager";
export class Game {
public canvas: HTMLCanvasElement;
public engine: Engine;
public scene: Scene;
public uiRoot: AdvancedDynamicTexture;
static instance: Game;
//初始化引擎和画布
public init(canvas: HTMLCanvasElement) {
Game.instance = this;
this.canvas = canvas;
this.engine = new Engine(canvas, null, { stencil: true });
Database.IDBStorageEnabled = true;//开启本地缓存
this.scene = new Scene(this.engine);
this.scene.useRightHandedSystem = true;//使用右手坐标系
RenderingManager.MIN_RENDERINGGROUPS = -1;//最小渲染序列
this.createScene();
let scene = this.scene;
// canvas.translate = true; //用于设置背景透明
// scene.autoClear = true;
UIManager.Instance.init();
StatusManager.enterStatus<LoginSatus>(LoginSatus);
//最后,将场景渲染出来 (重要,不可缺少)
this.engine.runRenderLoop(function () {
scene.render();
})
// 监听浏览器改变大小的事件,通过调用engine.resize()来自适应窗口大小
window.addEventListener("resize", function () {
Game.instance.engine.resize();
});
}
//创建初始场景
private createScene() {
let sceneManager = SceneManager.init(this.scene, this.canvas, this.engine);
sceneManager.initArcRotateCamera();
sceneManager.initLight();
sceneManager.updateSceneBG();
sceneManager.initSceneEvent();
}
}

37
src/app/babylon/model/data/camera-data.ts

@ -0,0 +1,37 @@
import { ArcRotateCamera, Vector3 } from "@babylonjs/core";
import { Type } from "class-transformer";
/**
*
*/
export class ArcRotateCameraData {
@Type(() => Vector3)
target: Vector3;
radius: number;
alpha: number;
beta: number;
/**
*
* @param camera
*/
setDataToCamera(camera: ArcRotateCamera) {
camera._scene.stopAnimation(camera);
camera.target = this.target;
camera.radius = this.radius;
camera.alpha = this.alpha;
camera.beta = this.beta;
}
/**
*
* @param camera
*/
getDataFromCamera(camera: ArcRotateCamera) {
this.target = camera.target;
this.radius = camera.radius;
this.alpha = camera.alpha;
this.beta = camera.beta;
}
}

70
src/app/babylon/model/data/institution/building/building-data.ts

@ -0,0 +1,70 @@
import { Type } from "class-transformer";
import { ModelEditData } from "../../model-data/model-edit-data";
import { NormalData } from "../institution-data";
//基础建筑信息
export class BuildingData {
// belongToInstitution: InstitutionData
@Type(() => NormalData)
normalData: NormalData; //常规信息
buildingIDFromPlatform: string;//关联自预案管理平台中的建筑id
describe: string; //描述
buildingType: BuildingType; //建筑类型
@Type(() => ModelEditData)
outdoorData: ModelEditData; //外观建筑编辑信息
constructor() {
// this.belongToInstitution = belongToInstitution;
this.normalData = new NormalData();
this.outdoorData = new ModelEditData();
}
}
//普通大楼信息
export class BuildingData_Normal extends BuildingData {
@Type(() => ModelEditData)
indoorsData: ModelEditData[];//室内编辑信息
constructor() {
super();
this.buildingType = BuildingType.Normal;
}
/**
* index序号
*/
getNextIndoorIndex() {
let result = -1;
for (let i = 0; i < this.indoorsData.length; i++) {
if (this.indoorsData[i].index > result) {
result = this.indoorsData[i].index;
}
}
result++;
return result;
}
}
//环境信息
export class BuildingData_Environment extends BuildingData {
constructor() {
super();
this.buildingType = BuildingType.Environment;
}
}
//化工厂信息
export class BuildingData_ChemicalPlant extends BuildingData {
constructor() {
super();
this.buildingType = BuildingType.ChemicalPlant;
}
}
//建筑类型
export enum BuildingType {
Normal = "normal", //普通大楼
Environment = "environment", //环境
ChemicalPlant = "chemicalPlant", //化工厂
}

78
src/app/babylon/model/data/institution/facility/all-facility-data.ts

@ -0,0 +1,78 @@
import { Type } from 'class-transformer';
import { ConfigManager } from 'src/assets/babylon/controller/config-manager';
import { DataManager } from 'src/assets/babylon/controller/data-manager';
import { FacilityPosType, FacilityType, ModelData_facility } from '../../model-data/model-data-facility';
import { TransformData } from '../../transform-data';
//所有设备数据
export class AllFacilityData {
@Type(() => ModelData_facility)
indoor: ModelData_facility[] = []; //室内
@Type(() => ModelData_facility)
outdoor: ModelData_facility[] = []; //室外
/**捏造所有消防设施的源数据 */
static CreateAllFacilityData(): AllFacilityData {
let result = new AllFacilityData();
AllFacilityData.newFacilityData(FacilityType.AQCK, FacilityPosType.Outdoor, result);
AllFacilityData.newFacilityData(FacilityType.DSXHS, FacilityPosType.Outdoor, result);
AllFacilityData.newFacilityData(FacilityType.DXXHS, FacilityPosType.Outdoor, result);
AllFacilityData.newFacilityData(FacilityType.SZDSXHS, FacilityPosType.Outdoor, result);
AllFacilityData.newFacilityData(FacilityType.SZDXXHS, FacilityPosType.Outdoor, result);
AllFacilityData.newFacilityData(FacilityType.DSSBJHQ, FacilityPosType.Outdoor, result);
AllFacilityData.newFacilityData(FacilityType.DXSBJHQ, FacilityPosType.Outdoor, result);
AllFacilityData.newFacilityData(FacilityType.QBSBJHQ, FacilityPosType.Outdoor, result);
AllFacilityData.newFacilityData(FacilityType.DGNSBJHQ, FacilityPosType.Outdoor, result);
AllFacilityData.newFacilityData(FacilityType.GD, FacilityPosType.Outdoor, result, false);
AllFacilityData.newFacilityData(FacilityType.PL, FacilityPosType.Outdoor, result);
AllFacilityData.newFacilityData(FacilityType.JTQ, FacilityPosType.Outdoor, result, false);
AllFacilityData.newFacilityData(FacilityType.JJQ, FacilityPosType.Outdoor, result, false);
AllFacilityData.newFacilityData(FacilityType.TPBZ, FacilityPosType.Outdoor, result, true);
AllFacilityData.newFacilityData(FacilityType.XKS, FacilityPosType.Indoor, result, false);
AllFacilityData.newFacilityData(FacilityType.BF, FacilityPosType.Indoor, result, false);
AllFacilityData.newFacilityData(FacilityType.SX, FacilityPosType.Indoor, result, false);
AllFacilityData.newFacilityData(FacilityType.LSXFB, FacilityPosType.Indoor, result);
AllFacilityData.newFacilityData(FacilityType.WSXFB, FacilityPosType.Indoor, result);
AllFacilityData.newFacilityData(FacilityType.CYXFB, FacilityPosType.Indoor, result);
AllFacilityData.newFacilityData(FacilityType.FHFQ, FacilityPosType.Indoor, result, false);
AllFacilityData.newFacilityData(FacilityType.SNXHS, FacilityPosType.Indoor, result);
AllFacilityData.newFacilityData(FacilityType.FHM, FacilityPosType.Indoor, result, false);
AllFacilityData.newFacilityData(FacilityType.FHJL, FacilityPosType.Indoor, result, false);
AllFacilityData.newFacilityData(FacilityType.SSLT, FacilityPosType.Indoor, result, false);
AllFacilityData.newFacilityData(FacilityType.XFDT, FacilityPosType.Indoor, result, false);
AllFacilityData.newFacilityData(FacilityType.PTDT, FacilityPosType.Indoor, result, false);
AllFacilityData.newFacilityData(FacilityType.HT, FacilityPosType.Indoor, result, false);
AllFacilityData.newFacilityData(FacilityType.WXY, FacilityPosType.Public, result);
AllFacilityData.newFacilityData(FacilityType.ZDQY, FacilityPosType.Public, result);
AllFacilityData.newFacilityData(FacilityType.DWBZ, FacilityPosType.Public, result);
return result;
}
//新建设备信息
static newFacilityData(type: FacilityType, posType: FacilityPosType, allFacilityData: AllFacilityData, isModel: boolean = true): ModelData_facility {
let name = ConfigManager.getFacilityTypeName(type);
let result = new ModelData_facility(type.toString(), type, name, DataManager.getResName_facility(type) + ".gltf", new TransformData(), posType, isModel);
switch (posType) {
case FacilityPosType.Outdoor:
allFacilityData.outdoor.push(result);
break;
case FacilityPosType.Indoor:
allFacilityData.indoor.push(result);
break;
case FacilityPosType.Public:
allFacilityData.outdoor.push(result);
allFacilityData.indoor.push(result);
break;
}
return result;
}
}

30
src/app/babylon/model/data/institution/facility/property-data/base/property-data-base-img.ts

@ -0,0 +1,30 @@
import { FacilityType } from "../../../../model-data/model-data-facility";
import { PropertyData_Base } from "../property-data-base";
/**
*
*/
export class PropertyData_Base_IMG extends PropertyData_Base {
img: string;//图片
is360: boolean;//全景图片
pos: string;//位置
info: string;//详情
constructor(key: string, img: string, pos: string, info: string, type: FacilityType) {
super(key, type);
this.img = img;
this.pos = pos;
this.info = info;
this.is360 = false;
}
clone(key: string) {
let result = new PropertyData_Base_IMG(key, this.img, this.pos, this.info, this.facilityType);
result.is360 = this.is360;
return result;
}
}

27
src/app/babylon/model/data/institution/facility/property-data/base/property-data-base-lt.ts

@ -0,0 +1,27 @@
import { FacilityType } from "../../../../model-data/model-data-facility";
import { PropertyData_Base } from "../property-data-base";
/**
*
*/
export class PropertyData_Base_LT extends PropertyData_Base {
number: string = "";//编号
channel: string = "";//通往层数
constructor(key: string, number: string, channel: string, type: FacilityType) {
super(key, type);
this.number = number;
this.channel = channel;
}
clone(key: string) {
let result = new PropertyData_Base_LT(key, this.number, this.channel, this.facilityType);
return result;
}
}

31
src/app/babylon/model/data/institution/facility/property-data/base/property-data-base-sbjhq.ts

@ -0,0 +1,31 @@
import { FacilityType } from "../../../../model-data/model-data-facility";
import { PropertyData_Base } from "../property-data-base";
/**
*
*/
export class PropertyData_Base_SBJHQ extends PropertyData_Base {
number: string;//编号
type: string;//类型(特殊字段,关系UI分类展示)
range: string;//供给范围
img: string;//图片
is360: boolean;//是否是全景图片
constructor(key: string, number: string, type: string, range: string, img: string, facilityType: FacilityType) {
super(key, facilityType);
this.number = number;
this.type = type;
this.range = range;
this.img = img;
this.is360 = false;
}
clone(key: string) {
let result = new PropertyData_Base_SBJHQ(key, this.number, this.type, this.range, this.img, this.facilityType);
result.is360 = this.is360;
return result;
}
}

34
src/app/babylon/model/data/institution/facility/property-data/base/property-data-base-xfb.ts

@ -0,0 +1,34 @@
import { FacilityType } from "../../../../model-data/model-data-facility";
import { PropertyData_Base } from "../property-data-base";
/**
*
*/
export class PropertyData_Base_XFB extends PropertyData_Base {
type: string;//类型
number: string;//型号
power: string;//功率
lift: string;//扬程
flow: string;//流量
pressure: string;//压力
constructor(key: string, type: string, number: string, power: string, lift: string, flow: string, pressure: string, facilityType: FacilityType) {
super(key, facilityType);
this.type = type;
this.power = power;
this.number = number;
this.lift = lift;
this.flow = flow;
this.pressure = pressure;
}
clone(key: string) {
let result = new PropertyData_Base_XFB(key, this.type, this.number, this.power, this.lift, this.flow, this.pressure, this.facilityType);
return result;
}
}

32
src/app/babylon/model/data/institution/facility/property-data/base/property-data-base-xhs.ts

@ -0,0 +1,32 @@
import { FacilityType } from "../../../../model-data/model-data-facility";
import { PropertyData_Base } from "../property-data-base";
/**
*
*/
export class PropertyData_Base_XHS extends PropertyData_Base {
img: string;//图片
is360: boolean;//全景图片
number: string;//编号
caliber: string;//管径
screw: string;//牙口
constructor(key: string, img: string, is360: boolean, number: string, caliber: string, screw: string, type: FacilityType) {
super(key, type);
this.img = img;
this.is360 = is360;
this.number = number;
this.caliber = caliber;
this.screw = screw;
}
clone(key: string) {
let result = new PropertyData_Base_XHS(key, this.img, this.is360, this.number, this.caliber, this.screw, this.facilityType);
return result;
}
}

27
src/app/babylon/model/data/institution/facility/property-data/indoor/property-data-dwbz.ts

@ -0,0 +1,27 @@
import { FacilityType } from "../../../../model-data/model-data-facility";
import { PropertyData_Base } from "../property-data-base";
/**
*
*/
export class PropertyData_DWBZ extends PropertyData_Base {
pos: string = "";//位置
info: string = "";//详情
constructor(key: string, pos: string, info: string) {
super(key, FacilityType.DWBZ);
this.pos = pos;
this.info = info;
}
clone(key: string) {
let result = new PropertyData_DWBZ(key, this.pos, this.info);
return result;
}
}

31
src/app/babylon/model/data/institution/facility/property-data/indoor/property-data-fhfq.ts

@ -0,0 +1,31 @@
import { Color3, Color4 } from "@babylonjs/core";
import { Type } from "class-transformer";
import { FacilityType } from "../../../../model-data/model-data-facility";
import { PropertyData_Base } from "../property-data-base";
/**
*
*/
export class PropertyData_FHFQ extends PropertyData_Base {
name: string = "";//名称
area: string = "";//面积
@Type(() => Color3)
color: Color3 = Color3.Red();//颜色
constructor(key: string, name: string, area: string, color: Color3 = Color3.Red()) {
super(key, FacilityType.FHFQ);
this.name = name;
this.area = area;
this.color = color;
}
clone(key: string) {
let result = new PropertyData_FHFQ(key, this.name, this.area, this.color);
return result;
}
}

26
src/app/babylon/model/data/institution/facility/property-data/indoor/property-data-sslt.ts

@ -0,0 +1,26 @@
import { FacilityType } from "../../../../model-data/model-data-facility";
import { PropertyData_Base_LT } from "../base/property-data-base-lt";
import { PropertyData_Base } from "../property-data-base";
/**
*
*/
export class PropertyData_SSLT extends PropertyData_Base_LT {
width: string = "";//宽度
constructor(key: string, number: string, channel: string, width: string) {
super(key, number, channel, FacilityType.SSLT);
this.width = width;
}
clone(key: string) {
let result = new PropertyData_SSLT(key, this.number, this.channel, this.width);
return result;
}
}

24
src/app/babylon/model/data/institution/facility/property-data/indoor/property-data-xfdt.ts

@ -0,0 +1,24 @@
import { FacilityType } from "../../../../model-data/model-data-facility";
import { PropertyData_Base_LT } from "../base/property-data-base-lt";
import { PropertyData_Base } from "../property-data-base";
/**
*
*/
export class PropertyData_XFDT extends PropertyData_Base_LT {
weight: string = "";//载重
constructor(key: string, number: string, channel: string, weight: string) {
super(key, number, channel, FacilityType.XFDT);
this.weight = weight;
}
clone(key: string) {
let result = new PropertyData_XFDT(key, this.number, this.channel, this.weight);
return result;
}
}

42
src/app/babylon/model/data/institution/facility/property-data/indoor/property-data-zdqy.ts

@ -0,0 +1,42 @@
import { FacilityType } from "../../../../model-data/model-data-facility";
import { PropertyData_Base } from "../property-data-base";
/**
*
*/
export class PropertyData_ZDQY extends PropertyData_Base {
name: string = "";//名称
pos: string = "";//所在位置
construction: string = "";//建筑结构
character: string = "";//使用性质
danger: string = "";//主要危险性
imgs: string[] = [];//图片
constructor(key: string, name: string, pos: string, construction: string, character: string, danger: string, imgs: string[]) {
super(key, FacilityType.ZDQY);
this.name = name;
this.pos = pos;
this.construction = construction;
this.character = character;
this.danger = danger;
this.imgs = imgs;
}
clone(key: string) {
let newImgs: string[] = [];
for (let i = 0; i < this.imgs.length; i++) {
newImgs.push(this.imgs[i]);
}
let result = new PropertyData_ZDQY(key, this.name, this.pos, this.construction, this.character, this.danger, newImgs);
return result;
}
}

31
src/app/babylon/model/data/institution/facility/property-data/outdoor/property-data-aqck.ts

@ -0,0 +1,31 @@
import { FacilityType } from "../../../../model-data/model-data-facility";
import { PropertyData_Base } from "../property-data-base";
/**
*
*/
export class PropertyData_AQCK extends PropertyData_Base {
img: string = "";
is360: boolean;//全景图片
name: string = "安全出口";
width: string = "";
constructor(key: string, img: string, is360: boolean, name: string, width: string) {
super(key, FacilityType.AQCK);
this.img = img;
this.is360 = is360;
this.name = name;
this.width = width;
}
clone(key: string) {
let result = new PropertyData_AQCK(key, this.img, this.is360, "安全出口", "1");
return result;
}
}

26
src/app/babylon/model/data/institution/facility/property-data/outdoor/property-data-gd.ts

@ -0,0 +1,26 @@
import { FacilityType } from "../../../../model-data/model-data-facility";
import { PropertyData_Base } from "../property-data-base";
/**
*
*/
export class PropertyData_GD extends PropertyData_Base {
info: string = "";
constructor(key: string, info: string) {
super(key, FacilityType.GD);
this.info = info;
}
clone(key: string) {
let result = new PropertyData_GD(key, this.info);
return result;
}
}

36
src/app/babylon/model/data/institution/facility/property-data/outdoor/property-data-pl.ts

@ -0,0 +1,36 @@
import { FacilityType } from "../../../../model-data/model-data-facility";
import { PropertyData_Base } from "../property-data-base";
/**
*
*/
export class tableData {
public tableRow: string[]
}
export class tableRow {
public street: string = ""
public adjoinBuilding: string = ""
public range: string = ""
}
export class PropertyData_PL extends PropertyData_Base {
direction: number = 0; //毗邻所属方向 0,1,2,3 --- 东南西北
info: string = "";
tableData: tableData[] = [];
constructor(key: string, direction: number, info: string, tableData: tableData[]) {
super(key, FacilityType.PL);
this.direction = direction;
this.info = info;
this.tableData = tableData
}
clone(key: string) {
let result = new PropertyData_PL(key, this.direction, this.info, this.tableData);
return result;
}
}

37
src/app/babylon/model/data/institution/facility/property-data/outdoor/property-data-q.ts

@ -0,0 +1,37 @@
import { Color3 } from "@babylonjs/core";
import { Type } from "class-transformer";
import { FacilityType } from "../../../../model-data/model-data-facility";
import { PropertyData_Base_IMG } from "../base/property-data-base-img";
import { PropertyData_Base } from "../property-data-base";
/**
*
*/
export class PropertyData_Q extends PropertyData_Base_IMG {
@Type(() => Color3)
color: Color3;//区域颜色
constructor(key: string, img: string, pos: string, info: string, color: Color3, type: FacilityType) {
super(key, img, pos, info, type);
this.color = color;
if (color == null) {
switch (type) {
case FacilityType.JTQ:
this.color = Color3.Yellow();
break;
case FacilityType.JJQ:
this.color = Color3.Green();
break;
}
}
}
clone(key: string) {
let result = new PropertyData_Q(key, this.img, this.pos, this.info, this.color, this.facilityType);
return result;
}
}

38
src/app/babylon/model/data/institution/facility/property-data/property-data-base.ts

@ -0,0 +1,38 @@
import { classToClass } from "class-transformer";
import { FacilityType } from "../../../model-data/model-data-facility";
//基本属性
export abstract class PropertyData_Base {
static readonly c_defaultText = "----"; //文字默认值
/**
* key
*/
key: string;
/**
*
*/
facilityType: FacilityType;
/**
*
*/
name: string;
constructor(key: string, facilityType: FacilityType) {
this.key = key;
this.facilityType = facilityType;
}
clone(key: string): PropertyData_Base {
let result = classToClass(this);
result.key = key;
return result;
}
}

14
src/app/babylon/model/data/institution/facility/property-data/property-data-public.ts

@ -0,0 +1,14 @@
import { PropertyData_Base } from "./property-data-base";
//暂时用于哪些还没有具体实现的属性
export class PropertyData_public extends PropertyData_Base {
clone(key: string) {
let result = new PropertyData_public(key, this.facilityType);
return result;
}
}

5
src/app/babylon/model/data/institution/institution-data-simple.ts

@ -0,0 +1,5 @@
//简易单位基本信息,用于显示于列表中
export class InsitutionDataSimple {
key: string;//唯一身份key
name: string;//自定义的名称
}

87
src/app/babylon/model/data/institution/institution-data.ts

@ -0,0 +1,87 @@
import { Vector3 } from "@babylonjs/core";
import { Type } from "class-transformer";
import { BuildingData_ChemicalPlant, BuildingData_Environment, BuildingData_Normal, BuildingType } from "./building/building-data";
//单位信息
export class InstitutionData {
@Type(() => NormalData)
normalData: NormalData = null;//常规信息
@Type(() => BuildingData_Normal)
normalBuildingDatas: BuildingData_Normal[] = [];//普通建筑列表
@Type(() => BuildingData_Environment)
environmentDatas: BuildingData_Environment[] = [];//环境信息
@Type(() => BuildingData_ChemicalPlant)
chemicalPlantData: BuildingData_ChemicalPlant[] = [];//化工厂信息
@Type(() => Vector3)
pos: Vector3 = new Vector3(0, 0, 0);
//获取一个最新的key(根据前一个同类建筑key,加一)
public getNewKey(buildingType: BuildingType): string {
let result = "";
let lastNormalData: NormalData = null;
let length = 0;
switch (buildingType) {
case BuildingType.Normal:
if (this.normalBuildingDatas != null && this.normalBuildingDatas.length > 0) {
length = this.normalBuildingDatas.length;
lastNormalData = this.normalBuildingDatas[length - 1].normalData;
}
break;
case BuildingType.Environment:
if (this.environmentDatas != null && this.environmentDatas.length > 0) {
length = this.environmentDatas.length;
lastNormalData = this.environmentDatas[length - 1].normalData;
}
break;
case BuildingType.ChemicalPlant:
if (this.chemicalPlantData != null && this.chemicalPlantData.length > 0) {
length = this.chemicalPlantData.length;
lastNormalData = this.chemicalPlantData[length - 1].normalData;
}
break;
}
let lastKey = 0;
if (lastNormalData != null) {
lastKey = Number.parseInt(lastNormalData.key);
lastKey++;
}
result += lastKey;
return result;
}
}
//常规、必有的信息
export class NormalData {
key: string;//唯一key
name: string;//给用户编辑、查看用的名称
constructor(key: string = "", name: string = "") {
this.key = key;
this.name = name;
}
clone(): NormalData {
let result = new NormalData(this.key, this.name);
return result;
}
getName() {
//console.log("getName==" + this.name);
return this.name;
}
}

226
src/app/babylon/model/data/mark/all-mark-data.ts

@ -0,0 +1,226 @@
import { Type } from "class-transformer";
import { MarkData_Area } from "./other/mark-data-area";
import { MarkData, MarkType, MarkKindType, MarkTagPos, MarkTask } from "./mark-data";
import { MarkData_Line } from "./other/mark-data-line";
import { MarkData_multiLine } from "./other/mark-data-multi-line";
import { MarkData_multiArrow_CT, MarkData_multiArrow_JG } from "./other/mark-data-multi-arrow";
import { ConfigManager } from "src/assets/babylon/controller/config-manager";
export class AllMarkData {
/**
*
*/
@Type(() => MarkData)
marks_Disaster: MarkData[] = [];
/**
*
*/
@Type(() => MarkData)
marks_FireFighting: MarkData[] = [];
/**
*
*/
@Type(() => MarkData)
marks_Linkage: MarkData[] = [];
/**
*
*/
@Type(() => MarkData)
marks_Inside: MarkData[] = [];
/**
*
*/
@Type(() => MarkData)
marks_Tool: MarkData[] = [];
static CreateAllMarkData(): AllMarkData {
let result = new AllMarkData();
//灾情
let tagPos: MarkTagPos = MarkTagPos.Disaster;
AllMarkData.newMarkData(MarkType.SYA, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.SYB, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.SYC, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.SYD, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.ZQR, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.WXP, MarkKindType.Goods, tagPos, result);
AllMarkData.newMarkData(MarkType.ZWD, MarkKindType.Goods, tagPos, result);
AllMarkData.newMarkData(MarkType.PCD, MarkKindType.Goods, tagPos, result);
AllMarkData.newMarkData(MarkType.H, MarkKindType.Effect, tagPos, result, undefined, false);
AllMarkData.newMarkData(MarkType.TPH, MarkKindType.Effect, tagPos, result, undefined, false);
AllMarkData.newMarkData(MarkType.SNH, MarkKindType.Effect, tagPos, result, undefined, false);
AllMarkData.newMarkData(MarkType.YWA, MarkKindType.Effect, tagPos, result, undefined, false);
AllMarkData.newMarkData(MarkType.YWB, MarkKindType.Effect, tagPos, result, undefined, false);
AllMarkData.newMarkData(MarkType.YWC, MarkKindType.Effect, tagPos, result, undefined, false);
//消防力量
tagPos = MarkTagPos.FireFighting;
AllMarkData.newMarkData(MarkType.MHF, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.JYF, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.GRF, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.FHF, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.BHF, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.YWXFY, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.AQS, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.MTC, MarkKindType.Car, tagPos, result);
AllMarkData.newMarkData(MarkType.XLC, MarkKindType.Car, tagPos, result);
AllMarkData.newMarkData(MarkType.SGC, MarkKindType.Car, tagPos, result);
AllMarkData.newMarkData(MarkType.PMC, MarkKindType.Car, tagPos, result);
AllMarkData.newMarkData(MarkType.GPC, MarkKindType.Car, tagPos, result);
AllMarkData.newMarkData(MarkType.DGPTC, MarkKindType.Car, tagPos, result);
AllMarkData.newMarkData(MarkType.YTC, MarkKindType.Car, tagPos, result);
AllMarkData.newMarkData(MarkType.QXJYC, MarkKindType.Car, tagPos, result);
AllMarkData.newMarkData(MarkType.QCC, MarkKindType.Car, tagPos, result);
AllMarkData.newMarkData(MarkType.ZMC, MarkKindType.Car, tagPos, result);
AllMarkData.newMarkData(MarkType.PCC, MarkKindType.Car, tagPos, result);
AllMarkData.newMarkData(MarkType.PYC, MarkKindType.Car, tagPos, result);
AllMarkData.newMarkData(MarkType.ZHC, MarkKindType.Car, tagPos, result);
AllMarkData.newMarkData(MarkType.GCGSC, MarkKindType.Car, tagPos, result);
AllMarkData.newMarkData(MarkType.KQHXCQC, MarkKindType.Car, tagPos, result);
//联动力量
tagPos = MarkTagPos.Linkage;
AllMarkData.newMarkData(MarkType.GA, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.JJ, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.YS, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.QXRY, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.JHC, MarkKindType.Car, tagPos, result);
AllMarkData.newMarkData(MarkType.JC, MarkKindType.Car, tagPos, result);
AllMarkData.newMarkData(MarkType.DLQXC, MarkKindType.Car, tagPos, result);
AllMarkData.newMarkData(MarkType.RQQXC, MarkKindType.Car, tagPos, result);
AllMarkData.newMarkData(MarkType.GSQXC, MarkKindType.Car, tagPos, result);
AllMarkData.newMarkData(MarkType.HBJCC, MarkKindType.Car, tagPos, result);
AllMarkData.newMarkData(MarkType.JTYSC, MarkKindType.Car, tagPos, result);
AllMarkData.newMarkData(MarkType.WSFYC, MarkKindType.Car, tagPos, result);
AllMarkData.newMarkData(MarkType.YJTXC, MarkKindType.Car, tagPos, result);
AllMarkData.newMarkData(MarkType.JCA, MarkKindType.Car, tagPos, result);
AllMarkData.newMarkData(MarkType.JCB, MarkKindType.Car, tagPos, result);
AllMarkData.newMarkData(MarkType.JCC, MarkKindType.Car, tagPos, result);
//内部力量
tagPos = MarkTagPos.Inside;
AllMarkData.newMarkData(MarkType.DSZ, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.JL, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.FZ, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.MS, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.ZJ, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.ZG, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.ZZ, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.QT, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.SJS, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.CXY, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.ZYA, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.ZYB, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.JG, MarkKindType.Persion, tagPos, result);
AllMarkData.newMarkData(MarkType.BA, MarkKindType.Persion, tagPos, result);
//标绘工具
tagPos = MarkTagPos.Tool;
AllMarkData.newMarkData(MarkType.JJX, MarkKindType.Goods, tagPos, result, undefined, false);
AllMarkData.newMarkData(MarkType.SD, MarkKindType.Goods, tagPos, result, undefined, false);
AllMarkData.newMarkData(MarkType.JGLX, MarkKindType.Virtual, tagPos, result, undefined, false);
AllMarkData.newMarkData(MarkType.CT, MarkKindType.Virtual, tagPos, result, undefined, false);
AllMarkData.newMarkData(MarkType.ZHB, MarkKindType.Goods, tagPos, result, MarkTask.Unknown);
AllMarkData.newMarkData(MarkType.LT6, MarkKindType.Goods, tagPos, result);
AllMarkData.newMarkData(MarkType.LT15, MarkKindType.Goods, tagPos, result);
AllMarkData.newMarkData(MarkType.FSQ, MarkKindType.Goods, tagPos, result);
AllMarkData.newMarkData(MarkType.STB, MarkKindType.Goods, tagPos, result);
AllMarkData.newMarkData(MarkType.SP, MarkKindType.Goods, tagPos, result, MarkTask.WaterMonitor);
AllMarkData.newMarkData(MarkType.WZ, MarkKindType.Virtual, tagPos, result, MarkTask.Unknown);
AllMarkData.newMarkData(MarkType.JJQ, MarkKindType.Virtual, tagPos, result, MarkTask.Unknown, false);
AllMarkData.newMarkData(MarkType.QYSDA, MarkKindType.Virtual, tagPos, result, MarkTask.Unknown, false);
AllMarkData.newMarkData(MarkType.QYSDB, MarkKindType.Virtual, tagPos, result, MarkTask.Unknown, false);
return result;
}
//新建设备信息
/**
*
* @param type
* @param kindType
* @param tagPos
* @param allMarkData
* @param taskType
* @param isModel
*/
static newMarkData(type: MarkType, kindType: MarkKindType, tagPos: MarkTagPos, allMarkData: AllMarkData, taskType?: MarkTask, isModel = true): MarkData {
let l_taskType: MarkTask = MarkTask.None;
let list = [];
switch (tagPos) {
case MarkTagPos.Disaster:
list = allMarkData.marks_Disaster;
break;
case MarkTagPos.FireFighting:
list = allMarkData.marks_FireFighting
break;
case MarkTagPos.Linkage:
list = allMarkData.marks_Linkage;
break;
case MarkTagPos.Inside:
list = allMarkData.marks_Inside;
break;
case MarkTagPos.Tool:
list = allMarkData.marks_Tool;
break;
}
//除了灾情以外, 人和车的任务类型
if (tagPos != MarkTagPos.Disaster) {
if (kindType == MarkKindType.Persion) {
l_taskType = MarkTask.Person;
}
else if (kindType == MarkKindType.Car) {
l_taskType = MarkTask.Car;
}
}
//没指定,则使用规则的任务类型
if (taskType == null) {
taskType = l_taskType;
}
let icon = ConfigManager.getMarkIconUrl(tagPos, type);
let modelPath = ConfigManager.getMarkModelPath(tagPos, type);
let modelName = type + ".gltf";
let result = null;
switch (type) {
case MarkType.JJQ:
case MarkType.QYSDA:
case MarkType.QYSDB:
result = new MarkData_Area(type.toString(), type, tagPos, kindType, icon, modelPath, modelName, taskType, isModel);
break;
case MarkType.JJX:
result = new MarkData_Line(type.toString(), type, tagPos, kindType, icon, modelPath, modelName, taskType, isModel);
break;
case MarkType.SD:
result = new MarkData_multiLine(type.toString(), type, tagPos, kindType, icon, modelPath, modelName, taskType, isModel);
break;
case MarkType.JGLX:
result = new MarkData_multiArrow_JG(type.toString(), type, tagPos, kindType, icon, modelPath, modelName, taskType, isModel);
break;
case MarkType.CT:
result = new MarkData_multiArrow_CT(type.toString(), type, tagPos, kindType, icon, modelPath, modelName, taskType, isModel);
break;
default:
result = new MarkData(type.toString(), type, tagPos, kindType, icon, modelPath, modelName, taskType, isModel);
break;
}
list.push(result);
return result;
}
}

597
src/app/babylon/model/data/mark/mark-data.ts

@ -0,0 +1,597 @@
import { Type } from "class-transformer";
import { ConfigManager } from "src/assets/babylon/controller/config-manager";
import { ModelData } from "../model-data/model-data";
import { TransformData } from "../transform-data";
import { MarkProperty } from "./mark-property";
/**
*
*/
export class MarkData extends ModelData {
/**
*
*/
type: MarkType = MarkType.SYA;
/**
* tag
*/
tagPos: MarkTagPos = MarkTagPos.Disaster;
/**
*
*
*/
markKindType: MarkKindType = MarkKindType.Persion;
/**
*
*/
iconURL: string;
/**
*
*/
belongtoBuildingId: string;
/**
*
*/
@Type(() => MarkProperty)
property: MarkProperty;
/**
* ()
*/
@Type(() => ChildNodeData)
childrenNodeData: ChildNodeData[] = [];
/**
*
*/
waterPower: number = 20;
constructor(id: string, type: MarkType, tagPos: MarkTagPos, markKindType: MarkKindType, iconURL: string, resPath: string, resName: string, taskType: MarkTask, isModel: boolean) {
super(id, ConfigManager.getMarkName(type), resPath, resName, undefined, isModel)
this.name = ConfigManager.getMarkName(type);
this.type = type;
this.tagPos = tagPos;
this.markKindType = markKindType;
this.iconURL = iconURL;
let defaultTask: string = undefined;
if (type == MarkType.WZ) {
defaultTask = "文字信息";
}
this.property = new MarkProperty(taskType, undefined, undefined, defaultTask);
}
}
/**
*
*/
export class ChildNodeData {
/**
*
*/
name: string;
/**
*
*/
@Type(() => TransformData)
transformData: TransformData = new TransformData();
}
/**
* tag
*/
export enum MarkTagPos {
/**
*
*/
Disaster = "Disaster",
/**
*
*/
FireFighting = "FireFighting",
/**
*
*/
Linkage = "Linkage",
/**
*
*/
Inside = "Inside",
/**
*
*/
Tool = "Tool",
}
/**
*
*/
export enum MarkKindType {
/**
*
*/
Persion = "Persion",
/**
*
*/
Car = "Car",
/**
*
*/
Goods = "Goods",
/**
*
*/
Virtual = "Virtual",
/**
*
*/
Effect = "Effect",
}
/**
*
* id
*/
export enum MarkType {
//============灾情设定===============
/**
* A
*/
SYA = "SYA",
/**
* B
*/
SYB = "SYB",
/**
* C
*/
SYC = "SYC",
/**
* D
*/
SYD = "SYD",
/**
*
*/
ZQR = "ZQR",
/**
*
*/
WXP = "WXP",
/**
*
*/
ZWD = "ZWD",
/**
*
*/
PCD = "PCD",
/**
*
*/
H = "H",
/**
*
*/
TPH = "TPH",
/**
*
*/
SNH = "SNH",
/**
* A
*/
YWA = "YWA",
/**
* B
*/
YWB = "YWB",
/**
* C
*/
YWC = "YWC",
//==================消防力量================
/**
*
*/
MHF = "MHF",
/**
*
*/
JYF = "JYF",
/**
*
*/
GRF = "GRF",
/**
*
*/
FHF = "FHF",
/**
*
*/
BHF = "BHF",
/**
*
*/
YWXFY = "YWXFY",
/**
*
*/
AQS = "AQS",
/**
*
*/
MTC = "MTC",
/**
*
*/
XLC = "XLC",
/**
*
*/
SGC = "SGC",
/**
*
*/
PMC = "PMC",
/**
*
*/
GPC = "GPC",
/**
*
*/
DGPTC = "DGPTC",
/**
*
*/
YTC = "YTC",
/**
*
*/
QXJYC = "QXJYC",
/**
*
*/
QCC = "QCC",
/**
*
*/
ZMC = "ZMC",
/**
*
*/
PCC = "PCC",
/**
*
*/
PYC = "PYC",
/**
*
*/
ZHC = "ZHC",
/**
*
*/
GCGSC = "GCGSC",
/**
*
*/
KQHXCQC = "KQHXCQC",
//================联动力量===================
/**
*
*/
GA = "GA",
/**
*
*/
JJ = "JJ",
/**
*
*/
YS = "YS",
/**
*
*/
QXRY = "QXRY",
/**
*
*/
JHC = "JHC",
/**
*
*/
JC = "JC",
/**
*
*/
DLQXC = "DLQXC",
/**
*
*/
RQQXC = "RQQXC",
/**
*
*/
GSQXC = "GSQXC",
/**
*
*/
HBJCC = "HBJCC",
/**
*
*/
JTYSC = "JTYSC",
/**
*
*/
WSFYC = "WSFYC",
/**
*
*/
YJTXC = "YJTXC",
/**
* 轿
*/
JCA = "JCA",
/**
* 轿
*/
JCB = "JCB",
/**
* 轿
*/
JCC = "JCC",
//===============内部力量=================
/**
*
*/
DSZ = "DSZ",
/**
*
*/
JL = "JL",
/**
*
*/
FZ = "FZ",
/**
*
*/
MS = "MS",
/**
*
*/
ZJ = "ZJ",
/**
*
*/
ZG = "ZG",
/**
*
*/
ZZ = "ZZ",
/**
*
*/
QT = "QT",
/**
*
*/
SJS = "SJS",
/**
*
*/
CXY = "CXY",
/**
*
*/
ZYA = "ZYA",
/**
*
*/
ZYB = "ZYB",
/**
*
*/
JG = "JG",
/**
*
*/
BA = "BA",
//===================标绘工具===================
/**
* 线
*/
JJX = "JJX",
/**
*
*/
SD = "SD",
/**
* 线
*/
JGLX = "JGLX",
/**
* 退
*/
CT = "CT",
/**
*
*/
ZHB = "ZHB",
/**
* 6
*/
LT6 = "LT6",
/**
* 15
*/
LT15 = "LT15",
/**
*
*/
FSQ = "FSQ",
/**
*
*/
STB = "STB",
/**
*
*/
SP = "SP",
/**
*
*/
WZ = "WZ",
/**
*
*/
JJQ = "JJQ",
/**
*
*/
QYSDA = "QYSDA",
/**
*
*/
QYSDB = "QYSDB",
}
/**
*
*/
export enum MarkTask {
/**
*
*/
None,
/**
*
*/
Unknown,
/**
*
*/
Person,
/**
*
*/
Car,
/**
*
*/
WaterMonitor
}

491
src/app/babylon/model/data/mark/mark-plan-data.ts

@ -0,0 +1,491 @@
import { Type } from "class-transformer";
import { TsTool } from "src/assets/babylon/tool/ts-tool";
import { ArcRotateCameraData } from "../camera-data";
import { MarkData } from "./mark-data";
/**
*
*/
export class AllMarkPlanData {
/**
* ID
*/
institutionID: string;
/**
*
*/
@Type(() => MarkPlanData)
datas: MarkPlanData[];
/**
*
* @param name
*/
createPlanData(name): MarkPlanData {
let id = this.getNextPlaneId();
let data = new MarkPlanData(id, name, []);
this.datas.push(data);
return data;
}
/**
*
*/
deletePlanData(id: number) {
let planeData = this.getMarkPlanById(id);
if (planeData != null) {
TsTool.arrayRemove(this.datas, planeData);
}
}
/**
* id
*/
getNextPlaneId() {
let index = -1;
if (this.datas != null && this.datas.length > 0) {
index = this.datas[this.datas.length - 1].id;
}
index++;
return index;
}
/**
* id查找标绘方案
* @param markPlanId
*/
getMarkPlanById(markPlanId: number) {
if (this.datas != null) {
for (let i = 0; i < this.datas.length; i++) {
if (this.datas[i].id == markPlanId) {
return this.datas[i];
}
}
}
return null;
}
}
/**
*
*/
export class MarkPlanData {
/**
* id
*/
id: number;
/**
*
*/
name: string;
/**
* UI上排序
*/
index: number = 0;
/**
*
*/
@Type(() => MarkNodeData)
nodes: MarkNodeData[] = [];
constructor(id: number, name: string, nodes: MarkNodeData[] = []) {
this.id = id;
this.index = id;
this.name = name;
this.nodes = nodes;
this.index = 0;
}
/**
* id
*/
getNextNodeId() {
let index = -1;
if (this.nodes != null && this.nodes.length > 0) {
index = this.nodes[this.nodes.length - 1].id;
}
index++;
return index;
}
/**
*
* @param name
*/
createMarkNode(name: string) {
let id = this.getNextNodeId();
let result = new MarkNodeData(id, name);
this.nodes.push(result);
return result;
}
/**
*
* @param id
*/
deleteMarkNode(id: number) {
let node = this.getNodeById(id);
if (node != null) {
TsTool.arrayRemove(this.nodes, node);
}
}
/**
* id获取节点
* @param id
*/
getNodeById(id: number) {
if (this.nodes != null) {
for (let i = 0; i < this.nodes.length; i++) {
if (this.nodes[i].id == id) {
return this.nodes[i];
}
}
}
return null;
}
/**
*
* @param id //要替换的节点id
* @param nodeData //新数据
*/
setNodeData(id: number, nodeData: MarkNodeData) {
if (this.nodes != null) {
for (let i = 0; i < this.nodes.length; i++) {
if (this.nodes[i].id == id) {
this.nodes[i] = nodeData;
}
}
}
}
}
/**
*
*/
export class MarkNodeData {
/**
* id
*/
id: number;
/**
*
*/
name: string;
/**
* UI上排序
*/
index: number = 0;
/**
*
*/
@Type(() => ArcRotateCameraData)
cameraData: ArcRotateCameraData;
/**
*
*/
@Type(() => EnvironmentData)
environmentData: EnvironmentData[];
/**
*
*/
@Type(() => NatureData)
natureData: NatureData;
constructor(id: number, name: string) {
this.id = id;
this.index = id;
this.name = name;
this.cameraData = new ArcRotateCameraData();
this.environmentData = [];
this.natureData = new NatureData();
this.index = 0;
}
/**
*
* @param id
*/
getEnvironmentData(id: number) {
let result = null;
for (let i = 0; i < this.environmentData.length; i++) {
if (this.environmentData[i].id == id) {
result = this.environmentData[i];
break;
}
}
return result;
}
/**
*
* @param id
*/
changeNowEnvironmentData(id: number) {
for (let i = 0; i < this.environmentData.length; i++) {
if (this.environmentData[i].id == id) {
this.environmentData[i].isNow = true;
}
else {
this.environmentData[i].isNow = false;
}
}
}
/**
*
* @param isOutdoor
* @param buildingId
* @param floorId
*/
getEnvironmentDataByValue(isOutdoor: boolean,
/**
* Id
*/
buildingId: string,
/**
* id
*/
floorId: string) {
let result: EnvironmentData = null;
for (let i = 0; i < this.environmentData.length; i++) {
if (isOutdoor == true && this.environmentData[i].isOutdoor == true) {
result = this.environmentData[i];
break;
}
else if (this.environmentData[i].isOutdoor == isOutdoor && this.environmentData[i].buildingId == buildingId && this.environmentData[i].floorId == floorId) {
result = this.environmentData[i];
break;
}
}
return result;
}
/**
*
*/
getCurrentEnvironmentData() {
let result = this.environmentData[0];
for (let i = 0; i < this.environmentData.length; i++) {
if (this.environmentData[i].isNow) {
result = this.environmentData[i];
break;
}
}
result.isNow = true;
return result;
}
addEnvironment(buildingId: string, isOutdoor: boolean, floorId: string) {
let index = -1;
for (let i = 0; i < this.environmentData.length; i++) {
if (this.environmentData[i].id > index) {
index = this.environmentData[i].id;
}
}
index++;
let newEnvironment = new EnvironmentData(index, buildingId, isOutdoor, floorId);
this.environmentData.push(newEnvironment);
return newEnvironment;
}
}
/**
*
*/
export class EnvironmentData {
id: number;
/**
*
*/
isOutdoor: boolean;
/**
* Id
*/
buildingId: string;
/**
* id
*/
floorId: string;
/**
*
*/
@Type(() => MarkData)
markDatas: MarkData[] = [];
/**
*
*/
isNow: boolean;
constructor(id: number, buildingId: string, isOutdoor: boolean, floorId: string) {
this.id = id;
this.buildingId = buildingId;
this.isOutdoor = isOutdoor;
this.floorId = floorId;
this.markDatas = [];
}
/**
* markData
* @param markData
*/
addMarkData(markData: MarkData) {
this.markDatas.push(markData);
}
/**
* markData
* @param markData
*/
removeMarkData(markData: MarkData) {
TsTool.arrayRemove(this.markDatas, markData);
}
}
/**
*
*/
export class NatureData {
/**
*
*/
weather: WeatherType;
/**
*
*/
temperature: number;
/**
*
*/
windDirection: WindDirectionType;
/**
*
*/
windPower: number;
constructor() {
this.weather = WeatherType.Sun;
this.temperature = 26;
this.windDirection = WindDirectionType.East;
this.windPower = 3;
}
}
/**
*
*/
export enum WeatherType {
/**
*
*/
Sun = "Sun",
/**
*
*/
Sloudy = "Sloudy",
/**
*
*/
Rain = "Rain",
/**
*
*/
Snow = "Snow"
}
/**
*
*/
export enum WindDirectionType {
/**
*
*/
East = "East",
/**
*
*/
South = "South",
/**
* 西
*/
West = "West",
/**
*
*/
North = "North",
/**
*
*/
SouthEast = "SouthEast",
/**
* 西
*/
SouthWest = "SouthWest",
/**
*
*/
NorthEast = "NorthEast",
/**
* 西
*/
NorthWest = "NorthWest",
}

50
src/app/babylon/model/data/mark/mark-property.ts

@ -0,0 +1,50 @@
import { MarkTask } from "./mark-data";
/**
*
*/
export class MarkProperty {
/**
*
*/
institution: string;
/**
*
*/
index: number;
/**
*
*/
taskType: MarkTask;
/**
*
*/
task: string;
/**
*
*/
description: string;
constructor(taskType?: MarkTask, institution: string = "辖区中队", index: number = 1, task: string = "待命", description?: string) {
this.taskType = taskType
this.institution = institution
this.index = index
this.task = task
this.description = description
}
/**
* -
*/
getInstitutionNum() {
return this.institution + "-" + this.index;
}
}

19
src/app/babylon/model/data/mark/other/mark-data-area.ts

@ -0,0 +1,19 @@
import { Vector3 } from "@babylonjs/core";
import { Type } from "class-transformer";
import { MarkData } from "../mark-data";
/**
*
*/
export class MarkData_Area extends MarkData {
/**
*
*/
@Type(() => Vector3)
pointData: Vector3[];
/**
*
*/
color: string = "#FF666D";
}

21
src/app/babylon/model/data/mark/other/mark-data-line.ts

@ -0,0 +1,21 @@
import { Vector3 } from "@babylonjs/core";
import { Type } from "class-transformer";
import { MarkData } from "../mark-data";
/**
* 线
*/
export class MarkData_Line extends MarkData {
/**
*
*/
@Type(() => Vector3)
pointData: Vector3[] = [];
/**
*
*/
color: string = "#FFD306";
}

41
src/app/babylon/model/data/mark/other/mark-data-multi-arrow.ts

@ -0,0 +1,41 @@
import { Vector3 } from "@babylonjs/core/Maths";
import { Type } from "class-transformer";
import { MarkData } from "../mark-data";
/**
* 线
*/
export class MarkData_multiArrow extends MarkData {
/**
*
*/
@Type(() => Vector3)
pointData: Vector3[];
/**
*
*/
color: string;
}
/**
* 线
*/
export class MarkData_multiArrow_JG extends MarkData_multiArrow {
/**
*
*/
color: string = "#d71345";
}
/**
* 退线
*/
export class MarkData_multiArrow_CT extends MarkData_multiArrow {
/**
*
*/
color: string = "#A9FF00";
}

31
src/app/babylon/model/data/mark/other/mark-data-multi-line.ts

@ -0,0 +1,31 @@
import { Vector3 } from "@babylonjs/core";
import { Type } from "class-transformer";
import { MarkData } from "../mark-data";
/**
* 线
*/
export class MarkData_multiLine extends MarkData {
/**
*
*/
@Type(() => Vector3)
pointData: Vector3[];
/**
*
*/
color: string = "#FF5151";
/**
* 线
*/
radius: number = 0.1;
/**
* y偏移
*/
yPos: number = 0;
}

18
src/app/babylon/model/data/model-data/model-data-building.ts

@ -0,0 +1,18 @@
import { TransformData } from "../transform-data";
import { BuildingPosType, ModelData } from "./model-data";
//建筑类 模型数据
export class ModelData_building extends ModelData {
modelType: BuildingPosType;//模型类别
baseInfoKey: string;//单位基本信息的key
constructor(key: string, name: string, modelType: BuildingPosType, resName: string, transformData: TransformData, l_resPath: string) {
super(key, name, null, resName, transformData);
this.modelType = modelType;
this.resPath = l_resPath;
}
}

279
src/app/babylon/model/data/model-data/model-data-facility.ts

@ -0,0 +1,279 @@
import { ModelData } from "./model-data";
import { TransformData } from "../transform-data";
import { PropertyData_Base } from "../institution/facility/property-data/property-data-base";
import { classToClass, Type } from "class-transformer";
import { Vector3 } from "@babylonjs/core";
import { DataManager } from "src/assets/babylon/controller/data-manager";
//设备数据
export class ModelData_facility extends ModelData {
posType: FacilityPosType = FacilityPosType.Outdoor;//位置类型
facilityType: FacilityType = FacilityType.AQCK;//具体设备类别
@Type(() => PropertyData_Base)
propertyData: PropertyData_Base = null;//属性信息
@Type(() => Vector3)
areaPoints: Vector3[] = [];//区域位点
constructor(key: string, type: FacilityType, name: string, resName: string, transformData: TransformData, posType: FacilityPosType, isModel: boolean = true) {
super(key, name, null, resName, transformData, isModel);
this.facilityType = type;
this.posType = posType;
if (type != undefined) {
let showType = ModelData_facility.getShowType(type);
switch (showType) {
case FacilityShowType.ModelAndTag:
this.resName = resName;
this.resPath = DataManager.getResPath_facility(this.posType, type);
break;
case FacilityShowType.AreaAndTag:
this.areaPoints = this.newAreapPoints();
break;
}
// this.resPath = ConfigManager.c_resPath_facilitiesRoot + this.posType.toString() + "/" + type.toLowerCase() + "/";
this.propertyData = DataManager.createPropertyData(key, type);
}
}
/**
*
*/
getShowtype() {
let showType = ModelData_facility.getShowType(this.facilityType);
return showType
}
clone(key: string): ModelData_facility {
let result = new ModelData_facility(key, this.facilityType, this.name, this.resName, this.transformData.clone(), this.posType);
result.propertyData = this.propertyData.clone(key);
result.areaPoints = classToClass(this.areaPoints);
return result;
}
//新建区域位点
newAreapPoints(): Vector3[] {
let size = 10;
let x = 0.75 * size;
let z = 0.5 * size;
let result: Vector3[] = [];
result.push(new Vector3(0, 0, 1 * size));
result.push(new Vector3(x, 0, z));
result.push(new Vector3(x, 0, -z));
result.push(new Vector3(0, 0, -1 * size));
result.push(new Vector3(-x, 0, -z));
result.push(new Vector3(-x, 0, z));
return result;
}
/**
*
* @param facilityType
*/
static getShowType(facilityType: FacilityType): FacilityShowType {
let result = FacilityShowType.ModelAndTag;
switch (facilityType) {
case FacilityType.AQCK:
case FacilityType.DSXHS:
case FacilityType.DXXHS:
case FacilityType.SZDXXHS:
case FacilityType.SZDSXHS:
case FacilityType.DSSBJHQ:
case FacilityType.DXSBJHQ:
case FacilityType.QBSBJHQ:
case FacilityType.DGNSBJHQ:
case FacilityType.PL:
case FacilityType.TPBZ:
case FacilityType.XKS:
case FacilityType.BF:
case FacilityType.SX:
case FacilityType.LSXFB:
case FacilityType.WSXFB:
case FacilityType.CYXFB:
case FacilityType.SNXHS:
case FacilityType.FHM:
case FacilityType.HT:
case FacilityType.PTDT:
case FacilityType.XFDT:
case FacilityType.SSLT:
case FacilityType.FHJL: result = FacilityShowType.ModelAndTag; break;//展示模型和标签
case FacilityType.JTQ:
case FacilityType.JJQ:
case FacilityType.FHFQ: result = FacilityShowType.AreaAndTag; break;//展示可编辑多边形
case FacilityType.GD: result = FacilityShowType.GdAndTag; break;//展示高度和标签
}
return result;
}
}
//设备位置类型(室内还是室外)
export enum FacilityPosType {
Indoor = "indoor", //室内
Outdoor = "outdoor", //室外
Public = "public",//共有
}
//设备展示类型
export enum FacilityShowType {
Tag,//标签
ModelAndTag,//模型和标签
AreaAndTag,//区域和标签
GdAndTag,//高度和标签
}
/**
*
*/
export enum FacilityType {
//室外
/**
*
*/
AQCK = "AQCK",
/**
*
*/
DSXHS = "DSXHS",
/**
*
*/
DXXHS = "DXXHS",
/**
*
*/
SZDSXHS = "SZDSXHS",
/**
*
*/
SZDXXHS = "SZDXXHS",
/**
*
*/
DSSBJHQ = "DSSBJHQ",
/**
*
*/
DXSBJHQ = "DXSBJHQ",
/**
*
*/
QBSBJHQ = "QBSBJHQ",
/**
*
*/
DGNSBJHQ = "DGNSBJHQ",
/**
*
*/
GD = "GD",
/**
*
*/
PL = "PL",
/**
*
*/
JTQ = "JTQ",
/**
*
*/
JJQ = "JJQ",
/**
*
*/
TPBZ = "TPBZ",//
//室内
/**
*
*/
XKS = "XKS",
/**
*
*/
BF = "BF",
/**
*
*/
SX = "SX",
/**
*
*/
LSXFB = "LSXFB",
/**
*
*/
WSXFB = "WSXFB",
/**
*
*/
CYXFB = "CYXFB",
/**
*
*/
SNXHS = "SNXHS",
/**
*
*/
FHM = "FHM",
/**
*
*/
FHJL = "FHJL",
/**
*
*/
SSLT = "SSLT",
/**
*
*/
XFDT = "XFDT",
/**
*
*/
PTDT = "PTDT",
/**
*
*/
HT = "HT",
/**
*
*/
BNC = "BNC",
/**
*
*/
WXY = "WXY",
/**
*
*/
ZDQY = "ZDQY",
/**
*
*/
DWBZ = "DWBZ",
/**
*
*/
FHFQ = "FHFQ",
}

71
src/app/babylon/model/data/model-data/model-data.ts

@ -0,0 +1,71 @@
import { TransformData } from '../transform-data';
import { Type } from 'class-transformer';
//模型 数据
export class ModelData {
key: string; //身份唯一标识
name: string; //用户定义的名称
resName: string; //资源名称
resPath: string; //资源路径(局部) 可使用 DataManager.getResPath进行构造
@Type(() => TransformData)
transformData: TransformData; //变换信息
version: number = 1;//版本号
isModel: boolean;//是否是现成的模型要加载
constructor(
key?: string,
name?: string,
resPath?: string,
resName?: string,
transformData?: TransformData,
isModel: boolean = true
) {
this.key = key;
this.name = name;
this.resPath = resPath;
this.resName = resName;
this.isModel = isModel;
if (transformData == null) {
this.transformData = new TransformData();
}
else {
this.transformData = transformData;
}
}
}
//建筑模型位置类别
export enum BuildingPosType {
Default = 'default',
OutDoor = 'outdoor', //建筑外观
Environment = 'environment', //环境
Indoor = 'indoor', //室内
}
//模型类别
export enum ModelType {
Building, //建筑
Facility, //设施
Mark,//态势标绘
}
//数据记录的类型
export enum DataRecordType {
Number,//数字
String,//字符串
Texture,//字符串
}
//数据记录
export class DataRecord {
dataRecordType: DataRecordType;//记录的类型
value: string;//值
}

78
src/app/babylon/model/data/model-data/model-edit-data.ts

@ -0,0 +1,78 @@
import { Type } from "class-transformer";
import { TsTool } from "src/assets/babylon/tool/ts-tool";
import { ModelData } from "./model-data";
import { FacilityType, ModelData_facility } from "./model-data-facility";
//模型编辑信息(外观、环境、室内分层)
export class ModelEditData {
index: number = 0; //楼层、顺序用于ui上排序
isRefugeFloor: boolean = false;//避难层
@Type(() => ModelData)
modelData: ModelData; //模型信息
@Type(() => FacilityDatasByType)
facilities: FacilityDatasByType[] = []; //含有哪些设备
constructor() {
// this.belongToBuilding = belongToBuilding;
this.modelData = new ModelData();
this.index = 0;
}
//添加设备
addFacility(modelData_facility: ModelData_facility) {
let facility = this.getFacilitiesByType(modelData_facility.facilityType);
if (facility == null) {
let newDataByType = new FacilityDatasByType(modelData_facility.facilityType);
this.facilities.push(newDataByType);
facility = newDataByType.facilities;
}
facility.push(modelData_facility);
}
//移除设备
removeFacility(modelData_facility: ModelData_facility) {
let facility = this.getFacilitiesByType(modelData_facility.facilityType);
if (facility == null) {
console.error(this.modelData.key + "移除设备出错" + modelData_facility.key);
}
else {
TsTool.arrayRemove(facility, modelData_facility);
}
}
/**
*
* @param facilityType
*/
getFacilitiesByType(facilityType: FacilityType) {
let result: ModelData_facility[] = null;
for (let i = 0; i < this.facilities.length; i++) {
if (this.facilities[i].facilityType == facilityType) {
result = this.facilities[i].facilities;
return result;
}
}
return result;
}
}
/**
*
*/
export class FacilityDatasByType {
facilityType: FacilityType;
@Type(() => ModelData_facility)
facilities: ModelData_facility[] = []; //含有哪些设备
constructor(type: FacilityType) {
this.facilityType = type;
this.facilities = [];
}
}

42
src/app/babylon/model/data/transform-data.ts

@ -0,0 +1,42 @@
import { Quaternion, Vector3 } from "@babylonjs/core";
import { Type } from "class-transformer";
import "reflect-metadata";
//变换信息
export class TransformData {
@Type(() => Vector3)
position: Vector3 = new Vector3(0, 0, 0);
@Type(() => Vector3)
rotation: Vector3 = new Vector3(0, 0, 0);
@Type(() => Quaternion)
rotationQuaternion: Quaternion = new Quaternion();
@Type(() => Vector3)
scaling: Vector3 = new Vector3(0, 0, 0); //在babylon中,相对父节点的当前缩放
@Type(() => Vector3)
originalScaling: Vector3 = new Vector3(0, 0, 0); //原始缩放
clone(): TransformData {
let result = new TransformData();
result.position = this.position.clone();
result.rotation = this.rotation.clone();
if (
result.rotationQuaternion != null &&
result.rotationQuaternion != undefined
) {
result.rotationQuaternion = this.rotationQuaternion.clone();
}
result.scaling = this.scaling.clone();
result.originalScaling = this.originalScaling.clone();
return result;
}
}

8
src/app/babylon/model/info/building/building-info-chemicalplant.ts

@ -0,0 +1,8 @@
import { BuildingInfo } from "./building-info";
/**
*
*/
export class BuildingInfo_ChemicalPlant extends BuildingInfo {
}

54
src/app/babylon/model/info/building/building-info-environment.ts

@ -0,0 +1,54 @@
import { TransformNode } from '@babylonjs/core';
import { BuildingStatus } from 'src/assets/babylon/controller/status/building-status';
import { IndoorStatus } from 'src/assets/babylon/controller/status/indoor-status';
import { StatusManager } from 'src/assets/babylon/controller/status/status-manager';
import { TsTool } from 'src/assets/babylon/tool/ts-tool';
import { BuildingInfo } from './building-info';
//环境数据
export class BuildingInfo_Environment extends BuildingInfo {
readonly c_FuGaiCeng = "FuGaiCeng";//覆盖层关键字
go_FuGaiCeng: TransformNode;
/**
*
*/
updateFuGaiCeng() {
if (this.go_FuGaiCeng == null) {
return;
}
let currentStatus = StatusManager.s_currentStatus;
if (currentStatus instanceof IndoorStatus) {
this.go_FuGaiCeng.setEnabled(true);
}
else if (currentStatus instanceof BuildingStatus) {
this.go_FuGaiCeng.setEnabled(false);
}
}
/**
* modelInfo时
*/
onSetModel() {
super.onSetModel();
if (this.ModelInfo != null && this.ModelInfo.modelBox != null) {
console.log("查找覆盖层", this.ModelInfo.modelBox);
let allChildren = this.ModelInfo.modelBox.getChildTransformNodes(false);
if (allChildren != null) {
for (let i = 0; i < allChildren.length; i++) {
if (TsTool.stringContain(allChildren[i].name, this.c_FuGaiCeng)) {
this.go_FuGaiCeng = allChildren[i];
break;
}
}
}
}
}
}

11
src/app/babylon/model/info/building/building-info-normal.ts

@ -0,0 +1,11 @@
import { BuildingData_Normal } from "../../data/institution/building/building-data";
import { ModelInfo_building } from "../model/model-info-building";
import { BuildingInfo } from "./building-info";
//普通大楼
export class BuildingInfo_Normal extends BuildingInfo {
constructor(buildingData: BuildingData_Normal, modelInfo: ModelInfo_building) {
super(buildingData, modelInfo)
}
}

118
src/app/babylon/model/info/building/building-info.ts

@ -0,0 +1,118 @@
import { Vector3 } from "@babylonjs/core";
import { InfoManager } from "src/assets/babylon/controller/info-manager";
import { SceneManager } from "src/assets/babylon/controller/scene-manager";
import { BuildingStatus } from "src/assets/babylon/controller/status/building-status";
import { StatusManager } from "src/assets/babylon/controller/status/status-manager";
import { GizmoTool } from "src/assets/babylon/tool/gizmo-tool";
import { BuildingData } from "../../data/institution/building/building-data";
import { TransformData } from "../../data/transform-data";
import { ModelInfo_building } from "../model/model-info-building";
//基本建筑信息
export class BuildingInfo {
/**
*
*/
buildingData: BuildingData;
/**
*
*/
private modelInfo: ModelInfo_building;
isDisposed = false;//已经释放了
isEnable = true;//显示状态
constructor(buildingData: BuildingData, modelInfo: ModelInfo_building) {
this.buildingData = buildingData;
this.ModelInfo = modelInfo;
this.isDisposed = false;
}
/**
*
*/
get ModelInfo() {
return this.modelInfo;
}
set ModelInfo(value: ModelInfo_building) {
this.modelInfo = value;
if (this.isDisposed) {
this.dispose();
return;
}
if (value != null) {
let modelInfo = this.modelInfo;
if (modelInfo.modelData.transformData == null) {
modelInfo.modelData.transformData = new TransformData();
}
if (
modelInfo.modelData.transformData.originalScaling.equals(Vector3.Zero())
) {
//表示是新建
modelInfo.modelData.transformData.position = modelInfo.modelBox.position;
modelInfo.modelData.transformData.rotation = modelInfo.modelBox.rotation;
modelInfo.modelData.transformData.rotationQuaternion =
modelInfo.modelBox.rotationQuaternion;
modelInfo.modelData.transformData.originalScaling = modelInfo.modelBox.absoluteScaling.clone();
modelInfo.modelData.transformData.scaling = modelInfo.modelBox.absoluteScaling.clone();
} //已有数据,进行还原
else {
modelInfo.modelBox.position = modelInfo.modelData.transformData.position;
modelInfo.modelBox.rotation = modelInfo.modelData.transformData.rotation;
modelInfo.modelBox.rotationQuaternion =
modelInfo.modelData.transformData.rotationQuaternion;
}
this.ModelInfo.buildingType = this.buildingData.buildingType;
this.ModelInfo.setEnable(this.isEnable);
this.onSetModel();
//this.initFacility();
}
// if (!this.isEnable) {
// }
// else {
// }
}
/**
*
*/
initFacility() {
if (StatusManager.s_currentStatus instanceof BuildingStatus) {
InfoManager.createFacilityInfos(this.buildingData.outdoorData, this);
this.ModelInfo.showFacilityUI(false);
}
}
setEnable(enable: boolean) {
this.isEnable = enable;
if (this.ModelInfo != null) {
this.ModelInfo.setEnable(enable);
}
}
/**
*
*/
onSetModel() {
}
//释放
dispose() {
this.isDisposed = true;
StatusManager.getStatus(BuildingStatus).buildingWindow.clearFacilityInfos(this);
if (this.modelInfo != null) {
if (GizmoTool.s_nowPickAim == this.modelInfo) {
GizmoTool.onPickMeshInfoObservable.notifyObservers(null);
}
SceneManager.destroyModel(this.modelInfo);
}
}
}

73
src/app/babylon/model/info/mark/all-mark-info.ts

@ -0,0 +1,73 @@
import { MarkType } from "../../data/mark/mark-data";
import { ModelInfo_mark } from "./model-info-mark";
/**
*
*/
export class AllMarkInfo {
/**
*
*/
marks_Disaster: Map<MarkType, ModelInfo_mark> = new Map();
/**
*
*/
marks_FireFighting: Map<MarkType, ModelInfo_mark> = new Map();
/**
*
*/
marks_Linkage: Map<MarkType, ModelInfo_mark> = new Map();
/**
*
*/
marks_Inside: Map<MarkType, ModelInfo_mark> = new Map();
/**
*
*/
marks_Tool: Map<MarkType, ModelInfo_mark> = new Map();
// /**
// * 根据类型,找到预制体info
// * @param data
// */
// getMarkPrefab(data: MarkData): ModelInfo_mark {
// let map: Map<MarkType, ModelInfo_mark>;
// switch (data.tagPos) {
// case MarkTagPos.Disaster:
// map = this.marks_Disaster;
// break;
// case MarkTagPos.FireFighting:
// map = this.marks_FireFighting;
// break;
// case MarkTagPos.Inside:
// map = this.marks_Inside;
// break;
// case MarkTagPos.Linkage:
// map = this.marks_Linkage;
// break;
// case MarkTagPos.Tool:
// map = this.marks_Tool;
// break;
// }
// if (!map.has(data.type)) {
// let markInfoPrefab = new ModelInfo_mark(data, true);
// map.set(data.type, markInfoPrefab);
// }
// return map.get(data.type);
// }
}

130
src/app/babylon/model/info/mark/mark-plan-info.ts

@ -0,0 +1,130 @@
import { TsTool } from "src/assets/babylon/tool/ts-tool";
import { MarkTagPos, MarkType } from "../../data/mark/mark-data";
import { MarkNodeData, MarkPlanData } from "../../data/mark/mark-plan-data";
import { ModelInfo_mark } from "./model-info-mark";
/**
* ()
*/
export class MarkNodeInfo {
/**
*
*/
belongToPlanData: MarkPlanData;
/**
*
*/
nodeData: MarkNodeData;
/**
*
*/
markInfos: Map<MarkTagPos, ModelInfo_mark[]> = new Map();
currentMarkDataIndex = -1;
constructor(belongToPlanData: MarkPlanData, nodeData: MarkNodeData) {
this.belongToPlanData = belongToPlanData;
this.nodeData = nodeData;
}
/**
*
* @param tagPos
* @param type
* @param id
*/
getMarkInfo(tagPos: MarkTagPos, type: MarkType, id: string) {
let result: ModelInfo_mark = null;
if (this.markInfos.has(tagPos)) {
let array = this.markInfos.get(tagPos);
for (let i = 0; i < array.length; i++) {
if (array[i].markData.key == id) {
result = array[i];
break;
}
}
}
return result;
}
/**
*
* @param markInfo
* @param addToData //新增时,需要添加进数据层
*/
addMarkInfo(markInfo: ModelInfo_mark, addToData: boolean) {
if (!this.markInfos.has(markInfo.markData.tagPos)) {
this.markInfos.set(markInfo.markData.tagPos, []);
}
this.markInfos.get(markInfo.markData.tagPos).push(markInfo);
if (addToData) {
this.nodeData.getCurrentEnvironmentData().addMarkData(markInfo.markData);//修改数据层
}
}
/**
*
* @param markInfo
*/
removeMarkInfo(markInfo: ModelInfo_mark) {
if (this.markInfos.has(markInfo.markData.tagPos)) {
TsTool.arrayRemove(this.markInfos.get(markInfo.markData.tagPos), markInfo);
}
this.nodeData.getCurrentEnvironmentData().removeMarkData(markInfo.markData);
markInfo.dispose();
}
/**
* id
*/
getNextMarkDataId() {
//console.log(this.currentMarkDataIndex, 1);
let environmentData = this.nodeData.getCurrentEnvironmentData();
if (this.currentMarkDataIndex < 0) {
if (this.nodeData != null && environmentData.markDatas.length > 0) {
this.currentMarkDataIndex = Number(environmentData.markDatas[environmentData.markDatas.length - 1].key);
//console.log(this.currentMarkDataIndex, this.nodeData.markDatas[this.nodeData.markDatas.length - 1].key);
}
}
this.currentMarkDataIndex++;
//console.log(this.currentMarkDataIndex, "=====");
return this.currentMarkDataIndex;
}
/**
*
*/
clearAllMarkDataAndInfo() {
let currentEnvironmentData = this.nodeData.getCurrentEnvironmentData();
currentEnvironmentData.markDatas.length = 0;
this.nodeData.environmentData.length = 0;
this.nodeData.environmentData.push(currentEnvironmentData);
this.disposeInfo();
}
/**
*
*/
disposeInfo() {
this.markInfos.forEach((value: ModelInfo_mark[], key: MarkTagPos, map: Map<MarkTagPos, ModelInfo_mark[]>) => {
if (value != null) {
for (let i = 0; i < value.length; i++) {
value[i].dispose();
}
}
});
this.markInfos.clear();
this.currentMarkDataIndex = -1;
}
}

534
src/app/babylon/model/info/mark/model-info-mark.ts

@ -0,0 +1,534 @@
import { AbstractMesh, Color3, EventState, Mesh, MeshBuilder, ParticleSystem, PointerDragBehavior, Vector3 } from "@babylonjs/core";
import { Button } from "@babylonjs/gui/2D/controls/button";
import { Control } from "@babylonjs/gui/2D/controls/control";
import { Ellipse } from "@babylonjs/gui/2D/controls/ellipse";
import { Rectangle } from "@babylonjs/gui/2D/controls/rectangle";
import { TextBlock, TextWrapping } from "@babylonjs/gui/2D/controls/textBlock";
import { Vector2WithInfo } from "@babylonjs/gui/2D/math2D";
import { classToClass } from "class-transformer";
import { ConfigManager } from "src/assets/babylon/controller/config-manager";
import { MarkInfoChangeType, Event_MarkInfoChange } from "src/assets/babylon/controller/event-manager/events/event-mark-info-change";
import { SceneManager } from "src/assets/babylon/controller/scene-manager";
import { UIManager } from "src/assets/babylon/controller/ui-manager";
import { BabylonTool } from "src/assets/babylon/tool/babylon-tool";
import { BabylonUIStyleTool } from "src/assets/babylon/tool/babylon-ui-style-tool";
import { ParticleSystemTool } from "src/assets/babylon/tool/particle-system-tool";
import { TsTool } from "src/assets/babylon/tool/ts-tool";
import { MarkWindow } from "src/assets/babylon/view/mark-window/mark-window";
import { ChildNodeData, MarkData, MarkTask, MarkType } from "../../data/mark/mark-data";
import { BuildingInfo } from "../building/building-info";
import { ModelInfo } from "../model/model-info";
/**
*
*/
export class ModelInfo_mark extends ModelInfo {
/**
*
*/
markData: MarkData;
/**
*
*/
belongToBuilding: BuildingInfo;
/**
*
*/
isSelect: boolean = false;
ui_select: Ellipse;
/**
* mesh
*/
headMesh: Mesh;
uiFollowHead: Rectangle;//头部跟随节点
uiFollowHeadBg: Rectangle;//头部跟随节点的背景
uiNumber: TextBlock;//标号
uiTask: TextBlock;//任务
readonly c_highLightColor = Color3.Green();
readonly c_uiDefaultWidth = 100;//默认UI宽度
/**
*
*/
static readonly c_waterPower_min: number = 5;
/**
*
*/
static readonly c_waterPower_max: number = 30;
constructor(markData: MarkData,
models: AbstractMesh[],
modelBox: AbstractMesh,
belongToBuilding: BuildingInfo,
isNew: boolean) {
super(markData.key, markData, models, modelBox, isNew);
this.belongToBuilding = belongToBuilding;
}
// 根据名字找到子对象数据
public getChildrenDataByName(name: string): ChildNodeData {
const data = this.markData.childrenNodeData.filter(item => item.name === name);
if (data.length > 0) {
return data[0]
} else {
return null;
}
}
onCreate(isNew: boolean) {
this.markData = this.modelData as MarkData;
}
onCreateFollowUI() {
super.onCreateFollowUI();
// console.log("创建跟随UI");
let instance = this;
let modelData = this.modelData as MarkData;
let posType = modelData.tagPos;
// let iconPath = ConfigManager.getMarkIconUrl(posType, modelData.type);
BabylonUIStyleTool.setStyle_size(this.uiFollowRoot, ConfigManager.c_size_facilityIconSize + "px", ConfigManager.c_size_facilityIconSize + "px");
this.uiFollowRoot.thickness = 0;
this.ui_select = new Ellipse("select");
this.uiFollowRoot.addControl(this.ui_select);
this.ui_select.background = BabylonUIStyleTool.c_color_3d_blue;
this.ui_select.thickness = 0;
this.ui_select.width = 0.95;
this.ui_select.height = 0.95;
this.ui_select.shadowColor = BabylonUIStyleTool.c_color_3d_blue;
this.ui_select.shadowBlur = 3;
this.ui_select.isVisible = false;
// this.uiIconBtn = Button.CreateImageButton("iconPath", "", iconPath);
// this.uiIconBtn.thickness = 0;
// this.uiIconBtn.image.width = 0.9;
// this.uiIconBtn.image.height = 0.9;
// this.uiIconBtn.image.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
// this.uiIconBtn.image.verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
// this.uiFollowRoot.addControl(this.uiIconBtn);
// this.uiIconBtn.onPointerClickObservable.add(() => {
// instance.onStopLongPress(null, null);
// });
this.uiFollowRoot.zIndex = BabylonUIStyleTool.c_zIndex_facilityIcon;
this.markData = this.modelData as MarkData;
if (this.markData.property != null && this.markData.property.taskType != MarkTask.None) {
this.headMesh = MeshBuilder.CreateBox("headMesh", { size: 0.001 });
this.headMesh.position = this.modelBox.absolutePosition.add(new Vector3(0, this.modelBox.scaling.y * 0.5, 0)).add(new Vector3(0, 0.5, 0));
this.headMesh.setParent(this.modelBox);
this.uiFollowHead = Button.CreateSimpleButton('followHead_' + this.key, "");
UIManager.Instance.uiRoot.addControl(this.uiFollowHead);
this.uiFollowHead.width = this.c_uiDefaultWidth + "px";
this.uiFollowHead.height = "50px";
this.uiFollowHead.thickness = 0;
this.uiFollowHead.linkWithMesh(this.headMesh);
this.uiFollowHead.onPointerClickObservable.add(() => {
MarkWindow.instance.selectMarkDataFrom3d(instance, true);
instance.lookAt();
});
this.uiFollowHeadBg = new Rectangle('bg');
this.uiFollowHead.addControl(this.uiFollowHeadBg);
this.uiFollowHeadBg.width = 1;
this.uiFollowHeadBg.alpha = 0.7;
this.uiFollowHeadBg.color = BabylonUIStyleTool.c_color_3d_blueLight;
this.uiFollowHeadBg.background = BabylonUIStyleTool.c_color_3d_blueBg;
this.uiNumber = new TextBlock(this.modelData.key + "-num", this.markData.property.getInstitutionNum());
this.uiFollowHead.addControl(this.uiNumber);
this.uiNumber.width = 1;
this.uiNumber.height = 0.5;
this.uiNumber.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
this.uiNumber.color = "white";
this.uiNumber.shadowBlur = 2;
this.uiNumber.textWrapping = TextWrapping.Clip;
this.uiNumber.resizeToFit = true;
this.uiTask = new TextBlock(this.modelData.key + "-task", this.markData.property.task);
this.uiFollowHead.addControl(this.uiTask);
this.uiTask.width = 1;
this.uiTask.height = 0.5;
this.uiTask.verticalAlignment = Control.VERTICAL_ALIGNMENT_BOTTOM
this.uiTask.color = BabylonUIStyleTool.c_color_3d_blue;
this.uiTask.shadowBlur = 1;
this.uiTask.textWrapping = TextWrapping.Clip;
this.uiTask.resizeToFit = true;
this.updateProperty();
}
}
//终止长按
onStopLongPress(eventData: Vector2WithInfo, eventState: EventState) {
// this.onClickMeshIconBtn(eventData,eventState);
MarkWindow.instance.selectMarkDataFrom3d(this, true);
}
/**
*
* @param select
*/
onSelect(select: boolean) {
this.isSelect = select;
// this.lookAt();
if (select) {
SceneManager.Instance.addToHighLight(this.modelBox as Mesh, this.c_highLightColor);
if (this.pointerDragBehavior == null) {
this.pointerDragBehavior = new PointerDragBehavior({ dragPlaneNormal: Vector3.Up() }); //平面内移动
this.modelBox.addBehavior(this.pointerDragBehavior);
this.pointerDragBehavior.onDragEndObservable.add((event) => {
// instance.modelData.transformData.position = instance.modelBox.position;
})
}
else {
//this.pointerDragBehavior.enabled = true;
}
// SceneManager.Instance.defaultCamera.target = this.modelBox.absolutePosition.clone()
// SceneManager.Instance.defaultCamera.setTarget(this.modelBox.absolutePosition.clone());
}
else {
SceneManager.Instance.removeFromHighLight(this.modelBox as Mesh)
if (this.pointerDragBehavior != null) {
//this.pointerDragBehavior.enabled = false; //停止拖拽
}
}
let eventType: MarkInfoChangeType = select ? MarkInfoChangeType.Select : MarkInfoChangeType.UnSelect;
Event_MarkInfoChange.dispatch(eventType, this);
}
/**
*
*/
lookAt() {
BabylonTool.changeCameraTarget(SceneManager.Instance.defaultCamera, this.modelBox, true, null);
}
/**
*
*/
updateProperty() {
if (this.markData.property.taskType != MarkTask.None) {
this.uiNumber.text = this.markData.property.getInstitutionNum();
this.uiTask.text = this.markData.property.task;
let instance = this;
setTimeout(() => {
if (instance.uiNumber == null) {
return;
}
let numWidth = instance.uiNumber.widthInPixels;
let taskWidth = instance.uiTask.widthInPixels;
let maxWidth = Math.max(numWidth, taskWidth, this.c_uiDefaultWidth);
instance.uiFollowHead.widthInPixels = maxWidth;
// instance.uiFollowHeadBg.widthInPixels = maxWidth;
}, (50));
if (this.taskNeedWaterParticle()) {
this.sprinklingWater(true);
}
else {
this.sprinklingWater(false);
}
}
}
/**
* ui
*/
disposeProperty() {
if (this.uiNumber != null) {
this.uiNumber.dispose();
this.uiNumber = null;
}
if (this.uiTask != null) {
this.uiTask.dispose();
this.uiTask = null;
}
if (this.uiFollowHead != null) {
this.uiFollowHead.dispose();
this.uiFollowHead = null;
}
}
/**
*
*/
clone(markData?: MarkData, isNew: boolean = true): ModelInfo_mark {
let l_markData: MarkData = null;
if (markData == null) {
l_markData = classToClass(this.modelData) as MarkData;
}
else {
l_markData = markData;
}
let childMeshes = null;
let modelBox = null;
modelBox = BabylonTool.cloneMesh(this.modelBox as Mesh, null, (childMesh: AbstractMesh[]) => {
childMeshes = childMesh;
});
modelBox.name = markData.key;
let info = new ModelInfo_mark(l_markData, childMeshes, modelBox, null, isNew);
this.cloneAnimTo(info);
return info;
}
/**
* UI
* @param show
*/
showFollowUI(show: boolean) {
super.showFollowUI(show);
if (this.uiFollowHead != null) {
this.uiFollowHead.isVisible = show;
}
}
dispose() {
SceneManager.Instance.removeFromHighLight(this.modelBox as Mesh);
this.disposeProperty();
super.dispose();
}
//#region 喷水
/**
*
*/
static readonly c_taskPenShui: string[] = ["喷水", "冷却", "灭火", "控火"];
/**
*
*/
particle_water: ParticleSystem;
/**
*
*/
node_pt: Mesh;
/**
*
*/
node_pz: Mesh;
/**
*
*/
isSprinkling: boolean;
/**
*
*/
canSprinkling() {
let result = false;
switch (this.markData.type) {
case MarkType.MHF:
case MarkType.JYF:
case MarkType.GRF:
case MarkType.FHF:
case MarkType.BHF:
result = true;
//五种消防员
if (this.node_pt == null && this.models != null) {
this.node_pt = this.getChildrenByName("PT") as Mesh;
// for (let i = 0; i < this.models.length; i++) {
// if (this.models[i].name == "PT") {
// this.node_pt = this.models[i] as Mesh;
// break;
// }
// }
}
break;
case MarkType.SGC:
case MarkType.PMC:
case MarkType.GPC:
case MarkType.GCGSC:
case MarkType.YTC:
//五种消防车
result = true;
break;
case MarkType.SP:
result = true;
break;
default:
break;
}
if (result == true && this.node_pz == null && this.models != null) {
this.node_pz = this.getChildrenByName("PZ") as Mesh;
// let transformNodes = this.modelBox.getChildTransformNodes();
// for (let i = 0; i < transformNodes.length; i++) {
// if (transformNodes[i].name == "PZ") {
// this.node_pz = new Mesh("PZ_1", undefined, transformNodes[i]);
// break;
// }
// }
}
if (this.node_pz == null) {
result = false;
}
else {
this.node_pz.scaling = Vector3.One();
this.node_pz.isVisible = false;
}
return result;
}
/**
*
*/
taskNeedWaterParticle() {
let result: boolean = false;
for (let i = 0; i < ModelInfo_mark.c_taskPenShui.length; i++) {
//包含某些特殊字
if (TsTool.stringContain(this.markData.property.task, ModelInfo_mark.c_taskPenShui[i])) {
result = true;
break;
}
}
return result;
}
/**
*
* @param show
*/
sprinklingWater(show: boolean) {
let canSprinkling = this.canSprinkling();//是否可以喷水
let instance = this;
if (!canSprinkling) {
return;
}
switch (this.markData.type) {
case MarkType.MHF:
case MarkType.JYF:
case MarkType.GRF:
case MarkType.FHF:
case MarkType.BHF:
//消防员,显隐喷枪
if (this.node_pt != null) {
this.node_pt.setEnabled(show);
}
break;
}
if (this.particle_water != null) {
this.playWater(show);
}
else {
//编写特效克隆方案
//加载特效,然后播放
ParticleSystemTool.instance.importParticle(this.markData.type + "_water", MarkWindow.c_water_particlePath, (ps) => {
instance.particle_water = ps;
instance.particle_water.emitter = instance.node_pz;
instance.playWater(show);
})
}
}
/**
*
* @param show
*/
playWater(show: boolean) {
if (this.particle_water == null) {
return;
}
this.isSprinkling = show;
if (show) {
this.changeWaterPower(this.markData.waterPower);
this.particle_water.start();
}
else {
this.particle_water.stop();
}
}
/**
* ,
* @param c_waterPower_min
* @param c_waterPower_max
* @param value
*/
changeWaterPower(value: number): number {
if (!this.isSprinkling) //不在喷水
{
return value;
}
let power = Math.min(value, ModelInfo_mark.c_waterPower_max);
power = Math.max(power, ModelInfo_mark.c_waterPower_min);
if (this.particle_water != null) {
this.particle_water.minEmitPower = power * 0.3;
this.particle_water.maxEmitPower = power;
}
this.markData.waterPower = power;
return power;
}
//#endregion
}

270
src/app/babylon/model/info/mark/other/mark-plan-area-info.ts

@ -0,0 +1,270 @@
import { AbstractMesh, Color3, Material, Mesh, MeshBuilder, PointerDragBehavior, PolygonMeshBuilder, Vector2, Vector3 } from "@babylonjs/core";
import { StandardMaterial } from "@babylonjs/core/Materials/standardMaterial";
import { classToClass, plainToClass } from "class-transformer";
import { SceneManager } from "src/assets/babylon/controller/scene-manager";
import { BabylonTool } from "src/assets/babylon/tool/babylon-tool";
import { MarkWindow } from "src/assets/babylon/view/mark-window/mark-window";
import { MarkData, MarkType } from "../../../data/mark/mark-data";
import { MarkData_Area } from "../../../data/mark/other/mark-data-area";
import { ModelInfo_mark } from "../model-info-mark";
/**
*
*/
export class ModelInfo_mark_area extends ModelInfo_mark {
areaSize = 5;//区域尺寸
material: StandardMaterial;//mesh材质
pointMat: StandardMaterial; //顶点材质
areaPoint: AreaPoint[];
areaMesh: Mesh;
areaDragEvent: PointerDragBehavior;//区域mesh 拖拽行为
onCreate(isNew: boolean) {
super.onCreate(isNew);
this.modelBox.position.y = this.modelBox.position.y + 1;
let data = this.markData as MarkData_Area;
this.pointMat = new StandardMaterial("mat_areaPoint", SceneManager.Instance.scene);
this.pointMat.emissiveColor = Color3.FromHexString("#A9FF00");
this.pointMat.disableLighting = true;
this.pointMat.alpha = 0.87;
let instance = this;
this.areaDragEvent = new PointerDragBehavior({ dragPlaneNormal: Vector3.Up() }); //平面内移动
this.areaDragEvent.moveAttached = false;
this.areaDragEvent.onDragStartObservable.add((eventData) => {
//instance.modelBox.translate(eventData.dragPlaneNormal, eventData.dragDistance);
MarkWindow.instance.selectMarkDataFrom3d(instance, true);
})
this.initMeshPoint(isNew);
this.material = new StandardMaterial("mat_area", SceneManager.Instance.scene);
this.material.emissiveColor = Color3.FromHexString((this.markData as MarkData_Area).color);
this.material.disableLighting = true;
this.material.alpha = 0.87;
this.refreshMesh();
}
getVector2Point(): Vector2[] {
let data = this.markData as MarkData_Area;
let point: Vector2[] = [];
for (let i = 0; i < data.pointData.length; i++) {
let pos = new Vector2(data.pointData[i].x, data.pointData[i].z);
point.push(pos);
}
return point;
}
/**
* mesh
*/
refreshMesh() {
if (this.areaMesh != null) {
this.areaMesh.removeBehavior(this.areaDragEvent);
this.areaMesh.dispose();
SceneManager.Instance.removeFromHighLight(this.areaMesh);
}
let poly_tri = new PolygonMeshBuilder("polytri", this.getVector2Point(), SceneManager.Instance.scene);
this.areaMesh = poly_tri.build(true, 0);
this.areaMesh.setParent(this.modelBox);
this.areaMesh.position = new Vector3(0, 1, 0);
this.areaMesh.material = this.material;
this.areaMesh.addBehavior(this.areaDragEvent);
if (this.isSelect) {
// console.log("选中状态下更新");
SceneManager.Instance.addToHighLight(this.areaMesh, this.c_highLightColor);
}
}
/**
*
* @param index
*/
initMeshPoint(isNew: boolean) {
let data = this.markData as MarkData_Area;
if (isNew) {
switch (data.type) {
case MarkType.JJQ: data.pointData = this.getDefaultPoint_4();
break;
case MarkType.QYSDA: data.pointData = this.getDefaultPoint_6();
break;
case MarkType.QYSDB: data.pointData = this.getDefaultPoint_8();
}
}
else {
data.pointData = plainToClass(Vector3, data.pointData);
}
this.areaPoint = [];
for (let i = 0; i < data.pointData.length; i++) {
let newPoint = new AreaPoint(data.pointData[i], this.pointMat, this);
this.areaPoint.push(newPoint);
}
}
/**
*
* @param show
*/
showMeshPoint(show: boolean) {
}
//清空顶点
clearMeshPoint() {
for (let i = 0; i < this.areaPoint.length; i++) {
this.areaPoint[i].dispose();
}
this.areaPoint = [];
}
/**
* 4
* @param center
*/
getDefaultPoint_4() {
let l_xy = this.areaSize;
let result = [new Vector3(l_xy, 0, l_xy), new Vector3(l_xy, 0, -l_xy), new Vector3(-l_xy, 0, -l_xy), new Vector3(-l_xy, 0, l_xy)];
return result;
}
/**
* 6
* @param center
*/
getDefaultPoint_6() {
let sin60 = Math.sin(Math.PI / 3) * this.areaSize;
let sin30 = 0.5 * this.areaSize;
let l_size = this.areaSize;
let result = [new Vector3(0, 0, l_size), new Vector3(sin60, 0, sin30), new Vector3(sin60, 0, -sin30), new Vector3(0, 0, -l_size), new Vector3(-sin60, 0, -sin30), new Vector3(-sin60, 0, sin30)];
return result;
}
/**
* 8
* @param center
*/
getDefaultPoint_8() {
let sin45 = Math.sin(Math.PI * 0.25) * this.areaSize;
let l_size = this.areaSize;
let result = [new Vector3(0, 0, l_size), new Vector3(sin45, 0, sin45), new Vector3(l_size, 0, 0), new Vector3(sin45, 0, -sin45),
new Vector3(0, 0, -l_size), new Vector3(-sin45, 0, -sin45), new Vector3(-l_size, 0, 0), new Vector3(-sin45, 0, sin45)];
return result;
}
/**
*
*/
clone(markData?: MarkData, isNew: boolean = true): ModelInfo_mark_area {
let l_markData: MarkData = null;
if (markData == null) {
l_markData = classToClass(this.modelData) as MarkData;
}
else {
l_markData = markData;
}
let childMeshes = null;
let modelBox = null;
modelBox = BabylonTool.cloneMesh(this.modelBox as Mesh, null, (childMesh: AbstractMesh[]) => {
childMeshes = childMesh;
});
let info = new ModelInfo_mark_area(l_markData, childMeshes, modelBox, null, isNew);
this.cloneAnimTo(info);
return info;
}
dispose() {
this.areaMesh.dispose();
this.material.dispose();
this.pointMat.dispose();
this.clearMeshPoint();
super.dispose();
}
}
/**
*
*/
export class AreaPoint {
parent: ModelInfo_mark_area;
mesh: Mesh;
pos: Vector3;
pointerDragBehavior: PointerDragBehavior;//拖拽事件
constructor(pos: Vector3, material: Material, parent: ModelInfo_mark_area) {
this.pos = pos;
this.parent = parent;
this.mesh = MeshBuilder.CreateSphere("AreaPoint", { segments: 4, diameter: 3 });
this.mesh.material = material;
this.mesh.setParent(parent.modelBox);
this.mesh.position = pos;
this.initDragEvent();
}
initDragEvent() {
let instance = this;
this.pointerDragBehavior = new PointerDragBehavior({ dragPlaneNormal: Vector3.Up() }); //平面内移动
this.mesh.addBehavior(this.pointerDragBehavior);
this.pointerDragBehavior.onDragStartObservable.add(() => {
instance.parent.setDragEventEnable(false);
})
this.pointerDragBehavior.onDragObservable.add(() => {
instance.parent.refreshMesh();
setTimeout(() => {
instance.parent.refreshMesh();
}, 100);
});
this.pointerDragBehavior.onDragEndObservable.add(() => {
instance.parent.setDragEventEnable(true);
instance.parent.refreshMesh();
})
}
dispose() {
this.mesh.removeBehavior(this.pointerDragBehavior);
this.pointerDragBehavior = null;
this.mesh.dispose();
}
}

182
src/app/babylon/model/info/mark/other/mark-plan-line-info.ts

@ -0,0 +1,182 @@
import { Color3, EventState, Mesh, MeshBuilder, Observer, PointerEventTypes, PointerInfo, Scene, StandardMaterial, Vector3 } from "@babylonjs/core";
import { AbstractMesh } from "@babylonjs/core/Meshes/abstractMesh";
import { classToClass, plainToClass } from "class-transformer";
import { SceneManager } from "src/assets/babylon/controller/scene-manager";
import { BabylonTool } from "src/assets/babylon/tool/babylon-tool";
import { MarkWindow } from "src/assets/babylon/view/mark-window/mark-window";
import { MarkData } from "../../../data/mark/mark-data";
import { MarkData_Line } from "../../../data/mark/other/mark-data-line";
import { ModelInfo_mark } from "../model-info-mark";
/**
* 线
*/
export class ModelInfo_mark_line extends ModelInfo_mark {
lineData: MarkData_Line;
onPointObserver: Observer<PointerInfo>;
lineMesh: Mesh;
mat: StandardMaterial;
onCreate(isNew: boolean) {
let instance = this;
instance.lineData = this.markData as MarkData_Line;
this.mat = new StandardMaterial("mat_areaPoint", SceneManager.Instance.scene);
this.mat.emissiveColor = Color3.FromHexString(this.lineData.color);
this.mat.disableLighting = true;
if (isNew) {
instance.lineData.pointData = [];
instance.lineData.pointData.push(Vector3.Zero());
setTimeout(() => {
instance.onPointObserver = SceneManager.Instance.scene.onPointerObservable.add((eventData: PointerInfo, eventState: EventState) => {
instance.onPointerObservable(eventData, eventState);
}
);
}, 300);
}
else {
instance.lineData.pointData = plainToClass(Vector3, instance.lineData.pointData);
}
instance.updateRender();
}
/**
*
*/
updateRender() {
if (this.lineData.pointData != null && this.lineData.pointData.length > 1) {
this.lineMesh = MeshBuilder.CreateTube("tube", { path: this.lineData.pointData, radius: 0.5, sideOrientation: Mesh.DOUBLESIDE, updatable: true }, SceneManager.Instance.scene);
this.lineMesh.setParent(this.modelBox);
this.lineMesh.position = Vector3.Zero();
this.lineMesh.material = this.mat;
}
}
/**
*
* @param point
*/
addPoint(point: Vector3) {
this.lineData.pointData.push(point.subtract(this.modelBox.absolutePosition));
//更新表现
if (this.lineData.pointData.length == 2) {
this.removeEvent();
this.updateRender();
MarkWindow.instance.selectMarkDataFrom3d(this, true);
}
}
/**
*
*/
removeEvent() {
if (this.onPointObserver != null) {
SceneManager.Instance.scene.onPointerObservable.remove(this.onPointObserver);
this.onPointObserver = null;
}
}
/**
*
*/
cancelCreate() {
if (this.lineData.pointData.length < 2) {
MarkWindow.instance.deleteMarkInfo(this);
}
}
onPointerObservable(eventData: PointerInfo, eventState: EventState) {
let instance = this;
if (MarkWindow.instance.markLineIsBreak < 0) {
instance.cancelCreate();
return;
}
switch (eventData.type) {
case PointerEventTypes.POINTERUP:
if (eventData.event.button == 0) { //左键正常
if (eventData.pickInfo.hit && !SceneManager.s_isPointerDrag) {
console.log("点击添加节点");
instance.addPoint(eventData.pickInfo.pickedPoint);
}
}
else { //右键取消
console.log("按键", eventData.event.button);
instance.cancelCreate();
}
break;
}
}
onSelect(select: boolean) {
super.onSelect(select);
if (select = false) {
this.cancelCreate();
}
}
/**
*
*/
clone(markData?: MarkData, isNew: boolean = true): ModelInfo_mark {
let l_markData: MarkData = null;
if (markData == null) {
l_markData = classToClass(this.modelData) as MarkData;
}
else {
l_markData = markData;
}
let childMeshes = null;
let modelBox = null;
modelBox = BabylonTool.cloneMesh(this.modelBox as Mesh, null, (childMesh: AbstractMesh[]) => {
childMeshes = childMesh;
});
let info = new ModelInfo_mark_line(l_markData, childMeshes, modelBox, null, isNew);
this.cloneAnimTo(info);
return info;
}
dispose() {
if (this.mat != null) {
this.mat.dispose();
}
this.removeEvent();
super.dispose();
}
}

322
src/app/babylon/model/info/mark/other/mark-plan-multi-arrow.ts

@ -0,0 +1,322 @@
import { Color3, MeshBuilder, Quaternion, Space, Vector3 } from "@babylonjs/core";
import { PointerEventTypes, PointerInfo } from "@babylonjs/core/Events/pointerEvents";
import { StandardMaterial } from "@babylonjs/core/Materials/standardMaterial";
import { AbstractMesh } from "@babylonjs/core/Meshes/abstractMesh";
import { Mesh } from "@babylonjs/core/Meshes/mesh";
import { EventState, Observer } from "@babylonjs/core/Misc/observable";
import { classToClass, plainToClass } from "class-transformer";
import { SceneManager } from "src/assets/babylon/controller/scene-manager";
import { BabylonTool } from "src/assets/babylon/tool/babylon-tool";
import { MarkWindow } from "src/assets/babylon/view/mark-window/mark-window";
import { MarkData, MarkType } from "../../../data/mark/mark-data";
import { MarkData_multiArrow } from "../../../data/mark/other/mark-data-multi-arrow";
import { ModelInfo_mark } from "../model-info-mark";
/**
*
*/
export class ModelInfo_mark_multiArrow extends ModelInfo_mark {
arrowData: MarkData_multiArrow;
onPointObserver: Observer<PointerInfo>;
arrowInfo: ArrowInfo[] = [];
mat: StandardMaterial;
onCreate(isNew: boolean) {
let instance = this;
instance.arrowData = this.markData as MarkData_multiArrow;
this.mat = new StandardMaterial("mat_multiArrow", SceneManager.Instance.scene);
if (this.arrowData.color == null) {
this.mat.emissiveColor = Color3.Green();
}
else {
this.mat.emissiveColor = Color3.FromHexString(this.arrowData.color);
}
this.mat.disableLighting = true;
if (isNew) {
instance.arrowData.pointData = [];
instance.addPoint(this.modelBox.absolutePosition.clone());
setTimeout(() => {
instance.onPointObserver = SceneManager.Instance.scene.onPointerObservable.add((eventData: PointerInfo, eventState: EventState) => {
instance.onPointerObservable(eventData, eventState);
}
);
}, 300);
}
else {
instance.arrowData.pointData = plainToClass(Vector3, instance.arrowData.pointData);
instance.updateRender();
}
}
/**
*
*/
updateRender() {
if (this.arrowData.pointData != null && this.arrowData.pointData.length > 1) {
// this.lineMesh = MeshBuilder.CreateTube("tube", { path: this.lineData.pointData, radius: this.lineData.radius, sideOrientation: Mesh.DOUBLESIDE, updatable: true }, SceneManager.Instance.scene);
// this.lineMesh.setParent(this.modelBox);
// this.lineMesh.position = Vector3.Zero();
// this.lineMesh.material = this.mat;
for (let i = 1; i < this.arrowData.pointData.length; i++) {
// let newBox = MeshBuilder.CreateBox("box", { size: 1 });
// newBox.setParent(this.modelBox);
// newBox.position = this.arrowData.pointData[i];
let lastPoint = this.arrowData.pointData[i - 1];
let point = this.arrowData.pointData[i];
let newArrow = new ArrowInfo(lastPoint, point, this.mat, this.modelBox as Mesh);
this.arrowInfo.push(newArrow);
}
}
}
/**
*
* @param point
*/
addPoint(point: Vector3) {
let localPos = point.subtract(this.modelBox.absolutePosition);
localPos.y = localPos.y / this.modelBox.scaling.y;
console.log(point, localPos, this.modelBox.absolutePosition);
let startBox = MeshBuilder.CreateBox("start", { size: 1 });
startBox.setParent(this.modelBox);
startBox.position = localPos;
this.arrowData.pointData.push(localPos);
//更新表现
if (this.arrowData.pointData.length > 1) {
// this.updateRender();
let lastPoint = this.arrowData.pointData[this.arrowData.pointData.length - 2];
let newArrow = new ArrowInfo(lastPoint, localPos, this.mat, this.modelBox as Mesh);
this.arrowInfo.push(newArrow);
}
}
/**
*
*/
removeEvent() {
if (this.onPointObserver != null) {
SceneManager.Instance.scene.onPointerObservable.remove(this.onPointObserver);
this.onPointObserver = null;
}
}
/**
*
*/
cancelCreate() {
if (this.arrowData.pointData.length < 2) {
MarkWindow.instance.deleteMarkInfo(this);
}
if (this.arrowData.type == MarkType.JGLX) {
MarkWindow.instance.mulArrowIsBreak_JG = -1;
}
else if (this.arrowData.type == MarkType.CT) {
MarkWindow.instance.mulArrowIsBreak_CT = -1;
}
}
onPointerObservable(eventData: PointerInfo, eventState: EventState) {
let instance = this;
if (this.arrowData.type == MarkType.JGLX && MarkWindow.instance.mulArrowIsBreak_JG < 0) {
instance.cancelCreate();
instance.removeEvent();
return;
}
else if (this.arrowData.type == MarkType.CT && MarkWindow.instance.mulArrowIsBreak_CT < 0) {
instance.cancelCreate();
instance.removeEvent();
return;
}
switch (eventData.type) {
case PointerEventTypes.POINTERUP:
if (eventData.event.button == 0) { //左键正常
if (eventData.pickInfo.hit && !SceneManager.s_isPointerDrag) {
instance.addPoint(eventData.pickInfo.pickedPoint);
}
}
else if (eventData.event.button == 2) { //右键取消
instance.cancelCreate();
instance.removeEvent();
}
break;
}
}
onSelect(select: boolean) {
super.onSelect(select);
if (select = false) {
this.cancelCreate();
}
}
/**
*
*/
clone(markData?: MarkData, isNew: boolean = true): ModelInfo_mark {
let l_markData: MarkData = null;
if (markData == null) {
l_markData = classToClass(this.modelData) as MarkData;
}
else {
l_markData = markData;
}
let childMeshes = null;
let modelBox = null;
modelBox = BabylonTool.cloneMesh(this.modelBox as Mesh, null, (childMesh: AbstractMesh[]) => {
childMeshes = childMesh;
});
let info = new ModelInfo_mark_multiArrow(l_markData, childMeshes, modelBox, null, isNew);
this.cloneAnimTo(info);
return info;
}
dispose() {
if (this.mat != null) {
this.mat.dispose();
}
this.removeEvent();
super.dispose();
}
}
/**
*
* meshmesh会跟随父节点释放
*/
class ArrowInfo {
static s_step = 3;//箭头间隔(从头到下一个的头)
lastArrowInfo: ArrowInfo;//上一个箭头
parent: Mesh;
mesh: Mesh[] = [];
point: Vector3[];
start: Vector3;
end: Vector3;
forward: Vector3;
endlocalY: number; //局部的Y做坐标,末尾
mat: StandardMaterial;
constructor(start: Vector3, end: Vector3, mat: StandardMaterial, parent: Mesh) {
this.start = start;
this.end = end;
this.forward = end.subtract(start).normalize();
this.mat = mat;
this.parent = parent;
this.createMesh();
}
createMesh() {
//let distance = Vector3.Distance(this.start, this.end);
//console.log(distance);
let distance = Vector3.Distance(new Vector3(this.start.x, 0, this.start.z), new Vector3(this.end.x, 0, this.end.z));
let yStep = (this.start.y - this.end.y) / (distance / ArrowInfo.s_step);
let index = 0;
while (distance > ArrowInfo.s_step) {
let offset = index * ArrowInfo.s_step;
let forwardDistance = this.forward.multiplyByFloats(1, 0, 1).normalize().multiplyByFloats(offset, offset, offset);
let meshStart: Vector3 = this.start.add(forwardDistance);
let posArray = [];
posArray.push(new Vector3(0, 0, 2));
posArray.push(new Vector3(-1, 0, 1));
posArray.push(new Vector3(-0.5, 0, 1));
posArray.push(new Vector3(-0.5, 0, 0));
posArray.push(new Vector3(0.5, 0, 0));
posArray.push(new Vector3(0.5, 0, 1));
posArray.push(new Vector3(1, 0, 1));
let l_mesh = MeshBuilder.ExtrudePolygon("arrow", { shape: posArray, depth: 1, updatable: false }, SceneManager.Instance.scene);
l_mesh.material = this.mat;
l_mesh.setParent(this.parent);
this.endlocalY = (0.5) / this.parent.scaling.y - index * yStep;//0.5 - index * yStep
//l_mesh.position = new Vector3(0, (0.5 - index * yStep) / this.parent.scaling.y, 0).add(meshStart);
l_mesh.position = new Vector3(0, this.endlocalY, 0).add(meshStart);
// l_mesh.setParent(null)
// setTimeout(() => {
l_mesh.lookAt(this.end.add(this.parent.absolutePosition), undefined, undefined, undefined, Space.WORLD);
l_mesh.rotation.x = 0;
l_mesh.rotation.z = 0;
// }, (50));
// l_mesh.rotation.x = 0;
// l_mesh.rotation.z = 0;
// l_mesh.setParent(this.parent);
//l_mesh.rotationQuaternion = Quaternion.FromEulerVector(Vector3.Zero());
// let angle = Vector3.GetAngleBetweenVectors(l_mesh.forward, this.forward, Vector3.Up());
// l_mesh.rotation.y = 180 / Math.PI * angle;
this.mesh.push(l_mesh);
distance -= ArrowInfo.s_step;
index++;
}
}
}

184
src/app/babylon/model/info/mark/other/mark-plan-multi-line-info.ts

@ -0,0 +1,184 @@
import { Color3, MeshBuilder, Vector3 } from "@babylonjs/core";
import { PointerEventTypes, PointerInfo } from "@babylonjs/core/Events/pointerEvents";
import { StandardMaterial } from "@babylonjs/core/Materials/standardMaterial";
import { AbstractMesh } from "@babylonjs/core/Meshes/abstractMesh";
import { Mesh } from "@babylonjs/core/Meshes/mesh";
import { EventState, Observer } from "@babylonjs/core/Misc/observable";
import { classToClass, plainToClass } from "class-transformer";
import { SceneManager } from "src/assets/babylon/controller/scene-manager";
import { BabylonTool } from "src/assets/babylon/tool/babylon-tool";
import { MarkWindow } from "src/assets/babylon/view/mark-window/mark-window";
import { MarkData } from "../../../data/mark/mark-data";
import { MarkData_multiLine } from "../../../data/mark/other/mark-data-multi-line";
import { ModelInfo_mark } from "../model-info-mark";
/**
* 线
*/
export class ModelInfo_mark_multiLine extends ModelInfo_mark {
lineData: MarkData_multiLine;
onPointObserver: Observer<PointerInfo>;
lineMesh: Mesh;
mat: StandardMaterial;
onCreate(isNew: boolean) {
let instance = this;
instance.lineData = this.markData as MarkData_multiLine;
this.mat = new StandardMaterial("mat_multiLine", SceneManager.Instance.scene);
this.mat.emissiveColor = Color3.FromHexString(this.lineData.color);
this.mat.disableLighting = true;
if (isNew) {
instance.lineData.pointData = [];
instance.addPoint(this.modelBox.absolutePosition.clone());
setTimeout(() => {
instance.onPointObserver = SceneManager.Instance.scene.onPointerObservable.add((eventData: PointerInfo, eventState: EventState) => {
instance.onPointerObservable(eventData, eventState);
}
);
}, 300);
}
else {
instance.lineData.pointData = plainToClass(Vector3, instance.lineData.pointData);
}
instance.updateRender();
}
/**
*
*/
updateRender() {
if (this.lineData.pointData != null && this.lineData.pointData.length > 1) {
this.lineMesh = MeshBuilder.CreateTube("tube", { path: this.lineData.pointData, radius: this.lineData.radius, sideOrientation: Mesh.DOUBLESIDE, updatable: true }, SceneManager.Instance.scene);
this.lineMesh.setParent(this.modelBox);
this.lineMesh.position = Vector3.Zero();
this.lineMesh.material = this.mat;
}
}
/**
*
* @param point
*/
addPoint(point: Vector3) {
point.y = point.y + this.lineData.yPos;
this.lineData.pointData.push(point.subtract(this.modelBox.absolutePosition));
//更新表现
if (this.lineData.pointData.length > 1) {
this.updateRender();
}
}
/**
*
*/
removeEvent() {
if (this.onPointObserver != null) {
SceneManager.Instance.scene.onPointerObservable.remove(this.onPointObserver);
this.onPointObserver = null;
}
}
/**
*
*/
cancelCreate() {
if (this.lineData.pointData.length < 2) {
MarkWindow.instance.deleteMarkInfo(this);
}
MarkWindow.instance.mulLineIsBreak_SD = -1;
}
onPointerObservable(eventData: PointerInfo, eventState: EventState) {
let instance = this;
if (MarkWindow.instance.mulLineIsBreak_SD < 0) {
instance.cancelCreate();
instance.removeEvent();
return;
}
switch (eventData.type) {
case PointerEventTypes.POINTERUP:
if (eventData.event.button == 0) { //左键正常
if (eventData.pickInfo.hit && !SceneManager.s_isPointerDrag) {
instance.addPoint(eventData.pickInfo.pickedPoint);
}
}
else if (eventData.event.button == 2) { //右键取消
instance.cancelCreate();
instance.removeEvent();
}
break;
}
}
onSelect(select: boolean) {
super.onSelect(select);
if (select = false) {
this.cancelCreate();
}
}
/**
*
*/
clone(markData?: MarkData, isNew: boolean = true): ModelInfo_mark {
let l_markData: MarkData = null;
if (markData == null) {
l_markData = classToClass(this.modelData) as MarkData;
}
else {
l_markData = markData;
}
let childMeshes = null;
let modelBox = null;
modelBox = BabylonTool.cloneMesh(this.modelBox as Mesh, null, (childMesh: AbstractMesh[]) => {
childMeshes = childMesh;
});
let info = new ModelInfo_mark_multiLine(l_markData, childMeshes, modelBox, null, isNew);
this.cloneAnimTo(info);
return info;
}
dispose() {
if (this.mat != null) {
this.mat.dispose();
}
this.removeEvent();
super.dispose();
}
}

148
src/app/babylon/model/info/mark/other/mark-plan-particle-info.ts

@ -0,0 +1,148 @@
import { Mesh, ParticleSystem, ParticleSystemSet, Vector3 } from "@babylonjs/core";
import { AbstractMesh } from "@babylonjs/core/Meshes/abstractMesh";
import { classToClass } from "class-transformer";
import { BabylonTool } from "src/assets/babylon/tool/babylon-tool";
import { ParticleSystemTool } from "src/assets/babylon/tool/particle-system-tool";
import { MarkType, MarkData } from "../../../data/mark/mark-data";
import { ModelInfo_mark } from "../model-info-mark";
export class ModelInfo_mark_particle extends ModelInfo_mark {
/**
*
*/
particleSet: ParticleSystemSet;
/**
*
*/
isPlaying: boolean = true;
onCreate(isNew: boolean) {
super.onCreate(isNew);
let instance = this;
this.particleSet = new ParticleSystemSet();
let particleJsonPath: string[] = [];
let posOffset = Vector3.Zero();
switch (this.markData.type) {
case MarkType.H:
particleJsonPath.push("assets/particlesystem/fire/fire_h_1.json");
particleJsonPath.push("assets/particlesystem/fire/fire_h_2.json");
particleJsonPath.push("assets/particlesystem/fire/fire_h_3.json");
particleJsonPath.push("assets/particlesystem/smoke/smoke_a.json");
instance.modelBox.scaling = new Vector3(300, 300, 300);
posOffset.y = 2.9 / instance.modelBox.scaling.y;
break;
case MarkType.TPH:
particleJsonPath.push("assets/particlesystem/fire/fire_tph_1.json");
particleJsonPath.push("assets/particlesystem/fire/fire_tph_2.json");
particleJsonPath.push("assets/particlesystem/fire/fire_tph_3.json");
particleJsonPath.push("assets/particlesystem/smoke/smoke_b.json");
instance.modelBox.scaling = new Vector3(300, 300, 300);
posOffset.y = 2.9 / instance.modelBox.scaling.y;
break;
case MarkType.SNH:
particleJsonPath.push("assets/particlesystem/fire/fire_snh_1.json");
particleJsonPath.push("assets/particlesystem/fire/fire_snh_2.json");
particleJsonPath.push("assets/particlesystem/fire/fire_snh_3.json");
particleJsonPath.push("assets/particlesystem/smoke/smoke_snh.json");
instance.modelBox.scaling = new Vector3(300, 100, 300);
posOffset.y = 1 / instance.modelBox.scaling.y;
break;
case MarkType.YWA:
particleJsonPath.push("assets/particlesystem/smoke/smoke_a.json");
instance.modelBox.scaling = new Vector3(500, 100, 500);
break;
case MarkType.YWB:
particleJsonPath.push("assets/particlesystem/smoke/smoke_b.json");
instance.modelBox.scaling = new Vector3(300, 600, 300);
break;
case MarkType.YWC:
particleJsonPath.push("assets/particlesystem/smoke/smoke_c.json");
instance.modelBox.scaling = new Vector3(100, 100, 100);
break;
}
let root: AbstractMesh = new AbstractMesh("psRoot");
root.setParent(instance.modelBox);
root.position = Vector3.Zero().add(posOffset);
root.rotationQuaternion = undefined;
root.rotation = Vector3.Zero();
for (let i = 0; i < particleJsonPath.length; i++) {
ParticleSystemTool.instance.importParticle(instance.markData.type.toString(), particleJsonPath[i], (ps: ParticleSystem) => {
// instance.modelBox.scaling = new Vector3(100, 300, 100);
ps.emitter = root;
instance.particleSet.systems.push(ps);
if (instance.isPlaying) {
instance.particleSet.start();
}
})
}
}
play() {
this.isPlaying = true;
if (this.particleSet == null) {
return;
}
this.particleSet.start();
}
stop() {
this.isPlaying = true;
if (this.particleSet == null) {
return;
}
for (let i = 0; i < this.particleSet.systems.length; i++) {
this.particleSet.systems[i].stop();
}
}
/**
*
*/
clone(markData?: MarkData, isNew: boolean = true): ModelInfo_mark {
let l_markData: MarkData = null;
if (markData == null) {
l_markData = classToClass(this.modelData) as MarkData;
}
else {
l_markData = markData;
}
let childMeshes = null;
let modelBox = null;
modelBox = BabylonTool.cloneMesh(this.modelBox as Mesh, null, (childMesh: AbstractMesh[]) => {
childMeshes = childMesh;
});
let info = new ModelInfo_mark_particle(l_markData, childMeshes, modelBox, null, isNew);
this.cloneAnimTo(info);
return info;
}
dispose() {
if (this.particleSet != null) {
this.particleSet.dispose();
}
super.dispose();
}
}

368
src/app/babylon/model/info/model/facilityinfo-tool/facility-area.ts

@ -0,0 +1,368 @@
//#region 区域
import { AbstractMesh, Color3, Mesh, MeshBuilder, Observer, PolygonMeshBuilder, Quaternion, Scene, StandardMaterial, Vector2, Vector3 } from "@babylonjs/core";
import { Button, Vector2WithInfo } from "@babylonjs/gui";
import { ModelInfo_facility } from "../model-info-facility";
import * as earcut from "earcut";
import { ModeManager, ModeType } from "src/assets/babylon/controller/mode-manager";
import { SceneManager } from "src/assets/babylon/controller/scene-manager";
import { UIManager } from "src/assets/babylon/controller/ui-manager";
import { BabylonUIStyleTool } from "src/assets/babylon/tool/babylon-ui-style-tool";
import { GizmoTool } from "src/assets/babylon/tool/gizmo-tool";
import { PosPointTool } from "src/assets/babylon/tool/pos-point-tool";
import { FacilityType, ModelData_facility } from "../../../data/model-data/model-data-facility";
(window as any).earcut = earcut;
// import {earcut} from "earcut";
/**
*
*/
export class AreaInfo {
pointData: Vector3[];//点位
mesh: Mesh;
material: StandardMaterial;
belongToFacility: ModelInfo_facility;
pointMesh: PolygonMeshPoint[] = [];
root: Mesh;
isShow: boolean;
onBeforeRenderObserver: Observer<Scene>;
onGizmoAimMeshObserver: Observer<AbstractMesh>;
/**
*
* @param facilityType
*/
static getAreaColor(facilityType: FacilityType): Color3 {
let result = Color3.Red();
switch (facilityType) {
case FacilityType.FHFQ:
result = Color3.Red();
break;
case FacilityType.JTQ:
result = Color3.Yellow();
break;
case FacilityType.JJQ:
result = Color3.Green();
break;
}
return result;
}
constructor(pointData: Vector3[], facilityInfo: ModelInfo_facility) {
this.belongToFacility = facilityInfo;
this.pointData = pointData;
this.root = MeshBuilder.CreateBox("areaRoot_" + this.belongToFacility.key, { size: 1 });
this.root.isVisible = false;
this.root.setParent(this.belongToFacility.modelBox);
this.root.position = Vector3.Zero();
this.root.rotationQuaternion = new Quaternion();
this.updateMeshPoint();
let poly_tri = new PolygonMeshBuilder("polytri", this.getVector2Point(), SceneManager.Instance.scene);
this.mesh = poly_tri.build(true, 0);
this.mesh.setParent(this.root);
this.mesh.position = Vector3.Zero();
this.mesh.isPickable = false;
this.material = new StandardMaterial("mat_area", SceneManager.Instance.scene);
this.material.emissiveColor = this.getAreaColor();
this.material.disableLighting = true;
this.material.alpha = 0.5;
this.mesh.material = this.material;
let instance = this;
this.onBeforeRenderObserver = SceneManager.Instance.scene.onBeforeRenderObservable.add(() => {
instance.onUpdate();
});
this.onGizmoAimMeshObserver = GizmoTool.onGizmoAimMeshObservable.add((mesh) => {
instance.onChangeGizmo(mesh);
})
//延时更新一下
setTimeout(
function () {
instance.refreshMesh();
},
100);
}
/**
*
*/
getAreaColor() {
let modelData = this.belongToFacility.modelData as ModelData_facility;
let propertyData = modelData.propertyData as any;
if (propertyData.color == undefined) {
propertyData.color = AreaInfo.getAreaColor(modelData.facilityType);
}
else if (!(propertyData.color instanceof Color3)) {
propertyData.color = new Color3(propertyData.color.r, propertyData.color.g, propertyData.color.b);
}
return propertyData.color as Color3;
}
getVector2Point(): Vector2[] {
let point: Vector2[] = [];
for (let i = 0; i < this.pointData.length; i++) {
point.push(new Vector2(this.pointData[i].x, this.pointData[i].z));
}
return point;
}
setEnable(enable: boolean) {
if (this.root != null) {
this.root.setEnabled(enable);
}
}
dispose() {
SceneManager.Instance.scene.onBeforeRenderObservable.remove(this.onBeforeRenderObserver);
this.onBeforeRenderObserver = null;
GizmoTool.onGizmoAimMeshObservable.remove(this.onGizmoAimMeshObserver);
this.onGizmoAimMeshObserver = null;
this.clearMeshPoint();
this.material.dispose();
this.mesh.dispose();
}
onChangeGizmo(mesh: AbstractMesh) {
if (mesh != null) {
this.isShow = mesh == this.belongToFacility.modelBox || this.isPosPointMesh(mesh);
this.isShow = this.isShow && ModeManager.currentMode == ModeType.Edit;
this.showPoint(this.isShow);
}
else {
this.showPoint(false);
}
}
//是否是位点mesh
isPosPointMesh(mesh: AbstractMesh): boolean {
if (mesh == null) {
return false;
}
for (let i = 0; i < this.pointMesh.length; i++) {
if (mesh == this.pointMesh[i].mesh) {
return true;
}
}
return false;
}
showPoint(show: boolean) {
for (let i = 0; i < this.pointMesh.length; i++) {
this.pointMesh[i].showUI(show);
}
}
onUpdate() {
if (!this.isShow) {
return;
}
for (let i = 0; i < this.pointData.length; i++) {
this.pointData[i].y = 0;
}
this.refreshMesh();
}
refreshMesh() {
if (this.mesh != null) {
this.mesh.dispose();
let poly_tri = new PolygonMeshBuilder("polytri", this.getVector2Point(), SceneManager.Instance.scene);
this.mesh = poly_tri.build(true, 0);
this.mesh.setParent(this.root);
this.mesh.position = Vector3.Zero();
this.mesh.isPickable = false;
this.mesh.material = this.material;
}
}
//更新顶点
updateMeshPoint(index = -1) {
this.clearMeshPoint();
let select = null;
for (let i = 0; i < this.pointData.length; i++) {
let l_meshPoint = new PolygonMeshPoint(PosPointTool.c_key + "_" + i, i, 0.2, this.root, this.pointData[i], this);
this.pointMesh.push(l_meshPoint);
if (i == index) {
select = l_meshPoint;
}
}
if (select != null) {
select.changeAim();
}
}
//清空顶点
clearMeshPoint() {
for (let i = 0; i < this.pointMesh.length; i++) {
this.pointMesh[i].dispose();
}
this.pointMesh = [];
}
//加点
addPoint(index: number) {
let newIndex = index;
let pos = Vector3.Zero();
let num = this.pointData.length;
if (newIndex < 1) {
pos = (this.pointData[0].add(this.pointData[num - 1])).multiplyByFloats(0.5, 0.5, 0.5);
this.pointData.push(pos);
this.updateMeshPoint(num);
}
else {
pos = (this.pointData[index].add(this.pointData[index - 1])).multiplyByFloats(0.5, 0.5, 0.5);
this.pointData.splice(index, 0, pos);
this.updateMeshPoint(index);
}
}
//减点
reducePoint(index: number) {
let num = this.pointData.length;
if (num < 4) {
//ThreeDimensionalHomeComponent.instance.openSnackBar("不能少于3个顶点");
// alert("不能少于3个顶点");
return;
}
this.pointData.splice(index, 1);
let newSelectIndex = index;
if (newSelectIndex <= 0) {
newSelectIndex = 1;
}
this.updateMeshPoint(newSelectIndex);
}
}
//可编辑多边形的mesh
export class PolygonMeshPoint {
area: AreaInfo
mesh: Mesh;
pos: Vector3;
index: number;
uiRoot: Button;
onGizmoAimMeshObservor: Observer<AbstractMesh>;
onPointerClickObservor: Observer<Vector2WithInfo>;
constructor(name: string, index: number, size: number, parent: Mesh, pos: Vector3, area: AreaInfo) {
this.index = index;
this.area = area;
this.initEditUI(name, size, parent, pos);
}
//初始化编辑UI
initEditUI(name: string, size: number, parent: Mesh, pos: Vector3) {
if (ModeManager.currentMode == ModeType.Edit) {
this.mesh = MeshBuilder.CreateBox(name, { size: size });
this.mesh.setParent(parent);
this.mesh.position = pos;
this.mesh.isVisible = false;
let instance = this;
this.uiRoot = Button.CreateSimpleButton("ui_" + name, this.index.toString());
UIManager.Instance.uiRoot.addControl(this.uiRoot);
this.uiRoot.linkWithMesh(this.mesh);
BabylonUIStyleTool.setStyle_size(this.uiRoot, "20px", "20px");
this.uiRoot.background = BabylonUIStyleTool.c_color_blue;
this.uiRoot.color = BabylonUIStyleTool.c_color_white;
this.uiRoot.onPointerClickObservable.add(() => {
instance.changeAim();
});
this.showUI(false);
}
}
//改变序号
changeIndex(newIndex: number) {
this.index = newIndex;
}
//改变选中的目标
changeAim() {
let instance = this;
GizmoTool.changeGizmoAim(instance.mesh);
PosPointTool.attachMesh(instance.mesh as Mesh, instance.pos,
() => {
instance.addPoint();
},
() => {
instance.reducePoint();
}
);
}
dispose() {
if (this.uiRoot != null) {
GizmoTool.onGizmoAimMeshObservable.remove(this.onGizmoAimMeshObservor);
this.uiRoot.onPointerClickObservable.clear();
this.mesh.dispose();
this.uiRoot.dispose();
}
}
//显示或隐藏UI
showUI(show: boolean) {
if (this.uiRoot != null) {
this.uiRoot.isVisible = show;
}
}
//加点
addPoint() {
this.area.addPoint(this.index);
}
//减点
reducePoint() {
this.area.reducePoint(this.index);
}
}
//#endregion

266
src/app/babylon/model/info/model/facilityinfo-tool/facility-gd.ts

@ -0,0 +1,266 @@
//#region 高度
import { AbstractMesh, MeshBuilder, Color3, Vector3, Mesh, Observer, Scene, Vector2 } from "@babylonjs/core";
import { Control, Button } from "@babylonjs/gui";
import { GridMaterial } from "@babylonjs/materials";
import { ModeManager, ModeType } from "src/assets/babylon/controller/mode-manager";
import { SceneManager } from "src/assets/babylon/controller/scene-manager";
import { UIManager } from "src/assets/babylon/controller/ui-manager";
import { BabylonUIStyleTool, UI_LineInfo } from "src/assets/babylon/tool/babylon-ui-style-tool";
import { GizmoTool, TransformUIType } from "src/assets/babylon/tool/gizmo-tool";
import { PropertyData_GD } from "../../../data/institution/facility/property-data/outdoor/property-data-gd";
import { ModelData_facility } from "../../../data/model-data/model-data-facility";
import { ModelInfo_facility } from "../model-info-facility";
/**
*
*/
export class GdInfo {
pointData_start: Vector3;//起位
pointData_end: Vector3;//终点
material: GridMaterial;
belongToFacility: ModelInfo_facility;
myPath: Vector3[] = [];
myTube: Mesh;
gdMeshPoints: GdMeshPoint[] = [];
isShow: boolean;
onGizmoAimMeshObserver: Observer<AbstractMesh>;
updateObserver: Observer<Scene>;
constructor(startPoint: Vector3, endPoint: Vector3, belongToFacility: ModelInfo_facility) {
let instance = this;
this.belongToFacility = belongToFacility;
this.pointData_start = startPoint;
let point_start = new GdMeshPoint(this, this.pointData_start, false);
this.gdMeshPoints.push(point_start);
this.pointData_end = endPoint;
let point_end = new GdMeshPoint(this, this.pointData_end, true);
this.gdMeshPoints.push(point_end);
this.myPath.push(point_start.pos);
this.myPath.push(point_end.pos);
this.updateObserver = SceneManager.Instance.scene.onBeforeRenderObservable.add(() => {
instance.update();
});
this.onGizmoAimMeshObserver = GizmoTool.onGizmoAimMeshObservable.add((mesh) => {
instance.onChangeGizmo(mesh);
})
this.createMesh();
}
createMesh() {
this.myTube = MeshBuilder.CreateTube("tube", { path: this.myPath, radius: 2, sideOrientation: Mesh.DOUBLESIDE, updatable: true }, SceneManager.Instance.scene);
this.myTube.parent = this.belongToFacility.modelBox;
this.myTube.position = Vector3.Zero();
this.material = new GridMaterial("mat_myTube", SceneManager.Instance.scene);
this.material.mainColor = Color3.FromHexString(BabylonUIStyleTool.c_color_3d_blue); // new Color3(0, 0.5, 1)
this.material.lineColor = new Color3(0, 0, 0);
this.myTube.material = this.material;
}
update() {
this.gdMeshPoints[1].mesh.position.x = 0;
this.gdMeshPoints[1].mesh.position.z = 0;
this.myPath[1] = this.gdMeshPoints[1].mesh.position;
this.myTube = MeshBuilder.CreateTube("tube", { path: this.myPath, radius: 2, sideOrientation: Mesh.DOUBLESIDE, updatable: true, instance: this.myTube }, SceneManager.Instance.scene);
let facilityData = this.belongToFacility.modelData as ModelData_facility;
let property = facilityData.propertyData as PropertyData_GD;
this.gdMeshPoints[1].updateInfo(property.info);
}
//释放
dispose() {
SceneManager.Instance.scene.onBeforeRenderObservable.remove(this.updateObserver);
GizmoTool.onGizmoAimMeshObservable.remove(this.onGizmoAimMeshObserver);
this.updateObserver = null;
for (let i = 0; i < this.gdMeshPoints.length; i++) {
this.gdMeshPoints[i].dispose();
}
this.material.dispose();
this.myTube.dispose();
}
onChangeGizmo(mesh: AbstractMesh) {
// if (mesh != null) {
// this.isShow = mesh == this.belongToFacility.modelBox || this.isPosPointMesh(mesh);
// this.setEnable(this.isShow);
// }
// else {
// this.setEnable(false);
// }
}
//是否是位点mesh
isPosPointMesh(mesh: AbstractMesh): boolean {
if (mesh == null) {
return false;
}
for (let i = 0; i < this.gdMeshPoints.length; i++) {
if (mesh == this.gdMeshPoints[i].mesh) {
return true;
}
}
return false;
}
setEnable(show: boolean) {
for (let i = 0; i < this.gdMeshPoints.length; i++) {
this.gdMeshPoints[i].setEnable(show);
}
}
setUIEnable(show: boolean) {
for (let i = 0; i < this.gdMeshPoints.length; i++) {
this.gdMeshPoints[i].showEditUI(show);
}
}
}
/**
* mesh
*/
export class GdMeshPoint {
pos: Vector3;
canSet: boolean;
gdInfo: GdInfo;
uiRoot: Button;
lineInfo: UI_LineInfo;
mesh: Mesh;
constructor(gdInfo: GdInfo, pos: Vector3, canSet: boolean) {
this.pos = pos;
this.canSet = canSet;
if (canSet) {
this.gdInfo = gdInfo;
this.mesh = MeshBuilder.CreateBox(gdInfo.belongToFacility.modelBox.name + "_point", { size: 1 });
this.mesh.setParent(gdInfo.belongToFacility.modelBox);
this.mesh.position = pos;
this.mesh.isVisible = false;
this.initEditUI();
this.lineInfo = BabylonUIStyleTool.createLineInfo(gdInfo.belongToFacility.modelBox.name, this.mesh);
this.showEditUI(false);
}
}
//初始化 编辑UI
initEditUI() {
if (ModeManager.currentMode == ModeType.Edit) {
let instance = this;
this.uiRoot = Button.CreateImageButton("ui_editPoint_" + this.gdInfo.belongToFacility.modelBox.name, "", "assets/images/ui/edit.png");
UIManager.Instance.uiRoot.addControl(this.uiRoot);
this.uiRoot.linkWithMesh(this.mesh);
this.uiRoot.linkOffsetYInPixels = 20;
this.uiRoot.linkOffsetXInPixels = -40;
BabylonUIStyleTool.setStyle_size(this.uiRoot, "20px", "20px");
this.uiRoot.image.width = 0.8;
this.uiRoot.image.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
this.uiRoot.image.verticalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
// this.uiRoot.thickness = 0;
this.uiRoot.background = BabylonUIStyleTool.c_color_3d_blueBg;
this.uiRoot.color = BabylonUIStyleTool.c_color_3d_blue;
// this.uiRoot.alpha = 0.7;
this.uiRoot.onPointerClickObservable.add(() => {
instance.changeAim();
});
}
}
//显示或隐藏 编辑UI
showEditUI(show: boolean) {
if (this.uiRoot != null) {
this.uiRoot.isVisible = show && this.canSet;
}
}
//显示、隐藏标识UI
setEnable(show: boolean) {
if (this.lineInfo != null) {
this.lineInfo.setEnable(show);
}
this.showEditUI(show && ModeManager.currentMode == ModeType.Edit);
}
//改变选中的目标
changeAim() {
let instance = this;
GizmoTool.onTransformUITypeChange(TransformUIType.Position);//强行变为position
GizmoTool.changeGizmoAim(instance.mesh, false, true, false);
// PosPointTool.attachMesh(instance.mesh as Mesh, instance.pos,
// () => {
// instance.addPoint();
// },
// () => {
// instance.reducePoint();
// }
// );
//如果需要增加节点,在此拓展
}
dispose() {
if (this.canSet) {
if (this.uiRoot != null) {
this.uiRoot.dispose();
}
GizmoTool.leaveTheGizmoAimMesh(this.mesh);
this.mesh.dispose();
this.lineInfo.dispose();
}
}
/**
*
* @param text
*/
updateInfo(text: string) {
if (this.lineInfo.info != null) {
this.lineInfo.info.text = "高度:" + text;
this.lineInfo.info.resizeToFit = true;
this.lineInfo.infoBg.height = (this.lineInfo.info.heightInPixels + 5) + "px";
}
}
}
//#endregion

231
src/app/babylon/model/info/model/model-info-building.ts

@ -0,0 +1,231 @@
import { Observer, Scene, TransformNode } from "@babylonjs/core";
import { Button, Rectangle } from "@babylonjs/gui";
import { ModelChangeType } from "src/assets/babylon/controller/data-manager";
import { Event_ModelInfoChange } from "src/assets/babylon/controller/event-manager/events/event-modelinfo-change";
import { InfoManager } from "src/assets/babylon/controller/info-manager";
import { ModeManager, ModeType } from "src/assets/babylon/controller/mode-manager";
import { SceneManager } from "src/assets/babylon/controller/scene-manager";
import { BuildingStatus } from "src/assets/babylon/controller/status/building-status";
import { IndoorStatus } from "src/assets/babylon/controller/status/indoor-status";
import { StatusManager } from "src/assets/babylon/controller/status/status-manager";
import { BabylonUIStyleTool } from "src/assets/babylon/tool/babylon-ui-style-tool";
import { GizmoTool } from "src/assets/babylon/tool/gizmo-tool";
import { TsTool } from "src/assets/babylon/tool/ts-tool";
import { BuildingType } from "../../data/institution/building/building-data";
import { ModelInfo_mark } from "../mark/model-info-mark";
import { ModelInfo } from "./model-info";
import { FacilityInfoByType, ModelInfo_facility } from "./model-info-facility";
//建筑类模型信息
export class ModelInfo_building extends ModelInfo {
facilityRoot: TransformNode;
facilityInfos: FacilityInfoByType[] = [];
buildingType: BuildingType = BuildingType.Normal;
neiRoot: TransformNode; //facilityRoot参照的节点
updateObserver: Observer<Scene>;
onSetModelBox() {
super.onSetModelBox();
this.initFacilityRoot();
}
initFacilityRoot() {
let allTransformNode = this.modelBox.getChildTransformNodes();
this.neiRoot = null;
for (let i = 0; i < allTransformNode.length; i++) {
if (TsTool.stringContain(allTransformNode[i].name, "nei")) {
this.neiRoot = allTransformNode[i];
break;
}
}
if (this.neiRoot == null) {
this.neiRoot = this.modelBox;
}
if (this.facilityRoot != null) {
this.facilityRoot.dispose();
}
this.facilityRoot = new TransformNode(this.modelData.key + '_facilityRoot');
let instance = this;
if (this.updateObserver != null) {
SceneManager.Instance.scene.onAfterRenderObservable.remove(this.updateObserver);
}
this.updateObserver = SceneManager.Instance.scene.onAfterRenderObservable.add(function () {
instance.onBeforeRender();
});
}
onClickMeshIconBtn() {
if (StatusManager.s_currentStatus instanceof BuildingStatus) {
StatusManager.s_currentStatus.buildingWindow.changeCurrentBuildingInfo(this);
}
else if (StatusManager.s_currentStatus instanceof IndoorStatus) {
GizmoTool.onPickMeshInfoObservable.notifyObservers(this);
// StatusManager.s_currentStatus.indoorWindow.lookAtCenter(this);
}
}
onCreateFollowUI() {
super.onCreateFollowUI();
this.uiFollowRoot.width = '104px';
this.uiFollowRoot.height = '26px';
this.uiFollowRoot.thickness = 0;
let border = new Rectangle("border");
this.uiFollowRoot.addControl(border);
border.thickness = 0;
border.background = BabylonUIStyleTool.c_color_blue;//"#0CB7F7";
border.alpha = 0.7;
this.uiIconBtn = Button.CreateSimpleButton(
'Btn_' + this.key,
"加载中..."
);
border.addControl(this.uiIconBtn);
this.uiIconBtn.width = '100px';
this.uiIconBtn.height = '22px';
this.uiIconBtn.background = "#415094";
this.uiIconBtn.color = "white";
this.uiIconBtn.thickness = 0;
this.uiIconBtn.textBlock.fontSize = 12;
this.uiIconBtn.shadowBlur = 1;
this.uiFollowRoot.zIndex = BabylonUIStyleTool.c_zIndex_buildingIcon;
}
/**
* UI
* @param show
*/
showFollowUI(show: boolean) {
if (ModeManager.currentMode == ModeType.Look && this.buildingType == BuildingType.Environment) {
super.showFollowUI(false);
}
else {
super.showFollowUI(show);
}
}
/**
* UI
* @param show
*/
showFacilityUI(show: boolean) {
if (this.facilityInfos != null) {
for (let i = 0; i < this.facilityInfos.length; i++) {
let facilityByType = this.facilityInfos[i].facilityInfo;
if (facilityByType != null) {
for (let i = 0; i < facilityByType.length; i++) {
facilityByType[i].setIconEnable(show)
}
}
}
}
}
//更新跟随UI的名称
updateName(name: string) {
this.uiIconBtn.textBlock.text = name;
}
dispose() {
this.disposeAllFacility();
super.dispose();
}
//释放所有设备
disposeAllFacility() {
ModeManager.log('释放室内设备' + this.facilityInfos.length);
for (let i = 0; i < this.facilityInfos.length; i++) {
for (let j = 0; j < this.facilityInfos[i].facilityInfo.length; j++) {
this.removeFacilityInfo(this.facilityInfos[i].facilityInfo[j], false);
}
}
this.facilityInfos = [];
this.facilityRoot.dispose();
}
onBeforeRender() {
// console.log(this.modelBox.absolutePosition);
this.facilityRoot.position = this.neiRoot.absolutePosition.clone();
this.facilityRoot.rotation = this.neiRoot.rotation.clone();
//if (this.modelBox.rotationQuaternion != null) {
this.facilityRoot.rotationQuaternion = this.neiRoot.absoluteRotationQuaternion.clone();
if (this.neiRoot.parent != null && (this.neiRoot.parent as TransformNode).scaling.y < 0) {
this.facilityRoot.scaling.y = -1;
}
//}
}
//设置设备的父节点
setFacilityParent(modelInfo_facility: ModelInfo_facility) {
modelInfo_facility.modelBox.setParent(this.facilityRoot);
}
//设置标绘物的父节点
steMarkParent(modelInfo_mark: ModelInfo_mark) {
modelInfo_mark.modelBox.setParent(this.facilityRoot);
}
//移除设备记录
removeFacilityInfo(modelInfo_facility: ModelInfo_facility, remove: boolean) {
if (remove) {
InfoManager.removeFacilityInfoToTypeList(modelInfo_facility, this.facilityInfos);
}
Event_ModelInfoChange.dispatch(modelInfo_facility, ModelChangeType.Remove);
SceneManager.destroyModel(modelInfo_facility);
}
/**
*
* @param enable true
*/
setEnable(enable: boolean) {
super.setEnable(enable);
this.setFacilityEnable(enable);
}
/**
*
* @param enable
*/
setFacilityEnable(enable: boolean) {
if (this.facilityRoot != null) {
this.facilityRoot.setEnabled(enable);
}
if (this.facilityInfos != null) {
for (let j = 0; j < this.facilityInfos.length; j++) {
for (let k = 0; k < this.facilityInfos[j].facilityInfo.length; k++) {
this.facilityInfos[j].facilityInfo[k].setEnable(enable);
}
}
}
}
}

196
src/app/babylon/model/info/model/model-info-facility.ts

@ -0,0 +1,196 @@
import { AbstractMesh, EventState } from "@babylonjs/core";
import { Button, Control, Ellipse, Rectangle, Vector2WithInfo } from "@babylonjs/gui";
import { ConfigManager } from "src/assets/babylon/controller/config-manager";
import { SceneManager } from "src/assets/babylon/controller/scene-manager";
import { BabylonUIStyleTool } from "src/assets/babylon/tool/babylon-ui-style-tool";
import { FacilityWindow } from "src/assets/babylon/view/facility-window/facility-window";
import { FacilityInfoInSceneWindow } from "src/assets/babylon/view/facilityinfoinscene-window/facilityinfoinscene-window";
import { PropertyBaseWindow } from "src/assets/babylon/view/property-window/property-base-window";
import { ModelData } from "../../data/model-data/model-data";
import { FacilityShowType, FacilityType, ModelData_facility } from "../../data/model-data/model-data-facility";
import { BuildingInfo } from "../building/building-info";
import { AreaInfo } from "./facilityinfo-tool/facility-area";
import { GdInfo } from "./facilityinfo-tool/facility-gd";
import { ModelInfo } from "./model-info";
//设施数据
export class ModelInfo_facility extends ModelInfo {
belongToBuilding: BuildingInfo;//属于哪个建筑
pickDown: boolean;//按下
facilityShowType: FacilityShowType;//设备展示状态
ui_select: Ellipse | Rectangle;
areaInfo: AreaInfo;//区域信息
gdInfo: GdInfo;//高度信息
isNew: boolean;//是否是新建
constructor(
key: string,
modelData: ModelData,
models: AbstractMesh[],
modelBox: AbstractMesh,
belongToBuilding: BuildingInfo,
isNew: boolean
) {
super(key, modelData, models, modelBox);
this.facilityShowType = ModelData_facility.getShowType((modelData as ModelData_facility).facilityType);
this.belongToBuilding = belongToBuilding;
this.isNew = isNew;
}
onCreateFollowUI() {
super.onCreateFollowUI();
let instance = this;
let modelData = this.modelData as ModelData_facility;
let posType = ConfigManager.getPosType(modelData.facilityType);
let iconPath = ConfigManager.getFacilityIconUrl(modelData.facilityType, posType);
BabylonUIStyleTool.setStyle_size(this.uiFollowRoot, ConfigManager.c_size_facilityIconSize + "px", ConfigManager.c_size_facilityIconSize + "px");
this.uiFollowRoot.thickness = 0;
if (modelData.facilityType == FacilityType.AQCK) {
this.ui_select = new Rectangle("select");
}
else {
this.ui_select = new Ellipse("select");
}
this.uiFollowRoot.addControl(this.ui_select);
this.ui_select.background = BabylonUIStyleTool.c_color_3d_blue;
this.ui_select.thickness = 0;
this.ui_select.width = 0.95;
this.ui_select.height = 0.95;
this.ui_select.shadowColor = BabylonUIStyleTool.c_color_3d_blue;
this.ui_select.shadowBlur = 3;
this.ui_select.isVisible = false;
this.uiIconBtn = Button.CreateImageButton("iconPath", "", iconPath);
this.uiIconBtn.thickness = 0;
this.uiIconBtn.image.width = 0.9;
this.uiIconBtn.image.height = 0.9;
this.uiIconBtn.image.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
this.uiIconBtn.image.verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
this.uiFollowRoot.addControl(this.uiIconBtn);
//BabylonUIStyleTool.addLongPressButtonBehave(this.uiIconBtn, SceneManager.Instance.scene, () => {
// instance.askDelete(instance);
// }, () => {
// // instance.onClickMeshIconBtn(null, null);
// instance.onStopLongPress(null, null);
// })
this.uiIconBtn.onPointerClickObservable.add(() => {
instance.onStopLongPress(null, null);
});
//双击,拉近镜头
BabylonUIStyleTool.addDoubleClickButtonBehave(this.uiIconBtn, SceneManager.Instance.scene, () => {
let item = FacilityInfoInSceneWindow.instance.getFacilityItem(instance);
if (item != null) {
item.lookAt();
}
});
this.uiFollowRoot.zIndex = BabylonUIStyleTool.c_zIndex_facilityIcon;
}
//询问删除
askDelete(modelInfo: ModelInfo_facility, ask = true) {
if (ask) {
// ThreeDimensionalHomeComponent.instance.deleteProperty(() => {
// FacilityWindow.instance.disposeFacility(modelInfo);
// }, modelInfo.key);
}
else { //直接删除
FacilityWindow.instance.disposeFacility(modelInfo);
}
}
//终止长按
onStopLongPress(eventData: Vector2WithInfo, eventState: EventState) {
// this.onClickMeshIconBtn(eventData,eventState);
FacilityInfoInSceneWindow.instance.selectFacilityInfo(this);
}
//展示属性
showProperty() {
PropertyBaseWindow.ShowWindow(this);
}
onSetModelBox() {
super.onSetModelBox();
}
setEnable(enable: boolean) {
super.setEnable(enable);
if (this.areaInfo != null) {
this.areaInfo.setEnable(enable);
}
if (this.gdInfo != null) {
this.gdInfo.setEnable(enable);
}
}
/**
*
* @param enable
*/
setSelectEnable(enable: boolean) {
this.ui_select.isVisible = enable;
}
/**
* Icon的显示状态
* @param enable
*/
setIconEnable(enable: boolean) {
this.showFollowUI(enable);
if (this.gdInfo != null) {
this.gdInfo.setUIEnable(enable);
}
if (!enable)//还原选中状态
{
this.setSelectEnable(false);
}
}
dispose() {
if (this.areaInfo != null) {
this.areaInfo.dispose();
}
if (this.gdInfo != null) {
this.gdInfo.dispose();
}
super.dispose();
}
}
//根据类型划分的设备信息
export class FacilityInfoByType {
type: FacilityType;
facilityInfo: ModelInfo_facility[];
constructor(type: FacilityType) {
this.type = type;
this.facilityInfo = [];
}
dispose() {
for (let i = 0; i < this.facilityInfo.length; i++) {
this.facilityInfo[i].dispose();
}
this.facilityInfo = [];
}
}

264
src/app/babylon/model/info/model/model-info.ts

@ -0,0 +1,264 @@
import {
AbstractMesh,
AnimationGroup,
EventState,
GizmoManager,
Mesh,
PointerDragBehavior,
TransformNode,
Node,
Vector3,
} from '@babylonjs/core';
import { Button, Rectangle, Vector2WithInfo } from '@babylonjs/gui';
import { classToClass } from 'class-transformer';
import { UIManager } from 'src/assets/babylon/controller/ui-manager';
import { BabylonTool } from 'src/assets/babylon/tool/babylon-tool';
import { GizmoTool } from 'src/assets/babylon/tool/gizmo-tool';
import { ModelData } from '../../data/model-data/model-data';
//基础模型信息
export class ModelInfo {
key: string;
/**
*
*/
models: AbstractMesh[];
/**
* 使modelBox 访
*/
_modelBox: AbstractMesh;
/**
*
*/
animationGroups: AnimationGroup[];
modelData: ModelData;
uiFollowRoot: Rectangle;
uiIconBtn: Button;
uiDeleteBtn: Button;
modelEnableChangeObserver; //模型enable状态变化监听
isDisposed: boolean = false;//已经被释放了
isEnable: boolean = true;//显示状态
pointerDragBehavior: PointerDragBehavior;//mesh 拖拽行为
//请不要直接new ,而是使用 InfoManager.new
constructor(
key: string,
modelData: ModelData,
models: AbstractMesh[],
modelBox: AbstractMesh,
isNew: boolean = true
) {
this.key = key;
this.models = models;
this.modelData = modelData;
this.modelBox = modelBox;
this.isDisposed = false;
if (this.modelBox != null) {
this.modelBox.name = this.modelData.key;
}
}
// 根据名字找到子对象
public getChildrenByName(name: string): AbstractMesh {
const children = this.models.filter(item => item.name === name);
if (children.length > 0) {
return children[0]
} else {
return null;
}
}
/**
*
*/
get modelBox(): AbstractMesh {
return this._modelBox;
}
/**
*
*/
set modelBox(value: AbstractMesh) {
if (this._modelBox != value && this._modelBox != null) {
this._modelBox.dispose();
}
if (this.isDisposed) {
this.dispose();
return;
}
this._modelBox = value;
if (value != null && this.uiFollowRoot == null) {
this.onCreateFollowUI();
let instance = this;
if (this.uiIconBtn != null) {
this.uiIconBtn.onPointerClickObservable.add(function (eventData, eventState) {
instance.onClickMeshIconBtn(eventData, eventState);
});
}
}
this.onSetModelBox();
if (!this.isEnable) {
this.setEnable(this.isEnable);
}
}
//创建跟随UI
onCreateFollowUI() {
this.uiFollowRoot = new Rectangle('follow_' + this.key);
UIManager.Instance.uiRoot.addControl(this.uiFollowRoot);
}
//展示或隐藏跟随UI
showFollowUI(show: boolean) {
if (this.uiFollowRoot != null) {
this.uiFollowRoot.isVisible = show;
}
}
/**
*
*/
clone(modelData?: ModelData, isNew: boolean = true): ModelInfo {
let l_modelData;
if (modelData == null) {
l_modelData = classToClass(this.modelData);
}
else {
l_modelData = modelData;
}
let childMeshes;
let modelBox = null;
modelBox = BabylonTool.cloneMesh(this.modelBox as Mesh, null, (childMesh: AbstractMesh[]) => {
childMeshes = childMesh;
});
let info = new ModelInfo(this.key, l_modelData, childMeshes, modelBox, isNew);
return info;
}
/**
* mesh上克隆动画给新模型
* @param newInfo
*/
cloneAnimTo(newInfo: ModelInfo) {
if (this.animationGroups != null) {
newInfo.animationGroups = [];
for (let i = 0; i < this.animationGroups.length; i++) {
let prfabAnim = this.animationGroups[i];
let newAnimGroup = prfabAnim.clone(prfabAnim.name, (oldTarget) => {
let newTarget = null;
let allChildren = newInfo.modelBox.getChildren((node) => {
if (oldTarget.name == node.name) {
newTarget = node;
// console.log("找到节点了", node);
return false;
}
else {
return true;
}
}, false);
// console.log("复制动画给新节点", newTarget);
return newTarget;
});
newInfo.animationGroups.push(newAnimGroup);
// console.log("测试播放动画", newAnimGroup);
// newAnimGroup.play();//完善正式逻辑时,注释掉此行
}
}
}
dispose() {
this.isDisposed = true;
this.uiFollowRoot.dispose();
// console.log("释放model" + this.key);
if (this.modelBox != null) {
this.modelBox.dispose();
} else {
this.models[0].dispose();
}
}
//设置模型盒子时
onSetModelBox() {
if (
(this.modelData.transformData.scaling as Vector3).equals(Vector3.Zero())
) {
this.modelData.transformData.originalScaling = this.modelBox.absoluteScaling.clone();
this.modelData.transformData.scaling = this.modelData.transformData.originalScaling.clone();
}
if (this.uiFollowRoot != null) {
this.uiFollowRoot.linkWithMesh(this.modelBox);
this.uiFollowRoot.linkOffsetY = '-50px';
}
}
//改变显示状态
setEnable(enable: boolean) {
this.isEnable = enable;
if (this.modelBox != null) {
this.modelBox.setEnabled(enable);
GizmoTool.leaveTheGizmoAim(this);
}
this.showFollowUI(enable);
}
/**
*
* @param enable
*/
setDragEventEnable(enable: boolean) {
if (this.pointerDragBehavior != null) {
this.pointerDragBehavior.enabled = enable;
}
}
//点击到图标按钮
onClickMeshIconBtn(eventData: Vector2WithInfo, eventState: EventState) {
}
}

534
src/app/babylon/tool/babylon-tool.ts

@ -0,0 +1,534 @@
import {
AbstractMesh,
Animation,
AnimationGroup,
ArcRotateCamera,
Camera,
EasingFunction,
IParticleSystem,
ISceneLoaderPlugin,
ISceneLoaderPluginAsync,
ISceneLoaderProgressEvent,
Mesh,
MeshBuilder,
PBRMaterial,
QuadraticEase,
Quaternion,
Scene,
SceneLoader,
Skeleton,
Vector3,
} from '@babylonjs/core';
import {
AdvancedDynamicTexture,
Button,
Container,
Control,
InputText,
Rectangle,
ScrollViewer,
StackPanel,
TextBlock,
} from '@babylonjs/gui';
import { ConfigManager } from '../controller/config-manager';
import { ModeManager } from '../controller/mode-manager';
import { UIManager } from '../controller/ui-manager';
import { UIBase } from '../view/window-base/ui-base';
import { BabylonUIStyleTool } from './babylon-ui-style-tool';
import { LoadTool } from './load-tool';
import { TsTool } from './ts-tool';
export class BabylonTool {
static readonly c_radian1 = 180 / Math.PI; //1弧度的度数
static readonly c_cloneSuffix = '(Clone)'; //克隆物体的名称后缀
static readonly alpha_N = Math.PI * 0.5;//面朝北时的alpha值 右手坐标系是pi,左手是-pi
//获取世界坐标
static getWorldPosition(mesh: AbstractMesh): Vector3 {
let result = mesh.position;
if (mesh.parent != null) {
result = mesh.absolutePosition;
}
return result.clone();
}
//载入模型
static importMesh(
meshNames: any,
rootUrl: string,
sceneFilename?: string | File,
scene?: Scene,
onSuccess?: (
meshes: AbstractMesh[],
particleSystems: IParticleSystem[],
skeletons: Skeleton[],
animationGroups: AnimationGroup[]
) => void,
onProgress?: (event: ISceneLoaderProgressEvent) => void,
onError?: (scene: Scene, message: string, exception?: any) => void,
pluginExtension?: string
): ISceneLoaderPlugin | ISceneLoaderPluginAsync {
let path = rootUrl; //"institutions/institution001/building001/outdoor/";
if (path == null) {
return null;
}
if (path.indexOf(ConfigManager.c_resPath_assetsRoot) == -1) {
path = ConfigManager.c_resPath_assetsRoot + rootUrl;
}
ModeManager.log("加载模型" + path + sceneFilename);
return SceneLoader.ImportMesh(
meshNames,
path,
sceneFilename,
scene,
onSuccess,
onProgress,
onError,
pluginExtension
);
}
/**
*
* @param meshNames
* @param rootUrl
* @param sceneFilename
* @param scene
* @param tag
* @param onSuccess
* @param onProgress
* @param onError
* @param pluginExtension
*/
static importMeshSync(meshNames: any,
rootUrl: string,
sceneFilename?: string | File,
scene?: Scene,
tag?: string,
onSuccess?: (
meshes: AbstractMesh[],
particleSystems: IParticleSystem[],
skeletons: Skeleton[],
animationGroups: AnimationGroup[]
) => void,
onProgress?: (event: ISceneLoaderProgressEvent) => void,
onError?: (scene: Scene, message: string, exception?: any) => void,
pluginExtension?: string) {
let path = rootUrl; //"institutions/institution001/building001/outdoor/";
if (path == null) {
return null;
}
if (path.indexOf(ConfigManager.c_resPath_assetsRoot) == -1) {
path = ConfigManager.c_resPath_assetsRoot + rootUrl;
}
console.log("异步加载模型" + path + sceneFilename);
let modelPath = path + sceneFilename;
LoadTool.add(modelPath, tag);
SceneLoader.ImportMeshAsync(
meshNames,
path,
sceneFilename,
scene,
onProgress,
).then(function (result) {
LoadTool.remove(modelPath);
onSuccess(result.meshes, result.particleSystems, result.skeletons, result.animationGroups);
}).catch(function (result) {
onError(scene, "load error", result);
});
}
/**
*
*/
static setMatToUnlit(meshes: AbstractMesh[], isUnlit: boolean, mask: string = null) {
if (meshes == null) {
return;
}
for (let i = 0; i < meshes.length; i++) {
if (meshes[i].material instanceof PBRMaterial) {
let mat_pbr = (meshes[i].material as PBRMaterial);
// mat_pbr.metallicF0Factor = 0;//关掉反光
if (mask == null || !TsTool.stringContain(mat_pbr.name, mask)) {
mat_pbr.unlit = isUnlit;
}
}
}
}
/**
*
* @param meshes
* @param enable //是否开启
* @param linkToAlbedo //是否反射环境光颜色
*/
static setMatSheen(meshes: AbstractMesh[], enable: boolean, linkToAlbedo: boolean) {
for (let i = 0; i < meshes.length; i++) {
if (meshes[i].material instanceof PBRMaterial) {
let mat_pbr = (meshes[i].material as PBRMaterial);
if (TsTool.stringContain(mat_pbr.name, "Color")) {
mat_pbr.sheen.isEnabled = enable;
mat_pbr.sheen.linkSheenWithAlbedo = linkToAlbedo;
}
}
}
}
//改变摄像机观察目标
static changeCameraTarget(camera: ArcRotateCamera, mesh: AbstractMesh, animMove: boolean = true, size = null) {
if (mesh == null) {
return;
}
let maxScaleAxis = size;
if (size == null) {
maxScaleAxis = mesh.scaling.x;
}
camera._scene.stopAnimation(camera);
maxScaleAxis = Math.max(maxScaleAxis, mesh.scaling.y);
maxScaleAxis = Math.max(maxScaleAxis, mesh.scaling.z);
maxScaleAxis *= 1.5;
if (BabylonTool.cameraModeIs2D) {
camera.target = BabylonTool.getWorldPosition(mesh);
camera.radius = maxScaleAxis + 5;
camera.alpha = BabylonTool.alpha_N;
camera.beta = 0;
}
else {
if (animMove) {
BabylonTool.AnimMoveCameraTarget(
camera,
60,
BabylonTool.getWorldPosition(mesh),
maxScaleAxis + 5
);
}
else {
let alpha = BabylonTool.alpha_N;
camera.target = BabylonTool.getWorldPosition(mesh).clone();
camera.radius = maxScaleAxis + 50;
camera.alpha = alpha;
camera.beta = 1;
BabylonTool.AnimMoveCameraTarget(
camera,
60,
BabylonTool.getWorldPosition(mesh).clone(),
maxScaleAxis + 5
);
}
}
}
/**
*
* @param camera
*/
static stopAnim(camera: ArcRotateCamera) {
camera._scene.stopAnimation(camera);
}
/**
* - 2d正交状态
*/
static cameraModeIs2D = false;
/**
*
* @param camera
* @param is2D
* @param mesh
*/
static changeCameraMode(camera: ArcRotateCamera, is2D: boolean) {
camera.mode = is2D ? Camera.ORTHOGRAPHIC_CAMERA : Camera.PERSPECTIVE_CAMERA;
BabylonTool.cameraModeIs2D = is2D;
// BabylonTool.AnimMoveCameraTarget(
// camera,
// 60,
// camera.target,
// camera.radius
// );
if (camera._scene.useRightHandedSystem) {
}
camera.alpha = BabylonTool.alpha_N;
camera.beta = 0;
}
//动画移动摄像机target
public static AnimMoveCameraTarget(
camera: ArcRotateCamera,
allFrame: number,
target: Vector3,
radius: number,
) {
//缓动动画
let easingFunction = new QuadraticEase();
easingFunction.setEasingMode(EasingFunction.EASINGMODE_EASEOUT);
//target
let anim_target = new Animation(
'CameraAnim_target',
'target',
60,
Animation.ANIMATIONTYPE_VECTOR3,
Animation.ANIMATIONLOOPMODE_CYCLE
);
let keys_target = [
{ frame: 0, value: camera.target },
{ frame: allFrame, value: target },
];
anim_target.setKeys(keys_target);
anim_target.setEasingFunction(easingFunction);
//radius
let anim_radius = new Animation(
'CameraAnim_radius',
'radius',
60,
Animation.ANIMATIONTYPE_FLOAT,
Animation.ANIMATIONLOOPMODE_CYCLE
);
let keys_radius = [
{ frame: 0, value: camera.radius },
{ frame: allFrame, value: radius },
];
anim_radius.setKeys(keys_radius);
anim_radius.setEasingFunction(easingFunction);
camera.animations = [];
camera.animations.push(anim_target);
camera.animations.push(anim_radius);
camera._scene.beginAnimation(camera, 0, allFrame, false);
// camera.target = target;
// SceneManager.scene.beginAnimation(camera, 0, allFrame, false);
}
//克隆mesh
static cloneMesh(prefab: Mesh, name?: string, onSuccess?: (childMesh: AbstractMesh[], root: AbstractMesh) => void): Mesh {
if (name == null || name == undefined) {
name = prefab.name + BabylonTool.c_cloneSuffix;
}
let prefabActive = prefab.isEnabled(false);
if (prefabActive == false) {
prefab.setEnabled(true);
}
let result = prefab.clone(name);
let childMesh: AbstractMesh[] = [];
//把名字中,因为复制而产生的无用前缀删掉
let allChildren = result.getChildren((node) => {
let names = node.name.split('.');
let newName = names[names.length - 1];
node.name = newName;
if (node instanceof AbstractMesh) {
childMesh.push(node);
}
return true;
}, false);
if (prefabActive == false) {
prefab.setEnabled(false);
}
if (onSuccess) {
onSuccess(childMesh, result);
}
return result;
}
}
//输入提示界面
export class InputHintWindow extends UIBase {
btn_hide: Button; //隐藏按钮
isShow: boolean = true;//是否是显示状态
txt_first: TextBlock;//第一行文字
onInit() {
super.onInit();
let window = this;
let advancedTexture = UIManager.Instance.uiRoot;
let inputInfoBg = new Rectangle('InputHintWindow');
inputInfoBg.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_RIGHT;
inputInfoBg.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
advancedTexture.addControl(inputInfoBg);
this.root = inputInfoBg;
BabylonUIStyleTool.setDefaultStyle_windowRoot(this.root, false);
BabylonUIStyleTool.setStyle_size(this.root, "160px", "100px");
this.root.alpha = 0.8;
let inputInfoRoot = new StackPanel('inputInfoRoot');
inputInfoRoot.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_RIGHT;
inputInfoRoot.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
inputInfoRoot.width = '150px';
inputInfoRoot.height = '100px';
inputInfoRoot.isVertical = true;
inputInfoBg.addControl(inputInfoRoot);
let infoStyle = advancedTexture.createStyle();
infoStyle.fontSize = 15;
let mouseLeft = new TextBlock('mouseLeft', '左键拖动 => 旋转镜头');
mouseLeft.color = 'white';
mouseLeft.height = '30px';
mouseLeft.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
mouseLeft.style = infoStyle;
inputInfoRoot.addControl(mouseLeft);
this.txt_first = mouseLeft;
let mouseRight = new TextBlock('mouseRight', '右键拖动 => 平移镜头');
mouseRight.color = 'white';
mouseRight.height = '30px';
mouseRight.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
mouseRight.style = infoStyle;
inputInfoRoot.addControl(mouseRight);
let mouseCenter = new TextBlock('mouseCenter', '前滑滚轮 => 拉近镜头');
mouseCenter.color = 'white';
mouseCenter.height = '30px';
mouseCenter.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
mouseCenter.style = infoStyle;
inputInfoRoot.addControl(mouseCenter);
this.btn_hide = Button.CreateSimpleButton("btn_hide", "...");
this.root.addControl(this.btn_hide);
this.btn_hide.textBlock.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_RIGHT;
this.btn_hide.textBlock.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
this.btn_hide.textBlock.color = "white";
this.btn_hide.thickness = 0;
this.btn_hide.onPointerClickObservable.add(() => {
console.log("隐藏");
window.setShowStatus(!window.isShow);
});
this.setShowStatus(true);
// setTimeout(() => {
// if (window.isShow) {
// window.setShowStatus(false);
// }
// }, 4000);
}
//设置显示状态
setShowStatus(newStatus: boolean) {
this.isShow = newStatus;
if (newStatus) {
this.root.width = "160px";
this.root.height = "100px";
this.root.alpha = 0.8;
this.txt_first.alpha = 1;
this.btn_hide.textBlock.isVisible = false;
}
else {
this.root.width = "20px";
this.root.height = "20px";
this.root.alpha = 0.5;
this.txt_first.alpha = 0;
this.btn_hide.textBlock.isVisible = true;
}
}
}
//封装的滚动条组件
export class MyScrollView {
name: string;
scrollView: ScrollViewer;
container: StackPanel;
constructor(name: string, parent: Rectangle, isVertical: boolean = true) {
this.name = name;
this.scrollView = new ScrollViewer(name);
parent.addControl(this.scrollView);
this.scrollView.paddingTop = "0px";
this.scrollView.paddingRight = "0px";
this.scrollView.paddingBottom = "0px";
this.scrollView.paddingLeft = "0px";
this.container = new StackPanel("Container");
this.scrollView.addControl(this.container);
this.container.isVertical = isVertical;
this.container.paddingTop = "0px";
this.container.paddingBottom = "0px";
this.container.paddingLeft = "0px";
this.container.paddingRight = "0px";
}
}
//带背景的输入框
export class MyInputText {
name: string;
bg: Rectangle;
inputText: InputText;
constructor(name: string, parent: Container, width: string, height: string) {
this.name = name;
this.bg = new Rectangle(name);
parent.addControl(this.bg);
this.bg.width = width;
this.bg.height = height;
this.inputText = new InputText(name + "_txt");
this.bg.addControl(this.inputText);
this.inputText.width = width;
this.inputText.height = height;
}
}

522
src/app/babylon/tool/babylon-ui-style-tool.ts

@ -0,0 +1,522 @@
import { AbstractMesh, EventState, Scene, setAndStartTimer, Vector2 } from "@babylonjs/core";
import { Button, Container, Control, Ellipse, MultiLine, RadioButton, Rectangle, StackPanel, TextBlock, Vector2WithInfo } from "@babylonjs/gui";
import { ConfigManager } from "../controller/config-manager";
import { SceneManager } from "../controller/scene-manager";
import { UIManager } from "../controller/ui-manager";
import { UIBase } from "../view/window-base/ui-base";
import { MyInputText } from "./babylon-tool";
//babylon UI 风格 工具
export class BabylonUIStyleTool {
static c_color_blue: string = "#0080FF";//普通蓝色,用于选中、确定等正面风格
static c_color_gray: string = "#E8ECF1";//普通灰色,用于取消、后退、输入背景等
static c_color_black: string = "black";//黑色
static c_color_blueBg: string = "#001121";//深蓝,用于长存界面的背景
static c_color_white: string = "white";
static c_color_green = "#439C08";//绿色按钮
static c_color_greenLight = '#00F424';//亮绿色
static c_color_red = "#C14242";//红色按钮,用于删除等危险操作
static c_color_3d_blueLight: string = "#99ECFC";//亮蓝,字
static c_color_3d_blue: string = "#47E0FF";//蓝, 框体
static c_color_3d_blueBg: string = "#122F49";//蓝黑,背景
static c_shadow_blur_button = 2;//按钮的阴影模糊
static c_shadow_blur_window = 20; //界面的阴影模糊
static readonly cornerRadius_window1 = 10;//界面圆角
static readonly cornerRadius_button = 6;//按钮圆角
static c_zIndex_gizmo = 200;//gizmo界面的z
static c_zIndex_topBar = 100;//topbar界面的z
static c_zIndex_buildingIcon = 50;//建筑标志的z
static c_zIndex_facilityIcon = 40;//设备标志的z
//#region 组件
//创建窗口根节点
static createWindoRoot(window: UIBase, name: string, width: string, height: string, isDialog: boolean) {
window.root = new Rectangle(name);
UIManager.Instance.uiRoot.addControl(window.root);
window.root.width = width;
window.root.height = height;
BabylonUIStyleTool.setDefaultStyle_windowRoot(window.root, isDialog);
}
//创建文本输入组件
static createInputText(name: string, parent: Container, width: string, height: string, textColor: string = "black", thickness: number = 0, cornerRadius: number = 6, backgroundColor: string = "#EEF1F5", focuseColor: string = "black", focuseBgColor: string = "#EEF1F5"): MyInputText {
let result = new MyInputText(name, parent, width, height);
result.inputText.color = textColor;
result.inputText.background = backgroundColor;
result.inputText.thickness = thickness;
result.inputText.focusedColor = focuseColor;
result.inputText.focusedBackground = focuseBgColor;
result.bg.cornerRadius = cornerRadius;
result.bg.color = backgroundColor;
result.bg.thickness = thickness;
return result;
}
//创建文本
static createTextBlock(name: string, text: string, width: string, height: string, fontSize: string): TextBlock {
let textBlock = new TextBlock(name, text);
BabylonUIStyleTool.setStyle_size(textBlock, width, height);
textBlock.fontSize = fontSize;
textBlock.color = "black";
return textBlock;
}
//创建统一风格的确定按钮
static createBtn_OK(name: string, text: string, width: string, height: string, fontSize: string): Button {
let result = BabylonUIStyleTool.createBtn(name, text, width, height, fontSize, "white", BabylonUIStyleTool.c_color_blue);
BabylonUIStyleTool.setStyle_Shadow(result, undefined, 1.5);
return result;
}
//创建统一风格的取消按钮
static createBtn_Cancel(name: string, text: string, width: string, height: string, fontSize: string): Button {
let result = BabylonUIStyleTool.createBtn(name, text, width, height, fontSize, "black", BabylonUIStyleTool.c_color_gray);
return result
}
//创建统一风格的删除按钮
static createBtn_Delete(name: string, text: string, width: string, height: string, fontSize: string,): Button {
let result = BabylonUIStyleTool.createBtn(name, text, width, height, fontSize, "white", BabylonUIStyleTool.c_color_red);
return result;
}
//创建按钮
static createBtn(name: string, text: string, width: string, height: string, fontSize: string, textColor: string = "black", bgColor: string = "white", thickness: number = 0, cornerRadius: number = 6): Button {
let result = Button.CreateSimpleButton(name, text);
result.background = bgColor;
result.color = textColor;
result.width = width;
result.height = height;
result.thickness = thickness;
result.cornerRadius = cornerRadius;
result.textBlock.color = textColor;
result.fontSize = fontSize;
return result;
}
//创建选择框
static createRadioButton(name: string, parent: Container, group: string, width: string, height: string, color: string, background: string, info?: string, infoWidth?: string, isChecked = false, callback?: (eventData: boolean, eventState: EventState) => void) {
let root = new StackPanel(name + "Root");
root.isVertical = false
root.width = width;
root.height = height;
parent.addControl(root);
let radioButton = new RadioButton(name);
root.addControl(radioButton);
radioButton.group = group;
BabylonUIStyleTool.setStyle_size(radioButton, height, height);
radioButton.background = background;
radioButton.color = color;
if (callback) {
radioButton.onIsCheckedChangedObservable.add(callback);
}
radioButton.isChecked = isChecked;
let header = new TextBlock(name + "_info", info);
root.addControl(header);
header.height = height;
header.width = width;
header.color = "black";
header.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
return radioButton;
}
/**
* 线UI
* @param key
* @param mesh mesh
* @param size 线
* @param infoSize
*/
static createLineInfo(key: string, mesh: AbstractMesh, size: Vector2 = new Vector2(160, 60), infoSize: Vector2 = new Vector2(120, 20)): UI_LineInfo {
if (size.x < infoSize.x) {
size.x = infoSize.x;
}
if (size.y < infoSize.y) {
size.y = infoSize.y;
}
let lineInfo = new UI_LineInfo(key, mesh, size, infoSize);
return lineInfo;
}
//#endregion
//#region 风格样式
//统一设置窗口根节点风格
static setDefaultStyle_windowRoot(container: Rectangle, isDialog = true, shadow: boolean = true, corner: boolean = true) {
container.thickness = 0;
//弹框
if (isDialog) {
container.color = BabylonUIStyleTool.c_color_white;
container.background = BabylonUIStyleTool.c_color_white;
container.alpha = 1;
container.zIndex = 100;
}
else//长存界面
{
container.color = BabylonUIStyleTool.c_color_blueBg;
container.background = BabylonUIStyleTool.c_color_blueBg;
container.alpha = 0.8;
container.zIndex = 1;
}
//阴影
if (shadow) {
BabylonUIStyleTool.setStyle_Shadow(container, BabylonUIStyleTool.c_color_black, BabylonUIStyleTool.c_shadow_blur_window);
}
//圆角
if (corner) {
container.cornerRadius = BabylonUIStyleTool.cornerRadius_window1;
}
}
//设置尺寸
static setStyle_size(control: Control, width: string, height: string) {
control.width = width;
control.height = height;
}
//设置文本风格
static setStyle_bodyText(text: TextBlock, fontSize: string = "20px", color: string = "#333333", alpha: number = 1) {
text.fontSize = fontSize;
text.color = color;
text.alpha = alpha;
}
//设置对齐方式
//horizontal: Control.HORIZONTAL_ALIGNMENT_CENTER;Control.HORIZONTAL_ALIGNMENT_LEFT;Control.HORIZONTAL_ALIGNMENT_RIGHT;
//vertical: Control.VERTICAL_ALIGNMENT_CENTER ; Control.VERTICAL_ALIGNMENT_LEFT;Control.VERTICAL_ALIGNMENT_RIGHT;
//
static setStyle_Alignment(control: Control, horizontal: number, vertical: number) {
control.horizontalAlignment = horizontal;
control.verticalAlignment = vertical;
}
//设置边距
static setStyle_padding(control: Control, paddingTop?: string, paddingRight?: string, paddingBottom?: string, paddingLeft?: string) {
if (paddingTop != undefined) {
control.paddingTop = paddingTop;
}
if (paddingRight != undefined) {
control.paddingRight = paddingRight;
}
if (paddingBottom != undefined) {
control.paddingBottom = paddingBottom;
}
if (paddingLeft != undefined) {
control.paddingLeft = paddingLeft;
}
}
//设置阴影
static setStyle_Shadow(container: Control, color: string = BabylonUIStyleTool.c_color_black, blur: number = BabylonUIStyleTool.c_shadow_blur_window) {
container.shadowColor = color;
container.shadowBlur = blur;
}
//#endregion
//#region 功能封装
/**
*
* @param button
* @param scene
* @param onEnd
* @param onAbort
*/
static addLongPressButtonBehave(button: Button, scene: Scene, onEnd?: () => void, onAbort?: () => void) {
let pickDown = false;
let size = ConfigManager.c_size_facilityIconSize;
let vector2WithInfo: Vector2WithInfo;
let ellipse: Ellipse;
button.onPointerUpObservable.add((info) => {
if (pickDown) {
pickDown = false;
ellipse.dispose();
console.log("onPointerUpObservable");
vector2WithInfo = info;
}
});
button.onPointerDownObservable.add(() => {
ellipse = new Ellipse("ellipse");
ellipse.width = size + "px";
ellipse.height = size + "px";
ellipse.color = BabylonUIStyleTool.c_color_blue;
button.addControl(ellipse);
console.log("onPointerDownObservable");
pickDown = true;
setAndStartTimer({
timeout: ConfigManager.c_time_longPress,
contextObservable: scene.onBeforeRenderObservable,
breakCondition: () => {
return pickDown == false;
},
onEnded: (data) => {
if (onEnd) {
onEnd();
setTimeout(
function () {
button.onPointerUpObservable.notifyObservers(vector2WithInfo);
//此处存在问题,因为打开了前端页面,导致焦点小时,babylon无法确定鼠标抬起,则下一次的按下操作失效
},
250);
}
},
onAborted: () => {
if (onAbort) {
onAbort();
}
},
onTick: (data) => {
ellipse.thickness = data.completeRate * 0.5 * size * data.completeRate * data.completeRate;
}
})
});
}
/**
*
* @param button
* @param scene
* @param onClick
*/
static addDoubleClickButtonBehave(button: Button, scene: Scene, onClick: () => void) {
if (BabylonUIStyleTool.s_doubleClickHelper == null) {
BabylonUIStyleTool.s_doubleClickHelper = new DoubleClickHelper(scene);
}
button.onPointerClickObservable.add(
(eventData: Vector2WithInfo, eventState: EventState) => {
let buttonID = button.uniqueId.toString();
if (BabylonUIStyleTool.s_doubleClickHelper.isDoubleClick(buttonID)) {
onClick();
}
else {
BabylonUIStyleTool.s_doubleClickHelper.setClickEvent(buttonID);
}
}
);
}
static s_doubleClickHelper: DoubleClickHelper;
//#endregion
}
/**
*
*/
class DoubleClickHelper {
readonly c_timer: number = 200; //双击的时间间隔
scene: Scene;
timer: number;
buttonID: string;
constructor(scene: Scene) {
this.scene = scene;
let instance = this;
this.scene.onBeforeRenderObservable.add(() => {
instance.update()
});
}
update() {
if (this.timer > 0) {
this.timer -= this.scene.deltaTime;
}
}
/**
*
* @param buttonID id
*/
isDoubleClick(buttonID: string) {
if (this.buttonID == buttonID && this.timer > 0) {
return true;
}
else {
return false;
}
}
/**
*
* @param buttonID
*/
setClickEvent(buttonID: string) {
this.buttonID = buttonID;
this.timer = this.c_timer;
}
}
//#region 功能类
export class UI_LineInfo {
key: string;
mesh: AbstractMesh;
root: Rectangle;
root_size: Vector2;
points: Ellipse[] = [];
lineLength: number;
infoBg: Rectangle;
info: TextBlock;
line: MultiLine;
constructor(l_key: string, l_mesh: AbstractMesh, rootSize: Vector2, infoSize: Vector2) {
this.key = l_key;
this.mesh = l_mesh;
this.root = new Rectangle("UI_LineRoot_" + this.key);
UIManager.Instance.uiRoot.addControl(this.root);
this.root.thickness = 0;
this.root_size = rootSize;
BabylonUIStyleTool.setStyle_size(this.root, rootSize.x + "px", rootSize.y + "px");
this.root.linkWithMesh(this.mesh);
this.root.linkOffsetXInPixels = rootSize.x * 0.5;
// this.root.linkOffsetYInPixels = -40;
let point_start = new Ellipse("start");
point_start.width = "5px";
point_start.height = "5px";
this.root.addControl(point_start);
point_start.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
point_start.color = BabylonUIStyleTool.c_color_3d_blue;
point_start.background = BabylonUIStyleTool.c_color_3d_blue;
point_start.shadowColor = BabylonUIStyleTool.c_color_3d_blue;
point_start.shadowBlur = 5;
this.points.push(point_start);
let point_end = new Ellipse("end");
point_end.width = "1px";
point_end.height = "1px";
this.root.addControl(point_end);
point_end.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
point_end.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
this.lineLength = 20;
point_end.left = this.lineLength + "px";
point_end.topInPixels = infoSize.y * 0.5;
this.points.push(point_end);
this.infoBg = new Rectangle("infoBg");
BabylonUIStyleTool.setStyle_size(this.infoBg, infoSize.x + "px", infoSize.y + "px");
this.root.addControl(this.infoBg);
this.infoBg.color = BabylonUIStyleTool.c_color_3d_blue;
this.infoBg.shadowBlur = 5;
this.infoBg.shadowColor = BabylonUIStyleTool.c_color_3d_blue;
this.infoBg.background = BabylonUIStyleTool.c_color_3d_blueBg;
this.infoBg.alpha = 0.7;
this.infoBg.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_RIGHT;
this.infoBg.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
this.info = new TextBlock("info", "info")
this.info.fontSize = 12;
this.infoBg.addControl(this.info);
this.info.color = BabylonUIStyleTool.c_color_3d_blueLight;
let point_infoBgLeft = new Ellipse("infoBgLeft");
this.infoBg.addControl(point_infoBgLeft);
BabylonUIStyleTool.setStyle_size(point_infoBgLeft, "1px", "1px");
point_infoBgLeft.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
point_infoBgLeft.leftInPixels = -1
this.points.push(point_infoBgLeft);
this.line = new MultiLine("ui_line_" + this.key);
for (let i = 0; i < this.points.length; i++) {
this.line.add(this.points[i]);
}
// this.line.add(this.mesh);//起点
// this.line.add(pointL);
// this.line.add(point);
this.line.lineWidth = 1.5;
this.line.color = BabylonUIStyleTool.c_color_3d_blue;
this.line.alpha = 0.7;
this.line.shadowColor = BabylonUIStyleTool.c_color_3d_blue;
this.line.shadowBlur = 5;
UIManager.Instance.uiRoot.addControl(this.line);
}
setEnable(show: boolean) {
this.root.isVisible = show;
this.line.isVisible = show;
}
dispose() {
this.root.dispose();
this.line.dispose();
}
}
//#endregion

9
src/app/babylon/tool/game-object.ts

@ -0,0 +1,9 @@
import { AbstractMesh } from "@babylonjs/core";
export class GameObject {
mesh: AbstractMesh;
components: any[]; //组件
}

615
src/app/babylon/tool/gizmo-tool.ts

@ -0,0 +1,615 @@
import { AbstractMesh, ArcRotateCamera, BoundingBoxGizmo, Color3, EventState, GizmoManager, Mesh, Observable, PickingInfo, PointerEventTypes, PointerInfo, Quaternion, Scene, UtilityLayerRenderer, Vector3 } from "@babylonjs/core";
import { AdvancedDynamicTexture, Button, Container, InputText, Rectangle, StackPanel, TextBlock } from "@babylonjs/gui";
import { ModeManager, ModeType } from "../controller/mode-manager";
import { SceneManager } from "../controller/scene-manager";
import { Game } from "../game";
import { ModelInfo } from "../model/info/model/model-info";
import { UIBase } from "../view/window-base/ui-base";
import { BabylonTool } from "./babylon-tool";
import { BabylonUIStyleTool } from "./babylon-ui-style-tool";
//transform 信息的UI
export enum TransformUIType {
Hide,
Position,
Rotation,
Scale,
}
export class GizmoTool {
static s_gizmoManager: GizmoManager;
static s_boundingBoxGizmo: BoundingBoxGizmo;
static s_needUpdateGizmo: NeedUpdateGizmo; //需要更新的gizmo分量
static s_transformUIInfo: TransformUIInfo;
static s_camera: ArcRotateCamera;
static onPickMeshInfoObservable: Observable<ModelInfo>; //pick事件
static onGizmoAimMeshObservable: Observable<AbstractMesh>;
static s_nowPickAim: ModelInfo;//当前pick的目标
static s_nowPickAim_mesh: AbstractMesh;//当前pick的目标
static s_btn_poisition: Button;
static s_btn_rotation: Button;
static s_btn_scaling: Button;
static init(scene: Scene, uiRoot: AdvancedDynamicTexture, camera: ArcRotateCamera) {
GizmoTool.s_camera = camera;
GizmoTool.s_boundingBoxGizmo = new BoundingBoxGizmo();
GizmoTool.s_boundingBoxGizmo.setColor(new Color3(1, 0.52, 0.07));
GizmoTool.s_boundingBoxGizmo.setEnabledRotationAxis('');
GizmoTool.s_boundingBoxGizmo.setEnabledScaling(false);
GizmoTool.initTransformUI(uiRoot);
GizmoTool.s_needUpdateGizmo = new NeedUpdateGizmo();
GizmoTool.s_gizmoManager = new GizmoManager(scene, undefined);
GizmoTool.s_gizmoManager.positionGizmoEnabled = true;
GizmoTool.s_gizmoManager.rotationGizmoEnabled = true;
GizmoTool.s_gizmoManager.scaleGizmoEnabled = true;
GizmoTool.s_gizmoManager.gizmos.positionGizmo.planarGizmoEnabled = false;
GizmoTool.s_gizmoManager.gizmos.positionGizmo.yPlaneGizmo.isEnabled = true;
GizmoTool.s_gizmoManager.gizmos.positionGizmo.yPlaneGizmo.scaleRatio = 1;
GizmoTool.s_gizmoManager.gizmos.positionGizmo.updateGizmoRotationToMatchAttachedMesh = false;
GizmoTool.s_gizmoManager.usePointerToAttachGizmos = false;
GizmoTool.s_gizmoManager.gizmos.positionGizmo.onDragStartObservable.add(
GizmoTool.onPositionGizmoStart
);
GizmoTool.s_gizmoManager.gizmos.positionGizmo.onDragEndObservable.add(
GizmoTool.onPositionGizmoEnd
);
GizmoTool.s_gizmoManager.gizmos.rotationGizmo.onDragStartObservable.add(
GizmoTool.onRotationGizmoStart
);
GizmoTool.s_gizmoManager.gizmos.rotationGizmo.onDragEndObservable.add(
GizmoTool.onRotationGizmoEnd
);
GizmoTool.s_gizmoManager.gizmos.scaleGizmo.onDragStartObservable.add(
GizmoTool.onScaleGizmoStart
);
GizmoTool.s_gizmoManager.gizmos.scaleGizmo.onDragEndObservable.add(
GizmoTool.onScaleGizmoEnd
);
scene.onPointerObservable.add(GizmoTool.onPointerObservable);
GizmoTool.onGizmoAimMeshObservable = new Observable();
GizmoTool.onPickMeshInfoObservable = new Observable();
GizmoTool.onPickMeshInfoObservable.add(GizmoTool.onChangeGizmoAim);
scene.onBeforeRenderObservable.add(GizmoTool.onBeforeRender);
GizmoTool.onTransformUITypeChange(TransformUIType.Hide);
}
static onBeforeRender(
eventData: Scene,
eventState: EventState
) {
GizmoTool.updateTransformUI();
let speed = 10 / GizmoTool.s_camera.radius;
speed *= 1000;
GizmoTool.s_camera.panningSensibility = speed;//动态修改平移灵敏度
if (SceneManager.Instance.cameraMode_Is2D) {
let camera = SceneManager.Instance.defaultCamera;
camera.beta = 0;
if (camera.beta > 0.2) {
SceneManager.Instance.changeCameraMode(false);
}
else {
//GizmoTool.s_camera.size = GizmoTool.s_camera.radius * 0.01;
//console.log(GizmoTool.s_camera.orthoTop);
let size_width = GizmoTool.s_camera.radius * Game.instance.canvas.width * 0.0008;
let size_height = GizmoTool.s_camera.radius * Game.instance.canvas.height * 0.0008;
camera.orthoTop = size_height;
camera.orthoBottom = - size_height;
camera.orthoLeft = - size_width;
camera.orthoRight = size_width;
}
}
}
//鼠标事件监听
static onPointerObservable(
eventData: PointerInfo,
eventState: EventState
) {
switch (eventData.type) {
case PointerEventTypes.POINTERDOWN:
//console.log("指针按下");
break;
case PointerEventTypes.POINTERUP:
//console.log("指针抬起");
GizmoTool.pickRayTest(eventData.pickInfo);
break;
case PointerEventTypes.POINTERMOVE:
//console.log("指针移动");
break;
}
}
/**
*
* @param modelInfo modelInfo
*/
static replacePick(modelInfo: ModelInfo) {
if (GizmoTool.s_nowPickAim != modelInfo) {
GizmoTool.onChangeGizmoAim(modelInfo);
}
}
//射线检测
static pickRayTest(pickResult: PickingInfo) {
if (!SceneManager.s_isPointerDrag) {
if (pickResult.hit) {
let meshName = pickResult.pickedMesh.name;
// GizmoTool.onPickMeshObservable.notifyObservers(pickResult.pickedMesh);
//GizmoTool.changeGizmoAim(pickResult.pickedMesh);
} else {
//GizmoTool.onPickMeshInfoObservable.notifyObservers(null);
}
}
// console.log("pickRayTest " + pickResult.hit);
}
//改变gizmo目标mesh
static onChangeGizmoAim(modelInfo: ModelInfo) {
let mesh = null;
GizmoTool.s_nowPickAim = modelInfo;
if (modelInfo != null) {
mesh = modelInfo.modelBox;
}
GizmoTool.changeGizmoAim(mesh);
if (ModeManager.currentMode == ModeType.Edit) {
GizmoTool.s_boundingBoxGizmo.attachedMesh = mesh;
}
GizmoTool.s_transformUIInfo.Mesh = mesh;
GizmoTool.s_transformUIInfo.modelInfo = modelInfo;
GizmoTool.updateTransformUI(mesh != null);
}
//改变Gizmo目标
static changeGizmoAim(mesh: AbstractMesh, x: boolean = true, y = true, z = true) {
GizmoTool.s_nowPickAim_mesh = mesh;
GizmoTool.s_gizmoManager.attachToMesh(mesh);
GizmoTool.s_gizmoManager.gizmos.positionGizmo.xGizmo.isEnabled = x;
GizmoTool.s_gizmoManager.gizmos.positionGizmo.yGizmo.isEnabled = y;
GizmoTool.s_gizmoManager.gizmos.positionGizmo.yPlaneGizmo.isEnabled = x && z;
GizmoTool.s_gizmoManager.gizmos.positionGizmo.zGizmo.isEnabled = z;
GizmoTool.onGizmoAimMeshObservable.notifyObservers(mesh);
}
//离开当前目标(如果当前在这个)
static leaveTheGizmoAim(modelInfo: ModelInfo) {
if (GizmoTool.s_nowPickAim != null && GizmoTool.s_nowPickAim == modelInfo) {
GizmoTool.onChangeGizmoAim(null);
}
}
//离开当前目标(如果当前在这个)
static leaveTheGizmoAimMesh(mesh: AbstractMesh) {
if (GizmoTool.s_nowPickAim_mesh != null && GizmoTool.s_nowPickAim_mesh == mesh) {
GizmoTool.onChangeGizmoAim(null);
}
}
//初始化
static initTransformUI(advTexture: AdvancedDynamicTexture) {
let transformUIInfo = new TransformUIInfo();
GizmoTool.s_transformUIInfo = transformUIInfo;
let width = 200;
let height = 150;
let ui_transformUIRoot = new Rectangle('GizmoWindow');
ui_transformUIRoot.width = width + 'px';
ui_transformUIRoot.height = height + 'px';
ui_transformUIRoot.background = UIBase.color_gray;
ui_transformUIRoot.color = '#FFFFFF';
ui_transformUIRoot.alpha = 0.8;
ui_transformUIRoot.horizontalAlignment =
Container.HORIZONTAL_ALIGNMENT_LEFT;
ui_transformUIRoot.verticalAlignment =
Container.VERTICAL_ALIGNMENT_TOP;
ui_transformUIRoot.thickness = 0;
ui_transformUIRoot.cornerRadius = BabylonUIStyleTool.cornerRadius_window1;
ui_transformUIRoot.zIndex = BabylonUIStyleTool.c_zIndex_gizmo;
advTexture.addControl(ui_transformUIRoot);
transformUIInfo.root = ui_transformUIRoot;
let stackPanel = new StackPanel('verticalGroup');
stackPanel.isVertical = true;
stackPanel.width = width + 'px';
stackPanel.height = height + 'px';
ui_transformUIRoot.addControl(stackPanel);
let txt_title = new TextBlock('title', '信息:(x,y,z)');
transformUIInfo.titleText = txt_title;
txt_title.width = width + 'px';
txt_title.height = '45px';
stackPanel.addControl(txt_title);
for (let i = 0; i < 3; i++) {
let l_InputInfo: UIVector3InputInfo = new UIVector3InputInfo();
let postionRoot = new StackPanel('Group' + i);
stackPanel.addControl(postionRoot);
postionRoot.width = width + 'px';
postionRoot.height = height * 0.23 + 'px';
postionRoot.isVertical = false;
let groupName = Button.CreateSimpleButton(
'groupName',
'info:'
);
groupName.width = width * 0.22 + 'px';
groupName.height = height * 0.22 + 'px';
groupName.fontSize = 12;
groupName.background = '#FF8833';
groupName.color = 'white';
groupName.thickness = 0;
groupName.paddingBottom = '2px';
postionRoot.addControl(groupName);
groupName.onPointerClickObservable.add(() => {
switch (i) {
case 0:
transformUIInfo.OnTypeChangeObservable.notifyObservers(
TransformUIType.Position
);
break;
case 1:
transformUIInfo.OnTypeChangeObservable.notifyObservers(
TransformUIType.Rotation
);
break;
case 2:
transformUIInfo.OnTypeChangeObservable.notifyObservers(
TransformUIType.Scale
);
break;
}
});
switch (i) {
case 0:
transformUIInfo.position = l_InputInfo;
postionRoot.name = 'transform';
groupName.textBlock.text = '位置:';
GizmoTool.s_btn_poisition = groupName;
break;
case 1:
transformUIInfo.rotation = l_InputInfo;
postionRoot.name = 'rotation';
groupName.textBlock.text = '旋转:';
GizmoTool.s_btn_rotation = groupName;
break;
case 2:
transformUIInfo.scale = l_InputInfo;
postionRoot.name = 'scale';
groupName.textBlock.text = '缩放:';
GizmoTool.s_btn_scaling = groupName;
break;
}
for (let j = 0; j < 3; j++) {
let xyz = new InputText('xyz', '12');
xyz.width = width * 0.25 + 'px';
xyz.height = height * 0.22 + 'px';
xyz.color = 'white';
xyz.alpha = 0.8;
xyz.margin = '5px';
xyz.fontSize = 13;
xyz.thickness = 0.1;
xyz.paddingLeft = '0.1px';
xyz.paddingBottom = '2px';
switch (i) {
case 0:
xyz.onTextChangedObservable.add(GizmoTool.onGizmoUIInput_Position);
break;
case 1:
xyz.onTextChangedObservable.add(GizmoTool.onGizmoUIInput_Rotation);
break;
case 2:
xyz.onTextChangedObservable.add(GizmoTool.onGizmoUIInput_Scale);
break;
}
switch (j) {
case 0:
l_InputInfo.x = xyz;
xyz.name = 'x';
xyz.background = '#C20000';
break;
case 1:
l_InputInfo.y = xyz;
xyz.name = 'y';
xyz.background = '#00820F';
break;
case 2:
l_InputInfo.z = xyz;
xyz.name = 'z';
xyz.background = '#0047C2';
break;
}
postionRoot.addControl(xyz);
}
}
transformUIInfo.OnTypeChangeObservable.add(
GizmoTool.onTransformUITypeChange
);
}
static onPositionGizmoStart() {
GizmoTool.s_needUpdateGizmo.position = true;
}
static onPositionGizmoEnd() {
GizmoTool.s_needUpdateGizmo.position = false;
}
static onRotationGizmoStart() {
GizmoTool.s_needUpdateGizmo.rotation = true;
}
static onRotationGizmoEnd() {
GizmoTool.s_needUpdateGizmo.rotation = false;
}
static onScaleGizmoStart() {
GizmoTool.s_needUpdateGizmo.scale = true;
}
static onScaleGizmoEnd() {
GizmoTool.s_needUpdateGizmo.scale = false;
}
static currentGizmoType: TransformUIType = TransformUIType.Position;
//操作的类型发生变化: 隐藏、position、rotation、scale
static onTransformUITypeChange(uiType: TransformUIType) {
// console.log("改变type" + uiType);
let transformUIInfo = GizmoTool.s_transformUIInfo;
// if (uiType == TransformUIType.Hide) {
// transformUIInfo.root.isVisible = false;
// } else {
// transformUIInfo.root.isVisible = true;
// }
transformUIInfo.root.isVisible = ModeManager.isDebug;//先隐藏,因为效果图中没有
let isEditMode = ModeManager.currentMode == ModeType.Edit;
let isPosition = uiType == TransformUIType.Position && isEditMode;
GizmoTool.s_btn_poisition.background = isPosition
? UIBase.color_yellow
: UIBase.color_null;
GizmoTool.s_gizmoManager.positionGizmoEnabled = isPosition;
let isRotation = uiType == TransformUIType.Rotation && isEditMode;
GizmoTool.s_btn_rotation.background = isRotation
? UIBase.color_yellow
: UIBase.color_null;
GizmoTool.s_gizmoManager.rotationGizmoEnabled = isRotation;
let isScaling = uiType == TransformUIType.Scale && isEditMode;
GizmoTool.s_btn_scaling.background = isScaling
? UIBase.color_yellow
: UIBase.color_null;
GizmoTool.s_gizmoManager.scaleGizmoEnabled = isScaling;
if (uiType == TransformUIType.Hide) { //隐藏选中框
GizmoTool.s_boundingBoxGizmo.attachedMesh = null;
}
}
//更新显示
static updateTransformUI(updateAll = false) {
let transformUIInfo = GizmoTool.s_transformUIInfo;
let updateGizmoInfo = GizmoTool.s_needUpdateGizmo;
let mesh = transformUIInfo.mesh;
if (transformUIInfo == null || mesh == null) {
transformUIInfo.titleText.text = '';
return;
}
transformUIInfo.titleText.text = mesh.name;
if (updateGizmoInfo.position || updateAll) {
transformUIInfo.position.x.text = mesh.position.x.toPrecision(6);
transformUIInfo.position.y.text = mesh.position.y.toPrecision(6);
transformUIInfo.position.z.text = mesh.position.z.toPrecision(6);
}
if (updateGizmoInfo.rotation || updateAll) {
let augle = mesh.rotationQuaternion.toEulerAngles();
let radian1 = BabylonTool.c_radian1; //1弧度
augle = augle.multiplyByFloats(radian1, radian1, radian1);
transformUIInfo.rotation.x.text = augle.x.toPrecision(6);
transformUIInfo.rotation.y.text = augle.y.toPrecision(6);
transformUIInfo.rotation.z.text = augle.z.toPrecision(6);
}
if (updateGizmoInfo.scale || updateAll) {
let originalScaling =
GizmoTool.s_transformUIInfo.modelInfo.modelData.transformData
.originalScaling;
transformUIInfo.scale.x.text = (
mesh.absoluteScaling.x / originalScaling.x
).toPrecision(6);
transformUIInfo.scale.y.text = (
mesh.absoluteScaling.y / originalScaling.y
).toPrecision(6);
transformUIInfo.scale.z.text = (
mesh.absoluteScaling.z / originalScaling.z
).toPrecision(6);
}
}
//输入gizmo 数值 - position
static onGizmoUIInput_Position(
eventData: InputText,
eventState: EventState
) {
let transformUIInfo = GizmoTool.s_transformUIInfo;
switch (eventData.name) {
case 'x':
transformUIInfo.Mesh.position.x = Number.parseFloat(
transformUIInfo.position.x.text
);
break;
case 'y':
transformUIInfo.Mesh.position.y = Number.parseFloat(
transformUIInfo.position.y.text
);
break;
case 'z':
transformUIInfo.Mesh.position.z = Number.parseFloat(
transformUIInfo.position.z.text
);
break;
}
}
//输入gizmo 数值 - rotation
static onGizmoUIInput_Rotation(
eventData: InputText,
eventState: EventState
) {
let transformUIInfo = GizmoTool.s_transformUIInfo;
let eugle = new Vector3();
eugle.x =
Number.parseFloat(transformUIInfo.rotation.x.text) /
BabylonTool.c_radian1;
eugle.y =
Number.parseFloat(transformUIInfo.rotation.y.text) /
BabylonTool.c_radian1;
eugle.z =
Number.parseFloat(transformUIInfo.rotation.z.text) /
BabylonTool.c_radian1;
transformUIInfo.Mesh.rotationQuaternion = Quaternion.FromEulerAngles(
eugle.x,
eugle.y,
eugle.z
);
}
//输入gizmo 数值 - scale
static onGizmoUIInput_Scale(
eventData: InputText,
eventState: EventState
) {
let transformUIInfo = GizmoTool.s_transformUIInfo;
let originalScaling =
GizmoTool.s_transformUIInfo.modelInfo.modelData.transformData
.originalScaling;
switch (eventData.name) {
case 'x':
transformUIInfo.Mesh.scaling.x =
Number.parseFloat(transformUIInfo.scale.x.text) * originalScaling.x;
break;
case 'y':
transformUIInfo.Mesh.scaling.y =
Number.parseFloat(transformUIInfo.scale.y.text) * originalScaling.y;
break;
case 'z':
transformUIInfo.Mesh.scaling.z =
Number.parseFloat(transformUIInfo.scale.z.text) * originalScaling.z;
break;
}
}
}
//需要更新gizmo的类型
class NeedUpdateGizmo {
public position = true;
public rotation = false;
public scale = false;
}
//存储vector3 对应文本输入UI的映射
class UIVector3InputInfo {
public x: InputText;
public y: InputText;
public z: InputText;
}
//存储 transform 相关UI输入类的映射
class TransformUIInfo {
public root: Rectangle;
public position: UIVector3InputInfo;
public rotation: UIVector3InputInfo;
public scale: UIVector3InputInfo;
public titleText: TextBlock;
public nowType: TransformUIType = TransformUIType.Hide;
public mesh: AbstractMesh;
public modelInfo: ModelInfo;
public onTypeChangeObservable: Observable<TransformUIType>;
public onPositionChangeObservable: Observable<Vector3> = new Observable<Vector3>();
public onRotationChangeObservable: Observable<Vector3> = new Observable<Vector3>();
public onScaleChangeObservable: Observable<Vector3> = new Observable<Vector3>();
set Mesh(value: AbstractMesh) {
let lastMesh = this.mesh;
this.mesh = value;
if (value == null) {
this.NowType = TransformUIType.Hide;
} else {
//if (lastMesh == null) {
this.NowType = GizmoTool.currentGizmoType;// TransformUIType.Position;
//}
}
}
get Mesh() {
return this.mesh;
}
set NowType(value: TransformUIType) {
this.nowType = value;
// console.log("NowType====" + value);
this.OnTypeChangeObservable.notifyObservers(this.nowType);
}
get OnTypeChangeObservable(): Observable<TransformUIType> {
if (this.onTypeChangeObservable == null) {
this.onTypeChangeObservable = new Observable<TransformUIType>();
}
return this.onTypeChangeObservable;
}
}

65
src/app/babylon/tool/load-tool.ts

@ -0,0 +1,65 @@
import { ThreeDimensionalHomeComponent } from "src/app/gis/three-dimensional-home/three-dimensional-home.component";
/**
*
*/
export class LoadTool {
static s_loadingData: Map<any, string> = new Map();
static s_loadingNum: number = 0;
static readonly c_tag_preloadMark = "preloadMark";//预加载标绘物模型(不阻断)
static readonly c_tag_createMark = "createMark";//创建标绘物(不阻断)
static readonly c_tag_facilityPrefab = "facilityPrefab";//设备预制体
/**
*
* @param data
* @param tag
*/
static add(data: any, tag?: string) {
switch (tag) {
case LoadTool.c_tag_preloadMark:
case LoadTool.c_tag_createMark: return;
}
let oldNum = LoadTool.s_loadingNum;
LoadTool.s_loadingData.set(data, tag);
LoadTool.s_loadingNum = LoadTool.s_loadingData.size;
if (oldNum == 0 && LoadTool.s_loadingNum == 1) {
LoadTool.onStart();
}
}
/**
*
* @param data
*/
static remove(data: any) {
let oldNum = LoadTool.s_loadingNum;
if (LoadTool.s_loadingData.has(data)) {
LoadTool.s_loadingData.delete(data);
}
LoadTool.s_loadingNum = LoadTool.s_loadingData.size;
if (oldNum > 0 && LoadTool.s_loadingNum == 0) {
LoadTool.onEnd();
}
}
/**
*
*/
static onStart() {
console.log("开始加载");
ThreeDimensionalHomeComponent.instance.maskLayerService.sendMessage(true)
}
/**
*
*/
static onEnd() {
console.log("结束加载");
ThreeDimensionalHomeComponent.instance.maskLayerService.sendMessage(false)
}
}

476
src/app/babylon/tool/measure-tool.ts

@ -0,0 +1,476 @@
import { EventState, Mesh, MeshBuilder, PickingInfo, PointerEventTypes, PointerInfo, Scene, Vector3 } from "@babylonjs/core";
import { Button, Container, Control, Ellipse, MultiLine, Rectangle, TextBlock } from "@babylonjs/gui";
import { UIManager } from "../controller/ui-manager";
import { BabylonUIStyleTool } from "./babylon-ui-style-tool";
/**
*
*/
export class MeasureTool {
static instance: MeasureTool;
/**
*
*/
currentMeasureInfo: MeasureInfo;
/**
*
*/
currentMeasureType: MeasureType = MeasureType.None;
scene: Scene;
constructor(scene: Scene) {
this.scene = scene;
MeasureTool.instance = this;
scene.onPointerObservable.add(
MeasureTool.instance.onPointerObservable
);
}
/**
*
* @param start
* @param type
*/
createMeasureInfo(start: Vector3) {
let type: MeasureType = this.currentMeasureType;
if (type != MeasureType.None) {
this.currentMeasureInfo = new MeasureInfo(start, type);
}
}
/**
*
*/
breakMeasure() {
this.currentMeasureInfo = null;
}
/**
*
* @param type MeasureType.None,
*/
changeMeasureType(type: MeasureType) {
this.currentMeasureType = type;
switch (type) {
case MeasureType.None:
this.breakMeasure();
break;
}
}
//鼠标交互监听
onPointerObservable(eventData: PointerInfo, eventState: EventState) {
let instance = MeasureTool.instance;
if (instance.currentMeasureType == MeasureType.None) {
return; //非测量状态
}
switch (eventData.type) {
case PointerEventTypes.POINTERPICK:
if (eventData.event.button == 0 && eventData.pickInfo.hit) {
if (!instance.isPickTooFar(eventData.pickInfo)) {
if (instance.currentMeasureInfo == null) {
instance.createMeasureInfo(eventData.pickInfo.pickedPoint);
}
else {
instance.addMeasurePoint(eventData.pickInfo);
}
}
}
else if (eventData.event.button == 2) //右键,中断
{
instance.breakMeasure();
}
break;
}
}
/**
*
*/
addMeasurePoint(pickInfo: PickingInfo) {
console.log("测量", pickInfo);
if (this.currentMeasureInfo != null) {
this.currentMeasureInfo.addPoint(pickInfo.pickedPoint);
}
}
/**
* ()
* @param point
*/
isPickTooFar(point: PickingInfo) {
if (point.pickedMesh != null && point.pickedMesh.name == "skyBox") {
return true;
}
else {
return false;
}
}
}
/**
*
*/
export enum MeasureType {
/**
*
*/
None,
/**
* 线
*/
Distance,
/**
*
*/
Height,
/**
*
*/
Area,
}
/**
*
*/
export class MeasureInfo {
/**
*
*/
points: MeasurePoint[];
type: MeasureType;
/**
* ui根节点
*/
uiRoot: Container;
/**
*
*/
ell_start: Ellipse;
/**
*
*/
btn_dispose: Button;
/**
*
*/
txt_info: TextBlock;
/**
*
*/
txtbg: Rectangle;
mulLine: MultiLine;
constructor(start: Vector3, type: MeasureType) {
this.points = [];
this.type = type;
this.mulLine = new MultiLine("mulLine" + type);
this.mulLine.lineWidth = 1.5;
this.mulLine.color = BabylonUIStyleTool.c_color_3d_blue;
this.mulLine.shadowColor = BabylonUIStyleTool.c_color_3d_blue;
this.mulLine.shadowBlur = 5;
UIManager.Instance.uiRoot.addControl(this.mulLine);
this.addPoint(start);
this.updateUI();
}
/**
*
*/
addPoint(pos: Vector3) {
if (this.points.length > 0) {
for (let i = 0; i < this.points.length; i++) {
this.points[i].changeEnd(false);
}
if (this.type == MeasureType.Height) {
pos.x = this.points[0].pos.x;
pos.z = this.points[0].pos.z;
}
}
let point = new MeasurePoint(pos, true, this);
this.points.push(point);
if (this.points.length > 3 && this.type == MeasureType.Area) {
let lastPoint = this.mulLine.getAt(this.points.length - 1);
this.mulLine.remove(lastPoint);
this.mulLine.add(point.mesh);
this.mulLine.add(this.points[0].mesh);
}
else {
this.mulLine.add(point.mesh);
}
if (this.points.length > 1 && this.type == MeasureType.Height) { //高度只能放两个点
MeasureTool.instance.breakMeasure();
}
if (this.points.length == 3 && this.type == MeasureType.Area) {
this.mulLine.add(this.points[0].mesh);
}
//更新显示
this.updateUI();
}
/**
* UI
*/
updateUI() {
if (this.uiRoot == null) {
this.ell_start = new Ellipse("MeasureStart")
UIManager.Instance.uiRoot.addControl(this.ell_start);
BabylonUIStyleTool.setStyle_size(this.ell_start, "10px", "10px");
this.ell_start.thickness = 2;
this.ell_start.color = BabylonUIStyleTool.c_color_3d_blue;
this.ell_start.background = BabylonUIStyleTool.c_color_3d_blueBg;
this.ell_start.linkWithMesh(this.points[0].mesh);
this.uiRoot = new Container("Measure");
this.uiRoot.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
UIManager.Instance.uiRoot.addControl(this.uiRoot);
BabylonUIStyleTool.setStyle_size(this.uiRoot, "100px", "40px");
this.btn_dispose = Button.CreateSimpleButton("dispose", "x");
this.uiRoot.addControl(this.btn_dispose);
this.btn_dispose.leftInPixels = 10;
BabylonUIStyleTool.setStyle_size(this.btn_dispose, "15px", "15px");
this.btn_dispose.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
this.btn_dispose.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
let instance = this;
this.btn_dispose.onPointerClickObservable.add(() => {
instance.dispose();
});
this.btn_dispose.background = BabylonUIStyleTool.c_color_3d_blueBg;
this.btn_dispose.color = BabylonUIStyleTool.c_color_3d_blue;
this.txtbg = new Rectangle("txtBG");
this.uiRoot.addControl(this.txtbg);
BabylonUIStyleTool.setStyle_size(this.txtbg, "70px", "25px");
this.txtbg.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
this.txtbg.verticalAlignment = Control.VERTICAL_ALIGNMENT_BOTTOM;
this.txtbg.background = BabylonUIStyleTool.c_color_3d_blueBg;
this.txtbg.color = BabylonUIStyleTool.c_color_3d_blue;
this.txt_info = new TextBlock("txt");
this.uiRoot.addControl(this.txt_info);
BabylonUIStyleTool.setStyle_size(this.txt_info, "70px", "25px");
this.txt_info.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
this.txt_info.verticalAlignment = Control.VERTICAL_ALIGNMENT_BOTTOM;
this.txt_info.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
this.txt_info.color = BabylonUIStyleTool.c_color_3d_blue;
this.txt_info.resizeToFit = true;
let ell_end = new Ellipse("end")
this.uiRoot.addControl(ell_end);
BabylonUIStyleTool.setStyle_size(ell_end, "10px", "10px");
ell_end.thickness = 2;
ell_end.color = BabylonUIStyleTool.c_color_3d_blue;
ell_end.background = BabylonUIStyleTool.c_color_3d_blueBg;
ell_end.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
ell_end.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
}
let info: string = "";
switch (this.type) {
case MeasureType.Distance:
info = " 长度:" + this.getPointsDistance(this.points).toFixed(1) + "米";
break;
case MeasureType.Height:
info = " 高度:" + this.getPointsHeight(this.points).toFixed(1) + "米";
break;
case MeasureType.Area:
info = " 面积:" + this.getPointsArea(this.points).toFixed(1) + "平方米";
break;
}
this.txt_info.text = info;
let instance = this;
setTimeout(() => {
instance.txtbg.widthInPixels = instance.txt_info.widthInPixels + 3;
instance.uiRoot.widthInPixels = instance.txt_info.widthInPixels + 3;
let lastPoint = instance.points[instance.points.length - 1];
instance.uiRoot.linkWithMesh(lastPoint.mesh);
instance.uiRoot.linkOffsetYInPixels = 20 - 5;
instance.uiRoot.linkOffsetXInPixels = instance.uiRoot.widthInPixels * 0.5 - 5;
}, (30));
}
/**
*
* @param points
*/
getPointsDistance(points: MeasurePoint[]) {
let result = 0;
if (points != null && points.length > 1) {
for (let i = 1; i < points.length; i++) {
result += Vector3.Distance(points[i - 1].pos, points[i].pos);
}
}
return result;
}
/**
*
* @param points
*/
getPointsHeight(points: MeasurePoint[]) {
let result = 0;
if (points != null && points.length > 1) {
result = points[points.length - 1].pos.y - points[0].pos.y;
result = Math.abs(result);
}
return result;
}
/**
* xz平面内
* @param points
*/
getPointsArea(points: MeasurePoint[]) {
let result = 0;
if (points != null && points.length > 2) {
for (let i = 0; i < points.length - 1; i++) {
result += (points[i].pos.x * points[i + 1].pos.z - points[i + 1].pos.x * points[i].pos.z);
}
let num = points.length - 1;
result = 0.5 * (result + points[num].pos.x * points[0].pos.z - points[0].pos.x * points[num].pos.z);
result = Math.abs(result);
}
return result;
}
/**
*
*/
dispose() {
this.ell_start.dispose();
this.uiRoot.dispose();
this.uiRoot = null;
this.btn_dispose = null;
this.txt_info = null;
this.mulLine.dispose();
this.mulLine = null;
for (let i = 0; i < this.points.length; i++) {
this.points[i].dispose();
}
this.points = [];
MeasureTool.instance.breakMeasure();
}
}
/**
*
*/
export class MeasurePoint {
/**
*
*/
isEnd: boolean;
pos: Vector3;
/**
*
*/
belongTo: MeasureInfo;
/**
*
*/
mesh: Mesh;
constructor(pos: Vector3, isEnd: boolean, belongTo: MeasureInfo) {
this.pos = pos;
this.isEnd = isEnd;
this.belongTo = belongTo;
this.mesh = MeshBuilder.CreateSphere(belongTo.type.toString(), { segments: 1, diameter: 0.01 }, MeasureTool.instance.scene);
this.mesh.position = pos;
}
/**
*
* @param isEnd
*/
changeEnd(isEnd: boolean) {
this.isEnd = isEnd;
//更新终点显示
}
dispose() {
if (this.mesh != null) {
this.mesh.dispose();
}
}
}

322
src/app/babylon/tool/mesh-pool.ts

@ -0,0 +1,322 @@
//mesh对象池
//为避免重复加载、销毁mesh对象
import { AbstractMesh, MeshBuilder, Observable, TransformNode, Vector3 } from "@babylonjs/core";
import { SceneManager } from "../controller/scene-manager";
import { ModelData, ModelType } from "../model/data/model-data/model-data";
import { ModelInfo } from "../model/info/model/model-info";
import { TsTool } from "./ts-tool";
export class MeshPool {
//#region 单例
private static instance: MeshPool;
static get Instance() {
if (MeshPool.instance == null) {
MeshPool.instance = new MeshPool();
}
return MeshPool.instance;
}
//#endregion
root: TransformNode;
prefabPool: Map<string, MeshPoolInfo[]> = new Map();//预制体池
idlePool: Map<string, MeshPoolInfo[]> = new Map();//空闲池
workingPool: Map<string, MeshPoolInfo[]> = new Map();//工作池
constructor() {
this.root = new TransformNode("MeshPoolRoot", SceneManager.Instance.scene);
this.root.setEnabled(false);//隐藏起来
}
//#region 外部方法
/**
*
*/
static importMesh(modeltype: ModelType, modelData: ModelData, isNew: boolean = true, fromClone: boolean = true, tag?: string, onSuccess?: (meshBox: AbstractMesh, meshes: AbstractMesh[], result: MeshPoolInfo) => void, onlyPrefab = false,): MeshPoolInfo {
let result = MeshPool.Instance.getMesh(modelData.resPath, modelData.resName, fromClone);
if (result == null) {
//console.log("对象池中没有,要加载:" + path + name);
let prefab = MeshPool.Instance.getMeshPrefab(modelData.resPath, modelData.resName);
result = new MeshPoolInfo(modelData.resPath, modelData.resName, fromClone);
if (prefab == null) {
prefab = new MeshPoolInfo(modelData.resPath, modelData.resName, false);
prefab.onSuccessObserver = new Observable<MeshPoolInfo>();
MeshPool.Instance.addPool(MeshPool.Instance.prefabPool, prefab);
SceneManager.createModel(modeltype, modelData, true, isNew, tag, (meshes: AbstractMesh[], box: AbstractMesh, modelInfo: ModelInfo) => {
prefab.meshes = meshes;
prefab.meshBox = box;
prefab.modelInfo = modelInfo;
prefab.setActive(false);
modelInfo.showFollowUI(false);
prefab.success();
MeshPool.Instance.addPool(MeshPool.Instance.prefabPool, prefab);
if (!onlyPrefab) {
if (fromClone) {
result.cloneMeshFrom(prefab, modelData, isNew);
result.setActive(true);
MeshPool.Instance.addPool(MeshPool.Instance.workingPool, result);
result.success();
if (onSuccess) {
onSuccess(result.meshBox, result.meshes, result);
}
}
else {
SceneManager.createModel(modeltype, modelData, true, isNew, tag, (meshes: AbstractMesh[], box: AbstractMesh, modelInfo: ModelInfo) => {
result.meshBox = box;
result.meshes = meshes;
result.modelInfo = modelInfo;
result.setActive(true);
modelInfo.showFollowUI(false);
result.success();
MeshPool.Instance.addPool(MeshPool.Instance.workingPool, result);
if (onSuccess) {
onSuccess(result.meshBox, result.meshes, result);
}
})
}
}
})
return result;
}
else {
if (fromClone) {
if (prefab.meshBox == null) {
// console.log("找到了预制体,但是还没加载完")
prefab.onSuccessObserver.add((eventData: MeshPoolInfo) => {
// console.log("加载回调");
result.cloneMeshFrom(prefab, modelData, isNew);
result.setActive(true);
MeshPool.Instance.addPool(MeshPool.Instance.workingPool, result);
result.success();
if (onSuccess) {
onSuccess(result.meshBox, result.meshes, result);
}
})
return result;
}
else {
result.cloneMeshFrom(prefab, modelData, isNew);
result.setActive(true);
MeshPool.Instance.addPool(MeshPool.Instance.workingPool, result);
result.success();
if (onSuccess) {
onSuccess(result.meshBox, result.meshes, result);
}
return result;
}
}
else {
SceneManager.createModel(modeltype, modelData, true, isNew, tag, (meshes: AbstractMesh[], box: AbstractMesh, modelInfo: ModelInfo) => {
result.meshBox = box;
result.meshes = meshes;
result.modelInfo = modelInfo;
result.setActive(true);
modelInfo.showFollowUI(false);
MeshPool.Instance.addPool(MeshPool.Instance.workingPool, result);
result.success();
if (onSuccess) {
onSuccess(result.meshBox, result.meshes, result);
}
})
return result;
}
}
}
else {
// console.log("从对象池取出" + result.key);
MeshPool.Instance.removePool(MeshPool.Instance.idlePool, result);
MeshPool.instance.addPool(MeshPool.Instance.workingPool, result);
result.setActive(true);
result.success();
if (onSuccess && result.meshBox != null) {
onSuccess(result.meshBox, result.meshes, result);
}
}
return result;
}
/**
*
* @param meshPoolInfo
*/
static disposeMesh(meshPoolInfo: MeshPoolInfo) {
MeshPool.Instance.removePool(MeshPool.Instance.workingPool, meshPoolInfo);
MeshPool.Instance.addPool(MeshPool.Instance.idlePool, meshPoolInfo);
meshPoolInfo.setActive(false);
}
//#endregion
//#region 内部方法
getMesh(path: string, name: string, fromClone: boolean = true): MeshPoolInfo {
let result: MeshPoolInfo = null;
let resKey = path + name;
let poolList = MeshPool.Instance.idlePool.get(resKey);
if (poolList != null && poolList.length > 0) {
for (let i = 0; i < poolList.length; i++) {
if (poolList[i].fromClone == fromClone) {
result = poolList[i];
break;
}
}
}
else {
//console.log("对象池取出失败" + name);
}
return result;
}
//放入某池
addPool(pool: Map<string, MeshPoolInfo[]>, value: MeshPoolInfo) {
let poolInfo = pool.get(value.key);
if (poolInfo == null) {
poolInfo = [];
pool.set(value.key, poolInfo);
}
poolInfo.push(value);
}
//移除池
removePool(pool: Map<string, MeshPoolInfo[]>, value: MeshPoolInfo) {
let poolInfo = pool.get(value.key);
if (poolInfo == null) {
console.error("removePool no key" + value.key);
return;
}
TsTool.arrayRemove(poolInfo, value);
}
/**
*
*/
getMeshPrefab(path: string, name: string): MeshPoolInfo {
let result: MeshPoolInfo = null;
let resKey = path + name;
let poolList = MeshPool.Instance.prefabPool.get(resKey);
if (poolList != null && poolList.length > 0) {
result = poolList[0];
}
else {
}
return result;
}
//#endregion
}
/**
*
*/
export class MeshPoolInfo {
key: string;
resPath: string;//资源路径,
resName: string;
meshBox: AbstractMesh;//对象
fromClone: boolean;//来自克隆
meshes: AbstractMesh[];//所有mesh节点
active: boolean;
modelInfo: ModelInfo;
onSuccessObserver: Observable<MeshPoolInfo>;
constructor(resPath: string, resName: string, fromClone: boolean = true, mesh?: AbstractMesh, meshes?: AbstractMesh[], modelInfo?: ModelInfo) {
this.key = resPath + resName;
this.resPath = resPath;
this.resName = resName;
this.fromClone = fromClone;
this.meshBox = mesh;
this.meshes = meshes;
this.modelInfo = modelInfo;
}
setActive(active: boolean) {
if (this.meshBox != null) {
if (active) {
this.meshBox.setParent(null);
let allNode = this.meshBox.getChildTransformNodes();
for (let i = 0; i < allNode.length; i++) {
allNode[i].setEnabled(true);
}
this.meshBox.setEnabled(true);
}
else {
this.meshBox.setParent(MeshPool.Instance.root);
this.meshBox.position = Vector3.Zero();
// this.meshBox.setEnabled(false);
// console.log("放入对象池" + this.meshBox.name);
}
}
}
/**
*
*/
success() {
if (this.onSuccessObserver != null) {
// console.log("导入完成", this.onSuccessObserver.observers);
this.onSuccessObserver.notifyObservers(this);
this.onSuccessObserver.clear();
}
}
clone() {
let modelInfo = this.modelInfo.clone();
let newMesh = new MeshPoolInfo(this.resPath, this.resName, true, modelInfo.modelBox, modelInfo.models, modelInfo);
return newMesh;
}
/**
* mesh
* @param prefab
*/
cloneMeshFrom(prefab: MeshPoolInfo, modelData?: ModelData, isNew: boolean = true) {
let modelInfo = prefab.modelInfo.clone(modelData, isNew);
this.meshBox = modelInfo.modelBox;
this.modelInfo = modelInfo;
// let box = MeshBuilder.CreateBox("box", { size: 1 }); //用于测试阴影
// box.setParent(modelInfo.modelBox);
// box.position = new Vector3(0, 2, 0);
if (SceneManager.s_openShadow) {
SceneManager.Instance.shadowGenerator.addShadowCaster(modelInfo.modelBox, true);
// console.log("添加到阴影", modelInfo.modelBox.name);
}
}
dispose() {
this.modelInfo.dispose();
}
}

262
src/app/babylon/tool/myArcRotateCameraPointersInput.ts

@ -0,0 +1,262 @@
import { ArcRotateCamera, CameraInputTypes, Nullable, PointerTouch, serialize } from "@babylonjs/core";
import { BaseCameraPointersInput } from "@babylonjs/core/Cameras/Inputs/BaseCameraPointersInput";
//修改为左键平移,右键旋转
export class MyArcRotateCameraPointersInput extends BaseCameraPointersInput {
/**
* Defines the camera the input is attached to.
*/
public camera: ArcRotateCamera;
/**
* Gets the class name of the current input.
* @returns the class name
*/
public getClassName(): string {
return "MyArcRotateCameraPointersInput";
}
/**
* Defines the buttons associated with the input to handle camera move.
*/
@serialize()
public buttons = [0, 1, 2];
/**
* Defines the pointer angular sensibility along the X axis or how fast is
* the camera rotating.
*/
@serialize()
public angularSensibilityX = 1000.0;
/**
* Defines the pointer angular sensibility along the Y axis or how fast is
* the camera rotating.
*/
@serialize()
public angularSensibilityY = 1000.0;
/**
* Defines the pointer pinch precision or how fast is the camera zooming.
*/
@serialize()
public pinchPrecision = 12.0;
/**
* pinchDeltaPercentage will be used instead of pinchPrecision if different
* from 0.
* It defines the percentage of current camera.radius to use as delta when
* pinch zoom is used.
*/
@serialize()
public pinchDeltaPercentage = 0;
/**
* When useNaturalPinchZoom is true, multi touch zoom will zoom in such
* that any object in the plane at the camera's target point will scale
* perfectly with finger motion.
* Overrides pinchDeltaPercentage and pinchPrecision.
*/
@serialize()
public useNaturalPinchZoom: boolean = false;
/**
* Defines whether zoom (2 fingers pinch) is enabled through multitouch
*/
@serialize()
public pinchZoom: boolean = true;
/**
* Defines the pointer panning sensibility or how fast is the camera moving.
*/
@serialize()
public panningSensibility: number = 1000.0;
/**
* Defines whether panning (2 fingers swipe) is enabled through multitouch.
*/
@serialize()
public multiTouchPanning: boolean = true;
/**
* Defines whether panning is enabled for both pan (2 fingers swipe) and
* zoom (pinch) through multitouch.
*/
@serialize()
public multiTouchPanAndZoom: boolean = true;
/**
* Revers pinch action direction.
*/
public pinchInwards = true;
private _isPanClick: boolean = false;
private _twoFingerActivityCount: number = 0;
private _isPinching: boolean = false;
/**
* Move camera from multi touch panning positions.
*/
private _computeMultiTouchPanning(
previousMultiTouchPanPosition: Nullable<PointerTouch>,
multiTouchPanPosition: Nullable<PointerTouch>
): void {
if (this.panningSensibility !== 0 && previousMultiTouchPanPosition
&& multiTouchPanPosition) {
var moveDeltaX = multiTouchPanPosition.x - previousMultiTouchPanPosition.x;
var moveDeltaY = multiTouchPanPosition.y - previousMultiTouchPanPosition.y;
// this.camera.inertialPanningX += -moveDeltaX / this.panningSensibility;
// this.camera.inertialPanningY += moveDeltaY / this.panningSensibility;
// this.moveCamera(-moveDeltaX, moveDeltaY);
this.rotateCamera(moveDeltaX, moveDeltaX);
}
}
moveCamera(x, y) {
this.camera.inertialPanningX += x / this.panningSensibility;
this.camera.inertialPanningY += y / this.panningSensibility;
}
/**
* Move camera from pinch zoom distances.
*/
private _computePinchZoom(
previousPinchSquaredDistance: number,
pinchSquaredDistance: number
): void {
if (this.useNaturalPinchZoom) {
this.camera.radius = this.camera.radius *
Math.sqrt(previousPinchSquaredDistance) / Math.sqrt(pinchSquaredDistance);
} else if (this.pinchDeltaPercentage) {
this.camera.inertialRadiusOffset +=
(pinchSquaredDistance - previousPinchSquaredDistance) * 0.001 *
this.camera.radius * this.pinchDeltaPercentage;
}
else {
this.camera.inertialRadiusOffset +=
(pinchSquaredDistance - previousPinchSquaredDistance) /
(this.pinchPrecision * (this.pinchInwards ? 1 : -1) *
(this.angularSensibilityX + this.angularSensibilityY) / 2);
}
}
/**
* Called on pointer POINTERMOVE event if only a single touch is active.
*/
protected onTouch(point: Nullable<PointerTouch>,
offsetX: number,
offsetY: number): void {
if (this.panningSensibility !== 0 &&
((this._ctrlKey && this.camera._useCtrlForPanning) || this._isPanClick)) {
// this.camera.inertialPanningX += -offsetX / this.panningSensibility;
// this.camera.inertialPanningY += offsetY / this.panningSensibility;
this.rotateCamera(offsetX, offsetY);
} else {
this.moveCamera(-offsetX, offsetY);
// this.camera.inertialAlphaOffset -= offsetX / this.angularSensibilityX;
// this.camera.inertialBetaOffset -= offsetY / this.angularSensibilityY;
}
}
rotateCamera(offsetX, offsetY) {
this.camera.inertialAlphaOffset -= offsetX / this.angularSensibilityX;
this.camera.inertialBetaOffset -= offsetY / this.angularSensibilityY;
}
/**
* Called on pointer POINTERDOUBLETAP event.
*/
protected onDoubleTap(type: string) {
if (this.camera.useInputToRestoreState) {
this.camera.restoreState();
}
}
/**
* Called on pointer POINTERMOVE event if multiple touches are active.
*/
protected onMultiTouch(pointA: Nullable<PointerTouch>,
pointB: Nullable<PointerTouch>,
previousPinchSquaredDistance: number,
pinchSquaredDistance: number,
previousMultiTouchPanPosition: Nullable<PointerTouch>,
multiTouchPanPosition: Nullable<PointerTouch>): void {
if (previousPinchSquaredDistance === 0 && previousMultiTouchPanPosition === null) {
// First time this method is called for new pinch.
// Next time this is called there will be a
// previousPinchSquaredDistance and pinchSquaredDistance to compare.
return;
}
if (pinchSquaredDistance === 0 && multiTouchPanPosition === null) {
// Last time this method is called at the end of a pinch.
return;
}
// Zoom and panning enabled together
if (this.multiTouchPanAndZoom) {
this._computePinchZoom(previousPinchSquaredDistance, pinchSquaredDistance);
this._computeMultiTouchPanning(previousMultiTouchPanPosition, multiTouchPanPosition);
// Zoom and panning enabled but only one at a time
} else if (this.multiTouchPanning && this.pinchZoom) {
this._twoFingerActivityCount++;
if (this._isPinching || (this._twoFingerActivityCount < 20
&& Math.abs(Math.sqrt(pinchSquaredDistance) - Math.sqrt(previousPinchSquaredDistance)) >
this.camera.pinchToPanMaxDistance)) {
// Since pinch has not been active long, assume we intend to zoom.
this._computePinchZoom(previousPinchSquaredDistance, pinchSquaredDistance);
// Since we are pinching, remain pinching on next iteration.
this._isPinching = true;
} else {
// Pause between pinch starting and moving implies not a zoom event. Pan instead.
this._computeMultiTouchPanning(previousMultiTouchPanPosition, multiTouchPanPosition);
}
// Panning enabled, zoom disabled
} else if (this.multiTouchPanning) {
this._computeMultiTouchPanning(previousMultiTouchPanPosition, multiTouchPanPosition);
// Zoom enabled, panning disabled
} else if (this.pinchZoom) {
this._computePinchZoom(previousPinchSquaredDistance, pinchSquaredDistance);
}
}
/**
* Called each time a new POINTERDOWN event occurs. Ie, for each button
* press.
*/
protected onButtonDown(evt: PointerEvent): void {
this._isPanClick = evt.button === this.camera._panningMouseButton;
}
/**
* Called each time a new POINTERUP event occurs. Ie, for each button
* release.
*/
protected onButtonUp(evt: PointerEvent): void {
this._twoFingerActivityCount = 0;
this._isPinching = false;
}
/**
* Called when window becomes inactive.
*/
protected onLostFocus(): void {
// console.trace("失去焦点")
this._isPanClick = false;
this._twoFingerActivityCount = 0;
this._isPinching = false;
}
}
(<any>CameraInputTypes)["MyArcRotateCameraPointersInput"] =
MyArcRotateCameraPointersInput;

113
src/app/babylon/tool/particle-system-tool.ts

@ -0,0 +1,113 @@
import { ParticleHelper, ParticleSystem, ParticleSystemSet, Scene, Vector3 } from "@babylonjs/core";
/**
*
*/
export class ParticleSystemTool {
/**
*
*/
psPool: Map<string, ParticleSystem>;
scene: Scene;
constructor(scene: Scene) {
this.scene = scene;
this.psPool = new Map();
}
static instance: ParticleSystemTool;
static Init(scene: Scene) {
ParticleSystemTool.instance = new ParticleSystemTool(scene);
}
static dispose() {
}
/**
*
* @param name
* @param path
* @param onSuccess
*/
loadPrefab(name: string, path: string, clone: boolean = true, onSuccess?: (ps: ParticleSystem) => void) {
let instance = this;
ParticleHelper.ParseFromFileAsync(null, path, this.scene, false).then((value: ParticleSystem) => {
value.stop();
instance.psPool.set(path, value);
if (clone) {
let result = instance.cloneParticle(value, name);
if (onSuccess) {
onSuccess(result)
}
}
else {
if (onSuccess) {
onSuccess(value)
}
}
});
}
/**
*
* @param path
* @param onSuccess
*/
importParticle(name: string, path: string, onSuccess: (ps: ParticleSystem) => void) {
let instance = this;
if (instance.psPool.has(path)) {
let set = instance.psPool.get(path);
let result = instance.cloneParticle(set, name);
onSuccess(result);
}
else {
instance.loadPrefab(null, path, true, (value: ParticleSystem) => {
onSuccess(value);
})
// ParticleHelper.ParseFromFileAsync(null, path, this.scene, false).then((value: ParticleSystem) => {
// instance.psPool.set(path, value);
// let result = instance.cloneParticle(value, name);
// onSuccess(result)
// });
}
}
/**
*
* @param setPrefab
* @param name
*/
cloneParticleSet(setPrefab: ParticleSystemSet, name: string) {
let result = new ParticleSystemSet();
for (let i = 0; i < setPrefab.systems.length; i++) {
result.systems.push(this.cloneParticle(setPrefab.systems[i] as ParticleSystem, name));
}
return result;
}
/**
*
* @param particle
* @param name
*/
cloneParticle(particle: ParticleSystem, name: string) {
// let root = new AbstractMesh("root_" + name, this.scene);
let root = Vector3.Zero();
let result = particle.clone(particle.name, root);
return result;
}
}

112
src/app/babylon/tool/photo360-tool.ts

@ -0,0 +1,112 @@
import { ArcRotateCamera, Color3, Color4, Database, Engine, EngineStore, PhotoDome, Scene, Vector3 } from "@babylonjs/core";
import { TextBlock } from "@babylonjs/gui";
import { AdvancedDynamicTexture } from "@babylonjs/gui/2D/advancedDynamicTexture";
/**
* 360
*/
export class Photo360Tool {
static instance: Photo360Tool;
canvas: HTMLCanvasElement;
engine: Engine;
scene: Scene;
photo: PhotoDome;
loadingTxt: TextBlock;
/**
*
* @param canvas
* @param photoURL
*/
static open(canvas: HTMLCanvasElement, photoURL: string) {
if (Photo360Tool.instance == null) {
Photo360Tool.instance = new Photo360Tool();
let instance = Photo360Tool.instance;
instance.canvas = canvas;
instance.engine = new Engine(canvas, null, { stencil: true });
instance.scene = new Scene(instance.engine, { virtual: true }); // virtual确保默认场景为主场景,而不是新创建的这个
instance.scene.useRightHandedSystem = true;//使用右手坐标系
instance.scene.clearColor = new Color4(0, 0, 0, 1);
//instance.initUI();
//最后,将场景渲染出来 (重要,不可缺少)
instance.engine.runRenderLoop(function () {
if (instance.scene != null) {
instance.scene.render();
}
})
// 监听浏览器改变大小的事件,通过调用engine.resize()来自适应窗口大小
window.addEventListener("resize", function () {
if (instance != null && instance.engine != null) {
instance.engine.resize();
}
});
let camera = new ArcRotateCamera("Camera", -Math.PI / 2, Math.PI / 2, 5, Vector3.Zero(), Photo360Tool.instance.scene);
camera.attachControl(canvas, true);
camera.inputs.attached.mousewheel.detachControl();
}
else {
console.error("重复开启全景图");
}
//确保默认场景为主场景,而不是新创建的这个. 替换为virtual: true 设置。
// EngineStore._LastCreatedScene = SceneManager.Instance.scene;
Photo360Tool.instance.changePhoto(photoURL);
}
static close() {
if (Photo360Tool.instance != null) {
Photo360Tool.instance.disposePhoto();
Photo360Tool.instance = null;
}
}
initUI() {
let rootUI = AdvancedDynamicTexture.CreateFullscreenUI("UIRoot", undefined, this.scene);//UtilityLayerRenderer.DefaultUtilityLayer.utilityLayerScene
this.loadingTxt = new TextBlock("loading", "加载中...");
rootUI.addControl(this.loadingTxt);
this.loadingTxt.fontSize = "30px";
this.loadingTxt.color = "white";
this.loadingTxt.width = "200px";
this.loadingTxt.height = "100px";
// this.scene.debugLayer.show();
}
changePhoto(photoURL: string) {
if (this.photo != null) {
this.photo.dispose();
}
Photo360Tool.instance.photo = new PhotoDome(
"testdome",
photoURL,
{
resolution: 32,
size: 1000
},
Photo360Tool.instance.scene
);
}
disposePhoto() {
if (this.photo != null) {
this.photo.dispose();
}
this.scene.dispose();
this.scene = null;
this.engine.dispose();
this.engine = null;
}
}

112
src/app/babylon/tool/pos-point-tool.ts

@ -0,0 +1,112 @@
import { Mesh, Vector3 } from "@babylonjs/core";
import { Button, Rectangle, StackPanel } from "@babylonjs/gui";
import { SceneManager } from "../controller/scene-manager";
import { UIManager } from "../controller/ui-manager";
import { BabylonUIStyleTool } from "./babylon-ui-style-tool";
import { GizmoTool } from "./gizmo-tool";
export class PosPointTool {
static readonly c_key = "PosPoint";
static instance: PosPointTool;
mesh: Mesh;
pos: Vector3;
uiRoot: Rectangle;
//#region UI
initUI() {
let instance = this;
this.uiRoot = new Rectangle("PosPointTooUI");
UIManager.Instance.uiRoot.addControl(this.uiRoot);
BabylonUIStyleTool.setStyle_size(this.uiRoot, "40px", "20px");
let stack = new StackPanel("stack");
this.uiRoot.addControl(stack);
stack.isVertical = false;
let btn_add = Button.CreateSimpleButton("add", "+");
stack.addControl(btn_add);
btn_add.background = BabylonUIStyleTool.c_color_blue;
btn_add.color = "white";
btn_add.thickness = 0;
btn_add.onPointerClickObservable.add(() => {
instance.btn_add();
});
BabylonUIStyleTool.setStyle_size(btn_add, "20px", "20px");
let btn_reduce = Button.CreateSimpleButton("reduce", "-");
stack.addControl(btn_reduce);
btn_reduce.background = BabylonUIStyleTool.c_color_red;
btn_reduce.color = "white";
btn_reduce.thickness = 0;
btn_reduce.onPointerClickObservable.add(() => {
instance.btn_reduce();
});
BabylonUIStyleTool.setStyle_size(btn_reduce, "20px", "20px");
}
showUI(show: boolean) {
this.uiRoot.isVisible = show;
this.uiRoot.linkWithMesh(this.mesh);
this.uiRoot.linkOffsetY = "-50px";
}
//#endregion
static get Instance() {
if (PosPointTool.instance == null) {
PosPointTool.instance = new PosPointTool();
PosPointTool.instance.initUI();
SceneManager.Instance.scene.onBeforeRenderObservable.add(PosPointTool.onUpdate);
GizmoTool.onGizmoAimMeshObservable.add((mesh) => {
if (mesh == null || !mesh.name.match(PosPointTool.c_key)) {
PosPointTool.attachMesh(null);
}
});
}
return PosPointTool.instance;
}
onAdd: () => void;
onReduce: () => void;
static attachMesh(mesh: Mesh, pos?: Vector3, onAdd?: () => void, onReduce?: () => void) {
PosPointTool.Instance.mesh = mesh;
PosPointTool.Instance.pos = pos;
PosPointTool.Instance.showUI(mesh != null);
PosPointTool.Instance.onAdd = onAdd;
PosPointTool.Instance.onReduce = onReduce;
}
static onUpdate() {
if (PosPointTool.Instance.mesh != null) {
}
}
//添加
btn_add() {
if (this.onAdd) {
this.onAdd();
}
}
//减少
btn_reduce() {
if (this.onReduce) {
this.onReduce();
}
}
}

6
src/app/babylon/tool/time-tool.ts

@ -0,0 +1,6 @@
class TimeTool {
}

26
src/app/babylon/tool/ts-tool.ts

@ -0,0 +1,26 @@
export class TsTool {
//在数组中移除目标(不留空位)
static arrayRemove(array: any[], remove: any): boolean {
let index = array.indexOf(remove, 0);
if (index > -1) {
array.splice(index, 1);
return true;
}
else {
return false;
}
}
//判断字符串source中是否包含某字符串aim
static stringContain(source: string, aim: string): boolean {
let result = source.indexOf(aim) != -1;
return result;
}
//打印调用堆栈
static trace() {
console.trace();
}
}

351
src/app/babylon/view/building-window/building-create-window.ts

@ -0,0 +1,351 @@
// import { Checkbox, Control, InputText, RadioButton, Rectangle, StackPanel, TextBlock } from "@babylonjs/gui";
// import { DataManager, ModelChangeType } from "src/babylon/controller/data-manager";
// import { Event_ModelInfoChange } from "src/babylon/controller/event-manager/events/event-modelinfo-change";
// import { ServeManager } from "src/babylon/controller/serve-manager";
// import { UIManager } from "src/babylon/controller/ui-manager";
// import { BuildingData, BuildingType } from "src/babylon/model/data/institution/building/building-data";
// import { BuildingPosType, ModelData } from "src/babylon/model/data/model-data/model-data";
// import { ModelEditData } from "src/babylon/model/data/model-data/model-edit-data";
// import { BuildingInfo } from "src/babylon/model/info/building/building-info";
// import { ModelInfo_facility } from "src/babylon/model/info/model/model-info-facility";
// import { BabylonUIStyleTool } from "src/babylon/tool/babylon-ui-style-tool";
// import { TsTool } from "src/babylon/tool/ts-tool";
// import { UIBase } from "../window-base/ui-base";
// import { BuildingUIItem } from "./building-ui-item";
// import { BuildingWindow } from "./building-window";
// //创建建筑物界面
// export class BuildingCreateWindow extends UIBase {
// buildingWindow: BuildingWindow;
// buildingData: BuildingData;
// buildingUIItem: BuildingUIItem;
// isChangeType: boolean;//是修改模式
// needUpdateModel: boolean;//需要更新模型
// newName: string;
// onInit() {
// super.onInit();
// }
// onOpen() {
// super.onOpen();
// }
// onClose() {
// super.onClose();
// }
// initUI() {
// let window = this;
// let isChangeType = this.isChangeType;
// let outDoorData: ModelEditData = null;
// if (isChangeType) {
// this.buildingData = this.buildingUIItem.buildingInfo.buildingData;
// outDoorData = this.buildingUIItem.buildingInfo.buildingData.outdoorData;
// if (outDoorData == null) {
// this.buildingUIItem.buildingInfo.buildingData.outdoorData = new ModelEditData();
// outDoorData = this.buildingUIItem.buildingInfo.buildingData.outdoorData;
// outDoorData.modelData = new ModelData("model0", "空模型", null, null, null);
// }
// }
// else {
// this.buildingData = DataManager.createBulding("请输入", "key", BuildingType.Normal);
// outDoorData = this.buildingData.outdoorData;
// }
// this.root = new Rectangle("BuildingCreateWindow")
// UIManager.Instance.uiRoot.addControl(this.root);
// BabylonUIStyleTool.setDefaultStyle_windowRoot(this.root, true);
// BabylonUIStyleTool.setStyle_size(this.root, "300px", "482px");
// let stackPanel = new StackPanel("Root");
// BabylonUIStyleTool.setStyle_size(stackPanel, "250px", "440px");
// this.root.addControl(stackPanel);
// stackPanel.isVertical = true;
// let titleValue = isChangeType ? "修改建筑" : "新建建筑";
// let title = new TextBlock("title", titleValue);
// BabylonUIStyleTool.setStyle_size(title, "220px", "36px");
// stackPanel.addControl(title);
// title.color = "black";
// let name = new TextBlock("name", "名称");
// BabylonUIStyleTool.setStyle_size(name, "220px", "16px");
// name.fontSize = "16px";
// name.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
// stackPanel.addControl(name);
// name.color = "black";
// let space = new Rectangle("space");
// BabylonUIStyleTool.setStyle_size(space, "220px", "2px");
// stackPanel.addControl(space);
// let nameInput = BabylonUIStyleTool.createInputText("nameInput", stackPanel, "220px", "20px", "black", 0, undefined, BabylonUIStyleTool.c_color_gray, "black", BabylonUIStyleTool.c_color_gray);
// nameInput.inputText.onTextChangedObservable.add(() => {
// this.newName = nameInput.inputText.text;
// })
// let key = new TextBlock("key", "key");
// BabylonUIStyleTool.setStyle_size(key, "220px", "16px");
// key.fontSize = "16px";
// key.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
// stackPanel.addControl(key);
// key.color = "black";
// let keyInput = BabylonUIStyleTool.createInputText("keyInput", stackPanel, "220px", "20px", "black", 0, undefined, BabylonUIStyleTool.c_color_gray, "black", BabylonUIStyleTool.c_color_gray);
// keyInput.inputText.text = window.isChangeType ? window.buildingData.normalData.key : "defalult";
// keyInput.inputText.onTextChangedObservable.add(() => {
// this.buildingData.normalData.key = keyInput.inputText.text;
// })
// let space2 = new Rectangle("space2");
// BabylonUIStyleTool.setStyle_size(space2, "220px", "20px");
// stackPanel.addControl(space2);
// if (!isChangeType) {
// let type = new TextBlock("type", "建筑类型");
// BabylonUIStyleTool.setStyle_size(type, "220px", "36px");
// type.color = "black";
// type.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
// stackPanel.addControl(type);
// let group = "buildingType";
// let normalBuilding = BabylonUIStyleTool.createRadioButton("normalBuilding", stackPanel, group, "200px", "20px", BabylonUIStyleTool.c_color_blue, BabylonUIStyleTool.c_color_gray, "普通建筑", "150px", true, (select) => {
// if (select) {
// window.onSelectType(BuildingType.Normal);
// }
// });
// let space3 = new Rectangle("space3");
// BabylonUIStyleTool.setStyle_size(space3, "220px", "10px");
// stackPanel.addControl(space3);
// let environment = BabylonUIStyleTool.createRadioButton("environment", stackPanel, group, "200px", "20px", BabylonUIStyleTool.c_color_blue, BabylonUIStyleTool.c_color_gray, "环境", "150px", false, (select) => {
// if (select) {
// window.onSelectType(BuildingType.Environment);
// }
// });
// }
// nameInput.inputText.text = window.buildingData.normalData.name;
// let buildingTitle = new TextBlock("buildingTitle", "模型:");
// buildingTitle.color = "black";
// BabylonUIStyleTool.setStyle_size(buildingTitle, "220px", "20px");
// buildingTitle.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
// stackPanel.addControl(buildingTitle);
// let nowBuilding_name = new TextBlock("nowBuildingName", "模型名");
// nowBuilding_name.fontSize = "16px";
// nowBuilding_name.color = "black";
// nowBuilding_name.alpha = 0.8;
// BabylonUIStyleTool.setStyle_size(nowBuilding_name, "220px", "20px");
// nowBuilding_name.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
// stackPanel.addControl(nowBuilding_name);
// let input_buildingName = BabylonUIStyleTool.createInputText("input_buildingName", stackPanel, "220px", "18px");
// input_buildingName.inputText.fontSize = "16px";
// input_buildingName.bg.paddingLeft = "20px";
// input_buildingName.inputText.text = "-空";
// if (isChangeType && outDoorData.modelData != null && outDoorData.modelData.name != null) {
// input_buildingName.inputText.text = outDoorData.modelData.name;
// }
// input_buildingName.inputText.onTextChangedObservable.add(() => {
// outDoorData.modelData.name = input_buildingName.inputText.text;
// });
// let nowBuilding_key = new TextBlock("nowBuildingKey", "文件名");
// BabylonUIStyleTool.setStyle_size(nowBuilding_key, "220px", "20px");
// nowBuilding_key.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
// nowBuilding_key.color = "black";
// nowBuilding_key.fontSize = "16px";
// stackPanel.addControl(nowBuilding_key);
// let txt_buildingKey = BabylonUIStyleTool.createInputText("txt_buildingKey", stackPanel, "220px", "20px", undefined, 0, undefined, undefined, undefined, undefined);
// txt_buildingKey.bg.paddingLeft = "20px";
// txt_buildingKey.inputText.fontSize = "16px";
// if (isChangeType && outDoorData.modelData.key != null) {
// txt_buildingKey.inputText.text = outDoorData.modelData.key;
// }
// txt_buildingKey.inputText.onTextChangedObservable.add(() => {
// window.buildingData.outdoorData.modelData.key = txt_buildingKey.inputText.text;
// })
// let btn_changeModel = BabylonUIStyleTool.createBtn_OK("btn_createModel", "修改模型", "200px", "30px", "18px");
// btn_changeModel.onPointerClickObservable.add(() => {
// window.onChangeModel();
// })
// stackPanel.addControl(btn_changeModel);
// let space5 = new Rectangle("space5");
// BabylonUIStyleTool.setStyle_size(space5, "220px", "40px");
// stackPanel.addControl(space5);
// let btns = new StackPanel("btns");
// BabylonUIStyleTool.setStyle_size(btns, "220px", "40px");
// btns.isVertical = false;
// stackPanel.addControl(btns);
// let btn_OK = BabylonUIStyleTool.createBtn_OK("OK", "确定", "100px", "36px", "18px");
// btns.addControl(btn_OK);
// btn_OK.onPointerClickObservable.add(() => {
// window.onOK();
// })
// let space4 = new Rectangle("space4");
// BabylonUIStyleTool.setStyle_size(space4, "20px", "36px");
// btns.addControl(space4);
// let btn_cancle = BabylonUIStyleTool.createBtn_Cancel("cancel", "取消", "100px", "36px", "18px");
// btns.addControl(btn_cancle);
// btn_cancle.onPointerClickObservable.add(() => {
// window.onCancel();
// });
// if (this.isChangeType) {
// let btn_delete = BabylonUIStyleTool.createBtn_Delete("delete", "删", "30px", "30px", "18px");
// this.root.addControl(btn_delete);
// btn_delete.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
// btn_delete.verticalAlignment = Control.VERTICAL_ALIGNMENT_BOTTOM;
// btn_delete.onPointerClickObservable.add(() => {
// window.onBtn_delete();
// })
// }
// }
// //初始化新建
// init(buildingWindow: BuildingWindow) {
// this.buildingWindow = buildingWindow;
// this.isChangeType = false;
// this.initUI();
// }
// //初始化修改
// initChange(buildingWindow: BuildingWindow, buildingUIItem: BuildingUIItem) {
// this.buildingUIItem = buildingUIItem;
// this.buildingWindow = buildingWindow;
// this.isChangeType = true;
// this.initUI();
// }
// //选择建筑类型
// onSelectType(buildingType: BuildingType) {
// this.buildingData.buildingType = buildingType;
// // this.key = DataManager.institutionData.getNewKey(buildingType);
// console.log("选择建筑类型" + buildingType + "key =" + this.buildingData.normalData.key);
// }
// //修改模型
// onChangeModel() {
// console.log("修改模型");
// let normalData = this.buildingData.normalData;
// let resPath_out = DataManager.getResPath_building(
// DataManager.institutionData.normalData.key.toLowerCase(),
// normalData.key.toLocaleLowerCase(),
// BuildingPosType.OutDoor,
// this.buildingData.outdoorData.modelData.key
// );
// console.log("新资源路径" + resPath_out);
// let instance = this;
// ServeManager.instance.openFileSelect(resPath_out, (name: string, path: string) => {
// if (TsTool.stringContain(name, ".gltf")) {
// this.buildingData.outdoorData.modelData.resName = name;
// this.buildingData.outdoorData.modelData.resPath = path;
// }
// instance.needUpdateModel = true;
// });
// }
// //确定
// onOK() {
// if (this.buildingData.normalData.name == null) {
// alert("请输入名称");
// }
// else {
// console.log("修改模式" + this.isChangeType);
// if (this.isChangeType) {
// // let normalData = this.buildingUIItem.buildingInfo.buildingData.normalData;
// // normalData.name = this.buildingData.normalData.name;
// this.buildingUIItem.changeName(this.newName);
// // this.buildingUIItem.updateUI();
// Event_ModelInfoChange.dispatch(this.buildingUIItem.buildingInfo.ModelInfo, ModelChangeType.Update);
// this.closeWindow();
// }
// else {
// if (this.buildingData.buildingType == null) {
// alert("请选择建筑类型")
// }
// else {
// let result = this.buildingData;
// this.buildingData.normalData.name = this.newName;
// if (result != null) {
// this.closeWindow();
// console.log("=======addOneBuilding");
// console.log(result);
// this.buildingWindow.addOneBuilding(result, -1);
// }
// }
// }
// }
// }
// //取消
// onCancel() {
// this.closeWindow();
// }
// //删除
// onBtn_delete() {
// this.buildingWindow.deleteBuilding(this.buildingUIItem);
// this.closeWindow();
// }
// //关闭界面
// closeWindow() {
// if (this.isChangeType) {
// this.buildingUIItem.closeChangeWindow();
// console.log("需要修改模型" + this.needUpdateModel);
// if (this.needUpdateModel) {
// this.buildingUIItem.buildingWindow.updateBuildingModel(this.buildingUIItem.buildingInfo, true);
// }
// }
// else {
// this.buildingWindow.closeCreateWindow();
// }
// }
// }

212
src/app/babylon/view/building-window/building-ui-item.ts

@ -0,0 +1,212 @@
import { SceneManager } from "../../controller/scene-manager";
import { IndoorStatus } from "../../controller/status/indoor-status";
import { StatusManager } from "../../controller/status/status-manager";
import { BuildingType, BuildingData_Normal } from "../../model/data/institution/building/building-data";
import { ModelEditData } from "../../model/data/model-data/model-edit-data";
import { BuildingInfo } from "../../model/info/building/building-info";
import { ModelInfo_building } from "../../model/info/model/model-info-building";
import { BabylonTool } from "../../tool/babylon-tool";
import { GizmoTool } from "../../tool/gizmo-tool";
import { MarkWindow } from "../mark-window/mark-window";
// import { BuildingCreateWindow } from "./building-create-window";
import { BuildingWindow } from "./building-window";
//建筑UI Item
export class BuildingUIItem {
buildingInfo: BuildingInfo;
buildingWindow: BuildingWindow;
constructor(buildingInfo: BuildingInfo, buildingWindow: BuildingWindow) {
this.buildingWindow = buildingWindow;
this.buildingInfo = buildingInfo;
}
dispose() {
this.buildingInfo.dispose();
}
//#region 前端对接
/**
* ID
*/
getBuildingID(): string {
return this.buildingInfo.buildingData.normalData.key;
}
/**
*
*/
getBuildingName(): string {
return this.buildingInfo.buildingData.normalData.name;
}
/**
*
*/
setBuildingName(newName: string) {
this.changeName(newName);
}
/**
*
*/
getBuildingType(): BuildingType {
return this.buildingInfo.buildingData.buildingType;
}
/**
* (null ,)
*/
getAllIndoorData(): ModelEditData[] {
if (this.buildingInfo.buildingData instanceof BuildingData_Normal) {
let buildingData: BuildingData_Normal = this.buildingInfo.buildingData as BuildingData_Normal;
let result = buildingData.indoorsData;
return result;
}
else {
return null;
}
}
/**
*
* ui的切换()
*/
enterIndoor(key: string = null, fromUI: boolean = true) {
GizmoTool.onPickMeshInfoObservable.notifyObservers(null);
IndoorStatus.changeStatusFromUI = fromUI;
if (fromUI && MarkWindow.instance != null && MarkWindow.instance.isShow && MarkWindow.instance.currentMarkNodeInfo != null) {
if (key == null) {
let indoorsData = (this.buildingInfo.buildingData as BuildingData_Normal).indoorsData;
if (indoorsData != null && indoorsData.length > 0) {
key = indoorsData[0].modelData.key;
}
else {
//ThreeDimensionalHomeComponent.instance.openSnackBar("暂无室内信息");
// alert("暂无室内信息");
return;
}
}
MarkWindow.instance.changeBuilding(false, this.buildingInfo.buildingData.normalData.key, key);
}
else {
console.log("进入室内");
let indoorStatus = StatusManager.enterStatus<IndoorStatus>(IndoorStatus);
indoorStatus.init(this.buildingInfo, key);
}
}
/**
*
* @param buildingData
*/
changeModel(file: File[]) {
this.buildingWindow.changeModel(file, this.buildingInfo.buildingData);
}
/**
* id
* @param id
*/
linkingBuildingID(id: string) {
this.buildingInfo.buildingData.buildingIDFromPlatform = id;
}
/**
* id
*/
getlinkedBuildingID(): string {
return this.buildingInfo.buildingData.buildingIDFromPlatform;
}
//#endregion
//#region 外部公有
/**
*
*/
select() {
this.buildingWindow.onChangeCurrentBuildingItem(this);
}
/**
*
* @param select true表示选中
*/
onSelect(select: boolean, animMove = true) {
if (select) {
if (this.buildingInfo.ModelInfo != null && this.buildingInfo.ModelInfo.modelBox != null) {
GizmoTool.onPickMeshInfoObservable.notifyObservers(this.buildingInfo.ModelInfo);
//BabylonTool.changeCameraTarget(SceneManager.Instance.defaultCamera, this.buildingInfo.ModelInfo.modelBox, animMove);
}
}
else {
if (this.buildingInfo != null) {
GizmoTool.leaveTheGizmoAim(this.buildingInfo.ModelInfo);
}
}
}
/**
*
*/
lookAt(anim: boolean = true) {
if (this.canLookAt()) {
BabylonTool.changeCameraTarget(SceneManager.Instance.defaultCamera, this.buildingInfo.ModelInfo.modelBox, anim);
}
}
/**
*
*/
canLookAt(): boolean {
let result = this.buildingInfo != null && this.buildingInfo.ModelInfo != null && this.buildingInfo.ModelInfo.modelBox != null;
return result;
}
/**
*
*/
setModelEnable(show: boolean) {
if (this.buildingInfo != null) {
this.buildingInfo.setEnable(show);
}
}
//#endregion
//#region 内部私有
//修改建筑名称
private changeName(name: string) {
this.buildingInfo.buildingData.normalData.name = name;
if (this.buildingInfo.ModelInfo != null) {
(this.buildingInfo.ModelInfo as ModelInfo_building).updateName(name);
}
}
//#endregion
}

499
src/app/babylon/view/building-window/building-window.ts

@ -0,0 +1,499 @@
import { DataManager } from "../../controller/data-manager";
import { InfoManager } from "../../controller/info-manager";
import { SceneManager } from "../../controller/scene-manager";
import { ServeManager } from "../../controller/serve-manager";
import { BuildingStatus } from "../../controller/status/building-status";
import { StatusManager } from "../../controller/status/status-manager";
import { BuildingData_Normal, BuildingData_Environment, BuildingData_ChemicalPlant, BuildingType, BuildingData } from "../../model/data/institution/building/building-data";
import { BuildingPosType, ModelType } from "../../model/data/model-data/model-data";
import { FacilityType } from "../../model/data/model-data/model-data-facility";
import { ModelEditData } from "../../model/data/model-data/model-edit-data";
import { BuildingInfo } from "../../model/info/building/building-info";
import { BuildingInfo_ChemicalPlant } from "../../model/info/building/building-info-chemicalplant";
import { BuildingInfo_Environment } from "../../model/info/building/building-info-environment";
import { BuildingInfo_Normal } from "../../model/info/building/building-info-normal";
import { ModelInfo_building } from "../../model/info/model/model-info-building";
import { TsTool } from "../../tool/ts-tool";
import { UIBase } from "../window-base/ui-base";
import { BuildingUIItem } from "./building-ui-item";
//建筑界面
export class BuildingWindow extends UIBase {
buldingStatus: BuildingStatus;
buildingUIItems: BuildingUIItem[] = [];//所有建筑UI
currentBuidngItem: BuildingUIItem; //当前正在操作的建筑
// three: ThreeDimensionalHomeComponent;//前端组件
//#region 与前端对接部分
/**
* UI上添加一个建筑item
* @param buildingData data数据
* @param index
* @param onSuccess
*/
createOneBuildingItem(buildingData: BuildingData_Normal | BuildingData_Environment | BuildingData_ChemicalPlant, index: number, onSuccess?: (buildingUIItem: BuildingUIItem, index: number) => void) {
let buildingInfo: BuildingInfo_Normal | BuildingInfo_Environment | BuildingInfo_ChemicalPlant;
switch (buildingData.buildingType) {
case BuildingType.Normal:
buildingInfo = new BuildingInfo_Normal(buildingData as BuildingData_Normal, null);
break;
case BuildingType.Environment:
buildingInfo = new BuildingInfo_Environment(buildingData, null);
break;
case BuildingType.ChemicalPlant:
buildingInfo = new BuildingInfo_ChemicalPlant(buildingData, null);
break;
}
// console.log("初始化建筑info");
// console.log(buildingInfo.buildingData);
let uiItem = this.addBuildingItem(buildingInfo);
if (buildingData.outdoorData != null && buildingData.outdoorData.modelData != null && buildingData.outdoorData.modelData.resName != null) {
this.updateBuildingModel(buildingInfo, false, () => {
buildingInfo.initFacility();
BuildingStatus.enterSuccessObservable.notifyObservers(uiItem);
if (onSuccess) {
onSuccess(uiItem, index);
}
})
}
}
//删除建筑
deleteBuilding(buidlingUIItem: BuildingUIItem) {
// console.log("删除建筑" + buidlingUIItem.buildingInfo.buildingData.normalData.key);
DataManager.deleteOneBuildingData(buidlingUIItem.buildingInfo.buildingData.buildingType, buidlingUIItem.buildingInfo.buildingData.normalData.key);
for (let i = 0; i < this.buildingUIItems.length; i++) {
if (this.buildingUIItems[i] == buidlingUIItem) {
buidlingUIItem.dispose();
TsTool.arrayRemove(this.buildingUIItems, buidlingUIItem);
break;
}
}
}
/**
*
* @param file
*/
changeModel(file: File[], buildingData: BuildingData) {
if (file == null || file.length == 0) {
return;
}
console.log("修改模型");
buildingData.outdoorData.modelData.key = buildingData.normalData.key;
buildingData.outdoorData.modelData.name = buildingData.normalData.key;
let normalData = buildingData.normalData;
let resPath_out = DataManager.getResPath_building(
DataManager.institutionData.normalData.key.toLowerCase(),
normalData.key.toLocaleLowerCase(),
BuildingPosType.OutDoor,
buildingData.normalData.key
);
// console.log("新资源路径" + resPath_out);
let buildingWindow = this;
let manifestFile: File = null;
if (buildingData.outdoorData.modelData.resName != null) {
manifestFile = DataManager.createManifestFile(buildingData.outdoorData.modelData);
file.push(manifestFile); //临时关闭缓存文件
}
ServeManager.instance.uploadFile(0, file, resPath_out, (name: string, path: string, currentfile) => {
if (TsTool.stringContain(name, ".gltf")) {
if (TsTool.stringContain(name, ".gltf.manifest")) {
//缓存文件,提取版本号
DataManager.readFile_manifest(currentfile, (version: number) => {
buildingData.outdoorData.modelData.version = version;
// console.log("设置version" + version);
});
}
else {
buildingData.outdoorData.modelData.resName = name;
buildingData.outdoorData.modelData.resPath = path;
if (manifestFile == null) {
manifestFile = DataManager.createManifestFile(buildingData.outdoorData.modelData);
file.push(manifestFile);
}//临时关闭缓存文件
}
}
}
, () => {
let buildingInfo = buildingWindow.getBuildingInfo(buildingData.normalData.key);
buildingWindow.updateBuildingModel(buildingInfo, true);
// buildingWindow.three = ThreeDimensionalHomeComponent.instance;
// buildingWindow.three.maskLayerService.sendMessage(false) //关闭遮罩层
});
}
/**
*
*/
getNormalBuildingIndoorFacilitys(buildingUIItem: BuildingUIItem, facilityType: FacilityType) {
let result = 0;
if (buildingUIItem.buildingInfo.buildingData.buildingType != BuildingType.Normal) {
//不是普通建筑,没有室内
}
else {
let indoorData: ModelEditData[] = (buildingUIItem.buildingInfo.buildingData as BuildingData_Normal).indoorsData;
if (indoorData != null) {
for (let i = 0; i < indoorData.length; i++) {
let facilitiesByType = indoorData[i].getFacilitiesByType(facilityType);
if (facilitiesByType != null) {
result += facilitiesByType.length;
}
}
}
}
return result;
}
/**
*
*/
changeToFirstIndoorByFacility(buildingUIItem: BuildingUIItem, facilityType: FacilityType) {
let result = false;//是否成功找到并进入某室内层
let num = 0;
if (buildingUIItem.buildingInfo.buildingData.buildingType != BuildingType.Normal) {
//不是普通建筑,没有室内
}
else {
let indoorData: ModelEditData[] = (buildingUIItem.buildingInfo.buildingData as BuildingData_Normal).indoorsData;
for (let i = 0; i < indoorData.length; i++) {
let facilitiesByType = indoorData[i].getFacilitiesByType(facilityType);
if (facilitiesByType != null) {
num += facilitiesByType.length;
}
if (num > 0) {
result = true;
buildingUIItem.enterIndoor(indoorData[i].modelData.key, true);
break;
}
}
}
return result;
}
//#endregion
//#region 生命周期
onInit() {
super.onInit();
this.buldingStatus = StatusManager.getStatus<BuildingStatus>(BuildingStatus);
this.initBuildings();//创建每一个建筑buildingItem
// this.three = ThreeDimensionalHomeComponent.instance;
// this.three.getAllBuilding(this);
}
onShow() {
this.showModel(true);
super.onShow();
}
onHide() {
this.showModel(false);
super.onHide();
}
//#endregion
//#region 外部公有
/**
*
* @param buildingInfo
*/
clearFacilityInfos(buildingInfo: BuildingInfo) {
if (buildingInfo.ModelInfo != null) {
for (let i = 0; i < buildingInfo.ModelInfo.facilityInfos.length; i++) {
buildingInfo.ModelInfo.facilityInfos[i].dispose();
}
buildingInfo.ModelInfo.facilityInfos = [];
}
}
/**
* icon
* @param buildingInfo
* @param show
*/
showFacilityInfosIcon(buildingInfo: BuildingInfo, show: boolean) {
if (buildingInfo.ModelInfo != null) {
buildingInfo.ModelInfo.showFacilityUI(show);
}
}
/**
* buildingInfo找到item
* @param buildingInfo
*/
changeCurrentBuildingInfo(modelInfo: ModelInfo_building) {
let item: BuildingUIItem = null;
for (let i = 0; i < this.buildingUIItems.length; i++) {
if (this.buildingUIItems[i].buildingInfo.ModelInfo == modelInfo) {
item = this.buildingUIItems[i];
break;
}
}
//this.onChangeCurrentBuildingItem(item);
// this.three.selectLeftBuilding(item);
}
/**
*
* @param buidlingUIItem
*/
onChangeCurrentBuildingItem(buidlingUIItem: BuildingUIItem, animMove = true) {
if (this.currentBuidngItem != null && this.currentBuidngItem != buidlingUIItem) {
this.currentBuidngItem.onSelect(false);
}
this.currentBuidngItem = buidlingUIItem;
this.currentBuidngItem.onSelect(true, animMove);
this.buldingStatus.changeCurrentBuilding(buidlingUIItem.buildingInfo);
}
/**
* buildingKey
* @param key
*/
public getBuildingInfo(key: string): BuildingInfo {
for (let i = 0; i < this.buildingUIItems.length; i++) {
if (this.buildingUIItems[i].buildingInfo.buildingData.normalData.key == key) {
return this.buildingUIItems[i].buildingInfo;
}
}
return null;
}
/**
* UIItem
* @param key
*/
public getBuildingUIItem(key: string) {
for (let i = 0; i < this.buildingUIItems.length; i++) {
if (this.buildingUIItems[i].buildingInfo.buildingData.normalData.key == key) {
return this.buildingUIItems[i];
}
}
return null;
}
/**
*
* @param buildingInfo
* @param updateFacility
* @param onSuccess
*/
public updateBuildingModel(buildingInfo: BuildingInfo, updateFacility: boolean, onSuccess?: () => void) {
if (buildingInfo == null) {
return;
}
if (buildingInfo.ModelInfo != null) {
buildingInfo.ModelInfo.dispose();
}
SceneManager.createModel(ModelType.Building, buildingInfo.buildingData.outdoorData.modelData, true, true, "Building", (newMesh, box, modelInfo) => {
buildingInfo.ModelInfo = modelInfo as ModelInfo_building;
buildingInfo.ModelInfo.updateName(buildingInfo.buildingData.normalData.name);
if (updateFacility) {
InfoManager.createFacilityInfos(buildingInfo.buildingData.outdoorData, buildingInfo);
}
if (buildingInfo instanceof BuildingInfo_Environment) {
buildingInfo.updateFuGaiCeng();
}
if (onSuccess) {
onSuccess();
}
});
}
//#endregion
//#region 内部私有
//填充建筑列表
private initBuildings() {
//因为babylon内对indexDB的封装使用有问题,在用户第一次使用时触发了创建数据库操作,导致我们同时调用多个加载方法时报错
//解决策略是:如果发现有多个模型要加载,则先加载第一个模型,保证indexDB数据库正常建立, 第一个加载完成后,在加载剩余模型
BuildingStatus.startEnterObservable.notifyObservers(null);
let instance = this;
let firstItem; //第一个要加载的模型
let firstType: BuildingType;
let allModelNumber = 0;
let buildingDatas_Environment = DataManager.getBuildingDataListByType(BuildingType.Environment);
if (buildingDatas_Environment != null) {
allModelNumber += buildingDatas_Environment.length;
if (buildingDatas_Environment.length > 0) {
firstItem = buildingDatas_Environment[0];
firstType = BuildingType.Environment;
}
}
let buildingDatas_mormal = DataManager.getBuildingDataListByType(BuildingType.Normal);
if (buildingDatas_mormal != null) {
allModelNumber += buildingDatas_mormal.length;
if (buildingDatas_mormal.length > 0) {
firstItem = buildingDatas_mormal[0];
firstType = BuildingType.Normal;
}
}
if (allModelNumber > 1) {
if (firstType == BuildingType.Environment) {
instance.createOneBuildingItem(firstItem, 0, (uiItem, index) => {
instance.onChangeCurrentBuildingItem(uiItem, false);
uiItem.lookAt(false);
if (buildingDatas_Environment.length > 1) {
instance.addBuildings(BuildingType.Environment, 1);
}
instance.addBuildings(BuildingType.Normal, 0);
});
}
else {
instance.createOneBuildingItem(firstItem, 0, (uiItem, index) => {
instance.onChangeCurrentBuildingItem(uiItem, false);
uiItem.lookAt(false);
if (buildingDatas_mormal.length > 1) {
instance.addBuildings(BuildingType.Normal, 1);
}
instance.addBuildings(BuildingType.Environment, 0);
});
}
}
else {
instance.addBuildings(BuildingType.Normal, 0, (uiItem, index) => {
if (index == 0 && uiItem.buildingInfo.isEnable) {
instance.onChangeCurrentBuildingItem(uiItem, false);
uiItem.lookAt(false);
// console.log("默认选中" + uiItem.buildingInfo.buildingData.normalData.key);
}
});
instance.addBuildings(BuildingType.Environment, 0);
}
}
//初始化建筑显示(根据类别)
private addBuildings(buildingType: BuildingType, startIndex: number, onSuccess?: (buildingUIItem: BuildingUIItem, index: number) => void) {
let index = startIndex;
let buildingDatas = DataManager.getBuildingDataListByType(buildingType);
// console.log(buildingDatas);
while (buildingDatas != null && index < buildingDatas.length) {
let l_index = index;
let buildingData = buildingDatas[l_index];
this.createOneBuildingItem(buildingData, l_index, onSuccess);
index++;
}
}
//添加一个item到界面中
private addBuildingItem(buildingInfo: BuildingInfo): BuildingUIItem {
let buildingItem = new BuildingUIItem(buildingInfo, this);
this.buildingUIItems.push(buildingItem);
return buildingItem;
}
/**
*
* @param show true-
*/
private showModel(show: boolean) {
for (let i = 0; i < this.buildingUIItems.length; i++) {
//周围环境,不隐藏(也就不用再显示)
if (this.buildingUIItems[i].buildingInfo.ModelInfo.buildingType == BuildingType.Environment) {
(this.buildingUIItems[i].buildingInfo as BuildingInfo_Environment).updateFuGaiCeng();
if (show) { //切换到室外时,根据选中状态恢复设备UI
if (this.currentBuidngItem == this.buildingUIItems[i]) {
this.buildingUIItems[i].buildingInfo.ModelInfo.showFacilityUI(show);
}
else {
this.buildingUIItems[i].buildingInfo.ModelInfo.showFacilityUI(false);
}
this.buildingUIItems[i].buildingInfo.ModelInfo.showFollowUI(true);//环境的名称UI 不显示
}
else { //切换到室内时,显示环境的设备UI
this.buildingUIItems[i].buildingInfo.ModelInfo.showFacilityUI(false);//(感觉太乱,暂时取消)
this.buildingUIItems[i].buildingInfo.ModelInfo.showFollowUI(false);//环境的名称UI 不显示
}
}
else { // 建筑,正常显隐
this.buildingUIItems[i].setModelEnable(show);
}
// if (this.buildingUIItems[i].buildingInfo != null) {
// this.buildingUIItems[i].buildingInfo.setEnable(show);
// }
}
}
//#endregion
}

131
src/app/babylon/view/dialog-window/dialog-window.ts

@ -0,0 +1,131 @@
// import { Button, Control, Rectangle, TextBlock } from "@babylonjs/gui";
// import { ThreeDimensionalHomeComponent } from "src/app/gis/three-dimensional-home/three-dimensional-home.component";
// import { UIManager } from "src/babylon/controller/ui-manager";
// import { BabylonUIStyleTool } from "src/babylon/tool/babylon-ui-style-tool";
// import { UIBase } from "../window-base/ui-base";
// //对话框
// export class DialogWindow extends UIBase {
// title: string;//标题
// content: string;//内容描述
// okText: string;//确定按钮上的文字
// okCallBack?: () => void; //确定按钮的回调
// cancelText: string;//取消按钮上的文字
// cancelCallBack?: () => void;//取消按钮的回调
// static OpenDialog(title: string, content: string, okText: string, okCallBack?: () => void, cancelText?: string, cancelCallBack?: () => void) {
// let result: DialogWindow = UIManager.open<DialogWindow>(DialogWindow);
// result.initInfo(title, content, okText, okCallBack, cancelText, cancelCallBack);
// result.initUI();
// return result;
// }
// onInit() {
// super.onInit();
// }
// onOpen() {
// super.onOpen();
// }
// onClose() {
// super.onClose();
// }
// //初始化信息
// initInfo(title: string, content: string, okText: string, okCallBack?: () => void, cancelText?: string, cancelCallBack?: () => void) {
// this.title = title;
// this.content = content;
// this.okText = okText;
// this.okCallBack = okCallBack;
// this.cancelText = cancelText;
// this.cancelCallBack = cancelCallBack;
// }
// //初始化界面
// initUI() {
// this.root = new Rectangle("DialogWindow");
// this.root.zIndex = 900;
// UIManager.Instance.uiRoot.addControl(this.root);
// this.root.width = "200px";
// this.root.height = "150px";
// this.root.background = UIBase.color_gray;
// this.root.thickness = 0;
// this.root.cornerRadius = BabylonUIStyleTool.cornerRadius_window1;
// let ui_title = new TextBlock("title");
// this.root.addControl(ui_title);
// ui_title.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
// ui_title.height = "30px";
// ui_title.text = this.title;
// ui_title.fontSize = 22;
// ui_title.color = "white";
// let ui_content = new TextBlock("content");
// this.root.addControl(ui_content);
// ui_content.width = "180px";
// ui_content.height = "100px";
// ui_content.text = this.content;
// ui_content.color = "white";
// ui_content.textWrapping = true;
// let btn_ok = Button.CreateSimpleButton("btn_ok", this.okText);
// this.root.addControl(btn_ok);
// btn_ok.width = "90px";
// btn_ok.height = "30px";
// btn_ok.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
// btn_ok.verticalAlignment = Control.VERTICAL_ALIGNMENT_BOTTOM;
// btn_ok.paddingLeft = "20px";
// btn_ok.background = BabylonUIStyleTool.c_color_green;
// btn_ok.textBlock.color = "white";
// btn_ok.thickness = 0;
// btn_ok.cornerRadius = BabylonUIStyleTool.cornerRadius_window1;
// btn_ok.onPointerClickObservable.add(() => {
// this.onOK(this.okCallBack);
// });
// let btn_Cancel = Button.CreateSimpleButton("btn_cancel", this.cancelText);
// this.root.addControl(btn_Cancel);
// btn_Cancel.width = "90px";
// btn_Cancel.height = "30px";
// btn_Cancel.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_RIGHT;
// btn_Cancel.verticalAlignment = Control.VERTICAL_ALIGNMENT_BOTTOM;
// btn_Cancel.paddingRight = "20px";
// btn_Cancel.background = UIBase.color_red;
// btn_Cancel.color = "white";
// btn_Cancel.thickness = 0;
// btn_Cancel.cornerRadius = BabylonUIStyleTool.cornerRadius_window1;
// btn_Cancel.onPointerClickObservable.add(() => {
// this.onConcel(this.cancelCallBack);
// });
// }
// //确定按钮回调
// onOK(okCallBack?: () => void) {
// if (okCallBack != null) {
// okCallBack();
// }
// this.onClickBtn();
// }
// //取消按钮回调
// onConcel(cancelCallBack?: () => void) {
// if (cancelCallBack != null) {
// cancelCallBack();
// }
// this.onClickBtn();
// }
// //按钮统一行为
// onClickBtn() {
// UIManager.close<DialogWindow>(this);
// }
// }

90
src/app/babylon/view/facility-window/facility-ui-item.ts

@ -0,0 +1,90 @@
import { AbstractMesh } from "@babylonjs/core";
import { Button, Rectangle } from "@babylonjs/gui";
import { ConfigManager } from "../../controller/config-manager";
import { ModeManager, ModeType } from "../../controller/mode-manager";
import { SceneManager } from "../../controller/scene-manager";
import { ModelType } from "../../model/data/model-data/model-data";
import { ModelData_facility, FacilityShowType } from "../../model/data/model-data/model-data-facility";
import { BabylonTool } from "../../tool/babylon-tool";
import { LoadTool } from "../../tool/load-tool";
import { MeshPoolInfo, MeshPool } from "../../tool/mesh-pool";
import { FacilityInfoInSceneWindow } from "../facilityinfoinscene-window/facilityinfoinscene-window";
import { FacilityWindow } from "./facility-window";
//设施UI item
export class FacilityUIItem {
facilityData: ModelData_facility;
meshPrefab: AbstractMesh;
meshPoolInfo: MeshPoolInfo;
constructor(facilityData: ModelData_facility, root: Rectangle, button: Button) {
this.facilityData = facilityData;
let instance = this;
if (facilityData.getShowtype() == FacilityShowType.ModelAndTag) {
instance.meshPoolInfo = MeshPool.importMesh(ModelType.Facility, facilityData, true, true, LoadTool.c_tag_facilityPrefab, (mesh, meshes, result: MeshPoolInfo) => {
instance.meshPrefab = mesh;
mesh.name = "pfb_" + this.facilityData.key;
mesh.setEnabled(false);
result.modelInfo.showFollowUI(false);
if (!SceneManager.s_openLight) {
BabylonTool.setMatToUnlit(meshes, true);
}
})
}
}
//#region 前端对接
//获取图片URL
getIconURL() {
return ConfigManager.getFacilityIconUrl(this.facilityData.facilityType, this.facilityData.posType)
}
//获取图片key
getIconID() {
return this.facilityData.key
}
//获取设备中文名
getIconName() {
return this.facilityData.name
}
//取消选择 当前设备
unSelect() {
FacilityWindow.instance.clearCurrentFacility();
}
/**
*
*/
select() {
FacilityWindow.instance.onClickFacilityBtn(this);
}
//#endregion
//选中时的表现
onSelect(select: boolean) {
if (ModeManager.currentMode == ModeType.Look) //只在查看模式下生效
{
FacilityInfoInSceneWindow.instance.showFacilityByType(this.facilityData.facilityType, select);
}
}
dispose() {
if (this.meshPoolInfo != null) {
//MeshPool.disposeMesh(this.meshPoolInfo);
this.meshPoolInfo.dispose();
this.meshPoolInfo = null;
}
}
}

521
src/app/babylon/view/facility-window/facility-window.ts

@ -0,0 +1,521 @@
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创建完成
BabylonTool.importMeshSync(null, "assets/facilities/outdoor/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);
}
// 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;
}
}

202
src/app/babylon/view/facilityinfoinscene-window/facilityinfo-ui-item.ts

@ -0,0 +1,202 @@
import { SceneManager } from "../../controller/scene-manager";
import { PropertyData_Base_IMG } from "../../model/data/institution/facility/property-data/base/property-data-base-img";
import { PropertyData_Base_SBJHQ } from "../../model/data/institution/facility/property-data/base/property-data-base-sbjhq";
import { PropertyData_Base_XFB } from "../../model/data/institution/facility/property-data/base/property-data-base-xfb";
import { PropertyData_Base_XHS } from "../../model/data/institution/facility/property-data/base/property-data-base-xhs";
import { PropertyData_DWBZ } from "../../model/data/institution/facility/property-data/indoor/property-data-dwbz";
import { PropertyData_FHFQ } from "../../model/data/institution/facility/property-data/indoor/property-data-fhfq";
import { PropertyData_SSLT } from "../../model/data/institution/facility/property-data/indoor/property-data-sslt";
import { PropertyData_XFDT } from "../../model/data/institution/facility/property-data/indoor/property-data-xfdt";
import { PropertyData_ZDQY } from "../../model/data/institution/facility/property-data/indoor/property-data-zdqy";
import { PropertyData_AQCK } from "../../model/data/institution/facility/property-data/outdoor/property-data-aqck";
import { PropertyData_GD } from "../../model/data/institution/facility/property-data/outdoor/property-data-gd";
import { PropertyData_PL } from "../../model/data/institution/facility/property-data/outdoor/property-data-pl";
import { PropertyData_Q } from "../../model/data/institution/facility/property-data/outdoor/property-data-q";
import { PropertyData_Base } from "../../model/data/institution/facility/property-data/property-data-base";
import { FacilityType, ModelData_facility } from "../../model/data/model-data/model-data-facility";
import { ModelInfo_facility } from "../../model/info/model/model-info-facility";
import { BabylonTool } from "../../tool/babylon-tool";
import { GizmoTool } from "../../tool/gizmo-tool";
import { TsTool } from "../../tool/ts-tool";
import { FacilityInfoInSceneWindow } from "./facilityinfoinscene-window";
//单个场景中的设备 UI item
export class FacilityInfoUIItem {
modelInfo: ModelInfo_facility;
facilityInfoInSceneWindow: FacilityInfoInSceneWindow;
isSelect: boolean = false;
isChecked: boolean = false; //是否 选中
// facilityBtn: Button;
constructor(modelInfo: ModelInfo_facility, facilityInfoInSceneWindow: FacilityInfoInSceneWindow) {
this.modelInfo = modelInfo;
this.facilityInfoInSceneWindow = facilityInfoInSceneWindow;
this.initUI();
}
//#region 前端对接
l_name = null;
/**
*
*/
getName(): string {
return this.modelInfo.modelData.name;
}
/**
*
*/
getType(): FacilityType {
return (this.modelInfo.modelData as ModelData_facility).facilityType;
}
/**
* ID
*/
getID(): string {
return this.modelInfo.key;
}
/**
*
*/
getPropertyData() {
let facilityData
// = (this.modelInfo.modelData as ModelData_facility).propertyData as any;
if ((this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.AQCK) {
//安全出口
facilityData = (this.modelInfo.modelData as ModelData_facility).propertyData as PropertyData_AQCK;
} else if ((this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.DSXHS || (this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.DXXHS || (this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.SZDSXHS || (this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.SZDXXHS) {
//消火栓
facilityData = (this.modelInfo.modelData as ModelData_facility).propertyData as PropertyData_Base_XHS;
} else if ((this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.DSSBJHQ || (this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.DXSBJHQ || (this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.QBSBJHQ || (this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.DGNSBJHQ) {
//水泵接合器
facilityData = (this.modelInfo.modelData as ModelData_facility).propertyData as PropertyData_Base_SBJHQ;
} else if ((this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.GD) {
//高度
facilityData = (this.modelInfo.modelData as ModelData_facility).propertyData as PropertyData_GD;
} else if ((this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.PL) {
//毗邻
facilityData = (this.modelInfo.modelData as ModelData_facility).propertyData as PropertyData_PL;
} else if ((this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.TPBZ || (this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.XKS || (this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.BF || (this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.SX) {
//图片标注,消控室,泵房,水箱
facilityData = (this.modelInfo.modelData as ModelData_facility).propertyData as PropertyData_Base_IMG;
} else if ((this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.JJQ || (this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.JTQ) {
//集结区,禁停区
facilityData = (this.modelInfo.modelData as ModelData_facility).propertyData as PropertyData_Q;
}
else if ((this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.LSXFB || (this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.WSXFB || (this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.CYXFB) {
//消防泵
facilityData = (this.modelInfo.modelData as ModelData_facility).propertyData as PropertyData_Base_XFB;
} else if ((this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.FHFQ) {
//防火分区
facilityData = (this.modelInfo.modelData as ModelData_facility).propertyData as PropertyData_FHFQ;
} else if ((this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.FHM) {
//防火门
} else if ((this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.FHJL) {
//防火卷帘
} else if ((this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.SSLT) {
//疏散楼梯
facilityData = (this.modelInfo.modelData as ModelData_facility).propertyData as PropertyData_SSLT;
} else if ((this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.XFDT) {
//消防电梯
facilityData = (this.modelInfo.modelData as ModelData_facility).propertyData as PropertyData_XFDT;
} else if ((this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.PTDT) {
//普通电梯
facilityData = null
} else if ((this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.ZDQY) {
//重点区域
facilityData = (this.modelInfo.modelData as ModelData_facility).propertyData as PropertyData_ZDQY;
} else if ((this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.WXY || (this.modelInfo.modelData as ModelData_facility).facilityType == FacilityType.DWBZ) {
//危险源,点位标注
facilityData = (this.modelInfo.modelData as ModelData_facility).propertyData as PropertyData_DWBZ;
} else {
//未匹配到的
facilityData = null
}
return facilityData
}
/**
*
* @param propertyData
*/
pasteProperty(propertyData: PropertyData_Base) {
let facilityData = this.modelInfo.modelData as ModelData_facility;
let key = facilityData.propertyData.key;
facilityData.propertyData = propertyData.clone(key);
console.log("粘贴属性");
}
/**
*
* @param ask true表示询问false表示不询问
*/
askDelete(ask: boolean = true) {
this.modelInfo.askDelete(this.modelInfo, ask);
}
//#endregion
initUI() {
}
dispose() {
TsTool.arrayRemove(this.facilityInfoInSceneWindow.facilityInfoUIItemes, this);
}
onSelect(select: boolean) {
this.isSelect = select;
this.modelInfo.setSelectEnable(select);
if (select) {
// console.log("选中设备==" + this.modelInfo.key);
GizmoTool.onPickMeshInfoObservable.notifyObservers(this.modelInfo);
this.facilityInfoInSceneWindow.selectFacilityItemToThree([this], true);
this.modelInfo.setIconEnable(select);
}
else {
this.facilityInfoInSceneWindow.selectFacilityItemToThree([this], false);
if (!this.facilityInfoInSceneWindow.getFacilityUIShowType(this.getType())) {
this.modelInfo.setIconEnable(select);
}
}
}
/**
*
*/
lookAt() {
if (!this.canLookAt()) {
return;
}
let size = null;
if (this.modelInfo.gdInfo != null) {
size = this.modelInfo.gdInfo.myPath[1].y * 3;
}
if (this.modelInfo.areaInfo != null) {
//计算多边形size
}
BabylonTool.changeCameraTarget(SceneManager.Instance.defaultCamera, this.modelInfo.modelBox, true, size);
}
/**
*
*/
canLookAt(): boolean {
let result = this.modelInfo != null && this.modelInfo.modelBox != null;
return result;
}
}

603
src/app/babylon/view/facilityinfoinscene-window/facilityinfoinscene-window.ts

@ -0,0 +1,603 @@
import { EventManager } from "@angular/platform-browser";
import { AbstractMesh, Ray, RayHelper, Vector3 } from "@babylonjs/core";
import { classToClass } from "class-transformer";
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: ThreeDimensionalHomeComponent;//前端组件
// 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 = ThreeDimensionalHomeComponent.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);
}
}
}
}
/**
*
* @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 false;
}
/**
*
* @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[];
}

234
src/app/babylon/view/indoor-window/indoor-create-window.ts

@ -0,0 +1,234 @@
// import { Control, Rectangle, StackPanel, TextBlock } from "@babylonjs/gui";
// import { DataManager } from "src/babylon/controller/data-manager";
// import { ServeManager } from "src/babylon/controller/serve-manager";
// import { IndoorStatus } from "src/babylon/controller/status/indoor-status";
// import { StatusManager } from "src/babylon/controller/status/status-manager";
// import { UIManager } from "src/babylon/controller/ui-manager";
// import { BuildingData_Normal } from "src/babylon/model/data/institution/building/building-data";
// import { BuildingPosType, ModelData } from "src/babylon/model/data/model-data/model-data";
// import { ModelEditData } from "src/babylon/model/data/model-data/model-edit-data";
// import { BabylonUIStyleTool } from "src/babylon/tool/babylon-ui-style-tool";
// import { TsTool } from "src/babylon/tool/ts-tool";
// import { UIBase } from "../window-base/ui-base";
// import { IndoorFloorUIItem } from "./indoor-floorui-item";
// export class IndoorCreateWindow extends UIBase {
// buildingData: BuildingData_Normal
// newFloorData: ModelEditData;//新的楼层信息,新建时填充
// indoorFloorUIItem: IndoorFloorUIItem;//已有的楼层item,修改时填充
// isCreate: boolean = true;//是新建楼层
// indoorStatus: IndoorStatus;
// isChangeModel = false;//修改了模型,则要重新加载模型
// //初始化为新建
// initCreate() {
// this.newFloorData = this.indoorStatus.newIndoorData("key", "name");
// this.initUI();
// }
// //初始化为修改
// initChange(indoorFloorUIItem: IndoorFloorUIItem) {
// this.indoorFloorUIItem = indoorFloorUIItem;
// this.newFloorData = indoorFloorUIItem.modelEditData;
// this.initUI();
// }
// //#region 声明周期
// onInit() {
// super.onInit();
// this.indoorStatus = StatusManager.getStatus<IndoorStatus>(IndoorStatus);
// }
// onOpen() {
// super.onOpen();
// BabylonUIStyleTool.createWindoRoot(this, "IndoorCreateWindow", "300px", "296px", true);
// }
// onClose() {
// super.onClose();
// }
// //#endregion
// initUI() {
// let window = this;
// let baseWidth = "220px";
// let baseHeight = "20px";
// let indoorStatus = StatusManager.getStatus<IndoorStatus>(IndoorStatus);
// this.buildingData = indoorStatus.buildingInfo.buildingData as BuildingData_Normal;
// let stack = new StackPanel("stack");
// stack.isVertical = true;
// BabylonUIStyleTool.setStyle_size(stack, baseWidth, "280px");
// this.root.addControl(stack);
// this.isCreate = this.indoorFloorUIItem == null;
// let titleText = this.isCreate ? "新建" : "编辑";
// let title = BabylonUIStyleTool.createTextBlock("title", titleText, baseWidth, baseHeight, "20px");
// stack.addControl(title);
// let space = new Rectangle("space");
// BabylonUIStyleTool.setStyle_size(space, baseWidth, baseHeight);
// stack.addControl(space);
// let floorKey = BabylonUIStyleTool.createTextBlock("floorKey", "唯一key", baseWidth, baseHeight, "18px");
// stack.addControl(floorKey);
// floorKey.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
// let floorKeyInput = BabylonUIStyleTool.createInputText("floorKeyInput", stack, baseWidth, baseHeight);
// if (!this.isCreate && this.newFloorData.modelData.key != null) {
// floorKeyInput.inputText.text = this.newFloorData.modelData.key;
// }
// floorKeyInput.inputText.onTextChangedObservable.add(() => {
// window.newFloorData.modelData.key = floorKeyInput.inputText.text;
// });
// let floorName = BabylonUIStyleTool.createTextBlock("floorName", "楼层名称", baseWidth, baseHeight, "18px");
// stack.addControl(floorName);
// floorName.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
// let floorNameInput = BabylonUIStyleTool.createInputText("floorNameInput", stack, baseWidth, baseHeight);
// if (this.isCreate) {
// }
// else {
// floorNameInput.inputText.text = this.newFloorData.modelData.name;
// }
// floorNameInput.inputText.onTextChangedObservable.add(() => {
// window.newFloorData.modelData.name = floorNameInput.inputText.text;
// })
// let space4 = new Rectangle("space4");
// BabylonUIStyleTool.setStyle_size(space4, baseWidth, "20px");
// stack.addControl(space4);
// let btn_changeModel = BabylonUIStyleTool.createBtn_OK("btn_changeModel", "上传模型", baseWidth, "30px", "18px");
// stack.addControl(btn_changeModel);
// btn_changeModel.onPointerClickObservable.add(() => {
// window.changeModel();
// })
// let space2 = new Rectangle("space2");
// BabylonUIStyleTool.setStyle_size(space2, baseWidth, "30px");
// stack.addControl(space2);
// let btns = new StackPanel("btns");
// BabylonUIStyleTool.setStyle_size(btns, baseWidth, "36px");
// stack.addControl(btns);
// btns.isVertical = false;
// let btn_OK = BabylonUIStyleTool.createBtn_OK("OK", "确定", "100px", "36px", "18px");
// btns.addControl(btn_OK);
// btn_OK.onPointerClickObservable.add(() => {
// window.onBtn_Ok();
// })
// let space3 = new Rectangle("space3");
// BabylonUIStyleTool.setStyle_size(space3, "20px", "36px");
// btns.addControl(space3);
// let btn_cancel = BabylonUIStyleTool.createBtn_Cancel("cancel", "取消", "100px", "36px", "18px");
// btns.addControl(btn_cancel);
// btn_cancel.onPointerClickObservable.add(() => {
// window.onBtn_Cancel();
// });
// if (!this.isCreate) {
// let btn_delete = BabylonUIStyleTool.createBtn_Delete("delete", "删", "30px", "30px", "20px");
// this.root.addControl(btn_delete);
// btn_delete.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
// btn_delete.verticalAlignment = Control.VERTICAL_ALIGNMENT_BOTTOM;
// btn_delete.onPointerClickObservable.add(() => {
// console.log("===btn_delete===");
// window.onBtn_Delete();
// });
// }
// }
// //修改模型
// changeModel() {
// let institutionKey = DataManager.institutionData.normalData.key;
// let indoorData = this.newFloorData;
// let buildingKey = StatusManager.getStatus<IndoorStatus>(IndoorStatus).buildingInfo.buildingData.normalData.key;
// let path = DataManager.getResPath_building(institutionKey, buildingKey, BuildingPosType.Indoor, this.newFloorData.modelData.key);
// console.log("模型路径" + path);
// let instance = this;
// ServeManager.instance.openFileSelect(path, (name: string, path: string) => {
// instance.isChangeModel = true;
// if (TsTool.stringContain(name, ".gltf")) {
// indoorData.modelData.resName = name;
// indoorData.modelData.resPath = path;
// }
// });
// }
// onBtn_Ok() {
// if (this.isCreate) {
// if (this.buildingData.indoorsData == null) {
// this.buildingData.indoorsData = [];
// }
// this.indoorStatus.addNewIndoorToBuilding(this.newFloorData);
// // this.buildingData.indoorsData.push(this.newFloorData);
// let indoorStatus = StatusManager.getStatus<IndoorStatus>(IndoorStatus);
// indoorStatus.indoorWindow.createOneFloorUIItem(this.newFloorData);
// }
// else {
// console.log(this.indoorFloorUIItem.modelEditData.modelData);
// //更新场景
// if (this.isChangeModel) {
// this.indoorFloorUIItem.updateBuilding();
// }
// else {
// this.indoorFloorUIItem.updateUI();
// }
// }
// this.closeWindow();
// }
// //点击取消按钮
// onBtn_Cancel() {
// this.closeWindow();
// }
// //点击删除按钮
// onBtn_Delete() {
// console.log("onBtn_Delete");
// let indoorStatus = StatusManager.getStatus<IndoorStatus>(IndoorStatus);
// indoorStatus.indoorWindow.deleteFloor(this.indoorFloorUIItem);
// this.closeWindow();
// }
// //关闭界面
// closeWindow() {
// if (this.isCreate) {
// let indoorStatus = StatusManager.getStatus<IndoorStatus>(IndoorStatus);
// indoorStatus.indoorWindow.closeCreateIndoorWindow();
// }
// else {
// this.isChangeModel = false;
// this.indoorFloorUIItem.closeChangeWindow();
// }
// }
// }

278
src/app/babylon/view/indoor-window/indoor-floorui-item.ts

@ -0,0 +1,278 @@
import { AbstractMesh, Mesh } from "@babylonjs/core";
import { Button, Container, Rectangle } from "@babylonjs/gui";
import ObjectID from "bson-objectid";
import { classToClass } from "class-transformer";
import { DataManager } from "../../controller/data-manager";
import { InfoManager } from "../../controller/info-manager";
import { SceneManager } from "../../controller/scene-manager";
import { IndoorStatus } from "../../controller/status/indoor-status";
import { ModelType } from "../../model/data/model-data/model-data";
import { ModelEditData } from "../../model/data/model-data/model-edit-data";
import { BuildingInfo } from "../../model/info/building/building-info";
import { ModelInfo } from "../../model/info/model/model-info";
import { ModelInfo_building } from "../../model/info/model/model-info-building";
import { BabylonTool } from "../../tool/babylon-tool";
import { GizmoTool } from "../../tool/gizmo-tool";
import { MeshPoolInfo } from "../../tool/mesh-pool";
import { MarkWindow } from "../mark-window/mark-window";
// import { IndoorCreateWindow } from "./indoor-create-window";
import { IndoorWindow } from "./indoor-window";
//室内楼层UI
export class IndoorFloorUIItem {
modelEditData: ModelEditData;
buildingInfo: BuildingInfo;
root: Rectangle;
content: Container;
indoorWindow: IndoorWindow;
btn: Button;
constructor(modelEditData: ModelEditData, indoorWindow: IndoorWindow) {
this.modelEditData = modelEditData;
this.indoorWindow = indoorWindow;
}
//#region 前端对接
/**
* key
*/
getIndoorKey() {
return this.modelEditData.modelData.key;
}
/**
*
*/
getIndoorName() {
return this.modelEditData.modelData.name;
}
/**
*
*/
getIndoorIndex() {
return this.modelEditData.index;
}
/**
*
* @param newName
*/
setIndoorName(newName: string) {
this.modelEditData.modelData.name = newName;
if (this.buildingInfo != null && this.buildingInfo.ModelInfo != null) {
(this.buildingInfo.ModelInfo as ModelInfo_building).updateName(newName);
}
}
/**
*
*/
setRefugeFloor(isRefugeFloor: boolean) {
this.modelEditData.isRefugeFloor = isRefugeFloor;
}
/**
*
* @param file
*/
changeModel(file: File[]) {
console.log("修改模型", file);
this.indoorWindow.changeModel(file, this.modelEditData);
}
/**
*
*/
copyFloor() {
let result = classToClass(this.modelEditData);
result.modelData.key = ObjectID.generate();
result.modelData.name = result.modelData.name + "(1)";
return result;
}
//#endregion
//#region 内部方法
//更新建筑
updateBuilding() {
let instance = this;
if (this.modelEditData != null && this.modelEditData.modelData != null && this.modelEditData.modelData.resPath != null) {
if (instance.buildingInfo == null) {
instance.buildingInfo = new BuildingInfo(DataManager.institutionData.normalBuildingDatas[0], null);
}
instance.buildingInfo.isDisposed = false;
if (instance.buildingInfo.ModelInfo != null) { //更新、释放掉之前的模型、ui
instance.buildingInfo.ModelInfo.dispose();
}
let resKey = this.modelEditData.modelData.resName + this.modelEditData.modelData.name;
let meshFromPool = IndoorFloorUIItem.getFromPool(resKey);
console.log(meshFromPool);
if (meshFromPool == null) {
//创建所有室内模型
SceneManager.createModel(ModelType.Building, this.modelEditData.modelData, true, true, undefined, (newMesh, box, modelInfo) => {
// instance.buildingInfo.ModelInfo = modelInfo as ModelInfo_building;
// box.position.y = box.scaling.y * 0.5 + 1;
// IndoorFloorUIItem.addToPool(this.modelEditData.modelData.resPath +this.modelEditData.modelData.name,box);
// // console.log("创建建筑成功=" + this.modelEditData.modelData.name + "isdispos" + instance.buildingInfo.ModelInfo.isDisposed);
// if (!instance.buildingInfo.ModelInfo.isDisposed) {
// instance.buildingInfo.ModelInfo.updateName(instance.modelEditData.modelData.name);
// let facilitysInFloor = instance.buildingInfo.ModelInfo.facilityInfos;
// SceneManager.s_facilityInfoInSceneWindow.createAllFacilities(facilitysInFloor);
// InfoManager.createFacilityInfos(instance.modelEditData, instance.buildingInfo);
// //BabylonTool.changeCameraTarget(SceneManager.Instance.defaultCamera, box, false);
// IndoorStatus.enterSuccessObservable.notifyObservers(instance);
// instance.lookAt(false);
// }
instance.onLoadMesh(instance, modelInfo, box);
IndoorFloorUIItem.addToPool(resKey, box);
});
}
else {
let modelInfo = InfoManager.newModelInfo_building(
instance.modelEditData.modelData.key,
instance.modelEditData.modelData,
null,
meshFromPool
);
instance.onLoadMesh(instance, modelInfo, meshFromPool);
}
}
else {
}
}
/**
*
* @param instance
* @param modelInfo
* @param modelBox
*/
onLoadMesh(instance: IndoorFloorUIItem, modelInfo: ModelInfo, modelBox: AbstractMesh) {
instance.buildingInfo.ModelInfo = modelInfo as ModelInfo_building;
modelBox.position.y = modelBox.scaling.y * 0.5 + 1;
// console.log("创建建筑成功=" + this.modelEditData.modelData.name + "isdispos" + instance.buildingInfo.ModelInfo.isDisposed);
if (!instance.buildingInfo.ModelInfo.isDisposed) {
instance.buildingInfo.ModelInfo.updateName(instance.modelEditData.modelData.name);
let facilitysInFloor = instance.buildingInfo.ModelInfo.facilityInfos;
SceneManager.s_facilityInfoInSceneWindow.createAllFacilities(facilitysInFloor);
InfoManager.createFacilityInfos(instance.modelEditData, instance.buildingInfo);
//BabylonTool.changeCameraTarget(SceneManager.Instance.defaultCamera, box, false);
IndoorStatus.enterSuccessObservable.notifyObservers(instance);
instance.lookAt(true);
}
}
dispose() {
if (this.buildingInfo != null) {
GizmoTool.leaveTheGizmoAim(this.buildingInfo.ModelInfo);
}
if (this.buildingInfo != null) {
this.buildingInfo.dispose();
}
}
//点击选中
onClick() {
this.indoorWindow.selectFloor(this);
}
//是否选中的表现更新
onSelect(select: boolean) {
if (select) {
this.updateBuilding();
}
else {
if (this.buildingInfo != null) {
GizmoTool.leaveTheGizmoAim(this.buildingInfo.ModelInfo);
this.buildingInfo.dispose();
}
}
}
/**
*
*/
lookAt(anim: boolean = true) {
if (MarkWindow.s_cameraData != null) {
// setTimeout(() => {
SceneManager.Instance.defaultCamera.animations
MarkWindow.s_cameraData.setDataToCamera(SceneManager.Instance.defaultCamera);
MarkWindow.s_cameraData = null;
// }, (500));
} else if (this.buildingInfo != null && this.buildingInfo.ModelInfo != null && this.buildingInfo.ModelInfo.modelBox != null) {
BabylonTool.changeCameraTarget(SceneManager.Instance.defaultCamera, this.buildingInfo.ModelInfo.modelBox, anim);
}
}
//#endregion
//#region 室内模型池
/**
*
*/
static pool: Map<string, MeshPoolInfo> = new Map();
/**
*
* @param meshKey
* @param mesh
*/
static addToPool(meshKey: string, mesh: AbstractMesh) {
if (IndoorFloorUIItem.pool.has(meshKey)) {
return;
}
else {
let prefabMesh = BabylonTool.cloneMesh(mesh as Mesh, mesh.name);
let poolInfo: MeshPoolInfo = new MeshPoolInfo(meshKey, meshKey, false, prefabMesh);
poolInfo.meshBox.setEnabled(false);
IndoorFloorUIItem.pool.set(meshKey, poolInfo);
}
}
/**
*
* @param modelPath
*/
static getFromPool(modelPath: string) {
if (IndoorFloorUIItem.pool.has(modelPath)) {
let result = IndoorFloorUIItem.pool.get(modelPath);
let modelBox = BabylonTool.cloneMesh(result.meshBox as Mesh, result.meshBox.name + "111");
modelBox.setEnabled(true);
return modelBox;
}
else {
return null;
}
}
//#endregion
}

281
src/app/babylon/view/indoor-window/indoor-window.ts

@ -0,0 +1,281 @@
import { DataManager } from "../../controller/data-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 { BuildingPosType } from "../../model/data/model-data/model-data";
import { ModelEditData } from "../../model/data/model-data/model-edit-data";
import { TsTool } from "../../tool/ts-tool";
import { MarkWindow } from "../mark-window/mark-window";
import { UIBase } from "../window-base/ui-base";
import { IndoorFloorUIItem } from "./indoor-floorui-item";
//室内界面
export class IndoorWindow extends UIBase {
allFloorDatas: ModelEditData[];
allFloorUIItems: IndoorFloorUIItem[] = [];
currentFloorUIItem: IndoorFloorUIItem;
refugeFloorNum: number;//避难层数目
indoorStatus: IndoorStatus;
//#region 生命周期
onInit() {
super.onInit();
this.indoorStatus = StatusManager.getStatus<IndoorStatus>(IndoorStatus);
}
onOpen() {
super.onOpen();
}
onClose() {
super.onClose();
}
//#endregion
//#region 前端对接
/**
*
*/
getRefugeFloorNum() {
return this.refugeFloorNum;
}
/**
*
* UI
*/
onBtnToOutDoor(fromUI: boolean = true) {
BuildingStatus.changeStatusFromUI = fromUI;
if (fromUI && MarkWindow.instance != null && MarkWindow.instance.isShow && MarkWindow.instance.currentMarkNodeInfo != null) {
MarkWindow.instance.changeBuilding(true);
}
else {
StatusManager.enterStatus<BuildingStatus>(BuildingStatus);
console.log("退出到室外");
}
}
/**
*
* @param file
* @param modelEditData
*/
changeModel(file: File[], modelEditData: ModelEditData) {
if (file == null || file.length == 0) {
return;
}
let institutionKey = DataManager.institutionData.normalData.key;
let indoorData = modelEditData;
let buildingKey = StatusManager.getStatus<IndoorStatus>(IndoorStatus).buildingInfo.buildingData.normalData.key;
let path = DataManager.getResPath_building(institutionKey, buildingKey, BuildingPosType.Indoor, indoorData.modelData.key);
// console.log("模型路径" + path);
let instance = this;
let manifestFile: File = null;
if (indoorData.modelData.resName != null) {
manifestFile = DataManager.createManifestFile(indoorData.modelData);
file.push(manifestFile);//临时关闭缓存文件
}
ServeManager.instance.uploadFile(0, file, path, (name: string, path: string, currentfile: File) => {
if (TsTool.stringContain(name, ".gltf")) {
if (TsTool.stringContain(name, ".gltf.manifest")) {
//缓存文件,提取版本号
DataManager.readFile_manifest(currentfile, (version: number) => {
indoorData.modelData.version = version;
// console.log("设置version" + version);
});
}
else {
indoorData.modelData.resName = name;
indoorData.modelData.resPath = path;
// console.log("上传室内:" + path + name);
if (manifestFile == null) {
manifestFile = DataManager.createManifestFile(indoorData.modelData);
file.push(manifestFile);//临时关闭缓存文件
}
}
}
}
, () => {
//ThreeDimensionalHomeComponent.instance.maskLayerService.sendMessage(false)
if (instance.currentFloorUIItem != null && modelEditData.modelData.key == instance.currentFloorUIItem.modelEditData.modelData.key) {
instance.currentFloorUIItem.updateBuilding();
}
else {
let newItem = this.getFloorByKey(modelEditData.modelData.key);
//ThreeDimensionalHomeComponent.instance.selectLeftBuilding(newItem);
}
});
}
//#endregion
//初始化所有楼层
initAllFloor(allFloorData: ModelEditData[], key: string) {
this.allFloorDatas = allFloorData;
this.updateFloorUIItem(key);
}
//更新item
updateFloorUIItem(key: string) {
this.clearAllFloorUIItem();
let defaultItem: IndoorFloorUIItem = null;
if (this.allFloorDatas != null) {
for (let i = 0; i < this.allFloorDatas.length; i++) {
let item = this.createOneFloorUIItem(this.allFloorDatas[i]);
if (this.allFloorDatas[i].modelData.key == key) {
defaultItem = item;
}
if (this.allFloorDatas[i].isRefugeFloor) {
this.refugeFloorNum++;
}
}
}
if (defaultItem == null) {
if (this.allFloorUIItems.length > 0) {
this.selectFloor(this.getFirstIndexFloor(this.allFloorUIItems), false);
}
}
else {
this.selectFloor(defaultItem, false);
}
}
/**
*
* @param items
*/
getFirstIndexFloor(items: IndoorFloorUIItem[]) {
let index = 0;
for (let i = 0; i < items.length; i++) {
if (items[i].getIndoorIndex() < items[index].getIndoorIndex()) {
index = i;
}
}
return items[index];
}
//创建单个楼层UIitem
createOneFloorUIItem(modelEditData: ModelEditData): IndoorFloorUIItem {
let result = new IndoorFloorUIItem(modelEditData, this);
this.allFloorUIItems.push(result);
return result;
}
//删除室内层
deleteFloor(indoorFloorUIItem: IndoorFloorUIItem) {
// console.log("试图删除");
for (let i = 0; i < this.allFloorDatas.length; i++) {
if (this.allFloorDatas[i] == indoorFloorUIItem.modelEditData) {
TsTool.arrayRemove(this.allFloorDatas, indoorFloorUIItem.modelEditData);
break;
}
}
for (let i = 0; i < this.allFloorUIItems.length; i++) {
if (this.allFloorUIItems[i] == indoorFloorUIItem) {
this.allFloorUIItems[i].dispose();
TsTool.arrayRemove(this.allFloorUIItems, indoorFloorUIItem);
// console.log("成功删除");
break;
}
}
}
//清空楼层item
clearAllFloorUIItem() {
// console.log("清空楼层item"+this.allFloorUIItems.length);
for (let i = 0; i < this.allFloorUIItems.length; i++) {
this.allFloorUIItems[i].dispose();
}
this.allFloorUIItems = [];
this.refugeFloorNum = 0;
}
//选中某层
selectFloor(floorUIItem: IndoorFloorUIItem, fromUI: boolean = true) {
if (fromUI && MarkWindow.instance != null && MarkWindow.instance.isShow) {
MarkWindow.instance.changeBuilding(false, this.indoorStatus.buildingInfo.buildingData.normalData.key, floorUIItem.modelEditData.modelData.key);
return;
}
if (this.currentFloorUIItem == floorUIItem) {
// if (floorUIItem.buildingInfo != null) {
// BabylonTool.changeCameraTarget(SceneManager.Instance.defaultCamera, floorUIItem.buildingInfo.ModelInfo.modelBox);
// }
return;
}
else if (this.currentFloorUIItem != null) {
this.currentFloorUIItem.onSelect(false);
}
this.currentFloorUIItem = floorUIItem;
SceneManager.s_facilityInfoInSceneWindow.clearFacilityInfoUIItemes();//先清空
this.currentFloorUIItem.onSelect(true);
}
/**
* key找item
* @param key
*/
getFloorByKey(key: string): IndoorFloorUIItem {
let result = null;
if (this.allFloorUIItems != null) {
for (let i = 0; i < this.allFloorUIItems.length; i++) {
if (this.allFloorUIItems[i].modelEditData.modelData.key == key) {
result = this.allFloorUIItems[i];
break;
}
}
}
return result;
}
// /**
// * 摄像机注视中心
// */
// lookAtCenter(buildingInfo: ModelInfo_building) {
// if (buildingInfo != null && buildingInfo.modelBox != null) {
// BabylonTool.changeCameraTarget(SceneManager.Instance.defaultCamera, buildingInfo.modelBox);
// }
// }
}

190
src/app/babylon/view/institution/institution-create-window.ts

@ -0,0 +1,190 @@
import { Button, Control, Rectangle, StackPanel, TextBlock } from "@babylonjs/gui";
import { LoginSatus } from "../../controller/status/login-status";
import { StatusManager } from "../../controller/status/status-manager";
import { UIManager } from "../../controller/ui-manager";
import { InstitutionData, NormalData } from "../../model/data/institution/institution-data";
import { InsitutionDataSimple } from "../../model/data/institution/institution-data-simple";
import { MyInputText } from "../../tool/babylon-tool";
import { BabylonUIStyleTool } from "../../tool/babylon-ui-style-tool";
import { UIBase } from "../window-base/ui-base";
//创建单位界面
//由于还没有可存放多个单位信息的位置,先预留,暂时没实现
export class InstitutionCreateWindow extends UIBase {
insDataSimple: InsitutionDataSimple;//新单位简易信息
insData: InstitutionData; //新单位的详细信息
//#region 声明周期
onInit() {
super.onInit();
}
onOpen() {
super.onOpen();
this.initUI();
}
onClose() {
super.onClose();
}
//#endregion
//#region 创建新单位
//开始创建
startCreate() {
this.insDataSimple = new InsitutionDataSimple();
this.insDataSimple.key = "test3";//因不可重复,应该从服务器获得
this.txt_keyValue.inputText.text = this.insDataSimple.key;//假装请求成功
this.txt_keyValue.inputText.onTextChangedObservable.add(() => {
this.insDataSimple.key = this.txt_keyValue.inputText.text;
console.log("设置key" + this.insDataSimple.key);
})
}
//确定
onbtnOK() {
this.insDataSimple.name = this.inputTxt_insName.inputText.text;//从输入框获取
// console.log("onbtnOK==key" + this.insDataSimple.key);
// console.log("onbtnOK==name" + this.insDataSimple.name);
if (this.insDataSimple.name == null) {
console.log("请输入单位名称");
}
else {
this.insData = new InstitutionData();
this.insData.normalData = new NormalData(this.insDataSimple.key, this.insDataSimple.name);
console.log(this.insData.normalData);
this.saveNewIns();
}
}
//保存新单位信息至服务器
saveNewIns() {
let window = this;
let loginStatus = StatusManager.getStatus<LoginSatus>(LoginSatus);
loginStatus.saveNewIns(loginStatus, window.insData, window.insDataSimple.key, (insDataSimple) => {
loginStatus.closeCreateWindow();
});
}
//#endregion
//#region UI界面
inputTxt_insName: MyInputText;//名称输入框
txt_keyValue: MyInputText;//唯一Key
btn_OK: Button;//确定创建
btn_Cancle: Button;//取消
initUI() {
let window = this;
this.root = new Rectangle("InstitutionCreateWindow");
this.root.width = "300px";
this.root.height = "382px";
BabylonUIStyleTool.setDefaultStyle_windowRoot(this.root);
UIManager.Instance.uiRoot.addControl(this.root);
let title = new TextBlock("title", "新建单位");
BabylonUIStyleTool.setStyle_size(title, "80px", "20px");
BabylonUIStyleTool.setStyle_bodyText(title);
this.root.addControl(title);
BabylonUIStyleTool.setStyle_Alignment(title, Control.HORIZONTAL_ALIGNMENT_CENTER, Control.VERTICAL_ALIGNMENT_TOP);
BabylonUIStyleTool.setStyle_padding(title, "40px", undefined, undefined, undefined);
let nameRoot = new StackPanel("nameRoor");
BabylonUIStyleTool.setStyle_size(nameRoot, "200px", "300px");
this.root.addControl(nameRoot);
BabylonUIStyleTool.setStyle_Alignment(nameRoot, Control.HORIZONTAL_ALIGNMENT_CENTER, Control.VERTICAL_ALIGNMENT_TOP);
BabylonUIStyleTool.setStyle_padding(nameRoot, "80px", undefined, undefined, undefined);
let nameTxt = new TextBlock("nameTxt", "单位名称");
BabylonUIStyleTool.setStyle_size(nameTxt, "200px", "20px");
nameTxt.textVerticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
BabylonUIStyleTool.setStyle_bodyText(nameTxt, "16px", UIBase.color_black);
nameTxt.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
nameRoot.addControl(nameTxt);
this.inputTxt_insName = BabylonUIStyleTool.createInputText("input_name", nameRoot, "200px", "30px");
let padding = new Control();
BabylonUIStyleTool.setStyle_size(padding, "200px", "20px");
nameRoot.addControl(padding);
let keyTxt = new TextBlock("keyTxt", "唯一key,仅供测试可见");
BabylonUIStyleTool.setStyle_size(keyTxt, "200px", "20px");
keyTxt.textVerticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
BabylonUIStyleTool.setStyle_bodyText(keyTxt, "16px", UIBase.color_black);
keyTxt.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
nameRoot.addControl(keyTxt);
keyTxt.alpha = 0.5;
this.txt_keyValue = BabylonUIStyleTool.createInputText("keyValueTxt", nameRoot, "200px", "20px", "black", undefined, undefined, BabylonUIStyleTool.c_color_gray, "black", BabylonUIStyleTool.c_color_gray);
// BabylonUIStyleTool.setStyle_size(this.txt_keyValue, "200px", "20px");
// this.txt_keyValue.textVerticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
// BabylonUIStyleTool.setStyle_bodyText(this.txt_keyValue, "14px", UIBase.color_black);
// this.txt_keyValue.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
// nameRoot.addControl(this.txt_keyValue);
// this.txt_keyValue.alpha = 0.7;
this.txt_keyValue.inputText.onTextChangedObservable.add(() => {
window.insDataSimple.key = window.txt_keyValue.inputText.text;
});
let btnRoot = new StackPanel("btnRoot");
btnRoot.isVertical = false;
this.root.addControl(btnRoot);
BabylonUIStyleTool.setStyle_size(btnRoot, "240px", "70px");
BabylonUIStyleTool.setStyle_Alignment(btnRoot, Control.HORIZONTAL_ALIGNMENT_CENTER, Control.VERTICAL_ALIGNMENT_BOTTOM);
BabylonUIStyleTool.setStyle_padding(btnRoot, undefined, undefined, "30px");
let padding_btn = new Control("padding_btn");
BabylonUIStyleTool.setStyle_size(padding_btn, "10px", "36px");
btnRoot.addControl(padding_btn);
this.btn_OK = BabylonUIStyleTool.createBtn_OK("OK", "确定", "100px", "36px", "18px");
btnRoot.addControl(this.btn_OK);
this.btn_OK.onPointerClickObservable.add(() => {
window.onbtnOK();
})
let padding_btn1 = new Control("padding_btn1");
BabylonUIStyleTool.setStyle_size(padding_btn1, "20px", "36px");
btnRoot.addControl(padding_btn1);
this.btn_Cancle = BabylonUIStyleTool.createBtn_Cancel("Cancel", "取消", "100px", "36px", "18px");
btnRoot.addControl(this.btn_Cancle);
this.btn_Cancle.onPointerClickObservable.add(() => {
window.onBtnClose();
})
}
onBtnClose() {
let loginStatus = StatusManager.getStatus<LoginSatus>(LoginSatus);
loginStatus.closeCreateWindow();
loginStatus.openSelectWindow();
}
//#endregion
}

59
src/app/babylon/view/institution/institution-item.ts

@ -0,0 +1,59 @@
import { Button, Rectangle, StackPanel } from "@babylonjs/gui";
import { InsitutionDataSimple } from "../../model/data/institution/institution-data-simple";
import { BabylonUIStyleTool } from "../../tool/babylon-ui-style-tool";
import { UIBase } from "../window-base/ui-base";
import { InstitutionSelectWindow } from "./institution-select-window";
export class InstitutionItem {
root: Rectangle;
window: InstitutionSelectWindow;//单位选择界面
insData: InsitutionDataSimple;//单位简易信息
btn_select: Button;
constructor(window: InstitutionSelectWindow, parent: StackPanel, insitutionDataSimple: InsitutionDataSimple) {
this.window = window;
this.insData = insitutionDataSimple;
if (this.insData == null) {
this.insData = new InsitutionDataSimple();
this.insData.name = "+新建单位";
this.insData.key = undefined;
}
this.root = new Rectangle("InstitutionItem");
BabylonUIStyleTool.setStyle_size(this.root, parent.width + "px", "40px");
this.root.color = UIBase.color_blue;
parent.addControl(this.root);
let name = "null";
if (this.insData.name != null) {
name = this.insData.name;
}
this.btn_select = Button.CreateSimpleButton("select", name);
let item = this;
this.btn_select.onPointerClickObservable.add(() => {
item.onSelect();
});
this.root.addControl(this.btn_select);
// let text = this.btn_select.textBlock;
// text.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_RIGHT;
}
//选择单位
onSelect() {
console.log("选择单位" + this.insData.name);
this.window.onSelectIns(this);
}
//新建单位
onNewSelect() {
console.log("新建单位");
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save