From e9fc57022e3c95ac0f5f47e9d5ee0afcbe4ad9bb Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Tue, 18 Apr 2023 18:42:33 +0200 Subject: [PATCH] Add new Mod Collections tab. --- OtterGui | 2 +- Penumbra/UI/ConfigWindow.cs | 10 +- Penumbra/UI/ModsTab/ModPanelCollectionsTab.cs | 107 ++++++++++++++++++ Penumbra/UI/ModsTab/ModPanelEditTab.cs | 4 +- Penumbra/UI/ModsTab/ModPanelTabBar.cs | 13 ++- 5 files changed, 126 insertions(+), 10 deletions(-) create mode 100644 Penumbra/UI/ModsTab/ModPanelCollectionsTab.cs diff --git a/OtterGui b/OtterGui index 8ebcbf3e..51c350b5 160000 --- a/OtterGui +++ b/OtterGui @@ -1 +1 @@ -Subproject commit 8ebcbf3e78ed498be35fa2b9a13d9765d109c428 +Subproject commit 51c350b5f129b53afda3a51b057c228e152a6b88 diff --git a/Penumbra/UI/ConfigWindow.cs b/Penumbra/UI/ConfigWindow.cs index 7484a344..7e465a82 100644 --- a/Penumbra/UI/ConfigWindow.cs +++ b/Penumbra/UI/ConfigWindow.cs @@ -9,8 +9,7 @@ using Penumbra.Api.Enums; using Penumbra.Mods; using Penumbra.UI.Classes; using Penumbra.UI.Tabs; -using Penumbra.Util; - +using Penumbra.Util; namespace Penumbra.UI; public sealed class ConfigWindow : Window @@ -45,7 +44,7 @@ public sealed class ConfigWindow : Window RespectCloseHotkey = true; SizeConstraints = new WindowSizeConstraints() { - MinimumSize = new Vector2(800, 600), + MinimumSize = new Vector2(900, 600), MaximumSize = new Vector2(4096, 2160), }; tutorial.UpdateTutorialStep(); @@ -112,9 +111,12 @@ public sealed class ConfigWindow : Window var text = e.ToString(); if (text == _lastException) return; - _lastException = text; } + else + { + _lastException = e.ToString(); + } Penumbra.Log.Error($"Exception thrown during UI Render:\n{_lastException}"); } diff --git a/Penumbra/UI/ModsTab/ModPanelCollectionsTab.cs b/Penumbra/UI/ModsTab/ModPanelCollectionsTab.cs new file mode 100644 index 00000000..069c981d --- /dev/null +++ b/Penumbra/UI/ModsTab/ModPanelCollectionsTab.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using Dalamud.Interface; +using ImGuiNET; +using Lumina.Data.Parsing.Layer; +using OtterGui; +using OtterGui.Raii; +using OtterGui.Widgets; +using Penumbra.Collections; +using Penumbra.Collections.Manager; +using Penumbra.Mods; +using Penumbra.UI.Classes; + +namespace Penumbra.UI.ModsTab; + +public class ModPanelCollectionsTab : ITab +{ + private readonly Configuration _config; + private readonly ModFileSystemSelector _selector; + private readonly CollectionStorage _collections; + + private readonly List<(ModCollection, ModCollection, uint, string)> _cache = new(); + + public ModPanelCollectionsTab(Configuration config, CollectionStorage storage, ModFileSystemSelector selector) + { + _config = config; + _collections = storage; + _selector = selector; + } + + public ReadOnlySpan Label + => "Collections"u8; + + public void DrawContent() + { + var (direct, inherited) = CountUsage(_selector.Selected!); + ImGui.NewLine(); + if (direct == 1) + ImGui.TextUnformatted("This Mod is directly configured in 1 collection."); + else if (direct == 0) + ImGuiUtil.TextColored(Colors.RegexWarningBorder, "This mod is entirely unused."); + else + ImGui.TextUnformatted($"This Mod is directly configured in {direct} collections."); + if (inherited > 0) + { + ImGui.TextUnformatted($"It is also implicitly used in {inherited} {(inherited == 1 ? "collection" : "collections")} through inheritance."); + } + + ImGui.NewLine(); + ImGui.Separator(); + ImGui.NewLine(); + using var table = ImRaii.Table("##modCollections", 3, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg); + if (!table) + return; + + var size = ImGui.CalcTextSize("Unconfigured").X + 20 * ImGuiHelpers.GlobalScale; + var collectionSize = 200 * ImGuiHelpers.GlobalScale; + ImGui.TableSetupColumn("Collection", ImGuiTableColumnFlags.WidthFixed, collectionSize); + ImGui.TableSetupColumn("State", ImGuiTableColumnFlags.WidthFixed, size); + ImGui.TableSetupColumn("Inherited From", ImGuiTableColumnFlags.WidthFixed, collectionSize); + + ImGui.TableHeadersRow(); + foreach (var (collection, parent, color, text) in _cache) + { + ImGui.TableNextColumn(); + ImGui.TextUnformatted(collection.Name); + + ImGui.TableNextColumn(); + using (var c = ImRaii.PushColor(ImGuiCol.Text, color)) + { + ImGui.TextUnformatted(text); + } + + ImGui.TableNextColumn(); + ImGui.TextUnformatted(parent == collection ? string.Empty : parent.Name); + } + } + + private (int Direct, int Inherited) CountUsage(Mod mod) + { + _cache.Clear(); + var undefined = ColorId.UndefinedMod.Value(_config); + var enabled = ColorId.EnabledMod.Value(_config); + var inherited = ColorId.InheritedMod.Value(_config); + var disabled = ColorId.DisabledMod.Value(_config); + var disInherited = ColorId.InheritedDisabledMod.Value(_config); + var directCount = 0; + var inheritedCount = 0; + foreach (var collection in _collections) + { + var (settings, parent) = collection[mod.Index]; + var (color, text) = settings == null + ? (undefined, "Unconfigured") + : settings.Enabled + ? (parent == collection ? enabled : inherited, "Enabled") + : (parent == collection ? disabled : disInherited, "Disabled"); + _cache.Add((collection, parent, color, text)); + + if (color == enabled) + ++directCount; + else if (color == inherited) + ++inheritedCount; + } + + return (directCount, inheritedCount); + } +} diff --git a/Penumbra/UI/ModsTab/ModPanelEditTab.cs b/Penumbra/UI/ModsTab/ModPanelEditTab.cs index 9ecbdc41..68f9707d 100644 --- a/Penumbra/UI/ModsTab/ModPanelEditTab.cs +++ b/Penumbra/UI/ModsTab/ModPanelEditTab.cs @@ -198,13 +198,13 @@ public class ModPanelEditTab : ITab _delayedActions.Enqueue(() => DescriptionEdit.OpenPopup(_filenames, _mod, Input.Description)); ImGui.SameLine(); - var fileExists = File.Exists(_modManager.DataEditor.MetaFile(_mod)); + var fileExists = File.Exists(_filenames.ModMetaPath(_mod)); var tt = fileExists ? "Open the metadata json file in the text editor of your choice." : "The metadata json file does not exist."; if (ImGuiUtil.DrawDisabledButton($"{FontAwesomeIcon.FileExport.ToIconString()}##metaFile", UiHelpers.IconButtonSize, tt, !fileExists, true)) - Process.Start(new ProcessStartInfo(_modManager.DataEditor.MetaFile(_mod)) { UseShellExecute = true }); + Process.Start(new ProcessStartInfo(_filenames.ModMetaPath(_mod)) { UseShellExecute = true }); } /// Do some edits outside of iterations. diff --git a/Penumbra/UI/ModsTab/ModPanelTabBar.cs b/Penumbra/UI/ModsTab/ModPanelTabBar.cs index 59dce714..503e471f 100644 --- a/Penumbra/UI/ModsTab/ModPanelTabBar.cs +++ b/Penumbra/UI/ModsTab/ModPanelTabBar.cs @@ -19,16 +19,18 @@ public class ModPanelTabBar Settings, ChangedItems, Conflicts, + Collections, Edit, }; public readonly ModPanelSettingsTab Settings; public readonly ModPanelDescriptionTab Description; + public readonly ModPanelCollectionsTab Collections; public readonly ModPanelConflictsTab Conflicts; public readonly ModPanelChangedItemsTab ChangedItems; public readonly ModPanelEditTab Edit; private readonly ModEditWindow _modEditWindow; - private readonly ModManager _modManager; + private readonly ModManager _modManager; private readonly TutorialService _tutorial; public readonly ITab[] Tabs; @@ -37,7 +39,7 @@ public class ModPanelTabBar public ModPanelTabBar(ModEditWindow modEditWindow, ModPanelSettingsTab settings, ModPanelDescriptionTab description, ModPanelConflictsTab conflicts, ModPanelChangedItemsTab changedItems, ModPanelEditTab edit, ModManager modManager, - TutorialService tutorial) + TutorialService tutorial, ModPanelCollectionsTab collections) { _modEditWindow = modEditWindow; Settings = settings; @@ -47,6 +49,7 @@ public class ModPanelTabBar Edit = edit; _modManager = modManager; _tutorial = tutorial; + Collections = collections; Tabs = new ITab[] { @@ -54,6 +57,7 @@ public class ModPanelTabBar Description, Conflicts, ChangedItems, + Collections, Edit, }; } @@ -83,6 +87,7 @@ public class ModPanelTabBar ModPanelTabType.Settings => Settings.Label, ModPanelTabType.ChangedItems => ChangedItems.Label, ModPanelTabType.Conflicts => Conflicts.Label, + ModPanelTabType.Collections => Collections.Label, ModPanelTabType.Edit => Edit.Label, _ => ReadOnlySpan.Empty, }; @@ -97,6 +102,8 @@ public class ModPanelTabBar return ModPanelTabType.ChangedItems; if (label == Conflicts.Label) return ModPanelTabType.Conflicts; + if (label == Collections.Label) + return ModPanelTabType.Collections; if (label == Edit.Label) return ModPanelTabType.Edit; @@ -108,7 +115,7 @@ public class ModPanelTabBar if (ImGui.TabItemButton("Advanced Editing", ImGuiTabItemFlags.Trailing | ImGuiTabItemFlags.NoTooltip)) { _modEditWindow.ChangeMod(mod); - _modEditWindow.ChangeOption((SubMod) mod.Default); + _modEditWindow.ChangeOption((SubMod)mod.Default); _modEditWindow.IsOpen = true; }