diff --git a/LightlessSync/Plugin.cs b/LightlessSync/Plugin.cs index 8198bb3..425703a 100644 --- a/LightlessSync/Plugin.cs +++ b/LightlessSync/Plugin.cs @@ -556,7 +556,6 @@ public sealed class Plugin : IDalamudPlugin public void Dispose() { - _host.StopAsync().GetAwaiter().GetResult(); - _host.Dispose(); + _host.StopAsync().ContinueWith(_ => _host.Dispose()).Wait(TimeSpan.FromSeconds(5)); } } diff --git a/LightlessSync/UI/CompactUI.cs b/LightlessSync/UI/CompactUI.cs index ec2ff0d..e297e11 100644 --- a/LightlessSync/UI/CompactUI.cs +++ b/LightlessSync/UI/CompactUI.cs @@ -453,17 +453,49 @@ public class CompactUi : WindowMediatorSubscriberBase float uidStartX = 25f; float cursorY = ImGui.GetCursorPosY(); + ImGui.SetCursorPosY(cursorY); + ImGui.SetCursorPosX(uidStartX); + + bool headerItemClicked; + using (_uiSharedService.UidFont.Push()) + { + if (useVanityColors) + { + var seString = SeStringUtils.BuildFormattedPlayerName(uidText, vanityTextColor, vanityGlowColor); + var cursorPos = ImGui.GetCursorScreenPos(); + var targetFontSize = ImGui.GetFontSize(); + var font = ImGui.GetFont(); + SeStringUtils.RenderSeStringWithHitbox(seString, cursorPos, targetFontSize ,font , "uid-header"); + } + else + { + ImGui.TextColored(uidColor, uidText); + } + } + + // Get the actual rendered text rect for proper icon alignment + var uidTextRect = ImGui.GetItemRectMax() - ImGui.GetItemRectMin(); + var uidTextRectMin = ImGui.GetItemRectMin(); + var uidTextHovered = ImGui.IsItemHovered(); + headerItemClicked = ImGui.IsItemClicked(); + + // Track position for icons next to UID text + // Use uidTextSize.Y (actual font height) for vertical centering, not hitbox height + float nextIconX = uidTextRectMin.X + uidTextRect.X + 10f; + float iconYOffset = (uidTextSize.Y - iconSize.Y) * 0.5f; + float textVerticalOffset = (uidTextRect.Y - uidTextSize.Y) * 0.5f; + var buttonSize = new Vector2(iconSize.X, uidTextSize.Y); + if (_configService.Current.BroadcastEnabled && _apiController.IsConnected) { - float iconYOffset = (uidTextSize.Y - iconSize.Y) * 0.5f; - var buttonSize = new Vector2(iconSize.X, uidTextSize.Y); - - ImGui.SetCursorPos(new Vector2(ImGui.GetStyle().ItemSpacing.X + 5f, cursorY)); + ImGui.SetCursorScreenPos(new Vector2(nextIconX, uidTextRectMin.Y + textVerticalOffset)); + ImGui.InvisibleButton("BroadcastIcon", buttonSize); - var iconPos = ImGui.GetItemRectMin() + new Vector2(0f, iconYOffset); using (_uiSharedService.IconFont.Push()) ImGui.GetWindowDrawList().AddText(iconPos, ImGui.GetColorU32(UIColors.Get("LightlessGreen")), FontAwesomeIcon.PersonCirclePlus.ToIconString()); + + nextIconX = ImGui.GetItemRectMax().X + 6f; if (ImGui.IsItemHovered()) @@ -535,56 +567,8 @@ public class CompactUi : WindowMediatorSubscriberBase if (ImGui.IsItemClicked()) _lightlessMediator.Publish(new UiToggleMessage(typeof(LightFinderUI))); } - - ImGui.SetCursorPosY(cursorY); - ImGui.SetCursorPosX(uidStartX); - - bool headerItemClicked; - using (_uiSharedService.UidFont.Push()) - { - if (useVanityColors) - { - var seString = SeStringUtils.BuildFormattedPlayerName(uidText, vanityTextColor, vanityGlowColor); - var cursorPos = ImGui.GetCursorScreenPos(); - var targetFontSize = ImGui.GetFontSize(); - var font = ImGui.GetFont(); - SeStringUtils.RenderSeStringWithHitbox(seString, cursorPos, targetFontSize ,font , "uid-header"); - } - else - { - ImGui.TextColored(uidColor, uidText); - } - } - - if (ImGui.IsItemHovered()) - { - var padding = new Vector2(35f * ImGuiHelpers.GlobalScale); - Selune.RegisterHighlight( - ImGui.GetItemRectMin() - padding, - ImGui.GetItemRectMax() + padding, - SeluneHighlightMode.Point, - exactSize: true, - clipToElement: true, - clipPadding: padding, - highlightColorOverride: vanityGlowColor, - highlightAlphaOverride: 0.05f); - } - - headerItemClicked = ImGui.IsItemClicked(); - - if (headerItemClicked) - { - ImGui.SetClipboardText(uidText); - } - - UiSharedService.AttachToolTip("Click to copy"); - - // Connect/Disconnect button next to big UID - DrawConnectButton(cursorY, uidTextSize.Y); - - // Add spacing below the big UID - ImGuiHelpers.ScaledDummy(5f); - + + // Warning threshold icon (next to lightfinder or UID text) if (_apiController.ServerState is ServerState.Connected && analysisSummary.HasData) { var objectSummary = analysisSummary.Objects.Values.FirstOrDefault(summary => summary.HasEntries); @@ -598,24 +582,30 @@ public class CompactUi : WindowMediatorSubscriberBase if ((isOverTriHold || isOverVRAMUsage) && _playerPerformanceConfig.Current.WarnOnExceedingThresholds) { - ImGui.SameLine(); - ImGui.SetCursorPosY(cursorY + 15f); - _uiSharedService.IconText(FontAwesomeIcon.ExclamationTriangle, UIColors.Get("LightlessYellow")); + ImGui.SetCursorScreenPos(new Vector2(nextIconX, uidTextRectMin.Y + textVerticalOffset)); + + ImGui.InvisibleButton("WarningThresholdIcon", buttonSize); + var warningIconPos = ImGui.GetItemRectMin() + new Vector2(0f, iconYOffset); + using (_uiSharedService.IconFont.Push()) + ImGui.GetWindowDrawList().AddText(warningIconPos, ImGui.GetColorU32(UIColors.Get("LightlessYellow")), FontAwesomeIcon.ExclamationTriangle.ToIconString()); - string warningMessage = ""; - if (isOverTriHold) + if (ImGui.IsItemHovered()) { - warningMessage += $"You exceed your own triangles threshold by " + - $"{actualTriCount - _playerPerformanceConfig.Current.TrisWarningThresholdThousands * 1000} triangles."; - warningMessage += Environment.NewLine; - + string warningMessage = ""; + if (isOverTriHold) + { + warningMessage += $"You exceed your own triangles threshold by " + + $"{actualTriCount - _playerPerformanceConfig.Current.TrisWarningThresholdThousands * 1000} triangles."; + warningMessage += Environment.NewLine; + } + if (isOverVRAMUsage) + { + warningMessage += $"You exceed your own VRAM threshold by " + + $"{UiSharedService.ByteToString(actualVramUsage - (_playerPerformanceConfig.Current.VRAMSizeWarningThresholdMiB * 1024 * 1024))}."; + } + UiSharedService.AttachToolTip(warningMessage); } - if (isOverVRAMUsage) - { - warningMessage += $"You exceed your own VRAM threshold by " + - $"{UiSharedService.ByteToString(actualVramUsage - (_playerPerformanceConfig.Current.VRAMSizeWarningThresholdMiB * 1024 * 1024))}."; - } - UiSharedService.AttachToolTip(warningMessage); + if (ImGui.IsItemClicked()) { _lightlessMediator.Publish(new UiToggleMessage(typeof(DataAnalysisUi))); @@ -624,6 +614,33 @@ public class CompactUi : WindowMediatorSubscriberBase } } + if (uidTextHovered) + { + var padding = new Vector2(35f * ImGuiHelpers.GlobalScale); + Selune.RegisterHighlight( + uidTextRectMin - padding, + uidTextRectMin + uidTextRect + padding, + SeluneHighlightMode.Point, + exactSize: true, + clipToElement: true, + clipPadding: padding, + highlightColorOverride: vanityGlowColor, + highlightAlphaOverride: 0.05f); + } + + if (headerItemClicked) + { + ImGui.SetClipboardText(uidText); + } + + UiSharedService.AttachToolTip("Click to copy"); + + // Connect/Disconnect button next to big UID (use screen pos to avoid affecting layout) + DrawConnectButton(uidTextRectMin.Y + textVerticalOffset, uidTextSize.Y); + + // Add spacing below the big UID + ImGuiHelpers.ScaledDummy(5f); + if (_apiController.ServerState is ServerState.Connected) { if (headerItemClicked) @@ -697,19 +714,20 @@ public class CompactUi : WindowMediatorSubscriberBase } } - private void DrawConnectButton(float cursorY, float buttonHeight) + private void DrawConnectButton(float screenY, float textHeight) { var buttonSize = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Link); bool isConnectingOrConnected = _apiController.ServerState is ServerState.Connected or ServerState.Connecting or ServerState.Reconnecting; var color = UiSharedService.GetBoolColor(!isConnectingOrConnected); var connectedIcon = isConnectingOrConnected ? FontAwesomeIcon.Unlink : FontAwesomeIcon.Link; - // Position next to big UID on the right side - + // Position on right side, vertically centered with text if (_apiController.ServerState is not (ServerState.Reconnecting or ServerState.Disconnecting)) { - ImGui.SetCursorPosX(UiSharedService.GetWindowContentRegionWidth() - buttonSize.X - 13f); - ImGui.SetCursorPosY(buttonHeight); + var windowPos = ImGui.GetWindowPos(); + var screenX = windowPos.X + UiSharedService.GetWindowContentRegionWidth() - buttonSize.X - 13f; + var yOffset = (textHeight - buttonSize.Y) * 0.5f; + ImGui.SetCursorScreenPos(new Vector2(screenX, screenY + yOffset)); using (ImRaii.PushColor(ImGuiCol.Text, color)) using (ImRaii.PushColor(ImGuiCol.Button, ImGui.ColorConvertFloat4ToU32(new(0, 0, 0, 0))))