/** * 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'; /** * 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: () => { this.hideSelectedModels(); this.rightKey?.hide(); } }); // 3. 半透明选中构件 items.push({ id: 'transparentSelected', label: 'menu.transparentSelected', group: 'component', order: 3, onClick: () => { this.translucentSelectedModels(); 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: () => { this.isolateSelectedModels(); this.rightKey?.hide(); } }, { id: 'transparentOthers', label: 'menu.transparentOthers', onClick: () => { this.translucentOtherModels(); this.rightKey?.hide(); } } ] }); // 6. 快速选择(带子菜单) items.push({ id: 'quickSelect', label: 'menu.quickSelect', group: 'component', order: 6, children: [ { id: 'selectSameType', label: 'menu.selectSameType', onClick: () => { this.batchSelectSameTypeModel(); this.rightKey?.hide(); } }, { id: 'selectSameLevel', label: 'menu.selectSameLevel', onClick: () => { this.batchSelectSameLevelModel(); this.rightKey?.hide(); } }, { id: 'selectSameLevelType', label: 'menu.selectSameLevelType', onClick: () => { this.batchSelectSameLevelTypeModel(); 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.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(); } 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(); } /** 激活框选放大功能 */ 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(); } // ==================== 结束:路径漫游 ==================== // ==================== 构件操作 ==================== /** * 隐藏选中构件 */ public hideSelectedModels(): void { this.engineInstance?.hideSelectedModels(); } /** * 半透明选中构件 */ public translucentSelectedModels(): void { this.engineInstance?.translucentSelectedModels(); } /** * 取消半透明 */ public unTranslucentModel(): void { this.engineInstance?.unTranslucentModel(); } /** * 隔离选中构件(隐藏其他) */ public isolateSelectedModels(): void { this.engineInstance?.isolateSelectedModels(); } /** * 半透明其他构件 */ public translucentOtherModels(): void { this.engineInstance?.translucentOtherModels(); } /** * 显示所有模型 */ public showAllModels(): void { this.engineInstance?.showAllModels(); } /** * 批量选择同类模型 */ public batchSelectSameTypeModel(): void { this.engineInstance?.batchSelectSameTypeModel(); } /** * 批量选择同层模型 */ public batchSelectSameLevelModel(): void { this.engineInstance?.batchSelectSameLevelModel(); } /** * 批量选择同层同类模型 */ public batchSelectSameLevelTypeModel(): void { this.engineInstance?.batchSelectSameLevelTypeModel(); } // ==================== 结束:构件操作 ==================== /** 销毁引擎管理器 */ public destroy(): void { if (this.engineInstance) { this.engineInstance.destroy(); this.engineInstance = null; } if (this.rightKey) { this.rightKey.destroy(); this.rightKey = null; } super.destroy(); } }