@navaramap/three 0.0.8 → 0.1.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/LICENSE +1 -1
- package/README.md +20 -8
- package/dist/assets/fontWorker-C5cHhkWQ.js +2 -0
- package/dist/assets/fontWorker-C5cHhkWQ.js.map +1 -0
- package/dist/assets/{index-DaejBdUz.js → index-VfUncKuS.js} +2 -2
- package/dist/assets/index-VfUncKuS.js.map +1 -0
- package/dist/assets/{navara_wasm_font_worker_bg-CSmoDs_Q.wasm → navara_wasm_font_worker_bg-CKqHBoCR.wasm} +0 -0
- package/dist/assets/{navara_wasm_worker_bg-C1dUd_Nk.wasm → navara_wasm_worker_bg-CT26EH41.wasm} +0 -0
- package/dist/index.d.ts +298 -54
- package/dist/index.js +1569 -1396
- package/dist/index.js.map +1 -1
- package/dist/index.umd.cjs +90 -69
- package/dist/index.umd.cjs.map +1 -1
- package/package.json +12 -12
- package/src/core/BaseDesc.ts +25 -1
- package/src/core/MeshDesc.test.ts +6 -8
- package/src/core/MeshDesc.ts +4 -6
- package/src/evaluations/FeatureEvaluator.ts +17 -10
- package/src/event/feature.ts +15 -2
- package/src/event/features/billboard.test.ts +62 -0
- package/src/event/features/billboard.ts +4 -2
- package/src/index.ts +266 -98
- package/src/material/enhancer/model/modelBaseEnhancer/shader.ts +2 -2
- package/src/material/enhancer/polygon/polygonBaseEnhancer/shader.ts +2 -2
- package/src/material/macro/tileShader.ts +12 -2
- package/src/mesh/polyline.ts +32 -4
- package/src/mesh/sdfText/batchedSdfText.test.ts +65 -0
- package/src/mesh/sdfText/batchedSdfText.ts +121 -43
- package/src/mesh/sprite/instancedSprite.ts +173 -65
- package/src/pick/pickHelper.test.ts +389 -4
- package/src/pick/pickHelper.ts +212 -37
- package/src/plugins/AttributionPlugin/index.ts +1 -1
- package/src/renderOrder.ts +10 -0
- package/src/terrain/sampleTerrainMostDetailed.test.ts +6 -6
- package/src/terrain/sampleTerrainMostDetailed.ts +7 -5
- package/src/type/index.ts +22 -1
- package/dist/assets/fontWorker-CkLGtrXf.js +0 -2
- package/dist/assets/fontWorker-CkLGtrXf.js.map +0 -1
- package/dist/assets/index-DaejBdUz.js.map +0 -1
package/src/mesh/polyline.ts
CHANGED
|
@@ -32,6 +32,16 @@ import { setupRTECallback } from "./rtcRteHelper";
|
|
|
32
32
|
// Sentinel value for picking coordinate when not picking (reused to avoid allocations)
|
|
33
33
|
const PICKING_COORD_SENTINEL = new Vector2(-1, -1);
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Minimum stroke width used while rendering the pick pass. A hairline stroke
|
|
37
|
+
* covers too few pick-buffer texels to click reliably — on the draped path the
|
|
38
|
+
* 512px tile atlas resolves a thin line to scattered partial texels, so the
|
|
39
|
+
* decoded batch id is background almost everywhere the line is visible.
|
|
40
|
+
* Fattening the stroke only for the pick render gives lines the same "click
|
|
41
|
+
* tolerance" pointing devices get elsewhere; the visible width is untouched.
|
|
42
|
+
*/
|
|
43
|
+
const MIN_PICK_WIDTH = 10;
|
|
44
|
+
|
|
35
45
|
type Attributes = BatchedFeatureAttributes<{
|
|
36
46
|
position: BufferAttribute;
|
|
37
47
|
// RTE mode attributes (only present when useRTE=true)
|
|
@@ -490,11 +500,21 @@ export class PolylineMesh extends BatchedFeatureMesh<
|
|
|
490
500
|
return this.getEnhancer().states().effectIdsMask;
|
|
491
501
|
}
|
|
492
502
|
|
|
503
|
+
/** Visible stroke width to restore after a pick-pass width bump. */
|
|
504
|
+
private _pickSavedWidth?: number;
|
|
505
|
+
|
|
493
506
|
onBeforePicking(pickingCoord?: Vector2) {
|
|
494
|
-
this.getEnhancer()
|
|
507
|
+
const enhancer = this.getEnhancer();
|
|
508
|
+
const width = enhancer.states().width;
|
|
509
|
+
if (width < MIN_PICK_WIDTH) {
|
|
510
|
+
this._pickSavedWidth = width;
|
|
511
|
+
enhancer.update({ base: { pickable: true, width: MIN_PICK_WIDTH } });
|
|
512
|
+
} else {
|
|
513
|
+
enhancer.update({ base: { pickable: true } });
|
|
514
|
+
}
|
|
495
515
|
this.needsUpdate();
|
|
496
516
|
|
|
497
|
-
const mutates =
|
|
517
|
+
const mutates = enhancer.mutates();
|
|
498
518
|
if (pickingCoord) {
|
|
499
519
|
mutates.setPickingCoord(pickingCoord);
|
|
500
520
|
} else {
|
|
@@ -503,9 +523,17 @@ export class PolylineMesh extends BatchedFeatureMesh<
|
|
|
503
523
|
}
|
|
504
524
|
|
|
505
525
|
onAfterPicking() {
|
|
506
|
-
this.getEnhancer()
|
|
526
|
+
const enhancer = this.getEnhancer();
|
|
527
|
+
if (this._pickSavedWidth !== undefined) {
|
|
528
|
+
enhancer.update({
|
|
529
|
+
base: { pickable: false, width: this._pickSavedWidth },
|
|
530
|
+
});
|
|
531
|
+
this._pickSavedWidth = undefined;
|
|
532
|
+
} else {
|
|
533
|
+
enhancer.update({ base: { pickable: false } });
|
|
534
|
+
}
|
|
507
535
|
this.needsUpdate();
|
|
508
|
-
|
|
536
|
+
enhancer.mutates().setPickingCoord(PICKING_COORD_SENTINEL);
|
|
509
537
|
}
|
|
510
538
|
|
|
511
539
|
_getDefaultBatchAttributeValues(): DefaultBatchAttributeValues {
|
|
@@ -212,6 +212,71 @@ describe("BatchedSdfTextMesh material updates vs per-feature values", () => {
|
|
|
212
212
|
});
|
|
213
213
|
});
|
|
214
214
|
|
|
215
|
+
// A feature owns several anchors for MultiPoint geometry and for labels
|
|
216
|
+
// derived from line/polygon vertices via `geometryTypes`. Per-feature setters
|
|
217
|
+
// address features (batch indices), so they must fan out to every anchor the
|
|
218
|
+
// feature owns via the geometry's per-anchor `batch_index` buffer.
|
|
219
|
+
describe("BatchedSdfTextMesh multi-instance fan-out", () => {
|
|
220
|
+
/** Feature 0 owns anchors 0 and 1 (MultiPoint); feature 1 owns anchor 2. */
|
|
221
|
+
function multiInstanceMeshEvent(mat: NavaraTextMaterial): NavaraTextMesh {
|
|
222
|
+
return {
|
|
223
|
+
material: mat,
|
|
224
|
+
transform: { tx: 0, ty: 0, tz: 0 },
|
|
225
|
+
geometry: {
|
|
226
|
+
batch_ids: { data: new Float32Array([7, 8, 9]), size: 1 },
|
|
227
|
+
batch_index: { data: new Uint32Array([0, 0, 1]), size: 1 },
|
|
228
|
+
position: {
|
|
229
|
+
data: new Float32Array([0, 0, 0, 10, 0, 0, 20, 0, 0]),
|
|
230
|
+
size: 3,
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
} as unknown as NavaraTextMesh;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function makeMultiInstanceMesh() {
|
|
237
|
+
const fontManager = makeFontManager();
|
|
238
|
+
const ctx = {
|
|
239
|
+
buf: {
|
|
240
|
+
removeF32: (d: Float32Array) => d,
|
|
241
|
+
u32: (d: Uint32Array) => d,
|
|
242
|
+
},
|
|
243
|
+
fontManager,
|
|
244
|
+
renderFlag: { forceUpdate: false },
|
|
245
|
+
} as unknown as EventContext;
|
|
246
|
+
const mesh = new BatchedSdfTextMesh(
|
|
247
|
+
ctx,
|
|
248
|
+
multiInstanceMeshEvent(material()),
|
|
249
|
+
"font",
|
|
250
|
+
{ layerId: "layer" },
|
|
251
|
+
);
|
|
252
|
+
return { mesh, fontManager };
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
it("applies text and styles to every anchor the feature owns", () => {
|
|
256
|
+
const { mesh } = makeMultiInstanceMesh();
|
|
257
|
+
mesh.setTextByBatchIndex(0, "AB");
|
|
258
|
+
mesh.setFeatureSizeByBatchIndex(0, 32);
|
|
259
|
+
|
|
260
|
+
// Feature 0's two anchors got labels (slots 0 and 1), both styled.
|
|
261
|
+
expect(showOf(mesh, 0)).toBe(1);
|
|
262
|
+
expect(showOf(mesh, 1)).toBe(1);
|
|
263
|
+
expect(sizeOf(mesh, 0)).toBe(32);
|
|
264
|
+
expect(sizeOf(mesh, 1)).toBe(32);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it("does not leak styling into other features' anchors", () => {
|
|
268
|
+
const { mesh } = makeMultiInstanceMesh();
|
|
269
|
+
mesh.setTextByBatchIndex(0, "AB");
|
|
270
|
+
mesh.setTextByBatchIndex(1, "CD");
|
|
271
|
+
mesh.setFeatureShowByBatchIndex(1, false);
|
|
272
|
+
|
|
273
|
+
expect(showOf(mesh, 0)).toBe(1);
|
|
274
|
+
expect(showOf(mesh, 1)).toBe(1);
|
|
275
|
+
// Feature 1 = anchor 2 = the third label slot.
|
|
276
|
+
expect(showOf(mesh, 2)).toBe(0);
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
|
|
215
280
|
// Unprepared text costs a worker round-trip and font-face fetches, and a
|
|
216
281
|
// low-zoom tile spans far more world than the screen shows. With declutter on,
|
|
217
282
|
// `setTextByBatchIndex` therefore parks preparation until a placement pass
|
|
@@ -81,7 +81,10 @@ type PositionsInfo = PositionsInfoBase &
|
|
|
81
81
|
type LabelRecord = {
|
|
82
82
|
/** Row block in the label data texture, and this label's declutter handle. */
|
|
83
83
|
slot: number;
|
|
84
|
-
|
|
84
|
+
/** Anchor (position) slot this label sits on, NOT the feature index: a
|
|
85
|
+
* feature spans several anchors for MultiPoint geometry and for labels
|
|
86
|
+
* derived from line/polygon vertices via `geometryTypes`. */
|
|
87
|
+
instanceIndex: number;
|
|
85
88
|
batchId: number;
|
|
86
89
|
/** The text currently laid out into the glyph run. */
|
|
87
90
|
text: string;
|
|
@@ -179,8 +182,15 @@ export class BatchedSdfTextMesh
|
|
|
179
182
|
|
|
180
183
|
/** Labels in slot order — `_labels[slot]` is also the declutter handle map. */
|
|
181
184
|
private _labels: LabelRecord[] = [];
|
|
182
|
-
/** Sparse
|
|
183
|
-
private
|
|
185
|
+
/** Sparse anchor slot → label; labels are created on first per-feature touch. */
|
|
186
|
+
private _labelByInstance: (LabelRecord | undefined)[] = [];
|
|
187
|
+
/**
|
|
188
|
+
* Feature (batch) index → this feature's anchor slots. A feature owns
|
|
189
|
+
* multiple anchors for MultiPoint geometry and for labels derived from
|
|
190
|
+
* line/polygon vertices via `geometryTypes`, so per-feature styling must fan
|
|
191
|
+
* out to all of them. `null` means anchors and features are 1:1.
|
|
192
|
+
*/
|
|
193
|
+
private _batchIndexToInstances: Map<number, number[]> | null = null;
|
|
184
194
|
|
|
185
195
|
/** In-flight per-feature text preparations; see {@link whenLabelsSettled}. */
|
|
186
196
|
private _pendingTextPrepares = new PendingSettlement();
|
|
@@ -240,6 +250,7 @@ export class BatchedSdfTextMesh
|
|
|
240
250
|
this._declutterPriority = material.declutterPriority ?? 0;
|
|
241
251
|
|
|
242
252
|
this._positions = this.extractPositions(m);
|
|
253
|
+
this._rebuildBatchIndexMap(m);
|
|
243
254
|
this._glyphs = new GlyphBuffers();
|
|
244
255
|
this._labelData = new LabelDataTexture();
|
|
245
256
|
|
|
@@ -359,12 +370,12 @@ export class BatchedSdfTextMesh
|
|
|
359
370
|
for (let i = 0; i < info.nPositions; i++) this._ensureLabel(i);
|
|
360
371
|
}
|
|
361
372
|
|
|
362
|
-
private _ensureLabel(
|
|
363
|
-
const existing = this.
|
|
373
|
+
private _ensureLabel(instanceIndex: number): LabelRecord | undefined {
|
|
374
|
+
const existing = this._labelByInstance[instanceIndex];
|
|
364
375
|
if (existing) return existing;
|
|
365
376
|
|
|
366
377
|
const info = this._positions;
|
|
367
|
-
if (!info ||
|
|
378
|
+
if (!info || instanceIndex < 0 || instanceIndex >= info.nPositions) {
|
|
368
379
|
return undefined;
|
|
369
380
|
}
|
|
370
381
|
|
|
@@ -376,8 +387,10 @@ export class BatchedSdfTextMesh
|
|
|
376
387
|
|
|
377
388
|
const record: LabelRecord = {
|
|
378
389
|
slot,
|
|
379
|
-
|
|
380
|
-
batchId: info.batchIDs
|
|
390
|
+
instanceIndex,
|
|
391
|
+
batchId: info.batchIDs
|
|
392
|
+
? info.batchIDs[instanceIndex * info.batchIDSize]
|
|
393
|
+
: 0,
|
|
381
394
|
text: "",
|
|
382
395
|
requestedText: "",
|
|
383
396
|
prepareDeferred: false,
|
|
@@ -405,7 +418,7 @@ export class BatchedSdfTextMesh
|
|
|
405
418
|
};
|
|
406
419
|
|
|
407
420
|
this._labels.push(record);
|
|
408
|
-
this.
|
|
421
|
+
this._labelByInstance[instanceIndex] = record;
|
|
409
422
|
|
|
410
423
|
this._writeAnchor(record);
|
|
411
424
|
this._writeStyle(record);
|
|
@@ -419,7 +432,7 @@ export class BatchedSdfTextMesh
|
|
|
419
432
|
private _writeAnchor(record: LabelRecord): void {
|
|
420
433
|
const info = this._positions;
|
|
421
434
|
if (!info) return;
|
|
422
|
-
const idx = record.
|
|
435
|
+
const idx = record.instanceIndex * info.positionSize;
|
|
423
436
|
const anchor = record.anchor;
|
|
424
437
|
|
|
425
438
|
if (info.RTE) {
|
|
@@ -971,6 +984,51 @@ export class BatchedSdfTextMesh
|
|
|
971
984
|
return null;
|
|
972
985
|
}
|
|
973
986
|
|
|
987
|
+
/**
|
|
988
|
+
* Group anchor slots by their feature's batch index from the geometry's
|
|
989
|
+
* per-anchor `batch_index` buffer. The u32 view is consumed synchronously —
|
|
990
|
+
* other wasm calls may detach views, so it must not be stored. An identity
|
|
991
|
+
* mapping (every feature owns exactly one anchor, the common MVT case) skips
|
|
992
|
+
* the map entirely.
|
|
993
|
+
*/
|
|
994
|
+
private _rebuildBatchIndexMap(m: NavaraTextMesh): void {
|
|
995
|
+
const batchIndexData = m.geometry.batch_index?.data;
|
|
996
|
+
const batchIndices =
|
|
997
|
+
batchIndexData !== undefined ? this.ctx.buf.u32(batchIndexData) : null;
|
|
998
|
+
this._batchIndexToInstances = null;
|
|
999
|
+
if (!batchIndices) return;
|
|
1000
|
+
|
|
1001
|
+
let identity = true;
|
|
1002
|
+
for (let i = 0; i < batchIndices.length; i++) {
|
|
1003
|
+
if (batchIndices[i] !== i) {
|
|
1004
|
+
identity = false;
|
|
1005
|
+
break;
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
if (identity) return;
|
|
1009
|
+
|
|
1010
|
+
const map = new Map<number, number[]>();
|
|
1011
|
+
for (let i = 0; i < batchIndices.length; i++) {
|
|
1012
|
+
const batchIndex = batchIndices[i];
|
|
1013
|
+
let instances = map.get(batchIndex);
|
|
1014
|
+
if (!instances) {
|
|
1015
|
+
instances = [];
|
|
1016
|
+
map.set(batchIndex, instances);
|
|
1017
|
+
}
|
|
1018
|
+
instances.push(i);
|
|
1019
|
+
}
|
|
1020
|
+
this._batchIndexToInstances = map;
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
/** All anchor slots owned by the feature at `batchIndex`. */
|
|
1024
|
+
private _instancesOfBatchIndex(batchIndex: number): number[] {
|
|
1025
|
+
if (this._batchIndexToInstances) {
|
|
1026
|
+
return this._batchIndexToInstances.get(batchIndex) ?? [];
|
|
1027
|
+
}
|
|
1028
|
+
const nPositions = this._positions?.nPositions ?? 0;
|
|
1029
|
+
return batchIndex >= 0 && batchIndex < nPositions ? [batchIndex] : [];
|
|
1030
|
+
}
|
|
1031
|
+
|
|
974
1032
|
async _update(m: NavaraTextMesh, needRender?: () => void) {
|
|
975
1033
|
if (needRender) this._needRender = needRender;
|
|
976
1034
|
|
|
@@ -992,6 +1050,7 @@ export class BatchedSdfTextMesh
|
|
|
992
1050
|
"Number of positions in the updated geometry must match the initial geometry",
|
|
993
1051
|
);
|
|
994
1052
|
this._positions = positionInfo;
|
|
1053
|
+
this._rebuildBatchIndexMap(m);
|
|
995
1054
|
this._enhancer
|
|
996
1055
|
.mutates()
|
|
997
1056
|
.setRtcCenter([m.transform.tx, m.transform.ty, m.transform.tz]);
|
|
@@ -1162,12 +1221,18 @@ export class BatchedSdfTextMesh
|
|
|
1162
1221
|
// --- Per-feature API (the FeatureEvaluator contract) ---
|
|
1163
1222
|
|
|
1164
1223
|
setTextByBatchIndex(batchIndex: number, text: string) {
|
|
1224
|
+
for (const instanceIndex of this._instancesOfBatchIndex(batchIndex)) {
|
|
1225
|
+
this._setTextByInstance(instanceIndex, text);
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
private _setTextByInstance(instanceIndex: number, text: string) {
|
|
1165
1230
|
// An empty text on a label that doesn't exist yet changes nothing (a
|
|
1166
1231
|
// lazily-skipped label is exactly an invisible empty-text label); only a
|
|
1167
1232
|
// non-empty text forces one into existence.
|
|
1168
1233
|
const record = text
|
|
1169
|
-
? this._ensureLabel(
|
|
1170
|
-
: this.
|
|
1234
|
+
? this._ensureLabel(instanceIndex)
|
|
1235
|
+
: this._labelByInstance[instanceIndex];
|
|
1171
1236
|
if (!record) return;
|
|
1172
1237
|
|
|
1173
1238
|
// Record the intent up front so a slower prepare for an older text can
|
|
@@ -1284,57 +1349,69 @@ export class BatchedSdfTextMesh
|
|
|
1284
1349
|
}
|
|
1285
1350
|
|
|
1286
1351
|
override setFeatureColorByBatchIndex(batchIndex: number, color: Color) {
|
|
1287
|
-
const
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1352
|
+
for (const instanceIndex of this._instancesOfBatchIndex(batchIndex)) {
|
|
1353
|
+
const record = this._ensureLabel(instanceIndex);
|
|
1354
|
+
if (!record) continue;
|
|
1355
|
+
record.colorHex = color.getHex();
|
|
1356
|
+
this._writeStyle(record);
|
|
1357
|
+
}
|
|
1291
1358
|
}
|
|
1292
1359
|
|
|
1293
1360
|
override setFeatureShowByBatchIndex(batchIndex: number, rawVisible: boolean) {
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1361
|
+
for (const instanceIndex of this._instancesOfBatchIndex(batchIndex)) {
|
|
1362
|
+
// A label that doesn't exist yet is already effectively `show:false`, so
|
|
1363
|
+
// only `show:true` needs to force one into existence — the common MVT
|
|
1364
|
+
// case is thousands of features that stay hidden and never get a label.
|
|
1365
|
+
const record = rawVisible
|
|
1366
|
+
? this._ensureLabel(instanceIndex)
|
|
1367
|
+
: this._labelByInstance[instanceIndex];
|
|
1368
|
+
if (!record) continue;
|
|
1369
|
+
record.requestedShow = rawVisible;
|
|
1370
|
+
this._recomputeShow(record);
|
|
1371
|
+
}
|
|
1303
1372
|
this._markDeclutterDirty();
|
|
1304
1373
|
}
|
|
1305
1374
|
|
|
1306
1375
|
override setFeatureHeightByBatchIndex(batchIndex: number, height: number) {
|
|
1307
|
-
const
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1376
|
+
for (const instanceIndex of this._instancesOfBatchIndex(batchIndex)) {
|
|
1377
|
+
const record = this._ensureLabel(instanceIndex);
|
|
1378
|
+
if (!record) continue;
|
|
1379
|
+
record.addHeight = height;
|
|
1380
|
+
this._writeAddHeight(record);
|
|
1381
|
+
}
|
|
1311
1382
|
this._markDeclutterDirty();
|
|
1312
1383
|
}
|
|
1313
1384
|
|
|
1314
1385
|
setFeatureSizeByBatchIndex(batchIndex: number, size: number) {
|
|
1315
|
-
const
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1386
|
+
for (const instanceIndex of this._instancesOfBatchIndex(batchIndex)) {
|
|
1387
|
+
const record = this._ensureLabel(instanceIndex);
|
|
1388
|
+
if (!record) continue;
|
|
1389
|
+
record.fontSize = Number.isFinite(size)
|
|
1390
|
+
? Math.max(0.0, size)
|
|
1391
|
+
: record.fontSize;
|
|
1392
|
+
this._writeFontSize(record);
|
|
1393
|
+
}
|
|
1321
1394
|
this._markDeclutterDirty();
|
|
1322
1395
|
}
|
|
1323
1396
|
|
|
1324
1397
|
setFeatureOpacityByBatchIndex(batchIndex: number, opacity: number) {
|
|
1325
|
-
const
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1398
|
+
for (const instanceIndex of this._instancesOfBatchIndex(batchIndex)) {
|
|
1399
|
+
const record = this._ensureLabel(instanceIndex);
|
|
1400
|
+
if (!record) continue;
|
|
1401
|
+
record.opacity = clamp01(opacity);
|
|
1402
|
+
this._writeStyle(record);
|
|
1403
|
+
}
|
|
1329
1404
|
}
|
|
1330
1405
|
|
|
1331
1406
|
setFeatureDeclutterPriorityByBatchIndex(
|
|
1332
1407
|
batchIndex: number,
|
|
1333
1408
|
priority: number,
|
|
1334
1409
|
) {
|
|
1335
|
-
const
|
|
1336
|
-
|
|
1337
|
-
|
|
1410
|
+
for (const instanceIndex of this._instancesOfBatchIndex(batchIndex)) {
|
|
1411
|
+
const record = this._ensureLabel(instanceIndex);
|
|
1412
|
+
if (!record) continue;
|
|
1413
|
+
record.priorityOverride = priority;
|
|
1414
|
+
}
|
|
1338
1415
|
this._markDeclutterDirty();
|
|
1339
1416
|
}
|
|
1340
1417
|
|
|
@@ -1368,7 +1445,8 @@ export class BatchedSdfTextMesh
|
|
|
1368
1445
|
record.retainedKeys = null;
|
|
1369
1446
|
}
|
|
1370
1447
|
this._labels.length = 0;
|
|
1371
|
-
this.
|
|
1448
|
+
this._labelByInstance.length = 0;
|
|
1449
|
+
this._batchIndexToInstances = null;
|
|
1372
1450
|
|
|
1373
1451
|
this._labelData.dispose();
|
|
1374
1452
|
this._glyphs.dispose();
|