bruce-cesium 7.4.4 → 7.4.6

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.
Files changed (36) hide show
  1. package/dist/bruce-cesium.es5.js +307 -36
  2. package/dist/bruce-cesium.es5.js.map +1 -1
  3. package/dist/bruce-cesium.umd.js +305 -34
  4. package/dist/bruce-cesium.umd.js.map +1 -1
  5. package/dist/lib/bruce-cesium.js +1 -1
  6. package/dist/lib/rendering/cesium-animated-property.js +16 -1
  7. package/dist/lib/rendering/cesium-animated-property.js.map +1 -1
  8. package/dist/lib/rendering/entity-render-engine-model3d.js +2 -1
  9. package/dist/lib/rendering/entity-render-engine-model3d.js.map +1 -1
  10. package/dist/lib/rendering/render-managers/common/entity-label.js +28 -4
  11. package/dist/lib/rendering/render-managers/common/entity-label.js.map +1 -1
  12. package/dist/lib/rendering/render-managers/entities/entities-loaded-render-manager.js +12 -4
  13. package/dist/lib/rendering/render-managers/entities/entities-loaded-render-manager.js.map +1 -1
  14. package/dist/lib/rendering/render-managers/entities/entities-render-manager.js +12 -4
  15. package/dist/lib/rendering/render-managers/entities/entities-render-manager.js.map +1 -1
  16. package/dist/lib/rendering/render-managers/tilesets/tileset-arb-render-manager.js +35 -2
  17. package/dist/lib/rendering/render-managers/tilesets/tileset-arb-render-manager.js.map +1 -1
  18. package/dist/lib/rendering/render-managers/tilesets/tileset-cad-render-manager.js +36 -3
  19. package/dist/lib/rendering/render-managers/tilesets/tileset-cad-render-manager.js.map +1 -1
  20. package/dist/lib/rendering/render-managers/tilesets/tileset-entities-render-manager.js +36 -3
  21. package/dist/lib/rendering/render-managers/tilesets/tileset-entities-render-manager.js.map +1 -1
  22. package/dist/lib/rendering/render-managers/tilesets/tileset-google-photos-render-manager.js +19 -0
  23. package/dist/lib/rendering/render-managers/tilesets/tileset-google-photos-render-manager.js.map +1 -1
  24. package/dist/lib/rendering/render-managers/tilesets/tileset-osm-render-manager.js +55 -2
  25. package/dist/lib/rendering/render-managers/tilesets/tileset-osm-render-manager.js.map +1 -1
  26. package/dist/lib/rendering/visuals-register.js +48 -9
  27. package/dist/lib/rendering/visuals-register.js.map +1 -1
  28. package/dist/lib/utils/cesium-entity-styler.js +5 -0
  29. package/dist/lib/utils/cesium-entity-styler.js.map +1 -1
  30. package/dist/types/bruce-cesium.d.ts +1 -1
  31. package/dist/types/rendering/render-managers/tilesets/tileset-arb-render-manager.d.ts +1 -0
  32. package/dist/types/rendering/render-managers/tilesets/tileset-cad-render-manager.d.ts +1 -0
  33. package/dist/types/rendering/render-managers/tilesets/tileset-entities-render-manager.d.ts +1 -0
  34. package/dist/types/rendering/render-managers/tilesets/tileset-google-photos-render-manager.d.ts +1 -0
  35. package/dist/types/rendering/render-managers/tilesets/tileset-osm-render-manager.d.ts +2 -0
  36. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  import * as Cesium from 'cesium';
