diff --git a/Penumbra/Services/ServiceManager.cs b/Penumbra/Services/ServiceManager.cs index b55a820f..6d1bf710 100644 --- a/Penumbra/Services/ServiceManager.cs +++ b/Penumbra/Services/ServiceManager.cs @@ -16,6 +16,7 @@ using Penumbra.Mods; using Penumbra.Mods.Manager; using Penumbra.UI; using Penumbra.UI.AdvancedWindow; +using Penumbra.UI.Classes; using Penumbra.UI.ModsTab; using Penumbra.UI.Tabs; @@ -139,6 +140,7 @@ public static class ServiceManager .AddSingleton() .AddSingleton() .AddSingleton() + .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton() diff --git a/Penumbra/UI/Classes/CollectionSelectHeader.cs b/Penumbra/UI/Classes/CollectionSelectHeader.cs new file mode 100644 index 00000000..5c4570bf --- /dev/null +++ b/Penumbra/UI/Classes/CollectionSelectHeader.cs @@ -0,0 +1,76 @@ +using System.Linq; +using System.Numerics; +using ImGuiNET; +using OtterGui.Raii; +using OtterGui; +using Penumbra.Collections; +using Penumbra.Collections.Manager; +using Penumbra.UI.CollectionTab; +using Penumbra.UI.ModsTab; + +namespace Penumbra.UI.Classes; + +public class CollectionSelectHeader +{ + private readonly CollectionCombo _collectionCombo; + private readonly ActiveCollections _activeCollections; + private readonly TutorialService _tutorial; + private readonly ModFileSystemSelector _selector; + + public CollectionSelectHeader(CollectionManager collectionManager, TutorialService tutorial, ModFileSystemSelector selector) + { + _tutorial = tutorial; + _selector = selector; + _activeCollections = collectionManager.Active; + _collectionCombo = new CollectionCombo(collectionManager, () => collectionManager.Storage.OrderBy(c => c.Name).ToList()); + } + + /// Draw the header line that can quick switch between collections. + public void Draw(bool spacing) + { + using var style = ImRaii.PushStyle(ImGuiStyleVar.FrameRounding, 0).Push(ImGuiStyleVar.ItemSpacing, new Vector2(0, spacing ? ImGui.GetStyle().ItemSpacing.Y : 0)); + var buttonSize = new Vector2(ImGui.GetContentRegionAvail().X / 8f, 0); + + using (var _ = ImRaii.Group()) + { + DrawDefaultCollectionButton(3 * buttonSize); + ImGui.SameLine(); + DrawInheritedCollectionButton(3 * buttonSize); + ImGui.SameLine(); + _collectionCombo.Draw("##collectionSelector", 2 * buttonSize.X, ColorId.SelectedCollection.Value()); + } + + _tutorial.OpenTutorial(BasicTutorialSteps.CollectionSelectors); + + if (!_activeCollections.CurrentCollectionInUse) + ImGuiUtil.DrawTextButton("The currently selected collection is not used in any way.", -Vector2.UnitX, Colors.PressEnterWarningBg); + } + + private void DrawDefaultCollectionButton(Vector2 width) + { + var name = $"{TutorialService.DefaultCollection} ({_activeCollections.Default.Name})"; + var isCurrent = _activeCollections.Default == _activeCollections.Current; + var isEmpty = _activeCollections.Default == ModCollection.Empty; + var tt = isCurrent ? $"The current collection is already the configured {TutorialService.DefaultCollection}." + : isEmpty ? $"The {TutorialService.DefaultCollection} is configured to be empty." + : $"Set the {TutorialService.SelectedCollection} to the configured {TutorialService.DefaultCollection}."; + if (ImGuiUtil.DrawDisabledButton(name, width, tt, isCurrent || isEmpty)) + _activeCollections.SetCollection(_activeCollections.Default, CollectionType.Current); + } + + private void DrawInheritedCollectionButton(Vector2 width) + { + var noModSelected = _selector.Selected == null; + var collection = _selector.SelectedSettingCollection; + var modInherited = collection != _activeCollections.Current; + var (name, tt) = (noModSelected, modInherited) switch + { + (true, _) => ("Inherited Collection", "No mod selected."), + (false, true) => ($"Inherited Collection ({collection.Name})", + "Set the current collection to the collection the selected mod inherits its settings from."), + (false, false) => ("Not Inherited", "The selected mod does not inherit its settings."), + }; + if (ImGuiUtil.DrawDisabledButton(name, width, tt, noModSelected || !modInherited)) + _activeCollections.SetCollection(collection, CollectionType.Current); + } +} diff --git a/Penumbra/UI/Tabs/ChangedItemsTab.cs b/Penumbra/UI/Tabs/ChangedItemsTab.cs index 92ce322d..b7880d0c 100644 --- a/Penumbra/UI/Tabs/ChangedItemsTab.cs +++ b/Penumbra/UI/Tabs/ChangedItemsTab.cs @@ -16,13 +16,15 @@ namespace Penumbra.UI.Tabs; public class ChangedItemsTab : ITab { - private readonly CollectionManager _collectionManager; - private readonly CommunicatorService _communicator; + private readonly CollectionManager _collectionManager; + private readonly CommunicatorService _communicator; + private readonly CollectionSelectHeader _collectionHeader; - public ChangedItemsTab(CollectionManager collectionManager, CommunicatorService communicator) + public ChangedItemsTab(CollectionManager collectionManager, CommunicatorService communicator, CollectionSelectHeader collectionHeader) { _collectionManager = collectionManager; _communicator = communicator; + _collectionHeader = collectionHeader; } public ReadOnlySpan Label @@ -32,7 +34,8 @@ public class ChangedItemsTab : ITab private LowerString _changedItemModFilter = LowerString.Empty; public void DrawContent() - { + { + _collectionHeader.Draw(true); var varWidth = DrawFilters(); using var child = ImRaii.Child("##changedItemsChild", -Vector2.One); if (!child) diff --git a/Penumbra/UI/Tabs/EffectiveTab.cs b/Penumbra/UI/Tabs/EffectiveTab.cs index d66c680e..de9ad706 100644 --- a/Penumbra/UI/Tabs/EffectiveTab.cs +++ b/Penumbra/UI/Tabs/EffectiveTab.cs @@ -9,41 +9,47 @@ using OtterGui.Classes; using OtterGui.Raii; using OtterGui.Widgets; using Penumbra.Collections; -using Penumbra.Collections.Cache; +using Penumbra.Collections.Cache; using Penumbra.Collections.Manager; using Penumbra.Meta.Manipulations; using Penumbra.Mods; using Penumbra.String.Classes; - +using Penumbra.UI.Classes; + namespace Penumbra.UI.Tabs; public class EffectiveTab : ITab { - private readonly CollectionManager _collectionManager; - - public EffectiveTab(CollectionManager collectionManager) - => _collectionManager = collectionManager; + private readonly CollectionManager _collectionManager; + private readonly CollectionSelectHeader _collectionHeader; + + public EffectiveTab(CollectionManager collectionManager, CollectionSelectHeader collectionHeader) + { + _collectionManager = collectionManager; + _collectionHeader = collectionHeader; + } public ReadOnlySpan Label => "Effective Changes"u8; public void DrawContent() { - SetupEffectiveSizes(); + SetupEffectiveSizes(); + _collectionHeader.Draw(true); DrawFilters(); using var child = ImRaii.Child("##EffectiveChangesTab", -Vector2.One, false); if (!child) return; - var height = ImGui.GetTextLineHeightWithSpacing() + 2 * ImGui.GetStyle().CellPadding.Y; - var skips = ImGuiClip.GetNecessarySkips(height); - using var table = ImRaii.Table("##EffectiveChangesTable", 3, ImGuiTableFlags.RowBg); + var height = ImGui.GetTextLineHeightWithSpacing() + 2 * ImGui.GetStyle().CellPadding.Y; + var skips = ImGuiClip.GetNecessarySkips(height); + using var table = ImRaii.Table("##EffectiveChangesTable", 3, ImGuiTableFlags.RowBg); if (!table) return; ImGui.TableSetupColumn("##gamePath", ImGuiTableColumnFlags.WidthFixed, _effectiveLeftTextLength); ImGui.TableSetupColumn(string.Empty, ImGuiTableColumnFlags.WidthFixed, _effectiveArrowLength); - ImGui.TableSetupColumn("##file", ImGuiTableColumnFlags.WidthFixed, _effectiveRightTextLength); + ImGui.TableSetupColumn("##file", ImGuiTableColumnFlags.WidthFixed, _effectiveRightTextLength); DrawEffectiveRows(_collectionManager.Active.Current, skips, height, _effectiveFilePathFilter.Length > 0 || _effectiveGamePathFilter.Length > 0); @@ -69,8 +75,8 @@ public class EffectiveTab : ITab ImGui.CalcTextSize(FontAwesomeIcon.LongArrowAltLeft.ToIconString()).X / UiHelpers.Scale; } - _effectiveArrowLength = _effectiveUnscaledArrowLength * UiHelpers.Scale; - _effectiveLeftTextLength = 450 * UiHelpers.Scale; + _effectiveArrowLength = _effectiveUnscaledArrowLength * UiHelpers.Scale; + _effectiveLeftTextLength = 450 * UiHelpers.Scale; _effectiveRightTextLength = ImGui.GetWindowSize().X - _effectiveArrowLength - _effectiveLeftTextLength; } @@ -89,7 +95,7 @@ public class EffectiveTab : ITab _effectiveFilePathFilter = tmp; } - /// Draw all rows for one collection respecting filters and using clipping. + /// Draw all rows for one collection respecting filters and using clipping. private void DrawEffectiveRows(ModCollection active, int skips, float height, bool hasFilters) { // We can use the known counts if no filters are active. @@ -134,7 +140,7 @@ public class EffectiveTab : ITab } } - /// Draw a line for a game path and its redirected file. + /// Draw a line for a game path and its redirected file. private static void DrawLine(KeyValuePair pair) { var (path, name) = pair; @@ -148,7 +154,7 @@ public class EffectiveTab : ITab ImGuiUtil.HoverTooltip($"\nChanged by {name.Mod.Name}."); } - /// Draw a line for a path and its name. + /// Draw a line for a path and its name. private static void DrawLine((string, LowerString) pair) { var (path, name) = pair; @@ -161,7 +167,7 @@ public class EffectiveTab : ITab ImGuiUtil.CopyOnClickSelectable(name); } - /// Draw a line for a unfiltered/unconverted manipulation and mod-index pair. + /// Draw a line for a unfiltered/unconverted manipulation and mod-index pair. private static void DrawLine(KeyValuePair pair) { var (manipulation, mod) = pair; @@ -174,7 +180,7 @@ public class EffectiveTab : ITab ImGuiUtil.CopyOnClickSelectable(mod.Name); } - /// Check filters for file replacements. + /// Check filters for file replacements. private bool CheckFilters(KeyValuePair kvp) { var (gamePath, fullPath) = kvp; @@ -184,7 +190,7 @@ public class EffectiveTab : ITab return _effectiveFilePathFilter.Length == 0 || fullPath.Path.FullName.ToLowerInvariant().Contains(_effectiveFilePathFilter.Lower); } - /// Check filters for meta manipulations. + /// Check filters for meta manipulations. private bool CheckFilters((string, LowerString) kvp) { var (name, path) = kvp; diff --git a/Penumbra/UI/Tabs/ModsTab.cs b/Penumbra/UI/Tabs/ModsTab.cs index b926c2c5..dba4c535 100644 --- a/Penumbra/UI/Tabs/ModsTab.cs +++ b/Penumbra/UI/Tabs/ModsTab.cs @@ -23,18 +23,19 @@ namespace Penumbra.UI.Tabs; public class ModsTab : ITab { - private readonly ModFileSystemSelector _selector; - private readonly ModPanel _panel; - private readonly TutorialService _tutorial; - private readonly ModManager _modManager; - private readonly ActiveCollections _activeCollections; - private readonly RedrawService _redrawService; - private readonly Configuration _config; - private readonly CollectionCombo _collectionCombo; - private readonly ClientState _clientState; + private readonly ModFileSystemSelector _selector; + private readonly ModPanel _panel; + private readonly TutorialService _tutorial; + private readonly ModManager _modManager; + private readonly ActiveCollections _activeCollections; + private readonly RedrawService _redrawService; + private readonly Configuration _config; + private readonly ClientState _clientState; + private readonly CollectionSelectHeader _collectionHeader; public ModsTab(ModManager modManager, CollectionManager collectionManager, ModFileSystemSelector selector, ModPanel panel, - TutorialService tutorial, RedrawService redrawService, Configuration config, ClientState clientState) + TutorialService tutorial, RedrawService redrawService, Configuration config, ClientState clientState, + CollectionSelectHeader collectionHeader) { _modManager = modManager; _activeCollections = collectionManager.Active; @@ -44,7 +45,7 @@ public class ModsTab : ITab _redrawService = redrawService; _config = config; _clientState = clientState; - _collectionCombo = new CollectionCombo(collectionManager, () => collectionManager.Storage.OrderBy(c => c.Name).ToList()); + _collectionHeader = collectionHeader; } public bool IsVisible @@ -68,7 +69,7 @@ public class ModsTab : ITab _selector.Draw(GetModSelectorSize(_config)); ImGui.SameLine(); using var group = ImRaii.Group(); - DrawHeaderLine(); + _collectionHeader.Draw(false); using var style = ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero); @@ -162,53 +163,4 @@ public class ModsTab : ITab ImGui.SameLine(); DrawButton(frameHeight with { X = ImGui.GetContentRegionAvail().X - 1 }, "Focus", "focus"); } - - /// Draw the header line that can quick switch between collections. - private void DrawHeaderLine() - { - using var style = ImRaii.PushStyle(ImGuiStyleVar.FrameRounding, 0).Push(ImGuiStyleVar.ItemSpacing, Vector2.Zero); - var buttonSize = new Vector2(ImGui.GetContentRegionAvail().X / 8f, 0); - - using (var _ = ImRaii.Group()) - { - DrawDefaultCollectionButton(3 * buttonSize); - ImGui.SameLine(); - DrawInheritedCollectionButton(3 * buttonSize); - ImGui.SameLine(); - _collectionCombo.Draw("##collectionSelector", 2 * buttonSize.X, ColorId.SelectedCollection.Value()); - } - - _tutorial.OpenTutorial(BasicTutorialSteps.CollectionSelectors); - - if (!_activeCollections.CurrentCollectionInUse) - ImGuiUtil.DrawTextButton("The currently selected collection is not used in any way.", -Vector2.UnitX, Colors.PressEnterWarningBg); - } - - private void DrawDefaultCollectionButton(Vector2 width) - { - var name = $"{TutorialService.DefaultCollection} ({_activeCollections.Default.Name})"; - var isCurrent = _activeCollections.Default == _activeCollections.Current; - var isEmpty = _activeCollections.Default == ModCollection.Empty; - var tt = isCurrent ? $"The current collection is already the configured {TutorialService.DefaultCollection}." - : isEmpty ? $"The {TutorialService.DefaultCollection} is configured to be empty." - : $"Set the {TutorialService.SelectedCollection} to the configured {TutorialService.DefaultCollection}."; - if (ImGuiUtil.DrawDisabledButton(name, width, tt, isCurrent || isEmpty)) - _activeCollections.SetCollection(_activeCollections.Default, CollectionType.Current); - } - - private void DrawInheritedCollectionButton(Vector2 width) - { - var noModSelected = _selector.Selected == null; - var collection = _selector.SelectedSettingCollection; - var modInherited = collection != _activeCollections.Current; - var (name, tt) = (noModSelected, modInherited) switch - { - (true, _) => ("Inherited Collection", "No mod selected."), - (false, true) => ($"Inherited Collection ({collection.Name})", - "Set the current collection to the collection the selected mod inherits its settings from."), - (false, false) => ("Not Inherited", "The selected mod does not inherit its settings."), - }; - if (ImGuiUtil.DrawDisabledButton(name, width, tt, noModSelected || !modInherited)) - _activeCollections.SetCollection(collection, CollectionType.Current); - } }