现版本
This commit is contained in:
19
basis/basis_transcoder.js
Normal file
19
basis/basis_transcoder.js
Normal file
File diff suppressed because one or more lines are too long
BIN
basis/basis_transcoder.wasm
Normal file
BIN
basis/basis_transcoder.wasm
Normal file
Binary file not shown.
@@ -57,6 +57,14 @@
|
||||
<button class="primary" @click="loadModel">加载模型</button>
|
||||
<button @click="switchModel">切换模型</button>
|
||||
</div>
|
||||
<div style="margin-top: 8px;">
|
||||
<input
|
||||
v-model="modelUrlInput"
|
||||
type="text"
|
||||
style="width:100%;padding:6px 8px;font-size:0.85rem;border:1px solid #ddd;border-radius:4px;font-family:Consolas,Monaco,monospace;outline:none;"
|
||||
placeholder="输入模型 URL(支持粘贴后切换)"
|
||||
/>
|
||||
</div>
|
||||
<div class="btn-container" style="margin-top: 8px;">
|
||||
<button @click="pauseRendering">暂停渲染</button>
|
||||
<button @click="resumeRendering">恢复渲染</button>
|
||||
@@ -86,6 +94,8 @@ const isLocationVisible = ref(true);
|
||||
const customGroupAdded = ref(false);
|
||||
const engineStatus = ref('未初始化');
|
||||
const engineStatusColor = ref('#666');
|
||||
const defaultModelUrl = 'https://lyz-1259524260.cos.ap-guangzhou.myqcloud.com/iflow/models/8634e556-a94e-4ba7-be3e-2ea1507cced5/';
|
||||
const modelUrlInput = ref(defaultModelUrl);
|
||||
|
||||
// 初始化引擎
|
||||
onMounted(() => {
|
||||
@@ -328,8 +338,11 @@ const loadModel = () => {
|
||||
}
|
||||
|
||||
try {
|
||||
// 加载模型文件(从 model 目录)
|
||||
const modelUrl = 'https://lyz-1259524260.cos.ap-guangzhou.myqcloud.com/iflow/models/8634e556-a94e-4ba7-be3e-2ea1507cced5/';
|
||||
const modelUrl = modelUrlInput.value.trim();
|
||||
if (!modelUrl) {
|
||||
alert('请输入模型 URL');
|
||||
return;
|
||||
}
|
||||
|
||||
engine.value.engine.loadModel([modelUrl], {
|
||||
position: [0, 0, 0], // 初始位置
|
||||
@@ -354,9 +367,9 @@ const switchModel = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
const newUrl = prompt('请输入新的模型 URL:', 'https://lyz-1259524260.cos.ap-guangzhou.myqcloud.com/iflow/models/8634e556-a94e-4ba7-be3e-2ea1507cced5/');
|
||||
|
||||
if (!newUrl || newUrl.trim() === '') {
|
||||
const newUrl = modelUrlInput.value.trim();
|
||||
if (!newUrl) {
|
||||
alert('请输入模型 URL');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -220,6 +220,11 @@
|
||||
<button onclick="loadCombinedModel()">组合模型</button>
|
||||
<button onclick="openCombineDialog()">自动组合</button>
|
||||
</div>
|
||||
<div style="margin-top: 8px;">
|
||||
<input type="text" id="url-input-3d"
|
||||
style="width:100%;padding:6px 8px;font-size:0.85rem;border:1px solid #ddd;border-radius:4px;font-family:Consolas,Monaco,monospace;outline:none;"
|
||||
placeholder="输入模型 URL(支持粘贴后切换)" />
|
||||
</div>
|
||||
<div class="btn-container" style="margin-top: 8px;">
|
||||
<button onclick="pauseRendering()">暂停渲染</button>
|
||||
<button onclick="resumeRendering()">恢复渲染</button>
|
||||
@@ -290,7 +295,8 @@
|
||||
<div
|
||||
style="background:#fff; border-radius:10px; padding:24px; width:560px; max-width:90vw; box-shadow:0 8px 32px rgba(0,0,0,.18);">
|
||||
<h3 style="margin:0 0 12px; font-size:1.1rem; color:#333;">跳转到构件视角</h3>
|
||||
<p style="margin:0 0 10px; font-size:.85rem; color:#888;">请输入相机配置 JSON(参考格式:modelJson.cameraRestorePose):</p>
|
||||
<p style="margin:0 0 10px; font-size:.85rem; color:#888;">请输入相机配置 JSON(参考格式:modelJson.cameraRestorePose):
|
||||
</p>
|
||||
<textarea id="jump-camera-json" rows="12"
|
||||
style="width:100%; padding:10px; font-size:.85rem; border:1px solid #ddd; border-radius:6px; resize:vertical; font-family:monospace;"
|
||||
placeholder='{
|
||||
@@ -302,7 +308,8 @@
|
||||
<div style="margin-top:10px; font-size:.8rem; color:#666;">
|
||||
<details>
|
||||
<summary style="cursor:pointer; color:#0078d4;">查看完整示例格式</summary>
|
||||
<pre style="margin-top:8px; padding:10px; background:#f5f5f5; border-radius:4px; overflow-x:auto; font-size:.75rem;">{
|
||||
<pre
|
||||
style="margin-top:8px; padding:10px; background:#f5f5f5; border-radius:4px; overflow-x:auto; font-size:.75rem;">{
|
||||
"type": "orthographic",
|
||||
"position": {"x": 229.68, "y": 247.98, "z": 233.79},
|
||||
"rotation": {"x": -0.79, "y": 0.62, "z": 0.52},
|
||||
@@ -332,6 +339,9 @@
|
||||
let unsubscribePresetSaved = null;
|
||||
let unsubscribePresetChanged = null;
|
||||
let unsubscribePresetDeleted = null;
|
||||
const DEFAULT_3D_MODEL_URL = 'https://lyz-1259524260.cos.ap-guangzhou.myqcloud.com/iflow/models/417664a3-76c8-4d94-9344-1337246a5d4e/';
|
||||
//const DEFAULT_3D_MODEL_URL = 'https://pub-8092fd0db2e14822a9f742ad0050750c.r2.dev/66ad9a66-5ca8-47ac-9139-6aa8756069c1/';
|
||||
let current3dModelUrl = DEFAULT_3D_MODEL_URL;
|
||||
|
||||
const PRESET_CACHE_KEY = 'iflow-demo-setting-presets-v1';
|
||||
|
||||
@@ -450,6 +460,10 @@
|
||||
window.onload = () => {
|
||||
if (window.IflowEngine) {
|
||||
try {
|
||||
const modelInput = document.getElementById('url-input-3d');
|
||||
if (modelInput) {
|
||||
modelInput.value = current3dModelUrl;
|
||||
}
|
||||
initEngine3D();
|
||||
} catch (err) {
|
||||
console.error('Init failed:', err);
|
||||
@@ -624,8 +638,15 @@
|
||||
alert('请先初始化 3D 引擎!');
|
||||
return;
|
||||
}
|
||||
|
||||
const urlInput = document.getElementById('url-input-3d');
|
||||
const inputValue = urlInput && urlInput.value ? urlInput.value.trim() : '';
|
||||
if (inputValue) {
|
||||
current3dModelUrl = inputValue;
|
||||
}
|
||||
|
||||
const modelUrl = current3dModelUrl;
|
||||
try {
|
||||
var modelUrl = 'https://lyz-1259524260.cos.ap-guangzhou.myqcloud.com/iflow/models/417664a3-76c8-4d94-9344-1337246a5d4e/';
|
||||
engine.engine.loadModel([modelUrl], {
|
||||
position: [0, 0, 0],
|
||||
rotation: [0, 0, 0],
|
||||
@@ -682,15 +703,22 @@
|
||||
alert('请先初始化 3D 引擎!');
|
||||
return;
|
||||
}
|
||||
var newUrl = prompt('请输入新的模型 URL:', 'https://lyz-1259524260.cos.ap-guangzhou.myqcloud.com/iflow/models/8634e556-a94e-4ba7-be3e-2ea1507cced5/');
|
||||
if (!newUrl || newUrl.trim() === '') return;
|
||||
|
||||
var urlInput = document.getElementById('url-input-3d');
|
||||
var newUrl = urlInput && urlInput.value ? urlInput.value.trim() : '';
|
||||
if (!newUrl) {
|
||||
alert('请输入模型 URL');
|
||||
return;
|
||||
}
|
||||
|
||||
current3dModelUrl = newUrl;
|
||||
try {
|
||||
engine.engine.loadModel([newUrl.trim()], {
|
||||
engine.engine.loadModel([current3dModelUrl], {
|
||||
position: [0, 0, 0],
|
||||
rotation: [0, 0, 0],
|
||||
scale: [1, 1, 1]
|
||||
});
|
||||
console.log('✅ 切换模型请求已发送:', newUrl);
|
||||
console.log('✅ 切换模型请求已发送:', current3dModelUrl);
|
||||
} catch (error) {
|
||||
console.error('❌ 切换模型错误:', error);
|
||||
}
|
||||
@@ -1100,4 +1128,4 @@
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
174
docs/外部API总览.md
Normal file
174
docs/外部API总览.md
Normal file
@@ -0,0 +1,174 @@
|
||||
# iflow-engine 外部 API(第三方接入)
|
||||
|
||||
## 1) 获取构件树 `getConstructTreeData()`
|
||||
|
||||
### 所属模块
|
||||
|
||||
- 调用入口:`bimEngine.engine`
|
||||
- 源码位置:`src/managers/engine-manager.ts`
|
||||
|
||||
### 方法签名
|
||||
|
||||
```ts
|
||||
getConstructTreeData(): {
|
||||
level: EngineModelData[];
|
||||
type: EngineModelData[];
|
||||
major: EngineModelData[];
|
||||
}
|
||||
```
|
||||
|
||||
### 入参
|
||||
|
||||
- 无入参。
|
||||
|
||||
### 返回值
|
||||
|
||||
- 返回一个对象,包含三类构件树:
|
||||
- `level`: 楼层树
|
||||
- `type`: 类型树
|
||||
- `major`: 专业树
|
||||
|
||||
```ts
|
||||
type EngineTreeNode = {
|
||||
name?: string;
|
||||
id?: string | null;
|
||||
ids?: string[] | null;
|
||||
children?: EngineTreeNode[] | null;
|
||||
isLeaf?: boolean;
|
||||
};
|
||||
|
||||
type EngineModelData = {
|
||||
name?: string;
|
||||
url: string;
|
||||
children?: EngineTreeNode[] | null;
|
||||
};
|
||||
```
|
||||
|
||||
### 行为约定
|
||||
|
||||
- 当 3D 引擎未初始化(`engine.initialize(...)` 未成功)时,返回:
|
||||
|
||||
```ts
|
||||
{ level: [], type: [], major: [] }
|
||||
```
|
||||
|
||||
### 调用示例
|
||||
|
||||
```ts
|
||||
const treeData = bimEngine.engine?.getConstructTreeData();
|
||||
|
||||
if (treeData) {
|
||||
console.log('level tree:', treeData.level);
|
||||
console.log('type tree:', treeData.type);
|
||||
console.log('major tree:', treeData.major);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2) 获取构件信息 `getComponentProperties(url, id, callback)`
|
||||
|
||||
### 所属模块
|
||||
|
||||
- 调用入口:`bimEngine.engine`
|
||||
- 源码位置:`src/managers/engine-manager.ts`
|
||||
|
||||
### 方法签名
|
||||
|
||||
```ts
|
||||
getComponentProperties(url: string, id: string, callback: (data: any) => void): void
|
||||
```
|
||||
|
||||
### 入参
|
||||
|
||||
- `url: string`:构件所属模型 URL
|
||||
- `id: string`:构件 ID
|
||||
- `callback: (data: any) => void`:异步回调,返回构件属性
|
||||
|
||||
### 调用示例
|
||||
|
||||
```ts
|
||||
bimEngine.engine?.getComponentProperties(modelUrl, componentId, (data) => {
|
||||
console.log('component properties:', data);
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3) 高亮指定构件 `highlightModel(models)`
|
||||
|
||||
### 所属模块
|
||||
|
||||
- 调用入口:`bimEngine.engine?.getEngineComponent()`
|
||||
- 源码位置:`src/components/engine/index.ts`
|
||||
|
||||
### 方法签名
|
||||
|
||||
```ts
|
||||
highlightModel(models: { url: string; ids: number[] }[]): void
|
||||
```
|
||||
|
||||
### 入参
|
||||
|
||||
- `models`:构件列表(可批量)
|
||||
- `url: string`:模型 URL
|
||||
- `ids: number[]`:要高亮的构件 ID 数组
|
||||
|
||||
### 调用示例
|
||||
|
||||
```ts
|
||||
bimEngine.engine?.getEngineComponent()?.highlightModel([
|
||||
{ url: modelUrl, ids: [350518] }
|
||||
]);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4) 剖切指定构件(推荐流程)
|
||||
|
||||
当前引擎提供的是“剖切盒适配已高亮构件”的能力,推荐按两步调用:
|
||||
|
||||
1. 先高亮目标构件:`highlightModel(...)`
|
||||
2. 再执行剖切盒适配:`fitSectionBoxToModel()`
|
||||
|
||||
### 方法签名
|
||||
|
||||
```ts
|
||||
fitSectionBoxToModel(): void
|
||||
```
|
||||
|
||||
### 调用示例
|
||||
|
||||
```ts
|
||||
const engineComp = bimEngine.engine?.getEngineComponent();
|
||||
|
||||
engineComp?.highlightModel([{ url: modelUrl, ids: [350518] }]);
|
||||
engineComp?.fitSectionBoxToModel();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5) 隐藏其他构件 `isolateModels(models)`
|
||||
|
||||
### 所属模块
|
||||
|
||||
- 调用入口:`bimEngine.engine?.getEngineComponent()`
|
||||
- 源码位置:`src/components/engine/index.ts`
|
||||
|
||||
### 方法签名
|
||||
|
||||
```ts
|
||||
isolateModels(models: { url: string; ids: number[] }[]): void
|
||||
```
|
||||
|
||||
### 入参
|
||||
|
||||
- `models`:要保留显示的构件(其他构件将隐藏)
|
||||
|
||||
### 调用示例
|
||||
|
||||
```ts
|
||||
bimEngine.engine?.getEngineComponent()?.isolateModels([
|
||||
{ url: modelUrl, ids: [350518] }
|
||||
]);
|
||||
```
|
||||
@@ -26,6 +26,7 @@
|
||||
| [贡献指南.md](贡献指南.md) | 开发协作、脚本说明、最小验证集 | 项目贡献者 |
|
||||
| [运维手册.md](运维手册.md) | 构建/发布/回滚流程与常见问题 | 维护者 |
|
||||
| [API调用链.md](API调用链.md) | API 调用链(用户交互 → Manager → Engine → 底层引擎) | SDK 维护者 |
|
||||
| [外部API总览.md](外部API总览.md) | 外部可调用 API 全量清单(按模块) | SDK 集成开发 |
|
||||
| [MODULES/设置系统.md](MODULES/设置系统.md) | 设置系统架构、API、第三方预设接入 | 所有开发者 |
|
||||
## 模块概览
|
||||
|
||||
|
||||
19
package-lock.json
generated
19
package-lock.json
generated
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"name": "iflow-engine",
|
||||
"version": "2.4.8",
|
||||
"version": "2.5.9",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "iflow-engine",
|
||||
"version": "2.4.8",
|
||||
"version": "2.5.9",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"iflow-engine-base": "^3.4.7",
|
||||
"iflow-engine-base": "^3.4.10",
|
||||
"three": "^0.182.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -1456,12 +1456,6 @@
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/draco3d": {
|
||||
"version": "1.5.7",
|
||||
"resolved": "https://registry.npmjs.org/draco3d/-/draco3d-1.5.7.tgz",
|
||||
"integrity": "sha512-m6WCKt/erDXcw+70IJXnG7M3awwQPAsZvJGX5zY7beBqpELw6RDGkYVU0W43AFxye4pDZ5i2Lbyc/NNGqwjUVQ==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/dunder-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
@@ -1829,14 +1823,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/iflow-engine-base": {
|
||||
"version": "3.4.7",
|
||||
"resolved": "https://registry.npmjs.org/iflow-engine-base/-/iflow-engine-base-3.4.7.tgz",
|
||||
"integrity": "sha512-SHVtyRpyPz1U9u73nULZUV6AQSCMOBovyPb6ROOToog1I/FowTuWNVM3zMLMNN88sJ/0XTWBHZbZEifwtMCIkg==",
|
||||
"version": "3.4.10",
|
||||
"resolved": "https://registry.npmjs.org/iflow-engine-base/-/iflow-engine-base-3.4.10.tgz",
|
||||
"integrity": "sha512-sKgV1qWr8z3Cbli3yoGRolAKz0Za5Iuycu/OAbpA2/oE9LJ+Zb0CH63LrSR7ljRK6NBRw4P0fHrs6/KCWppG7w==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@types/three": "^0.181.0",
|
||||
"axios": "^1.13.2",
|
||||
"draco3d": "^1.5.7",
|
||||
"jszip": "^3.10.1",
|
||||
"opentype.js": "^1.3.4",
|
||||
"stats.js": "^0.17.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "iflow-engine",
|
||||
"version": "2.5.2",
|
||||
"version": "2.5.10",
|
||||
"description": "iFlow Engine SDK for Vue2, Vue3, React and HTML",
|
||||
"main": "./dist/iflow-engine.umd.js",
|
||||
"module": "./dist/iflow-engine.es.js",
|
||||
@@ -59,7 +59,7 @@
|
||||
"vite-plugin-dts": "^4.5.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"iflow-engine-base": "^3.4.7",
|
||||
"iflow-engine-base": "^3.4.10",
|
||||
"three": "^0.182.0"
|
||||
}
|
||||
}
|
||||
@@ -97,6 +97,7 @@ export class RadialToolbar implements IBimComponent {
|
||||
this.mainButton.addEventListener('mouseenter', this.handlePointerEnter);
|
||||
this.mainButton.addEventListener('mouseleave', this.handlePointerLeave);
|
||||
this.mainButton.addEventListener('click', this.handleMainButtonClick);
|
||||
this.mainButton.addEventListener('dblclick', this.handleMainButtonDoubleClick);
|
||||
document.addEventListener('click', this.handleDocumentClick);
|
||||
document.addEventListener('mousemove', this.handleDocumentMouseMove);
|
||||
document.addEventListener('mouseleave', this.handleDocumentMouseLeave);
|
||||
@@ -148,15 +149,14 @@ export class RadialToolbar implements IBimComponent {
|
||||
|
||||
private readonly handleMainButtonClick = (event: MouseEvent): void => {
|
||||
event.stopPropagation();
|
||||
};
|
||||
|
||||
private readonly handleMainButtonDoubleClick = (event: MouseEvent): void => {
|
||||
event.stopPropagation();
|
||||
if (this.onMainButtonClick) {
|
||||
this.onMainButtonClick();
|
||||
return;
|
||||
}
|
||||
if (this.isActive) {
|
||||
this.collapse();
|
||||
return;
|
||||
}
|
||||
this.expand();
|
||||
};
|
||||
|
||||
private readonly handleDocumentClick = (event: MouseEvent): void => {
|
||||
|
||||
@@ -66,6 +66,10 @@
|
||||
background: color-mix(in srgb, var(--bim-border-default, #cbd5e1) 84%, transparent 16%);
|
||||
}
|
||||
|
||||
.section-dock-divider.is-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.section-dock-type-btn,
|
||||
.section-dock-tool-btn {
|
||||
width: 32px;
|
||||
@@ -139,4 +143,4 @@
|
||||
.section-dock-panel [data-tooltip]:focus-visible::after {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ export type SectionDockType = 'face' | 'axis' | 'box';
|
||||
export type SectionDockAxis = 'x' | 'y' | 'z';
|
||||
|
||||
export interface SectionDockPanelOptions {
|
||||
defaultType?: SectionDockType;
|
||||
defaultType?: SectionDockType | null;
|
||||
defaultAxis?: SectionDockAxis;
|
||||
defaultHidden?: boolean;
|
||||
onTypeChange?: (type: SectionDockType, axis: SectionDockAxis) => void;
|
||||
@@ -35,21 +35,23 @@ export class SectionDockPanel implements IBimComponent {
|
||||
private readonly axisButtons: Map<SectionDockAxis, HTMLButtonElement> = new Map();
|
||||
private readonly toolContainer: HTMLElement;
|
||||
private readonly axisPanel: HTMLElement;
|
||||
private readonly divider: HTMLElement;
|
||||
|
||||
private activeType: SectionDockType;
|
||||
private activeType: SectionDockType | null;
|
||||
private activeAxis: SectionDockAxis;
|
||||
private isHidden: boolean;
|
||||
|
||||
constructor(options: SectionDockPanelOptions = {}) {
|
||||
this.options = options;
|
||||
this.activeType = options.defaultType ?? 'face';
|
||||
this.activeType = options.defaultType ?? null;
|
||||
this.activeAxis = options.defaultAxis ?? 'x';
|
||||
this.isHidden = options.defaultHidden ?? false;
|
||||
|
||||
const { root, toolContainer, axisPanel } = this.createDom();
|
||||
const { root, toolContainer, axisPanel, divider } = this.createDom();
|
||||
this.element = root;
|
||||
this.toolContainer = toolContainer;
|
||||
this.axisPanel = axisPanel;
|
||||
this.divider = divider;
|
||||
}
|
||||
|
||||
public init(): void {
|
||||
@@ -96,15 +98,13 @@ export class SectionDockPanel implements IBimComponent {
|
||||
}
|
||||
|
||||
public resetForOpen(): void {
|
||||
this.activeType = 'face';
|
||||
this.activeType = null;
|
||||
this.isHidden = false;
|
||||
this.applyTypeState();
|
||||
this.renderTools();
|
||||
this.options.onTypeChange?.(this.activeType, this.activeAxis);
|
||||
this.options.onHideToggle?.(false);
|
||||
}
|
||||
|
||||
public getActiveType(): SectionDockType {
|
||||
public getActiveType(): SectionDockType | null {
|
||||
return this.activeType;
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ export class SectionDockPanel implements IBimComponent {
|
||||
return this.activeAxis;
|
||||
}
|
||||
|
||||
private createDom(): { root: HTMLElement; toolContainer: HTMLElement; axisPanel: HTMLElement } {
|
||||
private createDom(): { root: HTMLElement; toolContainer: HTMLElement; axisPanel: HTMLElement; divider: HTMLElement } {
|
||||
const root = document.createElement('div');
|
||||
root.className = 'section-dock-panel';
|
||||
|
||||
@@ -158,7 +158,7 @@ export class SectionDockPanel implements IBimComponent {
|
||||
root.appendChild(axisPanel);
|
||||
root.appendChild(main);
|
||||
|
||||
return { root, toolContainer, axisPanel };
|
||||
return { root, toolContainer, axisPanel, divider };
|
||||
}
|
||||
|
||||
private createTypeButton(type: SectionDockType, iconSvg: string): HTMLButtonElement {
|
||||
@@ -227,6 +227,13 @@ export class SectionDockPanel implements IBimComponent {
|
||||
private renderTools(): void {
|
||||
this.toolContainer.innerHTML = '';
|
||||
|
||||
if (!this.activeType) {
|
||||
this.divider.classList.add('is-hidden');
|
||||
return;
|
||||
}
|
||||
|
||||
this.divider.classList.remove('is-hidden');
|
||||
|
||||
this.getToolsForType(this.activeType).forEach((tool) => {
|
||||
const button = document.createElement('button');
|
||||
button.type = 'button';
|
||||
@@ -281,7 +288,7 @@ export class SectionDockPanel implements IBimComponent {
|
||||
textKey: 'sectionAxis.actions.reset',
|
||||
onClick: () => {
|
||||
this.isHidden = false;
|
||||
this.options.onReset?.(this.activeType, this.activeAxis);
|
||||
this.options.onReset?.(type, this.activeAxis);
|
||||
this.renderTools();
|
||||
}
|
||||
}
|
||||
@@ -305,7 +312,7 @@ export class SectionDockPanel implements IBimComponent {
|
||||
textKey: 'sectionBox.actions.reset',
|
||||
onClick: () => {
|
||||
this.isHidden = false;
|
||||
this.options.onReset?.(this.activeType, this.activeAxis);
|
||||
this.options.onReset?.(type, this.activeAxis);
|
||||
this.renderTools();
|
||||
}
|
||||
}
|
||||
@@ -321,7 +328,7 @@ export class SectionDockPanel implements IBimComponent {
|
||||
textKey: 'sectionPlane.actions.reset',
|
||||
onClick: () => {
|
||||
this.isHidden = false;
|
||||
this.options.onReset?.(this.activeType, this.activeAxis);
|
||||
this.options.onReset?.(type, this.activeAxis);
|
||||
this.renderTools();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,6 +302,66 @@ export class EngineManager extends BaseManager {
|
||||
return this.engineInstance.jumpToCamera(cameraData);
|
||||
}
|
||||
|
||||
public getConstructTreeData(): { level: any[]; type: any[]; major: any[] } {
|
||||
if (!this.engineInstance) {
|
||||
console.warn('[EngineManager] 3D Engine not initialized.');
|
||||
return { level: [], type: [], major: [] };
|
||||
}
|
||||
return {
|
||||
level: this.engineInstance.getLevelTreeData(),
|
||||
type: this.engineInstance.getTypeTreeData(),
|
||||
major: this.engineInstance.getMajorTreeData(),
|
||||
};
|
||||
}
|
||||
|
||||
public getComponentProperties(url: string, id: string, callback: (data: any) => void): void {
|
||||
if (!this.engineInstance) {
|
||||
console.warn('[EngineManager] 3D Engine not initialized.');
|
||||
return;
|
||||
}
|
||||
this.engineInstance.getComponentProperties(url, id, callback);
|
||||
}
|
||||
|
||||
public registerRightKeyHandler(handler: (e: MouseEvent) => MenuItemConfig[] | null): void {
|
||||
if (!this.rightKey) {
|
||||
console.warn('[EngineManager] RightKey manager not initialized.');
|
||||
return;
|
||||
}
|
||||
this.rightKey.registerHandler(handler);
|
||||
}
|
||||
|
||||
public unregisterRightKeyHandler(handler: (e: MouseEvent) => MenuItemConfig[] | null): void {
|
||||
if (!this.rightKey) {
|
||||
console.warn('[EngineManager] RightKey manager not initialized.');
|
||||
return;
|
||||
}
|
||||
this.rightKey.unregisterHandler(handler);
|
||||
}
|
||||
|
||||
public clearRightKeyHandlers(keepDefault: boolean = true): void {
|
||||
if (!this.rightKey) {
|
||||
console.warn('[EngineManager] RightKey manager not initialized.');
|
||||
return;
|
||||
}
|
||||
this.rightKey.clearHandlers(keepDefault);
|
||||
}
|
||||
|
||||
public showRightKeyMenu(x: number, y: number, items: MenuItemConfig[], groupOrder?: string[]): void {
|
||||
if (!this.rightKey) {
|
||||
console.warn('[EngineManager] RightKey manager not initialized.');
|
||||
return;
|
||||
}
|
||||
this.rightKey.showMenu(x, y, items, groupOrder);
|
||||
}
|
||||
|
||||
public hideRightKeyMenu(): void {
|
||||
if (!this.rightKey) {
|
||||
console.warn('[EngineManager] RightKey manager not initialized.');
|
||||
return;
|
||||
}
|
||||
this.rightKey.hide();
|
||||
}
|
||||
|
||||
/** 销毁引擎管理器 */
|
||||
public destroy(): void {
|
||||
if (this.engineInstance) {
|
||||
|
||||
@@ -46,6 +46,23 @@ export class RightKeyManager extends BaseManager {
|
||||
this.contextHandlers.push(handler);
|
||||
}
|
||||
|
||||
public unregisterHandler(handler: (e: MouseEvent) => MenuItemConfig[] | null): void {
|
||||
this.contextHandlers = this.contextHandlers.filter((item) => item !== handler);
|
||||
}
|
||||
|
||||
public clearHandlers(keepDefault: boolean = true): void {
|
||||
if (!keepDefault) {
|
||||
this.contextHandlers = [];
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.contextHandlers.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.contextHandlers = [this.contextHandlers[0]];
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示菜单
|
||||
* @param x 横坐标
|
||||
|
||||
@@ -64,7 +64,7 @@ export class SectionDockManager extends BaseManager {
|
||||
public getPanelElement(): HTMLElement {
|
||||
if (!this.panel) {
|
||||
this.panel = new SectionDockPanel({
|
||||
defaultType: 'face',
|
||||
defaultType: null,
|
||||
defaultAxis: 'x',
|
||||
defaultHidden: false,
|
||||
onTypeChange: (type, axis) => {
|
||||
|
||||
Reference in New Issue
Block a user