2
- import { Cartographic, ColorMaterialProperty, Entity, Color, ConstantProperty, CallbackProperty, Primitive, Cesium3DTileFeature, Math as Math$1, Cartesian3, JulianDate, Quaternion, Transforms, HeadingPitchRoll, HeightReference, Matrix4, ColorBlendMode, ShadowMode, ClassificationType, Model, HorizontalOrigin, VerticalOrigin, ConstantPositionProperty, ArcType, CornerType, DistanceDisplayCondition, ShaderSource, Ellipsoid, Geometry, GeometryAttribute, ComponentDatatype, PrimitiveType, BoundingSphere, GeometryPipeline, Cartesian2, Cartesian4, sampleTerrain, Texture, PixelFormat, Sampler, TextureWrap, TextureMinificationFilter, TextureMagnificationFilter, VertexArray, BufferUsage, ShaderProgram, RenderState, BlendingState, DrawCommand, Pass, ImageMaterialProperty, PolygonHierarchy, PolylineGraphics, Rectangle, SceneTransforms, FeatureDetection, NearFarScalar, Matrix3, KmlDataSource, GeoJsonDataSource, SceneMode, Cesium3DTileStyle, Cesium3DTileColorBlendMode, HeadingPitchRange, Ion, IonResource, Cesium3DTileset, EllipsoidTerrainProvider, IonImageryProvider, createWorldImagery, createWorldImageryAsync, BingMapsImageryProvider, BingMapsStyle, MapboxImageryProvider, MapboxStyleImageryProvider, ArcGisMapServerImageryProvider, OpenStreetMapImageryProvider, UrlTemplateImageryProvider, GridImageryProvider, GeographicTilingScheme, ImageryLayer, TileMapServiceImageryProvider, CesiumTerrainProvider, OrthographicFrustum, EasingFunction, CustomDataSource, PolygonPipeline, EllipsoidGeodesic, sampleTerrainMostDetailed, defined, ModelGraphics, PolygonGraphics, CorridorGraphics, PointGraphics, BillboardGraphics, EllipseGraphics, PolylineDashMaterialProperty, Intersect, GeometryInstance, CesiumInspector, ClockRange, DynamicEnvironmentMapManager, ScreenSpaceEventHandler, ScreenSpaceEventType, Fullscreen, CzmlDataSource } from 'cesium';
3
- import { Cartes, LRUCache, ProjectViewTile, ENVIRONMENT, Calculator, ClientFile, Entity as Entity$1, EntityLod, EntityTag, EntityType, ObjectUtils, Style, Api, Carto, Geometry as Geometry$1, ClientFileValueMap, Color as Color$1, Bounds, MenuItem, ProjectView, ProjectViewBookmark, Tileset, ZoomControl, BruceEvent, EntityCoords, DataLab, DelayQueue, AccountConcept, RecordChangeFeed, BruceApi, EntityRelation, EntitySource, ProgramKey, ProjectViewLegacyTile, Camera, Account, AccountLimits, Session, UrlUtils, EntityAttachment, EntityAttachmentType, EntityAttribute, MathUtils, ProjectViewBookmarkGroup, EntityRelationType, EntityHistoricData } from 'bruce-models';
2
+ import { Cartographic, ColorMaterialProperty, Entity, Color, ConstantProperty, CallbackProperty, Primitive, Cesium3DTileFeature, ConstantPositionProperty, HeightReference, DistanceDisplayCondition, Math as Math$1, Cartesian3, JulianDate, Quaternion, Transforms, HeadingPitchRoll, Matrix4, HorizontalOrigin, VerticalOrigin, ClassificationType, ArcType, CornerType, ShadowMode, ColorBlendMode, Model, Ellipsoid, Cartesian2, SceneTransforms, ShaderSource, Geometry, GeometryAttribute, ComponentDatatype, PrimitiveType, BoundingSphere, GeometryPipeline, Cartesian4, sampleTerrain, Texture, PixelFormat, Sampler, TextureWrap, TextureMinificationFilter, TextureMagnificationFilter, VertexArray, BufferUsage, ShaderProgram, RenderState, BlendingState, DrawCommand, Pass, FeatureDetection, ImageMaterialProperty, PolygonHierarchy, PolylineGraphics, Rectangle, NearFarScalar, Matrix3, KmlDataSource, GeoJsonDataSource, SceneMode, HeadingPitchRange, Ion, IonResource, Cesium3DTileStyle, Cesium3DTileColorBlendMode, Cesium3DTileset, EllipsoidTerrainProvider, IonImageryProvider, createWorldImagery, createWorldImageryAsync, BingMapsImageryProvider, BingMapsStyle, MapboxImageryProvider, MapboxStyleImageryProvider, ArcGisMapServerImageryProvider, OpenStreetMapImageryProvider, UrlTemplateImageryProvider, GridImageryProvider, GeographicTilingScheme, ImageryLayer, TileMapServiceImageryProvider, CesiumTerrainProvider, OrthographicFrustum, EasingFunction, EllipsoidGeodesic, sampleTerrainMostDetailed, defined, Intersect, PolygonPipeline, ModelGraphics, PolygonGraphics, CorridorGraphics, PointGraphics, BillboardGraphics, EllipseGraphics, PolylineDashMaterialProperty, CustomDataSource, GeometryInstance, ScreenSpaceEventHandler, ScreenSpaceEventType, CesiumInspector, ClockRange, DynamicEnvironmentMapManager, Fullscreen, CzmlDataSource } from 'cesium';
3
+ import { Cartes, LRUCache, ProjectViewTile, ENVIRONMENT, Api, Calculator, ClientFile, Entity as Entity$1, EntityTag, EntityType, ObjectUtils, Style, Carto, Geometry as Geometry$1, EntityLod, BruceEvent, EntityCoords, MenuItem, Tileset, ClientFileValueMap, Color as Color$1, ProjectView, ProjectViewBookmark, ZoomControl, Bounds, DataLab, DelayQueue, AccountConcept, EntityRelation, BruceApi, RecordChangeFeed, ProgramKey, ProjectViewLegacyTile, EntitySource, Camera, Account, AccountLimits, Session, UrlUtils, ProjectViewBookmarkGroup, EntityAttachment, EntityAttachmentType, EntityAttribute, MathUtils, EntityRelationType, EntityHistoricData } from 'bruce-models';
4
4
 
5
5
  /**
6
6
  * Ensures a number is returned from a given value.
@@ -1517,6 +1517,7 @@ function getPosition(viewer, obj) {
1517
1517
  * @returns
1518
1518
  */
1519
1519
  function isFeatureAlive(viewer, feature) {
1520
+ var _a, _b;
1520
1521
  if (!(viewer === null || viewer === void 0 ? void 0 : viewer.scene) || viewer.isDestroyed()) {
1521
1522
  return false;
1522
1523
  }
@@ -1527,6 +1528,10 @@ function isFeatureAlive(viewer, feature) {
1527
1528
  if (cTileset.isDestroyed() || !viewer.scene.primitives.contains(cTileset)) {
1528
1529
  return false;
1529
1530
  }
1531
+ // A tile unloads its content while the tileset lives on, and the feature's colour is then unreadable.
1532
+ if (feature._bruceUnloaded || ((_b = (_a = feature.content) === null || _a === void 0 ? void 0 : _a.isDestroyed) === null || _b === void 0 ? void 0 : _b.call(_a))) {
1533
+ return false;
1534
+ }
1530
1535
  return true;
1531
1536
  }
1532
1537
  let _lastMark = 0;
@@ -1717,7 +1722,17 @@ var CesiumAnimatedProperty;
1717
1722
  removal = null;
1718
1723
  return;
1719
1724
  }
