Files
bim_engine/docs/引擎API对接.md
yuding b96e5f3262 refactor: slim down EngineManager from 861 to 290 lines by removing passthrough proxy pattern
- EngineManager now only exposes public SDK API (initialize, loadModel, pause/resumeRendering, getEngineComponent, destroy)
- Internal managers access Engine component directly via this.engineComponent getter on BaseManager
- Non-manager components use registry.engine3d.getEngineComponent() for direct Engine access
- Replaced getEngine() with onRawEvent()/offRawEvent() for raw engine event access
- Migrated 62 call sites across 13 files (9 managers, 1 panel, 3 toolbar buttons)
- Updated all architecture docs, API docs, and README to reflect new patterns
2026-03-05 11:15:57 +08:00

174 lines
4.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Engine API 对接指南2026-03
本文档说明 SDK 层与底层 `iflow-engine-base` 的最新对接方式。
## 核心原则
1. `Engine` 组件是底层能力封装层(状态管理 + 参数转换 + 底层调用)
2. `EngineManager` 只保留少量对外公共 API不再做全量透传
3. 内部 Manager 直接通过 `this.engineComponent``Engine`
4. 非 Manager 组件通过 `registry.engine3d?.getEngineComponent()``Engine`
5. 不暴露 raw engine 实例,事件订阅走 `onRawEvent/offRawEvent`
---
## 对接层级
```text
L1 UI 层Button/Panel/Dialog
-> L2 Manager 层(业务编排)
-> L3 Engine 组件(统一封装)
-> L4 iflow-engine-base底层能力
```
---
## A. 对外 APIEngineManager
对外稳定入口:`bimEngine.engine`
```ts
interface EngineManagerPublicApi {
initialize(options?: Omit<EngineOptions, 'container'>): boolean;
isInitialized(): boolean;
loadModel(urls: string[], options?: ModelLoadOptions): void;
pauseRendering(): void;
resumeRendering(): void;
getEngineComponent(): Engine | null;
destroy(): void;
}
```
`EngineManager` 内部仍负责:
- 创建 `Engine` 实例
- 创建并持有 `RightKeyManager`
- 组装右键菜单逻辑
---
## B. 内部 Manager 对接(推荐)
`BaseManager` 已提供:
```ts
protected get engineComponent(): Engine | null;
```
### 示例:剖切盒
```ts
this.engineComponent?.activeSection('box');
this.engineComponent?.setSectionBoxRange(range);
this.engineComponent?.deactivateSection();
```
### 示例:漫游
```ts
this.engineComponent?.activateFirstPersonMode();
this.engineComponent?.setWalkSpeed(speed);
this.engineComponent?.deactivateFirstPersonMode();
```
---
## C. 非 Manager 组件对接
适用于 toolbar 按钮、独立组件(如 `WalkPathPanel`
```ts
registry.engine3d?.getEngineComponent()?.CameraGoHome();
registry.engine3d?.getEngineComponent()?.activateZoomBox();
registry.engine3d?.getEngineComponent()?.toggleMiniMap();
```
---
## D. 原始事件对接(替代 getEngine
`Engine.getEngine()` 已删除,改为事件桥接:
```ts
engineComponent?.onRawEvent('measure-changed', handler);
engineComponent?.offRawEvent('measure-changed', handler);
```
适用场景:
- 测量回调(`measure-changed` / `measure-click`
- 剖切盒拖动回调(`section-move`
---
## E. 新功能对接步骤(最新模板)
### Step 1: 在 Engine 组件实现能力
文件:`src/components/engine/index.ts`
```ts
public activateXx(): void {
if (!this._isInitialized || !this.engine?.xxModule) return;
this.engine.xxModule.active();
}
public deactivateXx(): void {
if (!this._isInitialized || !this.engine?.xxModule) return;
this.engine.xxModule.disActive();
}
```
### Step 2: 在 Manager 中调用(不要新增 EngineManager 透传)
文件:`src/managers/xx-dialog-manager.ts`
```ts
protected onDialogCreated(): void {
this.engineComponent?.activateXx();
}
protected onBeforeDestroy(): void {
this.engineComponent?.deactivateXx();
}
```
### Step 3: 若是非 Manager 组件,走 getEngineComponent
```ts
registry.engine3d?.getEngineComponent()?.activateXx();
```
### Step 4: 仅当需要“对外 SDK 公共 API”时再考虑给 EngineManager 增加方法
判定标准:
- 该能力是否需要 `bimEngine.engine?.xxx()` 供外部用户直接调用
- 若仅为内部链路使用,不应在 `EngineManager` 再包一层
---
## F. 常见反模式
- ❌ 在 `EngineManager` 里新增大批 `this.engineInstance?.xxx()` 透传
- ❌ 内部 Manager 继续写 `this.registry.engine3d?.xxx()`
- ❌ 通过 `Engine.getEngine()` 暴露 raw engine
对应正确方式:
- ✅ 内部 Manager 使用 `this.engineComponent?.xxx()`
- ✅ 非 Manager 使用 `registry.engine3d?.getEngineComponent()?.xxx()`
- ✅ 原始事件使用 `onRawEvent/offRawEvent`
---
## G. 验收清单
重构或新增功能后,至少检查:
1. `EngineManager` 是否只保留必要公共 API
2. Manager 层是否统一走 `engineComponent`
3. 是否无 `getEngine()` 调用
4. 事件订阅是否成对 `onRawEvent/offRawEvent`
5. `npm run build` 是否通过