Merge branch '1.12.0' into ui-redesign

This commit is contained in:
2025-09-30 16:15:30 +02:00
6 changed files with 219 additions and 115 deletions

View File

@@ -147,7 +147,7 @@ public sealed class Plugin : IDalamudPlugin
collection.AddSingleton<RedrawManager>(); collection.AddSingleton<RedrawManager>();
collection.AddSingleton<BroadcastService>(); collection.AddSingleton<BroadcastService>();
collection.AddSingleton(addonLifecycle); collection.AddSingleton(addonLifecycle);
collection.AddSingleton(p => new ContextMenu(contextMenu, pluginInterface, gameData, p.GetRequiredService<ILogger<ContextMenu>>(), p.GetRequiredService<DalamudUtilService>(), p.GetRequiredService<ApiController>(), objectTable)); collection.AddSingleton(p => new ContextMenu(contextMenu, pluginInterface, gameData, p.GetRequiredService<ILogger<ContextMenu>>(), p.GetRequiredService<DalamudUtilService>(), p.GetRequiredService<ApiController>(), objectTable, p.GetRequiredService<LightlessConfigService>()));
collection.AddSingleton((s) => new IpcCallerPenumbra(s.GetRequiredService<ILogger<IpcCallerPenumbra>>(), pluginInterface, collection.AddSingleton((s) => new IpcCallerPenumbra(s.GetRequiredService<ILogger<IpcCallerPenumbra>>(), pluginInterface,
s.GetRequiredService<DalamudUtilService>(), s.GetRequiredService<LightlessMediator>(), s.GetRequiredService<RedrawManager>())); s.GetRequiredService<DalamudUtilService>(), s.GetRequiredService<LightlessMediator>(), s.GetRequiredService<RedrawManager>()));
collection.AddSingleton((s) => new IpcCallerGlamourer(s.GetRequiredService<ILogger<IpcCallerGlamourer>>(), pluginInterface, collection.AddSingleton((s) => new IpcCallerGlamourer(s.GetRequiredService<ILogger<IpcCallerGlamourer>>(), pluginInterface,

View File

@@ -22,7 +22,7 @@ namespace LightlessSync.UI
private IReadOnlyList<GroupFullInfoDto> _allSyncshells; private IReadOnlyList<GroupFullInfoDto> _allSyncshells;
private string _userUid = string.Empty; private string _userUid = string.Empty;
private List<(string Label, string? GID, bool IsAvailable)> _syncshellOptions = new(); private readonly List<(string Label, string? GID, bool IsAvailable)> _syncshellOptions = new();
public BroadcastUI( public BroadcastUI(
ILogger<BroadcastUI> logger, ILogger<BroadcastUI> logger,
@@ -48,7 +48,7 @@ namespace LightlessSync.UI
MaximumSize = new(750, 400) MaximumSize = new(750, 400)
}; };
mediator.Subscribe<RefreshUiMessage>(this, async _ => await RefreshSyncshells()); mediator.Subscribe<RefreshUiMessage>(this, async _ => await RefreshSyncshells().ConfigureAwait(false));
} }
private void RebuildSyncshellDropdownOptions() private void RebuildSyncshellDropdownOptions()
@@ -62,7 +62,7 @@ namespace LightlessSync.UI
_syncshellOptions.Clear(); _syncshellOptions.Clear();
_syncshellOptions.Add(("None", null, true)); _syncshellOptions.Add(("None", null, true));
var addedGids = new HashSet<string>(); var addedGids = new HashSet<string>(StringComparer.Ordinal);
foreach (var shell in ownedSyncshells) foreach (var shell in ownedSyncshells)
{ {
@@ -73,7 +73,7 @@ namespace LightlessSync.UI
if (!string.IsNullOrEmpty(selectedGid) && !addedGids.Contains(selectedGid)) if (!string.IsNullOrEmpty(selectedGid) && !addedGids.Contains(selectedGid))
{ {
var matching = allSyncshells.FirstOrDefault(g => g.GID == selectedGid); var matching = allSyncshells.FirstOrDefault(g => string.Equals(g.GID, selectedGid, StringComparison.Ordinal));
if (matching != null) if (matching != null)
{ {
var label = matching.GroupAliasOrGID ?? matching.GID; var label = matching.GroupAliasOrGID ?? matching.GID;
@@ -97,7 +97,7 @@ namespace LightlessSync.UI
{ {
if (!_apiController.IsConnected) if (!_apiController.IsConnected)
{ {
_allSyncshells = Array.Empty<GroupFullInfoDto>(); _allSyncshells = [];
RebuildSyncshellDropdownOptions(); RebuildSyncshellDropdownOptions();
return; return;
} }
@@ -109,7 +109,7 @@ namespace LightlessSync.UI
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Failed to fetch Syncshells."); _logger.LogError(ex, "Failed to fetch Syncshells.");
_allSyncshells = Array.Empty<GroupFullInfoDto>(); _allSyncshells = [];
} }
RebuildSyncshellDropdownOptions(); RebuildSyncshellDropdownOptions();
@@ -260,14 +260,14 @@ namespace LightlessSync.UI
} }
var selectedGid = _configService.Current.SelectedFinderSyncshell; var selectedGid = _configService.Current.SelectedFinderSyncshell;
var currentOption = _syncshellOptions.FirstOrDefault(o => o.GID == selectedGid); var currentOption = _syncshellOptions.FirstOrDefault(o => string.Equals(o.GID, selectedGid, StringComparison.Ordinal));
var preview = currentOption.Label ?? "Select a Syncshell..."; var preview = currentOption.Label ?? "Select a Syncshell...";
if (ImGui.BeginCombo("##SyncshellDropdown", preview)) if (ImGui.BeginCombo("##SyncshellDropdown", preview))
{ {
foreach (var (label, gid, available) in _syncshellOptions) foreach (var (label, gid, available) in _syncshellOptions)
{ {
bool isSelected = gid == selectedGid; bool isSelected = string.Equals(gid, selectedGid, StringComparison.Ordinal);
if (!available) if (!available)
ImGui.PushStyleColor(ImGuiCol.Text, UIColors.Get("DimRed")); ImGui.PushStyleColor(ImGuiCol.Text, UIColors.Get("DimRed"));
@@ -310,6 +310,7 @@ namespace LightlessSync.UI
ImGui.EndTabItem(); ImGui.EndTabItem();
} }
#if DEBUG
if (ImGui.BeginTabItem("Debug")) if (ImGui.BeginTabItem("Debug"))
{ {
ImGui.Text("Broadcast Cache"); ImGui.Text("Broadcast Cache");
@@ -366,17 +367,12 @@ namespace LightlessSync.UI
ImGui.EndTable(); ImGui.EndTable();
} }
ImGui.EndTabItem(); ImGui.EndTabItem();
} }
#endif
ImGui.EndTabBar(); ImGui.EndTabBar();
} }
} }
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}
} }
} }

