From 020963c23fda35a5e578e0321d13a820f8272ba7 Mon Sep 17 00:00:00 2001 From: Detective Squirrel <2137769+DetectiveSquirrel@users.noreply.github.com> Date: Fri, 27 Mar 2026 20:00:05 +1300 Subject: [PATCH 1/6] Ignore MinimapIcon comp on monsters and render plugin icons always --- IconsBuilder/Icons/MonsterIcon.cs | 18 +++++++++--------- IconsBuilder/IconsBuilder.cs | 9 +++++---- MapIconsSettings.cs | 7 ++++++- MinimapIcons.cs | 3 ++- 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/IconsBuilder/Icons/MonsterIcon.cs b/IconsBuilder/Icons/MonsterIcon.cs index a400670..3dc8e47 100644 --- a/IconsBuilder/Icons/MonsterIcon.cs +++ b/IconsBuilder/Icons/MonsterIcon.cs @@ -7,18 +7,19 @@ using ExileCore.Shared.Enums; using ExileCore.Shared.Helpers; using GameOffsets.Native; +using MinimapIcons; namespace MinimapIcons.IconsBuilder.Icons; public class MonsterIcon : BaseIcon { - public MonsterIcon(Entity entity, IconsBuilderSettings settings, Dictionary modIcons) + public MonsterIcon(Entity entity, IconsBuilderSettings settings, Dictionary modIcons, MapIconsSettings mapSettings) : base(entity) { - Update(entity, settings, modIcons); + Update(entity, settings, modIcons, mapSettings); } - public void Update(Entity entity, IconsBuilderSettings settings, Dictionary modIcons) + public void Update(Entity entity, IconsBuilderSettings settings, Dictionary modIcons, MapIconsSettings mapSettings) { Show = () => entity.IsAlive; if(entity.IsHidden && settings.HideBurriedMonsters) @@ -43,10 +44,11 @@ public void Update(Entity entity, IconsBuilderSettings settings, Dictionary(out var mI) && + if (_HasIngameIcon && + entity.TryGetComponent(out var mI) && mI.Name != "NPC" && - !isMonsterWithIcon) + !isMonsterWithIcon && + !mapSettings.MonstersIgnoreMinimapIconComponent) return; if (!entity.IsHostile) { @@ -73,9 +75,7 @@ public void Update(Entity entity, IconsBuilderSettings settings, Dictionary(out var minimapIconComponent) && - (!minimapIconComponent.IsHide || _plugin.Settings.IgnoreHiddenStatusMinimapIcons.Content.Any(x => GetRegex(x.Value).IsMatch(entity.Path))) && - !Settings.MonstersWithIcons.Content.Any(x => GetRegex(x.Value).IsMatch(entity.Path))) + (!minimapIconComponent.IsHide || _plugin.Settings.IgnoreHiddenStatusMinimapIcons.Content.Any(x => GetRegex(x.Value).IsMatch(entity.Path))) && + !Settings.MonstersWithIcons.Content.Any(x => GetRegex(x.Value).IsMatch(entity.Path)) && + !(entity.Type == EntityType.Monster && _plugin.Settings.MonstersIgnoreMinimapIconComponent)) { var name = minimapIconComponent.Name; if (!string.IsNullOrEmpty(name)) @@ -178,7 +179,7 @@ worldItem.Icon is var icon && if (entity.League == LeagueType.Delirium) return new DeliriumIcon(entity, Settings, AlertEntitiesWithIconSize); - return new MonsterIcon(entity, Settings, AlertEntitiesWithIconSize); + return new MonsterIcon(entity, Settings, AlertEntitiesWithIconSize, _plugin.Settings); } //NPC diff --git a/MapIconsSettings.cs b/MapIconsSettings.cs index 4195147..26cfd99 100644 --- a/MapIconsSettings.cs +++ b/MapIconsSettings.cs @@ -1,4 +1,4 @@ -using ExileCore.Shared.Attributes; +using ExileCore.Shared.Attributes; using ExileCore.Shared.Interfaces; using ExileCore.Shared.Nodes; using MinimapIcons.IconsBuilder; @@ -21,6 +21,11 @@ public class MapIconsSettings : ISettings public RangeNode IconListRefreshPeriod { get; set; } = new RangeNode(100, 0, 1000); public ToggleNode HighlightHiddenMonsters { get; set; } = new ToggleNode(true); + [Menu( + "Monsters: ignore game MinimapIcon", + "When enabled, monsters always use plugin minimap styling (rarity circles, etc.) even if the entity has a MinimapIcon component. Skips the in-game-icon replacer route and still draws on the large map while the game shows its own icon.")] + public ToggleNode MonstersIgnoreMinimapIconComponent { get; set; } = new ToggleNode(false); + [Menu(null, CollapsedByDefault = true)] public ContentNode AlwaysShownIngameIcons { get; set; } = new ContentNode() diff --git a/MinimapIcons.cs b/MinimapIcons.cs index 47ce1fd..bb02d2f 100644 --- a/MinimapIcons.cs +++ b/MinimapIcons.cs @@ -271,7 +271,8 @@ public override void Render() if (icon.HasIngameIcon && icon is not CustomIcon && (!Settings.DrawReplacementsForGameIconsWhenOutOfRange || icon.Entity.IsValid) && - !Settings.AlwaysShownIngameIcons.Content.Any(x => global::MinimapIcons.IconsBuilder.IconsBuilder.GetRegex(x.Value).IsMatch(icon.Entity.Path))) + !Settings.AlwaysShownIngameIcons.Content.Any(x => global::MinimapIcons.IconsBuilder.IconsBuilder.GetRegex(x.Value).IsMatch(icon.Entity.Path)) && + !(icon.Entity.Type == EntityType.Monster && Settings.MonstersIgnoreMinimapIconComponent)) continue; var iconGridPos = icon.GridPosition(); From e29a3de4ed0fb534809e02ba66c44acab3e95578 Mon Sep 17 00:00:00 2001 From: Detective Squirrel <2137769+DetectiveSquirrel@users.noreply.github.com> Date: Fri, 27 Mar 2026 20:38:33 +1300 Subject: [PATCH 2/6] Add monster name background drawing and colors --- IconsBuilder/Icons/BaseIcon.cs | 4 +++- IconsBuilder/Icons/MonsterIcon.cs | 32 +++++++++++++++++++++------- IconsBuilder/IconsBuilderSettings.cs | 3 +++ MinimapIcons.cs | 13 ++++++++++- 4 files changed, 42 insertions(+), 10 deletions(-) diff --git a/IconsBuilder/Icons/BaseIcon.cs b/IconsBuilder/Icons/BaseIcon.cs index e185bf7..e5c9aa6 100644 --- a/IconsBuilder/Icons/BaseIcon.cs +++ b/IconsBuilder/Icons/BaseIcon.cs @@ -116,9 +116,11 @@ public BaseIcon(Entity entity) public Func Show { get; set; } public Func Hidden { get; protected set; } = () => false; public HudTexture MainTexture { get; protected set; } - public System.Drawing.Color? BorderColor { get; protected set; } = null; + public Color? BorderColor { get; protected set; } = null; public IconPriority Priority { get; protected set; } public MonsterRarity Rarity { get; protected set; } public string Text { get; protected set; } + public Color? TextColor { get; protected set; } = null; + public Color? BackgroundColor { get; protected set; } = null; public string RenderName => Entity.RenderName; } \ No newline at end of file diff --git a/IconsBuilder/Icons/MonsterIcon.cs b/IconsBuilder/Icons/MonsterIcon.cs index 3dc8e47..139f581 100644 --- a/IconsBuilder/Icons/MonsterIcon.cs +++ b/IconsBuilder/Icons/MonsterIcon.cs @@ -91,29 +91,45 @@ public void Update(Entity entity, IconsBuilderSettings settings, Dictionary Date: Fri, 27 Mar 2026 20:39:53 +1300 Subject: [PATCH 3/6] Change reload button to be less confusing --- IconsBuilder/IconsBuilder.cs | 2 +- IconsBuilder/IconsBuilderSettings.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/IconsBuilder/IconsBuilder.cs b/IconsBuilder/IconsBuilder.cs index 41de4ee..2756816 100644 --- a/IconsBuilder/IconsBuilder.cs +++ b/IconsBuilder/IconsBuilder.cs @@ -85,7 +85,7 @@ public void AreaChange(AreaInstance area) public bool Initialise() { - Settings.ResetIcons.OnPressed = () => { IconVersion++; }; + Settings.ReloadIcons.OnPressed = () => { IconVersion++; }; ReadAlertFile(); ReadIgnoreFile(); return true; diff --git a/IconsBuilder/IconsBuilderSettings.cs b/IconsBuilder/IconsBuilderSettings.cs index 4d51770..81d7e68 100644 --- a/IconsBuilder/IconsBuilderSettings.cs +++ b/IconsBuilder/IconsBuilderSettings.cs @@ -78,7 +78,7 @@ public class IconsBuilderSettings public RangeNode SizeShrineIcon { get; set; } = new RangeNode(10, 1, 50); [JsonIgnore] - public ButtonNode ResetIcons { get; set; } = new(); + public ButtonNode ReloadIcons { get; set; } = new(); [Menu(null, CollapsedByDefault = true)] public ContentNode MonstersWithIcons { get; set; } = From 863869586ab8f3fe8e6da37455a82f25929290c9 Mon Sep 17 00:00:00 2001 From: Detective Squirrel <2137769+DetectiveSquirrel@users.noreply.github.com> Date: Fri, 27 Mar 2026 22:02:45 +1300 Subject: [PATCH 4/6] Cleanup using new graphics utils --- MinimapIcons.cs | 74 +++++++++++++------------------------------------ 1 file changed, 19 insertions(+), 55 deletions(-) diff --git a/MinimapIcons.cs b/MinimapIcons.cs index ce371ef..c5f9362 100644 --- a/MinimapIcons.cs +++ b/MinimapIcons.cs @@ -159,8 +159,6 @@ public class MinimapIcons : BaseSettingsPlugin private IngameUIElements _ingameUi; private bool? _largeMap; - private float _mapScale; - private Vector2 _mapCenter; private SubMap LargeMapWindow => GameController.Game.IngameState.IngameUi.Map.LargeMap; private CachedValue> _iconListCache; private IconsBuilder.IconsBuilder _iconsBuilder; @@ -207,17 +205,11 @@ public override Job Tick() var smallMiniMap = _ingameUi.Map.SmallMiniMap; if (smallMiniMap.IsValid && smallMiniMap.IsVisibleLocal) { - var mapRect = smallMiniMap.GetClientRectCache; - _mapCenter = mapRect.Center.ToVector2Num(); _largeMap = false; - _mapScale = smallMiniMap.MapScale; } else if (_ingameUi.Map.LargeMap.IsVisibleLocal) { - var largeMapWindow = LargeMapWindow; - _mapCenter = largeMapWindow.MapCenter; _largeMap = true; - _mapScale = largeMapWindow.MapScale; } else { @@ -229,21 +221,9 @@ public override Job Tick() public override void Render() { - if (_largeMap == null || - !GameController.InGame || - Settings.DrawOnlyOnLargeMap && _largeMap != true) - return; - - if (!Settings.IgnoreFullscreenPanels && - _ingameUi.FullscreenPanels.Any(x => x.IsVisible) || - !Settings.IgnoreLargePanels && - _ingameUi.LargePanels.Any(x => x.IsVisible)) - return; - - var playerRender = GameController?.Player?.GetComponent(); - if (playerRender == null) return; - var playerPos = playerRender.PosNum.WorldToGrid(); - var playerHeight = -playerRender.UnclampedHeight; + if (_largeMap == null || !GameController.InGame || Settings.DrawOnlyOnLargeMap && _largeMap != true) return; + + if (!Settings.IgnoreFullscreenPanels && _ingameUi.FullscreenPanels.Any(x => x.IsVisible) || !Settings.IgnoreLargePanels && _ingameUi.LargePanels.Any(x => x.IsVisible)) return; if (LargeMapWindow == null) return; @@ -254,39 +234,29 @@ public override void Render() { if (icon?.Entity == null) continue; - if (!Settings.DrawMonsters && icon.Entity.Type == EntityType.Monster) - continue; + if (!Settings.DrawMonsters && icon.Entity.Type == EntityType.Monster) continue; - if (IgnoreCache.GetOrAdd(icon.Entity.Path, () => Ignored.Any(x => icon.Entity.Path.StartsWith(x)))) - continue; + if (IgnoreCache.GetOrAdd(icon.Entity.Path, () => Ignored.Any(x => icon.Entity.Path.StartsWith(x)))) continue; - if (icon.Entity.Path.StartsWith( - "Metadata/Monsters/AtlasExiles/BasiliskInfluenceMonsters/BasiliskBurrowingViper", StringComparison.Ordinal) - && icon.Entity.Rarity != MonsterRarity.Unique) - continue; + if (icon.Entity.Path.StartsWith("Metadata/Monsters/AtlasExiles/BasiliskInfluenceMonsters/BasiliskBurrowingViper", StringComparison.Ordinal) && + icon.Entity.Rarity != MonsterRarity.Unique) continue; - if (!icon.Show()) - continue; + if (!icon.Show()) continue; if (icon.HasIngameIcon && icon is not CustomIcon && (!Settings.DrawReplacementsForGameIconsWhenOutOfRange || icon.Entity.IsValid) && !Settings.AlwaysShownIngameIcons.Content.Any(x => global::MinimapIcons.IconsBuilder.IconsBuilder.GetRegex(x.Value).IsMatch(icon.Entity.Path)) && - !(icon.Entity.Type == EntityType.Monster && Settings.MonstersIgnoreMinimapIconComponent)) - continue; - - var iconGridPos = icon.GridPosition(); - var position = _mapCenter + - DeltaInWorldToMinimapDelta(iconGridPos - playerPos, - (playerHeight + GameController.IngameState.Data.GetTerrainHeightAt(iconGridPos)) * PoeMapExtension.WorldToGridConversion); + !(icon.Entity.Type == EntityType.Monster && Settings.MonstersIgnoreMinimapIconComponent)) continue; var iconValueMainTexture = icon.MainTexture; var size = iconValueMainTexture.Size; var halfSize = size / 2f; - icon.DrawRect = new RectangleF(position.X - halfSize, position.Y - halfSize, size, size); + var mapScreenPos = _largeMap == true ? Graphics.GridToLargeMap(icon.Entity.PosNum) : Graphics.GridToSmallMap(icon.Entity.PosNum); + + icon.DrawRect = new RectangleF(mapScreenPos.X - halfSize, mapScreenPos.Y - halfSize, size, size); var drawRect = icon.DrawRect; - if (_largeMap == false && !_ingameUi.Map.SmallMiniMap.GetClientRectCache.Contains(drawRect)) - continue; + if (_largeMap == false && !_ingameUi.Map.SmallMiniMap.GetClientRectCache.Contains(drawRect)) continue; Graphics.DrawImage(iconValueMainTexture.FileName, drawRect, iconValueMainTexture.UV, iconValueMainTexture.Color.ToSharpDx()); if (icon.BorderColor is { } borderColor) @@ -299,36 +269,30 @@ icon is not CustomIcon && var s = drawRect.Width * 0.1f; drawRect.Inflate(-s, -s); - Graphics.DrawImage("Icons.png", drawRect, - SpriteHelper.GetUV(MapIconsIndex.LootFilterSmallWhiteCircle), Color.White); + Graphics.DrawImage("Icons.png", drawRect, SpriteHelper.GetUV(MapIconsIndex.LootFilterSmallWhiteCircle), Color.White); drawRect.Inflate(s, s); } if (!string.IsNullOrEmpty(icon.Text)) { - var textPos = position.Translate(0, Settings.ZForText); + var textPos = mapScreenPos.Translate(0, Settings.ZForText); if (icon.BackgroundColor is { } bg) { var textColor = icon.TextColor?.ToSharpDx() ?? Color.White; Graphics.DrawTextWithBackground(icon.Text, textPos, textColor, FontAlign.Center, bg.ToSharpDx()); } else if (icon.TextColor is { } tc) + { Graphics.DrawText(icon.Text, textPos, tc.ToSharpDx(), FontAlign.Center); + } else + { Graphics.DrawText(icon.Text, textPos, FontAlign.Center); + } } } } - - private const float CameraAngle = 38.7f * MathF.PI / 180; - private static readonly float CameraAngleCos = MathF.Cos(CameraAngle); - private static readonly float CameraAngleSin = MathF.Sin(CameraAngle); - - private Vector2 DeltaInWorldToMinimapDelta(Vector2 delta, float deltaZ) - { - return _mapScale * Vector2.Multiply(new Vector2(delta.X - delta.Y, deltaZ - (delta.X + delta.Y)), new Vector2(CameraAngleCos, CameraAngleSin)); - } } public static class Extensions From 85c544f5c4cd80c94b78d8a0224bc7d4b261c7d7 Mon Sep 17 00:00:00 2001 From: Detective Squirrel <2137769+DetectiveSquirrel@users.noreply.github.com> Date: Fri, 27 Mar 2026 22:23:47 +1300 Subject: [PATCH 5/6] Property should be self explanatory on second thought --- MapIconsSettings.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/MapIconsSettings.cs b/MapIconsSettings.cs index 26cfd99..b7c7508 100644 --- a/MapIconsSettings.cs +++ b/MapIconsSettings.cs @@ -20,10 +20,6 @@ public class MapIconsSettings : ISettings public ToggleNode Enable { get; set; } = new ToggleNode(true); public RangeNode IconListRefreshPeriod { get; set; } = new RangeNode(100, 0, 1000); public ToggleNode HighlightHiddenMonsters { get; set; } = new ToggleNode(true); - - [Menu( - "Monsters: ignore game MinimapIcon", - "When enabled, monsters always use plugin minimap styling (rarity circles, etc.) even if the entity has a MinimapIcon component. Skips the in-game-icon replacer route and still draws on the large map while the game shows its own icon.")] public ToggleNode MonstersIgnoreMinimapIconComponent { get; set; } = new ToggleNode(false); [Menu(null, CollapsedByDefault = true)] From 217f5a794449fda3943c166c8abbd9f429ed7c02 Mon Sep 17 00:00:00 2001 From: Detective Squirrel <2137769+DetectiveSquirrel@users.noreply.github.com> Date: Sat, 28 Mar 2026 22:27:54 +1300 Subject: [PATCH 6/6] Use new Graphics utils --- MinimapIcons.cs | 92 ++++++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 50 deletions(-) diff --git a/MinimapIcons.cs b/MinimapIcons.cs index c5f9362..6682be4 100644 --- a/MinimapIcons.cs +++ b/MinimapIcons.cs @@ -4,7 +4,6 @@ using System.Linq; using ExileCore; using ExileCore.PoEMemory.Components; -using ExileCore.PoEMemory.Elements; using ExileCore.PoEMemory.MemoryObjects; using ExileCore.Shared.Cache; using ExileCore.Shared.Enums; @@ -159,7 +158,6 @@ public class MinimapIcons : BaseSettingsPlugin private IngameUIElements _ingameUi; private bool? _largeMap; - private SubMap LargeMapWindow => GameController.Game.IngameState.IngameUi.Map.LargeMap; private CachedValue> _iconListCache; private IconsBuilder.IconsBuilder _iconsBuilder; private IconsBuilder.IconsBuilder IconsBuilder => _iconsBuilder ??= new IconsBuilder.IconsBuilder(this); @@ -225,70 +223,64 @@ public override void Render() if (!Settings.IgnoreFullscreenPanels && _ingameUi.FullscreenPanels.Any(x => x.IsVisible) || !Settings.IgnoreLargePanels && _ingameUi.LargePanels.Any(x => x.IsVisible)) return; - if (LargeMapWindow == null) return; - var baseIcons = _iconListCache.Value; if (baseIcons == null) return; - foreach (var icon in baseIcons) + using (Graphics.MapSurfaceClip()) { - if (icon?.Entity == null) continue; - - if (!Settings.DrawMonsters && icon.Entity.Type == EntityType.Monster) continue; + foreach (var icon in baseIcons) + { + if (icon?.Entity == null) continue; - if (IgnoreCache.GetOrAdd(icon.Entity.Path, () => Ignored.Any(x => icon.Entity.Path.StartsWith(x)))) continue; + if (!Settings.DrawMonsters && icon.Entity.Type == EntityType.Monster) continue; - if (icon.Entity.Path.StartsWith("Metadata/Monsters/AtlasExiles/BasiliskInfluenceMonsters/BasiliskBurrowingViper", StringComparison.Ordinal) && - icon.Entity.Rarity != MonsterRarity.Unique) continue; + if (IgnoreCache.GetOrAdd(icon.Entity.Path, () => Ignored.Any(x => icon.Entity.Path.StartsWith(x)))) continue; - if (!icon.Show()) continue; + if (icon.Entity.Path.StartsWith("Metadata/Monsters/AtlasExiles/BasiliskInfluenceMonsters/BasiliskBurrowingViper", StringComparison.Ordinal) && + icon.Entity.Rarity != MonsterRarity.Unique) continue; - if (icon.HasIngameIcon && - icon is not CustomIcon && - (!Settings.DrawReplacementsForGameIconsWhenOutOfRange || icon.Entity.IsValid) && - !Settings.AlwaysShownIngameIcons.Content.Any(x => global::MinimapIcons.IconsBuilder.IconsBuilder.GetRegex(x.Value).IsMatch(icon.Entity.Path)) && - !(icon.Entity.Type == EntityType.Monster && Settings.MonstersIgnoreMinimapIconComponent)) continue; + if (!icon.Show()) continue; - var iconValueMainTexture = icon.MainTexture; - var size = iconValueMainTexture.Size; - var halfSize = size / 2f; - var mapScreenPos = _largeMap == true ? Graphics.GridToLargeMap(icon.Entity.PosNum) : Graphics.GridToSmallMap(icon.Entity.PosNum); + if (icon.HasIngameIcon && + icon is not CustomIcon && + (!Settings.DrawReplacementsForGameIconsWhenOutOfRange || icon.Entity.IsValid) && + !Settings.AlwaysShownIngameIcons.Content.Any(x => global::MinimapIcons.IconsBuilder.IconsBuilder.GetRegex(x.Value).IsMatch(icon.Entity.Path)) && + !(icon.Entity.Type == EntityType.Monster && Settings.MonstersIgnoreMinimapIconComponent)) continue; - icon.DrawRect = new RectangleF(mapScreenPos.X - halfSize, mapScreenPos.Y - halfSize, size, size); - var drawRect = icon.DrawRect; - if (_largeMap == false && !_ingameUi.Map.SmallMiniMap.GetClientRectCache.Contains(drawRect)) continue; + var iconValueMainTexture = icon.MainTexture; + var size = iconValueMainTexture.Size; + var halfSize = size / 2f; + var mapScreenPos = Graphics.GridToMap(icon.Entity.PosNum); - Graphics.DrawImage(iconValueMainTexture.FileName, drawRect, iconValueMainTexture.UV, iconValueMainTexture.Color.ToSharpDx()); - if (icon.BorderColor is { } borderColor) - { - Graphics.DrawFrame(drawRect, borderColor.ToSharpDx(), 1); - } - - if (Settings.HighlightHiddenMonsters && icon.Hidden()) - { - var s = drawRect.Width * 0.1f; - drawRect.Inflate(-s, -s); + icon.DrawRect = new RectangleF(mapScreenPos.X - halfSize, mapScreenPos.Y - halfSize, size, size); + var drawRect = icon.DrawRect; - Graphics.DrawImage("Icons.png", drawRect, SpriteHelper.GetUV(MapIconsIndex.LootFilterSmallWhiteCircle), Color.White); + Graphics.DrawImageMap(iconValueMainTexture.FileName, iconValueMainTexture.UV, iconValueMainTexture.Color.ToSharpDx(), icon.Entity.PosNum, size); + if (icon.BorderColor is { } borderColor) + Graphics.DrawFrame(drawRect, borderColor.ToSharpDx(), 1); - drawRect.Inflate(s, s); - } - - if (!string.IsNullOrEmpty(icon.Text)) - { - var textPos = mapScreenPos.Translate(0, Settings.ZForText); - if (icon.BackgroundColor is { } bg) + if (Settings.HighlightHiddenMonsters && icon.Hidden()) { - var textColor = icon.TextColor?.ToSharpDx() ?? Color.White; - Graphics.DrawTextWithBackground(icon.Text, textPos, textColor, FontAlign.Center, bg.ToSharpDx()); + var inset = size * 0.1f; + Graphics.DrawImageMap("Icons.png", SpriteHelper.GetUV(MapIconsIndex.LootFilterSmallWhiteCircle), Color.White, icon.Entity.PosNum, size - 2f * inset); } - else if (icon.TextColor is { } tc) - { - Graphics.DrawText(icon.Text, textPos, tc.ToSharpDx(), FontAlign.Center); - } - else + + if (!string.IsNullOrEmpty(icon.Text)) { - Graphics.DrawText(icon.Text, textPos, FontAlign.Center); + var textPos = mapScreenPos.Translate(0, Settings.ZForText); + if (icon.BackgroundColor is { } bg) + { + var textColor = icon.TextColor?.ToSharpDx() ?? Color.White; + Graphics.DrawTextWithBackground(icon.Text, textPos, textColor, FontAlign.Center, bg.ToSharpDx()); + } + else if (icon.TextColor is { } tc) + { + Graphics.DrawText(icon.Text, textPos, tc.ToSharpDx(), FontAlign.Center); + } + else + { + Graphics.DrawText(icon.Text, textPos, FontAlign.Center); + } } } }