1720
- if (!assertColorMark(mark, feature.color)) {
1725
+ // A throw here is inside Cesium's frame and stops rendering, so an unreadable feature ends the animation.
1726
+ let current;
1727
+ try {
1728
+ current = feature.color;
1729
+ }
1730
+ catch (e) {
1731
+ removal === null || removal === void 0 ? void 0 : removal();
1732
+ removal = null;
1733
+ return;
1734
+ }
1735
+ if (!assertColorMark(mark, current)) {
1721
1736
  removal === null || removal === void 0 ? void 0 : removal();
1722
1737
  removal = null;
1723
1738
  onDone === null || onDone === void 0 ? void 0 : onDone();
@@ -2936,6 +2951,7 @@ var CesiumAnimatedProperty;
2936
2951
  * @returns
2937
2952
  */
2938
2953
  function isAlive(viewer, visual) {
2954
+ var _a, _b;
2939
2955
  if (!(viewer === null || viewer === void 0 ? void 0 : viewer.scene) || viewer.isDestroyed()) {
2940
2956
  return false;
2941
2957
  }
@@ -2953,6 +2969,10 @@ function isAlive(viewer, visual) {
2953
2969
  if (cTileset.isDestroyed() || !viewer.scene.primitives.contains(cTileset)) {
2954
2970
  return false;
2955
2971
  }
2972
+ // Its tile unloaded, so reading or writing the feature's colour throws.
2973
+ if (visual._bruceUnloaded || ((_b = (_a = visual.content) === null || _a === void 0 ? void 0 : _a.isDestroyed) === null || _b === void 0 ? void 0 : _b.call(_a))) {
2974
+ return false;
2975
+ }
2956
2976
  return true;
2957
2977
  }
2958
2978
  return false;
@@ -5805,6 +5825,8 @@ var EntityLabel;
5805
5825
  this.element = document.createElement("div");
5806
5826
  this.coordinates = { x: 0, y: 0, scaleX: 1, scaleY: 1 };
5807
5827
  this.participants = new Set();
5828
+ // Participants whose failure has been logged, so a label that throws every frame logs once.
5829
+ this.failed = new WeakSet();
5808
5830
  this.placementMemory = new PlacementMemory();
5809
5831
  this.forwardingWheel = false;
5810
5832
  this.pendingDrag = null;
@@ -6005,15 +6027,35 @@ var EntityLabel;
6005
6027
  x: (pointer.x - rect.left) * this.viewer.canvas.clientWidth / rect.width,
6006
6028
  y: (pointer.y - rect.top) * this.viewer.canvas.clientHeight / rect.height
6007
6029
  } : undefined;
6030
+ // This runs inside Cesium's frame, where one throwing label would stop rendering for the whole scene.
6008
6031
  const projected = new Map();
6009
6032
  for (const participant of this.participants) {
6010
- projected.set(participant, participant.project());
6033
+ let frame = null;
6034
+ try {
6035
+ frame = participant.project();
6036
+ }
6037
+ catch (e) {
6038
+ this.logFailure(participant, e);
6039
+ }
6040
+ projected.set(participant, frame);
6011
6041
  }
6012
6042
  const placements = new Map(Layout(Array.from(projected.values()).filter(Boolean), this.placementMemory).map(item => [item.frame.id, item]));
6013
6043
  for (const [participant, frame] of projected) {
6014
- participant.apply(frame ? placements.get(frame.id) : undefined);
6044
+ try {
6045
+ participant.apply(frame ? placements.get(frame.id) : undefined);
6046
+ }
6047
+ catch (e) {
6048
+ this.logFailure(participant, e);
6049
+ }
6015
6050
  }
6016
6051
  }
6052
+ logFailure(participant, error) {
6053
+ if (this.failed.has(participant)) {
6054
+ return;
6055
+ }
6056
+ this.failed.add(participant);
6057
+ console.error("EntityLabel: a label failed to update and is skipped this frame.", error);
6058
+ }
6017
6059
  }
6018
6060
  let nextLabelId = 0;
6019
6061
  class Label {
@@ -6749,8 +6791,10 @@ var EntityLabel;
6749
6791
  const relative = Cartesian3.subtract(this._pos3d, cameraPosition, new Cartesian3());
6750
6792
  const depth = Cartesian3.dot(relative, camera.directionWC || camera.direction);
6751
6793
  const distance = Cartesian3.magnitude(relative);
6794
+ // If we're labelling from a temp label (mouse hover) don't drive opacity by cam distance.
6795
+ const hoverOnly = this.Transient && !this.Persistent;
6752
6796
  if (!Number.isFinite(distance) || depth <= 0 || distance < ((_c = this.options.near) !== null && _c !== void 0 ? _c : 0) ||
6753
- distance > ((_d = this.options.far) !== null && _d !== void 0 ? _d : Infinity) || (!this.prePositioned && distance >= MAX_DISTANCE)) {
6797
+ distance > ((_d = this.options.far) !== null && _d !== void 0 ? _d : Infinity) || (!this.prePositioned && !hoverOnly && distance >= MAX_DISTANCE)) {
6754
6798
  return null;
6755
6799
  }
6756
6800
  const transforms = SceneTransforms;
@@ -6879,7 +6923,7 @@ var EntityLabel;
6879
6923
  return null;
6880
6924
  }
6881
6925
  const state = (_p = this.visualRegister) === null || _p === void 0 ? void 0 : _p.GetState({ entityId: (_q = this.rego) === null || _q === void 0 ? void 0 : _q.entityId, menuItemId: (_r = this.rego) === null || _r === void 0 ? void 0 : _r.menuItemId });
6882
- const opacity = this.prePositioned || MAX_DISTANCE === Infinity ? 1 : 1 - distance / MAX_DISTANCE;
6926
+ const opacity = this.prePositioned || hoverOnly || MAX_DISTANCE === Infinity ? 1 : 1 - distance / MAX_DISTANCE;
6883
6927
  return {
6884
6928
  canFlip: leader && presentation !== "icon", hasLeader: leader,
6885
6929
  textWrapped: ((sourceNaturalText === null || sourceNaturalText === void 0 ? void 0 : sourceNaturalText.offsetWidth) || 0) > TEXT_MAX_WIDTH,
@@ -9283,6 +9327,7 @@ var VisualRegisterCuller;
9283
9327
  })(VisualRegisterCuller || (VisualRegisterCuller = {}));
9284
9328
 
