bruce-cesium 7.6.2 → 7.6.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.
Files changed (45) hide show
  1. package/dist/bruce-cesium.es5.js +508 -46
  2. package/dist/bruce-cesium.es5.js.map +1 -1
  3. package/dist/bruce-cesium.umd.js +501 -43
  4. package/dist/bruce-cesium.umd.js.map +1 -1
  5. package/dist/lib/bruce-cesium.js +2 -1
  6. package/dist/lib/bruce-cesium.js.map +1 -1
  7. package/dist/lib/rendering/menu-item-creator.js +44 -23
  8. package/dist/lib/rendering/menu-item-creator.js.map +1 -1
  9. package/dist/lib/rendering/menu-item-manager.js +116 -7
  10. package/dist/lib/rendering/menu-item-manager.js.map +1 -1
  11. package/dist/lib/rendering/menu-item-styles.js +151 -0
  12. package/dist/lib/rendering/menu-item-styles.js.map +1 -0
  13. package/dist/lib/rendering/render-managers/entities/entities-datalab-render-manager.js +10 -0
  14. package/dist/lib/rendering/render-managers/entities/entities-datalab-render-manager.js.map +1 -1
  15. package/dist/lib/rendering/render-managers/entities/entities-ids-render-manager.js +10 -0
  16. package/dist/lib/rendering/render-managers/entities/entities-ids-render-manager.js.map +1 -1
  17. package/dist/lib/rendering/render-managers/entities/entities-loaded-render-manager.js +10 -0
  18. package/dist/lib/rendering/render-managers/entities/entities-loaded-render-manager.js.map +1 -1
  19. package/dist/lib/rendering/render-managers/entities/entities-render-manager.js +48 -0
  20. package/dist/lib/rendering/render-managers/entities/entities-render-manager.js.map +1 -1
  21. package/dist/lib/rendering/render-managers/entities/entity-render-manager.js +10 -0
  22. package/dist/lib/rendering/render-managers/entities/entity-render-manager.js.map +1 -1
  23. package/dist/lib/rendering/render-managers/render-manager.js.map +1 -1
  24. package/dist/lib/rendering/render-managers/tilesets/tileset-arb-render-manager.js +17 -0
  25. package/dist/lib/rendering/render-managers/tilesets/tileset-arb-render-manager.js.map +1 -1
  26. package/dist/lib/rendering/render-managers/tilesets/tileset-cad-render-manager.js +15 -0
  27. package/dist/lib/rendering/render-managers/tilesets/tileset-cad-render-manager.js.map +1 -1
  28. package/dist/lib/rendering/render-managers/tilesets/tileset-entities-render-manager.js +15 -0
  29. package/dist/lib/rendering/render-managers/tilesets/tileset-entities-render-manager.js.map +1 -1
  30. package/dist/lib/widgets/tabs-left-panel/widget-left-panel-tab-menu-items.js +64 -12
  31. package/dist/lib/widgets/tabs-left-panel/widget-left-panel-tab-menu-items.js.map +1 -1
  32. package/dist/types/bruce-cesium.d.ts +2 -1
  33. package/dist/types/rendering/menu-item-manager.d.ts +25 -0
  34. package/dist/types/rendering/menu-item-styles.d.ts +30 -0
  35. package/dist/types/rendering/render-managers/entities/entities-datalab-render-manager.d.ts +5 -1
  36. package/dist/types/rendering/render-managers/entities/entities-ids-render-manager.d.ts +5 -1
  37. package/dist/types/rendering/render-managers/entities/entities-loaded-render-manager.d.ts +5 -1
  38. package/dist/types/rendering/render-managers/entities/entities-render-manager.d.ts +8 -1
  39. package/dist/types/rendering/render-managers/entities/entity-render-manager.d.ts +5 -1
  40. package/dist/types/rendering/render-managers/render-manager.d.ts +10 -1
  41. package/dist/types/rendering/render-managers/tilesets/tileset-arb-render-manager.d.ts +5 -1
  42. package/dist/types/rendering/render-managers/tilesets/tileset-cad-render-manager.d.ts +5 -1
  43. package/dist/types/rendering/render-managers/tilesets/tileset-entities-render-manager.d.ts +5 -1
  44. package/dist/types/widgets/tabs-left-panel/widget-left-panel-tab-menu-items.d.ts +1 -0
  45. package/package.json +2 -2
@@ -1,6 +1,6 @@
1
1
  import * as Cesium from 'cesium';
