bruce-cesium 7.3.0 → 7.3.2

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.
@@ -1,6 +1,6 @@
1
1
  import * as Cesium from 'cesium';
2
- import { Cartographic, ColorMaterialProperty, Entity, Color, ConstantProperty, CallbackProperty, Primitive, Cesium3DTileFeature, DistanceDisplayCondition, Math as Math$1, Cartesian3, JulianDate, Quaternion, Transforms, HeadingPitchRoll, Matrix4, HeightReference, ColorBlendMode, ShadowMode, ClassificationType, Model, ShaderSource, Ellipsoid, Geometry, GeometryAttribute, ComponentDatatype, PrimitiveType, BoundingSphere, GeometryPipeline, sampleTerrain, Texture, PixelFormat, Sampler, TextureWrap, TextureMinificationFilter, TextureMagnificationFilter, VertexArray, BufferUsage, ShaderProgram, RenderState, BlendingState, DrawCommand, Pass, Cartesian2, Cartesian4, ArcType, CornerType, ConstantPositionProperty, HorizontalOrigin, VerticalOrigin, ImageMaterialProperty, PolygonHierarchy, PolylineGraphics, Rectangle, SceneTransforms, NearFarScalar, Matrix3, KmlDataSource, SceneMode, GeoJsonDataSource, Cesium3DTileStyle, HeadingPitchRange, Ion, IonResource, Cesium3DTileColorBlendMode, Cesium3DTileset, EllipsoidTerrainProvider, IonImageryProvider, createWorldImagery, createWorldImageryAsync, BingMapsImageryProvider, BingMapsStyle, MapboxImageryProvider, MapboxStyleImageryProvider, ArcGisMapServerImageryProvider, OpenStreetMapImageryProvider, UrlTemplateImageryProvider, GridImageryProvider, GeographicTilingScheme, ImageryLayer, TileMapServiceImageryProvider, CesiumTerrainProvider, Intersect, ModelGraphics, PolygonGraphics, CorridorGraphics, PointGraphics, BillboardGraphics, EllipseGraphics, PolylineDashMaterialProperty, OrthographicFrustum, EasingFunction, EllipsoidGeodesic, sampleTerrainMostDetailed, defined, PolygonPipeline, CustomDataSource, GeometryInstance, CesiumInspector, ClockRange, DynamicEnvironmentMapManager, ScreenSpaceEventHandler, ScreenSpaceEventType, Fullscreen, CzmlDataSource } from 'cesium';
3
- import { Cartes, Entity as Entity$1, ProjectViewTile, ENVIRONMENT, Calculator, ClientFile, EntityLod, EntityTag, EntityType, LRUCache, ObjectUtils, Style, Carto, Geometry as Geometry$1, Api, MenuItem, ProjectView, ProjectViewBookmark, Tileset, ZoomControl, ClientFileValueMap, Color as Color$1, BruceEvent, EntityCoords, Bounds, DelayQueue, DataLab, BruceApi, EntityRelation, EntitySource, AccountConcept, RecordChangeFeed, ProgramKey, ProjectViewLegacyTile, Camera, Account, AccountLimits, Session, UrlUtils, ProjectViewBookmarkGroup, EntityAttachment, EntityAttachmentType, EntityAttribute, MathUtils, EntityRelationType, EntityHistoricData } from 'bruce-models';
2
+ import { Cartographic, ColorMaterialProperty, Entity, Color, ConstantProperty, CallbackProperty, Primitive, Cesium3DTileFeature, DistanceDisplayCondition, ShaderSource, Cartesian3, Math as Math$1, Ellipsoid, Transforms, Matrix4, Geometry, GeometryAttribute, ComponentDatatype, PrimitiveType, BoundingSphere, GeometryPipeline, sampleTerrain, Texture, PixelFormat, Sampler, TextureWrap, TextureMinificationFilter, TextureMagnificationFilter, VertexArray, BufferUsage, ShaderProgram, RenderState, BlendingState, DrawCommand, Pass, Cartesian2, Cartesian4, JulianDate, Quaternion, HeadingPitchRoll, ClassificationType, ArcType, HeightReference, CornerType, ShadowMode, ConstantPositionProperty, HorizontalOrigin, VerticalOrigin, ColorBlendMode, Model, SceneTransforms, ImageMaterialProperty, PolygonHierarchy, PolylineGraphics, Rectangle, NearFarScalar, Matrix3, KmlDataSource, GeoJsonDataSource, SceneMode, Cesium3DTileStyle, HeadingPitchRange, Cesium3DTileColorBlendMode, Ion, IonResource, Cesium3DTileset, EllipsoidTerrainProvider, IonImageryProvider, createWorldImagery, createWorldImageryAsync, BingMapsImageryProvider, BingMapsStyle, MapboxImageryProvider, MapboxStyleImageryProvider, ArcGisMapServerImageryProvider, OpenStreetMapImageryProvider, UrlTemplateImageryProvider, GridImageryProvider, GeographicTilingScheme, ImageryLayer, TileMapServiceImageryProvider, CesiumTerrainProvider, Intersect, OrthographicFrustum, EasingFunction, ModelGraphics, PolygonGraphics, CorridorGraphics, PointGraphics, BillboardGraphics, EllipseGraphics, PolylineDashMaterialProperty, EllipsoidGeodesic, sampleTerrainMostDetailed, defined, PolygonPipeline, CustomDataSource, CesiumInspector, ClockRange, DynamicEnvironmentMapManager, GeometryInstance, ScreenSpaceEventHandler, ScreenSpaceEventType, Fullscreen, CzmlDataSource } from 'cesium';
3
+ import { Cartes, Entity as Entity$1, ProjectViewTile, ENVIRONMENT, Calculator, Carto, EntityTag, EntityType, Geometry as Geometry$1, ObjectUtils, Style, Api, ClientFile, LRUCache, EntityLod, ClientFileValueMap, Color as Color$1, Bounds, MenuItem, ProjectView, ProjectViewBookmark, Tileset, ZoomControl, BruceEvent, EntityCoords, DataLab, DelayQueue, BruceApi, AccountConcept, RecordChangeFeed, EntityRelation, EntitySource, ProgramKey, ProjectViewLegacyTile, 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.
@@ -6591,7 +6591,7 @@ function shouldCullEntity(viewer, cEntity) {
6591
6591
  const adjustedSphere = boundingSphere.sphere.clone();
6592
6592
  // Terrain only matters here because it moves the sphere onto the ground.
6593
6593
  // Far enough away that a plausible ground height is a rounding error against the viewing distance, sampling it is wasted work.
6594
- const cameraDistance = Cartesian3.distance(camera.position, adjustedSphere.center);
6594
+ const cameraDistance = Cartesian3.distance(camera.positionWC, adjustedSphere.center);
6595
6595
  if (cameraDistance > TERRAIN_SKIP_DISTANCE) {
6596
6596
  adjustedSphere.radius += TERRAIN_SKIP_RADIUS_PAD;
6597
6597
  }
@@ -6604,7 +6604,8 @@ function shouldCullEntity(viewer, cEntity) {
6604
6604
  }
6605
6605
  adjustedSphere.center = grounded;
6606
6606
  }
6607
- const cullingVolume = camera.frustum.computeCullingVolume(camera.position, camera.direction, camera.up);
6607
+ // Camera vectors are frame relative while a reference frame is set (the compass orbits via lookAt).
6608
+ const cullingVolume = camera.frustum.computeCullingVolume(camera.positionWC, camera.directionWC, camera.upWC);
6608
6609
  const visibility = cullingVolume.computeVisibility(adjustedSphere);
6609
6610
  return visibility !== Intersect.INSIDE && visibility !== Intersect.INTERSECTING;
6610
6611
  }
