Files
bim_engine/src/managers/engine-manager.ts

701 lines
22 KiB
TypeScript
Raw Normal View History

/**
* 3D
* 3D
*/
import { Engine, type EngineOptions, type ModelLoadOptions, type EngineInfo } from '../components/engine';
import { BaseManager } from '../core/base-manager';
import { RightKeyManager } from './right-key-manager';
import type { MeasureMode } from '../types/measure';
import type { MeasureUnit, MeasurePrecision } from '../components/measure-panel/types';
import type { SectionBoxRange } from '../components/section-box-panel/types';
import type { MenuItemConfig } from '../components/menu/item';
import { ManagerRegistry } from '../core/manager-registry';
2025-12-04 18:41:11 +08:00
/**
* 3D
* 3D
2025-12-04 18:41:11 +08:00
*/
export class EngineManager extends BaseManager {
/** 容器元素 */
2025-12-04 18:41:11 +08:00
private container: HTMLElement;
/** 引擎实例 */
2025-12-08 10:02:24 +08:00
private engineInstance: Engine | null = null;
/** 右键菜单管理器 */
public rightKey: RightKeyManager | null = null;
2025-12-04 18:41:11 +08:00
constructor(container: HTMLElement) {
super();
2025-12-04 18:41:11 +08:00
this.container = container;
}
/**
* 3D
* @param options
2025-12-04 18:41:11 +08:00
* @returns
*/
public initialize(options?: Omit<EngineOptions, 'container'>): boolean {
2025-12-08 10:02:24 +08:00
if (this.engineInstance && this.engineInstance.isInitialized()) {
2025-12-04 18:41:11 +08:00
console.warn('[EngineManager] 3D Engine already initialized. Destroying old instance...');
2025-12-08 10:02:24 +08:00
this.engineInstance.destroy();
this.engineInstance = null;
2025-12-04 18:41:11 +08:00
}
try {
2025-12-08 10:02:24 +08:00
this.engineInstance = new Engine({
2025-12-04 18:41:11 +08:00
container: this.container,
...options,
2025-12-04 18:41:11 +08:00
});
2025-12-08 10:02:24 +08:00
this.engineInstance.init();
2025-12-04 18:41:11 +08:00
this.rightKey = new RightKeyManager(this.container);
this.rightKey.registerHandler((_e) => {
const selected = this.getSelectedComponent();
const items: MenuItemConfig[] = [];
if (selected) {
// 1. 构件详情
items.push({
id: 'componentDetail',
label: 'menu.componentDetail',
group: 'component',
order: 1,
divider: true,
onClick: () => {
const registry = ManagerRegistry.getInstance();
registry.componentDetail?.show();
this.rightKey?.hide();
}
});
// 2. 隐藏选中构件
items.push({
id: 'hideSelected',
label: 'menu.hideSelected',
group: 'component',
order: 2,
onClick: () => {
const models = this.getHighlightModels();
if (models) {
this.hideModels(models);
}
this.rightKey?.hide();
}
});
// 3. 半透明选中构件
items.push({
id: 'transparentSelected',
label: 'menu.transparentSelected',
group: 'component',
order: 3,
onClick: () => {
const models = this.getHighlightModels();
if (models) {
this.translucentModels(models);
}
this.rightKey?.hide();
}
});
// 4. 取消半透明
items.push({
id: 'cancelTranslucent',
label: 'menu.cancelTranslucent',
group: 'component',
order: 4,
onClick: () => {
this.unTranslucentModel();
this.rightKey?.hide();
}
});
// 5. 隔离选中构件(带子菜单)
items.push({
id: 'isolateSelected',
label: 'menu.isolateSelected',
group: 'component',
order: 5,
divider: true,
children: [
{
id: 'hideOthers',
label: 'menu.hideOthers',
onClick: () => {
const models = this.getHighlightModels();
if (models) {
this.isolateModels(models);
}
this.rightKey?.hide();
}
},
{
id: 'transparentOthers',
label: 'menu.transparentOthers',
onClick: () => {
const models = this.getHighlightModels();
if (models) {
this.translucentOtherModels(models);
}
this.rightKey?.hide();
}
}
]
});
// 6. 快速选择(带子菜单)
items.push({
id: 'quickSelect',
label: 'menu.quickSelect',
group: 'component',
order: 6,
children: [
{
id: 'selectSameType',
label: 'menu.selectSameType',
onClick: () => {
const models = this.getHighlightModels();
if (models) {
this.batchSelectSameTypeModel(models);
}
this.rightKey?.hide();
}
},
{
id: 'selectSameLevel',
label: 'menu.selectSameLevel',
onClick: () => {
const models = this.getHighlightModels();
if (models) {
this.batchSelectSameLevelModel(models);
}
this.rightKey?.hide();
}
},
{
id: 'selectSameLevelType',
label: 'menu.selectSameLevelType',
onClick: () => {
const models = this.getHighlightModels();
if (models) {
this.batchSelectSameLevelTypeModel(models);
}
this.rightKey?.hide();
}
}
]
});
// 7. 剖切盒适应
items.push({
id: 'fitSectionBox',
label: 'menu.fitSectionBox',
group: 'component',
order: 7,
onClick: () => {
this.fitSectionBoxToModel();
this.rightKey?.hide();
}
});
}
// 8. 显示全部(始终显示)
items.push({
id: 'showAll',
label: 'menu.showAll',
group: 'component',
order: 8,
onClick: () => {
this.showAllModels();
this.emit('menu:show-all', {});
this.rightKey?.hide();
}
});
return items;
});
2025-12-08 10:02:24 +08:00
return this.engineInstance.isInitialized();
2025-12-04 18:41:11 +08:00
} catch (error) {
console.error('[EngineManager] Failed to initialize 3D engine:', error);
2025-12-08 10:02:24 +08:00
this.engineInstance = null;
2025-12-04 18:41:11 +08:00
return false;
}
}
2025-12-04 18:41:11 +08:00
/**
*
* @returns
2025-12-04 18:41:11 +08:00
*/
public isInitialized(): boolean {
2025-12-08 10:02:24 +08:00
return this.engineInstance !== null && this.engineInstance.isInitialized();
2025-12-04 18:41:11 +08:00
}
2025-12-04 18:41:11 +08:00
/**
*
* @param urls URL
* @param options
2025-12-04 18:41:11 +08:00
*/
public loadModel(urls: string[], options?: ModelLoadOptions): void {
if (!this.engineInstance) {
console.warn('[EngineManager] 3D Engine not initialized.');
2025-12-04 18:41:11 +08:00
return;
}
this.engineInstance.loadModel(urls, options);
2025-12-04 18:41:11 +08:00
}
/**
*
* @returns
2025-12-04 18:41:11 +08:00
*/
public getEngine(): any {
2025-12-08 10:02:24 +08:00
if (!this.engineInstance) {
2025-12-04 18:41:11 +08:00
console.warn('[EngineManager] 3D Engine not initialized.');
return null;
}
2025-12-08 10:02:24 +08:00
return this.engineInstance.getEngine();
2025-12-04 18:41:11 +08:00
}
/** 相机回到初始位置 */
public CameraGoHome(): void {
if (!this.engineInstance) {
console.warn('[EngineManager] 3D Engine not initialized.');
return;
}
this.engineInstance.CameraGoHome();
}
/** 暂停渲染 */
public pauseRendering(): void {
if (!this.engineInstance) {
console.warn('[EngineManager] 3D Engine not initialized.');
return;
}
this.engineInstance.pauseRendering();
}
/** 恢复渲染 */
public resumeRendering(): void {
if (!this.engineInstance) {
console.warn('[EngineManager] 3D Engine not initialized.');
return;
}
this.engineInstance.resumeRendering();
}
/**
*
* @param mode
*/
public activateMeasure(mode: MeasureMode): void {
if (!this.engineInstance) {
console.warn('[EngineManager] 3D Engine not initialized.');
return;
}
this.engineInstance.activateMeasure(mode);
}
/** 停用测量模式 */
public deactivateMeasure(): void {
if (!this.engineInstance) {
return;
}
this.engineInstance.deactivateMeasure();
}
/**
*
* @returns
*/
public getCurrentMeasureType(): MeasureMode | null {
if (!this.engineInstance) {
return null;
}
return this.engineInstance.getCurrentMeasureType();
}
public clearAllMeasures(): void {
if (!this.engineInstance) {
return;
}
this.engineInstance.clearAllMeasures();
}
public saveMeasureSetting(setting: { unit: MeasureUnit; precision: MeasurePrecision }): void {
if (!this.engineInstance) {
return;
}
this.engineInstance.saveMeasureSetting(setting);
}
public activeSection(mode: 'x' | 'y' | 'z' | 'box' | 'face'): void {
if (!this.engineInstance) {
console.warn('[EngineManager] 3D Engine not initialized.');
return;
}
this.engineInstance.activeSection(mode);
}
/**
*
* @returns null
*/
public getCurrentSectionMode(): 'x' | 'y' | 'z' | 'box' | 'face' | null {
if (!this.engineInstance) {
return null;
}
return this.engineInstance.getCurrentSectionMode();
}
/**
*
* @remarks
*/
public deactivateSection(): void {
if (!this.engineInstance) {
return;
}
this.engineInstance.deactivateSection();
}
/**
*
* @param range ( 0-100)
* @remarks 'box'
*/
public setSectionBoxRange(range: SectionBoxRange): void {
if (!this.engineInstance) {
console.warn('[EngineManager] 3D Engine not initialized.');
return;
}
this.engineInstance.setSectionBoxRange(range);
}
/**
*
* @remarks recoverSection() 使
*/
public hideSection(): void {
if (!this.engineInstance) {
return;
}
this.engineInstance.hideSection();
}
/**
*
* @remarks hideSection()
*/
public recoverSection(): void {
if (!this.engineInstance) {
return;
}
this.engineInstance.recoverSection();
}
public fitSectionBoxToModel(): void {
if (!this.engineInstance) {
return;
}
this.engineInstance.fitSectionBoxToModel();
}
/**
*
* @remarks clipping.scaleBox()
*/
public scaleSectionBox(): void {
if (!this.engineInstance) {
return;
}
this.engineInstance.scaleSectionBox();
}
/**
*
* @remarks clipping.reverse()
*/
public reverseSection(): void {
if (!this.engineInstance) {
return;
}
this.engineInstance.reverseSection();
}
/** 激活框选放大功能 */
public activateZoomBox(): void {
if (!this.engineInstance) {
console.warn('[EngineManager] 3D Engine not initialized.');
return;
}
this.engineInstance.activateZoomBox();
}
// ==================== 漫游功能 ====================
/** 激活第一人称漫游模式 */
public activateFirstPersonMode(): void {
if (!this.engineInstance) {
console.warn('[EngineManager] 3D Engine not initialized.');
return;
}
this.engineInstance.activateFirstPersonMode();
}
/** 停用第一人称漫游模式 */
public deactivateFirstPersonMode(): void {
if (!this.engineInstance) {
return;
}
this.engineInstance.deactivateFirstPersonMode();
}
public setWalkSpeed(speed: number): void {
this.engineInstance?.setWalkSpeed(speed);
}
public setWalkGravity(enabled: boolean): void {
this.engineInstance?.setWalkGravity(enabled);
}
public setWalkCollision(enabled: boolean): void {
this.engineInstance?.setWalkCollision(enabled);
}
public toggleMiniMap(): void {
this.engineInstance?.toggleMiniMap();
}
public isFirstPersonModeActive(): boolean {
return this.engineInstance?.isFirstPersonModeActive() ?? false;
}
// ==================== 结束:漫游功能 ====================
// ==================== 构件选中 ====================
/**
*
* @returns URL ID null
*/
public getSelectedComponent(): { url: string; id: string } | null {
return this.engineInstance?.getSelectedComponent() ?? null;
}
/**
*
* @param url URL
* @param id ID
* @param callback
*/
public getComponentProperties(
url: string,
id: string,
callback: (data: any) => void
): void {
this.engineInstance?.getComponentProperties(url, id, callback);
}
// ==================== 结束:构件选中 ====================
// ==================== 模型树 ====================
public getTypeTreeData(): any[] {
return this.engineInstance?.getTypeTreeData() ?? [];
}
public getLevelTreeData(): any[] {
return this.engineInstance?.getLevelTreeData() ?? [];
}
public getMajorTreeData(): any[] {
return this.engineInstance?.getMajorTreeData() ?? [];
}
public getEngineInfo(): EngineInfo | null {
return this.engineInstance?.getEngineInfo() ?? null;
}
// ==================== 结束:模型树 ====================
// ==================== 路径漫游 ====================
/**
*
*
*/
public pathRoamingAddPoint(): void {
this.engineInstance?.pathRoamingAddPoint();
}
/**
*
* @param index
*/
public pathRoamingRemovePoint(index: number): void {
this.engineInstance?.pathRoamingRemovePoint(index);
}
/**
*
*/
public pathRoamingClearPoints(): void {
this.engineInstance?.pathRoamingClearPoints();
}
/**
*
* @returns
*/
public pathRoamingGetPoints(): any[] {
return this.engineInstance?.pathRoamingGetPoints() ?? [];
}
/**
*
* @param index
*/
public pathRoamingJumpToPoint(index: number): void {
this.engineInstance?.pathRoamingJumpToPoint(index);
}
/**
*
* @param options
*/
public pathRoamingPlay(options?: {
duration?: number;
loop?: boolean;
onComplete?: () => void;
onPointComplete?: (pointIndex: number) => void;
}): void {
this.engineInstance?.pathRoamingPlay(options);
}
/**
*
*/
public pathRoamingStop(): void {
this.engineInstance?.pathRoamingStop();
}
// ==================== 结束:路径漫游 ====================
// ==================== 构件操作 ====================
/**
* ()
* @returns , null
*/
public getHighlightModels(): any {
return this.engineInstance?.getHighlightModels() ?? null;
}
/**
*
*
* @param models - : [{ url: string, ids: string[] }]
*
* @example
* manager.highlightModel([
* { url: 'https://xxx/models/xxx/', ids: [350518, 350520] }
* ]);
*/
public highlightModel(models: { url: string; ids: number[] }[]): void {
this.engineInstance?.highlightModel(models);
}
public unhighlightAllModels(): void {
this.engineInstance?.unhighlightAllModels();
}
public viewScaleToModel(models: { url: string; ids: number[] }[]): void {
this.engineInstance?.viewScaleToModel(models);
}
public hideModels(models: { url: string; ids: number[] }[]): void {
this.engineInstance?.hideModels(models);
}
public showModel(models: { url: string; ids: number[] }[]): void {
this.engineInstance?.showModel(models);
}
/**
*
* @param models
*/
public translucentModels(models: any): void {
this.engineInstance?.translucentModels(models);
}
/**
*
*/
public unTranslucentModel(): void {
this.engineInstance?.unTranslucentModel();
}
/**
*
* @param models
*/
public isolateModels(models: any): void {
this.engineInstance?.isolateModels(models);
}
/**
*
* @param models
*/
public translucentOtherModels(models: any): void {
this.engineInstance?.translucentOtherModels(models);
}
/**
*
*/
public showAllModels(): void {
this.engineInstance?.showAllModels();
}
/**
*
* @param models
*/
public batchSelectSameTypeModel(models: any): void {
this.engineInstance?.batchSelectSameTypeModel(models);
}
/**
*
* @param models
*/
public batchSelectSameLevelModel(models: any): void {
this.engineInstance?.batchSelectSameLevelModel(models);
}
/**
*
* @param models
*/
public batchSelectSameLevelTypeModel(models: any): void {
this.engineInstance?.batchSelectSameLevelTypeModel(models);
}
// ==================== 结束:构件操作 ====================
/** 销毁引擎管理器 */
2025-12-04 18:41:11 +08:00
public destroy(): void {
2025-12-08 10:02:24 +08:00
if (this.engineInstance) {
this.engineInstance.destroy();
this.engineInstance = null;
2025-12-04 18:41:11 +08:00
}
if (this.rightKey) {
this.rightKey.destroy();
this.rightKey = null;
}
super.destroy();
2025-12-04 18:41:11 +08:00
}
}