diff --git a/Glamourer/Api/DesignsApi.cs b/Glamourer/Api/DesignsApi.cs index e21e6cb..9b48ade 100644 --- a/Glamourer/Api/DesignsApi.cs +++ b/Glamourer/Api/DesignsApi.cs @@ -20,12 +20,12 @@ public class DesignsApi( => designs.Designs.ToDictionary(d => d.Identifier, d => d.Name.Text); public Dictionary GetDesignListExtended() - => designs.Designs.ToDictionary(d => d.Identifier, - d => (d.Name.Text, fileSystem.FindLeaf(d, out var leaf) ? leaf.FullName() : d.Name.Text, color.GetColor(d), d.QuickDesign)); + => fileSystem.ToDictionary(kvp => kvp.Key.Identifier, + kvp => (kvp.Key.Name.Text, kvp.Value.FullName(), color.GetColor(kvp.Key), kvp.Key.QuickDesign)); public (string DisplayName, string FullPath, uint DisplayColor, bool ShowInQdb) GetExtendedDesignData(Guid designId) => designs.Designs.ByIdentifier(designId) is { } d - ? (d.Name.Text, fileSystem.FindLeaf(d, out var leaf) ? leaf.FullName() : d.Name.Text, color.GetColor(d), d.QuickDesign) + ? (d.Name.Text, fileSystem.TryGetValue(d, out var leaf) ? leaf.FullName() : d.Name.Text, color.GetColor(d), d.QuickDesign) : (string.Empty, string.Empty, 0, false); public GlamourerApiEc ApplyDesign(Guid designId, int objectIndex, uint key, ApplyFlag flags) diff --git a/Glamourer/Designs/DesignFileSystem.cs b/Glamourer/Designs/DesignFileSystem.cs index e985e32..4a1cb3d 100644 --- a/Glamourer/Designs/DesignFileSystem.cs +++ b/Glamourer/Designs/DesignFileSystem.cs @@ -114,14 +114,14 @@ public sealed class DesignFileSystem : FileSystem, IDisposable, ISavable return; case DesignChanged.Type.Deleted: - if (FindLeaf(design, out var leaf1)) + if (TryGetValue(design, out var leaf1)) Delete(leaf1); return; case DesignChanged.Type.ReloadedAll: Reload(); return; case DesignChanged.Type.Renamed when (data as RenameTransaction?)?.Old is { } oldName: - if (!FindLeaf(design, out var leaf2)) + if (!TryGetValue(design, out var leaf2)) return; var old = oldName.FixName(); @@ -150,15 +150,6 @@ public sealed class DesignFileSystem : FileSystem, IDisposable, ISavable ? (string.Empty, false) : (DesignToIdentifier(design), true); - // Search the entire filesystem for the leaf corresponding to a design. - public bool FindLeaf(Design design, [NotNullWhen(true)] out Leaf? leaf) - { - leaf = Root.GetAllDescendants(ISortMode.Lexicographical) - .OfType() - .FirstOrDefault(l => l.Value == design); - return leaf != null; - } - internal static void MigrateOldPaths(SaveService saveService, Dictionary oldPaths) { if (oldPaths.Count == 0) diff --git a/Glamourer/Designs/Special/RandomPredicate.cs b/Glamourer/Designs/Special/RandomPredicate.cs index efb3233..ae05f8f 100644 --- a/Glamourer/Designs/Special/RandomPredicate.cs +++ b/Glamourer/Designs/Special/RandomPredicate.cs @@ -22,7 +22,7 @@ public interface IDesignPredicate : designs; private static (Design Design, string LowerName, string Identifier, string LowerPath) Transform(Design d, DesignFileSystem fs) - => (d, d.Name.Lower, d.Identifier.ToString(), fs.FindLeaf(d, out var l) ? l.FullName().ToLowerInvariant() : string.Empty); + => (d, d.Name.Lower, d.Identifier.ToString(), fs.TryGetValue(d, out var l) ? l.FullName().ToLowerInvariant() : string.Empty); } public static class RandomPredicate diff --git a/Glamourer/Gui/DesignCombo.cs b/Glamourer/Gui/DesignCombo.cs index c1e474d..e5f3785 100644 --- a/Glamourer/Gui/DesignCombo.cs +++ b/Glamourer/Gui/DesignCombo.cs @@ -10,7 +10,6 @@ using OtterGui; using OtterGui.Classes; using OtterGui.Extensions; using OtterGui.Log; -using OtterGui.Services; using OtterGui.Widgets; namespace Glamourer.Gui; @@ -22,8 +21,8 @@ public abstract class DesignComboBase : FilterComboCache>> generator, Logger log, DesignChanged designChanged, TabSelected tabSelected, EphemeralConfig config, DesignColors designColors) @@ -34,7 +33,6 @@ public abstract class DesignComboBase : FilterComboCache _currentDesign == p.Item1); - UpdateSelection(CurrentSelectionIdx >= 0 ? Items[CurrentSelectionIdx] : null); - return CurrentSelectionIdx; - } - protected bool Draw(IDesignStandIn? currentDesign, string? label, float width) { _currentDesign = currentDesign; - InnerWidth = 400 * ImGuiHelpers.GlobalScale; + UpdateCurrentSelection(); + InnerWidth = 400 * ImGuiHelpers.GlobalScale; var name = label ?? "Select Design Here..."; bool ret; using (_ = currentDesign != null ? ImRaii.PushColor(ImGuiCol.Text, DesignColors.GetColor(currentDesign as Design)) : null) @@ -150,37 +123,52 @@ public abstract class DesignComboBase : FilterComboCache ReferenceEquals(s.Item1, CurrentSelection?.Item1)); + if (CurrentSelectionIdx >= 0) + { + UpdateSelection(Items[CurrentSelectionIdx]); + } + else if (Items.Count > 0) + { + CurrentSelectionIdx = 0; + UpdateSelection(Items[0]); + } + else + { + UpdateSelection(null); + } + + if (!priorState) + Cleanup(); + _isCurrentSelectionDirty = false; + } + + protected override int UpdateCurrentSelected(int currentSelected) + { + CurrentSelectionIdx = Items.IndexOf(p => _currentDesign == p.Item1); + UpdateSelection(CurrentSelectionIdx >= 0 ? Items[CurrentSelectionIdx] : null); + return CurrentSelectionIdx; + } + private void OnDesignChanged(DesignChanged.Type type, Design? _1, ITransaction? _2 = null) { - switch (type) + _isCurrentSelectionDirty = type switch { - case DesignChanged.Type.Created: - case DesignChanged.Type.Renamed: - case DesignChanged.Type.ChangedColor: - case DesignChanged.Type.Deleted: - case DesignChanged.Type.QuickDesignBar: - var priorState = IsInitialized; - if (priorState) - Cleanup(); - CurrentSelectionIdx = Items.IndexOf(s => ReferenceEquals(s.Item1, CurrentSelection?.Item1)); - if (CurrentSelectionIdx >= 0) - { - UpdateSelection(Items[CurrentSelectionIdx]); - } - else if (Items.Count > 0) - { - CurrentSelectionIdx = 0; - UpdateSelection(Items[0]); - } - else - { - UpdateSelection(null); - } - - if (!priorState) - Cleanup(); - break; - } + DesignChanged.Type.Created => true, + DesignChanged.Type.Renamed => true, + DesignChanged.Type.ChangedColor => true, + DesignChanged.Type.Deleted => true, + DesignChanged.Type.QuickDesignBar => true, + _ => _isCurrentSelectionDirty, + }; } private void QuickSelectedDesignTooltip(IDesignStandIn? design) @@ -248,8 +236,7 @@ public abstract class DesignCombo : DesignComboBase public sealed class QuickDesignCombo : DesignCombo { - public QuickDesignCombo(DesignManager designs, - DesignFileSystem fileSystem, + public QuickDesignCombo(DesignFileSystem fileSystem, Logger log, DesignChanged designChanged, TabSelected tabSelected, @@ -257,9 +244,9 @@ public sealed class QuickDesignCombo : DesignCombo DesignColors designColors) : base(log, designChanged, tabSelected, config, designColors, () => [ - .. designs.Designs - .Where(d => d.QuickDesign) - .Select(d => new Tuple(d, fileSystem.FindLeaf(d, out var l) ? l.FullName() : string.Empty)) + .. fileSystem + .Where(kvp => kvp.Key.QuickDesign) + .Select(kvp => new Tuple(kvp.Key, kvp.Value.FullName())) .OrderBy(d => d.Item2), ]) { @@ -300,7 +287,6 @@ public sealed class QuickDesignCombo : DesignCombo } public sealed class LinkDesignCombo( - DesignManager designs, DesignFileSystem fileSystem, Logger log, DesignChanged designChanged, @@ -309,8 +295,8 @@ public sealed class LinkDesignCombo( DesignColors designColors) : DesignCombo(log, designChanged, tabSelected, config, designColors, () => [ - .. designs.Designs - .Select(d => new Tuple(d, fileSystem.FindLeaf(d, out var l) ? l.FullName() : string.Empty)) + .. fileSystem + .Select(kvp => new Tuple(kvp.Key, kvp.Value.FullName())) .OrderBy(d => d.Item2), ]); @@ -324,8 +310,8 @@ public sealed class RandomDesignCombo( DesignColors designColors) : DesignCombo(log, designChanged, tabSelected, config, designColors, () => [ - .. designs.Designs - .Select(d => new Tuple(d, fileSystem.FindLeaf(d, out var l) ? l.FullName() : string.Empty)) + .. fileSystem + .Select(kvp => new Tuple(kvp.Key, kvp.Value.FullName())) .OrderBy(d => d.Item2), ]) { @@ -351,7 +337,6 @@ public sealed class RandomDesignCombo( } public sealed class SpecialDesignCombo( - DesignManager designs, DesignFileSystem fileSystem, TabSelected tabSelected, DesignColors designColors, @@ -361,8 +346,8 @@ public sealed class SpecialDesignCombo( EphemeralConfig config, RandomDesignGenerator rng, QuickSelectedDesign quickSelectedDesign) - : DesignComboBase(() => designs.Designs - .Select(d => new Tuple(d, fileSystem.FindLeaf(d, out var l) ? l.FullName() : string.Empty)) + : DesignComboBase(() => fileSystem + .Select(kvp => new Tuple(kvp.Key, kvp.Value.FullName())) .OrderBy(d => d.Item2) .Prepend(new Tuple(new RandomDesign(rng), string.Empty)) .Prepend(new Tuple(quickSelectedDesign, string.Empty)) @@ -380,29 +365,3 @@ public sealed class SpecialDesignCombo( autoDesignManager.AddDesign(set, CurrentSelection!.Item1); } } - -public class DesignComboWrapper(ServiceManager services) -{ - public readonly IReadOnlyList Combos = services.GetServicesImplementing().ToArray(); - - internal DesignComboListener StopListening() - { - var list = new List(Combos.Count); - foreach (var combo in Combos.Where(c => c.IsListening)) - { - combo.StopListening(); - list.Add(combo); - } - - return new DesignComboListener(list); - } - - internal readonly struct DesignComboListener(List combos) : IDisposable - { - public void Dispose() - { - foreach (var combo in combos) - combo.StartListening(); - } - } -} diff --git a/Glamourer/Gui/Tabs/AutomationTab/RandomRestrictionDrawer.cs b/Glamourer/Gui/Tabs/AutomationTab/RandomRestrictionDrawer.cs index e7efc09..ae3be7e 100644 --- a/Glamourer/Gui/Tabs/AutomationTab/RandomRestrictionDrawer.cs +++ b/Glamourer/Gui/Tabs/AutomationTab/RandomRestrictionDrawer.cs @@ -278,7 +278,7 @@ public sealed class RandomRestrictionDrawer : IService, IDisposable private void LookupTooltip(IEnumerable designs) { using var _ = ImRaii.Tooltip(); - var tt = string.Join('\n', designs.Select(d => _designFileSystem.FindLeaf(d, out var l) ? l.FullName() : d.Name.Text).OrderBy(t => t)); + var tt = string.Join('\n', designs.Select(d => _designFileSystem.TryGetValue(d, out var l) ? l.FullName() : d.Name.Text).OrderBy(t => t)); ImGui.TextUnformatted(tt.Length == 0 ? "Matches no currently existing designs." : "Matches the following designs:"); diff --git a/Glamourer/Gui/Tabs/DebugTab/DesignManagerPanel.cs b/Glamourer/Gui/Tabs/DebugTab/DesignManagerPanel.cs index ede3e9e..342bc41 100644 --- a/Glamourer/Gui/Tabs/DebugTab/DesignManagerPanel.cs +++ b/Glamourer/Gui/Tabs/DebugTab/DesignManagerPanel.cs @@ -3,7 +3,9 @@ using Glamourer.Designs; using ImGuiNET; using OtterGui; using OtterGui.Extensions; +using OtterGui.Filesystem; using OtterGui.Raii; +using OtterGui.Text; using Penumbra.GameData.Enums; using Penumbra.GameData.Gui.Debug; @@ -19,6 +21,7 @@ public class DesignManagerPanel(DesignManager _designManager, DesignFileSystem _ public void Draw() { + DrawButtons(); foreach (var (design, idx) in _designManager.Designs.WithIndex()) { using var t = ImRaii.TreeNode($"{design.Name}##{idx}"); @@ -26,7 +29,8 @@ public class DesignManagerPanel(DesignManager _designManager, DesignFileSystem _ continue; DrawDesign(design, _designFileSystem); - var base64 = DesignBase64Migration.CreateOldBase64(design.DesignData, design.Application.Equip, design.Application.Customize, design.Application.Meta, + var base64 = DesignBase64Migration.CreateOldBase64(design.DesignData, design.Application.Equip, design.Application.Customize, + design.Application.Meta, design.WriteProtected()); using var font = ImRaii.PushFont(UiBuilder.MonoFont); ImGuiUtil.TextWrapped(base64); @@ -35,6 +39,26 @@ public class DesignManagerPanel(DesignManager _designManager, DesignFileSystem _ } } + private void DrawButtons() + { + if (ImUtf8.Button("Generate 500 Test Designs"u8)) + for (var i = 0; i < 500; ++i) + { + var design = _designManager.CreateEmpty($"Test Designs/Test Design {i}", true); + _designManager.AddTag(design, "_DebugTest"); + } + + ImUtf8.SameLineInner(); + if (ImUtf8.Button("Remove All Test Designs"u8)) + { + var designs = _designManager.Designs.Where(d => d.Tags.Contains("_DebugTest")).ToArray(); + foreach (var design in designs) + _designManager.Delete(design); + if (_designFileSystem.Find("Test Designs", out var path) && path is DesignFileSystem.Folder { TotalChildren: 0 }) + _designFileSystem.Delete(path); + } + } + public static void DrawDesign(DesignBase design, DesignFileSystem? fileSystem) { using var table = ImRaii.Table("##equip", 8, ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit); @@ -53,7 +77,7 @@ public class DesignManagerPanel(DesignManager _designManager, DesignFileSystem _ ImGui.TableNextRow(); ImGuiUtil.DrawTableColumn("Design File System Path"); if (fileSystem != null) - ImGuiUtil.DrawTableColumn(fileSystem.FindLeaf(d, out var leaf) ? leaf.FullName() : "No Path Known"); + ImGuiUtil.DrawTableColumn(fileSystem.TryGetValue(d, out var leaf) ? leaf.FullName() : "No Path Known"); ImGui.TableNextRow(); ImGuiUtil.DrawTableColumn("Creation"); diff --git a/Glamourer/Gui/Tabs/DesignTab/MultiDesignPanel.cs b/Glamourer/Gui/Tabs/DesignTab/MultiDesignPanel.cs index ec8b465..1ecda0b 100644 --- a/Glamourer/Gui/Tabs/DesignTab/MultiDesignPanel.cs +++ b/Glamourer/Gui/Tabs/DesignTab/MultiDesignPanel.cs @@ -14,8 +14,7 @@ public class MultiDesignPanel( DesignFileSystemSelector selector, DesignManager editor, DesignColors colors, - Configuration config, - DesignComboWrapper combos) + Configuration config) { private readonly Button[] _leftButtons = []; private readonly Button[] _rightButtons = [new IncognitoButton(config)]; @@ -206,7 +205,6 @@ public class MultiDesignPanel( : $"Display all {_numDesigns} selected designs in the quick design bar. Changes {diff} designs."; if (ImUtf8.ButtonEx("Display Selected Designs in QDB"u8, tt, buttonWidth, diff == 0)) { - using var disableListener = combos.StopListening(); foreach (var design in selector.SelectedPaths.OfType()) editor.SetQuickDesign(design.Value, true); } @@ -217,7 +215,6 @@ public class MultiDesignPanel( : $"Hide all {_numDesigns} selected designs in the quick design bar. Changes {_numQuickDesignEnabled} designs."; if (ImUtf8.ButtonEx("Hide Selected Designs in QDB"u8, tt, buttonWidth, _numQuickDesignEnabled == 0)) { - using var disableListener = combos.StopListening(); foreach (var design in selector.SelectedPaths.OfType()) editor.SetQuickDesign(design.Value, false); } @@ -339,7 +336,6 @@ public class MultiDesignPanel( ImGui.SameLine(); if (ImUtf8.ButtonEx(label, tooltip, width, _addDesigns.Count == 0)) { - using var disableListener = combos.StopListening(); foreach (var design in _addDesigns) editor.ChangeColor(design, _colorCombo.CurrentSelection!); } @@ -353,7 +349,6 @@ public class MultiDesignPanel( ImGui.SameLine(); if (ImUtf8.ButtonEx(label, tooltip, width, _removeDesigns.Count == 0)) { - using var disableListener = combos.StopListening(); foreach (var (design, _) in _removeDesigns) editor.ChangeColor(design, string.Empty); } diff --git a/Glamourer/Services/ServiceManager.cs b/Glamourer/Services/ServiceManager.cs index 6c30d68..0754313 100644 --- a/Glamourer/Services/ServiceManager.cs +++ b/Glamourer/Services/ServiceManager.cs @@ -169,6 +169,5 @@ public static class StaticServiceManager .AddSingleton() .AddSingleton() .AddSingleton() - .AddSingleton() - .AddSingleton(); + .AddSingleton(); } diff --git a/OtterGui b/OtterGui index cee50c3..78528f9 160000 --- a/OtterGui +++ b/OtterGui @@ -1 +1 @@ -Subproject commit cee50c3fe97a03ca7445c81de651b609620da526 +Subproject commit 78528f93ac253db0061d9a8244cfa0cee5c2f873