fl-web-component 2.0.19-beta.1 → 2.0.19

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.
@@ -159,7 +159,7 @@ export class StreamLoader {
159
159
 
160
160
  async parseStreamImmediate(reader, list, range, abortSignal = null, streamId = null) {
161
161
  const batchMeshes = [];
162
- const batchPrimitiveGroups = [];
162
+ const batchPrimitives = [];
163
163
  const batchSize = this.batchSize;
164
164
  let batchStart = 0;
165
165
  const streamStats = {
@@ -168,31 +168,8 @@ export class StreamLoader {
168
168
  totalPrimitives: 0,
169
169
  };
170
170
 
171
- const flattenPrimitiveGroups = primitiveGroups => {
172
- if (!primitiveGroups || primitiveGroups.length === 0) return [];
173
- const primitivesToProcess = [];
174
- const usedIds = new Set();
175
-
176
- primitiveGroups.forEach(group => {
177
- const primitives = Array.isArray(group) ? group : [group];
178
- primitives.forEach(primitive => {
179
- if (!primitive) return;
180
- if (primitive.id == null) {
181
- primitivesToProcess.push(primitive);
182
- return;
183
- }
184
- if (usedIds.has(primitive.id)) return;
185
- usedIds.add(primitive.id);
186
- primitivesToProcess.push(primitive);
187
- });
188
- });
189
-
190
- return primitivesToProcess;
191
- };
192
-
193
- const processStreamBatch = async (meshesToProcess, primitiveGroupsToProcess) => {
171
+ const processStreamBatch = async (meshesToProcess, primitivesToProcess) => {
194
172
  if (!meshesToProcess || meshesToProcess.length === 0) return;
195
- const primitivesToProcess = flattenPrimitiveGroups(primitiveGroupsToProcess);
196
173
  await this.processBatchData(meshesToProcess, primitivesToProcess, list, range, abortSignal);
197
174
  streamStats.totalBatches += 1;
198
175
  streamStats.totalMeshes += meshesToProcess.length;
@@ -248,7 +225,7 @@ export class StreamLoader {
248
225
  const flushed = await this.workerRequest('streamFlush', { streamId: localStreamId });
249
226
  if (flushed?.meshes?.length) {
250
227
  batchMeshes.push(...flushed.meshes);
251
- batchPrimitiveGroups.push(...flushed.primitives);
228
+ batchPrimitives.push(...flushed.primitives);
252
229
  }
253
230
 
254
231
  while (batchMeshes.length - batchStart >= batchSize) {
@@ -257,12 +234,9 @@ export class StreamLoader {
257
234
  const interactionPromiseInBatch = ensureNotInteracting();
258
235
  if (interactionPromiseInBatch) await interactionPromiseInBatch;
259
236
  const meshesToProcess = batchMeshes.slice(batchStart, batchStart + batchSize);
260
- const primitiveGroupsToProcess = batchPrimitiveGroups.slice(
261
- batchStart,
262
- batchStart + batchSize
263
- );
237
+ const primitivesToProcess = batchPrimitives.slice(batchStart, batchStart + batchSize);
264
238
  batchStart += batchSize;
265
- await processStreamBatch(meshesToProcess, primitiveGroupsToProcess);
239
+ await processStreamBatch(meshesToProcess, primitivesToProcess);
266
240
  }
267
241
 
268
242
  if (batchMeshes.length - batchStart > 0) {
@@ -271,9 +245,9 @@ export class StreamLoader {
271
245
  const interactionPromiseInBatch = ensureNotInteracting();
272
246
  if (interactionPromiseInBatch) await interactionPromiseInBatch;
273
247
  const meshesToProcess = batchMeshes.slice(batchStart);
274
- const primitiveGroupsToProcess = batchPrimitiveGroups.slice(batchStart);
248
+ const primitivesToProcess = batchPrimitives.slice(batchStart);
275
249
  batchStart = batchMeshes.length;
276
- await processStreamBatch(meshesToProcess, primitiveGroupsToProcess);
250
+ await processStreamBatch(meshesToProcess, primitivesToProcess);
277
251
  }
278
252
  break;
279
253
  }
@@ -292,7 +266,7 @@ export class StreamLoader {
292
266
 
293
267
  if (parsed?.meshes?.length) {
294
268
  batchMeshes.push(...parsed.meshes);
295
- batchPrimitiveGroups.push(...parsed.primitives);
269
+ batchPrimitives.push(...parsed.primitives);
296
270
  }
297
271
 
298
272
  while (batchMeshes.length - batchStart >= batchSize) {
@@ -301,17 +275,14 @@ export class StreamLoader {
301
275
  const interactionPromiseInBatch = ensureNotInteracting();
302
276
  if (interactionPromiseInBatch) await interactionPromiseInBatch;
303
277
  const meshesToProcess = batchMeshes.slice(batchStart, batchStart + batchSize);
304
- const primitiveGroupsToProcess = batchPrimitiveGroups.slice(
305
- batchStart,
306
- batchStart + batchSize
307
- );
278
+ const primitivesToProcess = batchPrimitives.slice(batchStart, batchStart + batchSize);
308
279
  batchStart += batchSize;
309
- await processStreamBatch(meshesToProcess, primitiveGroupsToProcess);
280
+ await processStreamBatch(meshesToProcess, primitivesToProcess);
310
281
  }
311
282
 
312
283
  if (batchStart >= batchSize * 4) {
313
284
  batchMeshes.splice(0, batchStart);
314
- batchPrimitiveGroups.splice(0, batchStart);
285
+ batchPrimitives.splice(0, batchStart);
315
286
  batchStart = 0;
316
287
  }
317
288
  }
@@ -326,127 +297,10 @@ export class StreamLoader {
326
297
  const decoder = new TextDecoder('utf-8');
327
298
  let buffer = new Uint8Array();
328
299
 
329
- let expectingMesh = true;
330
- let pendingMesh = null;
331
- let pendingPrimitiveIds = new Set();
332
- let pendingPrimitiveGroups = [];
333
- let pendingMatchedPrimitiveIds = new Set();
300
+ const pendingPrimitives = new Map();
301
+ let expectingPrimitive = true;
334
302
  let isFullProps = true;
335
303
 
336
- const normalizeMesh = mesh => {
337
- this._applyPrefixId(mesh, 'id');
338
- const meshList = Array.isArray(mesh) ? mesh : [mesh];
339
- meshList.forEach(item => {
340
- if (!item) return;
341
- if (!Array.isArray(item.primitives)) {
342
- item.primitives = [];
343
- }
344
- this._applyPrefixId(item.primitives, 'prmid', item.documentId);
345
- });
346
- return mesh;
347
- };
348
-
349
- const collectMeshPrimitiveIds = mesh => {
350
- const ids = [];
351
- const meshList = Array.isArray(mesh) ? mesh : [mesh];
352
- meshList.forEach(item => {
353
- if (!item || !Array.isArray(item.primitives)) return;
354
- item.primitives.forEach(primitive => {
355
- if (primitive && primitive.prmid != null) {
356
- ids.push(primitive.prmid);
357
- }
358
- });
359
- });
360
- return ids;
361
- };
362
-
363
- const isValidStreamMesh = mesh => {
364
- const meshList = Array.isArray(mesh) ? mesh : [mesh];
365
- if (meshList.length === 0) return false;
366
- return meshList.every(
367
- item => item && typeof item === 'object' && Array.isArray(item.primitives)
368
- );
369
- };
370
-
371
- const tryParseMeshFromBuffer = () => {
372
- if (buffer.length < 4) {
373
- return { status: 'incomplete' };
374
- }
375
-
376
- const length = new DataView(buffer.buffer, buffer.byteOffset).getUint32(0, false);
377
- if (length <= 0 || length > 10 * 1024 * 1024) {
378
- return { status: 'invalid' };
379
- }
380
-
381
- const totalLen = 4 + length;
382
- if (buffer.length < totalLen) {
383
- return { status: 'incomplete' };
384
- }
385
-
386
- try {
387
- const data = buffer.slice(4, totalLen);
388
- const parsedMesh = JSON.parse(decoder.decode(data));
389
- if (!isValidStreamMesh(parsedMesh)) {
390
- return { status: 'invalid' };
391
- }
392
- const mesh = normalizeMesh(parsedMesh);
393
- return { status: 'success', mesh, totalLen };
394
- } catch (e) {
395
- return { status: 'invalid' };
396
- }
397
- };
398
-
399
- const parsePrimitiveFromBuffer = () => {
400
- const dataView = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
401
- const primitiveResult = this.parsePrimitive(dataView, buffer, 0, isFullProps);
402
- const primitiveData = primitiveResult.primitive;
403
-
404
- this._applyPrefixId(primitiveData, 'id');
405
- this._applyPrefixId(primitiveData, 'material');
406
-
407
- if (isFullProps) {
408
- const { position, normal, posindex, nolindex, indices } =
409
- this.parsePrimitiveData(primitiveData);
410
- const formatted = this.formatPrimitiveData({ position, normal, posindex, nolindex });
411
-
412
- delete primitiveData.nolindex;
413
- delete primitiveData.posindex;
414
-
415
- primitiveData.position = formatted.position;
416
- primitiveData.normal = formatted.normal;
417
- primitiveData.indices = indices;
418
- }
419
-
420
- return {
421
- primitive: primitiveData,
422
- consumedBytes: primitiveResult.offset,
423
- };
424
- };
425
-
426
- const commitPendingMesh = async () => {
427
- if (!pendingMesh) return;
428
-
429
- const meshList = Array.isArray(pendingMesh) ? pendingMesh : [pendingMesh];
430
- meshList.forEach(mesh => {
431
- batchMeshes.push(mesh);
432
- batchPrimitiveGroups.push(pendingPrimitiveGroups);
433
- });
434
-
435
- pendingMesh = null;
436
- pendingPrimitiveIds = new Set();
437
- pendingPrimitiveGroups = [];
438
- pendingMatchedPrimitiveIds = new Set();
439
-
440
- if (batchMeshes.length >= this.batchSize) {
441
- await ensureNotAborted();
442
- await this.ensureNotInteracting(abortSignal);
443
- await processStreamBatch(batchMeshes, batchPrimitiveGroups);
444
-
445
- batchMeshes.length = 0;
446
- batchPrimitiveGroups.length = 0;
447
- }
448
- };
449
-
450
304
  while (true) {
451
305
  await ensureNotAborted();
452
306
 
@@ -465,12 +319,11 @@ export class StreamLoader {
465
319
  const { done, value } = content;
466
320
  if (done) {
467
321
  await ensureNotAborted();
468
- await commitPendingMesh();
469
322
 
470
323
  if (batchMeshes.length > 0) {
471
324
  await ensureNotAborted();
472
325
  await this.ensureNotInteracting(abortSignal);
473
- await processStreamBatch(batchMeshes, batchPrimitiveGroups);
326
+ await processStreamBatch(batchMeshes, batchPrimitives);
474
327
  }
475
328
  break;
476
329
  }
@@ -482,55 +335,103 @@ export class StreamLoader {
482
335
 
483
336
  while (buffer.length > 0) {
484
337
  await ensureNotAborted();
485
- if (expectingMesh) {
486
- const meshResult = tryParseMeshFromBuffer();
487
- if (meshResult.status === 'incomplete') break;
488
- if (meshResult.status === 'invalid') {
338
+ if (expectingPrimitive) {
339
+ if (buffer.length < 12) break;
340
+
341
+ try {
342
+ const dataView = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
343
+ const primitiveResult = this.parsePrimitive(dataView, buffer, 0, isFullProps);
344
+ let primitiveData = primitiveResult.primitive;
345
+
346
+ this._applyPrefixId(primitiveData, 'id');
347
+ this._applyPrefixId(primitiveData, 'material');
348
+ const consumedBytes = primitiveResult.offset;
349
+
350
+ if (isFullProps) {
351
+ const { position, normal, posindex, nolindex, indices } =
352
+ this.parsePrimitiveData(primitiveData);
353
+ const formatted = this.formatPrimitiveData({ position, normal, posindex, nolindex });
354
+
355
+ delete primitiveData.nolindex;
356
+ delete primitiveData.posindex;
357
+
358
+ primitiveData.position = formatted.position;
359
+ primitiveData.normal = formatted.normal;
360
+ primitiveData.indices = indices;
361
+ }
362
+ const docId = primitiveData.id;
363
+
364
+ pendingPrimitives.set(docId, primitiveData);
365
+
366
+ expectingPrimitive = false;
367
+ buffer = buffer.slice(consumedBytes);
368
+ } catch (e) {
489
369
  break;
490
370
  }
491
-
492
- await commitPendingMesh();
493
- pendingMesh = meshResult.mesh;
494
- pendingPrimitiveIds = new Set(collectMeshPrimitiveIds(pendingMesh));
495
- pendingPrimitiveGroups = [];
496
- pendingMatchedPrimitiveIds = new Set();
497
- expectingMesh = false;
498
- buffer = buffer.slice(meshResult.totalLen);
499
371
  } else {
500
- const nextMeshResult = tryParseMeshFromBuffer();
501
- if (nextMeshResult.status === 'success') {
502
- await commitPendingMesh();
503
- pendingMesh = nextMeshResult.mesh;
504
- pendingPrimitiveIds = new Set(collectMeshPrimitiveIds(pendingMesh));
505
- expectingMesh = false;
506
- buffer = buffer.slice(nextMeshResult.totalLen);
372
+ if (buffer.length < 4) break;
373
+
374
+ const length = new DataView(buffer.buffer, buffer.byteOffset).getUint32(0, false);
375
+
376
+ if (length > 10 * 1024 * 1024) {
377
+ expectingPrimitive = true;
507
378
  continue;
508
379
  }
509
380
 
510
- if (buffer.length < 12) break;
381
+ const totalLen = 4 + length;
382
+
383
+ if (buffer.length < totalLen) break;
384
+
385
+ const data = buffer.slice(4, totalLen);
386
+ let mesh = null;
511
387
 
512
- let primitiveResult = null;
513
388
  try {
514
- primitiveResult = parsePrimitiveFromBuffer();
389
+ const jsonStr = decoder.decode(data);
390
+ mesh = JSON.parse(jsonStr);
515
391
  } catch (e) {
516
- break;
392
+ expectingPrimitive = true;
393
+ continue;
517
394
  }
518
395
 
519
- const primitiveData = primitiveResult.primitive;
396
+ if (mesh) {
397
+ isFullProps = true;
520
398
 
521
- if (pendingPrimitiveIds.has(primitiveData.id)) {
522
- pendingPrimitiveGroups.push(primitiveData);
523
- pendingMatchedPrimitiveIds.add(primitiveData.id);
524
- }
399
+ this._applyPrefixId(mesh, 'id');
400
+ if (Array.isArray(mesh)) {
401
+ mesh.forEach(item => {
402
+ this._applyPrefixId(item.primitives, 'prmid', item.documentId);
403
+ });
404
+ } else {
405
+ this._applyPrefixId(mesh.primitives, 'prmid', mesh.documentId);
406
+ }
525
407
 
526
- buffer = buffer.slice(primitiveResult.consumedBytes);
408
+ let docId = mesh.id;
409
+ const meshToPrimId = mesh.primitives.map(item => item.prmid);
410
+ const hasPendingPrimitive = meshToPrimId.some(item => pendingPrimitives.has(item));
411
+ const hasPendingMesh = pendingPrimitives.has(docId);
412
+
413
+ if (hasPendingMesh || hasPendingPrimitive) {
414
+ let primitiveData = pendingPrimitives.get(docId);
415
+ if (!hasPendingMesh && hasPendingPrimitive) {
416
+ const primId = meshToPrimId[0];
417
+ primitiveData = pendingPrimitives.get(primId);
418
+ }
419
+
420
+ batchMeshes.push(mesh);
421
+ batchPrimitives.push(primitiveData);
422
+
423
+ if (batchMeshes.length >= this.batchSize) {
424
+ await ensureNotAborted();
425
+ await this.ensureNotInteracting(abortSignal);
426
+ await processStreamBatch(batchMeshes, batchPrimitives);
427
+
428
+ batchMeshes.length = 0;
429
+ batchPrimitives.length = 0;
430
+ }
431
+ }
527
432
 
528
- if (
529
- pendingPrimitiveIds.size > 0 &&
530
- pendingMatchedPrimitiveIds.size >= pendingPrimitiveIds.size
531
- ) {
532
- await commitPendingMesh();
533
- expectingMesh = true;
433
+ expectingPrimitive = false;
434
+ buffer = buffer.slice(totalLen);
534
435
  }
535
436
  }
536
437
  }
@@ -547,18 +448,10 @@ export class StreamLoader {
547
448
  if (abortSignal && abortSignal.aborted) {
548
449
  throw new DOMException('Request was aborted', 'AbortError');
549
450
  }
550
- const renderResult = await this.renderModelData(
551
- meshes,
552
- primitives,
553
- list,
554
- range,
555
- null,
556
- undefined,
557
- {
558
- suppressLoadComplete: true,
559
- source: 'inRangeDis2',
560
- }
561
- );
451
+ const renderResult = await this.renderModelData(meshes, primitives, list, range, null, undefined, {
452
+ suppressLoadComplete: true,
453
+ source: 'inRangeDis2',
454
+ });
562
455
  if (renderResult && renderResult.canceled) {
563
456
  throw new DOMException('Batch loading was canceled', 'AbortError');
564
457
  }
@@ -956,12 +849,7 @@ export class StreamLoader {
956
849
  async fetchJsonStream(list, range, abortSignal = null, requestId = null) {
957
850
  try {
958
851
  const loadStartTime = Date.now();
959
- const streamResult = await this.fetchPrimitiveBufferByStream(
960
- range,
961
- list,
962
- abortSignal,
963
- requestId
964
- );
852
+ const streamResult = await this.fetchPrimitiveBufferByStream(range, list, abortSignal, requestId);
965
853
  return {
966
854
  ...(streamResult || {}),
967
855
  duration: Date.now() - loadStartTime,
@@ -1051,20 +939,8 @@ export class StreamLoader {
1051
939
  if (dataView.byteLength < offset + 12) {
1052
940
  throw new Error('Insufficient data for primitive header');
1053
941
  }
1054
- const primitiveIdTextLen = dataView.getUint32(offset, false);
942
+ primitive.id = dataView.getInt32(offset, false);
1055
943
  offset += 4;
1056
- if (primitiveIdTextLen === 0xffffffff) {
1057
- primitive.id = null;
1058
- } else if (primitiveIdTextLen > 0) {
1059
- if (dataView.byteLength < offset + primitiveIdTextLen) {
1060
- throw new Error('Insufficient data for primitive id content');
1061
- }
1062
- const textBytes = uint8Array.subarray(offset, offset + primitiveIdTextLen);
1063
- primitive.id = new TextDecoder('utf-8').decode(textBytes);
1064
- offset += primitiveIdTextLen;
1065
- } else {
1066
- primitive.id = '';
1067
- }
1068
944
 
1069
945
  if (dataView.byteLength < offset + 4) {
1070
946
  throw new Error('Insufficient data for GeomText length');
@@ -1084,23 +960,8 @@ export class StreamLoader {
1084
960
  primitive.documentId = '';
1085
961
  }
1086
962
 
1087
- if (dataView.byteLength < offset + 4) {
1088
- throw new Error('Insufficient data for Material length');
1089
- }
1090
- const materialTextLen = dataView.getUint32(offset, false);
963
+ primitive.material = dataView.getInt32(offset, false);
1091
964
  offset += 4;
1092
- if (materialTextLen === 0xffffffff) {
1093
- primitive.material = null;
1094
- } else if (materialTextLen > 0) {
1095
- if (dataView.byteLength < offset + materialTextLen) {
1096
- throw new Error('Insufficient data for Material content');
1097
- }
1098
- const textBytes = uint8Array.subarray(offset, offset + materialTextLen);
1099
- primitive.material = new TextDecoder('utf-8').decode(textBytes);
1100
- offset += materialTextLen;
1101
- } else {
1102
- primitive.material = '';
1103
- }
1104
965
 
1105
966
  if (dataView.byteLength < offset + 4) {
1106
967
  throw new Error('Insufficient data for GeomText length');
@@ -1450,10 +1311,10 @@ export class StreamLoader {
1450
1311
  }
1451
1312
  }
1452
1313
 
1453
- async getBox({ id, projectId = this.projectId || 0, isDebug }) {
1314
+ async getBox({ id, projectId = this.projectId || 0 }) {
1454
1315
  // 1. 尝试从 IndexedDB 读取
1455
1316
  const cached = await this._getFromDB(id, projectId);
1456
- if (cached && !isDebug) {
1317
+ if (cached) {
1457
1318
  return cached;
1458
1319
  }
1459
1320
 
@@ -1678,11 +1539,7 @@ export class StreamLoader {
1678
1539
  this.sceneBox = sceneBox;
1679
1540
 
1680
1541
  // 获取BoxIndex
1681
- const boxIndex = await this.getBox({
1682
- id: item.id,
1683
- projectId: this.projectId,
1684
- isDebug: this.debug,
1685
- });
1542
+ const boxIndex = await this.getBox({ id: item.id, projectId: this.projectId });
1686
1543
  this.boxIndex = boxIndex;
1687
1544
 
1688
1545
  // 将 mergeMaterialData 覆盖到 materialData(按 id 覆盖 color/transp)