@@ -6631,14 +6632,14 @@ function shouldRecheck(viewer) {
6631
6632
  return true;
6632
6633
  }
6633
6634
  const camera = viewer.scene.camera;
6634
- if (!((_a = camera === null || camera === void 0 ? void 0 : camera.position) === null || _a === void 0 ? void 0 : _a.x)) {
6635
+ if (!((_a = camera === null || camera === void 0 ? void 0 : camera.positionWC) === null || _a === void 0 ? void 0 : _a.x)) {
6635
6636
  return false;
6636
6637
  }
6637
6638
  const lastRecheck = camera[LAST_RECHECK_KEY];
6638
6639
  if (!lastRecheck) {
6639
6640
  camera[LAST_RECHECK_KEY] = {
6640
- position: camera.position.clone(),
6641
- direction: camera.direction.clone(),
6641
+ position: camera.positionWC.clone(),
6642
+ direction: camera.directionWC.clone(),
6642
6643
  tilesLoading: viewer.scene.globe.tilesLoaded
6643
6644
  };
6644
6645
  return true;
@@ -6647,14 +6648,14 @@ function shouldRecheck(viewer) {
6647
6648
  const tilesLoadingDiff = lastRecheck.tilesLoading != viewer.scene.globe.tilesLoaded;
6648
6649
  let recheck = tilesLoadingDiff;
6649
6650
  if (!recheck) {
6650
- const posDiff = Cartesian3.magnitude(Cartesian3.subtract(position, camera.position, new Cartesian3()));
6651
- const dirDiff = Cartesian3.magnitude(Cartesian3.subtract(direction, camera.direction, new Cartesian3()));
6651
+ const posDiff = Cartesian3.magnitude(Cartesian3.subtract(position, camera.positionWC, new Cartesian3()));
6652
+ const dirDiff = Cartesian3.magnitude(Cartesian3.subtract(direction, camera.directionWC, new Cartesian3()));
6652
6653
  recheck = posDiff > 100 || dirDiff > 0.01;
6653
6654
  }
6654
6655
  if (recheck) {
6655
6656
  camera[LAST_RECHECK_KEY] = {
6656
- position: camera.position.clone(),
6657
- direction: camera.direction.clone(),
6657
+ position: camera.positionWC.clone(),
6658
+ direction: camera.directionWC.clone(),
6658
6659
  tilesLoading: viewer.scene.globe.tilesLoaded
6659
6660
  };
6660
6661
  }
@@ -6707,7 +6708,9 @@ function cullTilesets(register) {
6707
6708
  return;
6708
6709
  }
6709
6710
  const camera = viewer.scene.camera;
6710
- const cullingVolume = camera.frustum.computeCullingVolume(camera.position, camera.direction, camera.up);
6711
+ // Camera vectors are frame relative while a reference frame is set (the compass orbits via lookAt).
6712
+ // These spheres are world space, so only the world coordinate vectors compare against them correctly.
6713
+ const cullingVolume = camera.frustum.computeCullingVolume(camera.positionWC, camera.directionWC, camera.upWC);
6711
6714
  let changed = false;
6712
6715
  for (const rego of tilesets) {
6713
6716
  const tileset = rego.tileset;
@@ -9132,12 +9135,13 @@ var VisualsRegister;
9132
9135
  ReassignMenuItem(params) {
9133
9136
  var _a;
9134
9137
  const { fromMenuItemId, toMenuItemId, toMenuItemType, toPriority, requestRender, source, lazy, onBatch, onComplete } = params;
9138
+ const noop = () => { };
9135
9139
  if (!fromMenuItemId || !toMenuItemId || fromMenuItemId === toMenuItemId) {
9136
- return;
9140
+ return noop;
9137
9141
  }
9138
9142
  const entityIds = this.entityIdsByMenuItem[fromMenuItemId];
9139
9143
  if (!entityIds) {
9140
- return;
9144
+ return noop;
9141
9145
  }
9142
9146
  const idsSnapshot = Array.from(entityIds);
9143
9147
  const regoSnapshot = new Map();
@@ -9148,7 +9152,7 @@ var VisualsRegister;
9148
9152
  }
9149
9153
  }
9150
9154
  const reassignOne = (entityId) => {
9151
- var _a, _b;
9155
+ var _a, _b, _c;
9152
9156
  const regos = this.rego[entityId];
9153
9157
  if (!regos) {
9154
9158
  return null;
@@ -9167,6 +9171,7 @@ var VisualsRegister;
9167
9171
  }
9168
9172
  rego.menuItemId = toMenuItemId;
9169
9173
  rego.menuItemType = toMenuItemType;
9174
+ const priorityChanged = toPriority != null && rego.priority !== toPriority;
9170
9175
  if (toPriority != null) {
9171
9176
  rego.priority = toPriority;
9172
9177
  }
@@ -9192,15 +9197,17 @@ var VisualsRegister;
9192
9197
  }
9193
9198
  this.unindexMenuItemEntityIfAbsent(fromMenuItemId, entityId);
9194
9199
  this.indexMenuItemEntity(toMenuItemId, entityId);
9195
- this.queueUpdate({
9196
- entityId,
9197
- refresh: true
9198
- });
9200
+ // Don't queue if no register-level visual changes are required.
9201
+ if (priorityChanged || ((_c = this.states[entityId]) === null || _c === void 0 ? void 0 : _c[toMenuItemId])) {
9202
+ this.queueUpdate({
9203
+ entityId,
9204
+ refresh: true
9205
+ });
9206
+ }
9199
9207
  return rego;
9200
9208
  };
9201
9209
  if (lazy) {
9202
- this.startLazyReassign(idsSnapshot, reassignOne, requestRender, onBatch, onComplete);
9203
- return;
9210
+ return this.startLazyReassign(idsSnapshot, reassignOne, requestRender, onBatch, onComplete);
9204
9211
  }
9205
9212
  for (const entityId of idsSnapshot) {
9206
9213
  reassignOne(entityId);
@@ -9208,17 +9215,12 @@ var VisualsRegister;
9208
9215
  if (requestRender != false) {
9209
9216
  this.viewer.scene.requestRender();
9210
9217
  }
9218
+ return noop;
9211
9219
  }
9212
9220
  startLazyReassign(entityIds, reassignOne, requestRender, onBatch, onComplete) {
9213
9221
  const BATCH_SIZE = 5000;
9214
9222
  let index = 0;
9215
- const interval = setInterval(() => {
9216
- if (this.Disposed) {
9217
- clearInterval(interval);
9218
- this.activeChunkedIntervals.delete(interval);
9219
- return;
9220
- }
9221
- const end = Math.min(index + BATCH_SIZE, entityIds.length);
9223
+ const runTo = (end) => {
9222
9224
  const batch = [];
9223
9225
  for (; index < end; index++) {
9224
9226
  const rego = reassignOne(entityIds[index]);
@@ -9232,6 +9234,14 @@ var VisualsRegister;
9232
9234
  if (requestRender != false) {
9233
9235
  this.viewer.scene.requestRender();
9234
9236
  }
9237
+ };
9238
+ const interval = setInterval(() => {
9239
+ if (this.Disposed) {
9240
+ clearInterval(interval);
9241
+ this.activeChunkedIntervals.delete(interval);
9242
+ return;
9243
+ }
9244
+ runTo(Math.min(index + BATCH_SIZE, entityIds.length));
9235
9245
  if (index >= entityIds.length) {
9236
9246
  clearInterval(interval);
9237
9247
  this.activeChunkedIntervals.delete(interval);
@@ -9239,6 +9249,14 @@ var VisualsRegister;
9239
9249
  }
9240
9250
  }, 10);
9241
9251
  this.activeChunkedIntervals.add(interval);
9252
+ return (finishRemaining) => {
9253
+ clearInterval(interval);
9254
+ this.activeChunkedIntervals.delete(interval);
9255
+ if (finishRemaining && !this.Disposed) {
9256
+ runTo(entityIds.length);
9257
+ onComplete === null || onComplete === void 0 ? void 0 : onComplete();
9258
+ }
9259
+ };
9242
9260
  }
9243
9261
  /**
9244
9262
  * Locates a visual corresponding to a given entity id.
@@ -9361,7 +9379,7 @@ var VisualsRegister;
9361
9379
  }
9362
9380
  }
9363
9381
  const removeOne = (entityId) => {
9364
- var _a;
9382
+ var _a, _b;
9365
9383
  const entityRegos = this.rego[entityId];
9366
9384
  if (!entityRegos) {
9367
9385
  return;
@@ -9400,15 +9418,24 @@ var VisualsRegister;
9400
9418
  if (source !== EUpdateSource.TREE_CASCADE) {
9401
9419
  (_a = this.onUpdate) === null || _a === void 0 ? void 0 : _a.Trigger(update);
9402
9420
  }
9403
- if (doesInclude) {
9421
+ // Only worth refreshing while the Entity is still drawn by something else, since
9422
+ // losing this rego can change which of the survivors wins. With none left there is
9423
+ // nothing to restyle, and queueing one per removed Entity is what turns disabling a
9424
+ // large menu item into minutes of scheduled work.
9425
+ if (doesInclude && ((_b = this.rego[entityId]) === null || _b === void 0 ? void 0 : _b.length)) {
9404
9426
  this.queueUpdate({
9405
9427
  entityId: entityId,
9406
9428
  refresh: false
9407
9429
  });
9408
9430
  }
9409
9431
  };
9432
+ const finish = () => {
9433
+ this.releaseMenuItemCollection(menuItemId);
9434
+ this.RemoveTilesetsByMenuItem(menuItemId);
9435
+ onComplete === null || onComplete === void 0 ? void 0 : onComplete();
9436
+ };
9410
9437
  if (lazy) {
9411
- this.startLazyRemoval(entityIds, removeOne, onComplete);
9438
+ this.startLazyRemoval(entityIds, removeOne, finish);
9412
9439
  return;
9413
9440
  }
9414
9441
  WithSuspendedCCollections(this.allSceneCollections(), () => {
@@ -9416,8 +9443,7 @@ var VisualsRegister;
9416
9443
  removeOne(entityId);
9417
9444
  }
9418
9445
  });
9419
- this.releaseMenuItemCollection(menuItemId);
9420
- this.RemoveTilesetsByMenuItem(menuItemId);
9446
+ finish();
9421
9447
  }
9422
9448
  else if (entityId) {
9423
9449
  const entityRegos = this.rego[entityId];
@@ -14409,6 +14435,14 @@ class EntityGatherer {
14409
14435
  this.disposed = true;
14410
14436
  this.hDisposals.forEach((d) => d());
14411
14437
  this.hDisposals = [];
14438
+ // A tick still awaiting a response resumes after this, and anything left here would have it
14439
+ // ask for the whole set again on the way out.
14440
+ this.eIdQueue = [];
14441
+ this.eIdQueued.clear();
14442
+ this.priorityCount = 0;
14443
+ this.allEIds.clear();
14444
+ this.lastFoundDateTimes.clear();
14445
+ this.entityDataOverrides.clear();
14412
14446
  }
14413
14447
  checkRange(force) {
14414
14448
  const min = this.viewer.clock.startTime.toString();
@@ -14421,7 +14455,7 @@ class EntityGatherer {
14421
14455
  }
14422
14456
  }
14423
14457
  onTick(force) {
14424
- if (this.runningTick) {
14458
+ if (this.runningTick || this.disposed) {
14425
14459
  return;
14426
14460
  }
14427
14461
  const rTime = this.viewer.clock.currentTime.toString();
@@ -16226,9 +16260,12 @@ var TilesetCadRenderManager;
16226
16260
  // Removal callbacks for this instance's own tile stream listeners.
16227
16261
  this.tileLoadRemoval = null;
16228
16262
  this.tileUnloadRemoval = null;
16229
- // Chunks AdoptHandoff()'s restyle of handed-off content across ticks instead of one
16230
- // synchronous pass over potentially millions of regos.
16231
- this.handoffRestyleInterval = null;
16263
+ // Cancels AdoptHandoff()'s chunked re-parent of handed-off content, which runs across ticks
16264
+ // instead of one synchronous pass over potentially millions of regos.
16265
+ this.handoffReassignCancel = null;
16266
+ // Menu item the in-flight re-parent is still pulling regos off, so a teardown mid-swap can
16267
+ // clear both sides rather than orphaning whatever had not moved yet.
16268
+ this.handoffSourceMenuItemId = null;
16232
16269
  this.styler = new TilesetRenderEngine.Styler();
16233
16270
  this.modelTreeUpdate = new BruceEvent();
16234
16271
  // Quick look-up of the model tree nodes by entity/geomId.
@@ -16557,7 +16594,7 @@ var TilesetCadRenderManager;
16557
16594
  }
16558
16595
  // Returns null (fall back to a normal Dispose()) if the tileset hasn't finished loading yet.
16559
16596
  PrepareHandoff() {
16560
- var _a, _b, _c;
16597
+ var _a, _b, _c, _d;
16561
16598
  if (this.disposed || !this.cTileset || this.cTileset.isDestroyed()) {
16562
16599
  return null;
16563
16600
  }
@@ -16569,15 +16606,15 @@ var TilesetCadRenderManager;
16569
16606
  clearInterval(this.featureQueueInterval);
16570
16607
  this.featureQueueInterval = null;
16571
16608
  }
16572
- if (this.handoffRestyleInterval) {
16573
- clearInterval(this.handoffRestyleInterval);
16574
- this.handoffRestyleInterval = null;
16575
- }
16609
+ // Settle a re-parent still in flight, so what is handed on is not split across two menu items.
16610
+ (_a = this.handoffReassignCancel) === null || _a === void 0 ? void 0 : _a.call(this, true);
16611
+ this.handoffReassignCancel = null;
16612
+ this.handoffSourceMenuItemId = null;
16576
16613
  // Not transferred, the receiving manager sets up its own fresh copy if needed.
16577
16614
  this.viewerDateTimeDispose();
16578
- (_a = this.styler) === null || _a === void 0 ? void 0 : _a.Dispose();
16579
- (_b = this.tileLoadRemoval) === null || _b === void 0 ? void 0 : _b.call(this);
16580
- (_c = this.tileUnloadRemoval) === null || _c === void 0 ? void 0 : _c.call(this);
16615
+ (_b = this.styler) === null || _b === void 0 ? void 0 : _b.Dispose();
16616
+ (_c = this.tileLoadRemoval) === null || _c === void 0 ? void 0 : _c.call(this);
16617
+ (_d = this.tileUnloadRemoval) === null || _d === void 0 ? void 0 : _d.call(this);
16581
16618
  this.tileLoadRemoval = null;
16582
16619
  this.tileUnloadRemoval = null;
16583
16620
  const payload = {
@@ -16627,13 +16664,6 @@ var TilesetCadRenderManager;
16627
16664
  }
16628
16665
  });
16629
16666
  // Same visuals, same registrations so just re-keyed onto this menu item.
16630
- this.visualsManager.ReassignMenuItem({
16631
- fromMenuItemId: payload.sourceMenuItemId,
16632
- toMenuItemId: this.item.id,
16633
- toMenuItemType: this.item.Type,
16634
- toPriority: this.renderPriority,
16635
- requestRender: false
16636
- });
16637
16667
  this.onCTilesetLoad();
16638
16668
  this.styler.Init({
16639
16669
  viewer: this.viewer,
@@ -16647,33 +16677,32 @@ var TilesetCadRenderManager;
16647
16677
  scenario: (_b = this.item.BruceEntity) === null || _b === void 0 ? void 0 : _b.Scenario,
16648
16678
  historic: (_c = this.item.BruceEntity) === null || _c === void 0 ? void 0 : _c.historic,
16649
16679
  });
16650
- this.queueHandoffRestyle(this.visualsManager.GetRegos({ menuItemId: this.item.id }));
16680
+ // A swap runs inside a render pass, so re-parenting a whole tileset in one go stalls it.
16681
+ // Each batch is restyled as it lands rather than after a second walk of the same set.
16682
+ this.handoffSourceMenuItemId = payload.sourceMenuItemId;
16683
+ this.handoffReassignCancel = this.visualsManager.ReassignMenuItem({
16684
+ fromMenuItemId: payload.sourceMenuItemId,
16685
+ toMenuItemId: this.item.id,
16686
+ toMenuItemType: this.item.Type,
16687
+ toPriority: this.renderPriority,
16688
+ requestRender: false,
16689
+ lazy: true,
16690
+ onBatch: (regos) => {
16691
+ if (this.disposed) {
16692
+ return;
16693
+ }
16694
+ this.styler.QueueEntities(regos, true);
16695
+ },
16696
+ onComplete: () => {
16697
+ this.handoffReassignCancel = null;
16698
+ this.handoffSourceMenuItemId = null;
16699
+ }
16700
+ });
16651
16701
  this.viewer.scene.requestRender();
16652
16702
  if (((_d = this.item.BruceEntity) === null || _d === void 0 ? void 0 : _d.historic) && this.tileset) {
16653
16703
  this.viewerDateTimeSub(this.tileset);
16654
16704
  }
16655
16705
  }
16656
- queueHandoffRestyle(regos) {
16657
- if (!regos.length) {
16658
- return;
16659
- }
16660
- const BATCH_SIZE = 5000;
16661
- let index = 0;
16662
- this.handoffRestyleInterval = setInterval(() => {
16663
- if (this.disposed) {
16664
- clearInterval(this.handoffRestyleInterval);
16665
- this.handoffRestyleInterval = null;
16666
- return;
16667
- }
16668
- const end = Math.min(index + BATCH_SIZE, regos.length);
16669
- this.styler.QueueEntities(regos.slice(index, end), true);
16670
- index = end;
16671
- if (index >= regos.length) {
16672
- clearInterval(this.handoffRestyleInterval);
16673
- this.handoffRestyleInterval = null;
16674
- }
16675
- }, 10);
16676
- }
16677
16706
  /**
16678
16707
  * @param tile
16679
16708
  * @param load indicates if we are loading or unloading the tile.
@@ -17225,33 +17254,40 @@ var TilesetCadRenderManager;
17225
17254
  this.doDispose();
17226
17255
  }
17227
17256
  doDispose() {
17228
- var _a, _b;
17257
+ var _a, _b, _c;
17229
17258
  if (this.featureQueueInterval) {
17230
17259
  clearInterval(this.featureQueueInterval);
17231
17260
  this.featureQueueInterval = null;
17232
17261
  this.featureQueue = [];
17233
17262
  }
17234
- if (this.handoffRestyleInterval) {
17235
- clearInterval(this.handoffRestyleInterval);
17236
- this.handoffRestyleInterval = null;
17237
- }
17263
+ (_a = this.handoffReassignCancel) === null || _a === void 0 ? void 0 : _a.call(this);
17264
+ this.handoffReassignCancel = null;
17238
17265
  if (this.cTileset) {
17239
17266
  const viewer = this.viewer;
17240
17267
  if (!(viewer === null || viewer === void 0 ? void 0 : viewer.isDestroyed()) && this.viewer.scene.primitives.contains(this.cTileset)) {
17241
17268
  this.cTileset.show = false;
17242
17269
  this.viewer.scene.primitives.remove(this.cTileset);
17243
- (_a = TilesetRenderEngine.GetMemoryWatcher(viewer)) === null || _a === void 0 ? void 0 : _a.Unwatch(this.cTileset);
17270
+ (_b = TilesetRenderEngine.GetMemoryWatcher(viewer)) === null || _b === void 0 ? void 0 : _b.Unwatch(this.cTileset);
17244
17271
  this.viewer.scene.requestRender();
17245
17272
  }
17246
17273
  this.cTileset = null;
17247
17274
  }
17248
- (_b = this.styler) === null || _b === void 0 ? void 0 : _b.Dispose();
17275
+ (_c = this.styler) === null || _c === void 0 ? void 0 : _c.Dispose();
17249
17276
  this.visualsManager.RemoveRegos({
17250
17277
  menuItemId: this.item.id,
17251
17278
  doRemove: false,
17252
17279
  source: VisualsRegister.EUpdateSource.TILESET_DISPOSE,
17253
17280
  lazy: true
17254
17281
  });
17282
+ if (this.handoffSourceMenuItemId) {
17283
+ this.visualsManager.RemoveRegos({
17284
+ menuItemId: this.handoffSourceMenuItemId,
17285
+ doRemove: false,
17286
+ source: VisualsRegister.EUpdateSource.TILESET_DISPOSE,
17287
+ lazy: true
17288
+ });
17289
+ this.handoffSourceMenuItemId = null;
17290
+ }
17255
17291
  this.viewerDateTimeDispose();
17256
17292
  }
17257
17293
  async ReRender(params) {
@@ -20010,9 +20046,12 @@ var TilesetEntitiesRenderManager;
20010
20046
  // Removal callbacks for this instance's own tile stream listeners.
20011
20047
  this.tileLoadRemoval = null;
20012
20048
  this.tileUnloadRemoval = null;
20013
- // Chunks AdoptHandoff()'s restyle of handed-off content across ticks instead of one
20014
- // synchronous pass over potentially millions of regos.
20015
- this.handoffRestyleInterval = null;
20049
+ // Cancels AdoptHandoff()'s chunked re-parent of handed-off content, which runs across ticks
20050
+ // instead of one synchronous pass over potentially millions of regos.
20051
+ this.handoffReassignCancel = null;
20052
+ // Menu item the in-flight re-parent is still pulling regos off, so a teardown mid-swap can
20053
+ // clear both sides rather than orphaning whatever had not moved yet.
20054
+ this.handoffSourceMenuItemId = null;
20016
20055
  this.styler = new TilesetRenderEngine.Styler();
20017
20056
  // Entity ID -> rego.
20018
20057
  // We retain this information as a quick look-up on what has been registered.
@@ -20325,31 +20364,36 @@ var TilesetEntitiesRenderManager;
20325
20364
  this.doDispose();
20326
20365
  }
20327
20366
  doDispose() {
20328
- var _a, _b;
20367
+ var _a, _b, _c;
20329
20368
  if (this.featureQueueInterval) {
20330
20369
  clearInterval(this.featureQueueInterval);
20331
20370
  this.featureQueueInterval = null;
20332
20371
  this.featureQueue = [];
20333
20372
  }
20334
- if (this.handoffRestyleInterval) {
20335
- clearInterval(this.handoffRestyleInterval);
20336
- this.handoffRestyleInterval = null;
20337
- }
20373
+ (_a = this.handoffReassignCancel) === null || _a === void 0 ? void 0 : _a.call(this);
20374
+ this.handoffReassignCancel = null;
20338
20375
  if (this.cTileset) {
20339
20376
  const viewer = this.viewer;
20340
20377
  if (!(viewer === null || viewer === void 0 ? void 0 : viewer.isDestroyed()) && this.viewer.scene.primitives.contains(this.cTileset)) {
20341
20378
  this.cTileset.show = false;
20342
20379
  this.viewer.scene.primitives.remove(this.cTileset);
20343
- (_a = TilesetRenderEngine.GetMemoryWatcher(viewer)) === null || _a === void 0 ? void 0 : _a.Unwatch(this.cTileset);
20380
+ (_b = TilesetRenderEngine.GetMemoryWatcher(viewer)) === null || _b === void 0 ? void 0 : _b.Unwatch(this.cTileset);
20344
20381
  this.viewer.scene.requestRender();
20345
20382
  }
20346
20383
  this.cTileset = null;
20347
20384
  }
20348
- (_b = this.styler) === null || _b === void 0 ? void 0 : _b.Dispose();
20385
+ (_c = this.styler) === null || _c === void 0 ? void 0 : _c.Dispose();
20349
20386
  this.visualsManager.RemoveRegos({
20350
20387
  menuItemId: this.item.id,
20351
20388
  lazy: true
20352
20389
  });
20390
+ if (this.handoffSourceMenuItemId) {
20391
+ this.visualsManager.RemoveRegos({
20392
+ menuItemId: this.handoffSourceMenuItemId,
20393
+ lazy: true
20394
+ });
20395
+ this.handoffSourceMenuItemId = null;
20396
+ }
20353
20397
  }
20354
20398
  onCTilesetLoad() {
20355
20399
  if (this.item.FlyTo) {
@@ -20389,7 +20433,7 @@ var TilesetEntitiesRenderManager;
20389
20433
  }
20390
20434
  // Returns null (fall back to a normal Dispose()) if the tileset hasn't finished loading yet.
20391
20435
  PrepareHandoff() {
20392
- var _a, _b, _c;
20436
+ var _a, _b, _c, _d;
20393
20437
  if (this.disposed || !this.cTileset || this.cTileset.isDestroyed()) {
20394
20438
  return null;
20395
20439
  }
@@ -20401,13 +20445,13 @@ var TilesetEntitiesRenderManager;
20401
20445
  clearInterval(this.featureQueueInterval);
20402
20446
  this.featureQueueInterval = null;
20403
20447
  }
20404
- if (this.handoffRestyleInterval) {
20405
- clearInterval(this.handoffRestyleInterval);
20406
- this.handoffRestyleInterval = null;
20407
- }
20408
- (_a = this.styler) === null || _a === void 0 ? void 0 : _a.Dispose();
20409
- (_b = this.tileLoadRemoval) === null || _b === void 0 ? void 0 : _b.call(this);
20410
- (_c = this.tileUnloadRemoval) === null || _c === void 0 ? void 0 : _c.call(this);
20448
+ // Settle a re-parent still in flight, so what is handed on is not split across two menu items.
20449
+ (_a = this.handoffReassignCancel) === null || _a === void 0 ? void 0 : _a.call(this, true);
20450
+ this.handoffReassignCancel = null;
20451
+ this.handoffSourceMenuItemId = null;
20452
+ (_b = this.styler) === null || _b === void 0 ? void 0 : _b.Dispose();
20453
+ (_c = this.tileLoadRemoval) === null || _c === void 0 ? void 0 : _c.call(this);
20454
+ (_d = this.tileUnloadRemoval) === null || _d === void 0 ? void 0 : _d.call(this);
20411
20455
  this.tileLoadRemoval = null;
20412
20456
  this.tileUnloadRemoval = null;
20413
20457
  const payload = {
@@ -20449,14 +20493,8 @@ var TilesetEntitiesRenderManager;
20449
20493
  console.error(e);
20450
20494
  }
20451
20495
  });
20452
- this.visualsManager.ReassignMenuItem({
20453
- fromMenuItemId: payload.sourceMenuItemId,
20454
- toMenuItemId: this.item.id,
20455
- toMenuItemType: this.item.Type,
20456
- toPriority: this.renderPriority,
20457
- requestRender: false
20458
- });
20459
- if (Manager.NeedsStyler(this.item)) {
20496
+ const needsStyler = Manager.NeedsStyler(this.item);
20497
+ if (needsStyler) {
20460
20498
  this.styler.Init({
20461
20499
  viewer: this.viewer,
20462
20500
  api: this.getters.GetBruceApi(),
@@ -20470,8 +20508,28 @@ var TilesetEntitiesRenderManager;
20470
20508
  applyStyles: Boolean(this.item.ApplyStyles),
20471
20509
  monitor: this.monitor
20472
20510
  });
20473
- this.queueHandoffRestyle(this.visualsManager.GetRegos({ menuItemId: this.item.id }));
20474
20511
  }
20512
+ // A swap runs inside a render pass, so re-parenting a whole Entities Set in one go stalls it.
20513
+ // Each batch is restyled as it lands rather than after a second walk of the same set.
20514
+ this.handoffSourceMenuItemId = payload.sourceMenuItemId;
20515
+ this.handoffReassignCancel = this.visualsManager.ReassignMenuItem({
20516
+ fromMenuItemId: payload.sourceMenuItemId,
20517
+ toMenuItemId: this.item.id,
20518
+ toMenuItemType: this.item.Type,
20519
+ toPriority: this.renderPriority,
20520
+ requestRender: false,
20521
+ lazy: true,
20522
+ onBatch: (regos) => {
20523
+ if (this.disposed || !needsStyler) {
20524
+ return;
20525
+ }
20526
+ this.styler.QueueEntities(regos, true);
20527
+ },
20528
+ onComplete: () => {
20529
+ this.handoffReassignCancel = null;
20530
+ this.handoffSourceMenuItemId = null;
20531
+ }
20532
+ });
20475
20533
  this.onCTilesetLoad();
20476
20534
  let attenuation = this.item.attenuation;
20477
20535
  if (!attenuation && attenuation != false) {
@@ -20490,27 +20548,6 @@ var TilesetEntitiesRenderManager;
20490
20548
  });
20491
20549
  this.viewer.scene.requestRender();
20492
20550
  }
20493
- queueHandoffRestyle(regos) {
20494
- if (!regos.length) {
20495
- return;
20496
- }
20497
- const BATCH_SIZE = 5000;
20498
- let index = 0;
20499
- this.handoffRestyleInterval = setInterval(() => {
20500
- if (this.disposed) {
20501
- clearInterval(this.handoffRestyleInterval);
20502
- this.handoffRestyleInterval = null;
20503
- return;
20504
- }
20505
- const end = Math.min(index + BATCH_SIZE, regos.length);
20506
- this.styler.QueueEntities(regos.slice(index, end), true);
20507
- index = end;
20508
- if (index >= regos.length) {
20509
- clearInterval(this.handoffRestyleInterval);
20510
- this.handoffRestyleInterval = null;
20511
- }
20512
- }, 10);
20513
- }
20514
20551
  /*
20515
20552
  * Reads a numeric feature property, returning null for anything that is not one.
20516
20553
  */
@@ -46391,7 +46428,7 @@ var StyleUtils;
46391
46428
  StyleUtils.ApplyTypeStyle = ApplyTypeStyle;
46392
46429
  })(StyleUtils || (StyleUtils = {}));
46393
46430
 
46394
- const VERSION = "7.3.0";
46431
+ const VERSION = "7.3.2";
46395
46432
  /**
46396
46433
  * Updates the environment instance used by bruce-cesium to one specified.
46397
46434
  * This can be used to ensure that the instance a parent is referencing is shared between bruce-cesium, bruce-models, and the parent app.