View File

@@ -1,14 +1,15 @@
using Dalamud.Game.ClientState.Objects.SubKinds; using Dalamud.Game.ClientState.Objects.SubKinds;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Game.Gui.ContextMenu; using Dalamud.Game.Gui.ContextMenu;
using Dalamud.Plugin; using Dalamud.Plugin;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using LightlessSync.LightlessConfiguration;
using LightlessSync.Services; using LightlessSync.Services;
using LightlessSync.Utils; using LightlessSync.Utils;
using LightlessSync.WebAPI; using LightlessSync.WebAPI;
using Lumina.Excel.Sheets; using Lumina.Excel.Sheets;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.Linq;
namespace LightlessSync.UI; namespace LightlessSync.UI;
@@ -19,6 +20,7 @@ internal class ContextMenu : IHostedService
private readonly IDataManager _gameData; private readonly IDataManager _gameData;
private readonly ILogger<ContextMenu> _logger; private readonly ILogger<ContextMenu> _logger;
private readonly DalamudUtilService _dalamudUtil; private readonly DalamudUtilService _dalamudUtil;
private readonly LightlessConfigService _configService;
private readonly ApiController _apiController; private readonly ApiController _apiController;
private readonly IObjectTable _objectTable; private readonly IObjectTable _objectTable;
@@ -37,7 +39,8 @@ internal class ContextMenu : IHostedService
ILogger<ContextMenu> logger, ILogger<ContextMenu> logger,
DalamudUtilService dalamudUtil, DalamudUtilService dalamudUtil,
ApiController apiController, ApiController apiController,
IObjectTable objectTable) IObjectTable objectTable,
LightlessConfigService configService)
{ {
_contextMenu = contextMenu; _contextMenu = contextMenu;
_pluginInterface = pluginInterface; _pluginInterface = pluginInterface;
@@ -46,6 +49,7 @@ internal class ContextMenu : IHostedService
_dalamudUtil = dalamudUtil; _dalamudUtil = dalamudUtil;
_apiController = apiController; _apiController = apiController;
_objectTable = objectTable; _objectTable = objectTable;
_configService = configService;
} }
public Task StartAsync(CancellationToken cancellationToken) public Task StartAsync(CancellationToken cancellationToken)
@@ -77,7 +81,7 @@ internal class ContextMenu : IHostedService
if (!_pluginInterface.UiBuilder.ShouldModifyUi) if (!_pluginInterface.UiBuilder.ShouldModifyUi)
return; return;
if (!ValidAddons.Contains(args.AddonName)) if (!ValidAddons.Contains(args.AddonName, StringComparer.Ordinal))
return; return;
if (args.Target is not MenuTargetDefault target) if (args.Target is not MenuTargetDefault target)
@@ -86,6 +90,10 @@ internal class ContextMenu : IHostedService
if (string.IsNullOrEmpty(target.TargetName) || target.TargetObjectId == 0 || target.TargetHomeWorld.RowId == 0) if (string.IsNullOrEmpty(target.TargetName) || target.TargetObjectId == 0 || target.TargetHomeWorld.RowId == 0)
return; return;
IPlayerCharacter? targetData = GetPlayerFromObjectTable(target);
if (targetData == null || targetData.Address == IntPtr.Zero)
return;
var world = GetWorld(target.TargetHomeWorld.RowId); var world = GetWorld(target.TargetHomeWorld.RowId);
if (!IsWorldValid(world)) if (!IsWorldValid(world))
return; return;
@@ -96,7 +104,7 @@ internal class ContextMenu : IHostedService
PrefixChar = 'L', PrefixChar = 'L',
UseDefaultPrefix = false, UseDefaultPrefix = false,
PrefixColor = 708, PrefixColor = 708,
OnClicked = async _ => await HandleSelection(args) OnClicked = async _ => await HandleSelection(args).ConfigureAwait(false)
}); });
} }
@@ -111,11 +119,7 @@ internal class ContextMenu : IHostedService
try try
{ {
var targetData = _objectTable IPlayerCharacter? targetData = GetPlayerFromObjectTable(target);
.OfType<IPlayerCharacter>()
.FirstOrDefault(p =>
string.Equals(p.Name.TextValue, target.TargetName, StringComparison.OrdinalIgnoreCase) &&
p.HomeWorld.RowId == target.TargetHomeWorld.RowId);
if (targetData == null || targetData.Address == IntPtr.Zero) if (targetData == null || targetData.Address == IntPtr.Zero)
{ {
@@ -123,11 +127,11 @@ internal class ContextMenu : IHostedService
return; return;
} }
var senderCid = (await _dalamudUtil.GetCIDAsync()).ToString().GetHash256(); var senderCid = (await _dalamudUtil.GetCIDAsync().ConfigureAwait(false)).ToString().GetHash256();
var receiverCid = DalamudUtilService.GetHashedCIDFromPlayerPointer(targetData.Address); var receiverCid = DalamudUtilService.GetHashedCIDFromPlayerPointer(targetData.Address);
_logger.LogInformation("Sending pair request: sender {SenderCid}, receiver {ReceiverCid}", senderCid, receiverCid); _logger.LogInformation("Sending pair request: sender {SenderCid}, receiver {ReceiverCid}", senderCid, receiverCid);
await _apiController.TryPairWithContentId(receiverCid, senderCid); await _apiController.TryPairWithContentId(receiverCid, senderCid).ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -135,12 +139,43 @@ internal class ContextMenu : IHostedService
} }
} }
private IPlayerCharacter? GetPlayerFromObjectTable(MenuTargetDefault target)
{
return _objectTable
.OfType<IPlayerCharacter>()
.FirstOrDefault(p =>
string.Equals(p.Name.TextValue, target.TargetName, StringComparison.OrdinalIgnoreCase) &&
p.HomeWorld.RowId == target.TargetHomeWorld.RowId);
}
private World GetWorld(uint worldId) private World GetWorld(uint worldId)
{ {
var sheet = _gameData.GetExcelSheet<World>()!; var sheet = _gameData.GetExcelSheet<World>()!;
return sheet.TryGetRow(worldId, out var world) ? world : sheet.First(); var luminaWorlds = sheet.Where(x =>
{
var dc = x.DataCenter.ValueNullable;
var name = x.Name.ExtractText();
var internalName = x.InternalName.ExtractText();
if (dc == null || dc.Value.Region == 0 || string.IsNullOrWhiteSpace(dc.Value.Name.ExtractText()))
return false;
if (string.IsNullOrWhiteSpace(name) || string.IsNullOrWhiteSpace(internalName))
return false;
if (name.Contains('-', StringComparison.Ordinal) || name.Contains('_', StringComparison.Ordinal))
return false;
return x.DataCenter.Value.Region != 5 || x.RowId > 3001 && x.RowId != 1200 && IsChineseJapaneseKoreanString(name);
});
return luminaWorlds.FirstOrDefault(x => x.RowId == worldId);
} }
private static bool IsChineseJapaneseKoreanString(string text) => text.All(IsChineseJapaneseKoreanCharacter);
private static bool IsChineseJapaneseKoreanCharacter(char c) => (c >= 0x4E00 && c <= 0x9FFF);
public bool IsWorldValid(uint worldId) => IsWorldValid(GetWorld(worldId)); public bool IsWorldValid(uint worldId) => IsWorldValid(GetWorld(worldId));
public static bool IsWorldValid(World world) public static bool IsWorldValid(World world)