2
- import { Cartographic, Entity, ConstantPositionProperty, HeightReference, Color, DistanceDisplayCondition, ColorMaterialProperty, ConstantProperty, CallbackProperty, Primitive, Cesium3DTileFeature, ColorBlendMode, HeadingPitchRoll, Math as Math$1, Transforms, ShadowMode, Cartesian3, ClassificationType, Model, JulianDate, Quaternion, Matrix4, HorizontalOrigin, VerticalOrigin, ShaderSource, Ellipsoid, Geometry, GeometryAttribute, ComponentDatatype, PrimitiveType, BoundingSphere, GeometryPipeline, Cartesian2, Cartesian4, sampleTerrain, Texture, PixelFormat, Sampler, TextureWrap, TextureMinificationFilter, TextureMagnificationFilter, PixelDatatype, VertexArray, BufferUsage, ShaderProgram, RenderState, BlendingState, DrawCommand, Pass, ArcType, CornerType, ImageMaterialProperty, PolygonHierarchy, PolylineGraphics, Rectangle, SceneMode, IntersectionTests, Ray, SceneTransforms, FeatureDetection, Matrix3, NearFarScalar, KmlDataSource, GeoJsonDataSource, Cesium3DTileStyle, HeadingPitchRange, Ion, IonResource, Cesium3DTileColorBlendMode, EllipsoidTerrainProvider, IonImageryProvider, createWorldImagery, createWorldImageryAsync, BingMapsImageryProvider, BingMapsStyle, MapboxImageryProvider, MapboxStyleImageryProvider, ArcGisMapServerImageryProvider, OpenStreetMapImageryProvider, UrlTemplateImageryProvider, GridImageryProvider, GeographicTilingScheme, ImageryLayer, TileMapServiceImageryProvider, CesiumTerrainProvider, Cesium3DTileset, OrthographicFrustum, EasingFunction, Intersect, ModelGraphics, PolygonGraphics, CorridorGraphics, PointGraphics, BillboardGraphics, EllipseGraphics, PolylineDashMaterialProperty, PolygonPipeline, EllipsoidGeodesic, sampleTerrainMostDetailed, defined, CustomDataSource, 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, UrlUtils, Api, Carto, Geometry as Geometry$1, Bounds, ClientFileValueMap, Color as Color$1, MenuItem, ProjectView, ProjectViewBookmark, Tileset, ZoomControl, BruceEvent, EntityCoords, DataLab, DelayQueue, AccountConcept, BruceApi, EntityRelation, RecordChangeFeed, EntitySource, ProgramKey, ProjectViewLegacyTile, Camera, Account, AccountLimits, Session, EntityAttachment, EntityAttachmentType, EntityAttribute, MathUtils, ProjectViewBookmarkGroup, EntityRelationType, EntityHistoricData } from 'bruce-models';
2
+ import { Cartographic, ColorMaterialProperty, Entity, Color, ConstantProperty, CallbackProperty, Primitive, Cesium3DTileFeature, Math as Math$1, Cartesian3, JulianDate, Quaternion, Transforms, HeadingPitchRoll, HeightReference, Matrix4, ConstantPositionProperty, DistanceDisplayCondition, ColorBlendMode, ShadowMode, ClassificationType, Model, ShaderSource, Ellipsoid, Geometry, GeometryAttribute, ComponentDatatype, PrimitiveType, BoundingSphere, GeometryPipeline, Cartesian2, Cartesian4, sampleTerrain, Texture, PixelFormat, Sampler, TextureWrap, TextureMinificationFilter, TextureMagnificationFilter, PixelDatatype, VertexArray, BufferUsage, ShaderProgram, RenderState, BlendingState, DrawCommand, Pass, ArcType, CornerType, ImageMaterialProperty, PolygonHierarchy, PolylineGraphics, Rectangle, SceneMode, IntersectionTests, Ray, SceneTransforms, HorizontalOrigin, VerticalOrigin, NearFarScalar, Matrix3, KmlDataSource, GeoJsonDataSource, FeatureDetection, Cesium3DTileStyle, Cesium3DTileColorBlendMode, HeadingPitchRange, 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, PolygonPipeline, GeometryInstance, EllipsoidGeodesic, sampleTerrainMostDetailed, defined, CesiumInspector, ClockRange, DynamicEnvironmentMapManager, CustomDataSource, ScreenSpaceEventHandler, ScreenSpaceEventType, Fullscreen, CzmlDataSource } from 'cesium';
3
+ import { Cartes, LRUCache, ProjectViewTile, ENVIRONMENT, Calculator, ClientFile, Entity as Entity$1, EntityLod, EntityTag, EntityType, ObjectUtils, Style, UrlUtils, Carto, Geometry as Geometry$1, Bounds, ClientFileValueMap, Color as Color$1, MenuItem, ProjectView, ProjectViewBookmark, Tileset, ZoomControl, BruceEvent, EntityCoords, Api, DataLab, DelayQueue, AccountConcept, RecordChangeFeed, BruceApi, EntityRelation, EntitySource, ProgramKey, ProjectViewLegacyTile, Camera, Account, AccountLimits, Session, 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.
@@ -16418,6 +16418,10 @@ var EntitiesRenderManager;
16418
16418
  this.zoomControl = [];
16419
16419
  // Scenario for retrieving Entities.
16420
16420
  this.scenario = null;
16421
+ // Hand-off key of the data currently drawn, or null when it is unknown or nothing is drawn.
16422
+ this.drawnKey = null;
16423
+ // How the drawn entities were last told to look, see getDrawnSettingsSignature.
16424
+ this.drawnSettings = null;
16421
16425
  // Type IDs that we'll allow to be rendered when receiving Entities.
16422
16426
  // This might be exactly the Menu Item Type ID because of local data sources.
16423
16427
  this.allowedTypeIDs = [];
@@ -16476,9 +16480,26 @@ var EntitiesRenderManager;
16476
16480
  if (this.disposed) {
16477
16481
  return;
16478
16482
  }
16483
+ // Landing on the data already drawn re-applies settings instead of removing and re-fetching it.
16484
+ const nextKey = shouldRender ? Manager.GetHandoffKey(this.item) : null;
16485
+ const keepDrawn = nextKey != null && nextKey === this.drawnKey;
16486
+ const restyle = keepDrawn && this.drawnSettings !== this.getDrawnSettingsSignature();
16487
+ this.drawnKey = nextKey;
16488
+ this.drawnSettings = this.getDrawnSettingsSignature();
16479
16489
  this.unsetGetter();
16480
16490
  (_a = this.viewMonitorRemoval) === null || _a === void 0 ? void 0 : _a.call(this);
16481
16491
  this.viewMonitorRemoval = null;
16492
+ if (keepDrawn) {
16493
+ this.setGetter();
16494
+ this.viewMonitorRemoval = this.monitor.Updated().Subscribe(() => {
16495
+ var _a;
16496
+ (_a = this.entityCheckQueue) === null || _a === void 0 ? void 0 : _a.Call();
16497
+ });
16498
+ if (restyle) {
16499
+ this.ReRender({ entityIds: Object.keys(this.renderedEntities), force: true });
16500
+ }
16501
+ return;
16502
+ }
16482
16503
  clearInterval(this.renderQueueInterval);
16483
16504
  this.renderQueueInterval = null;
16484
16505
  this.renderQueue = [];
@@ -16512,6 +16533,18 @@ var EntitiesRenderManager;
16512
16533
  }
16513
16534
  })();
16514
16535
  }
16536
+ /*
16537
+ * Everything about how drawn entities look that applying the item's settings can change.
16538
+ */
16539
+ getDrawnSettingsSignature() {
16540
+ var _a;
16541
+ return JSON.stringify({
16542
+ zoomControl: RenderManager.GetZoomControlSignature(this.zoomControl),
16543
+ renderPriority: (_a = this.renderPriority) !== null && _a !== void 0 ? _a : null,
16544
+ historicDrawTrack: Boolean(this.item.historicDrawTrack),
16545
+ historicInterpolation: Boolean(this.item.historicInterpolation)
16546
+ });
16547
+ }
16515
16548
  applyItemSettings() {
16516
16549
  var _a, _b, _c, _d, _e, _f;
16517
16550
  // Reset allowed list if there's change.
@@ -16887,10 +16920,13 @@ var EntitiesRenderManager;
16887
16920
  console.warn("Geojson rendering does not support multiple zoom controls. Only the first one will be used.");
16888
16921
  this.zoomControl = [this.zoomControl[0]];
16889
16922
  }
16923
+ this.drawnSettings = this.getDrawnSettingsSignature();
16890
16924
  changed = true;
16891
16925
  }
16892
16926
  if (scenario != null) {
16893
16927
  this.scenario = scenario;
16928
+ // The drawn records now belong to a scenario the item does not name.
16929
+ this.drawnKey = null;
16894
16930
  changed = true;
16895
16931
  }
16896
16932
  if (changed) {
@@ -16905,6 +16941,16 @@ var EntitiesRenderManager;
16905
16941
  this.doEntityCheck(entityIds);
16906
16942
  }
16907
16943
  }
16944
+ /**
16945
+ * Switches to another of the item's own styles, restyling what is drawn without re-creating it.
16946
+ */
16947
+ SwapStyle(item) {
16948
+ if (this.disposed) {
16949
+ return;
16950
+ }
16951
+ this.item = item;
16952
+ this.UpdateSettings({ zoomControl: item.CameraZoomSettings });
16953
+ }
16908
16954
  /**
16909
16955
  * Narrows a camera-driven check to the entities whose zoom band could actually have changed.
16910
16956
  * @param ids
@@ -17658,6 +17704,8 @@ var EntitiesRenderManager;
17658
17704
  AdoptHandoff(payload) {
17659
17705
  var _a;
17660
17706
  const { shouldRender } = this.applyItemSettings();
17707
+ this.drawnKey = shouldRender ? Manager.GetHandoffKey(this.item) : null;
17708
+ this.drawnSettings = this.getDrawnSettingsSignature();
17661
17709
  this.visualsManager.ReassignMenuItem({
17662
17710
  fromMenuItemId: payload.sourceMenuItemId,
17663
17711
  toMenuItemId: this.item.id,
@@ -18039,6 +18087,16 @@ var EntitiesLoadedRenderManager;
18039
18087
  this.doEntityCheck(entityIds);
18040
18088
  }
18041
18089
  }
18090
+ /**
18091
+ * Switches to another of the item's own styles, restyling what is drawn without re-creating it.
18092
+ */
18093
+ SwapStyle(item) {
18094
+ if (this.disposed) {
18095
+ return;
18096
+ }
18097
+ this.item = item;
18098
+ this.UpdateSettings({ zoomControl: item.CameraZoomSettings });
18099
+ }
18042
18100
  async doEntityCheck(ids, force = false) {
18043
18101
  var _a, _b;
18044
18102
  const api = this.apiGetter.getApi();
@@ -18744,6 +18802,16 @@ var EntitiesIdsRenderManager;
18744
18802
  this.onGetterUpdate(entityIds);
18745
18803
  }
