2026-01-28 17:19:36 +08:00
|
|
|
|
# BIM Engine SDK - API 调用链文档
|
2026-01-28 11:24:35 +08:00
|
|
|
|
|
2026-01-28 17:19:36 +08:00
|
|
|
|
本文档详细记录 BIM Engine SDK 中各功能模块的完整调用链,从用户交互到底层 3D 引擎 API。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 目录
|
|
|
|
|
|
|
|
|
|
|
|
### 第一章:工具栏 (Toolbar)
|
|
|
|
|
|
|
|
|
|
|
|
1. [首页 (Home)](#1-首页-home)
|
|
|
|
|
|
2. [框选放大 (Zoom Box)](#2-框选放大-zoom-box)
|
|
|
|
|
|
3. [测量 (Measure)](#3-测量-measure)
|
|
|
|
|
|
4. [剖切菜单 (Section)](#4-剖切菜单-section)
|
|
|
|
|
|
- [拾取面剖切 (Section Plane)](#41-拾取面剖切-section-plane)
|
|
|
|
|
|
- [轴向剖切 (Section Axis)](#42-轴向剖切-section-axis)
|
|
|
|
|
|
- [剖切盒 (Section Box)](#43-剖切盒-section-box)
|
|
|
|
|
|
5. [漫游 (Walk)](#5-漫游-walk)
|
|
|
|
|
|
6. [地图 (Map)](#6-地图-map)
|
|
|
|
|
|
7. [构件详情 (Property)](#7-构件详情-property)
|
|
|
|
|
|
8. [设置 (Setting)](#8-设置-setting)
|
|
|
|
|
|
9. [信息 (Info)](#9-信息-info)
|
|
|
|
|
|
10. [全屏 (Fullscreen)](#10-全屏-fullscreen)
|
|
|
|
|
|
|
|
|
|
|
|
### 第二章:右键菜单 (Context Menu)
|
|
|
|
|
|
|
|
|
|
|
|
1. [构件详情 (Component Detail)](#21-构件详情-component-detail)
|
|
|
|
|
|
2. [显示全部 (Show All)](#22-显示全部-show-all)
|
|
|
|
|
|
3. [信息 (Info)](#23-信息-info-1)
|
|
|
|
|
|
4. [首页 (Home)](#24-首页-home-1)
|
|
|
|
|
|
|
|
|
|
|
|
### 第三章:构件交互 (Component Interaction)
|
|
|
|
|
|
|
|
|
|
|
|
1. [构件选中 (Component Selection)](#31-构件选中-component-selection)
|
|
|
|
|
|
2. [取消选中 (Deselection)](#32-取消选中-deselection)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
# 第一章:工具栏 (Toolbar)
|
2026-01-28 11:24:35 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 目录
|
|
|
|
|
|
|
|
|
|
|
|
1. [首页 (Home)](#1-首页-home)
|
|
|
|
|
|
2. [框选放大 (Zoom Box)](#2-框选放大-zoom-box)
|
|
|
|
|
|
3. [测量 (Measure)](#3-测量-measure)
|
|
|
|
|
|
4. [剖切菜单 (Section)](#4-剖切菜单-section)
|
|
|
|
|
|
- [拾取面剖切 (Section Plane)](#41-拾取面剖切-section-plane)
|
|
|
|
|
|
- [轴向剖切 (Section Axis)](#42-轴向剖切-section-axis)
|
|
|
|
|
|
- [剖切盒 (Section Box)](#43-剖切盒-section-box)
|
|
|
|
|
|
5. [漫游 (Walk)](#5-漫游-walk)
|
|
|
|
|
|
6. [地图 (Map)](#6-地图-map)
|
|
|
|
|
|
7. [构件详情 (Property)](#7-构件详情-property)
|
|
|
|
|
|
8. [设置 (Setting)](#8-设置-setting)
|
|
|
|
|
|
9. [信息 (Info)](#9-信息-info)
|
|
|
|
|
|
10. [全屏 (Fullscreen)](#10-全屏-fullscreen)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 1. 首页 (Home)
|
|
|
|
|
|
|
|
|
|
|
|
**按钮 ID**: `home`
|
|
|
|
|
|
**功能**: 相机回到初始位置(主视角)
|
|
|
|
|
|
**保持激活**: 否
|
|
|
|
|
|
|
|
|
|
|
|
### 调用链
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
用户点击 [首页] 按钮
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
Button onClick (buttons/home/index.ts)
|
|
|
|
|
|
│ registry.engine3d?.CameraGoHome()
|
|
|
|
|
|
▼
|
|
|
|
|
|
EngineManager.CameraGoHome() (managers/engine-manager.ts)
|
|
|
|
|
|
│ this.engineInstance.CameraGoHome()
|
|
|
|
|
|
▼
|
|
|
|
|
|
Engine.CameraGoHome() (components/engine/index.ts)
|
|
|
|
|
|
│ this.engine.viewCube.CameraGoHome()
|
|
|
|
|
|
▼
|
|
|
|
|
|
底层引擎 API: engine.viewCube.CameraGoHome()
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 代码摘要
|
|
|
|
|
|
|
|
|
|
|
|
**按钮定义** (`buttons/home/index.ts`):
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
onClick: (button) => {
|
|
|
|
|
|
const registry = ManagerRegistry.getInstance();
|
|
|
|
|
|
registry.engine3d?.CameraGoHome();
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**EngineManager** (`managers/engine-manager.ts`):
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
public CameraGoHome(): void {
|
|
|
|
|
|
this.engineInstance.CameraGoHome();
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**Engine 组件** (`components/engine/index.ts`):
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
public CameraGoHome() {
|
|
|
|
|
|
this.engine.viewCube.CameraGoHome();
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 2. 框选放大 (Zoom Box)
|
|
|
|
|
|
|
|
|
|
|
|
**按钮 ID**: `zoom-box`
|
|
|
|
|
|
**功能**: 激活框选放大模式,用户可以框选区域进行放大
|
|
|
|
|
|
**保持激活**: 否
|
|
|
|
|
|
|
|
|
|
|
|
### 调用链
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
用户点击 [框选放大] 按钮
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
Button onClick (buttons/zoom-box/index.ts)
|
|
|
|
|
|
│ registry.engine3d?.activateZoomBox()
|
|
|
|
|
|
▼
|
|
|
|
|
|
EngineManager.activateZoomBox() (managers/engine-manager.ts)
|
|
|
|
|
|
│ this.engineInstance.activateZoomBox()
|
|
|
|
|
|
▼
|
|
|
|
|
|
Engine.activateZoomBox() (components/engine/index.ts)
|
|
|
|
|
|
│ this.engine.rangeScale?.active()
|
|
|
|
|
|
▼
|
|
|
|
|
|
底层引擎 API: engine.rangeScale.active()
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 代码摘要
|
|
|
|
|
|
|
|
|
|
|
|
**按钮定义** (`buttons/zoom-box/index.ts`):
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
onClick: () => {
|
|
|
|
|
|
const registry = ManagerRegistry.getInstance();
|
|
|
|
|
|
registry.engine3d?.activateZoomBox();
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**EngineManager** (`managers/engine-manager.ts`):
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
public activateZoomBox(): void {
|
|
|
|
|
|
this.engineInstance.activateZoomBox();
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**Engine 组件** (`components/engine/index.ts`):
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
public activateZoomBox(): void {
|
|
|
|
|
|
this.engine.rangeScale?.active();
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 3. 测量 (Measure)
|
|
|
|
|
|
|
|
|
|
|
|
**按钮 ID**: `measure`
|
|
|
|
|
|
**功能**: 打开测量对话框,支持距离、角度、标高、体积等多种测量
|
|
|
|
|
|
**保持激活**: 是
|
|
|
|
|
|
|
|
|
|
|
|
### 调用链
|
|
|
|
|
|
|
|
|
|
|
|
#### 3.1 打开测量对话框
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
用户点击 [测量] 按钮(激活)
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
Button onClick (buttons/measure/index.ts)
|
|
|
|
|
|
│ registry.measure?.show()
|
|
|
|
|
|
▼
|
|
|
|
|
|
MeasureDialogManager.show() (继承自 BaseDialogManager)
|
|
|
|
|
|
│ createContent() → 创建 MeasurePanel
|
|
|
|
|
|
│ onDialogCreated()
|
|
|
|
|
|
▼
|
|
|
|
|
|
对话框显示,等待用户选择测量模式
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 3.2 用户选择测量模式
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
用户在 Panel 中选择测量模式(如:距离测量)
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
MeasurePanel.onModeChange('distance')
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
MeasureDialogManager 回调 (managers/measure-dialog-manager.ts)
|
|
|
|
|
|
│ registry.engine3d?.activateMeasure(mode)
|
|
|
|
|
|
▼
|
|
|
|
|
|
EngineManager.activateMeasure('distance') (managers/engine-manager.ts)
|
|
|
|
|
|
│ this.engineInstance.activateMeasure(mode)
|
|
|
|
|
|
▼
|
|
|
|
|
|
Engine.activateMeasure('distance') (components/engine/index.ts)
|
|
|
|
|
|
│ switch(mode) → activateDistanceMeasure()
|
|
|
|
|
|
▼
|
|
|
|
|
|
Engine.activateDistanceMeasure()
|
|
|
|
|
|
│ this.engine.measure.active() // 激活主测量模块
|
|
|
|
|
|
│ this.engine.measure.distanceMeasure.active() // 激活距离测量
|
|
|
|
|
|
▼
|
|
|
|
|
|
底层引擎 API:
|
|
|
|
|
|
- engine.measure.active()
|
|
|
|
|
|
- engine.measure.distanceMeasure.active()
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 3.3 清除所有测量
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
用户点击 [删除全部] 按钮
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
MeasurePanel.onClearAll()
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
MeasureDialogManager 回调
|
|
|
|
|
|
│ registry.engine3d?.clearAllMeasures()
|
|
|
|
|
|
▼
|
|
|
|
|
|
EngineManager.clearAllMeasures()
|
|
|
|
|
|
│ this.engineInstance.clearAllMeasures()
|
|
|
|
|
|
▼
|
|
|
|
|
|
Engine.clearAllMeasures()
|
|
|
|
|
|
│ this.engine.measure.clearAll()
|
|
|
|
|
|
▼
|
|
|
|
|
|
底层引擎 API: engine.measure.clearAll()
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 3.4 关闭测量对话框
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
用户关闭对话框 / 再次点击按钮
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
MeasureDialogManager.onBeforeDestroy()
|
|
|
|
|
|
│ registry.engine3d.deactivateMeasure()
|
|
|
|
|
|
▼
|
|
|
|
|
|
EngineManager.deactivateMeasure()
|
|
|
|
|
|
│ this.engineInstance.deactivateMeasure()
|
|
|
|
|
|
▼
|
|
|
|
|
|
Engine.deactivateMeasure()
|
|
|
|
|
|
│ this.engine.measure.disActive()
|
|
|
|
|
|
▼
|
|
|
|
|
|
底层引擎 API: engine.measure.disActive()
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 测量模式与底层 API 对照表
|
|
|
|
|
|
|
|
|
|
|
|
| 模式 | Engine 方法 | 底层 API |
|
|
|
|
|
|
|------|-------------|----------|
|
|
|
|
|
|
| distance (距离) | `activateDistanceMeasure()` | `engine.measure.distanceMeasure.active()` |
|
|
|
|
|
|
| minDistance (最小距离) | `activateMinDistanceMeasure()` | `engine.measure.clearDistanceMeasure.active()` |
|
|
|
|
|
|
| angle (角度) | `activateAngleMeasure()` | `engine.measure.angleMeasure.active()` |
|
|
|
|
|
|
| elevation (标高) | `activateElevationMeasure()` | `engine.measure.elevationMeasure.active()` |
|
|
|
|
|
|
| volume (体积) | `activateVolumeMeasure()` | `engine.measure.areaMeasure.active()` |
|
|
|
|
|
|
| slope (坡度) | `activateSlopeMeasure()` | `engine.measure.slopeMeasure.active()` |
|
|
|
|
|
|
| laserDistance (激光测距) | `activateLaserDistanceMeasure()` | ⚠️ 暂未实现 |
|
|
|
|
|
|
| spaceVolume (空间体积) | `activateSpaceVolumeMeasure()` | ⚠️ 暂未实现 |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 4. 剖切菜单 (Section)
|
|
|
|
|
|
|
|
|
|
|
|
**按钮 ID**: `section`
|
|
|
|
|
|
**类型**: 菜单按钮,展开后显示子按钮
|
|
|
|
|
|
|
|
|
|
|
|
### 4.1 拾取面剖切 (Section Plane)
|
|
|
|
|
|
|
|
|
|
|
|
**按钮 ID**: `section-plane`
|
|
|
|
|
|
**功能**: 拾取模型表面进行剖切
|
|
|
|
|
|
**保持激活**: 是
|
|
|
|
|
|
**互斥**: 是(同一时间只能激活一种剖切)
|
|
|
|
|
|
|
|
|
|
|
|
#### 调用链
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
用户点击 [拾取面剖切] 按钮(激活)
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
Button onClick (buttons/section/section-plane/index.ts)
|
|
|
|
|
|
│ registry.sectionPlane?.show()
|
|
|
|
|
|
▼
|
|
|
|
|
|
SectionPlaneDialogManager.show() (继承自 BaseDialogManager)
|
|
|
|
|
|
│ createContent() → 创建 SectionPlanePanel
|
|
|
|
|
|
│ onDialogCreated()
|
|
|
|
|
|
▼
|
|
|
|
|
|
对话框显示(拾取面剖切需要用户在3D场景中点击表面)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
> ⚠️ **注意**: 拾取面剖切的底层 API 对接尚未完成,目前仅显示 UI 面板。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 4.2 轴向剖切 (Section Axis)
|
|
|
|
|
|
|
|
|
|
|
|
**按钮 ID**: `section-axis`
|
|
|
|
|
|
**功能**: 沿 X/Y/Z 轴向进行剖切
|
|
|
|
|
|
**保持激活**: 是
|
|
|
|
|
|
**互斥**: 是
|
|
|
|
|
|
|
|
|
|
|
|
#### 调用链 - 打开对话框
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
用户点击 [轴向剖切] 按钮(激活)
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
Button onClick (buttons/section/section-axis/index.ts)
|
|
|
|
|
|
│ registry.sectionAxis?.show()
|
|
|
|
|
|
▼
|
|
|
|
|
|
SectionAxisDialogManager.show() (继承自 BaseDialogManager)
|
|
|
|
|
|
│ createContent() → 创建 SectionAxisPanel
|
|
|
|
|
|
│ onDialogCreated()
|
2026-02-02 16:25:36 +08:00
|
|
|
|
│ └── registry.engine3d.activeSection('x') // 默认激活 X 轴
|
2026-01-28 11:24:35 +08:00
|
|
|
|
▼
|
2026-02-02 16:25:36 +08:00
|
|
|
|
EngineManager.activeSection('x')
|
|
|
|
|
|
│ this.engineInstance.activeSection(mode)
|
2026-01-28 11:24:35 +08:00
|
|
|
|
▼
|
2026-02-02 16:25:36 +08:00
|
|
|
|
Engine.activeSection('x')
|
|
|
|
|
|
│ this.engine.clipping.active('x')
|
2026-01-28 11:24:35 +08:00
|
|
|
|
▼
|
2026-02-02 16:25:36 +08:00
|
|
|
|
底层引擎 API: engine.clipping.active('x')
|
2026-01-28 11:24:35 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 调用链 - 切换轴向
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
用户在 Panel 中切换轴向(如:Y 轴)
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
SectionAxisPanel.onAxisChange('y')
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
SectionAxisDialogManager 回调
|
2026-02-02 16:25:36 +08:00
|
|
|
|
│ registry.engine3d?.activeSection('y')
|
2026-01-28 11:24:35 +08:00
|
|
|
|
▼
|
2026-02-02 16:25:36 +08:00
|
|
|
|
EngineManager.activeSection('y')
|
|
|
|
|
|
│ this.engineInstance.activeSection(mode)
|
2026-01-28 11:24:35 +08:00
|
|
|
|
▼
|
2026-02-02 16:25:36 +08:00
|
|
|
|
Engine.activeSection('y')
|
|
|
|
|
|
│ this.engine.clipping.active('y')
|
2026-01-28 11:24:35 +08:00
|
|
|
|
▼
|
2026-02-02 16:25:36 +08:00
|
|
|
|
底层引擎 API: engine.clipping.active('y')
|
2026-01-28 11:24:35 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 调用链 - 关闭对话框
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
用户关闭对话框 / 再次点击按钮
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
SectionAxisDialogManager.onBeforeDestroy()
|
2026-02-02 16:25:36 +08:00
|
|
|
|
│ registry.engine3d?.deactivateSection()
|
2026-01-28 11:24:35 +08:00
|
|
|
|
▼
|
2026-02-02 16:25:36 +08:00
|
|
|
|
EngineManager.deactivateSection()
|
|
|
|
|
|
│ this.engineInstance.deactivateSection()
|
2026-01-28 11:24:35 +08:00
|
|
|
|
▼
|
2026-02-02 16:25:36 +08:00
|
|
|
|
Engine.deactivateSection()
|
2026-01-28 11:24:35 +08:00
|
|
|
|
│ this.engine.clipping.disActive()
|
|
|
|
|
|
▼
|
|
|
|
|
|
底层引擎 API: engine.clipping.disActive()
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-02-02 16:25:36 +08:00
|
|
|
|
#### 剖切模式与底层 API 对照表
|
2026-01-28 11:24:35 +08:00
|
|
|
|
|
2026-02-02 16:25:36 +08:00
|
|
|
|
| 模式 | Engine 调用 | 底层 API |
|
|
|
|
|
|
|------|-------------|----------|
|
|
|
|
|
|
| x | `activeSection('x')` | `engine.clipping.active('x')` |
|
|
|
|
|
|
| y | `activeSection('y')` | `engine.clipping.active('y')` |
|
|
|
|
|
|
| z | `activeSection('z')` | `engine.clipping.active('z')` |
|
|
|
|
|
|
| box | `activeSection('box')` | `engine.clipping.active('box')` |
|
|
|
|
|
|
| face | `activeSection('face')` | `engine.clipping.active('face')` |
|
2026-01-28 11:24:35 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 4.3 剖切盒 (Section Box)
|
|
|
|
|
|
|
|
|
|
|
|
**按钮 ID**: `section-box`
|
|
|
|
|
|
**功能**: 六面体剖切盒,可调节 X/Y/Z 轴的最小/最大范围
|
|
|
|
|
|
**保持激活**: 是
|
|
|
|
|
|
**互斥**: 是
|
|
|
|
|
|
|
|
|
|
|
|
#### 调用链 - 打开对话框
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
用户点击 [剖切盒] 按钮(激活)
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
Button onClick (buttons/section/section-box/index.ts)
|
|
|
|
|
|
│ registry.sectionBox?.show()
|
|
|
|
|
|
▼
|
|
|
|
|
|
SectionBoxDialogManager.show() (继承自 BaseDialogManager)
|
|
|
|
|
|
│ createContent() → 创建 SectionBoxPanel
|
|
|
|
|
|
│ onDialogCreated()
|
2026-02-02 16:25:36 +08:00
|
|
|
|
│ └── registry.engine3d?.activeSection('box')
|
2026-01-28 11:24:35 +08:00
|
|
|
|
▼
|
2026-02-02 16:25:36 +08:00
|
|
|
|
EngineManager.activeSection('box')
|
|
|
|
|
|
│ this.engineInstance.activeSection(mode)
|
2026-01-28 11:24:35 +08:00
|
|
|
|
▼
|
2026-02-02 16:25:36 +08:00
|
|
|
|
Engine.activeSection('box')
|
|
|
|
|
|
│ this.engine.clipping.active('box')
|
2026-01-28 11:24:35 +08:00
|
|
|
|
▼
|
2026-02-02 16:25:36 +08:00
|
|
|
|
底层引擎 API: engine.clipping.active('box')
|
2026-01-28 11:24:35 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 调用链 - 调整范围(拖动滑块)
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
用户拖动 X/Y/Z 轴滑块调整范围
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
SectionBoxPanel.onRangeChange(range)
|
|
|
|
|
|
│ range = { x: {min, max}, y: {min, max}, z: {min, max} } // 百分比 0-100
|
|
|
|
|
|
▼
|
|
|
|
|
|
SectionBoxDialogManager 回调
|
|
|
|
|
|
│ registry.engine3d?.setSectionBoxRange(range)
|
|
|
|
|
|
▼
|
|
|
|
|
|
EngineManager.setSectionBoxRange(range)
|
|
|
|
|
|
│ this.engineInstance.setSectionBoxRange(range)
|
|
|
|
|
|
▼
|
|
|
|
|
|
Engine.setSectionBoxRange(range)
|
2026-02-02 16:25:36 +08:00
|
|
|
|
│ this.engine.clipping.updateClippingValue(range)
|
2026-01-28 11:24:35 +08:00
|
|
|
|
▼
|
2026-02-02 16:25:36 +08:00
|
|
|
|
底层引擎 API: engine.clipping.updateClippingValue(range)
|
2026-01-28 11:24:35 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-02-02 16:25:36 +08:00
|
|
|
|
#### 调用链 - 适应到模型 / 重置 (已废弃)
|
2026-01-28 11:24:35 +08:00
|
|
|
|
|
2026-02-02 16:25:36 +08:00
|
|
|
|
**注意**: `fitSectionBoxToModel()` 和 `resetSectionBox()` 已从新 API 中移除。
|
|
|
|
|
|
- 用户点击这些按钮时,现在仅输出日志,不执行任何操作
|
|
|
|
|
|
- 统一使用 `setSectionBoxRange()` 和 `updateClippingValue()` 调整范围
|
2026-01-28 11:24:35 +08:00
|
|
|
|
|
|
|
|
|
|
#### 调用链 - 关闭对话框
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
用户关闭对话框 / 再次点击按钮
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
SectionBoxDialogManager.onBeforeDestroy()
|
2026-02-02 16:25:36 +08:00
|
|
|
|
│ registry.engine3d?.deactivateSection()
|
2026-01-28 11:24:35 +08:00
|
|
|
|
▼
|
2026-02-02 16:25:36 +08:00
|
|
|
|
EngineManager.deactivateSection()
|
|
|
|
|
|
│ this.engineInstance.deactivateSection()
|
2026-01-28 11:24:35 +08:00
|
|
|
|
▼
|
2026-02-02 16:25:36 +08:00
|
|
|
|
Engine.deactivateSection()
|
|
|
|
|
|
│ this.engine.clipping.disActive()
|
2026-01-28 11:24:35 +08:00
|
|
|
|
▼
|
2026-02-02 16:25:36 +08:00
|
|
|
|
底层引擎 API: engine.clipping.disActive()
|
2026-01-28 11:24:35 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-02-02 16:25:36 +08:00
|
|
|
|
#### 剖切盒 API 汇总 (新版统一 API)
|
2026-01-28 11:24:35 +08:00
|
|
|
|
|
|
|
|
|
|
| 操作 | Engine 方法 | 底层 API |
|
|
|
|
|
|
|------|-------------|----------|
|
2026-02-02 16:25:36 +08:00
|
|
|
|
| 激活 | `activeSection('box')` | `engine.clipping.active('box')` |
|
|
|
|
|
|
| 停用 | `deactivateSection()` | `engine.clipping.disActive()` |
|
|
|
|
|
|
| 设置范围 | `setSectionBoxRange(range)` | `engine.clipping.updateClippingValue(range)` |
|
|
|
|
|
|
| ~~适应到模型~~ | ~~`fitSectionBoxToModel()`~~ (已废弃) | - |
|
|
|
|
|
|
| ~~重置~~ | ~~`resetSectionBox()`~~ (已废弃) | - |
|
2026-01-28 11:24:35 +08:00
|
|
|
|
|
|
|
|
|
|
#### 数据格式说明
|
|
|
|
|
|
|
|
|
|
|
|
| 层级 | 数据格式 | 示例 |
|
|
|
|
|
|
|------|----------|------|
|
|
|
|
|
|
| UI / SDK | 百分比 (0-100) | `{ x: {min: 20, max: 80}, y: {...}, z: {...} }` |
|
|
|
|
|
|
| 底层引擎 | 百分比 → 内部转换为坐标 | 底层负责转换 |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 5. 漫游 (Walk) - 第一人称漫游
|
|
|
|
|
|
|
|
|
|
|
|
> 标注说明: `[SDK]` = SDK 层代码, `[底层]` = bim_engine_base 底层引擎
|
|
|
|
|
|
|
|
|
|
|
|
**按钮 ID**: `walk`
|
|
|
|
|
|
**功能**: 打开漫游控制面板,支持第一人称漫游模式
|
|
|
|
|
|
**保持激活**: 否
|
|
|
|
|
|
|
|
|
|
|
|
### 5.1 第一人称漫游模式开关
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
UI 点击漫游按钮
|
|
|
|
|
|
→ [SDK] WalkControlPanel.onWalkModeToggle(isActive)
|
|
|
|
|
|
→ [SDK] WalkControlManager.onWalkModeToggle
|
|
|
|
|
|
→ [SDK] EngineManager.activateFirstPersonMode() / deactivateFirstPersonMode()
|
|
|
|
|
|
→ [SDK] Engine.activateFirstPersonMode() / deactivateFirstPersonMode()
|
|
|
|
|
|
→ [底层] engine.controlModule.switchFirstPersonMode() / switchDefaultMode()
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 5.2 速度调节
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
UI 速度按钮 (1-10)
|
|
|
|
|
|
→ [SDK] WalkControlPanel.onSpeedChange(speed)
|
|
|
|
|
|
→ [SDK] WalkControlManager.onSpeedChange
|
|
|
|
|
|
→ [SDK] EngineManager.setWalkSpeed(speed * 0.01) // 值转换: UI 1-10 → 引擎 0.01-0.1
|
|
|
|
|
|
→ [SDK] Engine.setWalkSpeed(speed)
|
|
|
|
|
|
→ [底层] engine.controlModule.firstPersonControls.moveSpeed = speed
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 5.3 重力开关
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
UI 重力复选框
|
|
|
|
|
|
→ [SDK] WalkControlPanel.onGravityToggle(enabled)
|
|
|
|
|
|
→ [SDK] WalkControlManager.onGravityToggle
|
|
|
|
|
|
→ [SDK] EngineManager.setWalkGravity(enabled)
|
|
|
|
|
|
→ [SDK] Engine.setWalkGravity(enabled)
|
|
|
|
|
|
→ [底层] engine.controlModule.firstPersonControls.applyGravity = enabled
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 5.4 碰撞检测开关
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
UI 碰撞复选框
|
|
|
|
|
|
→ [SDK] WalkControlPanel.onCollisionToggle(enabled)
|
|
|
|
|
|
→ [SDK] WalkControlManager.onCollisionToggle
|
|
|
|
|
|
→ [SDK] EngineManager.setWalkCollision(enabled)
|
|
|
|
|
|
→ [SDK] Engine.setWalkCollision(enabled)
|
|
|
|
|
|
→ [底层] engine.controlModule.firstPersonControls.applyCollision = enabled
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 6. 地图 (Map)
|
|
|
|
|
|
|
|
|
|
|
|
**按钮 ID**: `map`
|
|
|
|
|
|
**功能**: 打开/关闭地图对话框
|
|
|
|
|
|
**保持激活**: 是
|
|
|
|
|
|
|
|
|
|
|
|
### 调用链
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
用户点击 [地图] 按钮
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
Button onClick (buttons/map/index.ts)
|
|
|
|
|
|
│ if (registry.map?.isOpen()) {
|
|
|
|
|
|
│ registry.map?.hide()
|
|
|
|
|
|
│ } else {
|
|
|
|
|
|
│ registry.map?.show()
|
|
|
|
|
|
│ }
|
|
|
|
|
|
▼
|
|
|
|
|
|
MapDialogManager.show() / hide()
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
地图对话框显示/隐藏
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 事件监听
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// 按钮定义中监听地图开关事件,同步按钮激活状态
|
|
|
|
|
|
registry.on('map:opened', () => {
|
|
|
|
|
|
registry.toolbar?.setBtnActive('map', true);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
registry.on('map:closed', () => {
|
|
|
|
|
|
registry.toolbar?.setBtnActive('map', false);
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 7. 构件详情 (Property)
|
|
|
|
|
|
|
|
|
|
|
|
**按钮 ID**: `property`
|
|
|
|
|
|
**功能**: 打开构件属性面板
|
|
|
|
|
|
**保持激活**: 否
|
|
|
|
|
|
|
|
|
|
|
|
### 调用链
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
用户点击 [构件详情] 按钮
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
Button onClick (buttons/property/index.ts)
|
2026-01-28 17:19:36 +08:00
|
|
|
|
│ registry.componentDetail?.show()
|
2026-01-28 11:24:35 +08:00
|
|
|
|
▼
|
2026-01-28 17:19:36 +08:00
|
|
|
|
ComponentDetailManager.show()
|
2026-01-28 11:24:35 +08:00
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
属性面板显示
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 8. 设置 (Setting)
|
|
|
|
|
|
|
|
|
|
|
|
**按钮 ID**: `setting`
|
|
|
|
|
|
**功能**: 打开设置面板
|
|
|
|
|
|
**保持激活**: 否
|
|
|
|
|
|
|
|
|
|
|
|
### 调用链
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
用户点击 [设置] 按钮
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
Button onClick (buttons/setting/index.ts)
|
|
|
|
|
|
│ console.log('设置按钮被点击')
|
|
|
|
|
|
▼
|
|
|
|
|
|
⚠️ 暂未实现具体功能
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 9. 信息 (Info)
|
|
|
|
|
|
|
|
|
|
|
|
**按钮 ID**: `info`
|
|
|
|
|
|
**功能**: 打开信息对话框
|
|
|
|
|
|
**保持激活**: 否
|
|
|
|
|
|
|
|
|
|
|
|
### 调用链
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
用户点击 [信息] 按钮
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
Button onClick (buttons/info/index.ts)
|
|
|
|
|
|
│ registry.emit('ui:open-dialog', { id: 'info' })
|
|
|
|
|
|
▼
|
|
|
|
|
|
事件系统广播 'ui:open-dialog' 事件
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
监听该事件的组件响应并打开信息对话框
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 10. 全屏 (Fullscreen)
|
|
|
|
|
|
|
|
|
|
|
|
**按钮 ID**: `fullscreen`
|
|
|
|
|
|
**功能**: 切换全屏模式
|
|
|
|
|
|
**保持激活**: 否
|
|
|
|
|
|
|
|
|
|
|
|
### 调用链
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
用户点击 [全屏] 按钮
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
Button onClick (buttons/fullscreen/index.ts)
|
|
|
|
|
|
│ // 检测当前是否全屏
|
|
|
|
|
|
│ const isFullscreen = !!document.fullscreenElement
|
|
|
|
|
|
│
|
|
|
|
|
|
├── 如果不是全屏:
|
|
|
|
|
|
│ targetElem.requestFullscreen({ navigationUI: 'hide' })
|
|
|
|
|
|
│ ▼
|
|
|
|
|
|
│ 浏览器 API: Element.requestFullscreen()
|
|
|
|
|
|
│
|
|
|
|
|
|
└── 如果是全屏:
|
|
|
|
|
|
document.exitFullscreen()
|
|
|
|
|
|
▼
|
|
|
|
|
|
浏览器 API: Document.exitFullscreen()
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 注意事项
|
|
|
|
|
|
|
|
|
|
|
|
- 全屏功能使用浏览器原生 API,不涉及底层 3D 引擎
|
|
|
|
|
|
- 支持多种浏览器前缀:`webkitRequestFullscreen`、`mozRequestFullScreen`、`msRequestFullscreen`
|
|
|
|
|
|
- 在 iframe 中使用需要父级 iframe 标签添加 `allow="fullscreen"` 属性
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 附录:调用链层级说明
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
┌─────────────────────────────────────────────────────────────────────┐
|
|
|
|
|
|
│ L1: Toolbar Button │
|
|
|
|
|
|
│ 文件: src/components/button-group/toolbar/buttons/*/index.ts │
|
|
|
|
|
|
│ 职责: 定义按钮配置,处理 onClick 事件 │
|
|
|
|
|
|
└────────────────────────────────┬────────────────────────────────────┘
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
┌─────────────────────────────────────────────────────────────────────┐
|
|
|
|
|
|
│ L2: DialogManager │
|
|
|
|
|
|
│ 文件: src/managers/*-dialog-manager.ts │
|
|
|
|
|
|
│ 职责: 管理对话框生命周期,绑定 Panel 回调到 EngineManager │
|
|
|
|
|
|
└────────────────────────────────┬────────────────────────────────────┘
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
┌─────────────────────────────────────────────────────────────────────┐
|
|
|
|
|
|
│ L3: EngineManager │
|
|
|
|
|
|
│ 文件: src/managers/engine-manager.ts │
|
|
|
|
|
|
│ 职责: 代理 Engine 组件,提供统一 API,检查初始化状态 │
|
|
|
|
|
|
└────────────────────────────────┬────────────────────────────────────┘
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
┌─────────────────────────────────────────────────────────────────────┐
|
|
|
|
|
|
│ L4: Engine Component │
|
|
|
|
|
|
│ 文件: src/components/engine/index.ts │
|
|
|
|
|
|
│ 职责: 封装底层引擎,维护状态,进行数据转换 │
|
|
|
|
|
|
└────────────────────────────────┬────────────────────────────────────┘
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
┌─────────────────────────────────────────────────────────────────────┐
|
|
|
|
|
|
│ L5: 底层 3D 引擎 (iflow-engine-base) │
|
|
|
|
|
|
│ 来源: 第三方 SDK │
|
|
|
|
|
|
│ 职责: 实际 3D 渲染和功能实现 │
|
|
|
|
|
|
└─────────────────────────────────────────────────────────────────────┘
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 附录:ManagerRegistry 访问方式
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// 在 Button 中获取 Registry
|
|
|
|
|
|
const registry = ManagerRegistry.getInstance();
|
|
|
|
|
|
|
|
|
|
|
|
// 访问各个 Manager
|
|
|
|
|
|
registry.engine3d // EngineManager - 3D 引擎
|
|
|
|
|
|
registry.toolbar // ToolbarManager - 工具栏
|
|
|
|
|
|
registry.dialog // DialogManager - 对话框
|
|
|
|
|
|
registry.measure // MeasureDialogManager - 测量
|
|
|
|
|
|
registry.sectionPlane // SectionPlaneDialogManager - 拾取面剖切
|
|
|
|
|
|
registry.sectionAxis // SectionAxisDialogManager - 轴向剖切
|
|
|
|
|
|
registry.sectionBox // SectionBoxDialogManager - 剖切盒
|
|
|
|
|
|
registry.walkControl // WalkControlManager - 漫游控制
|
|
|
|
|
|
registry.map // MapDialogManager - 地图
|
2026-01-28 17:19:36 +08:00
|
|
|
|
registry.componentDetail // ComponentDetailManager - 构件详情弹窗
|
|
|
|
|
|
registry.componentDetail // ComponentDetailManager - 构件详情弹窗
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
# 第二章:右键菜单 (Context Menu)
|
|
|
|
|
|
|
|
|
|
|
|
右键菜单系统提供上下文相关的操作选项,根据当前状态动态生成菜单项。
|
|
|
|
|
|
|
|
|
|
|
|
## 2.1 构件详情 (Component Detail)
|
|
|
|
|
|
|
|
|
|
|
|
**触发条件**: 用户右键点击,且有构件被选中
|
|
|
|
|
|
**功能**: 打开构件详情弹窗,展示构件属性信息
|
|
|
|
|
|
|
|
|
|
|
|
### 调用链
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
用户右键点击 3D 场景(有构件选中)
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
RightKeyManager.handleContextMenu() (managers/right-key-manager.ts)
|
|
|
|
|
|
│ 获取当前选中构件: registry.engine3d.getSelectedComponent()
|
|
|
|
|
|
│ 动态生成菜单项(包含"构件详情")
|
|
|
|
|
|
▼
|
|
|
|
|
|
用户点击 [构件详情] 菜单项
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
MenuItem onClick (managers/engine-manager.ts:63-68)
|
|
|
|
|
|
│ registry.componentDetail?.show(selected.url, selected.id)
|
|
|
|
|
|
▼
|
|
|
|
|
|
ComponentDetailManager.show(url, id) (managers/component-detail-manager.ts)
|
|
|
|
|
|
│ 1. createDialog() - 创建右侧对话框(400px 宽)
|
|
|
|
|
|
│ 2. showLoading() - 显示"加载中..."
|
|
|
|
|
|
│ 3. registry.engine3d.getComponentProperties(url, id, callback)
|
|
|
|
|
|
▼
|
|
|
|
|
|
EngineManager.getComponentProperties(url, id, callback)
|
|
|
|
|
|
│ this.engineInstance.getComponentProperties(url, id, callback)
|
|
|
|
|
|
▼
|
|
|
|
|
|
Engine.getComponentProperties(url, id, callback)
|
|
|
|
|
|
│ this.engine.modelProperties.getModelProperties(url, id, callback)
|
|
|
|
|
|
▼
|
|
|
|
|
|
底层引擎 API: engine.modelProperties.getModelProperties(url, id, callback)
|
|
|
|
|
|
│ 异步回调返回属性数据
|
|
|
|
|
|
▼
|
|
|
|
|
|
ComponentDetailManager.renderProperties(data)
|
|
|
|
|
|
│ 使用 BimCollapse + BimDescription 渲染属性
|
|
|
|
|
|
▼
|
|
|
|
|
|
对话框显示构件属性(分类折叠面板 + 键值对列表)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 数据流
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// 1. 选中信息 (从 Engine)
|
|
|
|
|
|
{
|
|
|
|
|
|
url: string, // 模型 URL
|
|
|
|
|
|
id: string // 构件 ID
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 属性数据 (从底层引擎回调)
|
|
|
|
|
|
[
|
|
|
|
|
|
{
|
|
|
|
|
|
categoryName: "基本属性",
|
|
|
|
|
|
items: [
|
|
|
|
|
|
{ key: "名称", value: "墙-001" },
|
|
|
|
|
|
{ key: "类型", value: "承重墙" }
|
|
|
|
|
|
]
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
categoryName: "尺寸",
|
|
|
|
|
|
items: [
|
|
|
|
|
|
{ key: "长度", value: "5000mm" },
|
|
|
|
|
|
{ key: "高度", value: "3000mm" }
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
// 3. UI 渲染 (BimCollapse)
|
|
|
|
|
|
- 每个 category → 一个折叠面板
|
|
|
|
|
|
- items[] → BimDescription 键值对列表
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 代码摘要
|
|
|
|
|
|
|
|
|
|
|
|
**动态菜单生成** (`managers/engine-manager.ts`):
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
const selected = this.getSelectedComponent();
|
|
|
|
|
|
if (selected) {
|
|
|
|
|
|
menuItems.push({
|
|
|
|
|
|
id: 'component-detail',
|
|
|
|
|
|
label: 'menu.componentDetail',
|
|
|
|
|
|
group: 'component',
|
|
|
|
|
|
onClick: () => {
|
|
|
|
|
|
const registry = ManagerRegistry.getInstance();
|
|
|
|
|
|
registry.componentDetail?.show(selected.url, selected.id);
|
|
|
|
|
|
this.rightKey?.hide();
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**ComponentDetailManager** (`managers/component-detail-manager.ts`):
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
public show(modelUrl: string, componentId: string): void {
|
|
|
|
|
|
this.createDialog();
|
|
|
|
|
|
this.showLoading();
|
|
|
|
|
|
|
|
|
|
|
|
const registry = ManagerRegistry.getInstance();
|
|
|
|
|
|
registry.engine3d?.getComponentProperties(
|
|
|
|
|
|
modelUrl,
|
|
|
|
|
|
componentId,
|
|
|
|
|
|
(data) => {
|
|
|
|
|
|
this.renderProperties(data);
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 2.2 显示全部 (Show All)
|
|
|
|
|
|
|
|
|
|
|
|
**触发条件**: 用户右键点击(任何情况)
|
|
|
|
|
|
**功能**: 显示所有已加载的模型构件
|
|
|
|
|
|
|
|
|
|
|
|
### 调用链
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
用户右键点击 3D 场景
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
RightKeyManager.handleContextMenu()
|
|
|
|
|
|
│ 动态生成菜单项(始终包含"显示全部")
|
|
|
|
|
|
▼
|
|
|
|
|
|
用户点击 [显示全部] 菜单项
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
MenuItem onClick (managers/engine-manager.ts:71-77)
|
|
|
|
|
|
│ registry.engine3d?.showAllComponents()
|
|
|
|
|
|
▼
|
|
|
|
|
|
EngineManager.showAllComponents()
|
|
|
|
|
|
│ ⚠️ 方法尚未实现,当前为空方法
|
|
|
|
|
|
▼
|
|
|
|
|
|
⚠️ 待实现:调用底层引擎 API 显示所有构件
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
> **注意**: "显示全部"功能的底层 API 对接尚未完成,当前仅显示菜单项。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 2.3 信息 (Info)
|
|
|
|
|
|
|
|
|
|
|
|
**触发条件**: 用户右键点击(任何情况)
|
|
|
|
|
|
**功能**: 打开信息对话框
|
|
|
|
|
|
|
|
|
|
|
|
### 调用链
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
用户右键点击 3D 场景
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
RightKeyManager.handleContextMenu()
|
|
|
|
|
|
│ 动态生成菜单项(始终包含"信息")
|
|
|
|
|
|
▼
|
|
|
|
|
|
用户点击 [信息] 菜单项
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
MenuItem onClick (managers/engine-manager.ts)
|
|
|
|
|
|
│ registry.emit('ui:open-dialog', { id: 'info' })
|
|
|
|
|
|
│ this.rightKey?.hide()
|
|
|
|
|
|
▼
|
|
|
|
|
|
事件系统广播 'ui:open-dialog' 事件
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
监听该事件的组件响应并打开信息对话框
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 2.4 首页 (Home)
|
|
|
|
|
|
|
|
|
|
|
|
**触发条件**: 用户右键点击(任何情况)
|
|
|
|
|
|
**功能**: 相机回到初始位置
|
|
|
|
|
|
|
|
|
|
|
|
### 调用链
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
用户右键点击 3D 场景
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
RightKeyManager.handleContextMenu()
|
|
|
|
|
|
│ 动态生成菜单项(始终包含"首页")
|
|
|
|
|
|
▼
|
|
|
|
|
|
用户点击 [首页] 菜单项
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
MenuItem onClick (managers/engine-manager.ts)
|
|
|
|
|
|
│ registry.engine3d?.CameraGoHome()
|
|
|
|
|
|
│ this.rightKey?.hide()
|
|
|
|
|
|
▼
|
|
|
|
|
|
(调用链同 Toolbar 首页按钮)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 右键菜单系统架构
|
|
|
|
|
|
|
|
|
|
|
|
### 动态菜单机制
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// 1. 注册处理器 (EngineManager.initialize)
|
|
|
|
|
|
const handler: RightKeyHandler = () => {
|
|
|
|
|
|
const menuItems: MenuItemConfig[] = [];
|
|
|
|
|
|
|
|
|
|
|
|
// 根据选中状态动态生成菜单
|
|
|
|
|
|
const selected = this.getSelectedComponent();
|
|
|
|
|
|
if (selected) {
|
|
|
|
|
|
menuItems.push({ /* 构件详情 */ });
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 通用菜单项
|
|
|
|
|
|
menuItems.push({ /* 显示全部 */ });
|
|
|
|
|
|
menuItems.push({ /* 信息 */ });
|
|
|
|
|
|
menuItems.push({ /* 首页 */ });
|
|
|
|
|
|
|
|
|
|
|
|
return menuItems;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
registry.rightKey?.registerHandler('engine', handler);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 菜单项配置结构
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
interface MenuItemConfig {
|
|
|
|
|
|
id: string; // 唯一标识
|
|
|
|
|
|
label: string; // 国际化 key
|
|
|
|
|
|
group?: string; // 分组(可选)
|
|
|
|
|
|
onClick: () => void; // 点击回调
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
# 第三章:构件交互 (Component Interaction)
|
|
|
|
|
|
|
|
|
|
|
|
构件交互系统处理用户与 3D 场景中构件的交互事件,包括选中和取消选中。
|
|
|
|
|
|
|
|
|
|
|
|
## 3.1 构件选中 (Component Selection)
|
|
|
|
|
|
|
|
|
|
|
|
**触发**: 用户点击 3D 场景中的构件
|
|
|
|
|
|
**效果**: 记录选中状态,可用于后续操作(如右键菜单、属性面板等)
|
|
|
|
|
|
|
|
|
|
|
|
### 调用链
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
用户点击 3D 场景中的构件
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
[底层] interactionModule.handleMouseClick() (bim_engine_base)
|
|
|
|
|
|
│ 检测鼠标点击并进行射线拾取
|
|
|
|
|
|
│ 获取点击到的物体信息 (hit)
|
|
|
|
|
|
▼
|
|
|
|
|
|
[底层] engine.events.trigger('click', hit)
|
|
|
|
|
|
│ hit = { object: { url, name }, point, distance, ... }
|
|
|
|
|
|
▼
|
|
|
|
|
|
[SDK] Engine.init() 中的 'click' 事件监听器 (components/engine/index.ts:127-136)
|
|
|
|
|
|
│ if (hit && hit.object) {
|
|
|
|
|
|
│ this.selectedComponent = {
|
|
|
|
|
|
│ url: hit.object.url,
|
|
|
|
|
|
│ id: hit.object.name
|
|
|
|
|
|
│ };
|
|
|
|
|
|
│ console.log('[Engine] 构件选中:', this.selectedComponent);
|
|
|
|
|
|
│ }
|
|
|
|
|
|
▼
|
|
|
|
|
|
选中状态已记录在 Engine.selectedComponent
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 状态存储
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// Engine 组件 (components/engine/index.ts)
|
|
|
|
|
|
private selectedComponent: { url: string; id: string } | null = null;
|
|
|
|
|
|
|
|
|
|
|
|
// 点击事件监听器
|
|
|
|
|
|
this.engine.events.on('click', (hit: any) => {
|
|
|
|
|
|
if (hit && hit.object) {
|
|
|
|
|
|
this.selectedComponent = {
|
|
|
|
|
|
url: hit.object.url,
|
|
|
|
|
|
id: hit.object.name
|
|
|
|
|
|
};
|
|
|
|
|
|
console.log('[Engine] 构件选中:', this.selectedComponent);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.selectedComponent = null;
|
|
|
|
|
|
console.log('[Engine] 取消选中');
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 获取选中状态
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// Engine 方法
|
|
|
|
|
|
public getSelectedComponent(): { url: string; id: string } | null {
|
|
|
|
|
|
return this.selectedComponent;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// EngineManager 代理
|
|
|
|
|
|
public getSelectedComponent(): { url: string; id: string } | null {
|
|
|
|
|
|
if (!this.engineInstance) {
|
|
|
|
|
|
console.warn('[EngineManager] Engine 尚未初始化');
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
return this.engineInstance.getSelectedComponent();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 使用示例
|
|
|
|
|
|
const registry = ManagerRegistry.getInstance();
|
|
|
|
|
|
const selected = registry.engine3d?.getSelectedComponent();
|
|
|
|
|
|
if (selected) {
|
|
|
|
|
|
console.log(`选中构件: ${selected.url}#${selected.id}`);
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 3.2 取消选中 (Deselection)
|
|
|
|
|
|
|
|
|
|
|
|
**触发**: 用户点击 3D 场景的空白区域
|
|
|
|
|
|
**效果**: 清除选中状态
|
|
|
|
|
|
|
|
|
|
|
|
### 调用链
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
用户点击 3D 场景空白区域
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
[底层] interactionModule.handleMouseClick()
|
|
|
|
|
|
│ 射线拾取未命中任何物体
|
|
|
|
|
|
▼
|
|
|
|
|
|
[底层] engine.events.trigger('click', null)
|
|
|
|
|
|
│ hit = null(表示未点击到任何物体)
|
|
|
|
|
|
▼
|
|
|
|
|
|
[SDK] Engine.init() 中的 'click' 事件监听器
|
|
|
|
|
|
│ if (hit && hit.object) { ... }
|
|
|
|
|
|
│ else {
|
|
|
|
|
|
│ this.selectedComponent = null;
|
|
|
|
|
|
│ console.log('[Engine] 取消选中');
|
|
|
|
|
|
│ }
|
|
|
|
|
|
▼
|
|
|
|
|
|
选中状态已清除
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 构件交互数据流
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
|
|
|
|
│ [底层] 3D 引擎 - 事件系统 │
|
|
|
|
|
|
│ engine.events.trigger('click', hit) │
|
|
|
|
|
|
└────────────────────────────┬────────────────────────────────────┘
|
|
|
|
|
|
│
|
|
|
|
|
|
▼ hit: { object: {url, name}, ... } | null
|
|
|
|
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
|
|
|
|
│ [SDK] Engine 组件 - 事件监听 + 状态管理 │
|
|
|
|
|
|
│ - 监听 'click' 事件 │
|
|
|
|
|
|
│ - 更新 selectedComponent 状态 │
|
|
|
|
|
|
│ - 提供 getSelectedComponent() 方法 │
|
|
|
|
|
|
└────────────────────────────┬────────────────────────────────────┘
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
|
|
|
|
│ [SDK] EngineManager - 状态代理 │
|
|
|
|
|
|
│ - 代理 getSelectedComponent() 方法 │
|
|
|
|
|
|
│ - 供其他 Manager 调用 │
|
|
|
|
|
|
└────────────────────────────┬────────────────────────────────────┘
|
|
|
|
|
|
│
|
|
|
|
|
|
▼
|
|
|
|
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
|
|
|
|
│ [SDK] 消费者 - 使用选中状态 │
|
|
|
|
|
|
│ - RightKeyManager: 动态生成右键菜单 │
|
|
|
|
|
|
│ - ComponentDetailManager: 显示构件详情 │
|
|
|
|
|
|
│ - ComponentDetailManager: 显示构件详情弹窗 │
|
|
|
|
|
|
│ - ... 其他需要选中状态的功能 │
|
|
|
|
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 使用场景示例
|
|
|
|
|
|
|
|
|
|
|
|
### 场景 1: 右键菜单根据选中状态显示不同菜单项
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// RightKeyManager.handleContextMenu()
|
|
|
|
|
|
const handler: RightKeyHandler = () => {
|
|
|
|
|
|
const menuItems: MenuItemConfig[] = [];
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否有选中的构件
|
|
|
|
|
|
const selected = registry.engine3d?.getSelectedComponent();
|
|
|
|
|
|
|
|
|
|
|
|
if (selected) {
|
|
|
|
|
|
// 有选中构件:显示"构件详情"菜单
|
|
|
|
|
|
menuItems.push({
|
|
|
|
|
|
id: 'component-detail',
|
|
|
|
|
|
label: 'menu.componentDetail',
|
|
|
|
|
|
onClick: () => {
|
|
|
|
|
|
registry.componentDetail?.show(selected.url, selected.id);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 通用菜单项(无论是否选中都显示)
|
|
|
|
|
|
menuItems.push({
|
|
|
|
|
|
id: 'show-all',
|
|
|
|
|
|
label: 'menu.showAll',
|
|
|
|
|
|
onClick: () => { /* ... */ }
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return menuItems;
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 场景 2: 构件详情面板获取当前选中构件
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// ComponentDetailManager
|
|
|
|
|
|
public showCurrentSelection(): void {
|
|
|
|
|
|
const registry = ManagerRegistry.getInstance();
|
|
|
|
|
|
const selected = registry.engine3d?.getSelectedComponent();
|
|
|
|
|
|
|
|
|
|
|
|
if (!selected) {
|
|
|
|
|
|
console.warn('未选中任何构件');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 使用选中信息加载构件详情
|
|
|
|
|
|
this.show(selected.url, selected.id);
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 附录:完整 ManagerRegistry 访问方式(更新)
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
// 在任意位置获取 Registry
|
|
|
|
|
|
const registry = ManagerRegistry.getInstance();
|
|
|
|
|
|
|
|
|
|
|
|
// 访问各个 Manager
|
|
|
|
|
|
registry.engine3d // EngineManager - 3D 引擎
|
|
|
|
|
|
registry.toolbar // ToolbarManager - 工具栏
|
|
|
|
|
|
registry.dialog // DialogManager - 对话框
|
|
|
|
|
|
registry.rightKey // RightKeyManager - 右键菜单
|
|
|
|
|
|
registry.measure // MeasureDialogManager - 测量
|
|
|
|
|
|
registry.sectionPlane // SectionPlaneDialogManager - 拾取面剖切
|
|
|
|
|
|
registry.sectionAxis // SectionAxisDialogManager - 轴向剖切
|
|
|
|
|
|
registry.sectionBox // SectionBoxDialogManager - 剖切盒
|
|
|
|
|
|
registry.walkControl // WalkControlManager - 漫游控制
|
|
|
|
|
|
registry.map // MapDialogManager - 地图
|
|
|
|
|
|
registry.componentDetail // ComponentDetailManager - 构件详情弹窗
|
|
|
|
|
|
registry.componentDetail // ComponentDetailManager - 构件详情弹窗(新增)
|
2026-01-28 11:24:35 +08:00
|
|
|
|
```
|