504 lines
28 KiB
C#
504 lines
28 KiB
C#
using Dalamud.Bindings.ImGui;
|
|
using Dalamud.Interface;
|
|
using Dalamud.Interface.Colors;
|
|
using Dalamud.Interface.Utility.Raii;
|
|
using MareSynchronos.API.Data.Enum;
|
|
using MareSynchronos.Interop.Ipc;
|
|
using MareSynchronos.Services;
|
|
using MareSynchronos.Services.Mediator;
|
|
using MareSynchronos.Utils;
|
|
using Microsoft.Extensions.Logging;
|
|
using System.Numerics;
|
|
using MareSynchronos.Localization;
|
|
using System.Globalization;
|
|
|
|
namespace MareSynchronos.UI;
|
|
|
|
public class DataAnalysisUi : WindowMediatorSubscriberBase
|
|
{
|
|
private readonly CharacterAnalyzer _characterAnalyzer;
|
|
private readonly Progress<(string, int)> _conversionProgress = new();
|
|
private readonly IpcManager _ipcManager;
|
|
private readonly UiSharedService _uiSharedService;
|
|
private readonly Dictionary<string, string[]> _texturesToConvert = new(StringComparer.Ordinal);
|
|
private Dictionary<ObjectKind, Dictionary<string, CharacterAnalyzer.FileDataEntry>>? _cachedAnalysis;
|
|
private CancellationTokenSource _conversionCancellationTokenSource = new();
|
|
private string _conversionCurrentFileName = string.Empty;
|
|
private int _conversionCurrentFileProgress = 0;
|
|
private Task? _conversionTask;
|
|
private bool _enableBc7ConversionMode = false;
|
|
private bool _hasUpdate = false;
|
|
private bool _sortDirty = true;
|
|
private bool _modalOpen = false;
|
|
private string _selectedFileTypeTab = string.Empty;
|
|
private string _selectedHash = string.Empty;
|
|
private ObjectKind _selectedObjectTab;
|
|
private bool _showModal = false;
|
|
|
|
private string L(string key, string fallback, params object[] args)
|
|
{
|
|
var safeArgs = args ?? Array.Empty<object>();
|
|
return _uiSharedService.Localize(key, fallback, safeArgs);
|
|
}
|
|
|
|
public DataAnalysisUi(ILogger<DataAnalysisUi> logger, MareMediator mediator,
|
|
CharacterAnalyzer characterAnalyzer, IpcManager ipcManager,
|
|
PerformanceCollectorService performanceCollectorService,
|
|
UiSharedService uiSharedService)
|
|
: base(logger, mediator, uiSharedService.Localize("DataAnalysis.WindowTitle", "Character Data Analysis"), performanceCollectorService)
|
|
{
|
|
_characterAnalyzer = characterAnalyzer;
|
|
_ipcManager = ipcManager;
|
|
_uiSharedService = uiSharedService;
|
|
Mediator.Subscribe<CharacterDataAnalyzedMessage>(this, (_) =>
|
|
{
|
|
_hasUpdate = true;
|
|
});
|
|
SizeConstraints = new()
|
|
{
|
|
MinimumSize = new()
|
|
{
|
|
X = 800,
|
|
Y = 600
|
|
},
|
|
MaximumSize = new()
|
|
{
|
|
X = 3840,
|
|
Y = 2160
|
|
}
|
|
};
|
|
|
|
_conversionProgress.ProgressChanged += ConversionProgress_ProgressChanged;
|
|
}
|
|
|
|
protected override void DrawInternal()
|
|
{
|
|
var modalTitle = L("DataAnalysis.Bc7.ModalTitle", "BC7 Conversion in Progress");
|
|
if (_conversionTask != null && !_conversionTask.IsCompleted)
|
|
{
|
|
_showModal = true;
|
|
if (ImGui.BeginPopupModal(modalTitle))
|
|
{
|
|
ImGui.TextUnformatted(L("DataAnalysis.Bc7.Status", "BC7 Conversion in progress: {0}/{1}", _conversionCurrentFileProgress, _texturesToConvert.Count));
|
|
UiSharedService.TextWrapped(L("DataAnalysis.Bc7.CurrentFile", "Current file: {0}", _conversionCurrentFileName));
|
|
if (_uiSharedService.IconTextButton(FontAwesomeIcon.StopCircle, L("DataAnalysis.Bc7.Cancel", "Cancel conversion")))
|
|
{
|
|
_conversionCancellationTokenSource.Cancel();
|
|
}
|
|
UiSharedService.SetScaledWindowSize(500);
|
|
ImGui.EndPopup();
|
|
}
|
|
else
|
|
{
|
|
_modalOpen = false;
|
|
}
|
|
}
|
|
else if (_conversionTask != null && _conversionTask.IsCompleted && _texturesToConvert.Count > 0)
|
|
{
|
|
_conversionTask = null;
|
|
_texturesToConvert.Clear();
|
|
_showModal = false;
|
|
_modalOpen = false;
|
|
_enableBc7ConversionMode = false;
|
|
}
|
|
|
|
if (_showModal && !_modalOpen)
|
|
{
|
|
ImGui.OpenPopup(modalTitle);
|
|
_modalOpen = true;
|
|
}
|
|
|
|
if (_hasUpdate)
|
|
{
|
|
_cachedAnalysis = _characterAnalyzer.LastAnalysis.DeepClone();
|
|
_hasUpdate = false;
|
|
_sortDirty = true;
|
|
}
|
|
|
|
UiSharedService.TextWrapped(L("DataAnalysis.Description", "This window shows you all files and their sizes that are currently in use through your character and associated entities"));
|
|
|
|
if (_cachedAnalysis == null || _cachedAnalysis.Count == 0) return;
|
|
|
|
bool isAnalyzing = _characterAnalyzer.IsAnalysisRunning;
|
|
bool needAnalysis = _cachedAnalysis!.Any(c => c.Value.Any(f => !f.Value.IsComputed));
|
|
if (isAnalyzing)
|
|
{
|
|
UiSharedService.ColorTextWrapped(L("DataAnalysis.Analyzing", "Analyzing {0}/{1}", _characterAnalyzer.CurrentFile, _characterAnalyzer.TotalFiles),
|
|
ImGuiColors.DalamudYellow);
|
|
if (_uiSharedService.IconTextButton(FontAwesomeIcon.StopCircle, L("DataAnalysis.Button.CancelAnalysis", "Cancel analysis")))
|
|
{
|
|
_characterAnalyzer.CancelAnalyze();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (needAnalysis)
|
|
{
|
|
UiSharedService.ColorTextWrapped(L("DataAnalysis.Analyze.MissingNotice", "Some entries in the analysis have file size not determined yet, press the button below to analyze your current data"),
|
|
ImGuiColors.DalamudYellow);
|
|
if (_uiSharedService.IconTextButton(FontAwesomeIcon.PlayCircle, L("DataAnalysis.Button.StartMissing", "Start analysis (missing entries)")))
|
|
{
|
|
_ = _characterAnalyzer.ComputeAnalysis(print: false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (_uiSharedService.IconTextButton(FontAwesomeIcon.PlayCircle, L("DataAnalysis.Button.StartAll", "Start analysis (recalculate all entries)")))
|
|
{
|
|
_ = _characterAnalyzer.ComputeAnalysis(print: false, recalculate: true);
|
|
}
|
|
}
|
|
}
|
|
|
|
ImGui.Separator();
|
|
|
|
ImGui.TextUnformatted(L("DataAnalysis.TotalFiles", "Total files:"));
|
|
ImGui.SameLine();
|
|
ImGui.TextUnformatted(_cachedAnalysis!.Values.Sum(c => c.Values.Count).ToString());
|
|
ImGui.SameLine();
|
|
using (var font = ImRaii.PushFont(UiBuilder.IconFont))
|
|
{
|
|
ImGui.TextUnformatted(FontAwesomeIcon.InfoCircle.ToIconString());
|
|
}
|
|
if (ImGui.IsItemHovered())
|
|
{
|
|
var groupedfiles = _cachedAnalysis.Values.SelectMany(f => f.Values).GroupBy(f => f.FileType, StringComparer.Ordinal);
|
|
var summary = string.Join(Environment.NewLine, groupedfiles.OrderBy(f => f.Key, StringComparer.Ordinal)
|
|
.Select(f => L("DataAnalysis.Tooltip.FileSummary", "{0}: {1} files, size: {2}, compressed: {3}",
|
|
f.Key, f.Count(), UiSharedService.ByteToString(f.Sum(v => v.OriginalSize)), UiSharedService.ByteToString(f.Sum(v => v.CompressedSize)))));
|
|
ImGui.SetTooltip(summary);
|
|
}
|
|
ImGui.TextUnformatted(L("DataAnalysis.TotalSizeActual", "Total size (actual):"));
|
|
ImGui.SameLine();
|
|
ImGui.TextUnformatted(UiSharedService.ByteToString(_cachedAnalysis!.Sum(c => c.Value.Sum(c => c.Value.OriginalSize))));
|
|
ImGui.TextUnformatted(L("DataAnalysis.TotalSizeDownload", "Total size (download size):"));
|
|
ImGui.SameLine();
|
|
using (ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudYellow, needAnalysis))
|
|
{
|
|
ImGui.TextUnformatted(UiSharedService.ByteToString(_cachedAnalysis!.Sum(c => c.Value.Sum(c => c.Value.CompressedSize))));
|
|
if (needAnalysis && !isAnalyzing)
|
|
{
|
|
ImGui.SameLine();
|
|
using (ImRaii.PushFont(UiBuilder.IconFont))
|
|
ImGui.TextUnformatted(FontAwesomeIcon.ExclamationCircle.ToIconString());
|
|
UiSharedService.AttachToolTip(L("DataAnalysis.Tooltip.CalculateDownloadSize", "Click \"Start analysis\" to calculate download size"));
|
|
}
|
|
}
|
|
ImGui.TextUnformatted(L("DataAnalysis.TotalTriangles", "Total modded model triangles: {0}",
|
|
UiSharedService.TrisToString(_cachedAnalysis.Sum(c => c.Value.Sum(f => f.Value.Triangles)))));
|
|
ImGui.Separator();
|
|
|
|
using var tabbar = ImRaii.TabBar("objectSelection");
|
|
foreach (var kvp in _cachedAnalysis)
|
|
{
|
|
using var id = ImRaii.PushId(kvp.Key.ToString());
|
|
string tabText = kvp.Key.ToString();
|
|
using var tab = ImRaii.TabItem(tabText + "###" + kvp.Key.ToString());
|
|
if (tab.Success)
|
|
{
|
|
var groupedfiles = kvp.Value.Select(v => v.Value).GroupBy(f => f.FileType, StringComparer.Ordinal)
|
|
.OrderBy(k => k.Key, StringComparer.Ordinal).ToList();
|
|
|
|
ImGui.TextUnformatted(L("DataAnalysis.FilesFor", "Files for {0}", kvp.Key));
|
|
ImGui.SameLine();
|
|
ImGui.TextUnformatted(kvp.Value.Count.ToString());
|
|
ImGui.SameLine();
|
|
|
|
using (var font = ImRaii.PushFont(UiBuilder.IconFont))
|
|
{
|
|
ImGui.TextUnformatted(FontAwesomeIcon.InfoCircle.ToIconString());
|
|
}
|
|
if (ImGui.IsItemHovered())
|
|
{
|
|
var summary = string.Join(Environment.NewLine, groupedfiles
|
|
.Select(f => L("DataAnalysis.Tooltip.FileSummary", "{0}: {1} files, size: {2}, compressed: {3}",
|
|
f.Key, f.Count(), UiSharedService.ByteToString(f.Sum(v => v.OriginalSize)), UiSharedService.ByteToString(f.Sum(v => v.CompressedSize)))));
|
|
ImGui.SetTooltip(summary);
|
|
}
|
|
ImGui.TextUnformatted(L("DataAnalysis.Object.SizeActual", "{0} size (actual):", kvp.Key));
|
|
ImGui.SameLine();
|
|
ImGui.TextUnformatted(UiSharedService.ByteToString(kvp.Value.Sum(c => c.Value.OriginalSize)));
|
|
ImGui.TextUnformatted(L("DataAnalysis.Object.SizeDownload", "{0} size (download size):", kvp.Key));
|
|
ImGui.SameLine();
|
|
using (ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudYellow, needAnalysis))
|
|
{
|
|
ImGui.TextUnformatted(UiSharedService.ByteToString(kvp.Value.Sum(c => c.Value.CompressedSize)));
|
|
if (needAnalysis && !isAnalyzing)
|
|
{
|
|
ImGui.SameLine();
|
|
using (ImRaii.PushFont(UiBuilder.IconFont))
|
|
ImGui.TextUnformatted(FontAwesomeIcon.ExclamationCircle.ToIconString());
|
|
UiSharedService.AttachToolTip(L("DataAnalysis.Tooltip.CalculateDownloadSize", "Click \"Start analysis\" to calculate download size"));
|
|
}
|
|
}
|
|
ImGui.TextUnformatted(L("DataAnalysis.Object.Vram", "{0} VRAM usage:", kvp.Key));
|
|
ImGui.SameLine();
|
|
var vramUsage = groupedfiles.SingleOrDefault(v => string.Equals(v.Key, "tex", StringComparison.Ordinal));
|
|
if (vramUsage != null)
|
|
{
|
|
ImGui.TextUnformatted(UiSharedService.ByteToString(vramUsage.Sum(f => f.OriginalSize)));
|
|
}
|
|
ImGui.TextUnformatted(L("DataAnalysis.Object.Triangles", "{0} modded model triangles: {1}", kvp.Key,
|
|
UiSharedService.TrisToString(kvp.Value.Sum(f => f.Value.Triangles))));
|
|
|
|
ImGui.Separator();
|
|
if (_selectedObjectTab != kvp.Key)
|
|
{
|
|
_selectedHash = string.Empty;
|
|
_selectedObjectTab = kvp.Key;
|
|
_selectedFileTypeTab = string.Empty;
|
|
_enableBc7ConversionMode = false;
|
|
_texturesToConvert.Clear();
|
|
}
|
|
|
|
using var fileTabBar = ImRaii.TabBar("fileTabs");
|
|
|
|
foreach (IGrouping<string, CharacterAnalyzer.FileDataEntry>? fileGroup in groupedfiles)
|
|
{
|
|
string fileGroupText = fileGroup.Key + " [" + fileGroup.Count() + "]";
|
|
var requiresCompute = fileGroup.Any(k => !k.IsComputed);
|
|
using var tabcol = ImRaii.PushColor(ImGuiCol.Tab, UiSharedService.Color(ImGuiColors.DalamudYellow), requiresCompute);
|
|
ImRaii.IEndObject fileTab;
|
|
using (var textcol = ImRaii.PushColor(ImGuiCol.Text, UiSharedService.Color(new(0, 0, 0, 1)),
|
|
requiresCompute && !string.Equals(_selectedFileTypeTab, fileGroup.Key, StringComparison.Ordinal)))
|
|
{
|
|
fileTab = ImRaii.TabItem(fileGroupText + "###" + fileGroup.Key);
|
|
}
|
|
|
|
if (!fileTab) { fileTab.Dispose(); continue; }
|
|
|
|
if (!string.Equals(fileGroup.Key, _selectedFileTypeTab, StringComparison.Ordinal))
|
|
{
|
|
_selectedFileTypeTab = fileGroup.Key;
|
|
_selectedHash = string.Empty;
|
|
_enableBc7ConversionMode = false;
|
|
_texturesToConvert.Clear();
|
|
}
|
|
|
|
ImGui.TextUnformatted(L("DataAnalysis.FileGroup.Count", "{0} files", fileGroup.Key));
|
|
ImGui.SameLine();
|
|
ImGui.TextUnformatted(fileGroup.Count().ToString());
|
|
|
|
ImGui.TextUnformatted(L("DataAnalysis.FileGroup.SizeActual", "{0} files size (actual):", fileGroup.Key));
|
|
ImGui.SameLine();
|
|
ImGui.TextUnformatted(UiSharedService.ByteToString(fileGroup.Sum(c => c.OriginalSize)));
|
|
|
|
ImGui.TextUnformatted(L("DataAnalysis.FileGroup.SizeDownload", "{0} files size (download size):", fileGroup.Key));
|
|
ImGui.SameLine();
|
|
ImGui.TextUnformatted(UiSharedService.ByteToString(fileGroup.Sum(c => c.CompressedSize)));
|
|
|
|
if (string.Equals(_selectedFileTypeTab, "tex", StringComparison.Ordinal))
|
|
{
|
|
ImGui.Checkbox(L("DataAnalysis.Bc7.EnableMode", "Enable BC7 Conversion Mode"), ref _enableBc7ConversionMode);
|
|
if (_enableBc7ConversionMode)
|
|
{
|
|
UiSharedService.ColorText(L("DataAnalysis.Bc7.WarningTitle", "WARNING BC7 CONVERSION:"), ImGuiColors.DalamudYellow);
|
|
ImGui.SameLine();
|
|
UiSharedService.ColorText(L("DataAnalysis.Bc7.WarningIrreversible", "Converting textures to BC7 is irreversible!"), ImGuiColors.DalamudRed);
|
|
UiSharedService.ColorTextWrapped(L("DataAnalysis.Bc7.WarningDetails",
|
|
"- Converting textures to BC7 will reduce their size (compressed and uncompressed) drastically. It is recommended to be used for large (4k+) textures.\n"
|
|
+ "- Some textures, especially ones utilizing colorsets, might not be suited for BC7 conversion and might produce visual artifacts.\n"
|
|
+ "- Before converting textures, make sure to have the original files of the mod you are converting so you can reimport it in case of issues.\n"
|
|
+ "- Conversion will convert all found texture duplicates (entries with more than 1 file path) automatically.\n"
|
|
+ "- Converting textures to BC7 is a very expensive operation and, depending on the amount of textures to convert, will take a while to complete."),
|
|
ImGuiColors.DalamudYellow);
|
|
if (_texturesToConvert.Count > 0 && _uiSharedService.IconTextButton(FontAwesomeIcon.PlayCircle,
|
|
L("DataAnalysis.Bc7.StartConversion", "Start conversion of {0} texture(s)", _texturesToConvert.Count)))
|
|
{
|
|
_conversionCancellationTokenSource = _conversionCancellationTokenSource.CancelRecreate();
|
|
_conversionTask = _ipcManager.Penumbra.ConvertTextureFiles(_logger, _texturesToConvert, _conversionProgress, _conversionCancellationTokenSource.Token);
|
|
}
|
|
}
|
|
}
|
|
|
|
ImGui.Separator();
|
|
DrawTable(fileGroup);
|
|
|
|
fileTab.Dispose();
|
|
}
|
|
}
|
|
}
|
|
|
|
ImGui.Separator();
|
|
|
|
ImGui.TextUnformatted(L("DataAnalysis.SelectedFile", "Selected file:"));
|
|
ImGui.SameLine();
|
|
UiSharedService.ColorText(_selectedHash, ImGuiColors.DalamudYellow);
|
|
|
|
if (_cachedAnalysis[_selectedObjectTab].TryGetValue(_selectedHash, out CharacterAnalyzer.FileDataEntry? item))
|
|
{
|
|
var filePaths = item.FilePaths;
|
|
ImGui.TextUnformatted(L("DataAnalysis.LocalFilePath", "Local file path:"));
|
|
ImGui.SameLine();
|
|
UiSharedService.TextWrapped(filePaths[0]);
|
|
if (filePaths.Count > 1)
|
|
{
|
|
ImGui.SameLine();
|
|
ImGui.TextUnformatted(L("DataAnalysis.MoreCount", "(and {0} more)", filePaths.Count - 1));
|
|
ImGui.SameLine();
|
|
_uiSharedService.IconText(FontAwesomeIcon.InfoCircle);
|
|
UiSharedService.AttachToolTip(string.Join(Environment.NewLine, filePaths.Skip(1)));
|
|
}
|
|
|
|
var gamepaths = item.GamePaths;
|
|
ImGui.TextUnformatted(L("DataAnalysis.GamePath", "Used by game path:"));
|
|
ImGui.SameLine();
|
|
UiSharedService.TextWrapped(gamepaths[0]);
|
|
if (gamepaths.Count > 1)
|
|
{
|
|
ImGui.SameLine();
|
|
ImGui.TextUnformatted(L("DataAnalysis.MoreCount", "(and {0} more)", gamepaths.Count - 1));
|
|
ImGui.SameLine();
|
|
_uiSharedService.IconText(FontAwesomeIcon.InfoCircle);
|
|
UiSharedService.AttachToolTip(string.Join(Environment.NewLine, gamepaths.Skip(1)));
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void OnOpen()
|
|
{
|
|
_hasUpdate = true;
|
|
_selectedHash = string.Empty;
|
|
_enableBc7ConversionMode = false;
|
|
_texturesToConvert.Clear();
|
|
}
|
|
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
base.Dispose(disposing);
|
|
_conversionProgress.ProgressChanged -= ConversionProgress_ProgressChanged;
|
|
}
|
|
|
|
private void ConversionProgress_ProgressChanged(object? sender, (string, int) e)
|
|
{
|
|
_conversionCurrentFileName = e.Item1;
|
|
_conversionCurrentFileProgress = e.Item2;
|
|
}
|
|
|
|
private void DrawTable(IGrouping<string, CharacterAnalyzer.FileDataEntry> fileGroup)
|
|
{
|
|
var tableColumns = string.Equals(fileGroup.Key, "tex", StringComparison.Ordinal)
|
|
? (_enableBc7ConversionMode ? 7 : 6)
|
|
: (string.Equals(fileGroup.Key, "mdl", StringComparison.Ordinal) ? 6 : 5);
|
|
using var table = ImRaii.Table("Analysis", tableColumns, ImGuiTableFlags.Sortable | ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollY | ImGuiTableFlags.SizingFixedFit,
|
|
new Vector2(0, 300));
|
|
if (!table.Success) return;
|
|
ImGui.TableSetupColumn(L("DataAnalysis.Table.Hash", "Hash"));
|
|
ImGui.TableSetupColumn(L("DataAnalysis.Table.Filepaths", "Filepaths"), ImGuiTableColumnFlags.PreferSortDescending);
|
|
ImGui.TableSetupColumn(L("DataAnalysis.Table.Gamepaths", "Gamepaths"), ImGuiTableColumnFlags.PreferSortDescending);
|
|
ImGui.TableSetupColumn(L("DataAnalysis.Table.FileSize", "File Size"), ImGuiTableColumnFlags.DefaultSort | ImGuiTableColumnFlags.PreferSortDescending);
|
|
ImGui.TableSetupColumn(L("DataAnalysis.Table.DownloadSize", "Download Size"), ImGuiTableColumnFlags.PreferSortDescending);
|
|
if (string.Equals(fileGroup.Key, "tex", StringComparison.Ordinal))
|
|
{
|
|
ImGui.TableSetupColumn(L("DataAnalysis.Table.Format", "Format"));
|
|
if (_enableBc7ConversionMode) ImGui.TableSetupColumn(L("DataAnalysis.Table.ConvertToBc7", "Convert to BC7"));
|
|
}
|
|
if (string.Equals(fileGroup.Key, "mdl", StringComparison.Ordinal))
|
|
{
|
|
ImGui.TableSetupColumn(L("DataAnalysis.Table.Triangles", "Triangles"), ImGuiTableColumnFlags.PreferSortDescending);
|
|
}
|
|
ImGui.TableSetupScrollFreeze(0, 1);
|
|
ImGui.TableHeadersRow();
|
|
|
|
var sortSpecs = ImGui.TableGetSortSpecs();
|
|
if (sortSpecs.SpecsDirty || _sortDirty)
|
|
{
|
|
var idx = sortSpecs.Specs.ColumnIndex;
|
|
|
|
if (idx == 0 && sortSpecs.Specs.SortDirection == ImGuiSortDirection.Ascending)
|
|
_cachedAnalysis![_selectedObjectTab] = _cachedAnalysis[_selectedObjectTab].OrderBy(k => k.Key, StringComparer.Ordinal).ToDictionary(d => d.Key, d => d.Value, StringComparer.Ordinal);
|
|
if (idx == 0 && sortSpecs.Specs.SortDirection == ImGuiSortDirection.Descending)
|
|
_cachedAnalysis![_selectedObjectTab] = _cachedAnalysis[_selectedObjectTab].OrderByDescending(k => k.Key, StringComparer.Ordinal).ToDictionary(d => d.Key, d => d.Value, StringComparer.Ordinal);
|
|
if (idx == 1 && sortSpecs.Specs.SortDirection == ImGuiSortDirection.Ascending)
|
|
_cachedAnalysis![_selectedObjectTab] = _cachedAnalysis[_selectedObjectTab].OrderBy(k => k.Value.FilePaths.Count).ToDictionary(d => d.Key, d => d.Value, StringComparer.Ordinal);
|
|
if (idx == 1 && sortSpecs.Specs.SortDirection == ImGuiSortDirection.Descending)
|
|
_cachedAnalysis![_selectedObjectTab] = _cachedAnalysis[_selectedObjectTab].OrderByDescending(k => k.Value.FilePaths.Count).ToDictionary(d => d.Key, d => d.Value, StringComparer.Ordinal);
|
|
if (idx == 2 && sortSpecs.Specs.SortDirection == ImGuiSortDirection.Ascending)
|
|
_cachedAnalysis![_selectedObjectTab] = _cachedAnalysis[_selectedObjectTab].OrderBy(k => k.Value.GamePaths.Count).ToDictionary(d => d.Key, d => d.Value, StringComparer.Ordinal);
|
|
if (idx == 2 && sortSpecs.Specs.SortDirection == ImGuiSortDirection.Descending)
|
|
_cachedAnalysis![_selectedObjectTab] = _cachedAnalysis[_selectedObjectTab].OrderByDescending(k => k.Value.GamePaths.Count).ToDictionary(d => d.Key, d => d.Value, StringComparer.Ordinal);
|
|
if (idx == 3 && sortSpecs.Specs.SortDirection == ImGuiSortDirection.Ascending)
|
|
_cachedAnalysis![_selectedObjectTab] = _cachedAnalysis[_selectedObjectTab].OrderBy(k => k.Value.OriginalSize).ToDictionary(d => d.Key, d => d.Value, StringComparer.Ordinal);
|
|
if (idx == 3 && sortSpecs.Specs.SortDirection == ImGuiSortDirection.Descending)
|
|
_cachedAnalysis![_selectedObjectTab] = _cachedAnalysis[_selectedObjectTab].OrderByDescending(k => k.Value.OriginalSize).ToDictionary(d => d.Key, d => d.Value, StringComparer.Ordinal);
|
|
if (idx == 4 && sortSpecs.Specs.SortDirection == ImGuiSortDirection.Ascending)
|
|
_cachedAnalysis![_selectedObjectTab] = _cachedAnalysis[_selectedObjectTab].OrderBy(k => k.Value.CompressedSize).ToDictionary(d => d.Key, d => d.Value, StringComparer.Ordinal);
|
|
if (idx == 4 && sortSpecs.Specs.SortDirection == ImGuiSortDirection.Descending)
|
|
_cachedAnalysis![_selectedObjectTab] = _cachedAnalysis[_selectedObjectTab].OrderByDescending(k => k.Value.CompressedSize).ToDictionary(d => d.Key, d => d.Value, StringComparer.Ordinal);
|
|
if (string.Equals(fileGroup.Key, "mdl", StringComparison.Ordinal) && idx == 5 && sortSpecs.Specs.SortDirection == ImGuiSortDirection.Ascending)
|
|
_cachedAnalysis![_selectedObjectTab] = _cachedAnalysis[_selectedObjectTab].OrderBy(k => k.Value.Triangles).ToDictionary(d => d.Key, d => d.Value, StringComparer.Ordinal);
|
|
if (string.Equals(fileGroup.Key, "mdl", StringComparison.Ordinal) && idx == 5 && sortSpecs.Specs.SortDirection == ImGuiSortDirection.Descending)
|
|
_cachedAnalysis![_selectedObjectTab] = _cachedAnalysis[_selectedObjectTab].OrderByDescending(k => k.Value.Triangles).ToDictionary(d => d.Key, d => d.Value, StringComparer.Ordinal);
|
|
if (string.Equals(fileGroup.Key, "tex", StringComparison.Ordinal) && idx == 5 && sortSpecs.Specs.SortDirection == ImGuiSortDirection.Ascending)
|
|
_cachedAnalysis![_selectedObjectTab] = _cachedAnalysis[_selectedObjectTab].OrderBy(k => k.Value.Format.Value, StringComparer.Ordinal).ToDictionary(d => d.Key, d => d.Value, StringComparer.Ordinal);
|
|
if (string.Equals(fileGroup.Key, "tex", StringComparison.Ordinal) && idx == 5 && sortSpecs.Specs.SortDirection == ImGuiSortDirection.Descending)
|
|
_cachedAnalysis![_selectedObjectTab] = _cachedAnalysis[_selectedObjectTab].OrderByDescending(k => k.Value.Format.Value, StringComparer.Ordinal).ToDictionary(d => d.Key, d => d.Value, StringComparer.Ordinal);
|
|
|
|
sortSpecs.SpecsDirty = false;
|
|
_sortDirty = false;
|
|
}
|
|
|
|
foreach (var item in fileGroup)
|
|
{
|
|
using var text = ImRaii.PushColor(ImGuiCol.Text, new Vector4(0, 0, 0, 1), string.Equals(item.Hash, _selectedHash, StringComparison.Ordinal));
|
|
using var text2 = ImRaii.PushColor(ImGuiCol.Text, new Vector4(1, 1, 1, 1), !item.IsComputed);
|
|
ImGui.TableNextColumn();
|
|
if (string.Equals(_selectedHash, item.Hash, StringComparison.Ordinal))
|
|
{
|
|
ImGui.TableSetBgColor(ImGuiTableBgTarget.RowBg1, UiSharedService.Color(ImGuiColors.DalamudYellow));
|
|
ImGui.TableSetBgColor(ImGuiTableBgTarget.RowBg0, UiSharedService.Color(ImGuiColors.DalamudYellow));
|
|
}
|
|
ImGui.TextUnformatted(item.Hash);
|
|
if (ImGui.IsItemClicked()) _selectedHash = item.Hash;
|
|
ImGui.TableNextColumn();
|
|
ImGui.TextUnformatted(item.FilePaths.Count.ToString());
|
|
if (ImGui.IsItemClicked()) _selectedHash = item.Hash;
|
|
ImGui.TableNextColumn();
|
|
ImGui.TextUnformatted(item.GamePaths.Count.ToString());
|
|
if (ImGui.IsItemClicked()) _selectedHash = item.Hash;
|
|
ImGui.TableNextColumn();
|
|
ImGui.TextUnformatted(UiSharedService.ByteToString(item.OriginalSize));
|
|
if (ImGui.IsItemClicked()) _selectedHash = item.Hash;
|
|
ImGui.TableNextColumn();
|
|
using (ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudYellow, !item.IsComputed))
|
|
ImGui.TextUnformatted(UiSharedService.ByteToString(item.CompressedSize));
|
|
if (ImGui.IsItemClicked()) _selectedHash = item.Hash;
|
|
if (string.Equals(fileGroup.Key, "tex", StringComparison.Ordinal))
|
|
{
|
|
ImGui.TableNextColumn();
|
|
ImGui.TextUnformatted(item.Format.Value);
|
|
if (ImGui.IsItemClicked()) _selectedHash = item.Hash;
|
|
if (_enableBc7ConversionMode)
|
|
{
|
|
ImGui.TableNextColumn();
|
|
if (item.Format.Value.StartsWith("BC", StringComparison.Ordinal) || item.Format.Value.StartsWith("DXT", StringComparison.Ordinal)
|
|
|| item.Format.Value.StartsWith("24864", StringComparison.Ordinal)) // BC4
|
|
{
|
|
ImGui.TextUnformatted("");
|
|
continue;
|
|
}
|
|
var filePath = item.FilePaths[0];
|
|
bool toConvert = _texturesToConvert.ContainsKey(filePath);
|
|
if (ImGui.Checkbox("###convert" + item.Hash, ref toConvert))
|
|
{
|
|
if (toConvert && !_texturesToConvert.ContainsKey(filePath))
|
|
{
|
|
_texturesToConvert[filePath] = item.FilePaths.Skip(1).ToArray();
|
|
}
|
|
else if (!toConvert && _texturesToConvert.ContainsKey(filePath))
|
|
{
|
|
_texturesToConvert.Remove(filePath);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (string.Equals(fileGroup.Key, "mdl", StringComparison.Ordinal))
|
|
{
|
|
ImGui.TableNextColumn();
|
|
ImGui.TextUnformatted(UiSharedService.TrisToString(item.Triangles));
|
|
if (ImGui.IsItemClicked()) _selectedHash = item.Hash;
|
|
}
|
|
}
|
|
}
|
|
}
|