18746
18804
  }
18805
+ /**
18806
+ * Switches to another of the item's own styles, restyling what is drawn without re-creating it.
18807
+ */
18808
+ SwapStyle(item) {
18809
+ if (this.disposed) {
18810
+ return;
18811
+ }
18812
+ this.item = item;
18813
+ this.UpdateSettings({ zoomControl: item.CameraZoomSettings });
18814
+ }
18747
18815
  /*
18748
18816
  * The lane this item reads through, or null when it does not follow the clock.
18749
18817
  */
@@ -19207,6 +19275,16 @@ var EntityRenderManager;
19207
19275
  this.onGetterUpdate(entityId, true);
19208
19276
  }
19209
19277
  }
19278
+ /**
19279
+ * Switches to another of the item's own styles, restyling what is drawn without re-creating it.
19280
+ */
19281
+ SwapStyle(item) {
19282
+ if (this.disposed) {
19283
+ return;
19284
+ }
19285
+ this.item = item;
19286
+ this.UpdateSettings({ zoomControl: item.CameraZoomSettings });
19287
+ }
19210
19288
  renderEntity(entity, force = false) {
19211
19289
  // Waiting for prior call to finish resolving.
19212
19290
  // This avoids race conditions against two sets of overlapping Entities.
@@ -23082,6 +23160,21 @@ var TilesetCadRenderManager;
23082
23160
  }
23083
23161
  return children;
23084
23162
  }
23163
+ /**
23164
+ * Switches to another of the item's own styles, restyling the loaded tileset without reloading it.
23165
+ */
23166
+ SwapStyle(item) {
23167
+ var _a;
23168
+ if (this.disposed) {
23169
+ return;
23170
+ }
23171
+ this.item = item;
23172
+ // Before the tileset loads this only stores the pick, and the styler's Init reads the new item.
23173
+ this.styler.UpdateStyleMapping({
23174
+ styleMapping: (_a = item.StyleMapping) !== null && _a !== void 0 ? _a : [],
23175
+ fallbackStyleId: item.styleId
23176
+ });
23177
+ }
23085
23178
  Dispose() {
23086
23179
  var _a;
23087
23180
  if (this.disposed) {
@@ -24811,6 +24904,16 @@ var DataLabRenderManager;
24811
24904
  this.doEntityCheck(entityIds);
24812
24905
  }
24813
24906
  }
24907
+ /**
24908
+ * Switches to another of the item's own styles, restyling what is drawn without re-creating it.
24909
+ */
24910
+ SwapStyle(item) {
24911
+ if (this.disposed) {
24912
+ return;
24913
+ }
24914
+ this.item = item;
24915
+ this.UpdateSettings({ zoomControl: item.CameraZoomSettings });
24916
+ }
24814
24917
  async doEntityCheck(ids, force = false) {
24815
24918
  var _a, _b, _c, _d;
24816
24919
  if (this.isRunningCheck) {
@@ -26724,6 +26827,21 @@ var TilesetEntitiesRenderManager;
26724
26827
  }
26725
26828
  }
26726
26829
  }
26830
+ /**
26831
+ * Switches to another of the item's own styles, restyling the loaded tileset without reloading it.
26832
+ */
26833
+ SwapStyle(item) {
26834
+ if (this.disposed) {
26835
+ return;
26836
+ }
26837
+ this.item = item;
26838
+ if (Manager.NeedsStyler(item)) {
26839
+ this.styler.UpdateStyleMapping({
26840
+ styleMapping: [],
26841
+ fallbackStyleId: item.styleId
26842
+ });
26843
+ }
26844
+ }
26727
26845
  Dispose() {
26728
26846
  var _a;
26729
26847
  if (this.disposed) {
@@ -27980,6 +28098,23 @@ var TilesetArbRenderManager;
27980
28098
  this.viewer.zoomTo(this.cTileset, new HeadingPitchRange(0.0, -0.5, this.cTileset.boundingSphere.radius / 4.0));
27981
28099
  }
27982
28100
  }
28101
+ /**
28102
+ * Switches to another of the item's own styles, restyling the loaded tileset without reloading it.
28103
+ */
28104
+ SwapStyle(item) {
28105
+ var _a;
28106
+ if (this.disposed) {
28107
+ return;
28108
+ }
28109
+ // Copied for the same reason the constructor copies it.
28110
+ this.item = JSON.parse(JSON.stringify(item));
28111
+ if (this.item.ApplyStyles || this.item.Type == MenuItem.EType.IonTileset) {
28112
+ this.styler.UpdateStyleMapping({
28113
+ styleMapping: (_a = this.item.StyleMapping) !== null && _a !== void 0 ? _a : [],
28114
+ fallbackStyleId: this.item.styleId
28115
+ });
28116
+ }
28117
+ }
27983
28118
  Dispose() {
27984
28119
  if (this.disposed) {
27985
28120
  return;
@@ -31515,6 +31650,153 @@ var AssemblyRenderManager;
31515
31650
  AssemblyRenderManager.Manager = Manager;
31516
31651
  })(AssemblyRenderManager || (AssemblyRenderManager = {}));
31517
31652
 