View File

@@ -547,73 +547,147 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase
using var tab = ImRaii.TabItem(tabText + "###" + kvp.Key.ToString()); using var tab = ImRaii.TabItem(tabText + "###" + kvp.Key.ToString());
if (tab.Success) if (tab.Success)
{ {
var groupedfiles = kvp.Value.Select(v => v.Value).GroupBy(f => f.FileType, StringComparer.Ordinal) var groupedfiles = kvp.Value.Select(v => v.Value).GroupBy(f => f.FileType, StringComparer.Ordinal).OrderBy(k => k.Key, StringComparer.Ordinal).ToList();
.OrderBy(k => k.Key, StringComparer.Ordinal).ToList();
ImGui.TextUnformatted("Files for " + kvp.Key); ImGui.PushStyleVar(ImGuiStyleVar.CellPadding, new Vector2(1f, 1f));
ImGui.SameLine(); ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(1f, 1f));
if (ImGui.BeginTable($"##fileStats_{kvp.Key}", 3,
ImGuiTableFlags.BordersInnerV | ImGuiTableFlags.SizingFixedFit))
{
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.TextUnformatted($"Files for {kvp.Key}");
ImGui.TableNextColumn();
ImGui.TextUnformatted(kvp.Value.Count.ToString()); ImGui.TextUnformatted(kvp.Value.Count.ToString());
ImGui.SameLine(); ImGui.SameLine();
using (var font = ImRaii.PushFont(UiBuilder.IconFont)) using (var font = ImRaii.PushFont(UiBuilder.IconFont))
{
ImGui.TextUnformatted(FontAwesomeIcon.InfoCircle.ToIconString()); ImGui.TextUnformatted(FontAwesomeIcon.InfoCircle.ToIconString());
}
if (ImGui.IsItemHovered()) if (ImGui.IsItemHovered())
{ {
string text = ""; string text = string.Join(Environment.NewLine, groupedfiles.Select(f =>
text = string.Join(Environment.NewLine, groupedfiles $"{f.Key}: {f.Count()} files, size: {UiSharedService.ByteToString(f.Sum(v => v.OriginalSize))}, compressed: {UiSharedService.ByteToString(f.Sum(v => v.CompressedSize))}"));
.Select(f => f.Key + ": " + f.Count() + " files, size: " + UiSharedService.ByteToString(f.Sum(v => v.OriginalSize))
+ ", compressed: " + UiSharedService.ByteToString(f.Sum(v => v.CompressedSize))));
ImGui.SetTooltip(text); ImGui.SetTooltip(text);
} }
ImGui.TableNextColumn();
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.TextUnformatted($"{kvp.Key} size (actual):"); ImGui.TextUnformatted($"{kvp.Key} size (actual):");
ImGui.SameLine(); ImGui.TableNextColumn();
ImGui.TextUnformatted(UiSharedService.ByteToString(kvp.Value.Sum(c => c.Value.OriginalSize))); ImGui.TextUnformatted(UiSharedService.ByteToString(kvp.Value.Sum(c => c.Value.OriginalSize)));
ImGui.TableNextColumn();
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.TextUnformatted($"{kvp.Key} size (compressed for up/download only):"); ImGui.TextUnformatted($"{kvp.Key} size (compressed for up/download only):");
ImGui.SameLine(); _uiSharedService.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"), 1.5f);
ImGui.TableNextColumn();
ImGui.TextUnformatted(UiSharedService.ByteToString(kvp.Value.Sum(c => c.Value.CompressedSize))); ImGui.TextUnformatted(UiSharedService.ByteToString(kvp.Value.Sum(c => c.Value.CompressedSize)));
ImGui.Separator(); _uiSharedService.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"), 1.5f);
ImGui.TableNextColumn();
var vramUsage = groupedfiles.SingleOrDefault(v => string.Equals(v.Key, "tex", StringComparison.Ordinal)); var vramUsage = groupedfiles.SingleOrDefault(v => string.Equals(v.Key, "tex", StringComparison.Ordinal));
if (vramUsage != null) if (vramUsage != null)
{ {
var actualVramUsage = vramUsage.Sum(f => f.OriginalSize); var actualVramUsage = vramUsage.Sum(f => f.OriginalSize);
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.TextUnformatted($"{kvp.Key} VRAM usage:"); ImGui.TextUnformatted($"{kvp.Key} VRAM usage:");
ImGui.SameLine(); ImGui.TableNextColumn();
ImGui.TextUnformatted(UiSharedService.ByteToString(actualVramUsage)); ImGui.TextUnformatted(UiSharedService.ByteToString(actualVramUsage));
ImGui.TableNextColumn();
if (_playerPerformanceConfig.Current.WarnOnExceedingThresholds if (_playerPerformanceConfig.Current.WarnOnExceedingThresholds
|| _playerPerformanceConfig.Current.ShowPerformanceIndicator) || _playerPerformanceConfig.Current.ShowPerformanceIndicator)
{ {
using var _ = ImRaii.PushIndent(10f);
var currentVramWarning = _playerPerformanceConfig.Current.VRAMSizeWarningThresholdMiB; var currentVramWarning = _playerPerformanceConfig.Current.VRAMSizeWarningThresholdMiB;
ImGui.TextUnformatted($"Configured VRAM warning threshold: {currentVramWarning} MiB.");
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.TextUnformatted("Configured VRAM threshold:");
ImGui.TableNextColumn();
ImGui.TextUnformatted($"{currentVramWarning} MiB.");
ImGui.TableNextColumn();
if (currentVramWarning * 1024 * 1024 < actualVramUsage) if (currentVramWarning * 1024 * 1024 < actualVramUsage)
{ {
UiSharedService.ColorText($"You exceed your own threshold by " + UiSharedService.ColorText(
$"{UiSharedService.ByteToString(actualVramUsage - (currentVramWarning * 1024 * 1024))}.", $"You exceed your own threshold by {UiSharedService.ByteToString(actualVramUsage - (currentVramWarning * 1024 * 1024))}",
UIColors.Get("LightlessYellow")); UIColors.Get("LightlessYellow"));
} }
} }
} }
var actualTriCount = kvp.Value.Sum(f => f.Value.Triangles); var actualTriCount = kvp.Value.Sum(f => f.Value.Triangles);
ImGui.TextUnformatted($"{kvp.Key} modded model triangles: {actualTriCount}"); ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.TextUnformatted($"{kvp.Key} modded model triangles:");
ImGui.TableNextColumn();
ImGui.TextUnformatted(actualTriCount.ToString());
ImGui.TableNextColumn();
if (_playerPerformanceConfig.Current.WarnOnExceedingThresholds if (_playerPerformanceConfig.Current.WarnOnExceedingThresholds
|| _playerPerformanceConfig.Current.ShowPerformanceIndicator) || _playerPerformanceConfig.Current.ShowPerformanceIndicator)
{ {
using var _ = ImRaii.PushIndent(10f);
var currentTriWarning = _playerPerformanceConfig.Current.TrisWarningThresholdThousands; var currentTriWarning = _playerPerformanceConfig.Current.TrisWarningThresholdThousands;
ImGui.TextUnformatted($"Configured triangle warning threshold: {currentTriWarning * 1000} triangles.");
ImGui.TableNextRow();
ImGui.TableNextColumn();
ImGui.TextUnformatted("Configured triangle threshold:");
ImGui.TableNextColumn();
ImGui.TextUnformatted($"{currentTriWarning * 1000} triangles.");
ImGui.TableNextColumn();
if (currentTriWarning * 1000 < actualTriCount) if (currentTriWarning * 1000 < actualTriCount)
{ {
UiSharedService.ColorText($"You exceed your own threshold by " + UiSharedService.ColorText(
$"{actualTriCount - (currentTriWarning * 1000)} triangles.", $"You exceed your own threshold by {actualTriCount - (currentTriWarning * 1000)}",
UIColors.Get("LightlessYellow")); UIColors.Get("LightlessYellow"));
} }
} }
ImGui.EndTable();
}
ImGui.PopStyleVar(2);
_uiSharedService.ColoredSeparator(UIColors.Get("LightlessPurple"), 2f);
_uiSharedService.MediumText("Selected file:", UIColors.Get("LightlessBlue"));
ImGui.SameLine();
_uiSharedService.MediumText(_selectedHash, UIColors.Get("LightlessYellow"));
if (_cachedAnalysis[_selectedObjectTab].TryGetValue(_selectedHash, out CharacterAnalyzer.FileDataEntry? item))
{
var filePaths = item.FilePaths;
UiSharedService.ColorText("Local file path:", UIColors.Get("LightlessBlue"));
ImGui.SameLine();
UiSharedService.TextWrapped(filePaths[0]);
if (filePaths.Count > 1)
{
ImGui.SameLine();
ImGui.TextUnformatted($"(and {filePaths.Count - 1} more)");
ImGui.SameLine();
_uiSharedService.IconText(FontAwesomeIcon.InfoCircle);
UiSharedService.AttachToolTip(string.Join(Environment.NewLine, filePaths.Skip(1)));
}
var gamepaths = item.GamePaths;
UiSharedService.ColorText("Used by game path:", UIColors.Get("LightlessBlue"));
ImGui.SameLine();
UiSharedService.TextWrapped(gamepaths[0]);
if (gamepaths.Count > 1)
{
ImGui.SameLine();
ImGui.TextUnformatted($"(and {gamepaths.Count - 1} more)");
ImGui.SameLine();
_uiSharedService.IconText(FontAwesomeIcon.InfoCircle);
UiSharedService.AttachToolTip(string.Join(Environment.NewLine, gamepaths.Skip(1)));
}
}
ImGui.Separator(); ImGui.Separator();
if (_selectedObjectTab != kvp.Key) if (_selectedObjectTab != kvp.Key)
{ {
_selectedHash = string.Empty; _selectedHash = string.Empty;
@@ -692,41 +766,6 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase
} }
} }
} }
ImGui.Separator();
ImGui.TextUnformatted("Selected file:");
ImGui.SameLine();
UiSharedService.ColorText(_selectedHash, UIColors.Get("LightlessYellow"));
if (_cachedAnalysis[_selectedObjectTab].TryGetValue(_selectedHash, out CharacterAnalyzer.FileDataEntry? item))
{
var filePaths = item.FilePaths;
ImGui.TextUnformatted("Local file path:");
ImGui.SameLine();
UiSharedService.TextWrapped(filePaths[0]);
if (filePaths.Count > 1)
{
ImGui.SameLine();
ImGui.TextUnformatted($"(and {filePaths.Count - 1} more)");
ImGui.SameLine();
_uiSharedService.IconText(FontAwesomeIcon.InfoCircle);
UiSharedService.AttachToolTip(string.Join(Environment.NewLine, filePaths.Skip(1)));
}
var gamepaths = item.GamePaths;
ImGui.TextUnformatted("Used by game path:");
ImGui.SameLine();
UiSharedService.TextWrapped(gamepaths[0]);
if (gamepaths.Count > 1)
{
ImGui.SameLine();
ImGui.TextUnformatted($"(and {gamepaths.Count - 1} more)");
ImGui.SameLine();
_uiSharedService.IconText(FontAwesomeIcon.InfoCircle);
UiSharedService.AttachToolTip(string.Join(Environment.NewLine, gamepaths.Skip(1)));
}
}
} }
public override void OnOpen() public override void OnOpen()
@@ -855,7 +894,7 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase
} }
var filePath = item.FilePaths[0]; var filePath = item.FilePaths[0];
bool toConvert = _texturesToConvert.ContainsKey(filePath); bool toConvert = _texturesToConvert.ContainsKey(filePath);
if (ImGui.Checkbox("###convert" + item.Hash, ref toConvert)) if (UiSharedService.CheckboxWithBorder("###convert" + item.Hash, ref toConvert, UIColors.Get("LightlessPurple"), 1.5f))
{ {
if (toConvert && !_texturesToConvert.ContainsKey(filePath)) if (toConvert && !_texturesToConvert.ContainsKey(filePath))
{ {

View File

@@ -979,9 +979,17 @@ public class SettingsUi : WindowMediatorSubscriberBase
var colorNames = new[] var colorNames = new[]
{ {
("LightlessPurple", "Lightless Purple", "Primary colors"), ("LightlessPurple", "Lightless Purple", "Primary colors"),
("LightlessPurpleActive", "Lightless Purple Active", "Primary colors"),
("LightlessPurpleDefault", "Lightless Purple Inactive", "Primary colors"),
("LightlessBlue", "Lightless Blue", "Secondary colors"), ("LightlessBlue", "Lightless Blue", "Secondary colors"),
("LightlessGreen", "Lightless Green", "Active elements"),
("LightlessYellow", "Lightless Yellow", "Warning colors"), ("LightlessYellow", "Lightless Yellow", "Warning colors"),
("LightlessYellow2", "Lightless Yellow 2", "Warning colors"),
("PairBlue", "Pair Blue", "Pair UI elements"), ("PairBlue", "Pair Blue", "Pair UI elements"),
("DimRed", "Dim Red", "Error and offline") ("DimRed", "Dim Red", "Error and offline")
}; };
@@ -1020,6 +1028,8 @@ public class SettingsUi : WindowMediatorSubscriberBase
ImGui.Spacing(); ImGui.Spacing();
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"), 1.5f);
ImGui.TextUnformatted("Server Info Bar Colors"); ImGui.TextUnformatted("Server Info Bar Colors");
if (ImGui.Checkbox("Color-code the Server Info Bar entry according to status", ref useColorsInDtr)) if (ImGui.Checkbox("Color-code the Server Info Bar entry according to status", ref useColorsInDtr))
@@ -1054,6 +1064,9 @@ public class SettingsUi : WindowMediatorSubscriberBase
} }
ImGui.Spacing(); ImGui.Spacing();
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"), 1.5f);
ImGui.TextUnformatted("Nameplate Colors"); ImGui.TextUnformatted("Nameplate Colors");
var nameColorsEnabled = _configService.Current.IsNameplateColorsEnabled; var nameColorsEnabled = _configService.Current.IsNameplateColorsEnabled;
@@ -1092,6 +1105,10 @@ public class SettingsUi : WindowMediatorSubscriberBase
} }
} }
ImGui.Spacing();
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurpleDefault"), 1.5f);
if (ImGui.Checkbox("Use the complete redesign of the UI for Lightless client.", ref useLightlessRedesign)) if (ImGui.Checkbox("Use the complete redesign of the UI for Lightless client.", ref useLightlessRedesign))
{ {
_configService.Current.UseLightlessRedesign = useLightlessRedesign; _configService.Current.UseLightlessRedesign = useLightlessRedesign;

View File

@@ -173,12 +173,14 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
public static string ByteToString(long bytes, bool addSuffix = true) public static string ByteToString(long bytes, bool addSuffix = true)
{ {
string[] suffix = ["B", "KiB", "MiB", "GiB", "TiB"]; string[] suffix = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"};
int i; int i = 0;
double dblSByte = bytes; double dblSByte = bytes;
for (i = 0; i < suffix.Length && bytes >= 1024; i++, bytes /= 1024)
while (dblSByte >= 1000 && i < suffix.Length - 1)
{ {
dblSByte = bytes / 1024.0; dblSByte /= 1000.0;
i++;
} }
return addSuffix ? $"{dblSByte:0.00} {suffix[i]}" : $"{dblSByte:0.00}"; return addSuffix ? $"{dblSByte:0.00} {suffix[i]}" : $"{dblSByte:0.00}";
@@ -510,6 +512,21 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase
ImGui.Dummy(new Vector2(0, thickness * scale)); ImGui.Dummy(new Vector2(0, thickness * scale));
} }
public static bool CheckboxWithBorder(string label, ref bool value, Vector4? borderColor = null, float borderThickness = 1.0f, float rounding = 3.0f)
{
var pos = ImGui.GetCursorScreenPos();
bool changed = ImGui.Checkbox(label, ref value);
var min = pos;
var max = ImGui.GetItemRectMax();
var col = ImGui.GetColorU32(borderColor ?? ImGuiColors.DalamudGrey);
ImGui.GetWindowDrawList().AddRect(min, max, col, rounding, ImDrawFlags.None, borderThickness);
return changed;
}
public void MediumText(string text, Vector4? color = null) public void MediumText(string text, Vector4? color = null)
{ {
FontText(text, MediumFont, color); FontText(text, MediumFont, color);