fl-web-component 2.0.0-beta.9 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/dist/fl-web-component.common.js +34766 -1686
- package/dist/fl-web-component.common.js.map +1 -1
- package/dist/fl-web-component.css +1 -1
- package/package.json +4 -15
- package/packages/components/com-card/index.vue +1 -1
- package/packages/components/com-flcanvas/components/bspline.js +31 -34
- package/packages/components/com-flcanvas/components/entityFormatting.js +810 -823
- package/packages/components/com-flcanvas/components/round10.js +17 -17
- package/packages/components/com-flcanvas/index.vue +314 -333
- package/packages/components/com-formDialog/index.vue +6 -4
- package/packages/components/com-graphics/component/ann-tool.vue +263 -208
- package/packages/components/com-graphics/index.vue +374 -773
- package/packages/components/com-graphics/pid.vue +304 -295
- package/packages/components/com-table/column-default.vue +2 -3
- package/packages/components/com-table/column-dynamic.vue +7 -4
- package/packages/components/com-table/column.vue +1 -2
- package/packages/components/com-table/index.vue +6 -5
- package/packages/components/com-tabs/index.vue +1 -2
- package/packages/components/com-tiles/index.vue +134 -136
- package/packages/components/com-treeDynamic/index.vue +1 -1
- package/packages/utils/StreamLoader.js +95 -36
- package/packages/utils/StreamLoaderParser.worker.js +9 -14
- package/src/main.js +2 -8
- package/src/utils/cloud.js +28 -28
- package/src/utils/cursor.js +11 -9
- package/src/utils/flgltf-parser.js +257 -245
- package/src/utils/instance-parser.js +20 -22
- package/src/utils/mini-devtool.js +94 -39
- package/src/utils/threejs/measure-angle.js +51 -13
- package/src/utils/threejs/measure-area.js +44 -13
- package/src/utils/threejs/measure-distance.js +43 -12
- package/src/utils/threejs/rain-shader.js +10 -10
- package/src/utils/threejs/snow-shader.js +9 -9
|
@@ -12,10 +12,13 @@
|
|
|
12
12
|
v-if="column.children && column.children.length > 0"
|
|
13
13
|
:key="column.label"
|
|
14
14
|
:columnOption="column"
|
|
15
|
-
>
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
></column-dynamic>
|
|
16
|
+
<column-slot
|
|
17
|
+
v-else
|
|
18
|
+
:column="column"
|
|
19
|
+
:column-option="columnOption.children"
|
|
20
|
+
:key="column.id"
|
|
21
|
+
></column-slot>
|
|
19
22
|
</template>
|
|
20
23
|
</component>
|
|
21
24
|
</template>
|
|
@@ -7,8 +7,7 @@
|
|
|
7
7
|
v-if="column.children && column.children.length > 0"
|
|
8
8
|
:columnOption="column"
|
|
9
9
|
:key="column.label"
|
|
10
|
-
>
|
|
11
|
-
</column-dynamic>
|
|
10
|
+
></column-dynamic>
|
|
12
11
|
<column-slot v-else :column="column" :column-option="columnOption" :key="column.id">
|
|
13
12
|
<template v-for="item in comTable.mainSlot" slot-scope="scope" :slot="item">
|
|
14
13
|
<slot v-bind="scope" :name="item"></slot>
|
|
@@ -15,8 +15,9 @@
|
|
|
15
15
|
size="small"
|
|
16
16
|
@click="clearSelection"
|
|
17
17
|
v-if="vaildData(tableOption.selectClearBtn, config.selectClearBtn) && tableOption.selection"
|
|
18
|
-
>{{ '清 空' }}</el-button
|
|
19
18
|
>
|
|
19
|
+
{{ '清 空' }}
|
|
20
|
+
</el-button>
|
|
20
21
|
</el-tag>
|
|
21
22
|
<!-- 表格主体 -->
|
|
22
23
|
<el-table
|
|
@@ -57,7 +58,7 @@
|
|
|
57
58
|
</column>
|
|
58
59
|
</el-table>
|
|
59
60
|
<!-- 分页 -->
|
|
60
|
-
<table-page ref="tablePage"
|
|
61
|
+
<table-page ref="tablePage"></table-page>
|
|
61
62
|
</div>
|
|
62
63
|
</template>
|
|
63
64
|
<script>
|
|
@@ -121,7 +122,7 @@ export default {
|
|
|
121
122
|
mainSlot() {
|
|
122
123
|
let result = [];
|
|
123
124
|
|
|
124
|
-
this.propOption.forEach(
|
|
125
|
+
this.propOption.forEach(item => {
|
|
125
126
|
if (this.$scopedSlots[item.prop]) result.push(item.prop);
|
|
126
127
|
});
|
|
127
128
|
|
|
@@ -134,7 +135,7 @@ export default {
|
|
|
134
135
|
let result = [];
|
|
135
136
|
function findProp(list = []) {
|
|
136
137
|
if (!Array.isArray(list)) return;
|
|
137
|
-
list.forEach(
|
|
138
|
+
list.forEach(ele => {
|
|
138
139
|
if (Array.isArray(ele.children)) findProp(ele.children);
|
|
139
140
|
else result.push(ele);
|
|
140
141
|
});
|
|
@@ -273,7 +274,7 @@ export default {
|
|
|
273
274
|
sortable.create(el, {
|
|
274
275
|
animation: 500,
|
|
275
276
|
delay: 0,
|
|
276
|
-
onEnd:
|
|
277
|
+
onEnd: evt => callback(evt),
|
|
277
278
|
});
|
|
278
279
|
},
|
|
279
280
|
},
|
|
@@ -5,17 +5,18 @@
|
|
|
5
5
|
import CameraControls from 'camera-controls';
|
|
6
6
|
import { TilesRenderer } from '3d-tiles-renderer';
|
|
7
7
|
import { RoomEnvironment } from 'three/examples/jsm/environments/RoomEnvironment.js';
|
|
8
|
-
var instructions, renderer, cameraControls, scene, camera, renderTarget, tilesRenderer
|
|
9
|
-
var
|
|
10
|
-
|
|
8
|
+
var instructions, renderer, cameraControls, scene, camera, renderTarget, tilesRenderer;
|
|
9
|
+
var animateId,
|
|
10
|
+
singleFrameTime = 1 / 30,
|
|
11
|
+
frameCount = 0;
|
|
12
|
+
var needsRerender = false;
|
|
11
13
|
var [fpsClock, timeStamp] = (function* (v) {
|
|
12
14
|
while (true) yield v;
|
|
13
15
|
})(0);
|
|
14
16
|
export default {
|
|
15
17
|
name: 'FlTiles',
|
|
16
18
|
data() {
|
|
17
|
-
return {
|
|
18
|
-
}
|
|
19
|
+
return {};
|
|
19
20
|
},
|
|
20
21
|
created() {
|
|
21
22
|
CameraControls.install({ THREE: this.THREE });
|
|
@@ -36,152 +37,149 @@ export default {
|
|
|
36
37
|
this.initLight();
|
|
37
38
|
this.init3tiles();
|
|
38
39
|
cameraControls.addEventListener('wake', () => {
|
|
39
|
-
console.log(cameraControls._camera.position)
|
|
40
|
-
})
|
|
40
|
+
console.log(cameraControls._camera.position);
|
|
41
|
+
});
|
|
41
42
|
this.animate();
|
|
42
43
|
},
|
|
43
44
|
methods: {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
// 如果是BOX类型,可以获取其中心
|
|
107
|
-
if (tilesRenderer.root.boundingVolume.box) {
|
|
108
|
-
const box = tilesRenderer.root.boundingVolume.box;
|
|
109
|
-
// box: [中心x, 中心y, 中心z, x轴半长, y轴半长, z轴半长]
|
|
110
|
-
console.log(`[调试] 根节点包围盒中心: [${box[0]}, ${box[1]}, ${box[2]}]`);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// 2. 检查第一个子节点(中间节点)
|
|
115
|
-
if (tilesRenderer.root.children && tilesRenderer.root.children[0]) {
|
|
116
|
-
const firstChild = tilesRenderer.root.children[0];
|
|
117
|
-
console.log('[调试] 第一个子节点:', firstChild);
|
|
118
|
-
if (firstChild.boundingVolume) {
|
|
119
|
-
console.log('[调试] 第一个子节点包围盒:', firstChild.boundingVolume);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// 3. 如果中间节点还有children,继续往下找
|
|
124
|
-
if (tilesRenderer.root.children &&
|
|
125
|
-
tilesRenderer.root.children[0] &&
|
|
126
|
-
tilesRenderer.root.children[0].children &&
|
|
127
|
-
tilesRenderer.root.children[0].children[0]) {
|
|
128
|
-
const deepestChild = tilesRenderer.root.children[0].children[0];
|
|
129
|
-
console.log('[调试] 更深层的子节点:', deepestChild);
|
|
130
|
-
if (deepestChild.content) {
|
|
131
|
-
console.log('[调试] 首个Content URI:', deepestChild.content.uri);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
45
|
+
initRender() {
|
|
46
|
+
renderer = new this.THREE.WebGLRenderer({
|
|
47
|
+
antialias: true,
|
|
48
|
+
logarithmicDepthBuffer: true,
|
|
49
|
+
});
|
|
50
|
+
renderer.setPixelRatio(window.devicePixelRatio * 2);
|
|
51
|
+
renderer.setSize(window.innerWidth, window.innerHeight);
|
|
52
|
+
renderer.domElement.id = 'three-model';
|
|
53
|
+
renderer.shadowMap.enabled = true;
|
|
54
|
+
instructions.appendChild(renderer.domElement);
|
|
55
|
+
},
|
|
56
|
+
initScene() {
|
|
57
|
+
scene = new this.THREE.Scene();
|
|
58
|
+
scene.background = new this.THREE.Color(0xffffff);
|
|
59
|
+
},
|
|
60
|
+
initCamera() {
|
|
61
|
+
camera = new this.THREE.PerspectiveCamera(
|
|
62
|
+
45,
|
|
63
|
+
window.innerWidth / window.innerHeight,
|
|
64
|
+
0.1,
|
|
65
|
+
10000000
|
|
66
|
+
);
|
|
67
|
+
camera.position.set(0, 10, 105.524230957031);
|
|
68
|
+
},
|
|
69
|
+
initControl() {
|
|
70
|
+
// 初始化控件
|
|
71
|
+
cameraControls = new CameraControls(camera, renderer.domElement);
|
|
72
|
+
cameraControls.dollyToCursor = true;
|
|
73
|
+
cameraControls.smoothTime = 0.1;
|
|
74
|
+
cameraControls.draggingSmoothTime = 0.05;
|
|
75
|
+
cameraControls.truckSpeed = 2.0;
|
|
76
|
+
cameraControls.infinityDolly = true;
|
|
77
|
+
cameraControls.minDistance = 4;
|
|
78
|
+
},
|
|
79
|
+
// 初始化光源
|
|
80
|
+
initLight() {
|
|
81
|
+
const pmremGenerator = new this.THREE.PMREMGenerator(renderer);
|
|
82
|
+
scene.environment = pmremGenerator.fromScene(new RoomEnvironment(), 0.04).texture;
|
|
83
|
+
},
|
|
84
|
+
init3tiles() {
|
|
85
|
+
// 这个文件需要放到public文件夹下 Tile_+003_+003/Tile_+003_+003
|
|
86
|
+
tilesRenderer = new TilesRenderer('/tiles/tileset.json');
|
|
87
|
+
tilesRenderer.setCamera(camera);
|
|
88
|
+
tilesRenderer.setResolutionFromRenderer(camera, renderer);
|
|
89
|
+
scene.add(tilesRenderer.group);
|
|
90
|
+
|
|
91
|
+
setTimeout(() => (needsRerender = true), 1000);
|
|
92
|
+
},
|
|
93
|
+
// 添加一个标志,等待一帧让TilesRenderer初步解析JSON
|
|
94
|
+
debugTileset() {
|
|
95
|
+
if (tilesRenderer.root && frameCount++ < 10) {
|
|
96
|
+
// 检查前几帧
|
|
97
|
+
console.log('[调试] TilesRenderer根节点:', tilesRenderer.root);
|
|
98
|
+
|
|
99
|
+
// 1. 尝试获取根节点的包围盒 (通常很大,是整个世界范围)
|
|
100
|
+
if (tilesRenderer.root.boundingVolume) {
|
|
101
|
+
console.log('[调试] 根节点包围盒:', tilesRenderer.root.boundingVolume);
|
|
102
|
+
// 如果是BOX类型,可以获取其中心
|
|
103
|
+
if (tilesRenderer.root.boundingVolume.box) {
|
|
104
|
+
const box = tilesRenderer.root.boundingVolume.box;
|
|
105
|
+
// box: [中心x, 中心y, 中心z, x轴半长, y轴半长, z轴半长]
|
|
106
|
+
console.log(`[调试] 根节点包围盒中心: [${box[0]}, ${box[1]}, ${box[2]}]`);
|
|
134
107
|
}
|
|
135
|
-
|
|
136
|
-
animate() {
|
|
137
|
-
// const delta = fpsClock.getDelta();
|
|
138
|
-
// timeStamp += delta;
|
|
139
|
-
// requestAnimationFrame(this.animate)
|
|
140
|
-
// if (needsRerender) {
|
|
108
|
+
}
|
|
141
109
|
|
|
142
|
-
//
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
110
|
+
// 2. 检查第一个子节点(中间节点)
|
|
111
|
+
if (tilesRenderer.root.children && tilesRenderer.root.children[0]) {
|
|
112
|
+
const firstChild = tilesRenderer.root.children[0];
|
|
113
|
+
console.log('[调试] 第一个子节点:', firstChild);
|
|
114
|
+
if (firstChild.boundingVolume) {
|
|
115
|
+
console.log('[调试] 第一个子节点包围盒:', firstChild.boundingVolume);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
146
118
|
|
|
147
|
-
//
|
|
119
|
+
// 3. 如果中间节点还有children,继续往下找
|
|
120
|
+
if (
|
|
121
|
+
tilesRenderer.root.children &&
|
|
122
|
+
tilesRenderer.root.children[0] &&
|
|
123
|
+
tilesRenderer.root.children[0].children &&
|
|
124
|
+
tilesRenderer.root.children[0].children[0]
|
|
125
|
+
) {
|
|
126
|
+
const deepestChild = tilesRenderer.root.children[0].children[0];
|
|
127
|
+
console.log('[调试] 更深层的子节点:', deepestChild);
|
|
128
|
+
if (deepestChild.content) {
|
|
129
|
+
console.log('[调试] 首个Content URI:', deepestChild.content.uri);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
animate() {
|
|
135
|
+
// const delta = fpsClock.getDelta();
|
|
136
|
+
// timeStamp += delta;
|
|
137
|
+
// requestAnimationFrame(this.animate)
|
|
138
|
+
// if (needsRerender) {
|
|
139
|
+
|
|
140
|
+
// needsRerender = false;
|
|
141
|
+
// let box = new this.THREE.Box3()
|
|
142
|
+
|
|
143
|
+
// if (tilesRenderer.getBoundingBox(box)) {
|
|
148
144
|
|
|
149
|
-
|
|
145
|
+
// box.getCenter(tilesRenderer.group.position);
|
|
150
146
|
|
|
151
|
-
|
|
147
|
+
// tilesRenderer.group.position.multiplyScalar(-1);
|
|
152
148
|
|
|
153
|
-
|
|
149
|
+
// }
|
|
154
150
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
151
|
+
// tilesRenderer.update();
|
|
152
|
+
|
|
153
|
+
// }
|
|
154
|
+
// cameraControls.update(timeStamp)
|
|
155
|
+
// tilesRenderer.update();
|
|
156
|
+
// renderer.render(scene, camera);
|
|
157
|
+
const delta = fpsClock.getDelta();
|
|
158
|
+
timeStamp += delta;
|
|
159
|
+
animateId = requestAnimationFrame(this.animate);
|
|
160
|
+
if (timeStamp > singleFrameTime) {
|
|
161
|
+
if (needsRerender) {
|
|
162
|
+
needsRerender = false;
|
|
163
|
+
let box = new this.THREE.Box3();
|
|
164
|
+
if (tilesRenderer.getBoundingBox(box)) {
|
|
165
|
+
box.getCenter(tilesRenderer.group.position);
|
|
166
|
+
tilesRenderer.group.position.multiplyScalar(-1);
|
|
170
167
|
}
|
|
171
|
-
cameraControls.update(timeStamp);
|
|
172
|
-
// this.debugTileset();
|
|
173
|
-
tilesRenderer.update();
|
|
174
|
-
renderer.render(scene, camera);
|
|
175
|
-
timeStamp = timeStamp % singleFrameTime;
|
|
176
168
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
169
|
+
cameraControls.update(timeStamp);
|
|
170
|
+
// this.debugTileset();
|
|
171
|
+
tilesRenderer.update();
|
|
172
|
+
renderer.render(scene, camera);
|
|
173
|
+
timeStamp = timeStamp % singleFrameTime;
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
};
|
|
180
178
|
</script>
|
|
181
179
|
<style lang="scss" scoped>
|
|
182
|
-
#three-box{
|
|
180
|
+
#three-box {
|
|
183
181
|
width: 100%;
|
|
184
182
|
height: 100%;
|
|
185
183
|
overflow: hidden;
|
|
186
184
|
}
|
|
187
|
-
</style>
|
|
185
|
+
</style>
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
<span :title="node.label" class="title_tree">{{ node.label }}</span>
|
|
45
45
|
</span>
|
|
46
46
|
<span class="tree_operation" style="display: inline-block; width: 80px; text-align: right">
|
|
47
|
-
<slot v-if="treeNodeHandle" class="fr_text" :data="data"
|
|
47
|
+
<slot v-if="treeNodeHandle" class="fr_text" :data="data">操作按钮</slot>
|
|
48
48
|
</span>
|
|
49
49
|
</span>
|
|
50
50
|
</el-tree>
|
|
@@ -93,6 +93,46 @@ export class StreamLoader {
|
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
/**
|
|
97
|
+
* 将合并材质数据覆盖到原材质数据中(仅覆盖 merge 中明确提供的字段)
|
|
98
|
+
* 规则:mergeMaterialData 中 id 在 materialData 出现过的,覆盖其 color/transp
|
|
99
|
+
* 注意:应在 _applyPrefixId(materialData, 'id') 之前调用(使用原始 id 对比)
|
|
100
|
+
* @param {Array<Object>|Object|null} materialData
|
|
101
|
+
* @param {Array<Object>|Object|null} mergeMaterialData
|
|
102
|
+
* @returns {Array<Object>|Object|null} materialData(原地修改后返回)
|
|
103
|
+
*/
|
|
104
|
+
_mergeMaterialDataOverrides(materialData, mergeMaterialData) {
|
|
105
|
+
if (!materialData || !mergeMaterialData) return materialData;
|
|
106
|
+
|
|
107
|
+
const materials = Array.isArray(materialData) ? materialData : [materialData];
|
|
108
|
+
const merges = Array.isArray(mergeMaterialData) ? mergeMaterialData : [mergeMaterialData];
|
|
109
|
+
if (materials.length === 0 || merges.length === 0) return materialData;
|
|
110
|
+
|
|
111
|
+
const mergeById = new Map();
|
|
112
|
+
for (let i = 0; i < merges.length; i++) {
|
|
113
|
+
const m = merges[i];
|
|
114
|
+
if (!m || m.id == null) continue;
|
|
115
|
+
mergeById.set(String(m.id), m);
|
|
116
|
+
}
|
|
117
|
+
if (mergeById.size === 0) return materialData;
|
|
118
|
+
|
|
119
|
+
for (let i = 0; i < materials.length; i++) {
|
|
120
|
+
const mat = materials[i];
|
|
121
|
+
if (!mat || mat.id == null) continue;
|
|
122
|
+
const merge = mergeById.get(String(mat.id));
|
|
123
|
+
if (!merge) continue;
|
|
124
|
+
|
|
125
|
+
if (merge.color !== undefined) {
|
|
126
|
+
mat.color = merge.color;
|
|
127
|
+
}
|
|
128
|
+
if (merge.transp !== undefined) {
|
|
129
|
+
mat.transp = merge.transp;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return materialData;
|
|
134
|
+
}
|
|
135
|
+
|
|
96
136
|
workerRequest(type, data, transferable = []) {
|
|
97
137
|
if (!this.worker) {
|
|
98
138
|
return Promise.reject(new Error('Worker is not initialized'));
|
|
@@ -175,13 +215,7 @@ export class StreamLoader {
|
|
|
175
215
|
const meshesToProcess = batchMeshes.slice(batchStart, batchStart + batchSize);
|
|
176
216
|
const primitivesToProcess = batchPrimitives.slice(batchStart, batchStart + batchSize);
|
|
177
217
|
batchStart += batchSize;
|
|
178
|
-
this.processBatchData(
|
|
179
|
-
meshesToProcess,
|
|
180
|
-
primitivesToProcess,
|
|
181
|
-
list,
|
|
182
|
-
range,
|
|
183
|
-
abortSignal
|
|
184
|
-
);
|
|
218
|
+
this.processBatchData(meshesToProcess, primitivesToProcess, list, range, abortSignal);
|
|
185
219
|
}
|
|
186
220
|
|
|
187
221
|
if (batchMeshes.length - batchStart > 0) {
|
|
@@ -192,13 +226,7 @@ export class StreamLoader {
|
|
|
192
226
|
const meshesToProcess = batchMeshes.slice(batchStart);
|
|
193
227
|
const primitivesToProcess = batchPrimitives.slice(batchStart);
|
|
194
228
|
batchStart = batchMeshes.length;
|
|
195
|
-
this.processBatchData(
|
|
196
|
-
meshesToProcess,
|
|
197
|
-
primitivesToProcess,
|
|
198
|
-
list,
|
|
199
|
-
range,
|
|
200
|
-
abortSignal
|
|
201
|
-
);
|
|
229
|
+
this.processBatchData(meshesToProcess, primitivesToProcess, list, range, abortSignal);
|
|
202
230
|
}
|
|
203
231
|
break;
|
|
204
232
|
}
|
|
@@ -228,13 +256,7 @@ export class StreamLoader {
|
|
|
228
256
|
const meshesToProcess = batchMeshes.slice(batchStart, batchStart + batchSize);
|
|
229
257
|
const primitivesToProcess = batchPrimitives.slice(batchStart, batchStart + batchSize);
|
|
230
258
|
batchStart += batchSize;
|
|
231
|
-
this.processBatchData(
|
|
232
|
-
meshesToProcess,
|
|
233
|
-
primitivesToProcess,
|
|
234
|
-
list,
|
|
235
|
-
range,
|
|
236
|
-
abortSignal
|
|
237
|
-
);
|
|
259
|
+
this.processBatchData(meshesToProcess, primitivesToProcess, list, range, abortSignal);
|
|
238
260
|
}
|
|
239
261
|
|
|
240
262
|
if (batchStart >= batchSize * 4) {
|
|
@@ -258,7 +280,6 @@ export class StreamLoader {
|
|
|
258
280
|
let expectingPrimitive = true;
|
|
259
281
|
let isFullProps = true;
|
|
260
282
|
|
|
261
|
-
|
|
262
283
|
while (true) {
|
|
263
284
|
await ensureNotAborted();
|
|
264
285
|
|
|
@@ -440,7 +461,7 @@ export class StreamLoader {
|
|
|
440
461
|
throw new DOMException('Request was aborted', 'AbortError');
|
|
441
462
|
}
|
|
442
463
|
params.requestId = requestId;
|
|
443
|
-
params.projectId = this.projectId
|
|
464
|
+
params.projectId = this.projectId;
|
|
444
465
|
let res;
|
|
445
466
|
if (this.modelApi && typeof this.modelApi.getPrimitivesByRangeStream === 'function') {
|
|
446
467
|
res = await this.modelApi.getPrimitivesByRangeStream(params, internalController.signal);
|
|
@@ -510,6 +531,20 @@ export class StreamLoader {
|
|
|
510
531
|
}
|
|
511
532
|
}
|
|
512
533
|
|
|
534
|
+
async getPrimitivesByMergeMaterial(params) {
|
|
535
|
+
try {
|
|
536
|
+
if (!this.modelApi || typeof this.modelApi.getPrimitivesByMergeMaterial !== 'function') {
|
|
537
|
+
return null;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
const res = await this.modelApi.getPrimitivesByMergeMaterial(params);
|
|
541
|
+
return res || null;
|
|
542
|
+
} catch (error) {
|
|
543
|
+
// mergeMaterial 是可选能力:接口异常时降级为不合并
|
|
544
|
+
return null;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
513
548
|
createAbortableRequest(requestKey = null) {
|
|
514
549
|
const requestId = requestKey || `req_${++this.requestCounter}`;
|
|
515
550
|
|
|
@@ -814,7 +849,10 @@ export class StreamLoader {
|
|
|
814
849
|
const key = keyOrder[i];
|
|
815
850
|
const typeCode = dataTypeString[i];
|
|
816
851
|
const typeInfo = typeMap[typeCode];
|
|
817
|
-
const uint8Array =
|
|
852
|
+
const uint8Array =
|
|
853
|
+
primitive.isCompressed === 1 || primitive.isCompressed === undefined
|
|
854
|
+
? gunzipSync(primitive[key])
|
|
855
|
+
: primitive[key];
|
|
818
856
|
if (!typeInfo || !uint8Array) {
|
|
819
857
|
console.warn(`无法找到键 "${key}" 或其类型定义,已跳过。`);
|
|
820
858
|
parsedResult[key] = [];
|
|
@@ -1152,7 +1190,14 @@ export class StreamLoader {
|
|
|
1152
1190
|
const { mesh, primitives: parsed } = await this.parseBufferData(buffer);
|
|
1153
1191
|
primitives = parsed;
|
|
1154
1192
|
|
|
1155
|
-
await this.renderModelData(
|
|
1193
|
+
await this.renderModelData(
|
|
1194
|
+
mesh,
|
|
1195
|
+
primitives,
|
|
1196
|
+
params.folderInfo,
|
|
1197
|
+
null,
|
|
1198
|
+
onComplete,
|
|
1199
|
+
params.immediateUpdate ?? true
|
|
1200
|
+
);
|
|
1156
1201
|
|
|
1157
1202
|
return { primitives, mesh };
|
|
1158
1203
|
} catch (err) {
|
|
@@ -1202,7 +1247,7 @@ export class StreamLoader {
|
|
|
1202
1247
|
// 其他
|
|
1203
1248
|
// ----------------------------------------------------------------
|
|
1204
1249
|
|
|
1205
|
-
async getSceneBox({id, projectId = this.projectId}) {
|
|
1250
|
+
async getSceneBox({ id, projectId = this.projectId }) {
|
|
1206
1251
|
const res = await this.modelApi.getSceneBox({ id, projectId });
|
|
1207
1252
|
if (res && res[0]) {
|
|
1208
1253
|
this.sceneBox = res[0];
|
|
@@ -1212,7 +1257,7 @@ export class StreamLoader {
|
|
|
1212
1257
|
}
|
|
1213
1258
|
}
|
|
1214
1259
|
|
|
1215
|
-
async getBox({id, projectId = this.projectId || 0}) {
|
|
1260
|
+
async getBox({ id, projectId = this.projectId || 0 }) {
|
|
1216
1261
|
// 1. 尝试从 IndexedDB 读取
|
|
1217
1262
|
const cached = await this._getFromDB(id, projectId);
|
|
1218
1263
|
if (cached) {
|
|
@@ -1354,11 +1399,12 @@ export class StreamLoader {
|
|
|
1354
1399
|
}
|
|
1355
1400
|
}
|
|
1356
1401
|
|
|
1357
|
-
updateModelRegistry(item, materialData, sceneBox, boxIndex) {
|
|
1402
|
+
updateModelRegistry(item, materialData, mergeMaterialData, sceneBox, boxIndex) {
|
|
1358
1403
|
if (item && item.id) {
|
|
1359
1404
|
this.modelRegistry.set(item.id, {
|
|
1360
1405
|
item,
|
|
1361
1406
|
materialData,
|
|
1407
|
+
mergeMaterialData,
|
|
1362
1408
|
sceneBox,
|
|
1363
1409
|
boxIndex,
|
|
1364
1410
|
});
|
|
@@ -1402,12 +1448,22 @@ export class StreamLoader {
|
|
|
1402
1448
|
|
|
1403
1449
|
async processModelItem(item, options = {}) {
|
|
1404
1450
|
try {
|
|
1405
|
-
if(typeof item.id !== 'string'){
|
|
1406
|
-
item.id =
|
|
1451
|
+
if (typeof item.id !== 'string') {
|
|
1452
|
+
item.id = '' + item.id;
|
|
1407
1453
|
}
|
|
1408
1454
|
|
|
1409
1455
|
// 获取材质数据
|
|
1410
|
-
const materialData = await this.getPrimitivesByMaterial({
|
|
1456
|
+
const materialData = await this.getPrimitivesByMaterial({
|
|
1457
|
+
id: item.id,
|
|
1458
|
+
projectId: this.projectId,
|
|
1459
|
+
});
|
|
1460
|
+
|
|
1461
|
+
// 获取合并材质数据
|
|
1462
|
+
const mergeMaterialData = await this.getPrimitivesByMergeMaterial({
|
|
1463
|
+
id: item.id,
|
|
1464
|
+
projectId: this.projectId,
|
|
1465
|
+
});
|
|
1466
|
+
this._applyPrefixId(mergeMaterialData, 'id');
|
|
1411
1467
|
this._applyPrefixId(materialData, 'id');
|
|
1412
1468
|
|
|
1413
1469
|
// 获取场景包围盒
|
|
@@ -1418,11 +1474,14 @@ export class StreamLoader {
|
|
|
1418
1474
|
const boxIndex = await this.getBox({ id: item.id, projectId: this.projectId });
|
|
1419
1475
|
this.boxIndex = boxIndex;
|
|
1420
1476
|
|
|
1421
|
-
|
|
1477
|
+
// 将 mergeMaterialData 覆盖到 materialData(按 id 覆盖 color/transp)
|
|
1478
|
+
this._mergeMaterialDataOverrides(boxIndex, mergeMaterialData);
|
|
1479
|
+
|
|
1480
|
+
const modelResourceMapObj = { materialData, mergeMaterialData, item };
|
|
1422
1481
|
|
|
1423
1482
|
// 设置当前模型到注册表
|
|
1424
|
-
this.updateModelRegistry(item, materialData, sceneBox, boxIndex);
|
|
1425
|
-
console.log('modelRegistry', this.modelRegistry)
|
|
1483
|
+
this.updateModelRegistry(item, materialData, mergeMaterialData, sceneBox, boxIndex);
|
|
1484
|
+
console.log('modelRegistry', this.modelRegistry);
|
|
1426
1485
|
|
|
1427
1486
|
return { modelResourceMap: modelResourceMapObj, sceneBox, boxIndex, item };
|
|
1428
1487
|
} catch (error) {
|
|
@@ -1448,7 +1507,7 @@ export class StreamLoader {
|
|
|
1448
1507
|
resolve(null);
|
|
1449
1508
|
};
|
|
1450
1509
|
request.onsuccess = () => resolve(request.result);
|
|
1451
|
-
request.onupgradeneeded =
|
|
1510
|
+
request.onupgradeneeded = event => {
|
|
1452
1511
|
const db = event.target.result;
|
|
1453
1512
|
if (!db.objectStoreNames.contains('boxCache')) {
|
|
1454
1513
|
db.createObjectStore('boxCache');
|
|
@@ -1462,7 +1521,7 @@ export class StreamLoader {
|
|
|
1462
1521
|
try {
|
|
1463
1522
|
const db = await this._initDB();
|
|
1464
1523
|
if (!db) return null;
|
|
1465
|
-
return new Promise(
|
|
1524
|
+
return new Promise(resolve => {
|
|
1466
1525
|
const transaction = db.transaction(['boxCache'], 'readonly');
|
|
1467
1526
|
const store = transaction.objectStore('boxCache');
|
|
1468
1527
|
const request = store.get(`${projectId}:${id}`);
|