Files
bim_engine/.sisyphus/drafts/TOOLBAR_API_CALLCHAIN.md
2026-01-28 11:24:35 +08:00

22 KiB
Raw Blame History

Toolbar 按钮调用链文档

本文档详细记录 Toolbar 中每个按钮的完整调用链,从用户点击到底层 3D 引擎 API。


目录

  1. 首页 (Home)
  2. 框选放大 (Zoom Box)
  3. 测量 (Measure)
  4. 剖切菜单 (Section)
  5. 漫游 (Walk)
  6. 地图 (Map)
  7. 构件详情 (Property)
  8. 设置 (Setting)
  9. 信息 (Info)
  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):

onClick: (button) => {
    const registry = ManagerRegistry.getInstance();
    registry.engine3d?.CameraGoHome();
}

EngineManager (managers/engine-manager.ts):

public CameraGoHome(): void {
    this.engineInstance.CameraGoHome();
}

Engine 组件 (components/engine/index.ts):

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):

onClick: () => {
    const registry = ManagerRegistry.getInstance();
    registry.engine3d?.activateZoomBox();
}

EngineManager (managers/engine-manager.ts):

public activateZoomBox(): void {
    this.engineInstance.activateZoomBox();
}

Engine 组件 (components/engine/index.ts):

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()
    │       └── registry.engine3d.activateSectionAxis('x')  // 默认激活 X 轴
    ▼
EngineManager.activateSectionAxis('x')
    │   this.engineInstance.activateSectionAxis(axis)
    ▼
Engine.activateSectionAxis('x')
    │   this.engine.clipping.sectionPlaneX.active()
    ▼
底层引擎 API: engine.clipping.sectionPlaneX.active()

调用链 - 切换轴向

用户在 Panel 中切换轴向Y 轴)
    │
    ▼
SectionAxisPanel.onAxisChange('y')
    │
    ▼
SectionAxisDialogManager 回调
    │   registry.engine3d?.activateSectionAxis('y')
    ▼
EngineManager.activateSectionAxis('y')
    │   this.engineInstance.activateSectionAxis(axis)
    ▼
Engine.activateSectionAxis('y')
    │   // 1. 先停用当前轴向 (X)
    │   this.engine.clipping.sectionPlaneX.disActive()
    │   // 2. 再激活新轴向 (Y)
    │   this.engine.clipping.sectionPlaneY.active()
    ▼
底层引擎 API:
    - engine.clipping.sectionPlaneX.disActive()
    - engine.clipping.sectionPlaneY.active()

调用链 - 关闭对话框

用户关闭对话框 / 再次点击按钮
    │
    ▼
SectionAxisDialogManager.onBeforeDestroy()
    │   registry.engine3d?.deactivateSectionAxis()
    ▼
EngineManager.deactivateSectionAxis()
    │   this.engineInstance.deactivateSectionAxis()
    ▼
Engine.deactivateSectionAxis()
    │   this.engine.clipping.disActive()
    ▼
底层引擎 API: engine.clipping.disActive()

轴向与底层 API 对照表

轴向 Engine 内部调用 底层 API
x planeMap['x'] engine.clipping.sectionPlaneX.active()
y planeMap['y'] engine.clipping.sectionPlaneY.active()
z planeMap['z'] engine.clipping.sectionPlaneZ.active()

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()
    │       └── registry.engine3d?.activateSectionBox()
    ▼
EngineManager.activateSectionBox()
    │   this.engineInstance.activateSectionBox()
    ▼
Engine.activateSectionBox()
    │   this.engine.clipping.sectionBox.active()
    ▼
底层引擎 API: engine.clipping.sectionBox.active()

调用链 - 调整范围(拖动滑块)

用户拖动 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)
    │   this.engine.clipping.sectionBox.setboxPercent(range)  // 直传百分比
    ▼
底层引擎 API: engine.clipping.sectionBox.setboxPercent(range)
    │   (底层负责百分比→坐标转换)

调用链 - 适应到模型

用户点击 [适应到模型] 按钮
    │
    ▼
SectionBoxPanel.onFitToModel()
    │
    ▼
SectionBoxDialogManager 回调
    │   registry.engine3d?.fitSectionBoxToModel()
    ▼
EngineManager.fitSectionBoxToModel()
    │   this.engineInstance.fitSectionBoxToModel()
    ▼
Engine.fitSectionBoxToModel()
    │   const box = this.engine.octreeBox?.getBoundingBox()
    │   this.engine.clipping.sectionBox.setBox(box)
    ▼
底层引擎 API:
    - engine.octreeBox.getBoundingBox()
    - engine.clipping.sectionBox.setBox(box)

调用链 - 重置

用户点击 [重置] 按钮
    │
    ▼
SectionBoxPanel.onReset()
    │
    ▼
SectionBoxDialogManager 回调
    │   registry.engine3d?.resetSectionBox()
    ▼
EngineManager.resetSectionBox()
    │   this.engineInstance.resetSectionBox()
    ▼
Engine.resetSectionBox()
    │   this.fitSectionBoxToModel()  // 内部调用适应到模型
    ▼
(同上 "适应到模型" 流程)

调用链 - 关闭对话框

用户关闭对话框 / 再次点击按钮
    │
    ▼
SectionBoxDialogManager.onBeforeDestroy()
    │   registry.engine3d?.deactivateSectionBox()
    ▼
EngineManager.deactivateSectionBox()
    │   this.engineInstance.deactivateSectionBox()
    ▼
Engine.deactivateSectionBox()
    │   this.engine.clipping.sectionBox.disActive()
    ▼
底层引擎 API: engine.clipping.sectionBox.disActive()

剖切盒 API 汇总

操作 Engine 方法 底层 API
激活 activateSectionBox() engine.clipping.sectionBox.active()
停用 deactivateSectionBox() engine.clipping.sectionBox.disActive()
设置范围(百分比) setSectionBoxRange(range) engine.clipping.sectionBox.setboxPercent(range)
设置范围(坐标) - engine.clipping.sectionBox.setboxXyz(xyz)
适应到模型 fitSectionBoxToModel() engine.clipping.sectionBox.setBox(box)
获取包围盒 - engine.octreeBox.getBoundingBox()

数据格式说明

层级 数据格式 示例
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()
    │
    ▼
地图对话框显示/隐藏

事件监听

// 按钮定义中监听地图开关事件,同步按钮激活状态
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)
    │   registry.propertyPanel?.show()
    ▼
PropertyPanelManager.show()
    │
    ▼
属性面板显示

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 引擎
  • 支持多种浏览器前缀:webkitRequestFullscreenmozRequestFullScreenmsRequestFullscreen
  • 在 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 访问方式

// 在 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 - 地图
registry.propertyPanel   // PropertyPanelManager - 属性面板