9285
9329
  function isTilesetFeatureAlive(visual) {
9330
+ var _a, _b;
9286
9331
  const cTileset = visual === null || visual === void 0 ? void 0 : visual.tileset;
9287
9332
  if (!cTileset) {
9288
9333
  return false;
@@ -9293,8 +9338,32 @@ function isTilesetFeatureAlive(visual) {
9293
9338
  else if (visual.primitive && visual.primitive.isDestroyed()) {
9294
9339
  return false;
9295
9340
  }
9341
+ // A tile unloads its content while the tileset lives on, and every read through the feature then throws.
9342
+ else if (visual._bruceUnloaded || ((_b = (_a = visual.content) === null || _a === void 0 ? void 0 : _a.isDestroyed) === null || _b === void 0 ? void 0 : _b.call(_a))) {
9343
+ return false;
9344
+ }
9296
9345
  return true;
9297
9346
  }
9347
+ /*
9348
+ * Returns if a visual is currently shown, reading a tileset feature only while its tile is loaded.
9349
+ */
9350
+ function isVisualShown(visual) {
9351
+ if (!visual) {
9352
+ return true;
9353
+ }
9354
+ if (visual instanceof Cesium3DTileFeature) {
9355
+ if (!isTilesetFeatureAlive(visual)) {
9356
+ return false;
9357
+ }
9358
+ try {
9359
+ return visual.show !== false;
9360
+ }
9361
+ catch (e) {
9362
+ return false;
9363
+ }
9364
+ }
9365
+ return visual.show !== false;
9366
+ }
9298
9367
  /**
9299
9368
  * Returns if a given visual is alive and in the scene.
9300
9369
  * @param viewer
@@ -9302,6 +9371,7 @@ function isTilesetFeatureAlive(visual) {
9302
9371
  * @returns
9303
9372
  */
9304
9373
  function isAlive$1(viewer, visual) {
9374
+ var _a, _b;
9305
9375
  if (!(viewer === null || viewer === void 0 ? void 0 : viewer.scene) || viewer.isDestroyed()) {
9306
9376
  return false;
9307
9377
  }
@@ -9322,6 +9392,10 @@ function isAlive$1(viewer, visual) {
9322
9392
  else if (visual.primitive && visual.primitive.isDestroyed()) {
9323
9393
  return false;
9324
9394
  }
9395
+ // Its tile unloaded, so every read through the feature throws.
9396
+ else if (visual._bruceUnloaded || ((_b = (_a = visual.content) === null || _a === void 0 ? void 0 : _a.isDestroyed) === null || _b === void 0 ? void 0 : _b.call(_a))) {
9397
+ return false;
9398
+ }
9325
9399
  return true;
9326
9400
  }
9327
9401
  return false;
@@ -9784,6 +9858,13 @@ var VisualsRegister;
9784
9858
  // Adding is asynchronous, so ordering has to wait until it is actually in the collection.
9785
9859
  Promise.resolve(this.viewer.dataSources.add(source))
9786
9860
  .then(() => {
9861
+ // Released or disposed before the add landed, when the remove found nothing to take out.
9862
+ if (this.menuItemSources.get(menuItemId) !== record) {
9863
+ if (!this.viewer.isDestroyed() && this.viewer.dataSources.contains(source)) {
9864
+ this.viewer.dataSources.remove(source, true);
9865
+ }
9866
+ return;
9867
+ }
9787
9868
  record.added = true;
9788
9869
  this.applySourceOrder();
9789
9870
  })
@@ -9820,7 +9901,9 @@ var VisualsRegister;
9820
9901
  if (this.disposed || !this.sourceOrderDirty || !((_a = this.viewer) === null || _a === void 0 ? void 0 : _a.dataSources)) {
9821
9902
  return;
9822
9903
  }
9823
- const records = Array.from(this.menuItemSources.values()).filter(x => x.added);
9904
+ // raiseToTop throws for a source the collection does not hold.
9905
+ const dataSources = this.viewer.dataSources;
9906
+ const records = Array.from(this.menuItemSources.values()).filter(x => x.added && dataSources.contains(x.source));
9824
9907
  if (records.length < 2) {
9825
9908
  // Nothing to order against yet, so leave the flag set for when there is.
9826
9909
  return;
@@ -9830,7 +9913,7 @@ var VisualsRegister;
9830
9913
  records.sort((a, b) => a.maxZIndex - b.maxZIndex);
9831
9914
  for (const record of records) {
9832
9915
  try {
9833
- this.viewer.dataSources.raiseToTop(record.source);
9916
+ dataSources.raiseToTop(record.source);
9834
9917
  }
9835
9918
  catch (e) {
9836
9919
  console.error(e);
@@ -12170,7 +12253,7 @@ var VisualsRegister;
12170
12253
  return (hover === null || hover === void 0 ? void 0 : hover.entityId) === entityId && (hover.menuItemId == null || hover.menuItemId === menuItemId) ? hover.position : undefined;
12171
12254
  }
12172
12255
  SyncLabelHover() {
12173
- var _a, _b, _c, _d;
12256
+ var _a, _b, _c;
12174
12257
  const hover = this.labelHover;
12175
12258
  if (!hover || this.disposed) {
12176
12259
  return;
@@ -12195,7 +12278,7 @@ var VisualsRegister;
12195
12278
  }
12196
12279
  const existing = rego && EntityLabel.GetLabel({ rego });
12197
12280
  const state = this.GetState(hover);
12198
- if ((!rego && !group) || state.hidden || ((_b = rego === null || rego === void 0 ? void 0 : rego.visual) === null || _b === void 0 ? void 0 : _b.show) === false ||
12281
+ if ((!rego && !group) || state.hidden || ((rego === null || rego === void 0 ? void 0 : rego.visual) && !isVisualShown(rego.visual)) ||
12199
12282
  (this.GetIsIsolatedAny() && !state.isolated && this.GetIsolationOpacity() == null) ||
12200
12283
  (existing && existing !== this.hoverLabel && existing.HasText) ||
12201
12284
  (group && group.options.presentation !== "icon")) {
@@ -12207,7 +12290,7 @@ var VisualsRegister;
12207
12290
  return;
12208
12291
  }
12209
12292
  // Query-only icon groups have coordinates but no registered scene visual to attach to.
12210
- if (!rego && group && [group.item.longitude, group.item.latitude, (_c = group.item.altitude) !== null && _c !== void 0 ? _c : 0].every(Number.isFinite)) {
12293
+ if (!rego && group && [group.item.longitude, group.item.latitude, (_b = group.item.altitude) !== null && _b !== void 0 ? _b : 0].every(Number.isFinite)) {
12211
12294
  rego = {
12212
12295
  entityId: hover.entityId,
12213
12296
  menuItemId: hover.menuItemId,
@@ -12229,7 +12312,7 @@ var VisualsRegister;
12229
12312
  rego,
12230
12313
  viewer: this.viewer,
12231
12314
  visualRegister: this,
12232
- api: (_d = this.ApiGetters) === null || _d === void 0 ? void 0 : _d.GetBruceApi(),
12315
+ api: (_c = this.ApiGetters) === null || _c === void 0 ? void 0 : _c.GetBruceApi(),
12233
12316
  persistent: false,
12234
12317
  transient: true,
12235
12318
  hoverRingState: this.hoverRingState,
@@ -12239,10 +12322,10 @@ var VisualsRegister;
12239
12322
  selectOnClick: false
12240
12323
  },
12241
12324
  visible: () => {
12242
- var _a, _b;
12325
+ var _a;
12243
12326
  const current = this.GetState(hover);
12244
- return (!this.disposed && !current.hidden && ((_a = rego.visual) === null || _a === void 0 ? void 0 : _a.show) !== false &&
12245
- Boolean(this.GetRego(hover) || ((_b = this.labelGroups) === null || _b === void 0 ? void 0 : _b.Has(hover.entityId, hover.menuItemId))) &&
12327
+ return (!this.disposed && !current.hidden && isVisualShown(rego.visual) &&
12328
+ Boolean(this.GetRego(hover) || ((_a = this.labelGroups) === null || _a === void 0 ? void 0 : _a.Has(hover.entityId, hover.menuItemId))) &&
12246
12329
  (!this.GetIsIsolatedAny() || current.isolated || this.GetIsolationOpacity() != null));
12247
12330
  }
12248
12331
  };
@@ -14862,12 +14945,20 @@ var EntitiesRenderManager;
14862
14945
  strokeWidth: lineWidthPx,
14863
14946
  clampToGround: lineWidthPx <= 0 && polygonsClamped
14864
14947
  });
14865
- this.viewer.dataSources.add(source);
14866
- this.sources.push(source);
14867
- if (this.disposed) {
14868
- this.doDispose();
14948
+ // Dispose already cleared what was added before this, and this one has not been added.
14949
+ if (this.disposed || this.viewer.isDestroyed()) {
14869
14950
  return;
14870
14951
  }
14952
+ const viewer = this.viewer;
14953
+ this.sources.push(source);
14954
+ // The add lands asynchronously, so a dispose in between removes nothing and would orphan the source.
14955
+ Promise.resolve(viewer.dataSources.add(source)).then(() => {
14956
+ if (this.disposed && !viewer.isDestroyed() && viewer.dataSources.contains(source)) {
14957
+ viewer.dataSources.remove(source);
14958
+ }
14959
+ }).catch((e) => {
14960
+ console.error(e);
14961
+ });
14871
14962
  const groups = [];
14872
14963
  /**
14873
14964
  * Applies individual styling to a rendered entity.
@@ -15909,12 +16000,20 @@ var EntitiesLoadedRenderManager;
15909
16000
  strokeWidth: lineWidthPx,
15910
16001
  clampToGround: lineWidthPx <= 0 && polygonsClamped
15911
16002
  });
15912
- this.viewer.dataSources.add(source);
15913
- this.sources.push(source);
15914
- if (this.disposed) {
15915
- this.doDispose();
16003
+ // Dispose already cleared what was added before this, and this one has not been added.
16004
+ if (this.disposed || this.viewer.isDestroyed()) {
15916
16005
  return;
15917
16006
  }
16007
+ const viewer = this.viewer;
16008
+ this.sources.push(source);
16009
+ // The add lands asynchronously, so a dispose in between removes nothing and would orphan the source.
16010
+ Promise.resolve(viewer.dataSources.add(source)).then(() => {
16011
+ if (this.disposed && !viewer.isDestroyed() && viewer.dataSources.contains(source)) {
16012
+ viewer.dataSources.remove(source);
16013
+ }
16014
+ }).catch((e) => {
16015
+ console.error(e);
16016
+ });
15918
16017
  const groups = [];
15919
16018
  /**
15920
16019
  * Applies individual styling to a rendered entity.
@@ -19609,7 +19708,7 @@ var TilesetCadRenderManager;
19609
19708
  });
19610
19709
  this.tileUnloadRemoval = cTileset.tileUnload.addEventListener((tile) => {
19611
19710
  try {
19612
- this.queueTile(tile, false);
19711
+ this.unloadTile(tile);
19613
19712
  }
19614
19713
  catch (e) {
19615
19714
  console.error(e);
@@ -19793,7 +19892,7 @@ var TilesetCadRenderManager;
19793
19892
  });
19794
19893
  this.tileUnloadRemoval = this.cTileset.tileUnload.addEventListener((tile) => {
19795
19894
  try {
19796
- this.queueTile(tile, false);
19895
+ this.unloadTile(tile);
19797
19896
  }
19798
19897
  catch (e) {
19799
19898
  console.error(e);
@@ -19858,6 +19957,35 @@ var TilesetCadRenderManager;
19858
19957
  }
19859
19958
  this.pingFeatureQueue();
19860
19959
  }
19960
+ /*
19961
+ * Removes a tile's regos and marks its features dead, while the tile's content can still be read.
19962
+ */
19963
+ unloadTile(tile) {
19964
+ const content = tile === null || tile === void 0 ? void 0 : tile.content;
19965
+ if (!content) {
19966
+ return;
19967
+ }
19968
+ const features = [];
19969
+ for (let i = 0; i < content.featuresLength; i++) {
19970
+ const feature = content.getFeature(i);
19971
+ // Drops a load still queued for it, the batch skips anything marked.
19972
+ this.featureQueueStates.delete(feature);
19973
+ feature._bruceUnloaded = true;
19974
+ features.push(feature);
19975
+ }
19976
+ if (!features.length) {
19977
+ return;
19978
+ }
19979
+ const { removedEntityIds } = this.visualsManager.RemoveRegosByVisuals({
19980
+ visuals: features,
19981
+ requestRender: false,
19982
+ menuItemId: this.item.id,
19983
+ doRemove: false
19984
+ });
19985
+ for (const entityId of removedEntityIds) {
19986
+ delete this.loadedCesiumEntities[entityId];
19987
+ }
19988
+ }
19861
19989
  /**
19862
19990
  * Pings the feature queue to process any queued features.
19863
19991
  * Does nothing if we're already processing.
@@ -19874,7 +20002,7 @@ var TilesetCadRenderManager;
19874
20002
  return;
19875
20003
  }
19876
20004
  this.processFeatureQueueBatch();
19877
- if (!this.featureQueue) {
20005
+ if (!this.featureQueue.length) {
19878
20006
  clearInterval(this.featureQueueInterval);
19879
20007
  this.featureQueueInterval = null;
19880
20008
  }
@@ -19906,6 +20034,10 @@ var TilesetCadRenderManager;
19906
20034
  const regosToStyle = new Map();
19907
20035
  const featuresToRemove = [];
19908
20036
  for (const feature of batch) {
20037
+ // Its tile unloaded while it waited, unloadTile already removed whatever it registered.
20038
+ if (feature._bruceUnloaded) {
20039
+ continue;
20040
+ }
19909
20041
  const load = this.featureQueueStates.get(feature);
19910
20042
  this.featureQueueStates.delete(feature);
19911
20043
  if (!load) {
@@ -23078,6 +23210,7 @@ var TilesetOsmRenderManager;
23078
23210
  this.processingQueue = 0;
23079
23211
  this._osmIdToBruceId = {};
23080
23212
  this.tileLoadRemoval = null;
23213
+ this.tileUnloadRemoval = null;
23081
23214
  const { viewer, register: visualsManager, getters: apiGetter, monitor, item } = params;
23082
23215
  this.viewer = viewer;
23083
23216
  this.getters = apiGetter;
@@ -23086,7 +23219,7 @@ var TilesetOsmRenderManager;
23086
23219
  this.monitor = monitor;
23087
23220
  }
23088
23221
  Dispose() {
23089
- var _a;
23222
+ var _a, _b;
23090
23223
  if (this.disposed) {
23091
23224
  return;
23092
23225
  }
@@ -23094,6 +23227,8 @@ var TilesetOsmRenderManager;
23094
23227
  clearInterval(this.queueCheckInterval);
23095
23228
  (_a = this.tileLoadRemoval) === null || _a === void 0 ? void 0 : _a.call(this);
23096
23229
  this.tileLoadRemoval = null;
23230
+ (_b = this.tileUnloadRemoval) === null || _b === void 0 ? void 0 : _b.call(this);
23231
+ this.tileUnloadRemoval = null;
23097
23232
  if (this.cTileset) {
23098
23233
  const viewer = this.viewer;
23099
23234
  if (!(viewer === null || viewer === void 0 ? void 0 : viewer.isDestroyed()) && this.viewer.scene.primitives.contains(this.cTileset)) {
@@ -23189,6 +23324,14 @@ var TilesetOsmRenderManager;
23189
23324
  console.error(e);
23190
23325
  }
23191
23326
  });
23327
+ this.tileUnloadRemoval = this.cTileset.tileUnload.addEventListener((tile) => {
23328
+ try {
23329
+ this.unloadTile(tile);
23330
+ }
23331
+ catch (e) {
23332
+ console.error(e);
23333
+ }
23334
+ });
23192
23335
  this.queueCheckInterval = setInterval(() => {
23193
23336
  if (this.featureQueue.length > 0) {
23194
23337
  this.processQueue();
@@ -23225,6 +23368,34 @@ var TilesetOsmRenderManager;
23225
23368
  this.processQueue();
23226
23369
  }
23227
23370
  }
23371
+ /*
23372
+ * Removes a tile's regos and marks its features dead, while the tile's content can still be read.
23373
+ */
23374
+ unloadTile(tile) {
23375
+ const content = tile === null || tile === void 0 ? void 0 : tile.content;
23376
+ if (!content) {
23377
+ return;
23378
+ }
23379
+ const features = [];
23380
+ for (let i = 0; i < content.featuresLength; i++) {
23381
+ const feature = content.getFeature(i);
23382
+ feature._bruceUnloaded = true;
23383
+ features.push(feature);
23384
+ }
23385
+ if (!features.length) {
23386
+ return;
23387
+ }
23388
+ this.featureQueue = this.featureQueue.filter(x => !x._bruceUnloaded);
23389
+ const { removedEntityIds } = this.visualsManager.RemoveRegosByVisuals({
23390
+ visuals: features,
23391
+ requestRender: false,
23392
+ menuItemId: this.item.id,
23393
+ doRemove: false
23394
+ });
23395
+ for (const entityId of removedEntityIds) {
23396
+ delete this._loadedCesiumEntities[entityId];
23397
+ }
23398
+ }
23228
23399
  async processQueue() {
23229
23400
  if (this.processingQueue >= MAX_BATCHES) {
23230
23401
  return;
@@ -23357,6 +23528,10 @@ var TilesetOsmRenderManager;
23357
23528
  bruceId = ObjectUtils.UId();
23358
23529
  }
23359
23530
  const feature = featureMap[i];
23531
+ // Its tile unloaded while the ID lookup was in flight.
23532
+ if (feature._bruceUnloaded) {
23533
+ continue;
23534
+ }
23360
23535
  if (this.item.ghostLoading == true) {
23361
23536
  feature.color = feature._orgColor;
23362
23537
  }
@@ -23448,7 +23623,7 @@ var TilesetOsmRenderManager;
23448
23623
  return `osm:${sourceId}:${entityTypeId}`;
23449
23624
  }
23450
23625
  PrepareHandoff() {
23451
- var _a;
23626
+ var _a, _b;
23452
23627
  if (this.disposed || !this.cTileset || this.cTileset.isDestroyed()) {
23453
23628
  return null;
23454
23629
  }
@@ -23456,6 +23631,8 @@ var TilesetOsmRenderManager;
23456
23631
  this.queueCheckInterval = null;
23457
23632
  (_a = this.tileLoadRemoval) === null || _a === void 0 ? void 0 : _a.call(this);
23458
23633
  this.tileLoadRemoval = null;
23634
+ (_b = this.tileUnloadRemoval) === null || _b === void 0 ? void 0 : _b.call(this);
23635
+ this.tileUnloadRemoval = null;
23459
23636
  const payload = {
23460
23637
  cTileset: this.cTileset,
23461
23638
  loadedCesiumEntities: this._loadedCesiumEntities,
@@ -23503,6 +23680,14 @@ var TilesetOsmRenderManager;
23503
23680
  console.error(e);
23504
23681
  }
23505
23682
  });
23683
+ this.tileUnloadRemoval = this.cTileset.tileUnload.addEventListener((tile) => {
23684
+ try {
23685
+ this.unloadTile(tile);
23686
+ }
23687
+ catch (e) {
23688
+ console.error(e);
23689
+ }
23690
+ });
23506
23691
  this.queueCheckInterval = setInterval(() => {
23507
23692
  if (this.featureQueue.length > 0) {
23508
23693
  this.processQueue();
@@ -23693,7 +23878,7 @@ var TilesetEntitiesRenderManager;
23693
23878
  });
23694
23879
  this.tileUnloadRemoval = cTileset.tileUnload.addEventListener((tile) => {
23695
23880
  try {
23696
- this.queueTile(tile, false);
23881
+ this.unloadTile(tile);
23697
23882
  }
23698
23883
  catch (e) {
23699
23884
  console.error(e);
@@ -23739,6 +23924,35 @@ var TilesetEntitiesRenderManager;
23739
23924
  }
23740
23925
  this.pingFeatureQueue();
23741
23926
  }
23927
+ /*
23928
+ * Removes a tile's regos and marks its features dead, while the tile's content can still be read.
23929
+ */
23930
+ unloadTile(tile) {
23931
+ const content = tile === null || tile === void 0 ? void 0 : tile.content;
23932
+ if (!content) {
23933
+ return;
23934
+ }
23935
+ const features = [];
23936
+ for (let i = 0; i < content.featuresLength; i++) {
23937
+ const feature = content.getFeature(i);
23938
+ // Drops a load still queued for it, the batch skips anything marked.
23939
+ this.featureQueueStates.delete(feature);
23940
+ feature._bruceUnloaded = true;
23941
+ features.push(feature);
23942
+ }
23943
+ if (!features.length) {
23944
+ return;
23945
+ }
23946
+ const { removedEntityIds } = this.visualsManager.RemoveRegosByVisuals({
23947
+ visuals: features,
23948
+ requestRender: false,
23949
+ menuItemId: this.item.id,
23950
+ doRemove: false
23951
+ });
23952
+ for (const entityId of removedEntityIds) {
23953
+ delete this.loadedCesiumEntities[entityId];
23954
+ }
23955
+ }
23742
23956
  /**
23743
23957
  * Pings the feature queue to process any queued features.
23744
23958
  * Does nothing if we're already processing.
@@ -23755,7 +23969,7 @@ var TilesetEntitiesRenderManager;
23755
23969
  return;
23756
23970
  }
23757
23971
  this.processFeatureQueueBatch();
23758
- if (!this.featureQueue) {
23972
+ if (!this.featureQueue.length) {
23759
23973
  clearInterval(this.featureQueueInterval);
23760
23974
  this.featureQueueInterval = null;
23761
23975
  }
@@ -23773,6 +23987,10 @@ var TilesetEntitiesRenderManager;
23773
23987
  const regosToStyle = new Map();
23774
23988
  const featuresToRemove = [];
23775
23989
  for (const feature of batch) {
23990
+ // Its tile unloaded while it waited, unloadTile already removed whatever it registered.
23991
+ if (feature._bruceUnloaded) {
23992
+ continue;
23993
+ }
23776
23994
  const load = this.featureQueueStates.get(feature);
23777
23995
  this.featureQueueStates.delete(feature);
23778
23996
  if (!load) {
@@ -23978,7 +24196,7 @@ var TilesetEntitiesRenderManager;
23978
24196
  });
23979
24197
  this.tileUnloadRemoval = this.cTileset.tileUnload.addEventListener((tile) => {
23980
24198
  try {
23981
- this.queueTile(tile, false);
24199
+ this.unloadTile(tile);
23982
24200
  }
23983
24201
  catch (e) {
23984
24202
  console.error(e);
@@ -24939,7 +25157,7 @@ var TilesetArbRenderManager;
24939
25157
  });
24940
25158
  this.cTileset.tileUnload.addEventListener((tile) => {
24941
25159
  try {
24942
- this.queueTile(tile, false);
25160
+ this.unloadTile(tile);
24943
25161
  }
24944
25162
  catch (e) {
24945
25163
  console.error(e);
@@ -24967,6 +25185,35 @@ var TilesetArbRenderManager;
24967
25185
  }
24968
25186
  this.pingFeatureQueue();
24969
25187
  }
25188
+ /*
25189
+ * Removes a tile's regos and marks its features dead, while the tile's content can still be read.
25190
+ */
25191
+ unloadTile(tile) {
25192
+ const content = tile === null || tile === void 0 ? void 0 : tile.content;
25193
+ if (!content) {
25194
+ return;
25195
+ }
25196
+ const features = [];
25197
+ for (let i = 0; i < content.featuresLength; i++) {
25198
+ const feature = content.getFeature(i);
25199
+ // Drops a load still queued for it, the batch skips anything marked.
25200
+ this.featureQueueStates.delete(feature);
25201
+ feature._bruceUnloaded = true;
25202
+ features.push(feature);
25203
+ }
25204
+ if (!features.length) {
25205
+ return;
25206
+ }
25207
+ const { removedEntityIds } = this.visualsManager.RemoveRegosByVisuals({
25208
+ visuals: features,
25209
+ requestRender: false,
25210
+ menuItemId: this.item.id,
25211
+ doRemove: false
25212
+ });
25213
+ for (const entityId of removedEntityIds) {
25214
+ delete this.loadedCesiumEntities[entityId];
25215
+ }
25216
+ }
24970
25217
  /**
24971
25218
  * Pings the feature queue to process any queued features.
24972
25219
  * Does nothing if we're already processing.
@@ -24983,7 +25230,7 @@ var TilesetArbRenderManager;
24983
25230
  return;
24984
25231
  }
24985
25232
  this.processFeatureQueueBatch();
24986
- if (!this.featureQueue) {
25233
+ if (!this.featureQueue.length) {
24987
25234
  clearInterval(this.featureQueueInterval);
24988
25235
  this.featureQueueInterval = null;
24989
25236
  }
@@ -25001,6 +25248,10 @@ var TilesetArbRenderManager;
25001
25248
  const regosToStyle = new Map();
25002
25249
  const featuresToRemove = [];
25003
25250
  for (const feature of batch) {
25251
+ // Its tile unloaded while it waited, unloadTile already removed whatever it registered.
25252
+ if (feature._bruceUnloaded) {
25253
+ continue;
25254
+ }
25004
25255
  const load = this.featureQueueStates.get(feature);
25005
25256
  this.featureQueueStates.delete(feature);
25006
25257
  if (!load) {
@@ -25619,6 +25870,8 @@ var TilesetGooglePhotosRenderManager;
25619
25870
  constructor(params) {
25620
25871
  this.disposed = false;
25621
25872
  this.cTileset = null;
25873
+ // Set while a tileset is being created, so a second Init in the meantime cannot add another.
25874
+ this.initializing = false;
25622
25875
  const { viewer, item, getters } = params;
25623
25876
  this.viewer = viewer;
25624
25877
  this.item = item;
@@ -25639,6 +25892,10 @@ var TilesetGooglePhotosRenderManager;
25639
25892
  this.viewer.scene.primitives.remove(this.cTileset);
25640
25893
  this.viewer.scene.requestRender();
25641
25894
  }
25895
+ // Disposed before it was added, so nothing else will ever destroy it.
25896
+ else if (!this.cTileset.isDestroyed()) {
25897
+ this.cTileset.destroy();
25898
+ }
25642
25899
  this.cTileset = null;
25643
25900
  }
25644
25901
  }
@@ -25657,6 +25914,11 @@ var TilesetGooglePhotosRenderManager;
25657
25914
  this.viewer.scene.requestRender();
25658
25915
  return;
25659
25916
  }
25917
+ // The creation in flight applies the latest item's colour mask when it lands.
25918
+ if (this.initializing) {
25919
+ return;
25920
+ }
25921
+ this.initializing = true;
25660
25922
  try {
25661
25923
  const api = this.getters.GetBruceApi();
25662
25924
  await api.Loading;
@@ -25742,6 +26004,14 @@ var TilesetGooglePhotosRenderManager;
25742
26004
  console.error("Failed to load Google Photorealistic 3D tileset:", e);
25743
26005
  return;
25744
26006
  }
26007
+ finally {
26008
+ this.initializing = false;
26009
+ }
26010
+ // Creation can come back empty, and the viewer can go while it loads.
26011
+ if (this.disposed || !this.cTileset || this.cTileset.isDestroyed() || !this.viewer || this.viewer.isDestroyed()) {
26012
+ this.doDispose();
26013
+ return;
26014
+ }
25745
26015
  this.viewer.scene.primitives.add(this.cTileset);
25746
26016
  this.applyColorMask();
25747
26017
  this.viewer.scene.requestRender();
@@ -43232,7 +43502,8 @@ var EntityRenderEngineModel3d;
43232
43502
  const hpr = new HeadingPitchRoll(Math$1.toRadians(heading), Math$1.toRadians(pitch), Math$1.toRadians(roll));
43233
43503
  getOrient = new CallbackProperty(() => {
43234
43504
  const currentPos = position ? GetCValue(params.viewer, position) : pos3d;
43235
- return Transforms.headingPitchRollQuaternion(currentPos, hpr);
43505
+ // A live position can read as null mid-update, and throwing here would stop Cesium's frame.
43506
+ return Transforms.headingPitchRollQuaternion(currentPos || pos3d, hpr);
43236
43507
  }, false);
43237
43508
  }
43238
43509
  cEntity = new Entity({
@@ -50572,7 +50843,7 @@ var StyleUtils;
50572
50843
  StyleUtils.ApplyTypeStyle = ApplyTypeStyle;
50573
50844
  })(StyleUtils || (StyleUtils = {}));
50574
50845
 
50575
- const VERSION = "7.4.4";
50846
+ const VERSION = "7.4.6";
50576
50847
  /**
50577
50848
  * Updates the environment instance used by bruce-cesium to one specified.
50578
50849
  * This can be used to ensure that the instance a parent is referencing is shared between bruce-cesium, bruce-models, and the parent app.