diff --git a/MareSynchronos/MareConfiguration/Configurations/PlayerPerformanceConfig.cs b/MareSynchronos/MareConfiguration/Configurations/PlayerPerformanceConfig.cs
index 6b45ac7..74ab455 100644
--- a/MareSynchronos/MareConfiguration/Configurations/PlayerPerformanceConfig.cs
+++ b/MareSynchronos/MareConfiguration/Configurations/PlayerPerformanceConfig.cs
@@ -8,9 +8,10 @@ public class PlayerPerformanceConfig : IMareConfiguration
public bool AutoPausePlayersExceedingThresholds { get; set; } = true;
public bool NotifyAutoPauseDirectPairs { get; set; } = true;
public bool NotifyAutoPauseGroupPairs { get; set; } = true;
+ public bool ShowSelfAnalysisWarnings { get; set; } = true;
public int VRAMSizeAutoPauseThresholdMiB { get; set; } = 500;
public int TrisAutoPauseThresholdThousands { get; set; } = 400;
public bool IgnoreDirectPairs { get; set; } = true;
public TextureShrinkMode TextureShrinkMode { get; set; } = TextureShrinkMode.Default;
public bool TextureShrinkDeleteOriginal { get; set; } = false;
-}
\ No newline at end of file
+}
diff --git a/MareSynchronos/MareSynchronos.csproj b/MareSynchronos/MareSynchronos.csproj
index d403e3f..0b7986d 100644
--- a/MareSynchronos/MareSynchronos.csproj
+++ b/MareSynchronos/MareSynchronos.csproj
@@ -3,7 +3,7 @@
UmbraSync
UmbraSync
- 0.1.9.6
+ 0.1.9.9
diff --git a/MareSynchronos/Services/AutoDetect/NearbyDiscoveryService.cs b/MareSynchronos/Services/AutoDetect/NearbyDiscoveryService.cs
index 6baa786..ed73905 100644
--- a/MareSynchronos/Services/AutoDetect/NearbyDiscoveryService.cs
+++ b/MareSynchronos/Services/AutoDetect/NearbyDiscoveryService.cs
@@ -8,6 +8,7 @@ using MareSynchronos.WebAPI.AutoDetect;
using Dalamud.Plugin.Services;
using System.Numerics;
using System.Linq;
+using System.Collections.Generic;
using MareSynchronos.Utils;
namespace MareSynchronos.Services.AutoDetect;
@@ -35,6 +36,8 @@ public class NearbyDiscoveryService : IHostedService, IMediatorSubscriber
private bool _lastAutoDetectState;
private DateTime _lastHeartbeat = DateTime.MinValue;
private static readonly TimeSpan HeartbeatInterval = TimeSpan.FromSeconds(75);
+ private readonly object _entriesLock = new();
+ private List _lastEntries = [];
public NearbyDiscoveryService(ILogger logger, MareMediator mediator,
MareConfigService config, DiscoveryConfigProvider configProvider, DalamudUtilService dalamudUtilService,
@@ -134,6 +137,22 @@ public class NearbyDiscoveryService : IHostedService, IMediatorSubscriber
return Task.CompletedTask;
}
+ public List SnapshotEntries()
+ {
+ lock (_entriesLock)
+ {
+ return _lastEntries.ToList();
+ }
+ }
+
+ private void UpdateSnapshot(List entries)
+ {
+ lock (_entriesLock)
+ {
+ _lastEntries = entries.ToList();
+ }
+ }
+
private static void CancelAndDispose(ref CancellationTokenSource? cts)
{
if (cts == null) return;
@@ -443,6 +462,7 @@ public class NearbyDiscoveryService : IHostedService, IMediatorSubscriber
_logger.LogDebug("Nearby: well-known not available or disabled; running in local-only mode");
}
}
+ UpdateSnapshot(entries);
_mediator.Publish(new DiscoveryListUpdated(entries));
var delayMs = Math.Max(1000, _configProvider.MinQueryIntervalMs);
diff --git a/MareSynchronos/Services/CharacterAnalyzer.cs b/MareSynchronos/Services/CharacterAnalyzer.cs
index 65b2cbd..6352890 100644
--- a/MareSynchronos/Services/CharacterAnalyzer.cs
+++ b/MareSynchronos/Services/CharacterAnalyzer.cs
@@ -4,6 +4,7 @@ using Lumina.Data.Files;
using MareSynchronos.API.Data;
using MareSynchronos.API.Data.Enum;
using MareSynchronos.FileCache;
+using MareSynchronos.MareConfiguration;
using MareSynchronos.MareConfiguration.Models;
using MareSynchronos.Services.Mediator;
using MareSynchronos.UI;
@@ -29,8 +30,9 @@ public sealed class CharacterAnalyzer : DisposableMediatorSubscriberBase
private const long NotificationTriangleThreshold = 150_000;
private bool _sizeWarningShown;
private bool _triangleWarningShown;
+ private readonly PlayerPerformanceConfigService _playerPerformanceConfigService;
- public CharacterAnalyzer(ILogger logger, MareMediator mediator, FileCacheManager fileCacheManager, XivDataAnalyzer modelAnalyzer)
+ public CharacterAnalyzer(ILogger logger, MareMediator mediator, FileCacheManager fileCacheManager, XivDataAnalyzer modelAnalyzer, PlayerPerformanceConfigService playerPerformanceConfigService)
: base(logger, mediator)
{
Mediator.Subscribe(this, (msg) =>
@@ -41,6 +43,7 @@ public sealed class CharacterAnalyzer : DisposableMediatorSubscriberBase
});
_fileCacheManager = fileCacheManager;
_xivDataAnalyzer = modelAnalyzer;
+ _playerPerformanceConfigService = playerPerformanceConfigService;
}
public int CurrentFile { get; internal set; }
@@ -313,6 +316,12 @@ public sealed class CharacterAnalyzer : DisposableMediatorSubscriberBase
return;
}
+ if (!_playerPerformanceConfigService.Current.ShowSelfAnalysisWarnings)
+ {
+ ResetThresholdFlagsIfNeeded(summary);
+ return;
+ }
+
bool sizeExceeded = summary.TotalCompressedSize >= NotificationSizeThreshold;
bool trianglesExceeded = summary.TotalTriangles >= NotificationTriangleThreshold;
List exceededReasons = new();
diff --git a/MareSynchronos/UI/AutoDetectUi.cs b/MareSynchronos/UI/AutoDetectUi.cs
index f58ef79..e926e96 100644
--- a/MareSynchronos/UI/AutoDetectUi.cs
+++ b/MareSynchronos/UI/AutoDetectUi.cs
@@ -24,14 +24,16 @@ public class AutoDetectUi : WindowMediatorSubscriberBase
private readonly MareConfigService _configService;
private readonly DalamudUtilService _dalamud;
private readonly AutoDetectRequestService _requestService;
+ private readonly NearbyDiscoveryService _discoveryService;
private readonly NearbyPendingService _pendingService;
private readonly PairManager _pairManager;
- private List _entries = new();
+ private List _entries;
private readonly HashSet _acceptInFlight = new(StringComparer.Ordinal);
public AutoDetectUi(ILogger logger, MareMediator mediator,
MareConfigService configService, DalamudUtilService dalamudUtilService,
AutoDetectRequestService requestService, NearbyPendingService pendingService, PairManager pairManager,
+ NearbyDiscoveryService discoveryService,
PerformanceCollectorService performanceCollectorService)
: base(logger, mediator, "AutoDetect", performanceCollectorService)
{
@@ -40,6 +42,9 @@ public class AutoDetectUi : WindowMediatorSubscriberBase
_requestService = requestService;
_pendingService = pendingService;
_pairManager = pairManager;
+ _discoveryService = discoveryService;
+ Mediator.Subscribe(this, OnDiscoveryUpdated);
+ _entries = _discoveryService.SnapshotEntries();
Flags |= ImGuiWindowFlags.NoScrollbar;
SizeConstraints = new WindowSizeConstraints()
@@ -214,61 +219,102 @@ public class AutoDetectUi : WindowMediatorSubscriberBase
ImGuiHelpers.ScaledDummy(6);
- // Table header
- if (ImGui.BeginTable("autodetect-nearby", 5, ImGuiTableFlags.SizingStretchProp))
- {
- ImGui.TableSetupColumn("Name");
- ImGui.TableSetupColumn("World");
- ImGui.TableSetupColumn("Distance");
- ImGui.TableSetupColumn("Status");
- ImGui.TableSetupColumn("Action");
- ImGui.TableHeadersRow();
+ var sourceEntries = _entries.Count > 0 ? _entries : _discoveryService.SnapshotEntries();
+ var orderedEntries = sourceEntries
+ .OrderBy(e => float.IsNaN(e.Distance) ? float.MaxValue : e.Distance)
+ .ToList();
- var data = _entries.Count > 0 ? _entries.Where(e => e.IsMatch).ToList() : new List();
- foreach (var e in data)
+ if (orderedEntries.Count == 0)
+ {
+ UiSharedService.ColorTextWrapped("Aucune présence UmbraSync détectée à proximité pour le moment.", ImGuiColors.DalamudGrey3);
+ return;
+ }
+
+ if (!ImGui.BeginTable("autodetect-nearby", 5, ImGuiTableFlags.SizingStretchProp | ImGuiTableFlags.RowBg))
+ {
+ return;
+ }
+
+ ImGui.TableSetupColumn("Nom");
+ ImGui.TableSetupColumn("Monde");
+ ImGui.TableSetupColumn("Distance");
+ ImGui.TableSetupColumn("Statut");
+ ImGui.TableSetupColumn("Action");
+ ImGui.TableHeadersRow();
+
+ for (int i = 0; i < orderedEntries.Count; i++)
+ {
+ var entry = orderedEntries[i];
+ bool isMatch = entry.IsMatch;
+ bool alreadyPaired = IsAlreadyPairedByUidOrAlias(entry);
+ bool overDistance = !float.IsNaN(entry.Distance) && entry.Distance > maxDist;
+ bool canRequest = isMatch && entry.AcceptPairRequests && !string.IsNullOrEmpty(entry.Token) && !alreadyPaired;
+
+ string displayName = entry.DisplayName ?? entry.Name;
+ string worldName = entry.WorldId == 0
+ ? "-"
+ : (_dalamud.WorldData.Value.TryGetValue(entry.WorldId, out var mappedWorld) ? mappedWorld : entry.WorldId.ToString(CultureInfo.InvariantCulture));
+ string distanceText = float.IsNaN(entry.Distance) ? "-" : $"{entry.Distance:0.0} m";
+
+ string status = alreadyPaired
+ ? "Déjà appairé"
+ : overDistance
+ ? $"Hors portée (> {maxDist} m)"
+ : !isMatch
+ ? "Umbra non activé"
+ : !entry.AcceptPairRequests
+ ? "Invitations refusées"
+ : string.IsNullOrEmpty(entry.Token)
+ ? "Indisponible"
+ : "Disponible";
+
+ ImGui.TableNextColumn();
+ ImGui.TextUnformatted(displayName);
+
+ ImGui.TableNextColumn();
+ ImGui.TextUnformatted(worldName);
+
+ ImGui.TableNextColumn();
+ ImGui.TextUnformatted(distanceText);
+
+ ImGui.TableNextColumn();
+ ImGui.TextUnformatted(status);
+
+ ImGui.TableNextColumn();
+ using (ImRaii.PushId(i))
{
- ImGui.TableNextColumn();
- ImGui.TextUnformatted(e.Name);
- ImGui.TableNextColumn();
- ImGui.TextUnformatted(e.WorldId == 0 ? "-" : (_dalamud.WorldData.Value.TryGetValue(e.WorldId, out var w) ? w : e.WorldId.ToString()));
- ImGui.TableNextColumn();
- ImGui.TextUnformatted(float.IsNaN(e.Distance) ? "-" : $"{e.Distance:0.0} m");
- ImGui.TableNextColumn();
- bool alreadyPaired = IsAlreadyPairedByUidOrAlias(e);
- string status = alreadyPaired ? "Paired" : (string.IsNullOrEmpty(e.Token) ? "Requests disabled" : "On Umbra");
- ImGui.TextUnformatted(status);
- ImGui.TableNextColumn();
- using (ImRaii.Disabled(alreadyPaired || string.IsNullOrEmpty(e.Token)))
+ if (canRequest && !overDistance)
{
- if (alreadyPaired)
+ if (ImGui.Button("Envoyer invitation"))
{
- ImGui.Button($"Already sync##{e.Name}");
+ _ = _requestService.SendRequestAsync(entry.Token!, entry.Uid, entry.DisplayName);
}
- else if (string.IsNullOrEmpty(e.Token))
+ UiSharedService.AttachToolTip("Envoie une demande d'appairage via AutoDetect.");
+ }
+ else
+ {
+ string reason = alreadyPaired
+ ? "Vous êtes déjà appairé avec ce joueur."
+ : overDistance
+ ? $"Ce joueur est au-delà de la distance maximale configurée ({maxDist} m)."
+ : !isMatch
+ ? "Ce joueur n'utilise pas UmbraSync ou ne s'est pas rendu détectable."
+ : !entry.AcceptPairRequests
+ ? "Ce joueur a désactivé la réception automatique des invitations."
+ : string.IsNullOrEmpty(entry.Token)
+ ? "Impossible d'obtenir un jeton d'invitation pour ce joueur."
+ : string.Empty;
+
+ ImGui.TextDisabled(status);
+ if (!string.IsNullOrEmpty(reason))
{
- ImGui.Button($"Requests disabled##{e.Name}");
- }
- else if (ImGui.Button($"Send request##{e.Name}"))
- {
- _ = _requestService.SendRequestAsync(e.Token!, e.Uid, e.DisplayName);
+ UiSharedService.AttachToolTip(reason);
}
}
}
-
- ImGui.EndTable();
}
- }
- public override void OnOpen()
- {
- base.OnOpen();
- Mediator.Subscribe(this, OnDiscoveryUpdated);
- }
-
- public override void OnClose()
- {
- Mediator.Unsubscribe(this);
- base.OnClose();
+ ImGui.EndTable();
}
private void OnDiscoveryUpdated(Services.Mediator.DiscoveryListUpdated msg)
diff --git a/MareSynchronos/UI/CompactUI.cs b/MareSynchronos/UI/CompactUI.cs
index 5ad5319..3ab7c67 100644
--- a/MareSynchronos/UI/CompactUI.cs
+++ b/MareSynchronos/UI/CompactUI.cs
@@ -76,7 +76,7 @@ public class CompactUi : WindowMediatorSubscriberBase
private CompactUiSection _activeSection = CompactUiSection.VisiblePairs;
private const float SidebarWidth = 42f;
private const float SidebarIconSize = 22f;
- private const float ContentFontScale = 0.92f;
+ private const float ContentFontScale = UiSharedService.ContentFontScale;
private static readonly Vector4 SidebarButtonColor = new(0.08f, 0.08f, 0.10f, 0.92f);
private static readonly Vector4 SidebarButtonHoverColor = new(0.12f, 0.12f, 0.16f, 0.95f);
private static readonly Vector4 SidebarButtonActiveColor = new(0.16f, 0.16f, 0.22f, 0.95f);
@@ -186,7 +186,7 @@ public class CompactUi : WindowMediatorSubscriberBase
ImGui.SetCursorPosY(ImGui.GetCursorPosY() - ImGui.GetStyle().WindowPadding.Y - 1f * ImGuiHelpers.GlobalScale + ImGui.GetStyle().ItemSpacing.Y);
var sidebarWidth = ImGuiHelpers.ScaledVector2(SidebarWidth, 0).X;
- ImGui.SetWindowFontScale(ContentFontScale);
+ using var fontScale = UiSharedService.PushFontScale(ContentFontScale);
ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, ImGui.GetStyle().FramePadding * ContentFontScale);
ImGui.BeginChild("compact-sidebar", new Vector2(sidebarWidth, 0), false, ImGuiWindowFlags.NoScrollbar);
@@ -232,7 +232,6 @@ public class CompactUi : WindowMediatorSubscriberBase
}
ImGui.PopStyleVar();
- ImGui.SetWindowFontScale(1f);
}
public override void OnClose()
@@ -735,7 +734,6 @@ if (showNearby && pendingInvites > 0)
}
else
{
- var visibleUsers = visibleUsersSource.Select(c => new DrawUserPair("Visible" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager, _serverManager)).ToList();
var onlineUsers = nonVisibleUsers.Where(u => u.UserPair!.OtherPermissions.IsPaired() && (u.IsOnline || u.UserPair!.OwnPermissions.IsPaused()))
.Select(c => new DrawUserPair("Online" + c.UserData.UID, c, _uidDisplayHandler, _apiController, Mediator, _selectGroupForPairUi, _uiSharedService, _charaDataManager, _serverManager))
.ToList();
@@ -750,7 +748,7 @@ if (showNearby && pendingInvites > 0)
drawVisibleExtras = () => DrawNearbyCard(entriesForExtras);
}
- _pairGroupsUi.Draw(visibleUsers, onlineUsers, offlineUsers, drawVisibleExtras);
+ _pairGroupsUi.Draw(Array.Empty().ToList(), onlineUsers, offlineUsers, drawVisibleExtras);
}
ImGui.EndChild();
@@ -1289,7 +1287,7 @@ if (showNearby && pendingInvites > 0)
}
var originalPos = ImGui.GetCursorPos();
- ImGui.SetWindowFontScale(1.5f);
+ UiSharedService.SetFontScale(1.5f);
Vector2 buttonSize = Vector2.Zero;
float spacingX = ImGui.GetStyle().ItemSpacing.X;
@@ -1307,7 +1305,7 @@ if (showNearby && pendingInvites > 0)
}
ImGui.SetCursorPos(originalPos);
- ImGui.SetWindowFontScale(1f);
+ UiSharedService.SetFontScale(1f);
float referenceHeight = buttonSize.Y > 0f ? buttonSize.Y : ImGui.GetFrameHeight();
ImGui.SetCursorPosY(originalPos.Y + referenceHeight / 2f - uidTextSize.Y / 2f - spacingX / 2f);
diff --git a/MareSynchronos/UI/Components/DrawGroupPair.cs b/MareSynchronos/UI/Components/DrawGroupPair.cs
index dc96bfb..ec15593 100644
--- a/MareSynchronos/UI/Components/DrawGroupPair.cs
+++ b/MareSynchronos/UI/Components/DrawGroupPair.cs
@@ -201,7 +201,7 @@ public class DrawGroupPair : DrawPairBase
var individualVFXDisabled = (_pair.UserPair?.OwnPermissions.IsDisableVFX() ?? false) || (_pair.UserPair?.OtherPermissions.IsDisableVFX() ?? false);
bool showShared = _charaDataManager.SharedWithYouData.TryGetValue(_pair.UserData, out var sharedData);
- bool showInfo = (individualAnimDisabled || individualSoundsDisabled || animDisabled || soundsDisabled);
+ bool showInfo = (individualAnimDisabled || individualSoundsDisabled || individualVFXDisabled || animDisabled || soundsDisabled || vfxDisabled);
bool showPlus = _pair.UserPair == null && _pair.IsOnline;
bool showBars = (userIsOwner || (userIsModerator && !entryIsMod && !entryIsOwner)) || !_pair.IsPaused;
bool showPause = true;
@@ -267,7 +267,7 @@ public class DrawGroupPair : DrawPairBase
if (showInfo && infoIconWidth > 0f)
{
ImGui.SetCursorPosY(textPosY);
- if (individualAnimDisabled || individualSoundsDisabled)
+ if (individualAnimDisabled || individualSoundsDisabled || individualVFXDisabled)
{
ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudYellow);
_uiSharedService.IconText(permIcon);
diff --git a/MareSynchronos/UI/Components/GroupPanel.cs b/MareSynchronos/UI/Components/GroupPanel.cs
index 4a2ae22..a8b6d90 100644
--- a/MareSynchronos/UI/Components/GroupPanel.cs
+++ b/MareSynchronos/UI/Components/GroupPanel.cs
@@ -91,6 +91,7 @@ internal sealed class GroupPanel
public void DrawSyncshells()
{
+ using var fontScale = UiSharedService.PushFontScale(UiSharedService.ContentFontScale);
using (ImRaii.PushId("addsyncshell")) DrawAddSyncshell();
using (ImRaii.PushId("syncshelllist")) DrawSyncshellList();
_mainUi.TransferPartHeight = ImGui.GetCursorPosY();
@@ -613,7 +614,7 @@ internal sealed class GroupPanel
ImGui.Separator();
}
ImGui.Unindent(20);
- }, background: new Vector4(0.15f, 0.15f, 0.20f, 0.94f), border: new Vector4(0f, 0f, 0f, 0.78f), stretchWidth: true);
+ }, stretchWidth: true);
ImGuiHelpers.ScaledDummy(4f);
}
diff --git a/MareSynchronos/UI/Components/PairGroupsUi.cs b/MareSynchronos/UI/Components/PairGroupsUi.cs
index 7bb296c..fd4293b 100644
--- a/MareSynchronos/UI/Components/PairGroupsUi.cs
+++ b/MareSynchronos/UI/Components/PairGroupsUi.cs
@@ -198,10 +198,7 @@ public class PairGroupsUi
private void DrawUserPairs(List tagsWithPairsInThem, List allUsers, IEnumerable visibleUsers, IEnumerable onlineUsers, IEnumerable offlineUsers, Action? drawVisibleExtras)
{
- if (_mareConfig.Current.ShowVisibleUsersSeparately)
- {
- using (ImRaii.PushId("$group-VisibleCustomTag")) DrawCategory(TagHandler.CustomVisibleTag, visibleUsers, allUsers, drawExtraContent: drawVisibleExtras);
- }
+ // Visible section intentionally omitted for Individual Pairs view.
foreach (var tag in tagsWithPairsInThem)
{
if (_mareConfig.Current.ShowOfflineUsersSeparately)
diff --git a/MareSynchronos/UI/IntroUI.cs b/MareSynchronos/UI/IntroUI.cs
index 726fe66..bba67c1 100644
--- a/MareSynchronos/UI/IntroUI.cs
+++ b/MareSynchronos/UI/IntroUI.cs
@@ -144,12 +144,12 @@ public partial class IntroUi : WindowMediatorSubscriberBase
}
ImGui.Separator();
- ImGui.SetWindowFontScale(1.5f);
+ UiSharedService.SetFontScale(1.5f);
string readThis = "MERCI DE LIRE ATTENTIVEMENT";
Vector2 textSize = ImGui.CalcTextSize(readThis);
ImGui.SetCursorPosX(ImGui.GetWindowSize().X / 2 - textSize.X / 2);
UiSharedService.ColorText(readThis, UiSharedService.AccentColor);
- ImGui.SetWindowFontScale(1.0f);
+ UiSharedService.SetFontScale(1.0f);
ImGui.Separator();
UiSharedService.TextWrapped("""
Pour utiliser les services UmbraSync, vous devez être âgé de plus de 18 ans, où plus de 21 ans dans certaines juridictions.
diff --git a/MareSynchronos/UI/SettingsUi.cs b/MareSynchronos/UI/SettingsUi.cs
index 88f503a..29d3241 100644
--- a/MareSynchronos/UI/SettingsUi.cs
+++ b/MareSynchronos/UI/SettingsUi.cs
@@ -534,9 +534,9 @@ public class SettingsUi : WindowMediatorSubscriberBase
}, globalChatTypeIdx);
_uiShared.DrawHelpText("FFXIV chat channel to output chat messages on.");
- ImGui.SetWindowFontScale(0.6f);
+ UiSharedService.SetFontScale(0.6f);
_uiShared.BigText("\"Chat 2\" Plugin Integration");
- ImGui.SetWindowFontScale(1.0f);
+ UiSharedService.SetFontScale(1.0f);
var extraChatTags = _configService.Current.ExtraChatTags;
if (ImGui.Checkbox("Tag messages as ExtraChat", ref extraChatTags))
@@ -577,9 +577,9 @@ public class SettingsUi : WindowMediatorSubscriberBase
if (shellEnabled)
shellName = $"[{shellNumber}] {shellName}";
- ImGui.SetWindowFontScale(0.6f);
+ UiSharedService.SetFontScale(0.6f);
_uiShared.BigText(shellName);
- ImGui.SetWindowFontScale(1.0f);
+ UiSharedService.SetFontScale(1.0f);
using var pushIndent = ImRaii.PushIndent();
@@ -1333,6 +1333,14 @@ public class SettingsUi : WindowMediatorSubscriberBase
_uiShared.BigText("Global Configuration");
+ bool showSelfAnalysisWarnings = _playerPerformanceConfigService.Current.ShowSelfAnalysisWarnings;
+ if (ImGui.Checkbox("Display self-analysis warnings", ref showSelfAnalysisWarnings))
+ {
+ _playerPerformanceConfigService.Current.ShowSelfAnalysisWarnings = showSelfAnalysisWarnings;
+ _playerPerformanceConfigService.Save();
+ }
+ _uiShared.DrawHelpText("Disable to suppress UmbraSync chat warnings when your character exceeds the self-analysis thresholds.");
+
bool alwaysShrinkTextures = _playerPerformanceConfigService.Current.TextureShrinkMode == TextureShrinkMode.Always;
bool deleteOriginalTextures = _playerPerformanceConfigService.Current.TextureShrinkDeleteOriginal;
diff --git a/MareSynchronos/UI/UISharedService.cs b/MareSynchronos/UI/UISharedService.cs
index f9a9ea6..9f37058 100644
--- a/MareSynchronos/UI/UISharedService.cs
+++ b/MareSynchronos/UI/UISharedService.cs
@@ -21,6 +21,7 @@ using MareSynchronos.Services.ServerConfiguration;
using MareSynchronos.WebAPI;
using Microsoft.Extensions.Logging;
using System;
+using System.Collections.Generic;
using System.Numerics;
using System.Runtime.InteropServices;
using System.Text;
@@ -37,6 +38,8 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
ImGuiWindowFlags.NoScrollbar |
ImGuiWindowFlags.NoScrollWithMouse;
+ public const float ContentFontScale = 0.92f;
+
public static Vector4 AccentColor { get; set; } = ImGuiColors.DalamudViolet;
public static Vector4 AccentHoverColor { get; set; } = new Vector4(0x3A / 255f, 0x15 / 255f, 0x50 / 255f, 1f);
public static Vector4 AccentActiveColor { get; set; } = AccentHoverColor;
@@ -60,6 +63,8 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
private readonly Dictionary _selectedComboItems = new(StringComparer.Ordinal);
private readonly ServerConfigurationManager _serverConfigurationManager;
private bool _cacheDirectoryHasOtherFilesThanCache = false;
+ private static readonly Stack _fontScaleStack = new();
+ private static float _currentWindowFontScale = 1f;
private bool _cacheDirectoryIsValidPath = true;
@@ -217,6 +222,37 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
public static bool CtrlPressed() => (GetKeyState(0xA2) & 0x8000) != 0 || (GetKeyState(0xA3) & 0x8000) != 0;
+ public static IDisposable PushFontScale(float scale)
+ {
+ var previous = _currentWindowFontScale;
+ _fontScaleStack.Push(previous);
+ if (Math.Abs(previous - scale) > float.Epsilon)
+ {
+ SetFontScale(scale);
+ }
+
+ return new FontScaleScope();
+ }
+
+ private sealed class FontScaleScope : IDisposable
+ {
+ public void Dispose()
+ {
+ if (_fontScaleStack.Count == 0) return;
+ var previous = _fontScaleStack.Pop();
+ if (Math.Abs(previous - _currentWindowFontScale) > float.Epsilon)
+ {
+ SetFontScale(previous);
+ }
+ }
+ }
+
+ public static void SetFontScale(float scale)
+ {
+ ImGui.SetWindowFontScale(scale);
+ _currentWindowFontScale = scale;
+ }
+
public static void DrawGrouped(Action imguiDrawAction, float rounding = 5f, float? expectedWidth = null, bool drawBorder = true)
{
var cursorPos = ImGui.GetCursorPos();
@@ -894,9 +930,9 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
if (intro)
{
- ImGui.SetWindowFontScale(0.8f);
+ SetFontScale(0.8f);
BigText("Mandatory Plugins");
- ImGui.SetWindowFontScale(1.0f);
+ SetFontScale(1.0f);
}
else
{
@@ -917,9 +953,9 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
if (intro)
{
- ImGui.SetWindowFontScale(0.8f);
+ SetFontScale(0.8f);
BigText("Optional Addons");
- ImGui.SetWindowFontScale(1.0f);
+ SetFontScale(1.0f);
UiSharedService.TextWrapped("These addons are not required for basic operation, but without them you may not see others as intended.");
}
else