bruce-cesium 7.4.1 → 7.4.3
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/dist/bruce-cesium.es5.js +295 -159
- package/dist/bruce-cesium.es5.js.map +1 -1
- package/dist/bruce-cesium.umd.js +293 -157
- package/dist/bruce-cesium.umd.js.map +1 -1
- package/dist/lib/bruce-cesium.js +1 -1
- package/dist/lib/rendering/entity-gatherer.js +50 -51
- package/dist/lib/rendering/entity-gatherer.js.map +1 -1
- package/dist/lib/rendering/entity-render-engine.js +56 -26
- package/dist/lib/rendering/entity-render-engine.js.map +1 -1
- package/dist/lib/rendering/render-managers/common/entity-label.js +185 -78
- package/dist/lib/rendering/render-managers/common/entity-label.js.map +1 -1
- package/dist/types/bruce-cesium.d.ts +1 -1
- package/dist/types/rendering/entity-gatherer.d.ts +2 -1
- package/dist/types/rendering/entity-render-engine.d.ts +1 -0
- package/dist/types/rendering/render-managers/common/entity-label.d.ts +4 -1
- package/package.json +1 -1
package/dist/bruce-cesium.umd.js
CHANGED
|
@@ -5383,7 +5383,14 @@
|
|
|
5383
5383
|
(function (EntityLabel) {
|
|
5384
5384
|
const ICON_BACKGROUND_BLEND = 0.8;
|
|
5385
5385
|
const ICON_BACKGROUND_ALPHA = 0.45;
|
|
5386
|
+
// Under this much difference between the glyph's width and height the chip is squared off,
|
|
5387
|
+
// so a row of labels reads as one size rather than a set of differently shaped pills.
|
|
5388
|
+
const ICON_BACKGROUND_UNIFORM_TOLERANCE = 0.3;
|
|
5386
5389
|
const TEXT_MAX_WIDTH = 200;
|
|
5390
|
+
// How far an angled leader runs sideways before the label starts.
|
|
5391
|
+
const ANGLED_LEADER_RUN = 28;
|
|
5392
|
+
// One per tinted icon, since an SVG mask is addressed by id across the whole document.
|
|
5393
|
+
let tintCounter = 0;
|
|
5387
5394
|
// Key where the label instance is stored within the cesium entity.
|
|
5388
5395
|
// Eg: rego[ATTACH_KEY] = new EntityLabel(...);
|
|
5389
5396
|
EntityLabel.ATTACH_KEY = "nextspace-navigator-entity-label";
|
|
@@ -5482,7 +5489,7 @@
|
|
|
5482
5489
|
this.nextOrder = 0;
|
|
5483
5490
|
}
|
|
5484
5491
|
Resolve(frames) {
|
|
5485
|
-
var _a, _b;
|
|
5492
|
+
var _a, _b, _c;
|
|
5486
5493
|
const live = new Set(frames.map(frame => frame.id));
|
|
5487
5494
|
const moved = (frame) => {
|
|
5488
5495
|
var _a;
|
|
@@ -5509,10 +5516,17 @@
|
|
|
5509
5516
|
const placed = new Map();
|
|
5510
5517
|
const next = new Map();
|
|
5511
5518
|
const candidate = (frame, side) => {
|
|
5512
|
-
var _a;
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5519
|
+
var _a, _b;
|
|
5520
|
+
if (!frame.canFlip) {
|
|
5521
|
+
return frame;
|
|
5522
|
+
}
|
|
5523
|
+
if (frame.leaderRun != null) {
|
|
5524
|
+
const x = side === "left" ? frame.anchorX - frame.leaderRun - frame.width : frame.anchorX + frame.leaderRun;
|
|
5525
|
+
return { ...frame, x: Math.max(0, Math.min(x, ((_a = frame.viewportWidth) !== null && _a !== void 0 ? _a : Infinity) - frame.width)) };
|
|
5526
|
+
}
|
|
5527
|
+
return (side === "left" ?
|
|
5528
|
+
{ ...frame, x: Math.max(0, Math.min(frame.anchorX - frame.width, ((_b = frame.viewportWidth) !== null && _b !== void 0 ? _b : Infinity) - frame.width)) }
|
|
5529
|
+
: frame);
|
|
5516
5530
|
};
|
|
5517
5531
|
const score = (frame, padding = 0) => {
|
|
5518
5532
|
const box = {
|
|
@@ -5528,7 +5542,7 @@
|
|
|
5528
5542
|
};
|
|
5529
5543
|
for (const frame of ordered) {
|
|
5530
5544
|
const old = this.previous.get(frame.id);
|
|
5531
|
-
let side = frame.canFlip ? (_a = old === null || old === void 0 ? void 0 : old.side) !== null && _a !== void 0 ? _a : "right" : "right";
|
|
5545
|
+
let side = frame.canFlip ? (_b = (_a = old === null || old === void 0 ? void 0 : old.side) !== null && _a !== void 0 ? _a : frame.leaderSide) !== null && _b !== void 0 ? _b : "right" : "right";
|
|
5532
5546
|
let chosen = candidate(frame, side);
|
|
5533
5547
|
if (!fixed(frame) && frame.canFlip) {
|
|
5534
5548
|
const otherSide = side === "left" ? "right" : "left";
|
|
@@ -5540,7 +5554,7 @@
|
|
|
5540
5554
|
}
|
|
5541
5555
|
}
|
|
5542
5556
|
placed.set(frame.id, { frame: chosen, side });
|
|
5543
|
-
next.set(frame.id, { frame: fixed(frame) ? old.frame : { ...frame }, side, order: (
|
|
5557
|
+
next.set(frame.id, { frame: fixed(frame) ? old.frame : { ...frame }, side, order: (_c = old === null || old === void 0 ? void 0 : old.order) !== null && _c !== void 0 ? _c : this.nextOrder++ });
|
|
5544
5558
|
text.Add(chosen);
|
|
5545
5559
|
const stem = leaderBounds(chosen);
|
|
5546
5560
|
if (stem) {
|
|
@@ -5560,7 +5574,7 @@
|
|
|
5560
5574
|
* Resolves clustering and stable text placement before depth fading; highlighted labels receive priority.
|
|
5561
5575
|
*/
|
|
5562
5576
|
function Layout(input, memory = new PlacementMemory()) {
|
|
5563
|
-
var _a, _b, _c, _d, _e, _f, _g
|
|
5577
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
5564
5578
|
const frames = input.filter(frame => [frame.x, frame.y, frame.width, frame.height, frame.depth].every(Number.isFinite))
|
|
5565
5579
|
.sort((a, b) => (b.priority || 0) - (a.priority || 0) || a.depth - b.depth || a.id.localeCompare(b.id));
|
|
5566
5580
|
const result = new Map();
|
|
@@ -5626,17 +5640,13 @@
|
|
|
5626
5640
|
}
|
|
5627
5641
|
}
|
|
5628
5642
|
if (values.size > 1) {
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
if (values.size > 2)
|
|
5637
|
-
rows.push(`+${values.size - 2} more…`);
|
|
5638
|
-
representative.text = rows.join("\n");
|
|
5639
|
-
}
|
|
5643
|
+
// A value long enough to wrap fills the box on its own, so only one is listed.
|
|
5644
|
+
const wrapped = stableMembers.some(member => { var _a, _b; return member.textWrapped && ((_b = (member.text || ((_a = member.options) === null || _a === void 0 ? void 0 : _a.text))) === null || _b === void 0 ? void 0 : _b.trim()); });
|
|
5645
|
+
const limit = wrapped ? 1 : 2;
|
|
5646
|
+
const rows = Array.from(values).slice(0, limit);
|
|
5647
|
+
if (values.size > limit)
|
|
5648
|
+
rows.push(`+${values.size - limit} more…`);
|
|
5649
|
+
representative.text = rows.join("\n");
|
|
5640
5650
|
}
|
|
5641
5651
|
}
|
|
5642
5652
|
for (const frame of cluster.members) {
|
|
@@ -5660,7 +5670,7 @@
|
|
|
5660
5670
|
const box = { ...frame, x: frame.x + .01, y: frame.y + .01, width: Math.max(0, frame.width - .02), height: Math.max(0, frame.height - .02) };
|
|
5661
5671
|
const overlap = foreground.HasOverlap(box) || foregroundLeaders.HasOverlap(box) || Boolean(stem && foreground.HasOverlap(stem));
|
|
5662
5672
|
if (overlap) {
|
|
5663
|
-
placement.opacity *= Math.max(0, Math.min(1, (
|
|
5673
|
+
placement.opacity *= Math.max(0, Math.min(1, (_g = (_f = frame.options) === null || _f === void 0 ? void 0 : _f.overlapOpacity) !== null && _g !== void 0 ? _g : 0.25));
|
|
5664
5674
|
}
|
|
5665
5675
|
placement.zIndex = zIndex--;
|
|
5666
5676
|
foreground.Add(frame);
|
|
@@ -5982,6 +5992,8 @@
|
|
|
5982
5992
|
this.loadTimeout = null;
|
|
5983
5993
|
this.loadedName = false;
|
|
5984
5994
|
this.line = null;
|
|
5995
|
+
// The sideways half of an angled leader; the rise is drawn by line.
|
|
5996
|
+
this.leaderRun = null;
|
|
5985
5997
|
this.anchor = null;
|
|
5986
5998
|
// Null = not attempted to load.
|
|
5987
5999
|
this.additionalTexts = null;
|
|
@@ -6378,6 +6390,7 @@
|
|
|
6378
6390
|
}
|
|
6379
6391
|
};
|
|
6380
6392
|
const normalLeader = (_k = this.options.leader) !== null && _k !== void 0 ? _k : presentation === "text";
|
|
6393
|
+
const angled = this.options.leaderStyle === "angled";
|
|
6381
6394
|
let leader = normalLeader;
|
|
6382
6395
|
const content = document.createElement("span");
|
|
6383
6396
|
const originalText = (_l = this.options.text) !== null && _l !== void 0 ? _l : [text, ...additionalTexts].join("\n");
|
|
@@ -6386,6 +6399,7 @@
|
|
|
6386
6399
|
let sourceNaturalText;
|
|
6387
6400
|
let iconElement;
|
|
6388
6401
|
let iconContainer;
|
|
6402
|
+
let fitIconBackground;
|
|
6389
6403
|
content.className = "entity-label-content";
|
|
6390
6404
|
content.style.cssText = "display:flex;align-items:center;gap:6px;";
|
|
6391
6405
|
if (presentation === "icon-text-above") {
|
|
@@ -6408,34 +6422,49 @@
|
|
|
6408
6422
|
image.alt = this.options.icon || "";
|
|
6409
6423
|
const scale = (_o = this.options.iconScale) !== null && _o !== void 0 ? _o : 1;
|
|
6410
6424
|
const size = this.options.iconSize;
|
|
6411
|
-
const
|
|
6412
|
-
|
|
6413
|
-
|
|
6414
|
-
|
|
6415
|
-
|
|
6416
|
-
|
|
6417
|
-
mask
|
|
6418
|
-
mask.
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
}
|
|
6425
|
+
const svgNs = "http://www.w3.org/2000/svg";
|
|
6426
|
+
const tint = iconColor ? document.createElementNS(svgNs, "svg") : null;
|
|
6427
|
+
const painted = tint ? document.createElementNS(svgNs, "image") : null;
|
|
6428
|
+
const inked = tint ? document.createElementNS(svgNs, "rect") : null;
|
|
6429
|
+
if (tint) {
|
|
6430
|
+
const maskId = `entity-label-tint-${++tintCounter}`;
|
|
6431
|
+
const mask = document.createElementNS(svgNs, "mask");
|
|
6432
|
+
mask.setAttribute("id", maskId);
|
|
6433
|
+
mask.setAttribute("maskUnits", "userSpaceOnUse");
|
|
6434
|
+
painted.setAttribute("href", this.options.iconUrl);
|
|
6435
|
+
painted.setAttribute("preserveAspectRatio", "xMidYMid meet");
|
|
6436
|
+
mask.appendChild(painted);
|
|
6437
|
+
inked.setAttribute("fill", iconColor);
|
|
6438
|
+
inked.setAttribute("mask", `url(#${maskId})`);
|
|
6439
|
+
tint.append(mask, inked);
|
|
6440
|
+
tint.style.display = "block";
|
|
6441
|
+
icon.style.display = "inline-flex";
|
|
6442
|
+
icon.appendChild(tint);
|
|
6425
6443
|
}
|
|
6426
6444
|
const resize = () => {
|
|
6427
6445
|
if (this.disposed || this.counter !== counter) {
|
|
6428
6446
|
return;
|
|
6429
6447
|
}
|
|
6430
6448
|
const intrinsic = this.options.iconScale != null && size == null;
|
|
6431
|
-
|
|
6432
|
-
|
|
6449
|
+
const width = (intrinsic ? image.naturalWidth || 24 : size || 24) * scale;
|
|
6450
|
+
const height = (intrinsic ? image.naturalHeight || 24 : size || 24) * scale;
|
|
6451
|
+
if (tint) {
|
|
6452
|
+
tint.setAttribute("viewBox", `0 0 ${width} ${height}`);
|
|
6453
|
+
for (const node of [tint, painted, inked]) {
|
|
6454
|
+
node.setAttribute("width", String(width));
|
|
6455
|
+
node.setAttribute("height", String(height));
|
|
6456
|
+
}
|
|
6457
|
+
}
|
|
6458
|
+
else {
|
|
6459
|
+
image.style.width = `${width}px`;
|
|
6460
|
+
image.style.height = `${height}px`;
|
|
6461
|
+
}
|
|
6433
6462
|
this.viewer.scene.requestRender();
|
|
6434
6463
|
};
|
|
6435
6464
|
image.onload = resize;
|
|
6436
6465
|
resize();
|
|
6437
6466
|
image.src = this.options.iconUrl;
|
|
6438
|
-
if (!
|
|
6467
|
+
if (!tint) {
|
|
6439
6468
|
icon.appendChild(image);
|
|
6440
6469
|
}
|
|
6441
6470
|
}
|
|
@@ -6460,6 +6489,27 @@
|
|
|
6460
6489
|
icon.style.minWidth = `${size}px`;
|
|
6461
6490
|
icon.style.minHeight = `${size}px`;
|
|
6462
6491
|
icon.style.boxSizing = "content-box";
|
|
6492
|
+
let fitted = false;
|
|
6493
|
+
fitIconBackground = () => {
|
|
6494
|
+
if (fitted) {
|
|
6495
|
+
return;
|
|
6496
|
+
}
|
|
6497
|
+
const padding = size / 3;
|
|
6498
|
+
const width = icon.offsetWidth - padding * 2;
|
|
6499
|
+
const height = icon.offsetHeight - padding * 2;
|
|
6500
|
+
if (width <= 0 || height <= 0) {
|
|
6501
|
+
return;
|
|
6502
|
+
}
|
|
6503
|
+
fitted = true;
|
|
6504
|
+
const longest = Math.max(width, height);
|
|
6505
|
+
const difference = (longest - Math.min(width, height)) / longest;
|
|
6506
|
+
if (difference > ICON_BACKGROUND_UNIFORM_TOLERANCE) {
|
|
6507
|
+
return;
|
|
6508
|
+
}
|
|
6509
|
+
icon.style.minWidth = `${longest}px`;
|
|
6510
|
+
icon.style.minHeight = `${longest}px`;
|
|
6511
|
+
this.viewer.scene.requestRender();
|
|
6512
|
+
};
|
|
6463
6513
|
}
|
|
6464
6514
|
if (this.options.iconScale === 0) {
|
|
6465
6515
|
icon.style.display = "none";
|
|
@@ -6498,8 +6548,10 @@
|
|
|
6498
6548
|
const countElement = document.createElement("span");
|
|
6499
6549
|
countElement.className = "entity-label-count";
|
|
6500
6550
|
countElement.style.cssText = "flex:none;align-self:center;white-space:nowrap;background:#fff;color:#000;text-shadow:none;border-radius:8px;padding:0 3px;display:none;";
|
|
6551
|
+
// Text above the icon would have the badge land in it, so the free corner is the lower one.
|
|
6552
|
+
const badgeBelow = presentation === "icon-text-above";
|
|
6501
6553
|
if (iconContainer) {
|
|
6502
|
-
countElement.style.cssText +=
|
|
6554
|
+
countElement.style.cssText += `position:absolute;left:100%;top:${badgeBelow ? "100%" : "0"};transform:translate(-50%,-50%);`;
|
|
6503
6555
|
iconContainer.appendChild(countElement);
|
|
6504
6556
|
}
|
|
6505
6557
|
if (!layers.has(this.viewer)) {
|
|
@@ -6508,6 +6560,7 @@
|
|
|
6508
6560
|
const layer = layers.get(this.viewer);
|
|
6509
6561
|
let ele = null;
|
|
6510
6562
|
let lineEle = null;
|
|
6563
|
+
let runEle = null;
|
|
6511
6564
|
if (this.label) {
|
|
6512
6565
|
ele = this.label;
|
|
6513
6566
|
}
|
|
@@ -6544,6 +6597,7 @@
|
|
|
6544
6597
|
}
|
|
6545
6598
|
if (this.line) {
|
|
6546
6599
|
lineEle = this.line;
|
|
6600
|
+
runEle = this.leaderRun;
|
|
6547
6601
|
}
|
|
6548
6602
|
else {
|
|
6549
6603
|
lineEle = document.createElement("div");
|
|
@@ -6587,6 +6641,14 @@
|
|
|
6587
6641
|
layer.element.appendChild(lineEleNode);
|
|
6588
6642
|
layer.element.appendChild(lineEle);
|
|
6589
6643
|
}
|
|
6644
|
+
// Built here rather than beside the stem, since the style can change on a label that is reused.
|
|
6645
|
+
if (angled && !runEle) {
|
|
6646
|
+
runEle = lineEle.cloneNode(false);
|
|
6647
|
+
runEle.className = "entity-label-leader-run";
|
|
6648
|
+
runEle.style.display = "none";
|
|
6649
|
+
this.leaderRun = runEle;
|
|
6650
|
+
layer.element.appendChild(runEle);
|
|
6651
|
+
}
|
|
6590
6652
|
let MAX_DISTANCE = Math.max(15000, sizeInM * 35);
|
|
6591
6653
|
if (visual && visual instanceof Cesium.Entity) {
|
|
6592
6654
|
// Consistent sized things.
|
|
@@ -6606,6 +6668,25 @@
|
|
|
6606
6668
|
y: upwards ? endY - height : endY, endY
|
|
6607
6669
|
};
|
|
6608
6670
|
};
|
|
6671
|
+
/*
|
|
6672
|
+
* An angled leader parks the label beside the anchor instead of over it,
|
|
6673
|
+
* so the stem rises to the label's middle and then runs out to whichever side has the room.
|
|
6674
|
+
*/
|
|
6675
|
+
const fitAngledLeader = (anchorX, anchorY, desired, width, height, radius = 0) => {
|
|
6676
|
+
const canvas = this.viewer.canvas;
|
|
6677
|
+
const above = Math.max(0, anchorY - height / 2);
|
|
6678
|
+
const below = Math.max(0, canvas.clientHeight - anchorY - height / 2);
|
|
6679
|
+
const upwards = above >= Math.max(radius ? radius + 4 : 0, Math.min(8, desired)) || above >= below;
|
|
6680
|
+
const length = Math.min(desired, upwards ? above : below);
|
|
6681
|
+
const endY = anchorY + (upwards ? -length : length);
|
|
6682
|
+
const run = Math.max(ANGLED_LEADER_RUN, radius + 4);
|
|
6683
|
+
const rightwards = anchorX + run + width <= canvas.clientWidth || anchorX - run - width < 0;
|
|
6684
|
+
return {
|
|
6685
|
+
x: Math.max(0, Math.min(rightwards ? anchorX + run : anchorX - run - width, canvas.clientWidth - width)),
|
|
6686
|
+
y: Math.max(0, Math.min(endY - height / 2, canvas.clientHeight - height)), endY,
|
|
6687
|
+
run, side: (rightwards ? "right" : "left")
|
|
6688
|
+
};
|
|
6689
|
+
};
|
|
6609
6690
|
let cursorMotion = this.cursorMotion;
|
|
6610
6691
|
const project = () => {
|
|
6611
6692
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
|
|
@@ -6743,7 +6824,14 @@
|
|
|
6743
6824
|
y -= height / 2;
|
|
6744
6825
|
}
|
|
6745
6826
|
// Membership uses the unclamped source footprint, never the summary's changing dimensions.
|
|
6746
|
-
|
|
6827
|
+
let leaderRun;
|
|
6828
|
+
let leaderSide;
|
|
6829
|
+
if (leader && angled) {
|
|
6830
|
+
const fit = fitAngledLeader(anchorX, anchorY, leaderLength, width, height);
|
|
6831
|
+
({ x, y } = fit);
|
|
6832
|
+
({ run: leaderRun, side: leaderSide } = fit);
|
|
6833
|
+
}
|
|
6834
|
+
else if (leader)
|
|
6747
6835
|
({ x, y } = fitLeader(anchorX, anchorY, leaderLength, width, height));
|
|
6748
6836
|
const bounds = clusterBounds || { x, y, width, height };
|
|
6749
6837
|
if (!leader && (bounds.x + bounds.width < 0 || bounds.y + bounds.height < 0 || bounds.x > this.viewer.canvas.clientWidth || bounds.y > this.viewer.canvas.clientHeight)) {
|
|
@@ -6758,20 +6846,21 @@
|
|
|
6758
6846
|
extendedGeometry: visual instanceof Cesium.Entity && Boolean(visual.polygon || visual.polyline || visual.corridor),
|
|
6759
6847
|
viewportWidth: this.viewer.canvas.clientWidth,
|
|
6760
6848
|
id: this.id, entityKey: ((_s = this.rego) === null || _s === void 0 ? void 0 : _s.entityId) ? JSON.stringify([this.rego.entityId, this.rego.menuItemId || "", this.Transient && !this.Persistent ? "hover" : ""]) : undefined,
|
|
6761
|
-
entityId: (_t = this.rego) === null || _t === void 0 ? void 0 : _t.entityId, group: this.groupId, x, y, width, height, anchorX, anchorY, depth, leaderLength, distance,
|
|
6849
|
+
entityId: (_t = this.rego) === null || _t === void 0 ? void 0 : _t.entityId, group: this.groupId, x, y, width, height, anchorX, anchorY, depth, leaderLength, leaderRun, leaderSide, distance,
|
|
6762
6850
|
// Priority shows the hovered member individually without dragging its cluster along.
|
|
6763
6851
|
opacity, priority: hover || cursorAmount > 0 || (state === null || state === void 0 ? void 0 : state.highlighted) ? 1 : 0, options: this.options, text: originalText, clusterBounds
|
|
6764
6852
|
};
|
|
6765
6853
|
};
|
|
6766
6854
|
let displacement = { x: 0, y: 0 };
|
|
6767
|
-
let displayedSummaryMore = false;
|
|
6768
6855
|
let nudge = { x: 0, y: 0, fromX: 0, fromY: 0, targetX: 0, targetY: 0, start: 0 };
|
|
6769
6856
|
const apply = (placement) => {
|
|
6770
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y;
|
|
6857
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0;
|
|
6771
6858
|
const show = (placement === null || placement === void 0 ? void 0 : placement.visible) && placement.opacity > 0;
|
|
6772
6859
|
clickEntityIds = show ? placement.entityIds : [];
|
|
6773
6860
|
ele.style.visibility = show ? "visible" : "hidden";
|
|
6774
6861
|
lineEle.style.display = show && leader ? "block" : "none";
|
|
6862
|
+
if (runEle)
|
|
6863
|
+
runEle.style.display = show && leader ? "block" : "none";
|
|
6775
6864
|
this.anchor.style.display = show && leader ? "block" : "none";
|
|
6776
6865
|
if (!show) {
|
|
6777
6866
|
displacement = { x: 0, y: 0 };
|
|
@@ -6782,17 +6871,8 @@
|
|
|
6782
6871
|
return;
|
|
6783
6872
|
}
|
|
6784
6873
|
const displayText = (_a = placement.text) !== null && _a !== void 0 ? _a : originalText;
|
|
6785
|
-
|
|
6786
|
-
if (textElement && (textElement.textContent !== displayText + (summaryMore ? "\n…" : "") || displayedSummaryMore !== summaryMore)) {
|
|
6874
|
+
if (textElement && textElement.textContent !== displayText) {
|
|
6787
6875
|
textElement.textContent = displayText;
|
|
6788
|
-
if (summaryMore) {
|
|
6789
|
-
const more = document.createElement("span");
|
|
6790
|
-
more.className = "entity-label-more";
|
|
6791
|
-
more.style.opacity = "0.65";
|
|
6792
|
-
more.textContent = "\n…";
|
|
6793
|
-
textElement.appendChild(more);
|
|
6794
|
-
}
|
|
6795
|
-
displayedSummaryMore = summaryMore;
|
|
6796
6876
|
// Measure the summary's footprint next frame without replacing each member's source text.
|
|
6797
6877
|
this.viewer.scene.requestRender();
|
|
6798
6878
|
}
|
|
@@ -6810,6 +6890,7 @@
|
|
|
6810
6890
|
// The badge participates in layout, so its new width needs another measurement.
|
|
6811
6891
|
this.viewer.scene.requestRender();
|
|
6812
6892
|
}
|
|
6893
|
+
fitIconBackground === null || fitIconBackground === void 0 ? void 0 : fitIconBackground();
|
|
6813
6894
|
if (iconContainer) {
|
|
6814
6895
|
const badgeWidth = countElement.offsetWidth;
|
|
6815
6896
|
const iconWidth = iconElement.offsetWidth;
|
|
@@ -6817,7 +6898,9 @@
|
|
|
6817
6898
|
const clearance = badgeWidth ? (narrow ? badgeWidth / 2 + 2 : Math.max(0, badgeWidth / 2 - iconWidth / 4)) : 0;
|
|
6818
6899
|
countElement.style.left = `calc(100% + ${clearance}px)`;
|
|
6819
6900
|
// Reserve the badge overhang so adjacent text and viewport edges remain clear.
|
|
6820
|
-
|
|
6901
|
+
const overhang = countElement.offsetHeight / 2;
|
|
6902
|
+
iconContainer.style.marginTop = badgeBelow ? "0px" : `${overhang}px`;
|
|
6903
|
+
iconContainer.style.marginBottom = badgeBelow ? `${overhang}px` : "0px";
|
|
6821
6904
|
iconContainer.style.marginRight = `${badgeWidth / 2 + clearance}px`;
|
|
6822
6905
|
}
|
|
6823
6906
|
// Summary and badge changes must fit on their first visible frame, including after resize.
|
|
@@ -6860,19 +6943,26 @@
|
|
|
6860
6943
|
sharedRing.animation = ringAnimation;
|
|
6861
6944
|
}
|
|
6862
6945
|
const radius = ringAnimation.inner > 0 ? ringAnimation.outer : 0;
|
|
6863
|
-
const stem = (leader ? fitLeader(frame.anchorX, frame.anchorY, Math.max(frame.leaderLength, radius ? radius + 4 : 0), ele.offsetWidth / coordinates.scaleX, ele.offsetHeight / coordinates.scaleY, radius) : undefined);
|
|
6946
|
+
const stem = (leader ? (angled ? fitAngledLeader : fitLeader)(frame.anchorX, frame.anchorY, Math.max(frame.leaderLength, radius ? radius + 4 : 0), ele.offsetWidth / coordinates.scaleX, ele.offsetHeight / coordinates.scaleY, radius) : undefined);
|
|
6864
6947
|
const position = { x: (stem || frame).x, y: (stem || frame).y };
|
|
6865
6948
|
const width = ele.offsetWidth / coordinates.scaleX;
|
|
6866
6949
|
const height = ele.offsetHeight / coordinates.scaleY;
|
|
6867
|
-
if (leader &&
|
|
6950
|
+
if (leader && angled) {
|
|
6951
|
+
// The declutter owns the side; the fit only says which one had the room to begin with.
|
|
6952
|
+
const run = Math.max(ANGLED_LEADER_RUN, radius + 4);
|
|
6953
|
+
const side = (_l = (_k = placement.textSide) !== null && _k !== void 0 ? _k : frame.leaderSide) !== null && _l !== void 0 ? _l : "right";
|
|
6954
|
+
const beside = side === "left" ? frame.anchorX - run - width : frame.anchorX + run;
|
|
6955
|
+
position.x = Math.max(0, Math.min(beside, this.viewer.canvas.clientWidth - width));
|
|
6956
|
+
}
|
|
6957
|
+
else if (leader && placement.textSide === "left") {
|
|
6868
6958
|
position.x = Math.max(0, Math.min(frame.anchorX - width, this.viewer.canvas.clientWidth - width));
|
|
6869
6959
|
}
|
|
6870
|
-
const gap = (
|
|
6960
|
+
const gap = (_o = (_m = this.options.pointerAvoidance) === null || _m === void 0 ? void 0 : _m.gap) !== null && _o !== void 0 ? _o : 12;
|
|
6871
6961
|
const containsPointer = (x, y, margin) => {
|
|
6872
6962
|
return pointer && pointer.x >= x - margin && pointer.x <= x + width + margin && pointer.y >= y - margin && pointer.y <= y + height + margin;
|
|
6873
6963
|
};
|
|
6874
6964
|
const passive = !selectOnClick || !this.visualRegister;
|
|
6875
|
-
if (passive && ((
|
|
6965
|
+
if (passive && ((_p = this.options.pointerAvoidance) === null || _p === void 0 ? void 0 : _p.enabled) !== false && pointer &&
|
|
6876
6966
|
(containsPointer(position.x, position.y, gap) || containsPointer(position.x + displacement.x, position.y + displacement.y, gap))) {
|
|
6877
6967
|
if (containsPointer(position.x + displacement.x, position.y + displacement.y, 0)) {
|
|
6878
6968
|
// Choose against the original box and retain the offset until the pointer leaves both boxes.
|
|
@@ -6890,7 +6980,7 @@
|
|
|
6890
6980
|
else {
|
|
6891
6981
|
displacement = { x: 0, y: 0 };
|
|
6892
6982
|
}
|
|
6893
|
-
const nudgeDuration = (
|
|
6983
|
+
const nudgeDuration = (_r = (_q = this.options.pointerAvoidance) === null || _q === void 0 ? void 0 : _q.transitionDuration) !== null && _r !== void 0 ? _r : 200;
|
|
6894
6984
|
const animateNudge = () => {
|
|
6895
6985
|
const progress = now < nudge.start ? 0 : nudgeDuration > 0 ? Math.min(1, (now - nudge.start) / nudgeDuration) : 1;
|
|
6896
6986
|
const eased = progress * progress * (3 - 2 * progress);
|
|
@@ -6906,7 +6996,7 @@
|
|
|
6906
6996
|
fromY: nudge.y,
|
|
6907
6997
|
targetX: displacement.x,
|
|
6908
6998
|
targetY: displacement.y,
|
|
6909
|
-
start: now + ((
|
|
6999
|
+
start: now + ((_t = (_s = this.options.pointerAvoidance) === null || _s === void 0 ? void 0 : _s.delay) !== null && _t !== void 0 ? _t : 180)
|
|
6910
7000
|
};
|
|
6911
7001
|
}
|
|
6912
7002
|
if (animateNudge() < 1 && (nudge.fromX !== nudge.targetX || nudge.fromY !== nudge.targetY)) {
|
|
@@ -6918,7 +7008,7 @@
|
|
|
6918
7008
|
ele.style.top = `${coordinates.y + position.y * coordinates.scaleY}px`;
|
|
6919
7009
|
const clickTarget = content.querySelector('[role="button"]');
|
|
6920
7010
|
if (clickTarget) {
|
|
6921
|
-
clickTarget.setAttribute("aria-label", placement.members.length ? `Select ${placement.entityIds.length} entities` : `Select ${(
|
|
7011
|
+
clickTarget.setAttribute("aria-label", placement.members.length ? `Select ${placement.entityIds.length} entities` : `Select ${(_v = (_u = this.options.text) !== null && _u !== void 0 ? _u : text) !== null && _v !== void 0 ? _v : (_w = this.rego) === null || _w === void 0 ? void 0 : _w.entityId}`);
|
|
6922
7012
|
}
|
|
6923
7013
|
if (leader) {
|
|
6924
7014
|
const nodeRadius = ringAnimation.outer;
|
|
@@ -6941,8 +7031,13 @@
|
|
|
6941
7031
|
anchor.style.opacity = String(opacity * (normalLeader ? 1 : cursorMotion.amount));
|
|
6942
7032
|
anchor.style.zIndex = String(placement.zIndex);
|
|
6943
7033
|
// The stem starts at the rim, never across the transparent centre, even after passive displacement.
|
|
6944
|
-
const
|
|
6945
|
-
const
|
|
7034
|
+
const straightX = Math.max(position.x, Math.min(frame.anchorX, position.x + width));
|
|
7035
|
+
const straightY = frame.anchorY < position.y ? position.y : frame.anchorY > position.y + height ? position.y + height : frame.anchorY;
|
|
7036
|
+
const beside = angled && (frame.anchorX < position.x || frame.anchorX > position.x + width);
|
|
7037
|
+
const elbowY = position.y + height / 2;
|
|
7038
|
+
const endX = beside ? frame.anchorX : straightX;
|
|
7039
|
+
const endY = beside ? elbowY : straightY;
|
|
7040
|
+
const runToX = frame.anchorX < position.x ? position.x : position.x + width;
|
|
6946
7041
|
const dx = endX - frame.anchorX, dy = endY - frame.anchorY;
|
|
6947
7042
|
const length = Math.hypot(dx, dy);
|
|
6948
7043
|
const leaderAngle = Math.atan2(dy, dx);
|
|
@@ -6953,13 +7048,13 @@
|
|
|
6953
7048
|
// Keep the stem inside the 126-degree arc, away from antialiased endpoints.
|
|
6954
7049
|
const arcFraction = 0.35;
|
|
6955
7050
|
const rotationLimit = Math.PI * arcFraction - Math.PI / 30;
|
|
6956
|
-
const targetOffset = hovered ? Math.max(-rotationLimit, Math.min(rotationLimit, wrappedAngle)) : ((
|
|
7051
|
+
const targetOffset = hovered ? Math.max(-rotationLimit, Math.min(rotationLimit, wrappedAngle)) : ((_x = ringAnimation.arcOffset) !== null && _x !== void 0 ? _x : 0);
|
|
6957
7052
|
const targetOpen = cursorMotion.target || (hovered && (ring === null || ring === void 0 ? void 0 : ring.enabled) !== false && targetRadius > 0) ? 1 : 0;
|
|
6958
|
-
const elapsed = Math.min(32, Math.max(0, now - ((
|
|
7053
|
+
const elapsed = Math.min(32, Math.max(0, now - ((_y = ringAnimation.arcTime) !== null && _y !== void 0 ? _y : now)));
|
|
6959
7054
|
const blend = duration > 0 ? 1 - Math.exp(-elapsed / (duration / 3)) : 1;
|
|
6960
7055
|
const approach = (value, target) => Math.abs(value - target) < 0.001 ? target : value + (target - value) * blend;
|
|
6961
|
-
ringAnimation.arcOffset = approach((
|
|
6962
|
-
ringAnimation.arcOpen = approach((
|
|
7056
|
+
ringAnimation.arcOffset = approach((_z = ringAnimation.arcOffset) !== null && _z !== void 0 ? _z : 0, targetOffset);
|
|
7057
|
+
ringAnimation.arcOpen = approach((_0 = ringAnimation.arcOpen) !== null && _0 !== void 0 ? _0 : 0, targetOpen);
|
|
6963
7058
|
ringAnimation.arcTime = now;
|
|
6964
7059
|
if (ringAnimation.arcOffset !== targetOffset || ringAnimation.arcOpen !== targetOpen) {
|
|
6965
7060
|
this.viewer.scene.requestRender();
|
|
@@ -6971,17 +7066,27 @@
|
|
|
6971
7066
|
const cut = Math.min(radius, length);
|
|
6972
7067
|
const startX = frame.anchorX + (length ? dx / length * cut : 0);
|
|
6973
7068
|
const startY = frame.anchorY + (length ? dy / length * cut : 0);
|
|
6974
|
-
const
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
6978
|
-
|
|
6979
|
-
|
|
6980
|
-
|
|
6981
|
-
|
|
6982
|
-
|
|
6983
|
-
|
|
6984
|
-
|
|
7069
|
+
const draw = (element, fromX, fromY, toX, toY) => {
|
|
7070
|
+
const screenDx = (toX - fromX) * coordinates.scaleX;
|
|
7071
|
+
const screenDy = (toY - fromY) * coordinates.scaleY;
|
|
7072
|
+
element.style.width = `${2 * coordinates.scaleX}px`;
|
|
7073
|
+
element.style.left = `${coordinates.x + (fromX - 1) * coordinates.scaleX}px`;
|
|
7074
|
+
element.style.top = `${coordinates.y + fromY * coordinates.scaleY}px`;
|
|
7075
|
+
element.style.height = `${Math.hypot(screenDx, screenDy)}px`;
|
|
7076
|
+
element.style.transform = `rotate(${Math.atan2(screenDy, screenDx) - Math.PI / 2}rad)`;
|
|
7077
|
+
element.style.boxShadow = radius ? "none" : "0 0 5px rgba(0, 0, 0, 0.3)";
|
|
7078
|
+
element.style.transformOrigin = "top center";
|
|
7079
|
+
element.style.opacity = String(opacity * (normalLeader ? 1 : cursorMotion.amount));
|
|
7080
|
+
element.style.zIndex = String(placement.zIndex);
|
|
7081
|
+
};
|
|
7082
|
+
draw(lineEle, startX, startY, endX, endY);
|
|
7083
|
+
if (runEle) {
|
|
7084
|
+
// Overlap the corner by the stem's own width so the elbow has no notch in it.
|
|
7085
|
+
const overlap = frame.anchorX < runToX ? -1 : 1;
|
|
7086
|
+
runEle.style.display = beside ? "block" : "none";
|
|
7087
|
+
if (beside)
|
|
7088
|
+
draw(runEle, endX + overlap, endY, runToX, endY);
|
|
7089
|
+
}
|
|
6985
7090
|
}
|
|
6986
7091
|
};
|
|
6987
7092
|
ele.style.display = "flex";
|
|
@@ -7006,7 +7111,7 @@
|
|
|
7006
7111
|
* Removes label from the viewer and unsubscribes from events.
|
|
7007
7112
|
*/
|
|
7008
7113
|
removeLabel() {
|
|
7009
|
-
var _a;
|
|
7114
|
+
var _a, _b;
|
|
7010
7115
|
(_a = this.anchor) === null || _a === void 0 ? void 0 : _a.remove();
|
|
7011
7116
|
this.anchor = null;
|
|
7012
7117
|
if (this.label &&
|
|
@@ -7018,6 +7123,8 @@
|
|
|
7018
7123
|
this.line.parentElement.removeChild(this.line);
|
|
7019
7124
|
this.line = null;
|
|
7020
7125
|
}
|
|
7126
|
+
(_b = this.leaderRun) === null || _b === void 0 ? void 0 : _b.remove();
|
|
7127
|
+
this.leaderRun = null;
|
|
7021
7128
|
if (this.renderRemoval) {
|
|
7022
7129
|
this.renderRemoval();
|
|
7023
7130
|
this.renderRemoval = null;
|
|
@@ -16647,9 +16754,6 @@
|
|
|
16647
16754
|
// Last date-time range taken from the clock.
|
|
16648
16755
|
this.lastDateTimeMin = null;
|
|
16649
16756
|
this.lastDateTimeMax = null;
|
|
16650
|
-
// Entity ID -> last resolved date time.
|
|
16651
|
-
// Helps determine if a slow resolved request can still be applied while we wait for the next one.
|
|
16652
|
-
this.lastFoundDateTimes = new Map();
|
|
16653
16757
|
// ID of Entity IDs that need to be requested.
|
|
16654
16758
|
this.eIdQueue = [];
|
|
16655
16759
|
// Membership mirror of eIdQueue for quick checks.
|
|
@@ -16681,8 +16785,12 @@
|
|
|
16681
16785
|
// Unsubscribes the view monitor listener that queues what the camera has moved onto.
|
|
16682
16786
|
this.monitorRemoval = null;
|
|
16683
16787
|
// Indicates a tick is active.
|
|
16684
|
-
// When true,
|
|
16788
|
+
// When true, a new tick is not started; it is noted in pendingTick and run once this one ends.
|
|
16685
16789
|
this.runningTick = false;
|
|
16790
|
+
// A tick was asked for while one was running, so another is owed once it finishes.
|
|
16791
|
+
this.pendingTick = false;
|
|
16792
|
+
// The debounce every clock change goes through, kept so a tick owed after a running one does too.
|
|
16793
|
+
this.tickDelay = null;
|
|
16686
16794
|
// Entity ID -> Entity blob.
|
|
16687
16795
|
// This is a tool that lets developers set their own JSON blobs instead of requesting data from API.
|
|
16688
16796
|
this.entityDataOverrides = new Map();
|
|
@@ -16746,11 +16854,13 @@
|
|
|
16746
16854
|
let tickDelay = new BModels.DelayQueue(() => {
|
|
16747
16855
|
this.onTick(false);
|
|
16748
16856
|
}, 250, true);
|
|
16857
|
+
this.tickDelay = tickDelay;
|
|
16749
16858
|
this.hDisposals.push(() => {
|
|
16750
16859
|
if (tickDelay) {
|
|
16751
16860
|
tickDelay.Dispose();
|
|
16752
16861
|
}
|
|
16753
16862
|
tickDelay = null;
|
|
16863
|
+
this.tickDelay = null;
|
|
16754
16864
|
});
|
|
16755
16865
|
// React to clock changes and request new Entities.
|
|
16756
16866
|
let prevTime = null;
|
|
@@ -16790,7 +16900,6 @@
|
|
|
16790
16900
|
this.priorityCount = 0;
|
|
16791
16901
|
this.lastOrderFocus = null;
|
|
16792
16902
|
this.allEIds.clear();
|
|
16793
|
-
this.lastFoundDateTimes.clear();
|
|
16794
16903
|
this.everFound.clear();
|
|
16795
16904
|
this.clearIndex();
|
|
16796
16905
|
this.lastDateTime = null;
|
|
@@ -17152,7 +17261,6 @@
|
|
|
17152
17261
|
this.eIdQueued.clear();
|
|
17153
17262
|
this.priorityCount = 0;
|
|
17154
17263
|
this.allEIds.clear();
|
|
17155
|
-
this.lastFoundDateTimes.clear();
|
|
17156
17264
|
this.everFound.clear();
|
|
17157
17265
|
this.clearIndex();
|
|
17158
17266
|
this.entityDataOverrides.clear();
|
|
@@ -17168,7 +17276,13 @@
|
|
|
17168
17276
|
}
|
|
17169
17277
|
}
|
|
17170
17278
|
onTick(force) {
|
|
17171
|
-
if (this.
|
|
17279
|
+
if (this.disposed) {
|
|
17280
|
+
return;
|
|
17281
|
+
}
|
|
17282
|
+
if (this.runningTick) {
|
|
17283
|
+
if (this.historic) {
|
|
17284
|
+
this.pendingTick = true;
|
|
17285
|
+
}
|
|
17172
17286
|
return;
|
|
17173
17287
|
}
|
|
17174
17288
|
const rTime = this.viewer.clock.currentTime.toString();
|
|
@@ -17176,10 +17290,16 @@
|
|
|
17176
17290
|
return;
|
|
17177
17291
|
}
|
|
17178
17292
|
this.lastDateTime = rTime;
|
|
17293
|
+
// Whether the clock has left the moment this tick is reading.
|
|
17294
|
+
const movedOn = () => this.historic && this.viewer.clock.currentTime.toString() !== rTime;
|
|
17179
17295
|
(async () => {
|
|
17180
17296
|
this.runningTick = true;
|
|
17297
|
+
this.pendingTick = false;
|
|
17181
17298
|
this.placeStragglers();
|
|
17182
17299
|
let rerun = false;
|
|
17300
|
+
let interrupted = false;
|
|
17301
|
+
// Batch's answer is applied while the next batch is being read.
|
|
17302
|
+
const applying = [];
|
|
17183
17303
|
try {
|
|
17184
17304
|
const handleResponse = async (requestedBatch, entities) => {
|
|
17185
17305
|
var _a, _b, _c, _d;
|
|
@@ -17243,45 +17363,7 @@
|
|
|
17243
17363
|
api: this.api
|
|
17244
17364
|
})).tags;
|
|
17245
17365
|
}
|
|
17246
|
-
|
|
17247
|
-
// 1 = rTime is in the future.
|
|
17248
|
-
// -1 = rTime is in the past.
|
|
17249
|
-
let changeDir = 0;
|
|
17250
|
-
if (this.lastDateTime !== this.viewer.clock.currentTime.toString()) {
|
|
17251
|
-
changeDir = this.lastDateTime < this.viewer.clock.currentTime.toString() ? 1 : -1;
|
|
17252
|
-
}
|
|
17253
|
-
let toEmit;
|
|
17254
|
-
if (this.historic) {
|
|
17255
|
-
// We can emit Entities if the last resolved time (per Entity) isn't newer than rTime.
|
|
17256
|
-
// We compare using the changeDir to determine if we should emit or not.
|
|
17257
|
-
toEmit = resolvedEntities.filter((e) => {
|
|
17258
|
-
var _a;
|
|
17259
|
-
const entityId = ((_a = e === null || e === void 0 ? void 0 : e.Bruce) === null || _a === void 0 ? void 0 : _a.ID) || (e === null || e === void 0 ? void 0 : e.id);
|
|
17260
|
-
const lastFoundDateTime = this.lastFoundDateTimes.get(entityId);
|
|
17261
|
-
if (lastFoundDateTime) {
|
|
17262
|
-
if (changeDir === 1) {
|
|
17263
|
-
return lastFoundDateTime <= rTime;
|
|
17264
|
-
}
|
|
17265
|
-
else if (changeDir === -1) {
|
|
17266
|
-
return lastFoundDateTime >= rTime;
|
|
17267
|
-
}
|
|
17268
|
-
}
|
|
17269
|
-
return true;
|
|
17270
|
-
});
|
|
17271
|
-
// Update the last found date times for the filtered Entities.
|
|
17272
|
-
toEmit.forEach((e) => {
|
|
17273
|
-
var _a;
|
|
17274
|
-
const entityId = ((_a = e === null || e === void 0 ? void 0 : e.Bruce) === null || _a === void 0 ? void 0 : _a.ID) || (e === null || e === void 0 ? void 0 : e.id);
|
|
17275
|
-
if (entityId) {
|
|
17276
|
-
this.lastFoundDateTimes.set(entityId, rTime);
|
|
17277
|
-
}
|
|
17278
|
-
});
|
|
17279
|
-
}
|
|
17280
|
-
else {
|
|
17281
|
-
// If we're not historic, we can just emit everything.
|
|
17282
|
-
toEmit = resolvedEntities;
|
|
17283
|
-
}
|
|
17284
|
-
this.emitEntities(toEmit, tags);
|
|
17366
|
+
this.emitEntities(resolvedEntities, tags);
|
|
17285
17367
|
};
|
|
17286
17368
|
const QUEUE_BATCH_SIZE = 500;
|
|
17287
17369
|
const requestedIds = new Set();
|
|
@@ -17290,7 +17372,8 @@
|
|
|
17290
17372
|
const total = this.eIdQueue.length;
|
|
17291
17373
|
let done = 0;
|
|
17292
17374
|
while (this.eIdQueue.length && !this.disposed) {
|
|
17293
|
-
if (
|
|
17375
|
+
if (movedOn()) {
|
|
17376
|
+
interrupted = true;
|
|
17294
17377
|
break;
|
|
17295
17378
|
}
|
|
17296
17379
|
this.orderQueueByCamera();
|
|
@@ -17306,7 +17389,7 @@
|
|
|
17306
17389
|
api: this.api,
|
|
17307
17390
|
maxSearchTimeSec: 60 * 2
|
|
17308
17391
|
});
|
|
17309
|
-
handleResponse(batch, entities);
|
|
17392
|
+
applying.push(handleResponse(batch, entities));
|
|
17310
17393
|
for (let i = 0; i < batch.length; i++) {
|
|
17311
17394
|
requestedIds.add(batch[i]);
|
|
17312
17395
|
}
|
|
@@ -17338,7 +17421,8 @@
|
|
|
17338
17421
|
// The near ones are resolved first out of whatever the view still reaches.
|
|
17339
17422
|
allEIds = this.bandIds(allEIds);
|
|
17340
17423
|
while (allEIds.length && !this.disposed && !this.eIdQueue.length) {
|
|
17341
|
-
if (
|
|
17424
|
+
if (movedOn()) {
|
|
17425
|
+
interrupted = true;
|
|
17342
17426
|
break;
|
|
17343
17427
|
}
|
|
17344
17428
|
const batch = allEIds.splice(0, QUEUE_BATCH_SIZE);
|
|
@@ -17349,7 +17433,7 @@
|
|
|
17349
17433
|
api: this.api,
|
|
17350
17434
|
maxSearchTimeSec: 60 * 2
|
|
17351
17435
|
});
|
|
17352
|
-
handleResponse(batch, entities);
|
|
17436
|
+
applying.push(handleResponse(batch, entities));
|
|
17353
17437
|
for (let i = 0; i < batch.length; i++) {
|
|
17354
17438
|
requestedIds.add(batch[i]);
|
|
17355
17439
|
}
|
|
@@ -17364,10 +17448,32 @@
|
|
|
17364
17448
|
console.error(e);
|
|
17365
17449
|
}
|
|
17366
17450
|
finally {
|
|
17451
|
+
// Only a historic answer can be overtaken by a newer moment, so nothing else waits.
|
|
17452
|
+
if (this.historic && applying.length) {
|
|
17453
|
+
await Promise.all(applying.map((pending) => pending.catch((e) => console.error(e))));
|
|
17454
|
+
}
|
|
17367
17455
|
this.runningTick = false;
|
|
17368
17456
|
}
|
|
17369
|
-
|
|
17457
|
+
// A moment read only in part is forgotten, so coming back to it reads it again in full.
|
|
17458
|
+
if (interrupted && this.lastDateTime === rTime) {
|
|
17459
|
+
this.lastDateTime = null;
|
|
17460
|
+
}
|
|
17461
|
+
if (this.disposed) {
|
|
17462
|
+
return;
|
|
17463
|
+
}
|
|
17464
|
+
// Leftovers at the same moment carry straight on, as they always have.
|
|
17465
|
+
if (rerun && !interrupted) {
|
|
17370
17466
|
this.onTick(true);
|
|
17467
|
+
return;
|
|
17468
|
+
}
|
|
17469
|
+
if (interrupted || this.pendingTick || movedOn()) {
|
|
17470
|
+
this.pendingTick = false;
|
|
17471
|
+
if (this.tickDelay) {
|
|
17472
|
+
this.tickDelay.Call();
|
|
17473
|
+
}
|
|
17474
|
+
else {
|
|
17475
|
+
this.onTick(false);
|
|
17476
|
+
}
|
|
17371
17477
|
}
|
|
17372
17478
|
})();
|
|
17373
17479
|
}
|
|
@@ -48962,7 +49068,7 @@ void main() {
|
|
|
48962
49068
|
}
|
|
48963
49069
|
EntityRenderEngine.GetGraphicShapeId = GetGraphicShapeId;
|
|
48964
49070
|
async function Render(params) {
|
|
48965
|
-
var _a, _b, _c;
|
|
49071
|
+
var _a, _b, _c, _d, _e;
|
|
48966
49072
|
const groupRenderParams = {
|
|
48967
49073
|
apiGetter: params.apiGetter,
|
|
48968
49074
|
viewer: params.viewer,
|
|
@@ -49139,10 +49245,20 @@ void main() {
|
|
|
49139
49245
|
polygons.push(entity);
|
|
49140
49246
|
continue;
|
|
49141
49247
|
}
|
|
49248
|
+
// Present when the gate above chose to reuse this entity's graphic.
|
|
49249
|
+
const existingRoot = cEntities.get(entity.Bruce.ID);
|
|
49250
|
+
const existingParts = new Map();
|
|
49251
|
+
(_d = existingRoot === null || existingRoot === void 0 ? void 0 : existingRoot._siblingGraphics) === null || _d === void 0 ? void 0 : _d.forEach((part) => {
|
|
49252
|
+
if (part._multiPartIndex != null) {
|
|
49253
|
+
existingParts.set(part._multiPartIndex, part);
|
|
49254
|
+
}
|
|
49255
|
+
});
|
|
49256
|
+
const partRendered = new Map();
|
|
49257
|
+
const partIndexes = new Map();
|
|
49142
49258
|
const pParams = {
|
|
49143
49259
|
...groupRenderParams,
|
|
49144
49260
|
entities: [],
|
|
49145
|
-
rendered:
|
|
49261
|
+
rendered: partRendered
|
|
49146
49262
|
};
|
|
49147
49263
|
pParams.entitiesHistoric = params.entitiesHistoric;
|
|
49148
49264
|
const zoomItem = pParams.zoomItems[entity.Bruce.ID];
|
|
@@ -49158,39 +49274,59 @@ void main() {
|
|
|
49158
49274
|
};
|
|
49159
49275
|
pParams.zoomItems[subEntity.Bruce.ID] = zoomItem;
|
|
49160
49276
|
pParams.entities.push(subEntity);
|
|
49161
|
-
|
|
49162
|
-
|
|
49163
|
-
|
|
49164
|
-
|
|
49165
|
-
|
|
49166
|
-
|
|
49167
|
-
|
|
49168
|
-
|
|
49169
|
-
|
|
49170
|
-
|
|
49171
|
-
|
|
49277
|
+
partIndexes.set(subEntity.Bruce.ID, j);
|
|
49278
|
+
const existingPart = existingParts.get(j);
|
|
49279
|
+
if (existingPart) {
|
|
49280
|
+
// An engine preparing a reused graphic gathers everything connected to it, so a part still
|
|
49281
|
+
// attached to its root would have every other part evicted from the scene.
|
|
49282
|
+
existingPart._parentEntity = null;
|
|
49283
|
+
partRendered.set(subEntity.Bruce.ID, existingPart);
|
|
49284
|
+
}
|
|
49285
|
+
}
|
|
49286
|
+
const rendered = [];
|
|
49287
|
+
const collect = (results) => {
|
|
49288
|
+
results.forEach((cEntity, key) => {
|
|
49289
|
+
if (!cEntity) {
|
|
49290
|
+
return;
|
|
49291
|
+
}
|
|
49292
|
+
cEntity._multiPartIndex = partIndexes.get(key);
|
|
49293
|
+
rendered.push(cEntity);
|
|
49172
49294
|
pParams.entities = pParams.entities.filter((e) => e.Bruce.ID != key);
|
|
49173
|
-
}
|
|
49174
|
-
}
|
|
49175
|
-
|
|
49295
|
+
});
|
|
49296
|
+
};
|
|
49297
|
+
collect(await Polygon.RenderGroup(pParams));
|
|
49298
|
+
collect(await Polyline.RenderGroup(pParams));
|
|
49176
49299
|
// We'll only render points when there's no other geometry.
|
|
49177
49300
|
// Generally speaking when polygons/polylines are drawn, points are only drawn because of invalid data.
|
|
49178
49301
|
if (!rendered.length) {
|
|
49179
|
-
|
|
49180
|
-
rendered = rendered.concat(Array.from(cPoints.values()));
|
|
49302
|
+
collect(await Point.RenderGroup(pParams));
|
|
49181
49303
|
}
|
|
49182
|
-
rendered = rendered.filter(x => x != null);
|
|
49183
49304
|
if (rendered.length) {
|
|
49184
|
-
const
|
|
49185
|
-
|
|
49186
|
-
|
|
49187
|
-
|
|
49305
|
+
const sameParts = ((_e = existingRoot === null || existingRoot === void 0 ? void 0 : existingRoot._siblingGraphics) === null || _e === void 0 ? void 0 : _e.length) == rendered.length &&
|
|
49306
|
+
rendered.every((part) => existingRoot._siblingGraphics.includes(part));
|
|
49307
|
+
let rootEntity;
|
|
49308
|
+
if (sameParts) {
|
|
49309
|
+
rootEntity = existingRoot;
|
|
49310
|
+
}
|
|
49311
|
+
else {
|
|
49312
|
+
if (existingRoot === null || existingRoot === void 0 ? void 0 : existingRoot._siblingGraphics) {
|
|
49313
|
+
// Retiring the old root removes its parts, and the ones carried over belong to the new root now.
|
|
49314
|
+
existingRoot._siblingGraphics = existingRoot._siblingGraphics.filter((part) => !rendered.includes(part));
|
|
49315
|
+
}
|
|
49316
|
+
rootEntity = new Cesium.Entity({
|
|
49317
|
+
id: BModels.ObjectUtils.UId(15)
|
|
49318
|
+
});
|
|
49319
|
+
}
|
|
49320
|
+
rootEntity._siblingGraphics = rendered;
|
|
49188
49321
|
rootEntity._renderGroup = GetRenderGroupId(zoomItem);
|
|
49189
|
-
|
|
49322
|
+
// The skip gate compares the rego's style against the zoom item's, and the rego takes it from here.
|
|
49323
|
+
rootEntity.styleId = (zoomItem === null || zoomItem === void 0 ? void 0 : zoomItem.StyleID) == -1 ? -1 : (+(zoomItem === null || zoomItem === void 0 ? void 0 : zoomItem.StyleID) || null);
|
|
49324
|
+
rootEntity.styleEffective = rendered[0].styleEffective;
|
|
49190
49325
|
cEntities.set(entity.Bruce.ID, rootEntity);
|
|
49191
|
-
const
|
|
49192
|
-
|
|
49193
|
-
|
|
49326
|
+
const newPosition = GetCValue(params.viewer, rendered[0].position);
|
|
49327
|
+
const oldPosition = GetCValue(params.viewer, rootEntity.position);
|
|
49328
|
+
if (newPosition && (!oldPosition || !BModels.Cartes.IsEqualCartes3(oldPosition, newPosition))) {
|
|
49329
|
+
rootEntity.position = new Cesium.ConstantPositionProperty(newPosition);
|
|
49194
49330
|
}
|
|
49195
49331
|
rendered.forEach((child) => {
|
|
49196
49332
|
child._parentEntity = rootEntity;
|
|
@@ -50124,7 +50260,7 @@ void main() {
|
|
|
50124
50260
|
StyleUtils.ApplyTypeStyle = ApplyTypeStyle;
|
|
50125
50261
|
})(exports.StyleUtils || (exports.StyleUtils = {}));
|
|
50126
50262
|
|
|
50127
|
-
const VERSION = "7.4.
|
|
50263
|
+
const VERSION = "7.4.3";
|
|
50128
50264
|
/**
|
|
50129
50265
|
* Updates the environment instance used by bruce-cesium to one specified.
|
|
50130
50266
|
* This can be used to ensure that the instance a parent is referencing is shared between bruce-cesium, bruce-models, and the parent app.
|