Files
bim_engine/docs/MODULES/设置系统.md

927 lines
24 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.

# 设置系统模块文档
> 本文档基于 `iflow-engine` SDK 真实代码实现说明设置系统的架构、API 和第三方预设接入方式。
## 目录
- [1. 架构概览](#1-架构概览)
- [2. 核心类型](#2-核心类型)
- [3. 设置面板UI](#3-设置面板ui)
- [4. API 参考](#4-api-参考)
- [5. 第三方预设接入](#5-第三方预设接入)
- [6. 事件系统](#6-事件系统)
---
## 1. 架构概览
设置系统采用分层架构:
```
┌─────────────────────────────────────────────────────────┐
│ UI 层: Toolbar Setting Button │
│ -> registry.setting.toggle() │
└─────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│ Manager 层: SettingDialogManager │
│ - 管理设置面板生命周期 │
│ - 维护预设列表 │
│ - 编排设置应用流程 │
└─────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│ 组件层: Engine (src/components/engine/index.ts) │
│ - 封装底层引擎设置能力 │
│ - 提供统一 getSettings/setSettings API │
└─────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│ 底层: iflow-engine-base │
│ - 实际 WebGL/Three.js 渲染设置 │
│ - Setting 模块 (shadow, lighting, env, etc.) │
└─────────────────────────────────────────────────────────┘
```
### 关键文件
| 文件 | 职责 |
|------|------|
| `src/managers/setting-dialog-manager.ts` | 设置对话框管理器UI 和预设管理 |
| `src/components/engine/index.ts` | 引擎组件,设置 API 实现 |
| `src/components/engine/types.ts` | 设置相关类型定义 |
| `src/types/events.ts` | 设置相关事件定义 |
| `src/locales/zh-CN.ts` | 设置面板文案国际化 |
---
## 2. 核心类型
### 2.1 EngineSettings - 完整设置
```typescript
interface EngineSettings {
render: RenderSettings;
display: DisplaySettings;
environment: EnvironmentSettings;
}
interface RenderSettings {
mode: 'simple' | 'balance' | 'advanced'; // 渲染模式
contrast: number; // 对比度 0-100
saturation: number; // 饱和度 0-100
shadowIntensity: number; // 阴影强度 0-100
lightIntensity: number; // 光照强度 0-100
gtaoIntensity: number; // GTAO 强度 0-100
}
interface DisplaySettings {
showEdge: boolean; // 显示边线
edgeOpacity: number; // 边线透明度 0-100
showGrid: boolean; // 显示轴网
showLevel: boolean; // 显示标高
showGround: boolean; // 显示地面
groundId: string; // 地面类型 ID
groundHeight: number; // 地面高度 (米)
}
interface EnvironmentSettings {
type: 'none' | 'hdr' | 'sky'; // 环境类型
hdrId: string; // HDR 背景 ID
hdrIntensity: number; // HDR 强度 0-100
skyPreset: string; // 天空预设
skyParams: SkyParams; // 天空高级参数
skyIntensity: number; // 天空强度 0-100
}
interface SkyParams {
turbidity?: number;
rayleigh?: number;
mieCoefficient?: number;
mieDirectionalG?: number;
elevation?: number;
azimuth?: number;
exposure?: number;
orthoExposureScale?: number;
cloudCoverage?: number;
cloudDensity?: number;
cloudElevation?: number;
showSunDisc?: boolean;
}
```
### 2.2 EngineSettingPreset - 预设定义
```typescript
interface EngineSettingPreset {
id: string; // 唯一标识
presetName: string; // 预设显示名称
isDefault: boolean; // 是否为默认预设
settings: EngineSettings; // 预设包含的设置
readonly?: boolean; // 是否只读
source?: 'sdk-default' | 'external' | 'user'; // 预设来源
}
```
**source 字段说明:**
- `'sdk-default'`: SDK 内置的默认预设
- `'external'`: 第三方注入的预设
- `'user'`: 用户自行保存的预设
### 2.3 设置补丁 (局部更新)
```typescript
interface EngineSettingsPatch {
render?: Partial<RenderSettings>;
display?: Partial<DisplaySettings>;
environment?: Partial<EnvironmentSettings>;
}
```
### 2.4 预设资源列表
```typescript
interface SettingPresetLists {
ground: PresetListItem[]; // 地面类型列表
hdr: PresetListItem[]; // HDR 背景列表
sky: PresetListItem[]; // 天空预设列表
}
interface PresetListItem {
id: string;
names: string[]; // [中文名, 繁体名, 英文名]
}
```
---
## 3. 设置面板UI
### 3.1 面板结构
设置对话框宽度 `420px`,包含以下区域:
```
┌───────────────────────────────────────────┐
│ 设置 [×] │ ← 标题栏
├───────────────────────────────────────────┤
│ │
│ ▓▓ 渲染设置 ▓▓ │
│ 渲染模式: [性能] [平衡] [效果] │
│ 阴影强度: [══════════════●══] 75 │
│ 光照强度: [════════●═══════] 50 │
│ 对比度: [════════●═══════] 50 (效果模式可见)
│ 饱和度: [════════●═══════] 50 (效果模式可见)
│ GTAO: [════════●═══════] 50 (效果模式可见)
│ │
│ ▓▓ 显示设置 ▓▓ │
│ 边线 [◉] 透明度 [═══●═══] 50 │
│ 轴网 [◉] │
│ 标高 [◉] │
│ 地面 [◉] 类型 [地面一 ▼] 高度 [0] │
│ │
│ ▓▓ 环境背景 ▓▓ │
│ [无] [HDR背景] [天空盒] │
│ HDR: [hdr-001 ▼] 强度 [══●═══] 40 │
│ 或 │
│ 天空: [晴朗 ▼] 强度 [══●═══] 40 │
│ │
├───────────────────────────────────────────┤
│ [撤销修改] │ ← 修改时显示
│ [预设选择 ▼] [🗑] [保存预设] │ ← 底部操作栏
└───────────────────────────────────────────┘
```
### 3.2 UI 交互规则
1. **渲染模式条件显示**
- `contrast`, `saturation`, `gtaoIntensity` 仅在 `advanced` 模式下显示
- 切换模式时面板不抖动,控件平滑显示/隐藏
2. **环境类型互斥**
- `none`: 无环境背景
- `hdr`: 显示 HDR 选择器和强度滑块
- `sky`: 显示天空预设选择器和强度滑块
3. **显示设置联动**
- 边线开启后才显示透明度滑块
- 地面开启后才显示地面类型和高度输入
---
## 4. API 参考
### 4.1 SettingDialogManager
文件: `src/managers/setting-dialog-manager.ts`
#### 生命周期
```typescript
// 初始化设置管理器
init(): void
// 销毁设置管理器
destroy(): void
```
#### 对话框控制
```typescript
// 显示设置对话框
show(): void
// 隐藏设置对话框
hide(): void
// 切换显示状态
toggle(): void
// 获取对话框是否打开
isOpen(): boolean
```
#### 预设管理
```typescript
/**
* 设置/注入预设列表
* @param presets 预设数组,会合并到现有预设列表
*/
setPresetList(presets: EngineSettingPreset[]): void
// 获取当前预设列表
getPresetList(): EngineSettingPreset[]
// 获取当前选中的预设
getSelectedPreset(): EngineSettingPreset | null
// 应用指定 ID 的预设
applyPresetById(id: string): Promise<void>
```
### 4.2 Engine 组件设置 API
文件: `src/components/engine/index.ts`
#### 批量设置
```typescript
/**
* 获取当前完整设置
* @returns 当前 EngineSettings 的深拷贝
*/
getSettings(): EngineSettings
/**
* 应用设置补丁
* @param patch 部分设置,会合并到当前设置
* @returns Promise设置应用完成后 resolve
*/
setSettings(patch: EngineSettingsPatch): Promise<void>
/**
* 重置为默认设置
* @returns Promise
*/
resetToDefault(): Promise<void>
```
#### 预设资源
```typescript
/**
* 获取预设资源列表(地面/HDR/天空)
* @returns 各类资源的可用选项
*/
getPresetLists(): SettingPresetLists
```
#### 渲染模式
```typescript
// 获取当前渲染模式
getRenderMode(): 'simple' | 'balance' | 'advanced'
// 设置渲染模式
setRenderMode(mode: 'simple' | 'balance' | 'advanced'): void
```
#### 光照与渲染
```typescript
// 环境光强度
setAmbientLightIntensity(intensity: number): void // 0-100
getAmbientLightIntensity(): number
// 对比度
setSceneContrast(contrast: number): void // 0-100
getSceneContrast(): number
// 饱和度
setSceneSaturation(saturation: number): void // 0-100
getSceneSaturation(): number
// 阴影强度
setShadowIntensity(intensity: number): void // 0-100
```
#### 边线
```typescript
// 启用边线
activeModelEdge(): void
// 禁用边线
disActiveModelEdge(): void
// 获取边线是否启用
getModelEdgeActive(): boolean
// 设置边线透明度
setEdgeOpacity(opacity: number): void // 0-100
```
#### HDR 背景
```typescript
// 获取 HDR 列表
getHDRBackgroundList(): { name: string; id: string }[]
// 设置 HDR ID
setHDRBackgroundId(id: string): void
// 获取当前 HDR ID
getHDRBackgroundId(): string
// 设置 HDR 可见性
setHDRBackgroundVisibility(visible: boolean): void
// 设置 HDR 强度
setHDRIntensity(intensity: number): void // 0-100
```
#### 地面
```typescript
// 获取地面列表
getGroundList(): { name: string; id: string }[]
// 设置地面 ID
setGroundId(id: string): void
// 获取当前地面 ID
getGroundId(): string
// 设置地面高度
setGroundElevation(elevation: number): void // 米
// 获取地面高度
getGroundElevation(): number
// 设置地面可见性
setGroundVisible(visible: boolean): void
```
#### 天空
```typescript
// 获取天空预设列表
getSkyPresetList(): { name: string; id: string }[]
// 设置天空预设
setSkyPreset(presetId: string): void
// 设置天空强度
setSkyIntensity(intensity: number): void // 0-100
// 设置天空参数
setSkyParams(params: Partial<SkyParams>): void
```
### 4.3 BimEngine 快捷访问
```typescript
const bimEngine = new BimEngine(container, options);
// 初始化设置管理器
bimEngine.initSetting();
// 访问设置管理器
bimEngine.setting?.show();
bimEngine.setting?.hide();
bimEngine.setting?.toggle();
// 通过引擎组件访问设置 API
bimEngine.engine?.getSettings();
bimEngine.engine?.setSettings({ render: { mode: 'advanced' } });
```
---
## 5. 第三方预设接入
### 5.1 注入预设
第三方可通过 `setPresetList` 方法注入自定义预设:
```typescript
import { BimEngine } from 'iflow-engine';
// 创建引擎
const bimEngine = new BimEngine(container, {
locale: 'zh-CN',
theme: 'dark'
});
// 初始化必要组件
bimEngine.initToolbar();
bimEngine.initButtonGroup();
bimEngine.initDialog();
bimEngine.initEngine();
bimEngine.initSetting(); // 初始化设置管理器
// 注入第三方预设
const externalPresets = [
{
id: 'vendor-indoor',
presetName: '室内展厅',
isDefault: false,
source: 'external', // 标记为外部来源
settings: {
render: {
mode: 'advanced',
contrast: 55,
saturation: 60,
shadowIntensity: 70,
lightIntensity: 80,
gtaoIntensity: 60,
},
display: {
showEdge: true,
edgeOpacity: 40,
showGrid: false,
showLevel: true,
showGround: true,
groundId: 'marble-01',
groundHeight: 0,
},
environment: {
type: 'hdr',
hdrId: 'interior-01',
hdrIntensity: 30,
skyPreset: 'sunrise_clear',
skyParams: {},
skyIntensity: 20,
},
},
},
{
id: 'vendor-outdoor',
presetName: '室外建筑',
isDefault: true, // 设为默认预设
source: 'external',
settings: {
render: {
mode: 'balance',
contrast: 50,
saturation: 50,
shadowIntensity: 50,
lightIntensity: 50,
gtaoIntensity: 50,
},
display: {
showEdge: false,
edgeOpacity: 30,
showGrid: true,
showLevel: false,
showGround: true,
groundId: 'grass-01',
groundHeight: 0,
},
environment: {
type: 'sky',
hdrId: '0',
hdrIntensity: 20,
skyPreset: 'sunny_clear',
skyParams: {
turbidity: 3,
cloudCoverage: 0.2,
},
skyIntensity: 25,
},
},
},
];
bimEngine.setting?.setPresetList(externalPresets);
```
### 5.2 预设合并规则
调用 `setPresetList` 时的处理逻辑:
1. **保留内置预设**`__internal-default-preset__` 始终保留
2. **去重**:相同 `id` 的预设会被新传入的替换
3. **来源标记**:建议第三方预设标记 `source: 'external'`
4. **默认预设**
- 若传入的预设中有 `isDefault: true`,则选中该预设
- 若有多个 `isDefault: true`,取第一个
- 若没有指定默认,选中内置默认预设
### 5.3 动态更新预设
```typescript
// 随时可以更新预设列表
bimEngine.setting?.setPresetList([
{
id: 'dynamic-preset',
presetName: '动态预设',
isDefault: false,
source: 'external',
settings: { /* ... */ },
},
]);
// 获取当前预设列表
const presets = bimEngine.setting?.getPresetList();
```
### 5.4 完整示例
```typescript
import { BimEngine } from 'iflow-engine';
import type { EngineSettingPreset } from 'iflow-engine';
class VendorPresetManager {
private engine: BimEngine;
constructor(engine: BimEngine) {
this.engine = engine;
}
// 注册供应商预设
registerVendorPresets() {
const presets: EngineSettingPreset[] = [
this.createReviewPreset(),
this.createPresentationPreset(),
this.createPerformancePreset(),
];
this.engine.setting?.setPresetList(presets);
}
// 评审模式 - 高对比度,显示边线
private createReviewPreset(): EngineSettingPreset {
return {
id: 'vendor-review',
presetName: '评审模式',
isDefault: false,
source: 'external',
settings: {
render: {
mode: 'advanced',
contrast: 70,
saturation: 55,
shadowIntensity: 65,
lightIntensity: 55,
gtaoIntensity: 50,
},
display: {
showEdge: true,
edgeOpacity: 50,
showGrid: true,
showLevel: true,
showGround: true,
groundId: 'grid-01',
groundHeight: 0,
},
environment: {
type: 'hdr',
hdrId: 'studio-01',
hdrIntensity: 35,
skyPreset: 'sunrise_clear',
skyParams: {},
skyIntensity: 20,
},
},
};
}
// 展示模式 - 高饱和度HDR环境
private createPresentationPreset(): EngineSettingPreset {
return {
id: 'vendor-presentation',
presetName: '展示模式',
isDefault: true, // 设为默认
source: 'external',
settings: {
render: {
mode: 'advanced',
contrast: 55,
saturation: 75,
shadowIntensity: 80,
lightIntensity: 70,
gtaoIntensity: 60,
},
display: {
showEdge: false,
edgeOpacity: 30,
showGrid: false,
showLevel: false,
showGround: true,
groundId: 'pavement-01',
groundHeight: -0.5,
},
environment: {
type: 'hdr',
hdrId: 'outdoor-afternoon',
hdrIntensity: 45,
skyPreset: 'sunset_glow',
skyParams: {},
skyIntensity: 25,
},
},
};
}
// 性能模式 - 低画质,高帧率
private createPerformancePreset(): EngineSettingPreset {
return {
id: 'vendor-performance',
presetName: '性能模式',
isDefault: false,
source: 'external',
settings: {
render: {
mode: 'simple',
contrast: 50,
saturation: 50,
shadowIntensity: 20,
lightIntensity: 50,
gtaoIntensity: 0,
},
display: {
showEdge: false,
edgeOpacity: 30,
showGrid: false,
showLevel: false,
showGround: false,
groundId: '0',
groundHeight: 0,
},
environment: {
type: 'none',
hdrId: '0',
hdrIntensity: 20,
skyPreset: 'sunrise_clear',
skyParams: {},
skyIntensity: 20,
},
},
};
}
}
// 使用
const bimEngine = new BimEngine(container);
bimEngine.initToolbar();
bimEngine.initButtonGroup();
bimEngine.initDialog();
bimEngine.initEngine();
bimEngine.initSetting();
const presetManager = new VendorPresetManager(bimEngine);
presetManager.registerVendorPresets();
// 监听预设变更
bimEngine.on('setting:preset-changed', ({ preset }) => {
console.log(`已切换到: ${preset.presetName}`);
// 可以在这里做自定义逻辑
if (preset.source === 'external') {
console.log('使用第三方预设');
}
});
```
---
## 6. 事件系统
### 6.1 设置相关事件
文件: `src/types/events.ts`
```typescript
// 预设保存事件
'setting:preset-saved': {
preset: EngineSettingPreset; // 被保存的预设
currentSettings: EngineSettings; // 当前完整设置
timestamp: number;
}
// 预设切换事件
'setting:preset-changed': {
preset: EngineSettingPreset; // 切换后的目标预设
timestamp: number;
}
// 预设删除事件
'setting:preset-deleted': EngineSettingPreset; // 被删除的预设
```
### 6.2 事件监听示例
```typescript
const bimEngine = new BimEngine(container);
// 监听预设保存
const offSaved = bimEngine.on('setting:preset-saved', ({ preset, currentSettings, timestamp }) => {
console.log('用户保存预设:', preset.presetName);
console.log('预设来源:', preset.source);
console.log('保存时间:', new Date(timestamp));
// 可以持久化到本地存储或后端
localStorage.setItem(`preset_${preset.id}`, JSON.stringify(preset));
});
// 监听预设切换
const offChanged = bimEngine.on('setting:preset-changed', ({ preset, timestamp }) => {
console.log('预设已切换:', preset.presetName);
// 根据来源做不同处理
switch (preset.source) {
case 'sdk-default':
console.log('使用 SDK 默认预设');
break;
case 'external':
console.log('使用第三方预设');
break;
case 'user':
console.log('使用用户自定义预设');
break;
}
});
// 监听预设删除
const offDeleted = bimEngine.on('setting:preset-deleted', (preset) => {
console.log('预设已删除:', preset.presetName);
// 清理本地存储
localStorage.removeItem(`preset_${preset.id}`);
});
// 取消监听
// offSaved();
// offChanged();
// offDeleted();
```
### 6.3 与第三方系统集成
```typescript
// 示例:将用户保存的预设同步到后端
class PresetSyncService {
constructor(private engine: BimEngine) {
this.setupListeners();
}
private setupListeners() {
// 保存时同步到后端
this.engine.on('setting:preset-saved', async ({ preset }) => {
if (preset.source === 'user') {
await this.saveToServer(preset);
}
});
// 切换时上报埋点
this.engine.on('setting:preset-changed', ({ preset }) => {
this.trackPresetUsage(preset);
});
}
private async saveToServer(preset: EngineSettingPreset) {
try {
await fetch('/api/presets', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(preset),
});
} catch (error) {
console.error('同步预设失败:', error);
}
}
private trackPresetUsage(preset: EngineSettingPreset) {
// 埋点上报
analytics.track('Preset Changed', {
presetId: preset.id,
presetName: preset.presetName,
source: preset.source,
});
}
}
```
---
## 7. 默认值参考
```typescript
const DEFAULT_SETTINGS: EngineSettings = {
render: {
mode: 'advanced',
contrast: 50,
saturation: 50,
shadowIntensity: 50,
lightIntensity: 50,
gtaoIntensity: 50,
},
display: {
showEdge: false,
edgeOpacity: 30,
showGrid: false,
showLevel: false,
showGround: false,
groundId: '0',
groundHeight: 0,
},
environment: {
type: 'none',
hdrId: '0',
hdrIntensity: 20,
skyPreset: 'sunrise_clear',
skyParams: {},
skyIntensity: 20,
},
};
```
---
## 8. 常见问题
### Q1: 如何获取当前生效的设置?
```typescript
const currentSettings = bimEngine.engine?.getSettings();
console.log(currentSettings.render.mode);
```
### Q2: 如何只修改部分设置?
```typescript
// 只修改渲染模式,其他保持不变
await bimEngine.engine?.setSettings({
render: { mode: 'simple' }
});
```
### Q3: 第三方预设会被用户删除吗?
不会。`readonly: true` 的预设不会显示删除按钮。建议第三方预设设置 `readonly: true`
```typescript
{
id: 'vendor-preset',
presetName: '供应商预设',
source: 'external',
readonly: true, // 用户不可删除
settings: { ... }
}
```
### Q4: 如何清空所有第三方预设?
```typescript
// 获取当前列表
const currentList = bimEngine.setting?.getPresetList() || [];
// 过滤掉外部预设
const filteredList = currentList.filter(p => p.source !== 'external');
// 重新设置
bimEngine.setting?.setPresetList(filteredList);
```
### Q5: 设置修改后立即生效吗?
`setSettings` 返回 Promise设置应用完成后 resolve
```typescript
await bimEngine.engine?.setSettings({
environment: { type: 'hdr', hdrId: 'hdr-01' }
});
// 到这里设置已生效
```
---
**文档版本**: 1.0.0
**更新时间**: 2026-03-30
**适用 SDK 版本**: iflow-engine >= 2.2.0