/** * 3D 引擎管理器 * 负责管理 3D 渲染引擎的初始化、模型加载和测量功能 */ import { Engine, type EngineOptions, type ModelLoadOptions } from '../components/engine'; import { BaseManager } from '../core/base-manager'; import { RightKeyManager } from './right-key-manager'; import type { MeasureMode } from '../types/measure'; import type { SectionBoxRange } from '../components/section-box-panel/types'; import type { MenuItemConfig } from '../components/menu/item'; import { ManagerRegistry } from '../core/manager-registry'; /** * 3D 引擎管理器 * 封装底层 3D 引擎,提供模型加载、相机控制、测量等功能 */ export class EngineManager extends BaseManager { /** 容器元素 */ private container: HTMLElement; /** 引擎实例 */ private engineInstance: Engine | null = null; /** 右键菜单管理器 */ public rightKey: RightKeyManager | null = null; constructor(container: HTMLElement) { super(); this.container = container; } /** * 初始化 3D 引擎 * @param options 引擎配置选项 * @returns 是否初始化成功 */ public initialize(options?: Omit): boolean { if (this.engineInstance && this.engineInstance.isInitialized()) { console.warn('[EngineManager] 3D Engine already initialized. Destroying old instance...'); this.engineInstance.destroy(); this.engineInstance = null; } try { this.engineInstance = new Engine({ container: this.container, ...options, }); this.engineInstance.init(); 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: () => { console.log('[Menu] 隐藏选中构件 - 暂未实现'); this.rightKey?.hide(); } }); // 3. 半透明选中构件 items.push({ id: 'transparentSelected', label: 'menu.transparentSelected', group: 'component', order: 3, onClick: () => { console.log('[Menu] 半透明选中构件 - 暂未实现'); this.rightKey?.hide(); } }); // 4. 隔离选中构件(带子菜单) items.push({ id: 'isolateSelected', label: 'menu.isolateSelected', group: 'component', order: 4, divider: true, children: [ { id: 'hideOthers', label: 'menu.hideOthers', onClick: () => { console.log('[Menu] 隔离 - 其他构件隐藏 - 暂未实现'); this.rightKey?.hide(); } }, { id: 'transparentOthers', label: 'menu.transparentOthers', onClick: () => { console.log('[Menu] 隔离 - 其他构件半透明 - 暂未实现'); this.rightKey?.hide(); } } ] }); // 5. 剖切盒适应 items.push({ id: 'fitSectionBox', label: 'menu.fitSectionBox', group: 'component', order: 5, onClick: () => { console.log('[Menu] 剖切盒适应 - 暂未实现'); this.rightKey?.hide(); } }); } // 6. 显示全部(始终显示) items.push({ id: 'showAll', label: 'menu.showAll', group: 'component', order: 6, onClick: () => { console.log('[Menu] 显示全部 - 暂未实现'); this.rightKey?.hide(); } }); return items; }); return this.engineInstance.isInitialized(); } catch (error) { console.error('[EngineManager] Failed to initialize 3D engine:', error); this.engineInstance = null; return false; } } /** * 检查引擎是否已初始化 * @returns 是否已初始化 */ public isInitialized(): boolean { return this.engineInstance !== null && this.engineInstance.isInitialized(); } /** * 加载模型 * @param url 模型 URL * @param options 加载选项 */ public loadModel(url: string, options?: ModelLoadOptions): void { if (!this.engineInstance) { console.warn('[EngineManager] 3D Engine not initialized.'); return; } this.engineInstance.loadModel(url, options); } /** * 获取底层引擎实例 * @returns 引擎实例 */ public getEngine(): any { if (!this.engineInstance) { console.warn('[EngineManager] 3D Engine not initialized.'); return null; } return this.engineInstance.getEngine(); } /** 相机回到初始位置 */ 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(); } /** * 激活剖切功能(统一入口) * @param mode 剖切模式: 'x' | 'y' | 'z' (轴向剖切) | 'box' (剖切盒) | 'face' (拾取面剖切) * @remarks 代理调用 Engine.activeSection(mode) */ 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 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(); } /** * 设置漫游移动速度 * @param speed 移动速度 */ public setWalkSpeed(speed: number): void { if (!this.engineInstance) { console.warn('[EngineManager] 3D Engine not initialized.'); return; } this.engineInstance.setWalkSpeed(speed); } /** * 设置漫游重力开关 * @param enabled 是否启用重力 */ public setWalkGravity(enabled: boolean): void { if (!this.engineInstance) { console.warn('[EngineManager] 3D Engine not initialized.'); return; } this.engineInstance.setWalkGravity(enabled); } /** * 设置漫游碰撞检测开关 * @param enabled 是否启用碰撞检测 */ public setWalkCollision(enabled: boolean): void { if (!this.engineInstance) { console.warn('[EngineManager] 3D Engine not initialized.'); return; } this.engineInstance.setWalkCollision(enabled); } /** * 获取漫游模式是否激活 * @returns 是否处于漫游模式 */ public isFirstPersonModeActive(): boolean { if (!this.engineInstance) { return false; } return this.engineInstance.isFirstPersonModeActive(); } // ==================== 结束:漫游功能 ==================== // ==================== 构件选中 ==================== /** * 获取当前选中的构件 * @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 destroy(): void { if (this.engineInstance) { this.engineInstance.destroy(); this.engineInstance = null; } if (this.rightKey) { this.rightKey.destroy(); this.rightKey = null; } super.destroy(); } }