1018 lines
27 KiB
Markdown
1018 lines
27 KiB
Markdown
# 设置系统模块文档
|
||
|
||
> 本文档基于 `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'; // 预设来源
|
||
allowModify?: boolean; // 是否允许修改(保存/删除),默认 true
|
||
}
|
||
```
|
||
|
||
**字段说明:**
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `id` | `string` | 预设唯一标识 |
|
||
| `presetName` | `string` | 预设显示名称 |
|
||
| `isDefault` | `boolean` | 是否为默认预设,打开面板时自动选中 |
|
||
| `settings` | `EngineSettings` | 预设包含的完整设置 |
|
||
| `readonly` | `boolean` | 是否只读,只读预设用户无法修改设置值(但仍可保存为新预设) |
|
||
| `source` | `'sdk-default' \| 'external' \| 'user'` | 预设来源 |
|
||
| `allowModify` | `boolean` | **是否允许修改当前预设**,`false` 时隐藏"保存"和"删除"按钮,默认 `true` |
|
||
|
||
**source 字段说明:**
|
||
- `'sdk-default'`: SDK 内置的默认预设(`allowModify: false`)
|
||
- `'external'`: 第三方注入的预设
|
||
- `'user'`: 用户自行保存的预设
|
||
|
||
**allowModify 字段说明:**
|
||
- `true`(默认): 显示所有操作按钮("保存预设"、"存为新预设"、"删除")
|
||
- `false`: 隐藏"保存当前预设"和"删除"按钮,但保留"另存为新预设"按钮
|
||
|
||
> **注意:** "另存为新预设"始终可用,因为创建新预设不是在修改当前预设。下拉框宽度始终保持固定。
|
||
|
||
### 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 禁止修改预设
|
||
|
||
使用 `allowModify: false` 可以禁止用户保存或删除某个预设:
|
||
|
||
```typescript
|
||
bimEngine.setting?.setPresetList([
|
||
{
|
||
id: 'vendor-locked',
|
||
presetName: '供应商锁定预设',
|
||
isDefault: false,
|
||
source: 'external',
|
||
allowModify: false, // ← 禁止修改
|
||
settings: {
|
||
render: { mode: 'advanced', contrast: 60, ... },
|
||
display: { showEdge: true, ... },
|
||
environment: { type: 'hdr', hdrId: 'hdr-01', ... }
|
||
}
|
||
}
|
||
]);
|
||
```
|
||
|
||
**效果:**
|
||
- ❌ 不显示"保存当前预设"按钮(无法覆盖原预设)
|
||
- ❌ 不显示删除按钮
|
||
- ✅ 保留"另存为新预设"按钮(可基于此预设创建新预设)
|
||
- ✅ 预设选择下拉框宽度固定不变
|
||
- ✅ 用户仍可修改设置值(如需禁止修改设置值,使用 `readonly: true`)
|
||
|
||
**适用场景:**
|
||
- 供应商提供的标准预设,不希望用户覆盖或删除,但允许基于此创建新预设
|
||
- 项目规定的固定展示模式
|
||
- 内置默认预设(SDK 默认 `allowModify: false`)
|
||
|
||
> **为什么保留"另存为新预设"?**
|
||
>
|
||
> "另存为新预设"是创建一个新的预设,不是在修改当前预设。即使用户不能修改供应商预设,也应该可以基于它创建自己的版本。>
|
||
> 如果你希望完全禁止用户基于此预设创建新预设,需要额外的前端逻辑控制。
|
||
|
||
### 5.4 动态更新预设
|
||
|
||
```typescript
|
||
// 随时可以更新预设列表
|
||
bimEngine.setting?.setPresetList([
|
||
{
|
||
id: 'dynamic-preset',
|
||
presetName: '动态预设',
|
||
isDefault: false,
|
||
source: 'external',
|
||
settings: { /* ... */ },
|
||
},
|
||
]);
|
||
|
||
// 获取当前预设列表
|
||
const presets = bimEngine.setting?.getPresetList();
|
||
```
|
||
|
||
### 5.5 完整示例
|
||
|
||
```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: 如何禁止用户修改(保存/删除)某个预设?
|
||
|
||
使用 `allowModify: false` 可以禁止用户覆盖或删除某个预设:
|
||
|
||
```typescript
|
||
{
|
||
id: 'vendor-locked-preset',
|
||
presetName: '供应商锁定预设',
|
||
source: 'external',
|
||
allowModify: false, // 禁止修改当前预设
|
||
settings: { ... }
|
||
}
|
||
```
|
||
|
||
**效果:**
|
||
- ❌ 隐藏"保存当前预设"按钮(无法覆盖原预设)
|
||
- ❌ 隐藏"删除"按钮
|
||
- ✅ 保留"另存为新预设"按钮(可基于此创建新预设)
|
||
- ✅ 下拉框宽度保持不变
|
||
|
||
**注意:**
|
||
- `allowModify: false` 时,用户仍可以切换到这个预设
|
||
- 用户仍可以修改设置值,只是无法保存到当前预设
|
||
- 如需完全禁止修改设置值,需配合 `readonly: true`
|
||
|
||
### Q4: `readonly` 和 `allowModify` 有什么区别?
|
||
|
||
| 字段 | 作用 | 对用户的影响 |
|
||
|------|------|-------------|
|
||
| `readonly` | 禁止修改设置值 | 禁用所有设置控件(滑块、开关等) |
|
||
| `allowModify` | 禁止覆盖/删除当前预设 | 隐藏"保存当前预设"和"删除"按钮,但保留"另存为新预设" |
|
||
|
||
内置默认预设(`__internal-default-preset__`)的 `allowModify: false`。
|
||
|
||
### Q5: 第三方预设会被用户删除吗?
|
||
|
||
如果设置了 `allowModify: false`,用户无法删除该预设。建议第三方预设设置 `allowModify: false`:
|
||
|
||
```typescript
|
||
{
|
||
id: 'vendor-preset',
|
||
presetName: '供应商预设',
|
||
source: 'external',
|
||
allowModify: false, // 用户不可删除/保存该预设
|
||
settings: { ... }
|
||
}
|
||
```
|
||
|
||
### Q6: 如何清空所有第三方预设?
|
||
|
||
```typescript
|
||
// 获取当前列表
|
||
const currentList = bimEngine.setting?.getPresetList() || [];
|
||
|
||
// 过滤掉外部预设
|
||
const filteredList = currentList.filter(p => p.source !== 'external');
|
||
|
||
// 重新设置
|
||
bimEngine.setting?.setPresetList(filteredList);
|
||
```
|
||
|
||
### Q7: 设置修改后立即生效吗?
|
||
|
||
`setSettings` 返回 Promise,设置应用完成后 resolve:
|
||
|
||
```typescript
|
||
await bimEngine.engine?.setSettings({
|
||
environment: { type: 'hdr', hdrId: 'hdr-01' }
|
||
});
|
||
// 到这里设置已生效
|
||
```
|
||
|
||
---
|
||
|
||
**文档版本**: 1.1.0
|
||
**更新时间**: 2026-03-30
|
||
**适用 SDK 版本**: iflow-engine >= 2.2.1
|