From 2ebca491fc63672c83333d8c0e9cdd77c25251ac Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Sun, 11 Jun 2023 01:59:20 +0200 Subject: [PATCH] Cleanup fixed design display code a bit. --- Glamourer/GlamourerConfig.cs | 64 ++-- Glamourer/Gui/InterfaceConfig.cs | 215 ++++++++------ Glamourer/Gui/InterfaceFixedDesigns.cs | 391 +++++++++++++------------ 3 files changed, 356 insertions(+), 314 deletions(-) diff --git a/Glamourer/GlamourerConfig.cs b/Glamourer/GlamourerConfig.cs index 39b04f3..5126c3f 100644 --- a/Glamourer/GlamourerConfig.cs +++ b/Glamourer/GlamourerConfig.cs @@ -1,47 +1,47 @@ using System.Collections.Generic; using Dalamud.Configuration; -namespace Glamourer +namespace Glamourer; + +public class GlamourerConfig : IPluginConfiguration { - public class GlamourerConfig : IPluginConfiguration + public class FixedDesign { - public class FixedDesign - { - public string Name = string.Empty; - public string Path = string.Empty; - public uint JobGroups; - public bool Enabled; - } + public string Name = string.Empty; + public string Path = string.Empty; + public uint JobGroups; + public bool Enabled; + } - public int Version { get; set; } = 1; + public int Version { get; set; } = 1; - public const uint DefaultCustomizationColor = 0xFFC000C0; - public const uint DefaultStateColor = 0xFF00C0C0; - public const uint DefaultEquipmentColor = 0xFF00C000; + public const uint DefaultCustomizationColor = 0xFFC000C0; + public const uint DefaultStateColor = 0xFF00C0C0; + public const uint DefaultEquipmentColor = 0xFF00C000; - public bool FoldersFirst { get; set; } = false; - public bool ColorDesigns { get; set; } = true; - public bool ShowLocks { get; set; } = true; - public bool AttachToPenumbra { get; set; } = true; - public bool ApplyFixedDesigns { get; set; } = true; + public bool FoldersFirst { get; set; } = false; + public bool ColorDesigns { get; set; } = true; + public bool ShowLocks { get; set; } = true; + public bool AttachToPenumbra { get; set; } = true; + public bool ApplyFixedDesigns { get; set; } = true; - public uint CustomizationColor { get; set; } = DefaultCustomizationColor; - public uint StateColor { get; set; } = DefaultStateColor; - public uint EquipmentColor { get; set; } = DefaultEquipmentColor; + public uint CustomizationColor { get; set; } = DefaultCustomizationColor; + public uint StateColor { get; set; } = DefaultStateColor; + public uint EquipmentColor { get; set; } = DefaultEquipmentColor; + public ushort GroupFixedWhen { get; set; } = 2; - public List FixedDesigns { get; set; } = new(); + public List FixedDesigns { get; set; } = new(); - public void Save() - => Dalamud.PluginInterface.SavePluginConfig(this); + public void Save() + => Dalamud.PluginInterface.SavePluginConfig(this); - public static GlamourerConfig Load() - { - if (Dalamud.PluginInterface.GetPluginConfig() is GlamourerConfig config) - return config; - - config = new GlamourerConfig(); - config.Save(); + public static GlamourerConfig Load() + { + if (Dalamud.PluginInterface.GetPluginConfig() is GlamourerConfig config) return config; - } + + config = new GlamourerConfig(); + config.Save(); + return config; } } diff --git a/Glamourer/Gui/InterfaceConfig.cs b/Glamourer/Gui/InterfaceConfig.cs index 7d4c683..3e71282 100644 --- a/Glamourer/Gui/InterfaceConfig.cs +++ b/Glamourer/Gui/InterfaceConfig.cs @@ -1,112 +1,139 @@ using System; using System.Numerics; +using Dalamud.Interface; using ImGuiNET; -namespace Glamourer.Gui +namespace Glamourer.Gui; + +internal partial class Interface { - internal partial class Interface + private static void DrawConfigCheckMark(string label, string tooltip, bool value, Action setter) { - private static void DrawConfigCheckMark(string label, string tooltip, bool value, Action setter) - { - if (DrawCheckMark(label, value, setter)) - Glamourer.Config.Save(); - - ImGuiCustom.HoverTooltip(tooltip); - } - - private static void ChangeAndSave(T value, T currentValue, Action setter) where T : IEquatable - { - if (value.Equals(currentValue)) - return; - - setter(value); + if (DrawCheckMark(label, value, setter)) Glamourer.Config.Save(); + + ImGuiCustom.HoverTooltip(tooltip); + } + + private static void ChangeAndSave(T value, T currentValue, Action setter) where T : IEquatable + { + if (value.Equals(currentValue)) + return; + + setter(value); + Glamourer.Config.Save(); + } + + private static void DrawColorPicker(string name, string tooltip, uint value, uint defaultValue, Action setter) + { + const ImGuiColorEditFlags flags = ImGuiColorEditFlags.AlphaPreviewHalf | ImGuiColorEditFlags.NoInputs; + + var tmp = ImGui.ColorConvertU32ToFloat4(value); + if (ImGui.ColorEdit4($"##{name}", ref tmp, flags)) + ChangeAndSave(ImGui.ColorConvertFloat4ToU32(tmp), value, setter); + ImGui.SameLine(); + if (ImGui.Button($"Default##{name}")) + ChangeAndSave(defaultValue, value, setter); + ImGuiCustom.HoverTooltip( + $"Reset to default: #{defaultValue & 0xFF:X2}{(defaultValue >> 8) & 0xFF:X2}{(defaultValue >> 16) & 0xFF:X2}{defaultValue >> 24:X2}"); + ImGui.SameLine(); + ImGui.Text(name); + ImGuiCustom.HoverTooltip(tooltip); + } + + private void DrawRestorePenumbraButton() + { + const string buttonLabel = "Re-Register Penumbra"; + if (!Glamourer.Config.AttachToPenumbra) + { + using var raii = new ImGuiRaii().PushStyle(ImGuiStyleVar.Alpha, 0.5f); + ImGui.Button(buttonLabel); + return; } - private static void DrawColorPicker(string name, string tooltip, uint value, uint defaultValue, Action setter) - { - const ImGuiColorEditFlags flags = ImGuiColorEditFlags.AlphaPreviewHalf | ImGuiColorEditFlags.NoInputs; + if (ImGui.Button(buttonLabel)) + Glamourer.Penumbra.Reattach(true); - var tmp = ImGui.ColorConvertU32ToFloat4(value); - if (ImGui.ColorEdit4($"##{name}", ref tmp, flags)) - ChangeAndSave(ImGui.ColorConvertFloat4ToU32(tmp), value, setter); - ImGui.SameLine(); - if (ImGui.Button($"Default##{name}")) - ChangeAndSave(defaultValue, value, setter); - ImGuiCustom.HoverTooltip( - $"Reset to default: #{defaultValue & 0xFF:X2}{(defaultValue >> 8) & 0xFF:X2}{(defaultValue >> 16) & 0xFF:X2}{defaultValue >> 24:X2}"); - ImGui.SameLine(); - ImGui.Text(name); - ImGuiCustom.HoverTooltip(tooltip); - } + ImGuiCustom.HoverTooltip( + "If Penumbra did not register the functions for some reason, pressing this button might help restore functionality."); + } - private void DrawRestorePenumbraButton() - { - const string buttonLabel = "Re-Register Penumbra"; - if (!Glamourer.Config.AttachToPenumbra) + private int _currentFixedDesignGroup = -1; + + private void DrawConfigTab() + { + using var raii = new ImGuiRaii(); + if (!raii.Begin(() => ImGui.BeginTabItem("Config"), ImGui.EndTabItem)) + return; + + var cfg = Glamourer.Config; + ImGui.Dummy(Vector2.UnitY * ImGui.GetTextLineHeightWithSpacing() / 2); + + DrawConfigCheckMark("Folders First", "Sort Folders before all designs instead of lexicographically.", cfg.FoldersFirst, + v => cfg.FoldersFirst = v); + DrawConfigCheckMark("Color Designs", "Color the names of designs in the selector using the colors from below for the given cases.", + cfg.ColorDesigns, + v => cfg.ColorDesigns = v); + DrawConfigCheckMark("Show Locks", "Write-protected Designs show a lock besides their name in the selector.", cfg.ShowLocks, + v => cfg.ShowLocks = v); + DrawConfigCheckMark("Attach to Penumbra", + "Allows you to right-click items in the Changed Items tab of a mod in Penumbra to apply them to your player character.", + cfg.AttachToPenumbra, + v => { - using var raii = new ImGuiRaii().PushStyle(ImGuiStyleVar.Alpha, 0.5f); - ImGui.Button(buttonLabel); - return; + cfg.AttachToPenumbra = v; + if (v) + Glamourer.Penumbra.Reattach(true); + else + Glamourer.Penumbra.Unattach(); + }); + ImGui.SameLine(); + DrawRestorePenumbraButton(); + + DrawConfigCheckMark("Apply Fixed Designs", + "Automatically apply fixed designs to characters and redraw them when anything changes.", + cfg.ApplyFixedDesigns, + v => + { + cfg.ApplyFixedDesigns = v; + if (v) + Glamourer.PlayerWatcher.Enable(); + else + Glamourer.PlayerWatcher.Disable(); + }); + DrawFixedDesignGroup(); + + ImGui.Dummy(Vector2.UnitY * ImGui.GetTextLineHeightWithSpacing() / 2); + + DrawColorPicker("Customization Color", "The color for designs that only apply their character customization.", + cfg.CustomizationColor, GlamourerConfig.DefaultCustomizationColor, c => cfg.CustomizationColor = c); + DrawColorPicker("Equipment Color", "The color for designs that only apply some or all of their equipment slots and stains.", + cfg.EquipmentColor, GlamourerConfig.DefaultEquipmentColor, c => cfg.EquipmentColor = c); + DrawColorPicker("State Color", "The color for designs that only apply some state modification.", + cfg.StateColor, GlamourerConfig.DefaultStateColor, c => cfg.StateColor = c); + } + + private void DrawFixedDesignGroup() + { + if (_currentFixedDesignGroup == -1) + _currentFixedDesignGroup = Glamourer.Config.GroupFixedWhen; + + ImGui.SetNextItemWidth(100 * ImGuiHelpers.GlobalScale); + ImGui.DragInt("Group Fixed Designs From", ref _currentFixedDesignGroup, 0.01f, 2, ushort.MaxValue); + if (ImGui.IsItemDeactivatedAfterEdit()) + { + _currentFixedDesignGroup = Math.Clamp(_currentFixedDesignGroup, 2, ushort.MaxValue); + if (_currentFixedDesignGroup != Glamourer.Config.GroupFixedWhen) + { + Glamourer.Config.GroupFixedWhen = (ushort)_currentFixedDesignGroup; + Glamourer.Config.Save(); } - if (ImGui.Button(buttonLabel)) - Glamourer.Penumbra.Reattach(true); - - ImGuiCustom.HoverTooltip( - "If Penumbra did not register the functions for some reason, pressing this button might help restore functionality."); + _currentFixedDesignGroup = -1; } - private void DrawConfigTab() - { - using var raii = new ImGuiRaii(); - if (!raii.Begin(() => ImGui.BeginTabItem("Config"), ImGui.EndTabItem)) - return; - - var cfg = Glamourer.Config; - ImGui.Dummy(Vector2.UnitY * ImGui.GetTextLineHeightWithSpacing() / 2); - - DrawConfigCheckMark("Folders First", "Sort Folders before all designs instead of lexicographically.", cfg.FoldersFirst, - v => cfg.FoldersFirst = v); - DrawConfigCheckMark("Color Designs", "Color the names of designs in the selector using the colors from below for the given cases.", - cfg.ColorDesigns, - v => cfg.ColorDesigns = v); - DrawConfigCheckMark("Show Locks", "Write-protected Designs show a lock besides their name in the selector.", cfg.ShowLocks, - v => cfg.ShowLocks = v); - DrawConfigCheckMark("Attach to Penumbra", - "Allows you to right-click items in the Changed Items tab of a mod in Penumbra to apply them to your player character.", - cfg.AttachToPenumbra, - v => - { - cfg.AttachToPenumbra = v; - if (v) - Glamourer.Penumbra.Reattach(true); - else - Glamourer.Penumbra.Unattach(); - }); - ImGui.SameLine(); - DrawRestorePenumbraButton(); - - DrawConfigCheckMark("Apply Fixed Designs", - "Automatically apply fixed designs to characters and redraw them when anything changes.", - cfg.ApplyFixedDesigns, - v => - { - cfg.ApplyFixedDesigns = v; - if (v) - Glamourer.PlayerWatcher.Enable(); - else - Glamourer.PlayerWatcher.Disable(); - }); - - ImGui.Dummy(Vector2.UnitY * ImGui.GetTextLineHeightWithSpacing() / 2); - - DrawColorPicker("Customization Color", "The color for designs that only apply their character customization.", - cfg.CustomizationColor, GlamourerConfig.DefaultCustomizationColor, c => cfg.CustomizationColor = c); - DrawColorPicker("Equipment Color", "The color for designs that only apply some or all of their equipment slots and stains.", - cfg.EquipmentColor, GlamourerConfig.DefaultEquipmentColor, c => cfg.EquipmentColor = c); - DrawColorPicker("State Color", "The color for designs that only apply some state modification.", - cfg.StateColor, GlamourerConfig.DefaultStateColor, c => cfg.StateColor = c); - } + if (ImGui.IsItemHovered()) + ImGui.SetTooltip( + "Set how many fixed designs have to be set to a specific character before their designs are grouped with a header in the Fixed Designs tab."); } } diff --git a/Glamourer/Gui/InterfaceFixedDesigns.cs b/Glamourer/Gui/InterfaceFixedDesigns.cs index 8ca1d9e..5a6d59e 100644 --- a/Glamourer/Gui/InterfaceFixedDesigns.cs +++ b/Glamourer/Gui/InterfaceFixedDesigns.cs @@ -1,222 +1,237 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Numerics; using Dalamud.Interface; using Glamourer.Designs; using Glamourer.FileSystem; using ImGuiNET; -using Penumbra.PlayerWatch; -namespace Glamourer.Gui +namespace Glamourer.Gui; + +internal partial class Interface { - internal partial class Interface + private const string FixDragDropLabel = "##FixDragDrop"; + + private List? _fullPathCache; + private string _newFixCharacterName = string.Empty; + private string _newFixDesignPath = string.Empty; + private JobGroup? _newFixDesignGroup; + private Design? _newFixDesign; + private int _fixDragDropIdx = -1; + private readonly HashSet _closedGroups = new(); + + private static unsafe bool IsDropping() + => ImGui.AcceptDragDropPayload(FixDragDropLabel).NativePtr != null; + + private static string NormalizeIdentifier(string value) + => value.Replace(" ", "_").Replace("#", "_"); + + private void DrawFixedDesignsTab() { - private const string FixDragDropLabel = "##FixDragDrop"; + _newFixDesignGroup ??= _plugin.FixedDesigns.JobGroups[1]; - private List? _fullPathCache; - private string _newFixCharacterName = string.Empty; - private string _newFixDesignPath = string.Empty; - private JobGroup? _newFixDesignGroup; - private Design? _newFixDesign; - private int _fixDragDropIdx = -1; - private readonly HashSet _openNames = new(); - - private static unsafe bool IsDropping() - => ImGui.AcceptDragDropPayload(FixDragDropLabel).NativePtr != null; - - private static string NormalizeIdentifier(string value) - => value.Replace(" ", "_").Replace("#", "_"); - - private void DrawFixedDesignsTab() + using var raii = new ImGuiRaii(); + if (!raii.Begin(() => ImGui.BeginTabItem("Fixed Designs"), ImGui.EndTabItem)) { - _newFixDesignGroup ??= _plugin.FixedDesigns.JobGroups[1]; + _fullPathCache = null; + _newFixDesign = null; + _newFixDesignPath = string.Empty; + _newFixDesignGroup = _plugin.FixedDesigns.JobGroups[1]; + return; + } - using var raii = new ImGuiRaii(); - if (!raii.Begin(() => ImGui.BeginTabItem("Fixed Designs"), ImGui.EndTabItem)) - { - _fullPathCache = null; - _newFixDesign = null; - _newFixDesignPath = string.Empty; - _newFixDesignGroup = _plugin.FixedDesigns.JobGroups[1]; - return; - } + _fullPathCache ??= _plugin.FixedDesigns.Data.Select(d => d.Design.FullName()).ToList(); - _fullPathCache ??= _plugin.FixedDesigns.Data.Select(d => d.Design.FullName()).ToList(); + Action? endAction = null; + var buttonWidth = ImGui.GetFrameHeight(); + var groups = _plugin.FixedDesigns.Data.Select((d, i) => (d, i)).GroupBy(d => d.d.Name) + .OrderBy(g => g.Key) + .Select(g => (g.Key, g.ToList())) + .ToList(); - raii.Begin(() => ImGui.BeginTable("##FixedTable", 4), ImGui.EndTable); - var buttonWidth = 23.5f * ImGuiHelpers.GlobalScale; + raii.PushStyle(ImGuiStyleVar.FrameRounding, 0); + raii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero); + if (ImGui.Button("Collapse All Groups", new Vector2(ImGui.GetContentRegionAvail().X / 2, 0))) + _closedGroups.UnionWith(groups.Select(kvp => kvp.Key)); + ImGui.SameLine(); + if (ImGui.Button("Expand All Groups", new Vector2(ImGui.GetContentRegionAvail().X, 0))) + _closedGroups.Clear(); + raii.PopStyles(2); - ImGui.TableSetupColumn("##DeleteColumn", ImGuiTableColumnFlags.WidthFixed, 2 * buttonWidth); - ImGui.TableSetupColumn("Character", ImGuiTableColumnFlags.WidthFixed, 200 * ImGuiHelpers.GlobalScale); - ImGui.TableSetupColumn("Jobs", ImGuiTableColumnFlags.WidthFixed, 175 * ImGuiHelpers.GlobalScale); - ImGui.TableSetupColumn("Design", ImGuiTableColumnFlags.WidthStretch); - ImGui.TableHeadersRow(); + raii.Begin(() => ImGui.BeginTable("##FixedTable", 5, ImGuiTableFlags.RowBg), ImGui.EndTable); - var grouping = new Dictionary>(); - for (var i = 0; i < _fullPathCache.Count; ++i) - { - var name = _plugin.FixedDesigns.Data[i].Name; + ImGui.TableSetupColumn("##DeleteColumn", ImGuiTableColumnFlags.WidthFixed, buttonWidth); + ImGui.TableSetupColumn("##EnableColumn", ImGuiTableColumnFlags.WidthFixed, buttonWidth); + ImGui.TableSetupColumn("Character", ImGuiTableColumnFlags.WidthFixed, 200 * ImGuiHelpers.GlobalScale); + ImGui.TableSetupColumn("Jobs", ImGuiTableColumnFlags.WidthFixed, 175 * ImGuiHelpers.GlobalScale); + ImGui.TableSetupColumn("Design", ImGuiTableColumnFlags.WidthStretch); + ImGui.TableHeadersRow(); - grouping.TryAdd(name, new List()); - grouping[name].Add(i); - } - - var xPos = 0f; - - foreach (var (groupedName, indices) in grouping.OrderBy(kvp => kvp.Key)) - { - - ImGui.TableNextRow(); - ImGui.TableNextColumn(); - raii.PushStyle(ImGuiStyleVar.ItemSpacing, ImGui.GetStyle().ItemSpacing / 2); - raii.PushFont(UiBuilder.IconFont); - var isOpen = _openNames.Contains(groupedName); - var groupIcon = isOpen ? FontAwesomeIcon.CaretDown : FontAwesomeIcon.CaretRight; - if (ImGui.Button($"{groupIcon.ToIconChar()}##group_{NormalizeIdentifier(groupedName)}")) - { - if (isOpen) - { - _openNames.Remove(groupedName); - } else - { - _openNames.Add(groupedName); - } - return; - } - raii.PopStyles(); - raii.PopFonts(); - - ImGui.SameLine(); - xPos = ImGui.GetCursorPosX(); - - ImGui.TableNextColumn(); - ImGui.Text(groupedName); - - if (!_openNames.Contains(groupedName)) - { - ImGui.TableNextRow(); - continue; - } - - foreach (var i in indices) - { - var path = _fullPathCache[i]; - var name = _plugin.FixedDesigns.Data[i]; - - ImGui.TableNextRow(); - ImGui.TableNextColumn(); - raii.PushStyle(ImGuiStyleVar.ItemSpacing, ImGui.GetStyle().ItemSpacing / 2); - raii.PushFont(UiBuilder.IconFont); - if (ImGui.Button($"{FontAwesomeIcon.Trash.ToIconChar()}##{i}")) - { - _fullPathCache.RemoveAt(i); - _plugin.FixedDesigns.Remove(name); - continue; - } - - var tmp = name.Enabled; - ImGui.SameLine(); - xPos = ImGui.GetCursorPosX(); - if (ImGui.Checkbox($"##Enabled{i}", ref tmp)) - if (tmp && _plugin.FixedDesigns.EnableDesign(name) - || !tmp && _plugin.FixedDesigns.DisableDesign(name)) - { - Glamourer.Config.FixedDesigns[i].Enabled = tmp; - Glamourer.Config.Save(); - } - - raii.PopStyles(); - raii.PopFonts(); - ImGui.TableNextColumn(); - ImGui.Selectable($"{name.Name}##Fix{i}"); - if (ImGui.BeginDragDropSource()) - { - _fixDragDropIdx = i; - ImGui.SetDragDropPayload("##FixDragDrop", IntPtr.Zero, 0); - ImGui.Text($"Dragging {name.Name} ({path})..."); - ImGui.EndDragDropSource(); - } - if (ImGui.BeginDragDropTarget()) - { - if (IsDropping() && _fixDragDropIdx >= 0) - { - var d = _plugin.FixedDesigns.Data[_fixDragDropIdx]; - _plugin.FixedDesigns.Move(d, i); - var p = _fullPathCache[_fixDragDropIdx]; - _fullPathCache.RemoveAt(_fixDragDropIdx); - _fullPathCache.Insert(i, p); - _fixDragDropIdx = -1; - } - ImGui.EndDragDropTarget(); - } - - ImGui.TableNextColumn(); - ImGui.Text(_plugin.FixedDesigns.Data[i].Jobs.Name); - ImGui.TableNextColumn(); - ImGui.Text(path); - } - - ImGui.TableNextRow(); - } - - ImGui.TableNextRow(); + void DrawDesign(FixedDesigns.FixedDesign design, int idx) + { + ImGui.PushID(idx); + var path = _fullPathCache[idx]; ImGui.TableNextColumn(); raii.PushFont(UiBuilder.IconFont); - - ImGui.SetCursorPosX(xPos); - if (_newFixDesign == null || _newFixCharacterName == string.Empty) - { - raii.PushStyle(ImGuiStyleVar.Alpha, 0.5f); - ImGui.Button($"{FontAwesomeIcon.Plus.ToIconChar()}##NewFix"); - raii.PopStyles(); - } - else if (ImGui.Button($"{FontAwesomeIcon.Plus.ToIconChar()}##NewFix")) - { - _fullPathCache.Add(_newFixDesignPath); - _plugin.FixedDesigns.Add(_newFixCharacterName, _newFixDesign, _newFixDesignGroup.Value, false); - _newFixCharacterName = string.Empty; - _newFixDesignPath = string.Empty; - _newFixDesign = null; - _newFixDesignGroup = _plugin.FixedDesigns.JobGroups[1]; - } - - if (_newFixCharacterName == string.Empty) - _newFixCharacterName = Dalamud.ClientState.LocalPlayer?.Name.ToString() ?? string.Empty; - - raii.PopFonts(); - ImGui.TableNextColumn(); - ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale); - ImGui.InputTextWithHint("##NewFix", "Enter new Character", ref _newFixCharacterName, 64); - ImGui.TableNextColumn(); - ImGui.SetNextItemWidth(-1); - if (raii.Begin(() => ImGui.BeginCombo("##NewFixDesignGroup", _newFixDesignGroup.Value.Name), ImGui.EndCombo)) - { - foreach (var (id, group) in _plugin.FixedDesigns.JobGroups) + if (ImGui.Button(FontAwesomeIcon.Trash.ToIconString())) + endAction = () => { - ImGui.SetNextItemWidth(-1); - if (ImGui.Selectable($"{group.Name}##NewFixDesignGroup", group.Name == _newFixDesignGroup.Value.Name)) - _newFixDesignGroup = group; + _fullPathCache.RemoveAt(idx); + _plugin.FixedDesigns.Remove(design); + }; + raii.PopFonts(); + + var tmp = design.Enabled; + ImGui.TableNextColumn(); + if (ImGui.Checkbox("##Enabled", ref tmp)) + if (tmp && _plugin.FixedDesigns.EnableDesign(design) + || !tmp && _plugin.FixedDesigns.DisableDesign(design)) + { + Glamourer.Config.FixedDesigns[idx].Enabled = tmp; + Glamourer.Config.Save(); } - raii.End(); + + ImGui.TableNextColumn(); + ImGui.Selectable($"{design.Name}##Fix"); + if (ImGui.BeginDragDropSource()) + { + _fixDragDropIdx = idx; + ImGui.SetDragDropPayload("##FixDragDrop", IntPtr.Zero, 0); + ImGui.Text($"Dragging {design.Name} ({path})..."); + ImGui.EndDragDropSource(); + } + + if (ImGui.BeginDragDropTarget()) + { + if (IsDropping() && _fixDragDropIdx >= 0) + { + var i = _fixDragDropIdx; + var d = _plugin.FixedDesigns.Data[_fixDragDropIdx]; + var p = _fullPathCache[_fixDragDropIdx]; + endAction = () => + { + _plugin.FixedDesigns.Move(d, idx); + _fullPathCache.RemoveAt(i); + _fullPathCache.Insert(idx, p); + _fixDragDropIdx = -1; + }; + } + + ImGui.EndDragDropTarget(); } ImGui.TableNextColumn(); - ImGui.SetNextItemWidth(-1); - if (!raii.Begin(() => ImGui.BeginCombo("##NewFixPath", _newFixDesignPath), ImGui.EndCombo)) - return; + ImGui.TextUnformatted(_plugin.FixedDesigns.Data[idx].Jobs.Name); + ImGui.TableNextColumn(); + ImGui.TextUnformatted(path); + ImGui.PopID(); + } - foreach (var design in _plugin.Designs.FileSystem.Root.AllLeaves(SortMode.Lexicographical).Cast()) + foreach (var (playerName, designs) in groups) + { + if (designs.Count >= Glamourer.Config.GroupFixedWhen) { - var fullName = design.FullName(); - ImGui.SetNextItemWidth(-1); - if (!ImGui.Selectable($"{fullName}##NewFixDesign", fullName == _newFixDesignPath)) - continue; + var isOpen = !_closedGroups.Contains(playerName); + var color = isOpen ? 0x40005000u : 0x40000050u; + ImGui.TableNextColumn(); + ImGui.TableSetBgColor(ImGuiTableBgTarget.CellBg, color); + ImGui.TableNextColumn(); + ImGui.TableSetBgColor(ImGuiTableBgTarget.CellBg, color); - _newFixDesignPath = fullName; - _newFixDesign = design; + var groupIcon = isOpen ? FontAwesomeIcon.CaretDown : FontAwesomeIcon.CaretRight; + ImGui.PushID(playerName); + raii.PushFont(UiBuilder.IconFont); + if (ImGui.Button(groupIcon.ToIconString(), new Vector2(buttonWidth))) + { + if (isOpen) + _closedGroups.Add(playerName); + else + _closedGroups.Remove(playerName); + isOpen = !isOpen; + } + + raii.PopFonts(); + + ImGui.TableNextColumn(); + ImGui.TableSetBgColor(ImGuiTableBgTarget.CellBg, color); + ImGui.TextUnformatted(playerName); + ImGui.TableNextColumn(); + ImGui.TableSetBgColor(ImGuiTableBgTarget.CellBg, color); + ImGui.TextUnformatted($"{designs.Count} Designs"); + ImGui.TableNextColumn(); + ImGui.TableSetBgColor(ImGuiTableBgTarget.CellBg, color); + if (isOpen) + foreach (var (d, i) in designs) + DrawDesign(d, i); + ImGui.PopID(); } + else + { + foreach (var (d, i) in designs) + DrawDesign(d, i); + } + } + + endAction?.Invoke(); + + ImGui.TableNextColumn(); + ImGui.TableNextColumn(); + raii.PushFont(UiBuilder.IconFont); + + if (_newFixDesign == null || _newFixCharacterName == string.Empty) + { + raii.PushStyle(ImGuiStyleVar.Alpha, 0.5f); + ImGui.Button($"{FontAwesomeIcon.Plus.ToIconChar()}##NewFix"); + raii.PopStyles(); + } + else if (ImGui.Button($"{FontAwesomeIcon.Plus.ToIconChar()}##NewFix")) + { + _fullPathCache.Add(_newFixDesignPath); + _plugin.FixedDesigns.Add(_newFixCharacterName, _newFixDesign, _newFixDesignGroup.Value, false); + _newFixCharacterName = string.Empty; + _newFixDesignPath = string.Empty; + _newFixDesign = null; + _newFixDesignGroup = _plugin.FixedDesigns.JobGroups[1]; + } + + if (_newFixCharacterName == string.Empty) + _newFixCharacterName = Dalamud.ClientState.LocalPlayer?.Name.ToString() ?? string.Empty; + + raii.PopFonts(); + ImGui.TableNextColumn(); + ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale); + ImGui.InputTextWithHint("##NewFix", "Enter new Character (current: {", ref _newFixCharacterName, 64); + ImGui.TableNextColumn(); + ImGui.SetNextItemWidth(-1); + if (raii.Begin(() => ImGui.BeginCombo("##NewFixDesignGroup", _newFixDesignGroup.Value.Name), ImGui.EndCombo)) + { + foreach (var (id, group) in _plugin.FixedDesigns.JobGroups) + { + ImGui.SetNextItemWidth(-1); + if (ImGui.Selectable($"{group.Name}##NewFixDesignGroup", group.Name == _newFixDesignGroup.Value.Name)) + _newFixDesignGroup = group; + } + + raii.End(); + } + + ImGui.TableNextColumn(); + ImGui.SetNextItemWidth(-1); + if (!raii.Begin(() => ImGui.BeginCombo("##NewFixPath", _newFixDesignPath), ImGui.EndCombo)) + return; + + foreach (var design in _plugin.Designs.FileSystem.Root.AllLeaves(SortMode.Lexicographical).Cast()) + { + var fullName = design.FullName(); + ImGui.SetNextItemWidth(-1); + if (!ImGui.Selectable($"{fullName}##NewFixDesign", fullName == _newFixDesignPath)) + continue; + + _newFixDesignPath = fullName; + _newFixDesign = design; } } }