31653
+ /**
31654
+ * Reads and picks between a menu item's ordered styles, writing the pick to the single field renderers read.
31655
+ */
31656
+ var MenuItemStyles;
31657
+ (function (MenuItemStyles) {
31658
+ // Tileset items whose render manager applies styleId through a Styler.
31659
+ const TILESET_TYPES = [
31660
+ MenuItem.EType.CadTileset,
31661
+ MenuItem.EType.ArbTileset,
31662
+ MenuItem.EType.IonTileset,
31663
+ MenuItem.EType.EntityTileset
31664
+ ];
31665
+ // Items whose style lives on their zoom control rows.
31666
+ const ZOOM_CONTROL_TYPES = [
31667
+ MenuItem.EType.Entities,
31668
+ MenuItem.EType.Entity,
31669
+ MenuItem.EType.EntitiesIds,
31670
+ MenuItem.EType.EntitiesLoaded,
31671
+ MenuItem.EType.DataLab
31672
+ ];
31673
+ /**
31674
+ * Returns the ordered styles a user can swap between for the item, or an empty array when it offers no choice.
31675
+ */
31676
+ function GetStyleIds(item) {
31677
+ var _a;
31678
+ if (isStyledTileset(item)) {
31679
+ return cleanIds(item.styleIds);
31680
+ }
31681
+ if (ZOOM_CONTROL_TYPES.includes(item === null || item === void 0 ? void 0 : item.Type)) {
31682
+ return cleanIds((_a = getVisibleRow(item.CameraZoomSettings)) === null || _a === void 0 ? void 0 : _a.StyleIDs);
31683
+ }
31684
+ return [];
31685
+ }
31686
+ MenuItemStyles.GetStyleIds = GetStyleIds;
31687
+ /**
31688
+ * Returns the style the item currently renders with, from styleId or its one non-hidden zoom row.
31689
+ */
31690
+ function GetStyleId(item) {
31691
+ var _a;
31692
+ if (TILESET_TYPES.includes(item === null || item === void 0 ? void 0 : item.Type)) {
31693
+ return item.styleId;
31694
+ }
31695
+ if (ZOOM_CONTROL_TYPES.includes(item === null || item === void 0 ? void 0 : item.Type)) {
31696
+ return (_a = getVisibleRow(item.CameraZoomSettings)) === null || _a === void 0 ? void 0 : _a.StyleID;
31697
+ }
31698
+ return undefined;
31699
+ }
31700
+ MenuItemStyles.GetStyleId = GetStyleId;
31701
+ /**
31702
+ * Returns a copy of the item rendering with the given style, or null when that style is not one of its options.
31703
+ */
31704
+ function WithStyleId(item, styleId) {
31705
+ const styleIds = GetStyleIds(item);
31706
+ const picked = styleIds.find(x => isSameId(x, styleId));
31707
+ if (picked == null) {
31708
+ return null;
31709
+ }
31710
+ if (isStyledTileset(item)) {
31711
+ return { ...item, styleId: picked };
31712
+ }
31713
+ const zItem = item;
31714
+ const visible = getVisibleRow(zItem.CameraZoomSettings);
31715
+ return {
31716
+ ...zItem,
31717
+ CameraZoomSettings: zItem.CameraZoomSettings.map(row => {
31718
+ if (row !== visible) {
31719
+ return row;
31720
+ }
31721
+ // An inline style would win over the picked ID.
31722
+ const next = { ...row, StyleID: picked };
31723
+ delete next.Style;
31724
+ return next;
31725
+ })
31726
+ };
31727
+ }
31728
+ MenuItemStyles.WithStyleId = WithStyleId;
31729
+ /**
31730
+ * Returns the item on the first of its styles unless it already uses one, or the same object when it has none.
31731
+ */
31732
+ function Resolve(item) {
31733
+ var _a;
31734
+ const styleIds = GetStyleIds(item);
31735
+ if (!styleIds.length) {
31736
+ return item;
31737
+ }
31738
+ const current = GetStyleId(item);
31739
+ if (current != null && styleIds.some(x => isSameId(x, current))) {
31740
+ return item;
31741
+ }
31742
+ return (_a = WithStyleId(item, styleIds[0])) !== null && _a !== void 0 ? _a : item;
31743
+ }
31744
+ MenuItemStyles.Resolve = Resolve;
31745
+ /**
31746
+ * Returns a copy on the style a bookmark alternation picked, or the item itself when that is not an option.
31747
+ */
31748
+ function ApplyAlternation(item, alternation) {
31749
+ var _a, _b, _c;
31750
+ // Alternations are partial items and may carry no Type, so the pick is read from whichever field is present.
31751
+ const alt = alternation;
31752
+ const picked = (_a = alt === null || alt === void 0 ? void 0 : alt.styleId) !== null && _a !== void 0 ? _a : (_b = getVisibleRow(alt === null || alt === void 0 ? void 0 : alt.CameraZoomSettings)) === null || _b === void 0 ? void 0 : _b.StyleID;
31753
+ if (picked == null) {
31754
+ return item;
31755
+ }
31756
+ return (_c = WithStyleId(item, picked)) !== null && _c !== void 0 ? _c : item;
31757
+ }
31758
+ MenuItemStyles.ApplyAlternation = ApplyAlternation;
31759
+ /**
31760
+ * Returns true when the two items differ by nothing but which of their styles is picked.
31761
+ */
31762
+ function IsStyleChangeOnly(from, to) {
31763
+ if (!from || !to || from.Type !== to.Type) {
31764
+ return false;
31765
+ }
31766
+ const toStyleId = GetStyleId(to);
31767
+ if (toStyleId == null || isSameId(GetStyleId(from), toStyleId)) {
31768
+ return false;
31769
+ }
31770
+ const moved = WithStyleId(from, toStyleId);
31771
+ // A false mismatch only costs the in-place swap, so key order is not normalized.
31772
+ return Boolean(moved) && JSON.stringify(moved) === JSON.stringify(to);
31773
+ }
31774
+ MenuItemStyles.IsStyleChangeOnly = IsStyleChangeOnly;
31775
+ function isStyledTileset(item) {
31776
+ if (!TILESET_TYPES.includes(item === null || item === void 0 ? void 0 : item.Type)) {
31777
+ return false;
31778
+ }
31779
+ // These two only run a Styler when asked to.
31780
+ if (item.Type === MenuItem.EType.ArbTileset || item.Type === MenuItem.EType.EntityTileset) {
31781
+ return Boolean(item.ApplyStyles);
31782
+ }
31783
+ return true;
31784
+ }
31785
+ function getVisibleRow(rows) {
31786
+ const visible = (rows !== null && rows !== void 0 ? rows : []).filter(x => x && x.DisplayType !== ZoomControl.EDisplayType.Hidden);
31787
+ return visible.length === 1 ? visible[0] : null;
31788
+ }
31789
+ function cleanIds(ids) {
31790
+ return (ids !== null && ids !== void 0 ? ids : []).filter(x => x != null && x !== "");
31791
+ }
31792
+ /*
31793
+ * Compares style references, which can be an ID typed as a string or a number.
31794
+ */
31795
+ function isSameId(a, b) {
31796
+ return a != null && b != null && String(a) === String(b);
31797
+ }
31798
+ })(MenuItemStyles || (MenuItemStyles = {}));
31799
+
31518
31800
  /**
31519
31801
  * Util to batch Tileset and Root Entity coord requests between Menu Items.
31520
31802
  * This avoids per-menu-item requests and allows for them to request together if enabled within N ms of each other.
@@ -31759,6 +32041,8 @@ var MenuItemManager;
31759
32041
  constructor(params) {
31760
32042
  this.items = [];
31761
32043
  this.pendingHandoffPool = [];
32044
+ // The settings bookmark alternations overwrite on a view's items, as that view authored them.
32045
+ this.authoredAlternations = new WeakMap();
31762
32046
  this.onUpdate = null;
31763
32047
  // Segments discovered so far per menu item ID.
31764
32048
  this.seriesSegments = new Map();
@@ -31814,7 +32098,7 @@ var MenuItemManager;
31814
32098
  * @returns
31815
32099
  */
