compact menu redesign with new animated particle header, enable particles toggle added in UI settings

This commit is contained in:
choco
2025-12-23 17:16:51 +01:00
parent 4e03b381dc
commit 5b81caf5a8
5 changed files with 102 additions and 105 deletions

View File

@@ -154,4 +154,5 @@ public class LightlessConfig : ILightlessConfiguration
public bool SyncshellFinderEnabled { get; set; } = false; public bool SyncshellFinderEnabled { get; set; } = false;
public string? SelectedFinderSyncshell { get; set; } = null; public string? SelectedFinderSyncshell { get; set; } = null;
public string LastSeenVersion { get; set; } = string.Empty; public string LastSeenVersion { get; set; } = string.Empty;
public bool EnableParticleEffects { get; set; } = true;
} }

View File

@@ -68,7 +68,7 @@ public class CompactUi : WindowMediatorSubscriberBase
private bool _wasOpen; private bool _wasOpen;
private float _windowContentWidth; private float _windowContentWidth;
private readonly SeluneBrush _seluneBrush = new(); private readonly SeluneBrush _seluneBrush = new();
private readonly AnimatedHeader _animatedHeader = new() { Height = 120f, EnableBottomGradient = false }; private readonly AnimatedHeader _animatedHeader = new();
private const float _connectButtonHighlightThickness = 14f; private const float _connectButtonHighlightThickness = 14f;
private Pair? _focusedPair; private Pair? _focusedPair;
private Pair? _pendingFocusPair; private Pair? _pendingFocusPair;
@@ -128,6 +128,11 @@ public class CompactUi : WindowMediatorSubscriberBase
.Apply(); .Apply();
_drawFolders = [.. DrawFolders]; _drawFolders = [.. DrawFolders];
_animatedHeader.Height = 120f;
_animatedHeader.EnableBottomGradient = true;
_animatedHeader.GradientHeight = 250f;
_animatedHeader.EnableParticles = _configService.Current.EnableParticleEffects;
#if DEBUG #if DEBUG
string dev = "Dev Build"; string dev = "Dev Build";
@@ -218,17 +223,11 @@ public class CompactUi : WindowMediatorSubscriberBase
} }
using (ImRaii.PushId("header")) DrawUIDHeader(); using (ImRaii.PushId("header")) DrawUIDHeader();
_uiSharedService.RoundedSeparator(UIColors.Get("LightlessPurple"), 2.5f, 1f, 12f);
using (ImRaii.PushId("serverstatus"))
{
DrawServerStatus();
}
selune.DrawHighlightOnly(ImGui.GetIO().DeltaTime); selune.DrawHighlightOnly(ImGui.GetIO().DeltaTime);
var style = ImGui.GetStyle(); var style = ImGui.GetStyle();
var contentMinY = windowPos.Y + ImGui.GetWindowContentRegionMin().Y; var contentMinY = windowPos.Y + ImGui.GetWindowContentRegionMin().Y;
var gradientInset = 4f * ImGuiHelpers.GlobalScale; var gradientInset = 4f * ImGuiHelpers.GlobalScale;
var gradientTop = MathF.Max(contentMinY, ImGui.GetCursorScreenPos().Y - style.ItemSpacing.Y + gradientInset); var gradientTop = MathF.Max(contentMinY, ImGui.GetCursorScreenPos().Y - style.ItemSpacing.Y + gradientInset);
ImGui.Separator();
if (_apiController.ServerState is ServerState.Connected) if (_apiController.ServerState is ServerState.Connected)
{ {
@@ -236,7 +235,6 @@ public class CompactUi : WindowMediatorSubscriberBase
using (ImRaii.PushId("global-topmenu")) _tabMenu.Draw(pairSnapshot); using (ImRaii.PushId("global-topmenu")) _tabMenu.Draw(pairSnapshot);
using (ImRaii.PushId("pairlist")) DrawPairs(); using (ImRaii.PushId("pairlist")) DrawPairs();
ImGui.Separator();
var transfersTop = ImGui.GetCursorScreenPos().Y; var transfersTop = ImGui.GetCursorScreenPos().Y;
var gradientBottom = MathF.Max(gradientTop, transfersTop - style.ItemSpacing.Y - gradientInset); var gradientBottom = MathF.Max(gradientTop, transfersTop - style.ItemSpacing.Y - gradientInset);
selune.DrawGradient(gradientTop, gradientBottom, ImGui.GetIO().DeltaTime); selune.DrawGradient(gradientTop, gradientBottom, ImGui.GetIO().DeltaTime);
@@ -317,95 +315,6 @@ public class CompactUi : WindowMediatorSubscriberBase
ImGui.EndChild(); ImGui.EndChild();
} }
private void DrawServerStatus()
{
var buttonSize = _uiSharedService.GetIconButtonSize(FontAwesomeIcon.Link);
var userCount = _apiController.OnlineUsers.ToString(CultureInfo.InvariantCulture);
var userSize = ImGui.CalcTextSize(userCount);
var textSize = ImGui.CalcTextSize("Users Online");
#if DEBUG
string shardConnection = $"Shard: {_apiController.ServerInfo.ShardName}";
#else
string shardConnection = string.Equals(_apiController.ServerInfo.ShardName, "Main", StringComparison.OrdinalIgnoreCase) ? string.Empty : $"Shard: {_apiController.ServerInfo.ShardName}";
#endif
var shardTextSize = ImGui.CalcTextSize(shardConnection);
var printShard = !string.IsNullOrEmpty(_apiController.ServerInfo.ShardName) && shardConnection != string.Empty;
if (_apiController.ServerState is ServerState.Connected)
{
ImGui.SetCursorPosX((ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth()) / 2 - (userSize.X + textSize.X) / 2 - ImGui.GetStyle().ItemSpacing.X / 2);
if (!printShard) ImGui.AlignTextToFramePadding();
ImGui.TextColored(UIColors.Get("LightlessPurple"), userCount);
ImGui.SameLine();
if (!printShard) ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted("Users Online");
}
else
{
ImGui.AlignTextToFramePadding();
ImGui.TextColored(UIColors.Get("DimRed"), "Not connected to any server");
}
if (printShard)
{
ImGui.SetCursorPosY(ImGui.GetCursorPosY() - ImGui.GetStyle().ItemSpacing.Y);
ImGui.SetCursorPosX((ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth()) / 2 - shardTextSize.X / 2);
ImGui.TextUnformatted(shardConnection);
}
ImGui.SameLine();
if (printShard)
{
ImGui.SetCursorPosY(ImGui.GetCursorPosY() - ((userSize.Y + textSize.Y) / 2 + shardTextSize.Y) / 2 - ImGui.GetStyle().ItemSpacing.Y + buttonSize.Y / 2);
}
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;
ImGui.SameLine(ImGui.GetWindowContentRegionMin().X + UiSharedService.GetWindowContentRegionWidth() - buttonSize.X);
if (printShard)
{
ImGui.SetCursorPosY(ImGui.GetCursorPosY() - ((userSize.Y + textSize.Y) / 2 + shardTextSize.Y) / 2 - ImGui.GetStyle().ItemSpacing.Y + buttonSize.Y / 2);
}
if (_apiController.ServerState is not (ServerState.Reconnecting or ServerState.Disconnecting))
{
using (ImRaii.PushColor(ImGuiCol.Text, color))
{
if (_uiSharedService.IconButton(connectedIcon))
{
if (isConnectingOrConnected && !_serverManager.CurrentServer.FullPause)
{
_serverManager.CurrentServer.FullPause = true;
_serverManager.Save();
}
else if (!isConnectingOrConnected && _serverManager.CurrentServer.FullPause)
{
_serverManager.CurrentServer.FullPause = false;
_serverManager.Save();
}
_ = _apiController.CreateConnectionsAsync();
}
}
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenBlockedByActiveItem) || ImGui.IsItemActive())
{
Selune.RegisterHighlight(
ImGui.GetItemRectMin(),
ImGui.GetItemRectMax(),
SeluneHighlightMode.Both,
borderOnly: true,
borderThicknessOverride: _connectButtonHighlightThickness,
exactSize: true,
clipToElement: true,
roundingOverride: ImGui.GetStyle().FrameRounding);
}
UiSharedService.AttachToolTip(isConnectingOrConnected ? "Disconnect from " + _serverManager.CurrentServer.ServerName : "Connect to " + _serverManager.CurrentServer.ServerName);
}
}
private void DrawTransfers() private void DrawTransfers()
{ {
var currentUploads = _fileTransferManager.GetCurrentUploadsSnapshot(); var currentUploads = _fileTransferManager.GetCurrentUploadsSnapshot();
@@ -541,8 +450,7 @@ public class CompactUi : WindowMediatorSubscriberBase
using (_uiSharedService.IconFont.Push()) using (_uiSharedService.IconFont.Push())
iconSize = ImGui.CalcTextSize(FontAwesomeIcon.PersonCirclePlus.ToIconString()); iconSize = ImGui.CalcTextSize(FontAwesomeIcon.PersonCirclePlus.ToIconString());
float contentWidth = ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X; float uidStartX = 25f;
float uidStartX = (contentWidth - uidTextSize.X) / 2f;
float cursorY = ImGui.GetCursorPosY(); float cursorY = ImGui.GetCursorPosY();
if (_configService.Current.BroadcastEnabled && _apiController.IsConnected) if (_configService.Current.BroadcastEnabled && _apiController.IsConnected)
@@ -671,6 +579,12 @@ public class CompactUi : WindowMediatorSubscriberBase
UiSharedService.AttachToolTip("Click to copy"); 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);
if (_apiController.ServerState is ServerState.Connected && analysisSummary.HasData) if (_apiController.ServerState is ServerState.Connected && analysisSummary.HasData)
{ {
var objectSummary = analysisSummary.Objects.Values.FirstOrDefault(summary => summary.HasEntries); var objectSummary = analysisSummary.Objects.Values.FirstOrDefault(summary => summary.HasEntries);
@@ -717,10 +631,12 @@ public class CompactUi : WindowMediatorSubscriberBase
ImGui.SetClipboardText(_apiController.DisplayName); ImGui.SetClipboardText(_apiController.DisplayName);
} }
if (!string.Equals(_apiController.DisplayName, _apiController.UID, StringComparison.Ordinal)) // Only show smaller UID line if DisplayName differs from UID (custom vanity name)
bool hasCustomName = !string.Equals(_apiController.DisplayName, _apiController.UID, StringComparison.OrdinalIgnoreCase);
if (hasCustomName)
{ {
var origTextSize = ImGui.CalcTextSize(_apiController.UID); ImGui.SetCursorPosX(uidStartX);
ImGui.SetCursorPosX((ImGui.GetWindowContentRegionMax().X - ImGui.GetWindowContentRegionMin().X) / 2 - (origTextSize.X / 2));
if (useVanityColors) if (useVanityColors)
{ {
@@ -755,14 +671,83 @@ public class CompactUi : WindowMediatorSubscriberBase
{ {
ImGui.SetClipboardText(_apiController.UID); ImGui.SetClipboardText(_apiController.UID);
} }
// Users Online on same line as smaller UID (with separator)
ImGui.SameLine();
ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted("|");
ImGui.SameLine();
ImGui.TextColored(UIColors.Get("LightlessGreen"), _apiController.OnlineUsers.ToString(CultureInfo.InvariantCulture));
ImGui.SameLine();
ImGui.TextUnformatted("Users Online");
}
else
{
// No custom name - just show Users Online aligned to uidStartX
ImGui.SetCursorPosX(uidStartX);
ImGui.TextColored(UIColors.Get("LightlessGreen"), _apiController.OnlineUsers.ToString(CultureInfo.InvariantCulture));
ImGui.SameLine();
ImGui.TextUnformatted("Users Online");
} }
} }
else else
{ {
ImGui.SetCursorPosX(uidStartX);
UiSharedService.ColorTextWrapped(_apiController.ServerState.GetServerError(_apiController.AuthFailureMessage), uidColor); UiSharedService.ColorTextWrapped(_apiController.ServerState.GetServerError(_apiController.AuthFailureMessage), uidColor);
} }
} }
private void DrawConnectButton(float cursorY, float buttonHeight)
{
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
if (_apiController.ServerState is not (ServerState.Reconnecting or ServerState.Disconnecting))
{
ImGui.SetCursorPosX(UiSharedService.GetWindowContentRegionWidth() - buttonSize.X - 13f);
ImGui.SetCursorPosY(buttonHeight);
using (ImRaii.PushColor(ImGuiCol.Text, color))
using (ImRaii.PushColor(ImGuiCol.Button, ImGui.ColorConvertFloat4ToU32(new(0, 0, 0, 0))))
{
if (_uiSharedService.IconButton(connectedIcon, buttonSize.Y))
{
if (isConnectingOrConnected && !_serverManager.CurrentServer.FullPause)
{
_serverManager.CurrentServer.FullPause = true;
_serverManager.Save();
}
else if (!isConnectingOrConnected && _serverManager.CurrentServer.FullPause)
{
_serverManager.CurrentServer.FullPause = false;
_serverManager.Save();
}
_ = _apiController.CreateConnectionsAsync();
}
}
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenBlockedByActiveItem) || ImGui.IsItemActive())
{
Selune.RegisterHighlight(
ImGui.GetItemRectMin(),
ImGui.GetItemRectMax(),
SeluneHighlightMode.Both,
borderOnly: true,
borderThicknessOverride: _connectButtonHighlightThickness,
exactSize: true,
clipToElement: true,
roundingOverride: ImGui.GetStyle().FrameRounding);
}
UiSharedService.AttachToolTip(isConnectingOrConnected ? "Disconnect from " + _serverManager.CurrentServer.ServerName : "Connect to " + _serverManager.CurrentServer.ServerName);
}
}
private IEnumerable<IDrawFolder> DrawFolders private IEnumerable<IDrawFolder> DrawFolders
{ {
get get

View File

@@ -2082,7 +2082,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
ImGui.Separator(); ImGui.Separator();
var openPopupOnAddition = _configService.Current.OpenPopupOnAdd; var openPopupOnAddition = _configService.Current.OpenPopupOnAdd;
using (var popupTree = BeginGeneralTree("Popup & Auto Fill", UIColors.Get("LightlessPurple"))) using (var popupTree = BeginGeneralTree("Popup & Auto Fill", UIColors.Get("LightlessPurple")))
{ {
if (popupTree.Visible) if (popupTree.Visible)
@@ -2139,11 +2139,18 @@ public class SettingsUi : WindowMediatorSubscriberBase
var groupInVisible = _configService.Current.ShowSyncshellUsersInVisible; var groupInVisible = _configService.Current.ShowSyncshellUsersInVisible;
var syncshellOfflineSeparate = _configService.Current.ShowSyncshellOfflineUsersSeparately; var syncshellOfflineSeparate = _configService.Current.ShowSyncshellOfflineUsersSeparately;
var greenVisiblePair = _configService.Current.ShowVisiblePairsGreenEye; var greenVisiblePair = _configService.Current.ShowVisiblePairsGreenEye;
var enableParticleEffects = _configService.Current.EnableParticleEffects;
using (var behaviorTree = BeginGeneralTree("Behavior", UIColors.Get("LightlessPurple"))) using (var behaviorTree = BeginGeneralTree("Behavior", UIColors.Get("LightlessPurple")))
{ {
if (behaviorTree.Visible) if (behaviorTree.Visible)
{ {
if (ImGui.Checkbox("Enable Particle Effects", ref enableParticleEffects))
{
_configService.Current.EnableParticleEffects = enableParticleEffects;
_configService.Save();
}
if (ImGui.Checkbox("Enable Game Right Click Menu Entries", ref enableRightClickMenu)) if (ImGui.Checkbox("Enable Game Right Click Menu Entries", ref enableRightClickMenu))
{ {
_configService.Current.EnableRightClickMenus = enableRightClickMenu; _configService.Current.EnableRightClickMenus = enableRightClickMenu;

View File

@@ -47,6 +47,8 @@ public class AnimatedHeader
public Vector4 BottomColor { get; set; } = new(0.12f, 0.08f, 0.20f, 1.0f); public Vector4 BottomColor { get; set; } = new(0.12f, 0.08f, 0.20f, 1.0f);
public bool EnableParticles { get; set; } = true; public bool EnableParticles { get; set; } = true;
public bool EnableBottomGradient { get; set; } = true; public bool EnableBottomGradient { get; set; } = true;
public float GradientHeight { get; set; } = 60f;
/// <summary> /// <summary>
/// Draws the animated header with some customizable content /// Draws the animated header with some customizable content
@@ -171,7 +173,7 @@ public class AnimatedHeader
private void DrawBottomGradient(Vector2 headerStart, Vector2 headerEnd, float width) private void DrawBottomGradient(Vector2 headerStart, Vector2 headerEnd, float width)
{ {
var drawList = ImGui.GetWindowDrawList(); var drawList = ImGui.GetWindowDrawList();
var gradientHeight = 60f; var gradientHeight = GradientHeight;
for (int i = 0; i < gradientHeight; i++) for (int i = 0; i < gradientHeight; i++)
{ {

View File

@@ -40,6 +40,7 @@ public class UpdateNotesUi : WindowMediatorSubscriberBase
logger.LogInformation("UpdateNotesUi constructor called"); logger.LogInformation("UpdateNotesUi constructor called");
_uiShared = uiShared; _uiShared = uiShared;
_configService = configService; _configService = configService;
_animatedHeader.EnableParticles = _configService.Current.EnableParticleEffects;
RespectCloseHotkey = true; RespectCloseHotkey = true;
ShowCloseButton = true; ShowCloseButton = true;
@@ -48,7 +49,8 @@ public class UpdateNotesUi : WindowMediatorSubscriberBase
ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoMove; ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoMove;
PositionCondition = ImGuiCond.Always; PositionCondition = ImGuiCond.Always;
WindowBuilder.For(this) WindowBuilder.For(this)
.AllowPinning(false) .AllowPinning(false)
.AllowClickthrough(false) .AllowClickthrough(false)