init 2
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Dalamud.Game.Text;
|
||||
using Dalamud.Game.ClientState.Objects.Enums;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Colors;
|
||||
using Dalamud.Interface.Utility;
|
||||
@@ -16,8 +17,10 @@ using LightlessSync.LightlessConfiguration.Models;
|
||||
using LightlessSync.PlayerData.Handlers;
|
||||
using LightlessSync.PlayerData.Pairs;
|
||||
using LightlessSync.Services;
|
||||
using LightlessSync.Services.ActorTracking;
|
||||
using LightlessSync.Services.Mediator;
|
||||
using LightlessSync.Services.ServerConfiguration;
|
||||
using LightlessSync.UI.Services;
|
||||
using LightlessSync.UI.Style;
|
||||
using LightlessSync.Utils;
|
||||
using LightlessSync.UtilsEnum.Enum;
|
||||
@@ -25,10 +28,12 @@ using LightlessSync.WebAPI;
|
||||
using LightlessSync.WebAPI.Files;
|
||||
using LightlessSync.WebAPI.Files.Models;
|
||||
using LightlessSync.WebAPI.SignalR.Utils;
|
||||
using DalamudObjectKind = Dalamud.Game.ClientState.Objects.Enums.ObjectKind;
|
||||
using Microsoft.AspNetCore.Http.Connections;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
@@ -37,6 +42,9 @@ using System.Net.Http.Json;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.Object;
|
||||
using FfxivCharacter = FFXIVClientStructs.FFXIV.Client.Game.Character.Character;
|
||||
using FfxivCharacterBase = FFXIVClientStructs.FFXIV.Client.Graphics.Scene.CharacterBase;
|
||||
|
||||
namespace LightlessSync.UI;
|
||||
|
||||
@@ -54,7 +62,8 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
private readonly FileUploadManager _fileTransferManager;
|
||||
private readonly FileTransferOrchestrator _fileTransferOrchestrator;
|
||||
private readonly IpcManager _ipcManager;
|
||||
private readonly PairManager _pairManager;
|
||||
private readonly ActorObjectService _actorObjectService;
|
||||
private readonly PairUiService _pairUiService;
|
||||
private readonly PerformanceCollectorService _performanceCollector;
|
||||
private readonly PlayerPerformanceConfigService _playerPerformanceConfigService;
|
||||
private readonly PairProcessingLimiter _pairProcessingLimiter;
|
||||
@@ -94,7 +103,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
|
||||
public SettingsUi(ILogger<SettingsUi> logger,
|
||||
UiSharedService uiShared, LightlessConfigService configService, UiThemeConfigService themeConfigService,
|
||||
PairManager pairManager,
|
||||
PairUiService pairUiService,
|
||||
ServerConfigurationManager serverConfigurationManager,
|
||||
PlayerPerformanceConfigService playerPerformanceConfigService,
|
||||
PairProcessingLimiter pairProcessingLimiter,
|
||||
@@ -106,12 +115,13 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
IpcManager ipcManager, CacheMonitor cacheMonitor,
|
||||
DalamudUtilService dalamudUtilService, HttpClient httpClient,
|
||||
NameplateService nameplateService,
|
||||
NameplateHandler nameplateHandler) : base(logger, mediator, "Lightless Sync Settings",
|
||||
NameplateHandler nameplateHandler,
|
||||
ActorObjectService actorObjectService) : base(logger, mediator, "Lightless Sync Settings",
|
||||
performanceCollector)
|
||||
{
|
||||
_configService = configService;
|
||||
_themeConfigService = themeConfigService;
|
||||
_pairManager = pairManager;
|
||||
_pairUiService = pairUiService;
|
||||
_serverConfigurationManager = serverConfigurationManager;
|
||||
_playerPerformanceConfigService = playerPerformanceConfigService;
|
||||
_pairProcessingLimiter = pairProcessingLimiter;
|
||||
@@ -128,13 +138,15 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
_uiShared = uiShared;
|
||||
_nameplateService = nameplateService;
|
||||
_nameplateHandler = nameplateHandler;
|
||||
_actorObjectService = actorObjectService;
|
||||
AllowClickthrough = false;
|
||||
AllowPinning = true;
|
||||
_validationProgress = new Progress<(int, int, FileCacheEntity)>(v => _currentProgress = v);
|
||||
|
||||
SizeConstraints = new WindowSizeConstraints()
|
||||
{
|
||||
MinimumSize = new Vector2(800, 400), MaximumSize = new Vector2(800, 2000),
|
||||
MinimumSize = new Vector2(850f, 400f),
|
||||
MaximumSize = new Vector2(850f, 2000f),
|
||||
};
|
||||
|
||||
TitleBarButtons = new()
|
||||
@@ -449,6 +461,74 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawTextureDownscaleCounters()
|
||||
{
|
||||
HashSet<Pair> trackedPairs = new();
|
||||
|
||||
var snapshot = _pairUiService.GetSnapshot();
|
||||
|
||||
foreach (var pair in snapshot.DirectPairs)
|
||||
{
|
||||
trackedPairs.Add(pair);
|
||||
}
|
||||
|
||||
foreach (var group in snapshot.GroupPairs.Values)
|
||||
{
|
||||
foreach (var pair in group)
|
||||
{
|
||||
trackedPairs.Add(pair);
|
||||
}
|
||||
}
|
||||
|
||||
long totalOriginalBytes = 0;
|
||||
long totalEffectiveBytes = 0;
|
||||
var hasData = false;
|
||||
|
||||
foreach (var pair in trackedPairs)
|
||||
{
|
||||
if (!pair.IsVisible)
|
||||
continue;
|
||||
|
||||
var original = pair.LastAppliedApproximateVRAMBytes;
|
||||
var effective = pair.LastAppliedApproximateEffectiveVRAMBytes;
|
||||
|
||||
if (original >= 0)
|
||||
{
|
||||
hasData = true;
|
||||
totalOriginalBytes += original;
|
||||
}
|
||||
|
||||
if (effective >= 0)
|
||||
{
|
||||
hasData = true;
|
||||
totalEffectiveBytes += effective;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasData)
|
||||
{
|
||||
ImGui.TextDisabled("VRAM usage has not been calculated yet.");
|
||||
return;
|
||||
}
|
||||
|
||||
var savedBytes = Math.Max(0L, totalOriginalBytes - totalEffectiveBytes);
|
||||
var originalText = UiSharedService.ByteToString(totalOriginalBytes, addSuffix: true);
|
||||
var effectiveText = UiSharedService.ByteToString(totalEffectiveBytes, addSuffix: true);
|
||||
var savedText = UiSharedService.ByteToString(savedBytes, addSuffix: true);
|
||||
|
||||
ImGui.TextUnformatted($"Total VRAM usage (original): {originalText}");
|
||||
ImGui.TextUnformatted($"Total VRAM usage (effective): {effectiveText}");
|
||||
|
||||
if (savedBytes > 0)
|
||||
{
|
||||
UiSharedService.ColorText($"VRAM saved by downscaling: {savedText}", UIColors.Get("LightlessGreen"));
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.TextUnformatted($"VRAM saved by downscaling: {savedText}");
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawThemeVectorRow(MainStyle.StyleVector2Option option)
|
||||
{
|
||||
ImGui.TableNextRow();
|
||||
@@ -1383,6 +1463,22 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
_logger.LogWarning(ex, $"Could not delete file {file} because it is in use.");
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var directory in Directory.GetDirectories(_configService.Current.CacheFolder))
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(directory, recursive: true);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Could not delete directory {Directory} because it is in use.", directory);
|
||||
}
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Could not delete directory {Directory} due to access restrictions.", directory);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1422,8 +1518,9 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
{
|
||||
if (_uiShared.IconTextButton(FontAwesomeIcon.StickyNote, "Export all your user notes to clipboard"))
|
||||
{
|
||||
ImGui.SetClipboardText(UiSharedService.GetNotes(_pairManager.DirectPairs
|
||||
.UnionBy(_pairManager.GroupPairs.SelectMany(p => p.Value), p => p.UserData,
|
||||
var snapshot = _pairUiService.GetSnapshot();
|
||||
ImGui.SetClipboardText(UiSharedService.GetNotes(snapshot.DirectPairs
|
||||
.UnionBy(snapshot.GroupPairs.SelectMany(p => p.Value), p => p.UserData,
|
||||
UserDataComparer.Instance).ToList()));
|
||||
}
|
||||
|
||||
@@ -2388,6 +2485,22 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
_uiShared.DrawHelpText(
|
||||
"Will show a performance indicator when players exceed defined thresholds in Lightless UI." +
|
||||
Environment.NewLine + "Will use warning thresholds.");
|
||||
|
||||
using (ImRaii.Disabled(!showPerformanceIndicator))
|
||||
{
|
||||
using var indent = ImRaii.PushIndent();
|
||||
bool showCompactStats = _playerPerformanceConfigService.Current.ShowPerformanceUsageNextToName;
|
||||
if (ImGui.Checkbox("Show performance stats next to alias", ref showCompactStats))
|
||||
{
|
||||
_playerPerformanceConfigService.Current.ShowPerformanceUsageNextToName = showCompactStats;
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
|
||||
_uiShared.DrawHelpText(
|
||||
"Adds a text with approx. VRAM usage and triangle count to the right of pairs alias." +
|
||||
Environment.NewLine + "Requires performance indicator to be enabled.");
|
||||
}
|
||||
|
||||
bool warnOnExceedingThresholds = _playerPerformanceConfigService.Current.WarnOnExceedingThresholds;
|
||||
if (ImGui.Checkbox("Warn on loading in players exceeding performance thresholds",
|
||||
ref warnOnExceedingThresholds))
|
||||
@@ -2552,6 +2665,102 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
ImGui.Separator();
|
||||
|
||||
if (_uiShared.MediumTreeNode("Texture Optimization", UIColors.Get("LightlessYellow")))
|
||||
{
|
||||
_uiShared.MediumText("Warning", UIColors.Get("DimRed"));
|
||||
_uiShared.DrawNoteLine("! ", UIColors.Get("DimRed"),
|
||||
new SeStringUtils.RichTextEntry("Texture compression and downscaling is potentially a "),
|
||||
new SeStringUtils.RichTextEntry("destructive", UIColors.Get("DimRed"), true),
|
||||
new SeStringUtils.RichTextEntry(" process and may cause broken or incorrect character appearances."));
|
||||
|
||||
_uiShared.DrawNoteLine("! ", UIColors.Get("DimRed"),
|
||||
new SeStringUtils.RichTextEntry("This feature is encouraged to help "),
|
||||
new SeStringUtils.RichTextEntry("lower-end systems with limited VRAM", UIColors.Get("LightlessYellow"), true),
|
||||
new SeStringUtils.RichTextEntry(" and for use in "),
|
||||
new SeStringUtils.RichTextEntry("performance-critical scenarios", UIColors.Get("LightlessYellow"), true),
|
||||
new SeStringUtils.RichTextEntry("."));
|
||||
|
||||
_uiShared.DrawNoteLine("! ", UIColors.Get("DimRed"),
|
||||
new SeStringUtils.RichTextEntry("Runtime downscaling "),
|
||||
new SeStringUtils.RichTextEntry("MAY", UIColors.Get("DimRed"), true),
|
||||
new SeStringUtils.RichTextEntry(" cause higher load on the system when processing downloads."));
|
||||
|
||||
_uiShared.DrawNoteLine("!!! ", UIColors.Get("DimRed"),
|
||||
new SeStringUtils.RichTextEntry("When enabled, we cannot provide support for appearance issues caused by this setting!", UIColors.Get("DimRed"), true));
|
||||
|
||||
var textureConfig = _playerPerformanceConfigService.Current;
|
||||
var trimNonIndex = textureConfig.EnableNonIndexTextureMipTrim;
|
||||
if (ImGui.Checkbox("Trim mip levels for textures", ref trimNonIndex))
|
||||
{
|
||||
textureConfig.EnableNonIndexTextureMipTrim = trimNonIndex;
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
_uiShared.DrawHelpText("When enabled, Lightless will remove high-resolution mip levels from textures (not index) that exceed the size limit and are not compressed with any kind compression.");
|
||||
|
||||
var downscaleIndex = textureConfig.EnableIndexTextureDownscale;
|
||||
if (ImGui.Checkbox("Downscale index textures above limit", ref downscaleIndex))
|
||||
{
|
||||
textureConfig.EnableIndexTextureDownscale = downscaleIndex;
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
_uiShared.DrawHelpText("Controls whether Lightless reduces index textures that exceed the size limit.");
|
||||
|
||||
var dimensionOptions = new[] { 512, 1024, 2048, 4096 };
|
||||
var optionLabels = dimensionOptions.Select(static value => value.ToString()).ToArray();
|
||||
var currentDimension = textureConfig.TextureDownscaleMaxDimension;
|
||||
var selectedIndex = Array.IndexOf(dimensionOptions, currentDimension);
|
||||
if (selectedIndex < 0)
|
||||
{
|
||||
selectedIndex = Array.IndexOf(dimensionOptions, 2048);
|
||||
}
|
||||
|
||||
ImGui.SetNextItemWidth(140 * ImGuiHelpers.GlobalScale);
|
||||
if (ImGui.Combo("Maximum texture dimension", ref selectedIndex, optionLabels, optionLabels.Length))
|
||||
{
|
||||
textureConfig.TextureDownscaleMaxDimension = dimensionOptions[selectedIndex];
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
_uiShared.DrawHelpText($"Textures above this size will be reduced until their largest dimension is at or below the limit. Block-compressed textures are skipped when \"Only downscale uncompressed\" is enabled.{UiSharedService.TooltipSeparator}Default: 2048");
|
||||
|
||||
var keepOriginalTextures = textureConfig.KeepOriginalTextureFiles;
|
||||
if (ImGui.Checkbox("Keep original texture files", ref keepOriginalTextures))
|
||||
{
|
||||
textureConfig.KeepOriginalTextureFiles = keepOriginalTextures;
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
_uiShared.DrawHelpText("When disabled, Lightless removes the original texture after a downscaled copy is created.");
|
||||
ImGui.SameLine();
|
||||
_uiShared.DrawNoteLine("! ", UIColors.Get("LightlessYellow"), new SeStringUtils.RichTextEntry("If disabled, saved + effective VRAM usage information will not work.", UIColors.Get("LightlessYellow")));
|
||||
|
||||
if (!textureConfig.EnableNonIndexTextureMipTrim && !textureConfig.EnableIndexTextureDownscale)
|
||||
{
|
||||
UiSharedService.ColorTextWrapped("Both trimming and downscale are disabled. Lightless will keep original textures regardless of size.", UIColors.Get("DimRed"));
|
||||
}
|
||||
|
||||
ImGui.Dummy(new Vector2(5));
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("DimRed"), 3f);
|
||||
var onlyUncompressed = textureConfig.OnlyDownscaleUncompressedTextures;
|
||||
if (ImGui.Checkbox("Only downscale uncompressed textures", ref onlyUncompressed))
|
||||
{
|
||||
textureConfig.OnlyDownscaleUncompressedTextures = onlyUncompressed;
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
_uiShared.DrawHelpText("If disabled, compressed textures will be targeted for downscaling too.");
|
||||
_uiShared.ColoredSeparator(UIColors.Get("DimRed"), 3f);
|
||||
|
||||
ImGui.Dummy(new Vector2(5));
|
||||
|
||||
DrawTextureDownscaleCounters();
|
||||
|
||||
ImGui.Dummy(new Vector2(5));
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessYellow"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
ImGui.Separator();
|
||||
ImGui.Dummy(new Vector2(10));
|
||||
|
||||
@@ -3511,7 +3720,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
// Lightless notification locations
|
||||
var lightlessLocations = GetLightlessNotificationLocations();
|
||||
var downloadLocations = GetDownloadNotificationLocations();
|
||||
|
||||
|
||||
if (ImGui.BeginTable("##NotificationLocationTable", 3, ImGuiTableFlags.Borders | ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit))
|
||||
{
|
||||
ImGui.TableSetupColumn("Notification Type", ImGuiTableColumnFlags.WidthFixed, 200f * ImGuiHelpers.GlobalScale);
|
||||
@@ -3674,7 +3883,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
|
||||
ImGui.EndTable();
|
||||
}
|
||||
|
||||
|
||||
ImGuiHelpers.ScaledDummy(5);
|
||||
if (_uiShared.IconTextButton(FontAwesomeIcon.Trash, "Clear All Notifications"))
|
||||
{
|
||||
@@ -3792,7 +4001,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
|
||||
ImGui.Spacing();
|
||||
ImGui.TextUnformatted("Size & Layout");
|
||||
|
||||
|
||||
float notifWidth = _configService.Current.NotificationWidth;
|
||||
if (ImGui.SliderFloat("Notification Width", ref notifWidth, 250f, 600f, "%.0f"))
|
||||
{
|
||||
@@ -3825,7 +4034,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
|
||||
ImGui.Spacing();
|
||||
ImGui.TextUnformatted("Position");
|
||||
|
||||
|
||||
var currentCorner = _configService.Current.NotificationCorner;
|
||||
if (ImGui.BeginCombo("Notification Position", GetNotificationCornerLabel(currentCorner)))
|
||||
{
|
||||
@@ -3843,7 +4052,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
_uiShared.DrawHelpText("Choose which corner of the screen notifications appear in.");
|
||||
|
||||
|
||||
int offsetY = _configService.Current.NotificationOffsetY;
|
||||
if (ImGui.SliderInt("Vertical Offset", ref offsetY, -2500, 2500))
|
||||
{
|
||||
@@ -4136,7 +4345,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
|
||||
ImGui.Separator();
|
||||
// Location descriptions removed - information is now inline with each setting
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4256,7 +4465,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
ImGui.TableSetColumnIndex(2);
|
||||
var availableWidth = ImGui.GetContentRegionAvail().X;
|
||||
var buttonWidth = (availableWidth - ImGui.GetStyle().ItemSpacing.X * 2) / 3;
|
||||
|
||||
|
||||
// Play button
|
||||
using var playId = ImRaii.PushId($"Play_{typeIndex}");
|
||||
using (ImRaii.Disabled(isDisabled))
|
||||
@@ -4277,7 +4486,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
}
|
||||
UiSharedService.AttachToolTip("Test this sound");
|
||||
|
||||
|
||||
// Disable toggle button
|
||||
ImGui.SameLine();
|
||||
using var disableId = ImRaii.PushId($"Disable_{typeIndex}");
|
||||
@@ -4285,11 +4494,11 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
{
|
||||
var icon = isDisabled ? FontAwesomeIcon.VolumeOff : FontAwesomeIcon.VolumeUp;
|
||||
var color = isDisabled ? UIColors.Get("DimRed") : UIColors.Get("LightlessGreen");
|
||||
|
||||
|
||||
ImGui.PushStyleColor(ImGuiCol.Button, color);
|
||||
ImGui.PushStyleColor(ImGuiCol.ButtonHovered, color * new Vector4(1.2f, 1.2f, 1.2f, 1f));
|
||||
ImGui.PushStyleColor(ImGuiCol.ButtonActive, color * new Vector4(0.8f, 0.8f, 0.8f, 1f));
|
||||
|
||||
|
||||
if (ImGui.Button(icon.ToIconString(), new Vector2(buttonWidth, 0)))
|
||||
{
|
||||
bool newDisabled = !isDisabled;
|
||||
@@ -4303,16 +4512,16 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
_configService.Save();
|
||||
}
|
||||
|
||||
|
||||
ImGui.PopStyleColor(3);
|
||||
}
|
||||
UiSharedService.AttachToolTip(isDisabled ? "Sound is disabled - click to enable" : "Sound is enabled - click to disable");
|
||||
|
||||
|
||||
// Reset button
|
||||
ImGui.SameLine();
|
||||
using var resetId = ImRaii.PushId($"Reset_{typeIndex}");
|
||||
bool isDefault = currentSoundId == defaultSoundId;
|
||||
|
||||
|
||||
using (ImRaii.Disabled(isDefault))
|
||||
{
|
||||
using (ImRaii.PushFont(UiBuilder.IconFont))
|
||||
@@ -4337,6 +4546,4 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
ImGui.EndTable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user