31816
32100
  RenderItem(params) {
31817
- var _a, _b, _c, _d, _e, _f, _g;
32101
+ var _a, _b, _c, _d, _e, _f, _g, _h;
31818
32102
  if (this.viewer.isDestroyed()) {
31819
32103
  return null;
31820
32104
  }
@@ -31838,13 +32122,21 @@ var MenuItemManager;
31838
32122
  if (params.modelSpace == null) {
31839
32123
  params.modelSpace = false;
31840
32124
  }
32125
+ // An item with a style set renders its first style unless the caller already picked one of them.
32126
+ params = { ...params, item: MenuItemStyles.Resolve(params.item) };
31841
32127
  let rItem = this.items.find(x => x.id == params.item.id);
31842
32128
  let create = true;
31843
32129
  // Item already exists so we'll check if we should re-create it.
31844
32130
  if (rItem) {
32131
+ // Only the picked style changed, so what is drawn gets restyled rather than rebuilt.
32132
+ if (MenuItemStyles.IsStyleChangeOnly(rItem.item, params.item) && this.isStyleSwapCapable(rItem.renderManager)) {
32133
+ rItem.renderManager.SwapStyle(params.item);
32134
+ rItem.item = params.item;
32135
+ create = false;
32136
+ }
31845
32137
  // This means we're updating an entities menu item re-using the same id.
31846
32138
  // Eg: a bookmark swap that keeps the same item but changes tags, style, or zoom settings.
31847
- if (rItem.type == MenuItem.EType.Entities && params.item.Type == MenuItem.EType.Entities) {
32139
+ else if (rItem.type == MenuItem.EType.Entities && params.item.Type == MenuItem.EType.Entities) {
31848
32140
  rItem.renderManager.Init({
31849
32141
  item: params.item,
31850
32142
  });
@@ -32179,7 +32471,17 @@ var MenuItemManager;
32179
32471
  // We no longer support folder items being both a folder and an action.
32180
32472
  // Now an item must have no action to be a folder.
32181
32473
  const isFolder = !params.item.Type || params.item.Type == MenuItem.EType.None;
32182
- if (params.item.Children && params.recursive != false && isFolder) {
32474
+ const isRadioFolder = isFolder && Boolean(params.item.childrenAsRadios);
32475
+ if (((_f = params.item.Children) === null || _f === void 0 ? void 0 : _f.length) && params.recursive != false && isRadioFolder) {
32476
+ const picked = this.pickRadioChild(params.item.Children, params.preferredIds);
32477
+ const others = params.item.Children.filter(x => x !== picked && this.items.some(y => y.id === x.id));
32478
+ const childId = this.renderInPlaceOf(others.map(x => x.id), () => this.RenderItem({
32479
+ ...params,
32480
+ item: picked
32481
+ }));
32482
+ rItem.childIds = childId ? [childId] : [];
32483
+ }
32484
+ else if (params.item.Children && params.recursive != false && isFolder) {
32183
32485
  for (let i = 0; i < params.item.Children.length; i++) {
32184
32486
  const childId = this.RenderItem({
32185
32487
  ...params,
@@ -32188,8 +32490,8 @@ var MenuItemManager;
32188
32490
  rItem.childIds.push(childId);
32189
32491
  }
32190
32492
  }
32191
- if (rItem.renderManager && !((_f = rItem.renderManager) === null || _f === void 0 ? void 0 : _f.Disposed)) {
32192
- (_g = this.onUpdate) === null || _g === void 0 ? void 0 : _g.Trigger({ isEnabling: true, itemId: rItem.id });
32493
+ if (rItem.renderManager && !((_g = rItem.renderManager) === null || _g === void 0 ? void 0 : _g.Disposed)) {
32494
+ (_h = this.onUpdate) === null || _h === void 0 ? void 0 : _h.Trigger({ isEnabling: true, itemId: rItem.id });
32193
32495
  }
32194
32496
  return rItem.id;
32195
32497
  }
@@ -32238,9 +32540,74 @@ var MenuItemManager;
32238
32540
  (_b = this.onUpdate) === null || _b === void 0 ? void 0 : _b.Trigger({ isEnabling: false, itemId: item.id });
32239
32541
  }
32240
32542
  }
32543
+ /**
32544
+ * Replaces enabled menu items with another, which reuses their graphics where both draw the same data.
32545
+ */
32546
+ SwapItem(params) {
32547
+ const { fromIds, item, modelSpace } = params;
32548
+ const parents = this.items.filter(x => x.childIds.some(id => fromIds.includes(id)));
32549
+ const id = this.renderInPlaceOf(fromIds, () => this.RenderItem({
32550
+ item,
32551
+ modelSpace
32552
+ }));
32553
+ // Keeps a radio folder's removal reaching the child that replaced its old one.
32554
+ for (const parent of parents) {
32555
+ const kept = parent.childIds.filter(x => !fromIds.includes(x));
32556
+ parent.childIds = id && !kept.includes(id) ? kept.concat(id) : kept;
32557
+ }
32558
+ return id;
32559
+ }
32560
+ /**
32561
+ * Restyles an enabled menu item in place with another of its own styles, returning false when it cannot.
32562
+ */
32563
+ SetItemStyle(params) {
32564
+ var _a;
32565
+ const { menuItemId, styleId } = params;
32566
+ const rItem = this.items.find(x => x.id === menuItemId);
32567
+ if (!rItem || !this.isStyleSwapCapable(rItem.renderManager) || rItem.renderManager.Disposed) {
32568
+ return false;
32569
+ }
32570
+ const next = MenuItemStyles.WithStyleId(rItem.item, styleId);
32571
+ if (!next) {
32572
+ return false;
32573
+ }
32574
+ rItem.renderManager.SwapStyle(next);
32575
+ rItem.item = next;
32576
+ (_a = this.onUpdate) === null || _a === void 0 ? void 0 : _a.Trigger({ isEnabling: true, itemId: rItem.id });
32577
+ return true;
32578
+ }
32579
+ /*
32580
+ * Picks the child the caller asked for, else the one already enabled, else the first.
32581
+ */
32582
+ pickRadioChild(children, preferredIds) {
32583
+ var _a, _b;
32584
+ return ((_b = (_a = children.find(x => preferredIds === null || preferredIds === void 0 ? void 0 : preferredIds.includes(x.id))) !== null && _a !== void 0 ? _a : children.find(x => this.items.some(y => y.id === x.id))) !== null && _b !== void 0 ? _b : children[0]);
32585
+ }
32586
+ /*
32587
+ * Removes the items so the render can claim their graphics, then disposes whatever it left unclaimed.
32588
+ */
32589
+ renderInPlaceOf(removeIds, render) {
32590
+ const pooledBefore = new Set(this.pendingHandoffPool);
32591
+ for (const id of removeIds) {
32592
+ this.RemoveItemById({
32593
+ menuItemId: id,
32594
+ allowHandoff: true
32595
+ });
32596
+ }
32597
+ const pooled = this.pendingHandoffPool.filter(x => !pooledBefore.has(x));
32598
+ try {
32599
+ return render();
32600
+ }
32601
+ finally {
32602
+ this.disposePooled(x => pooled.includes(x));
32603
+ }
32604
+ }
32241
32605
  isHandoffCapable(renderManager) {
32242
32606
  return Boolean(renderManager) && typeof renderManager.PrepareHandoff === "function";
32243
32607
  }
32608
+ isStyleSwapCapable(renderManager) {
32609
+ return Boolean(renderManager) && typeof renderManager.SwapStyle === "function";
32610
+ }
32244
32611
  // Resolves the hand-off key a menu item's data would have.
32245
32612
  computeHandoffKey(item, modelSpace) {
32246
32613
  if (item.Type === MenuItem.EType.CadTileset) {
@@ -32316,12 +32683,15 @@ var MenuItemManager;
32316
32683
  }
32317
32684
  // Disposes everything left unclaimed in the pending-hand-off pool.
32318
32685
  FlushPendingHandoffs() {
32686
+ this.disposePooled(() => true);
32687
+ }
32688
+ disposePooled(match) {
32319
32689
  var _a;
32320
32690
  if (!this.pendingHandoffPool.length) {
32321
32691
  return;
32322
32692
  }
32323
- const pool = this.pendingHandoffPool;
32324
- this.pendingHandoffPool = [];
32693
+ const pool = this.pendingHandoffPool.filter(match);
32694
+ this.pendingHandoffPool = this.pendingHandoffPool.filter(x => !match(x));
32325
32695
  for (const item of pool) {
32326
32696
  try {
32327
32697
  (_a = item.renderManager) === null || _a === void 0 ? void 0 : _a.Dispose();
@@ -32332,6 +32702,26 @@ var MenuItemManager;
32332
32702
  this.ClearSeriesSegments(item.id);
32333
32703
  }
32334
32704
  }
32705
+ /**
32706
+ * Returns the tags and attenuation the item's view authored, before any bookmark wrote over them.
32707
+ */
32708
+ GetAuthoredAlternation(item) {
32709
+ var _a;
32710
+ let authored = this.authoredAlternations.get(item);
32711
+ if (!authored) {
32712
+ const eItem = item;
32713
+ const tItem = item;
32714
+ authored = JSON.parse(JSON.stringify({
32715
+ id: item.id,
32716
+ Type: item.Type,
32717
+ BruceEntity: { SelectedExpandLayers: (_a = eItem.BruceEntity) === null || _a === void 0 ? void 0 : _a.SelectedExpandLayers },
32718
+ attenuation: tItem.attenuation,
32719
+ attenuationMax: tItem.attenuationMax
32720
+ }));
32721
+ this.authoredAlternations.set(item, authored);
32722
+ }
32723
+ return authored;
32724
+ }
32335
32725
  GetEnabledItemIds() {
32336
32726
  return this.items.map(x => x.id);
32337
32727
  }
@@ -33406,6 +33796,7 @@ var EMenuItemState;
33406
33796
  })(EMenuItemState || (EMenuItemState = {}));
33407
33797
  // Icons are inline so the library stays dependency free.
33408
33798
  const ICON_CHECK = `<svg viewBox="0 0 11 8" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1 4L4 7L10 1" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
33799
+ const ICON_RADIO = `<svg viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="6" cy="6" r="3.5" fill="white"/></svg>`;
33409
33800
  const ICON_PARTIAL_CHECK = `<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M8 12H16" stroke="white" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
33410
33801
  const ICON_CHEV_DOWN = `<svg viewBox="0 0 16 9" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M15 1L8 8L1 1" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
33411
33802
  const ICON_CHEV_RIGHT = `<svg viewBox="0 0 10 17" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1.5 1.5L8.5 8.5L1.5 15.5" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
@@ -33609,6 +34000,10 @@ class WidgetLeftPanelTabMenuItems extends WidgetLeftPanelTab.ATab {
33609
34000
  margin-right: 8px;
33610
34001
  }
33611
34002
 
34003
+ .NextspaceMenuItemRow >.NextspaceMenuItemRowItem >.NextspaceMenuItemRowCheckbox[is-radio="true"] {
34004
+ border-radius: 50%;
34005
+ }
34006
+
33612
34007
  .NextspaceMenuItemRow >.NextspaceMenuItemRowItem >.NextspaceMenuItemRowToggle {
33613
34008
  margin-right: 3px;
33614
34009
  }
@@ -33859,13 +34254,15 @@ class WidgetLeftPanelTabMenuItems extends WidgetLeftPanelTab.ATab {
33859
34254
  }
33860
34255
  return this._waitedForView ? "No view is loaded." : "Loading..";
33861
34256
  }
33862
- _renderRow(item, depth, parent) {
34257
+ _renderRow(item, depth, parent, radioParent) {
33863
34258
  var _a;
33864
34259
  if (!(item === null || item === void 0 ? void 0 : item.id)) {
33865
34260
  return;
33866
34261
  }
33867
34262
  const isFolder = !item.Type || item.Type === MenuItem.EType.None;
33868
- const children = item.hideChildren ? [] : ((_a = item.Children) !== null && _a !== void 0 ? _a : []);
34263
+ const isRadioFolder = isFolder && Boolean(item.childrenAsRadios);
34264
+ // Radios are the folder's whole point, so they show even when the folder also hides its children.
34265
+ const children = item.hideChildren && !isRadioFolder ? [] : ((_a = item.Children) !== null && _a !== void 0 ? _a : []);
33869
34266
  const hasChildren = children.length > 0;
33870
34267
  const row = document.createElement("div");
33871
34268
  row.className = "NextspaceMenuItemRow";
@@ -33897,8 +34294,9 @@ class WidgetLeftPanelTabMenuItems extends WidgetLeftPanelTab.ATab {
33897
34294
  }
33898
34295
  const checkbox = document.createElement("div");
33899
34296
  checkbox.className = "NextspaceMenuItemRowCheckbox";
34297
+ checkbox.setAttribute("is-radio", radioParent ? "true" : "false");
33900
34298
  checkbox.onclick = () => {
33901
- this._toggleItem(item);
34299
+ this._toggleItem(item, radioParent);
33902
34300
  };
33903
34301
  itemElement.appendChild(checkbox);
33904
34302
  const title = document.createElement("div");
@@ -33948,10 +34346,11 @@ class WidgetLeftPanelTabMenuItems extends WidgetLeftPanelTab.ATab {
33948
34346
  itemElement,
33949
34347
  checkboxElement: checkbox,
33950
34348
  countElement: count,
33951
- childrenElement
34349
+ childrenElement,
34350
+ radioParent
33952
34351
  });
33953
34352
  for (const child of children) {
33954
- this._renderRow(child, depth + 1, childrenElement);
34353
+ this._renderRow(child, depth + 1, childrenElement, isRadioFolder ? item : undefined);
33955
34354
  }
33956
34355
  }
33957
34356
  _getOpen(itemId, depth) {
@@ -33986,7 +34385,10 @@ class WidgetLeftPanelTabMenuItems extends WidgetLeftPanelTab.ATab {
33986
34385
  for (const row of Array.from(this._rows.values())) {
33987
34386
  const state = this._resolveState(row.item, enabledIds);
33988
34387
  row.itemElement.setAttribute("is-enabled", state === EMenuItemState.Disabled ? "false" : "true");
33989
- if (state === EMenuItemState.Enabled) {
34388
+ if (row.radioParent && state !== EMenuItemState.Disabled) {
34389
+ row.checkboxElement.innerHTML = ICON_RADIO;
34390
+ }
34391
+ else if (state === EMenuItemState.Enabled) {
33990
34392
  row.checkboxElement.innerHTML = ICON_CHECK;
33991
34393
  }
33992
34394
  else if (state === EMenuItemState.ChildEnabled) {
@@ -34001,17 +34403,33 @@ class WidgetLeftPanelTabMenuItems extends WidgetLeftPanelTab.ATab {
34001
34403
  * Works out a single item's state, rolling up children so a folder can report a partial state.
34002
34404
  */
34003
34405
  _resolveState(item, enabledIds) {
34004
- var _a;
34406
+ var _a, _b;
34005
34407
  const isFolder = !item.Type || item.Type === MenuItem.EType.None;
34006
34408
  if (!isFolder) {
34007
34409
  return enabledIds.has(item.id) ? EMenuItemState.Enabled : EMenuItemState.Disabled;
34008
34410
  }
34411
+ // Only one radio is ever enabled, so the folder is as enabled as that one.
34412
+ if (item.childrenAsRadios && ((_a = item.Children) === null || _a === void 0 ? void 0 : _a.length)) {
34413
+ const states = item.Children.map(x => this._resolveState(x, enabledIds));
34414
+ if (states.includes(EMenuItemState.Enabled)) {
34415
+ return EMenuItemState.Enabled;
34416
+ }
34417
+ return states.includes(EMenuItemState.ChildEnabled) ? EMenuItemState.ChildEnabled : EMenuItemState.Disabled;
34418
+ }
34009
34419
  // Folders derive from the leaves below them rather than their own enabled flag.
34010
34420
  let actionCount = 0;
34011
34421
  let enabledActionCount = 0;
34012
34422
  const traverse = (current) => {
34013
- var _a;
34423
+ var _a, _b;
34014
34424
  const currentIsFolder = !current.Type || current.Type === MenuItem.EType.None;
34425
+ // A radio folder counts as one choice rather than as each of its radios.
34426
+ if (currentIsFolder && current.childrenAsRadios && ((_a = current.Children) === null || _a === void 0 ? void 0 : _a.length)) {
34427
+ actionCount += 1;
34428
+ if (this._resolveState(current, enabledIds) === EMenuItemState.Enabled) {
34429
+ enabledActionCount += 1;
34430
+ }
34431
+ return;
34432
+ }
34015
34433
  if (!currentIsFolder) {
34016
34434
  actionCount += 1;
34017
34435
  if (enabledIds.has(current.id)) {
@@ -34019,11 +34437,11 @@ class WidgetLeftPanelTabMenuItems extends WidgetLeftPanelTab.ATab {
34019
34437
  }
34020
34438
  return;
34021
34439
  }
34022
- if ((_a = current.Children) === null || _a === void 0 ? void 0 : _a.length) {
34440
+ if ((_b = current.Children) === null || _b === void 0 ? void 0 : _b.length) {
34023
34441
  current.Children.forEach(traverse);
34024
34442
  }
34025
34443
  };
34026
- (_a = item.Children) === null || _a === void 0 ? void 0 : _a.forEach(traverse);
34444
+ (_b = item.Children) === null || _b === void 0 ? void 0 : _b.forEach(traverse);
34027
34445
  if (actionCount <= 0) {
34028
34446
  return enabledIds.has(item.id) ? EMenuItemState.Enabled : EMenuItemState.Disabled;
34029
34447
  }
@@ -34049,7 +34467,7 @@ class WidgetLeftPanelTabMenuItems extends WidgetLeftPanelTab.ATab {
34049
34467
  row.countElement.textContent = count.toLocaleString();
34050
34468
  }
34051
34469
  }
34052
- _toggleItem(item) {
34470
+ _toggleItem(item, radioParent) {
34053
34471
  var _a;
34054
34472
  const manager = (_a = this._widget) === null || _a === void 0 ? void 0 : _a._getManager();
34055
34473
  if (!manager) {
@@ -34057,7 +34475,21 @@ class WidgetLeftPanelTabMenuItems extends WidgetLeftPanelTab.ATab {
34057
34475
  }
34058
34476
  const enabledIds = new Set(manager.GetEnabledItemIds());
34059
34477
  const state = this._resolveState(item, enabledIds);
34060
- if (state === EMenuItemState.Enabled) {
34478
+ // A radio stays picked until another one is, the folder's own checkbox turns them all off.
34479
+ if (radioParent && state === EMenuItemState.Enabled) {
34480
+ return;
34481
+ }
34482
+ let siblingIds = [];
34483
+ if (radioParent && state === EMenuItemState.Disabled) {
34484
+ siblingIds = radioParent.Children.filter(x => x !== item).flatMap(x => this._getEnabledIdsUnder(x, enabledIds));
34485
+ }
34486
+ if (siblingIds.length) {
34487
+ manager.SwapItem({
34488
+ fromIds: siblingIds,
34489
+ item
34490
+ });
34491
+ }
34492
+ else if (state === EMenuItemState.Enabled) {
34061
34493
  this._disableItem(item);
34062
34494
  }
34063
34495
  else {
@@ -34067,6 +34499,16 @@ class WidgetLeftPanelTabMenuItems extends WidgetLeftPanelTab.ATab {
34067
34499
  }
34068
34500
  this._stateQueue.Call(true);
34069
34501
  }
34502
+ /*
34503
+ * Returns the highest enabled ids at or below the item, since removing one removes everything under it.
34504
+ */
34505
+ _getEnabledIdsUnder(item, enabledIds) {
34506
+ var _a;
34507
+ if (enabledIds.has(item.id)) {
34508
+ return [item.id];
34509
+ }
34510
+ return ((_a = item.Children) !== null && _a !== void 0 ? _a : []).flatMap(x => this._getEnabledIdsUnder(x, enabledIds));
34511
+ }
34070
34512
  _disableItem(item) {
34071
34513
  var _a, _b;
34072
34514
  const manager = (_a = this._widget) === null || _a === void 0 ? void 0 : _a._getManager();
@@ -35599,33 +36041,50 @@ var MenuItemCreator;
35599
36041
  }
35600
36042
  const renderedItemIds = [];
35601
36043
  if ((menuItems === null || menuItems === void 0 ? void 0 : menuItems.length) && (enabledIds === null || enabledIds === void 0 ? void 0 : enabledIds.length)) {
35602
- const traverseItems = async (item) => {
36044
+ const alternateItems = (item) => {
36045
+ var _a, _b, _c, _d;
36046
+ // The project view menu item contains the instruction to enable tags, the bookmark specifies which ones.
36047
+ if (item.Type == MenuItem.EType.Entities && ((_a = item.BruceEntity) === null || _a === void 0 ? void 0 : _a.ExpandLayers)) {
36048
+ const eItem = item;
36049
+ // A setting the bookmark leaves out gets the view's own value back, not the last bookmark's.
36050
+ const authored = manager.GetAuthoredAlternation(item);
36051
+ const eItemAlt = alternations[item.id];
36052
+ const tags = (_b = eItemAlt === null || eItemAlt === void 0 ? void 0 : eItemAlt.BruceEntity) === null || _b === void 0 ? void 0 : _b.SelectedExpandLayers;
36053
+ eItem.BruceEntity = {
36054
+ ...eItem.BruceEntity,
36055
+ SelectedExpandLayers: tags !== undefined ? tags : (_c = authored.BruceEntity) === null || _c === void 0 ? void 0 : _c.SelectedExpandLayers,
36056
+ };
36057
+ }
36058
+ else if (item.Type == MenuItem.EType.EntityTileset) {
36059
+ const tItem = item;
36060
+ const authored = manager.GetAuthoredAlternation(item);
36061
+ const tItemAlt = alternations[item.id];
36062
+ const hasAttenuation = (tItemAlt === null || tItemAlt === void 0 ? void 0 : tItemAlt.attenuation) !== undefined || (tItemAlt === null || tItemAlt === void 0 ? void 0 : tItemAlt.attenuationMax) !== undefined;
36063
+ const source = hasAttenuation ? tItemAlt : authored;
36064
+ tItem.attenuation = source.attenuation;
36065
+ tItem.attenuationMax = source.attenuationMax;
36066
+ }
36067
+ (_d = item.Children) === null || _d === void 0 ? void 0 : _d.forEach(alternateItems);
36068
+ };
36069
+ /*
36070
+ * Lays each picked style over a copy, so it never stays on the view's item for a later bookmark.
36071
+ */
36072
+ const styleItems = (item) => {
35603
36073
  var _a;
35604
- if (alternations[item.id]) {
35605
- // The only alternation we support right now is tag menu item ones.
35606
- // The project view menu item contains the instruction to enable tags, the bookmark specifies which ones.
35607
- if (item.Type == MenuItem.EType.Entities) {
35608
- const eItem = item;
35609
- if (eItem.BruceEntity.ExpandLayers) {
35610
- const eItemAlt = alternations[item.id];
35611
- eItem.BruceEntity = {
35612
- ...eItem.BruceEntity,
35613
- SelectedExpandLayers: (_a = eItemAlt.BruceEntity) === null || _a === void 0 ? void 0 : _a.SelectedExpandLayers,
35614
- };
35615
- }
35616
- }
35617
- else if (item.Type == MenuItem.EType.EntityTileset) {
35618
- const tItem = item;
35619
- const tItemAlt = alternations[item.id];
35620
- tItem.attenuation = tItemAlt.attenuation;
35621
- tItem.attenuationMax = tItemAlt.attenuationMax;
35622
- }
36074
+ let next = alternations[item.id] ? MenuItemStyles.ApplyAlternation(item, alternations[item.id]) : item;
36075
+ const children = (_a = item.Children) === null || _a === void 0 ? void 0 : _a.map(styleItems);
36076
+ if (children === null || children === void 0 ? void 0 : children.some((child, i) => child !== item.Children[i])) {
36077
+ next = { ...next, Children: children };
35623
36078
  }
36079
+ return next;
36080
+ };
36081
+ const traverseItems = async (item) => {
35624
36082
  if (enabledIds.includes(item.id)) {
35625
36083
  const itemId = await manager.RenderItem({
35626
36084
  item: item,
35627
36085
  getters: getters,
35628
- modelSpace: contentType === ProjectViewBookmark.EContentType.WEB_3D_MODEL_SPACE
36086
+ modelSpace: contentType === ProjectViewBookmark.EContentType.WEB_3D_MODEL_SPACE,
36087
+ preferredIds: enabledIds
35629
36088
  });
35630
36089
  renderedItemIds.push(itemId);
35631
36090
  }
@@ -35635,8 +36094,11 @@ var MenuItemCreator;
35635
36094
  }
35636
36095
  }
35637
36096
  };
35638
- for (let i = 0; i < menuItems.length; i++) {
35639
- await traverseItems(menuItems[i]);
36097
+ // Tag and attenuation alternations write into the view's items, since Navigator's tag tree reads them back.
36098
+ menuItems.forEach(alternateItems);
36099
+ const styled = menuItems.map(styleItems);
36100
+ for (let i = 0; i < styled.length; i++) {
36101
+ await traverseItems(styled[i]);
35640
36102
  }
35641
36103
  }
35642
36104
  return {
@@ -55122,7 +55584,7 @@ var StyleUtils;
55122
55584
  StyleUtils.ApplyTypeStyle = ApplyTypeStyle;
55123
55585
  })(StyleUtils || (StyleUtils = {}));
55124
55586
 
55125
- const VERSION = "7.6.2";
55587
+ const VERSION = "7.6.3";
55126
55588
  /**
55127
55589
  * Updates the environment instance used by bruce-cesium to one specified.
55128
55590
  * This can be used to ensure that the instance a parent is referencing is shared between bruce-cesium, bruce-models, and the parent app.
@@ -55139,5 +55601,5 @@ const getENVIRONMENT = () => {
55139
55601
  return ENVIRONMENT;
55140
55602
  };
55141
55603
 
55142
- export { VERSION, setENVIRONMENT, getENVIRONMENT, ClusterItems, PointClustering, PointClusterSize, CesiumAnimatedInOut, DisplacedSurfacePrimitive, CesiumAnimatedProperty, isStyleChanged, isOutlineChanged$1 as isOutlineChanged, StyleEffective, EntityRenderEngine, EntityRenderEngineModel3d, EntityRenderEnginePoint, extractMetadataFromFileUrl, EntityRenderEnginePolygon, EntityRenderEnginePolyline, TextureFrameSeriesAnimator, TextureValueLabels, MenuItemCreator, MenuItemManager, CesiumParabola, EntityLabel, EntityLabelGroup, LiveCursor, SharedGetters, EntitySimulation, DataSourceStaticKmlManager, DataLabRenderManager, EntitiesIdsRenderManager, EntitiesLoadedRenderManager, EntitiesRenderManager, EntityRenderManager, AssemblyRenderManager, GoogleSearchRenderManager, RelationsRenderManager, RenderManager, TilesetArbRenderManager, TilesetCadRenderManager, TilesetEntitiesRenderManager, TilesetGooglePhotosRenderManager, TilesetOsmRenderManager, TilesetPointcloudRenderManager, TileRenderEngine, createTileset, TilesetRenderEngine, ViewRenderEngine, VisualRegisterCuller, VisualsRegister, XGridsRenderEngine, CesiumEntityStyler, DrawingUtils, EntityUtils, MeasureUtils, StyleUtils, CESIUM_INSPECTOR_KEY, CESIUM_TIMELINE_KEY, CESIUM_TIMELINE_LIVE_KEY, CESIUM_TIMELINE_LIVE_PADDING_KEY, CESIUM_TIMELINE_INTERVAL_KEY, CESIUM_MODEL_SPACE_KEY, DEFAULT_LIVE_PADDING_SECONDS, DEFAULT_BRIGHTNESS_SHIFT, DEFAULT_LIGHT_INTENSITY, LIGHTING_SETTINGS_VERSION, LIGHT_INTENSITY_COMPENSATION, MAX_COMPENSATED_LIGHT_INTENSITY, ViewUtils, CesiumViewMonitor, ViewGroundArea, ViewerEventTracker, ViewerUtils, Draw3dPolygon, Draw3dPolyline, MeasureCreator, Walkthrough, WidgetControlViewBar, WidgetControlViewBarSearch, WidgetLeftPanelTab, WidgetLeftPanelTabBookmarks, WidgetLeftPanelTabDashboard, EMenuItemState, WidgetLeftPanelTabMenuItems, Widget, VIEWER_BOOKMARKS_WIDGET_KEY, WidgetBookmarks, WidgetBranding, ECursor, WidgetCursorBar, WidgetEmbeddedInfoView, WidgetInfoView, VIEWER_LEFT_PANEL_WIDGET_KEY, VIEWER_LEFT_PANEL_CSS_VAR_LEFT, CreateTabIconSvg, WidgetLeftPanel, WidgetNavCompass$$1 as WidgetNavCompass, VIEWER_VIEW_BAR_WIDGET_KEY, WidgetViewBar };
55604
+ export { VERSION, setENVIRONMENT, getENVIRONMENT, ClusterItems, PointClustering, PointClusterSize, CesiumAnimatedInOut, DisplacedSurfacePrimitive, CesiumAnimatedProperty, isStyleChanged, isOutlineChanged$1 as isOutlineChanged, StyleEffective, EntityRenderEngine, EntityRenderEngineModel3d, EntityRenderEnginePoint, extractMetadataFromFileUrl, EntityRenderEnginePolygon, EntityRenderEnginePolyline, TextureFrameSeriesAnimator, TextureValueLabels, MenuItemCreator, MenuItemManager, MenuItemStyles, CesiumParabola, EntityLabel, EntityLabelGroup, LiveCursor, SharedGetters, EntitySimulation, DataSourceStaticKmlManager, DataLabRenderManager, EntitiesIdsRenderManager, EntitiesLoadedRenderManager, EntitiesRenderManager, EntityRenderManager, AssemblyRenderManager, GoogleSearchRenderManager, RelationsRenderManager, RenderManager, TilesetArbRenderManager, TilesetCadRenderManager, TilesetEntitiesRenderManager, TilesetGooglePhotosRenderManager, TilesetOsmRenderManager, TilesetPointcloudRenderManager, TileRenderEngine, createTileset, TilesetRenderEngine, ViewRenderEngine, VisualRegisterCuller, VisualsRegister, XGridsRenderEngine, CesiumEntityStyler, DrawingUtils, EntityUtils, MeasureUtils, StyleUtils, CESIUM_INSPECTOR_KEY, CESIUM_TIMELINE_KEY, CESIUM_TIMELINE_LIVE_KEY, CESIUM_TIMELINE_LIVE_PADDING_KEY, CESIUM_TIMELINE_INTERVAL_KEY, CESIUM_MODEL_SPACE_KEY, DEFAULT_LIVE_PADDING_SECONDS, DEFAULT_BRIGHTNESS_SHIFT, DEFAULT_LIGHT_INTENSITY, LIGHTING_SETTINGS_VERSION, LIGHT_INTENSITY_COMPENSATION, MAX_COMPENSATED_LIGHT_INTENSITY, ViewUtils, CesiumViewMonitor, ViewGroundArea, ViewerEventTracker, ViewerUtils, Draw3dPolygon, Draw3dPolyline, MeasureCreator, Walkthrough, WidgetControlViewBar, WidgetControlViewBarSearch, WidgetLeftPanelTab, WidgetLeftPanelTabBookmarks, WidgetLeftPanelTabDashboard, EMenuItemState, WidgetLeftPanelTabMenuItems, Widget, VIEWER_BOOKMARKS_WIDGET_KEY, WidgetBookmarks, WidgetBranding, ECursor, WidgetCursorBar, WidgetEmbeddedInfoView, WidgetInfoView, VIEWER_LEFT_PANEL_WIDGET_KEY, VIEWER_LEFT_PANEL_CSS_VAR_LEFT, CreateTabIconSvg, WidgetLeftPanel, WidgetNavCompass$$1 as WidgetNavCompass, VIEWER_VIEW_BAR_WIDGET_KEY, WidgetViewBar };
55143
55605
  //# sourceMappingURL=bruce-cesium.es5.js.map