diff --git a/LightlessSync/Plugin.cs b/LightlessSync/Plugin.cs index c3b1216..f6bdcb6 100644 --- a/LightlessSync/Plugin.cs +++ b/LightlessSync/Plugin.cs @@ -1,4 +1,4 @@ -using Dalamud.Game; +using Dalamud.Game; using Dalamud.Game.ClientState.Objects; using Dalamud.Interface.ImGuiFileDialog; using Dalamud.Interface.Windowing; @@ -150,7 +150,7 @@ public sealed class Plugin : IDalamudPlugin collection.AddSingleton(addonLifecycle); collection.AddSingleton(p => new ContextMenuService(contextMenu, pluginInterface, gameData, p.GetRequiredService>(), p.GetRequiredService(), p.GetRequiredService(), objectTable, - p.GetRequiredService(), p.GetRequiredService(), clientState)); + p.GetRequiredService(), p.GetRequiredService(), p.GetRequiredService(), clientState)); collection.AddSingleton((s) => new IpcCallerPenumbra(s.GetRequiredService>(), pluginInterface, s.GetRequiredService(), s.GetRequiredService(), s.GetRequiredService())); collection.AddSingleton((s) => new IpcCallerGlamourer(s.GetRequiredService>(), pluginInterface, @@ -277,4 +277,4 @@ public sealed class Plugin : IDalamudPlugin _host.StopAsync().GetAwaiter().GetResult(); _host.Dispose(); } -} \ No newline at end of file +} diff --git a/LightlessSync/Services/ContextMenuService.cs b/LightlessSync/Services/ContextMenuService.cs index 632a047..b03ef28 100644 --- a/LightlessSync/Services/ContextMenuService.cs +++ b/LightlessSync/Services/ContextMenuService.cs @@ -1,4 +1,4 @@ -using Dalamud.Game.ClientState.Objects.SubKinds; +using Dalamud.Game.ClientState.Objects.SubKinds; using Dalamud.Game.Gui.ContextMenu; using Dalamud.Plugin; using Dalamud.Plugin.Services; @@ -21,6 +21,7 @@ internal class ContextMenuService : IHostedService private readonly DalamudUtilService _dalamudUtil; private readonly IClientState _clientState; private readonly PairManager _pairManager; + private readonly PairRequestService _pairRequestService; private readonly ApiController _apiController; private readonly IObjectTable _objectTable; @@ -33,6 +34,7 @@ internal class ContextMenuService : IHostedService ApiController apiController, IObjectTable objectTable, LightlessConfigService configService, + PairRequestService pairRequestService, PairManager pairManager, IClientState clientState) { @@ -44,6 +46,7 @@ internal class ContextMenuService : IHostedService _apiController = apiController; _objectTable = objectTable; _pairManager = pairManager; + _pairRequestService = pairRequestService; _clientState = clientState; } @@ -140,6 +143,10 @@ internal class ContextMenuService : IHostedService _logger.LogInformation("Sending pair request: sender {SenderCid}, receiver {ReceiverCid}", senderCid, receiverCid); await _apiController.TryPairWithContentId(receiverCid, senderCid).ConfigureAwait(false); + if (!string.IsNullOrWhiteSpace(receiverCid)) + { + _pairRequestService.RemoveRequest(receiverCid); + } } catch (Exception ex) { diff --git a/LightlessSync/UI/BroadcastUI.cs b/LightlessSync/UI/BroadcastUI.cs index ae3d17a..b83e657 100644 --- a/LightlessSync/UI/BroadcastUI.cs +++ b/LightlessSync/UI/BroadcastUI.cs @@ -141,8 +141,8 @@ namespace LightlessSync.UI ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(1, -2)); - _uiSharedService.DrawNoteLine("# ", UIColors.Get("LightlessPurple"), "This lets other Lightless users know you use Lightless."); - _uiSharedService.DrawNoteLine("# ", UIColors.Get("LightlessPurple"), "While enabled, you and other people using Lightfinder can see each other identified as Lightless users."); + _uiSharedService.DrawNoteLine("# ", UIColors.Get("LightlessPurple"),"This lets other Lightless users know you use Lightless. While enabled, you and others using Lightfinder can see each other identified as Lightless users."); + ImGui.Indent(15f); ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudGrey); ImGui.Text("- This is done using a 'Lightless' label above player nameplates."); @@ -183,15 +183,16 @@ namespace LightlessSync.UI new SeStringUtils.RichTextEntry(" and does not share any data with other users. All identifying information remains private to the server.")); _uiSharedService.DrawNoteLine("! ", UIColors.Get("DimRed"), "Pairing is intended as a mutual agreement between both parties. A pair request will not be visible to the recipient unless Lightfinder is enabled."); - ImGuiHelpers.ScaledDummy(3f); + + ImGuiHelpers.ScaledDummy(5f); ImGui.PushStyleColor(ImGuiCol.Text, UIColors.Get("DimRed")); - ImGui.Text("Use Lightfinder only when you want to be visible."); + ImGui.TextWrapped("Use Lightfinder when you're okay with being visible to other users and understand that you are responsible for your own experience."); ImGui.PopStyleColor(); ImGui.PopStyleVar(); - ImGuiHelpers.ScaledDummy(2.2f); + ImGuiHelpers.ScaledDummy(3f); _uiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 2f); if (_configService.Current.BroadcastEnabled) diff --git a/LightlessSync/UI/CompactUI.cs b/LightlessSync/UI/CompactUI.cs index 7edbefc..42311c6 100644 --- a/LightlessSync/UI/CompactUI.cs +++ b/LightlessSync/UI/CompactUI.cs @@ -512,7 +512,7 @@ public class CompactUi : WindowMediatorSubscriberBase ImGui.PopStyleColor(); ImGui.PushStyleColor(ImGuiCol.Text, UIColors.Get("DimRed")); - ImGui.Text("Use it only when you want to be visible."); + ImGui.TextWrapped("Use Lightfinder when you're okay with being visible to other users and understand that you are responsible for your own experience."); ImGui.PopStyleColor(); ImGuiHelpers.ScaledDummy(0.2f); diff --git a/LightlessSync/UI/EditProfileUi.cs b/LightlessSync/UI/EditProfileUi.cs index 50c4dbe..72e8d33 100644 --- a/LightlessSync/UI/EditProfileUi.cs +++ b/LightlessSync/UI/EditProfileUi.cs @@ -9,6 +9,7 @@ using LightlessSync.API.Data; using LightlessSync.API.Dto.User; using LightlessSync.Services; using LightlessSync.Services.Mediator; +using LightlessSync.UI.Style; using LightlessSync.Utils; using LightlessSync.WebAPI; using Microsoft.Extensions.Logging; @@ -33,6 +34,7 @@ public class EditProfileUi : WindowMediatorSubscriberBase private bool _showFileDialogError = false; private bool _wasOpen; + private Vector4 _currentBg = new(0.15f, 0.15f, 0.15f, 1f); private bool vanityInitialized; // useless for now private bool textEnabled; private bool glowEnabled; @@ -303,22 +305,37 @@ public class EditProfileUi : WindowMediatorSubscriberBase using (ImRaii.PushFont(font)) { - var offsetX = 10f; - var pos = ImGui.GetCursorScreenPos() + new Vector2(offsetX, 0); - var size = ImGui.CalcTextSize(seString.TextValue); + var drawList = ImGui.GetWindowDrawList(); + var textSize = ImGui.CalcTextSize(seString.TextValue); - var padding = new Vector2(6, 3); - var rectMin = pos - padding; - var rectMax = pos + size + padding; + float minWidth = 150f * ImGuiHelpers.GlobalScale; + float bgWidth = Math.Max(textSize.X + 20f, minWidth); + + float paddingY = 5f * ImGuiHelpers.GlobalScale; + + var cursor = ImGui.GetCursorScreenPos(); + + var rectMin = cursor; + var rectMax = rectMin + new Vector2(bgWidth, textSize.Y + (paddingY * 2f)); + + float boost = Luminance.ComputeHighlight(previewTextColor, previewGlowColor); + + var baseBg = new Vector4(0.15f + boost, 0.15f + boost, 0.15f + boost, 1f); + var bgColor = Luminance.BackgroundContrast(previewTextColor, previewGlowColor, baseBg, ref _currentBg); - var bgColor = new Vector4(0.15f, 0.15f, 0.15f, 1f); var borderColor = UIColors.Get("LightlessPurple"); - var drawList = ImGui.GetWindowDrawList(); drawList.AddRectFilled(rectMin, rectMax, ImGui.GetColorU32(bgColor), 6.0f); drawList.AddRect(rectMin, rectMax, ImGui.GetColorU32(borderColor), 6.0f, ImDrawFlags.None, 1.5f); - SeStringUtils.RenderSeStringWithHitbox(seString, pos, font); + var textPos = new Vector2( + rectMin.X + (bgWidth - textSize.X) * 0.5f, + rectMin.Y + paddingY + ); + + SeStringUtils.RenderSeStringWithHitbox(seString, textPos, font); + + ImGui.Dummy(new Vector2(5)); } const float colorPickAlign = 90f; diff --git a/LightlessSync/UI/Handlers/IdDisplayHandler.cs b/LightlessSync/UI/Handlers/IdDisplayHandler.cs index 1e3fee2..01f0df6 100644 --- a/LightlessSync/UI/Handlers/IdDisplayHandler.cs +++ b/LightlessSync/UI/Handlers/IdDisplayHandler.cs @@ -7,6 +7,7 @@ using LightlessSync.LightlessConfiguration; using LightlessSync.PlayerData.Pairs; using LightlessSync.Services.Mediator; using LightlessSync.Services.ServerConfiguration; +using LightlessSync.UI.Style; using LightlessSync.Utils; using System; using System.Numerics; @@ -26,6 +27,9 @@ public class IdDisplayHandler private bool _popupShown = false; private DateTime? _popupTime; + private Vector4 _currentBg = new(0.15f, 0.15f, 0.15f, 1f); + private float _highlightBoost; + public IdDisplayHandler(LightlessMediator mediator, ServerConfigurationManager serverManager, LightlessConfigService lightlessConfigService) { _mediator = mediator; @@ -98,7 +102,7 @@ public class IdDisplayHandler { ImGui.AlignTextToFramePadding(); - var font = UiBuilder.MonoFont; + var font = textIsUid ? UiBuilder.MonoFont : ImGui.GetFont(); Vector4? textColor = null; Vector4? glowColor = null; @@ -127,10 +131,11 @@ public class IdDisplayHandler float highlightPadX = 0f; float highlightPadY = 0f; - if (useVanityColors && textColor is Vector4 contrastColor) + if (useVanityColors) { - var brightness = (0.299f * contrastColor.X) + (0.587f * contrastColor.Y) + (0.114f * contrastColor.Z); - if (brightness < 0.35f) + float boost = Luminance.ComputeHighlight(textColor, glowColor); + + if (boost > 0f) { var style = ImGui.GetStyle(); useHighlight = true; @@ -138,6 +143,12 @@ public class IdDisplayHandler highlightPadY = MathF.Max(style.FramePadding.Y * 0.55f, 1.25f * ImGuiHelpers.GlobalScale); drawList.ChannelsSplit(2); drawList.ChannelsSetCurrent(1); + + _highlightBoost = boost; + } + else + { + _highlightBoost = 0f; } } @@ -149,7 +160,7 @@ public class IdDisplayHandler SeStringUtils.RenderSeStringWithHitbox(seString, rowStart, font); itemMin = ImGui.GetItemRectMin(); itemMax = ImGui.GetItemRectMax(); - textSize = itemMax - itemMin; + //textSize = itemMax - itemMin; } if (useHighlight) @@ -170,11 +181,14 @@ public class IdDisplayHandler highlightMin.Y = MathF.Max(highlightMin.Y, contentMin.Y); highlightMax.Y = MathF.Min(highlightMax.Y, contentMax.Y); - var highlightColor = style.Colors[(int)ImGuiCol.TableRowBgAlt]; - highlightColor.X = 0.25f; - highlightColor.Y = 0.25f; - highlightColor.Z = 0.25f; - highlightColor.W = 1f; + var highlightColor = new Vector4( + 0.25f + _highlightBoost, + 0.25f + _highlightBoost, + 0.25f + _highlightBoost, + 1f + ); + + highlightColor = Luminance.BackgroundContrast(textColor, glowColor, highlightColor, ref _currentBg); float rounding = style.FrameRounding > 0f ? style.FrameRounding : 5f * ImGuiHelpers.GlobalScale; drawList.ChannelsSetCurrent(0); diff --git a/LightlessSync/UI/Style/Luminance.cs b/LightlessSync/UI/Style/Luminance.cs new file mode 100644 index 0000000..62609af --- /dev/null +++ b/LightlessSync/UI/Style/Luminance.cs @@ -0,0 +1,64 @@ +using System; +using System.Numerics; + +namespace LightlessSync.UI.Style +{ + internal static class Luminance + { + public static float BrightnessThreshold { get; set; } = 0.4f; + public static float HighlightBoostMax { get; set; } = 0.1f; + public static float SmoothFactor { get; set; } = 0.15f; + + private static float Brightness(Vector4 color) + => Math.Max(color.X, Math.Max(color.Y, color.Z)); + + public static float ComputeHighlight(Vector4? textColor, Vector4? glowColor) + { + float brightnessText = textColor.HasValue ? Brightness(textColor.Value) : 1f; + float brightnessGlow = glowColor.HasValue ? Brightness(glowColor.Value) : 1f; + + if (brightnessText >= BrightnessThreshold || brightnessGlow >= BrightnessThreshold) + return 0f; + + float deficit = Math.Min(BrightnessThreshold - brightnessText, + BrightnessThreshold - brightnessGlow); + + float factor = Math.Clamp(deficit / BrightnessThreshold, 0f, 1f); + factor = MathF.Pow(factor, 2.0f); + + return factor * HighlightBoostMax; + } + + public static Vector4 BackgroundContrast(Vector4? textColor, Vector4? glowColor, Vector4 backgroundColor, ref Vector4 currentBg) + { + if (!textColor.HasValue && !glowColor.HasValue) + return backgroundColor; + + float brightnessText = textColor.HasValue ? Brightness(textColor.Value) : 0f; + float brightnessGlow = glowColor.HasValue ? Brightness(glowColor.Value) : 0f; + + float fgBrightness = Math.Max(brightnessText, brightnessGlow); + float bgBrightness = Brightness(backgroundColor); + float diff = Math.Abs(bgBrightness - fgBrightness); + + bool shouldBeDark = fgBrightness > 0.5f; + Vector4 targetBg; + + if (diff >= BrightnessThreshold) + { + targetBg = backgroundColor; + } + else + { + targetBg = shouldBeDark + ? new Vector4(0.05f, 0.05f, 0.05f, backgroundColor.W) + : new Vector4(0.95f, 0.95f, 0.95f, backgroundColor.W); + } + + float t = Math.Clamp(SmoothFactor, 0f, 1f); + currentBg = t <= 0f ? targetBg : Vector4.Lerp(currentBg, targetBg, t); + + return currentBg; + } + } +}