import { DefaultLevelControl } from "./DefaultLevelControl";
import { LevelControlHelper } from "../LevelControlHelper";
import { Selector } from "@uino/thing";
const __ = {
private: Symbol('private')
}
/**
* @class BuildingLevelControl
* 园区建筑层级控制类
* @extends THING.DefaultLevelControl
* @public
*/
class BuildingLevelControl extends DefaultLevelControl {
static levelCondition = 'tags:or(Building)';
static levelName = 'building';
constructor(options) {
super(options);
let _private = this[__.private] = {};
_private.hideObjects = [];
_private.enableExpandFloors = false;
_private.notCheckOutline = false;
}
async onEnter(param) {
let _private = this[__.private];
let prev = param.prev;
if (prev && prev.isCampus) {
LevelControlHelper.setEnvMap(prev, 'inner');
}
let promise = super.onEnter(param);
const building = param.current;
if (_private.enableExpandFloors) {
building.expandFloors();
}
return promise;
}
onLeave(param) {
let _private = this[__.private];
super.onLeave(param);
return new Promise((resolve) => {
const building = param.current;
if (_private.enableExpandFloors && building.expanded) {
building.unexpandFloors({
duration: 1, onComplete: resolve
});
} else {
resolve();
}
});
}
onSetEffect(param) {
const object = param.current;
if (!object) {
return;
}
let _private = this[__.private];
// Hide brothers
const brothers = object.brothers;
brothers.forEach(brother => {
LevelControlHelper.traverseByIgnore(brother, 'ignoreVisible', (child) => {
child.setVisible(false, false);
});
});
object.children.forEach(child => {
const objTags = child.tags;
if (objTags.has('Floor')) {
child.setVisible(true, false);
LevelControlHelper.traverseByIgnore(child, 'ignoreVisible', (floorChild) => {
if (floorChild == child) {
return;
}
const floorChildTags = floorChild.tags;
if (floorChildTags.has('BuildingElement')) {
floorChild.setVisible(!(floorChildTags.has('RoomRoof') || floorChildTags.has('Roof')), false);
} else {
floorChild.setVisible(true, false);
}
});
}
else if (objTags.has('Facade') || objTags.has('Roof')) {
LevelControlHelper.traverseByIgnore(child, 'ignoreVisible', (facadeChild) => {
facadeChild.setVisible(false, false);
});
}
else {
LevelControlHelper.traverseByIgnore(child, 'ignoreVisible', (childchild) => {
childchild.setVisible(true, false);
});
}
});
// Hide uncles
let parent = object.parent;
const uncles = parent.brothers.queryByTags('Campus');
uncles.forEach(uncle => {
LevelControlHelper.traverseByIgnore(uncle, 'ignoreVisible', (child) => {
if (child.isLight || child.isCamera) {
return;
}
_private.hideObjects.push(child);
child.setVisible(false, false);
});
});
}
onResetEffect(param) {
let current = param['current'];
let next = param['next'];
if (next && current.parent != next) {
return;
}
let _private = this[__.private];
_private.hideObjects.forEach(element => {
element.setVisible(true, false);
});
_private.hideObjects.length = 0;
}
onSetOutlineColor(object, color) {
if (!object) {
return;
}
let _private = this[__.private];
const be = object.find('tags:or(Wall,BuildingElement)');
_private.notCheckOutline = !!!be;
super.onSetOutlineColor(object, color);
}
shouldOutline(object) {
let _private = this[__.private];
if (_private.notCheckOutline) {
return true;
}
if (object) {
// Check type
if (object.tags.has('Door') || object.tags.has('Window')) {
return true;
}
// Check tags
let tags = object.tags;
if (tags.has('Wall')) {
return true;
}
else if (tags.has('Slab')) {
return true;
}
else if (tags.has('BuildingElement')) {
return true;
}
}
return false;
}
/**
* 启用/禁用进入建筑物展开楼层和离开建筑物收起楼层
* @type {Boolean}
* @public
*/
get enableExpandFloors() {
let _private = this[__.private];
return _private.enableExpandFloors;
}
set enableExpandFloors(value) {
let _private = this[__.private];
_private.enableExpandFloors = value;
}
onFlyTo(flyParam) {
const target = flyParam.target;
if (target && target.isObject3D) {
const floors = target.children.queryByTags('Floor');
const walls = new Selector();
floors.forEach(floor => {
floor.children.forEach(child => {
if (child.tags && child.tags.has('Wall')) {
walls.push(child);
}
})
});
if (walls.length === 0) {
flyParam.target = target;
return super.onFlyTo(flyParam);;
}
const boundingBox = walls.getBoundingBox();
flyParam.position = LevelControlHelper.getNearestObjectPosition({
target: target,
boundingBox: boundingBox,
camera: this.app.camera,
});
flyParam.target = boundingBox.center;
}
return super.onFlyTo(flyParam);
}
}
export { BuildingLevelControl };