Add support for custom colors for design display.

This commit is contained in:
Ottermandias 2023-11-16 19:43:04 +01:00
parent ec7a53bee2
commit 2b30a88bf4
13 changed files with 438 additions and 39 deletions

View file

@ -3,6 +3,8 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using Dalamud.Interface.Internal.Notifications;
using Glamourer.Customization;
using Glamourer.Gui;
using Glamourer.Interop.Penumbra;
using Glamourer.Services;
using Newtonsoft.Json;
@ -14,6 +16,7 @@ namespace Glamourer.Designs;
public sealed class Design : DesignBase, ISavable
{
#region Data
internal Design(CustomizationService customize, ItemManager items)
: base(customize, items)
{ }
@ -40,6 +43,7 @@ public sealed class Design : DesignBase, ISavable
public string Description { get; internal set; } = string.Empty;
public string[] Tags { get; internal set; } = Array.Empty<string>();
public int Index { get; internal set; }
public string Color { get; internal set; } = string.Empty;
public SortedList<Mod, ModSettings> AssociatedMods { get; private set; } = new();
public string Incognito
@ -59,6 +63,7 @@ public sealed class Design : DesignBase, ISavable
["LastEdit"] = LastEdit,
["Name"] = Name.Text,
["Description"] = Description,
["Color"] = Color,
["Tags"] = JArray.FromObject(Tags),
["WriteProtected"] = WriteProtected(),
["Equipment"] = SerializeEquipment(),
@ -131,6 +136,7 @@ public sealed class Design : DesignBase, ISavable
LoadCustomize(customizations, json["Customize"], design, design.Name, true, false);
LoadEquip(items, json["Equipment"], design, design.Name, true);
LoadMods(json["Mods"], design);
design.Color = json["Color"]?.ToObject<string>() ?? string.Empty;
return design;
}

View file

@ -0,0 +1,303 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Numerics;
using Dalamud.Interface;
using Dalamud.Interface.Internal.Notifications;
using Dalamud.Interface.Utility.Raii;
using Glamourer.Gui;
using Glamourer.Services;
using ImGuiNET;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OtterGui;
using OtterGui.Classes;
namespace Glamourer.Designs;
public class DesignColorUi
{
private readonly DesignColors _colors;
private readonly DesignManager _designs;
private readonly Configuration _config;
private string _newName = string.Empty;
public DesignColorUi(DesignColors colors, DesignManager designs, Configuration config)
{
_colors = colors;
_designs = designs;
_config = config;
}
public void Draw()
{
using var table = ImRaii.Table("designColors", 3, ImGuiTableFlags.RowBg);
if (!table)
return;
var changeString = string.Empty;
uint? changeValue = null;
var buttonSize = new Vector2(ImGui.GetFrameHeight());
ImGui.TableSetupColumn("##Delete", ImGuiTableColumnFlags.WidthFixed, buttonSize.X);
ImGui.TableSetupColumn("##Select", ImGuiTableColumnFlags.WidthFixed, buttonSize.X);
ImGui.TableSetupColumn("Color Name", ImGuiTableColumnFlags.WidthStretch);
ImGui.TableHeadersRow();
ImGui.TableNextColumn();
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Recycle.ToIconString(), buttonSize,
"Revert the color used for missing design colors to its default.", _colors.MissingColor == DesignColors.MissingColorDefault,
true))
{
changeString = DesignColors.MissingColorName;
changeValue = DesignColors.MissingColorDefault;
}
ImGui.TableNextColumn();
if (DrawColorButton(DesignColors.MissingColorName, _colors.MissingColor, out var newColor))
{
changeString = DesignColors.MissingColorName;
changeValue = newColor;
}
ImGui.TableNextColumn();
ImGui.SetCursorPosX(ImGui.GetCursorPosX() + ImGui.GetStyle().FramePadding.X);
ImGui.TextUnformatted(DesignColors.MissingColorName);
ImGuiUtil.HoverTooltip("This color is used when the color specified in a design is not available.");
var disabled = !_config.DeleteDesignModifier.IsActive();
var tt = "Delete this color. This does not remove it from designs using it.";
if (disabled)
tt += $"\nHold {_config.DeleteDesignModifier} to delete.";
foreach (var ((name, color), idx) in _colors.WithIndex())
{
using var id = ImRaii.PushId(idx);
ImGui.TableNextColumn();
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Trash.ToIconString(), buttonSize, tt, disabled, true))
{
changeString = name;
changeValue = null;
}
ImGui.TableNextColumn();
if (DrawColorButton(name, color, out newColor))
{
changeString = name;
changeValue = newColor;
}
ImGui.TableNextColumn();
ImGui.SetCursorPosX(ImGui.GetCursorPosX() + ImGui.GetStyle().FramePadding.X);
ImGui.TextUnformatted(name);
}
ImGui.TableNextColumn();
(tt, disabled) = _newName.Length == 0
? ("Specify a name for a new color first.", true)
: _newName is DesignColors.MissingColorName or DesignColors.AutomaticName
? ($"You can not use the name {DesignColors.MissingColorName} or {DesignColors.AutomaticName}, choose a different one.", true)
: _colors.ContainsKey(_newName)
? ($"The color {_newName} already exists, please choose a different name.", true)
: ($"Add a new color {_newName} to your list.", false);
if (ImGuiUtil.DrawDisabledButton(FontAwesomeIcon.Plus.ToIconString(), buttonSize, tt, disabled, true))
{
changeString = _newName;
changeValue = 0xFFFFFFFF;
}
ImGui.TableNextColumn();
ImGui.TableNextColumn();
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X);
if (ImGui.InputTextWithHint("##newDesignColor", "New Color Name...", ref _newName, 64, ImGuiInputTextFlags.EnterReturnsTrue))
{
changeString = _newName;
changeValue = 0xFFFFFFFF;
}
if (changeString.Length > 0)
{
if (!changeValue.HasValue)
_colors.DeleteColor(changeString);
else
_colors.SetColor(changeString, changeValue.Value);
}
}
public static bool DrawColorButton(string tooltip, uint color, out uint newColor)
{
var vec = ImGui.ColorConvertU32ToFloat4(color);
if (!ImGui.ColorEdit4(tooltip, ref vec, ImGuiColorEditFlags.AlphaPreviewHalf | ImGuiColorEditFlags.NoInputs))
{
ImGuiUtil.HoverTooltip(tooltip);
newColor = color;
return false;
}
ImGuiUtil.HoverTooltip(tooltip);
newColor = ImGui.ColorConvertFloat4ToU32(vec);
return newColor != color;
}
}
public class DesignColors : ISavable, IReadOnlyDictionary<string, uint>
{
public const string AutomaticName = "Automatic";
public const string MissingColorName = "Missing Color";
public const uint MissingColorDefault = 0xFF0000D0;
private readonly SaveService _saveService;
private readonly Dictionary<string, uint> _colors = new();
public uint MissingColor { get; private set; } = MissingColorDefault;
public event Action? ColorChanged;
public DesignColors(SaveService saveService)
{
_saveService = saveService;
Load();
}
public uint GetColor(Design design)
{
if (design.Color.Length == 0)
return AutoColor(design);
return TryGetValue(design.Color, out var color) ? color : MissingColor;
}
public void SetColor(string key, uint newColor)
{
if (key.Length == 0)
return;
if (key is MissingColorName && MissingColor != newColor)
{
MissingColor = newColor;
SaveAndInvoke();
return;
}
if (_colors.TryAdd(key, newColor))
{
SaveAndInvoke();
return;
}
_colors.TryGetValue(key, out var color);
_colors[key] = newColor;
if (color != newColor)
SaveAndInvoke();
}
private void SaveAndInvoke()
{
ColorChanged?.Invoke();
_saveService.DelaySave(this, TimeSpan.FromSeconds(2));
}
public void DeleteColor(string key)
{
if (_colors.Remove(key))
SaveAndInvoke();
}
public string ToFilename(FilenameService fileNames)
=> fileNames.DesignColorFile;
public void Save(StreamWriter writer)
{
var jObj = new JObject
{
["Version"] = 1,
["MissingColor"] = MissingColor,
["Definitions"] = JToken.FromObject(_colors),
};
writer.Write(jObj.ToString(Formatting.Indented));
}
private void Load()
{
_colors.Clear();
var file = _saveService.FileNames.DesignColorFile;
if (!File.Exists(file))
return;
try
{
var text = File.ReadAllText(file);
var jObj = JObject.Parse(text);
var version = jObj["Version"]?.ToObject<int>() ?? 0;
switch (version)
{
case 1:
{
var dict = jObj["Definitions"]?.ToObject<Dictionary<string, uint>>() ?? new Dictionary<string, uint>();
_colors.EnsureCapacity(dict.Count);
foreach (var kvp in dict)
_colors.Add(kvp.Key, kvp.Value);
MissingColor = jObj["MissingColor"]?.ToObject<uint>() ?? MissingColorDefault;
break;
}
default: throw new Exception($"Unknown Version {version}");
}
}
catch (Exception ex)
{
Glamourer.Messager.NotificationMessage(ex, "Could not read design color file.", NotificationType.Error);
}
}
public IEnumerator<KeyValuePair<string, uint>> GetEnumerator()
=> _colors.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator()
=> GetEnumerator();
public int Count
=> _colors.Count;
public bool ContainsKey(string key)
=> _colors.ContainsKey(key);
public bool TryGetValue(string key, out uint value)
{
if (_colors.TryGetValue(key, out value))
{
if (value == 0)
value = ImGui.GetColorU32(ImGuiCol.Text);
return true;
}
return false;
}
public static uint AutoColor(DesignBase design)
{
var customize = design.ApplyCustomize == 0;
var equip = design.ApplyEquip == 0;
return (customize, equip) switch
{
(true, true) => ColorId.StateDesign.Value(),
(true, false) => ColorId.EquipmentDesign.Value(),
(false, true) => ColorId.CustomizationDesign.Value(),
(false, false) => ColorId.NormalDesign.Value(),
};
}
public uint this[string key]
=> _colors[key];
public IEnumerable<string> Keys
=> _colors.Keys;
public IEnumerable<uint> Values
=> _colors.Values;
}

View file

@ -1,5 +1,4 @@
using System;
using System.Buffers.Text;
using System.Runtime.CompilerServices;
using Glamourer.Customization;
using Glamourer.Services;

View file

@ -6,7 +6,6 @@ using System.Linq;
using System.Text.RegularExpressions;
using Dalamud.Interface.Internal.Notifications;
using Glamourer.Events;
using Glamourer.Interop.Penumbra;
using Glamourer.Services;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

View file

@ -189,6 +189,19 @@ public class DesignManager
_event.Invoke(DesignChanged.Type.ChangedDescription, design, oldDescription);
}
public void ChangeColor(Design design, string newColor)
{
var oldColor = design.Color;
if (oldColor == newColor)
return;
design.Color = newColor;
design.LastEdit = DateTimeOffset.UtcNow;
_saveService.QueueSave(design);
Glamourer.Log.Debug($"Changed color of design {design.Identifier}.");
_event.Invoke(DesignChanged.Type.ChangedColor, design, oldColor);
}
/// <summary> Add a new tag to a design. The tags remain sorted. </summary>
public void AddTag(Design design, string tag)
{

View file

@ -32,6 +32,9 @@ public sealed class DesignChanged : EventWrapper<Action<DesignChanged.Type, Desi
/// <summary> An existing design had its description changed. Data is the prior description [string]. </summary>
ChangedDescription,
/// <summary> An existing design had its associated color changed. Data is the prior color [string]. </summary>
ChangedColor,
/// <summary> An existing design had a new tag added. Data is the new tag and the index it was added at [(string, int)]. </summary>
AddedTag,

View file

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using Dalamud.Interface.Utility;
using Dalamud.Interface.Utility.Raii;
using Glamourer.Automation;
using Glamourer.Customization;
using Glamourer.Designs;
@ -19,17 +20,19 @@ public abstract class DesignComboBase : FilterComboCache<Tuple<Design, string>>,
{
private readonly Configuration _config;
private readonly DesignChanged _designChanged;
private readonly DesignColors _designColors;
protected readonly TabSelected TabSelected;
protected float InnerWidth;
private Design? _currentDesign;
protected DesignComboBase(Func<IReadOnlyList<Tuple<Design, string>>> generator, Logger log, DesignChanged designChanged,
TabSelected tabSelected, Configuration config)
TabSelected tabSelected, Configuration config, DesignColors designColors)
: base(generator, log)
{
_designChanged = designChanged;
TabSelected = tabSelected;
_config = config;
_designColors = designColors;
_designChanged.Subscribe(OnDesignChange, DesignChanged.Priority.DesignCombo);
}
@ -41,8 +44,13 @@ public abstract class DesignComboBase : FilterComboCache<Tuple<Design, string>>,
protected override bool DrawSelectable(int globalIdx, bool selected)
{
var ret = base.DrawSelectable(globalIdx, selected);
var (design, path) = Items[globalIdx];
bool ret;
using (var color = ImRaii.PushColor(ImGuiCol.Text, _designColors.GetColor(design)))
{
ret = base.DrawSelectable(globalIdx, selected);
}
if (path.Length > 0 && design.Name != path)
{
var start = ImGui.GetItemRectMin();
@ -128,11 +136,11 @@ public sealed class DesignCombo : DesignComboBase
private readonly DesignManager _manager;
public DesignCombo(DesignManager designs, DesignFileSystem fileSystem, Logger log, DesignChanged designChanged, TabSelected tabSelected,
Configuration config)
Configuration config, DesignColors designColors)
: base(() => designs.Designs
.Select(d => new Tuple<Design, string>(d, fileSystem.FindLeaf(d, out var l) ? l.FullName() : string.Empty))
.OrderBy(d => d.Item2)
.ToList(), log, designChanged, tabSelected, config)
.ToList(), log, designChanged, tabSelected, config, designColors)
{
_manager = designs;
if (designs.Designs.Count == 0)
@ -170,19 +178,19 @@ public sealed class RevertDesignCombo : DesignComboBase, IDisposable
public readonly Design RevertDesign;
private readonly AutoDesignManager _autoDesignManager;
public RevertDesignCombo(DesignManager designs, DesignFileSystem fileSystem, TabSelected tabSelected,
public RevertDesignCombo(DesignManager designs, DesignFileSystem fileSystem, TabSelected tabSelected, DesignColors designColors,
ItemManager items, CustomizationService customize, Logger log, DesignChanged designChanged, AutoDesignManager autoDesignManager,
Configuration config)
: this(designs, fileSystem, tabSelected, CreateRevertDesign(customize, items), log, designChanged, autoDesignManager, config)
: this(designs, fileSystem, tabSelected, designColors, CreateRevertDesign(customize, items), log, designChanged, autoDesignManager, config)
{ }
private RevertDesignCombo(DesignManager designs, DesignFileSystem fileSystem, TabSelected tabSelected,
private RevertDesignCombo(DesignManager designs, DesignFileSystem fileSystem, TabSelected tabSelected, DesignColors designColors,
Design revertDesign, Logger log, DesignChanged designChanged, AutoDesignManager autoDesignManager, Configuration config)
: base(() => designs.Designs
.Select(d => new Tuple<Design, string>(d, fileSystem.FindLeaf(d, out var l) ? l.FullName() : string.Empty))
.OrderBy(d => d.Item2)
.Prepend(new Tuple<Design, string>(revertDesign, string.Empty))
.ToList(), log, designChanged, tabSelected, config)
.ToList(), log, designChanged, tabSelected, config, designColors)
{
RevertDesign = revertDesign;
_autoDesignManager = autoDesignManager;

View file

@ -1,5 +1,6 @@
using System;
using System.Diagnostics;
using System.Linq;
using System.Numerics;
using Dalamud.Interface;
using Dalamud.Interface.Internal.Notifications;
@ -13,12 +14,35 @@ using OtterGui.Widgets;
namespace Glamourer.Gui.Tabs.DesignTab;
public sealed class DesignColorCombo : FilterComboCache<string>
{
private readonly DesignColors _designColors;
public DesignColorCombo(DesignColors designColors)
: base(designColors.Keys.OrderBy(k => k).Prepend(DesignColors.AutomaticName), Glamourer.Log)
=> _designColors = designColors;
protected override bool DrawSelectable(int globalIdx, bool selected)
{
var key = Items[globalIdx];
var color = globalIdx == 0 ? 0 : _designColors[key];
using var c = ImRaii.PushColor(ImGuiCol.Text, color, color != 0);
var ret = base.DrawSelectable(globalIdx, selected);
if (globalIdx == 0)
ImGuiUtil.HoverTooltip(
"The automatic color uses the colors dependent on the design state, as defined in the regular color definitions.");
return ret;
}
}
public class DesignDetailTab
{
private readonly SaveService _saveService;
private readonly DesignFileSystemSelector _selector;
private readonly DesignFileSystem _fileSystem;
private readonly DesignManager _manager;
private readonly DesignColors _colors;
private readonly DesignColorCombo _colorCombo;
private readonly TagButtons _tagButtons = new();
private string? _newPath;
@ -29,12 +53,15 @@ public class DesignDetailTab
private Design? _changeDesign;
private DesignFileSystem.Leaf? _changeLeaf;
public DesignDetailTab(SaveService saveService, DesignFileSystemSelector selector, DesignManager manager, DesignFileSystem fileSystem)
public DesignDetailTab(SaveService saveService, DesignFileSystemSelector selector, DesignManager manager, DesignFileSystem fileSystem,
DesignColors colors)
{
_saveService = saveService;
_selector = selector;
_manager = manager;
_fileSystem = fileSystem;
_colors = colors;
_colorCombo = new DesignColorCombo(_colors);
}
public void Draw()
@ -89,7 +116,8 @@ public class DesignDetailTab
}
catch (Exception ex)
{
Glamourer.Messager.NotificationMessage(ex, $"Could not open file {fileName}.", $"Could not open file {fileName}", NotificationType.Warning);
Glamourer.Messager.NotificationMessage(ex, $"Could not open file {fileName}.", $"Could not open file {fileName}",
NotificationType.Warning);
}
}
@ -117,6 +145,34 @@ public class DesignDetailTab
Glamourer.Messager.NotificationMessage(ex, ex.Message, "Could not rename or move design", NotificationType.Error);
}
ImGuiUtil.DrawFrameColumn("Color");
var colorName = _selector.Selected!.Color.Length == 0 ? DesignColors.AutomaticName : _selector.Selected!.Color;
ImGui.TableNextColumn();
if (_colorCombo.Draw("##colorCombo", colorName, "Associate a color with this design. Right-Click to revert to automatic coloring.",
width.X - ImGui.GetStyle().ItemSpacing.X - ImGui.GetFrameHeight(), ImGui.GetTextLineHeight())
&& _colorCombo.CurrentSelection != null)
{
colorName = _colorCombo.CurrentSelection is DesignColors.AutomaticName ? string.Empty : _colorCombo.CurrentSelection;
_manager.ChangeColor(_selector.Selected!, colorName);
}
if (ImGui.IsItemClicked(ImGuiMouseButton.Right))
_manager.ChangeColor(_selector.Selected!, string.Empty);
if (_colors.TryGetValue(_selector.Selected!.Color, out var currentColor))
{
ImGui.SameLine();
if (DesignColorUi.DrawColorButton($"Color associated with {_selector.Selected!.Color}", currentColor, out var newColor))
_colors.SetColor(_selector.Selected!.Color, newColor);
}
else if (_selector.Selected!.Color.Length != 0)
{
ImGui.SameLine();
var size = new Vector2(ImGui.GetFrameHeight());
using var font = ImRaii.PushFont(UiBuilder.IconFont);
ImGuiUtil.DrawTextButton(FontAwesomeIcon.ExclamationCircle.ToIconString(), size, 0, _colors.MissingColor);
ImGuiUtil.HoverTooltip("The color associated with this design does not exist.");
}
ImGuiUtil.DrawFrameColumn("Creation Date");
ImGui.TableNextColumn();
ImGuiUtil.DrawTextButton(_selector.Selected!.CreationDate.LocalDateTime.ToString("F"), width, 0);

View file

@ -25,6 +25,7 @@ public sealed class DesignFileSystemSelector : FileSystemSelector<Design, Design
private readonly DesignConverter _converter;
private readonly TabSelected _selectionEvent;
private readonly CustomizationService _customizationService;
private readonly DesignColors _designColors;
private string? _clipboardText;
private Design? _cloneDesign;
@ -43,13 +44,12 @@ public sealed class DesignFileSystemSelector : FileSystemSelector<Design, Design
public new DesignFileSystem.Leaf? SelectedLeaf
=> base.SelectedLeaf;
public struct DesignState
{
public ColorId Color;
}
public record struct DesignState(uint Color)
{ }
public DesignFileSystemSelector(DesignManager designManager, DesignFileSystem fileSystem, IKeyState keyState, DesignChanged @event,
Configuration config, DesignConverter converter, TabSelected selectionEvent, Logger log, CustomizationService customizationService)
Configuration config, DesignConverter converter, TabSelected selectionEvent, Logger log, CustomizationService customizationService,
DesignColors designColors)
: base(fileSystem, keyState, log, allowMultipleSelection: true)
{
_designManager = designManager;
@ -58,8 +58,10 @@ public sealed class DesignFileSystemSelector : FileSystemSelector<Design, Design
_converter = converter;
_selectionEvent = selectionEvent;
_customizationService = customizationService;
_designColors = designColors;
_event.Subscribe(OnDesignChange, DesignChanged.Priority.DesignFileSystemSelector);
_selectionEvent.Subscribe(OnTabSelected, TabSelected.Priority.DesignSelector);
_designColors.ColorChanged += SetFilterDirty;
AddButton(NewDesignButton, 0);
AddButton(ImportDesignButton, 10);
@ -77,7 +79,7 @@ public sealed class DesignFileSystemSelector : FileSystemSelector<Design, Design
{
var flag = selected ? ImGuiTreeNodeFlags.Selected | LeafFlags : LeafFlags;
var name = IncognitoMode ? leaf.Value.Incognito : leaf.Value.Name.Text;
using var color = ImRaii.PushColor(ImGuiCol.Text, state.Color.Value());
using var color = ImRaii.PushColor(ImGuiCol.Text, state.Color);
using var _ = ImRaii.TreeNode(name, flag);
}
@ -86,6 +88,7 @@ public sealed class DesignFileSystemSelector : FileSystemSelector<Design, Design
base.Dispose();
_event.Unsubscribe(OnDesignChange);
_selectionEvent.Unsubscribe(OnTabSelected);
_designColors.ColorChanged -= SetFilterDirty;
}
public override ISortMode<Design> SortMode
@ -121,7 +124,7 @@ public sealed class DesignFileSystemSelector : FileSystemSelector<Design, Design
case DesignChanged.Type.ApplyStain:
case DesignChanged.Type.Customize:
case DesignChanged.Type.Equip:
case DesignChanged.Type.Weapon:
case DesignChanged.Type.ChangedColor:
SetFilterDirty();
break;
}
@ -277,17 +280,7 @@ public sealed class DesignFileSystemSelector : FileSystemSelector<Design, Design
/// <summary> Combined wrapper for handling all filters and setting state. </summary>
private bool ApplyFiltersAndState(DesignFileSystem.Leaf leaf, out DesignState state)
{
var applyEquip = leaf.Value.ApplyEquip != 0;
var applyCustomize = leaf.Value.ApplyCustomize != 0;
state.Color = (applyEquip, applyCustomize) switch
{
(false, false) => ColorId.StateDesign,
(false, true) => ColorId.CustomizationDesign,
(true, false) => ColorId.EquipmentDesign,
(true, true) => ColorId.NormalDesign,
};
state = new DesignState(_designColors.GetColor(leaf.Value));
return ApplyStringFilters(leaf, leaf.Value);
}

View file

@ -7,6 +7,7 @@ using Dalamud.Interface;
using Dalamud.Interface.Components;
using Dalamud.Interface.Utility;
using Dalamud.Plugin.Services;
using Glamourer.Designs;
using Glamourer.Gui.Tabs.DesignTab;
using Glamourer.Interop;
using Glamourer.Interop.Penumbra;
@ -30,9 +31,11 @@ public class SettingsTab : ITab
private readonly UiBuilder _uiBuilder;
private readonly GlamourerChangelog _changelog;
private readonly FunModule _funModule;
private readonly DesignColorUi _designColorUi;
public SettingsTab(Configuration config, DesignFileSystemSelector selector, CodeService codeService, PenumbraAutoRedraw autoRedraw,
ContextMenuService contextMenuService, UiBuilder uiBuilder, GlamourerChangelog changelog, FunModule funModule, IKeyState keys)
ContextMenuService contextMenuService, UiBuilder uiBuilder, GlamourerChangelog changelog, FunModule funModule, IKeyState keys,
DesignColorUi designColorUi)
{
_config = config;
_selector = selector;
@ -42,6 +45,7 @@ public class SettingsTab : ITab
_uiBuilder = uiBuilder;
_changelog = changelog;
_funModule = funModule;
_designColorUi = designColorUi;
_validKeys = keys.GetValidVirtualKeys().Prepend(VirtualKey.NO_KEY).ToArray();
}
@ -177,6 +181,15 @@ public class SettingsTab : ITab
if (!ImGui.CollapsingHeader("Colors"))
return;
using (var tree = ImRaii.TreeNode("Custom Design Colors"))
{
if (tree)
_designColorUi.Draw();
}
using (var tree = ImRaii.TreeNode("Color Settings"))
{
if (tree)
foreach (var color in Enum.GetValues<ColorId>())
{
var (defaultColor, name, description) = color.Data();
@ -184,6 +197,7 @@ public class SettingsTab : ITab
if (Widget.ColorPicker(name, description, currentColor, c => _config.Colors[color] = c, defaultColor))
_config.Save();
}
}
ImGui.NewLine();
}

View file

@ -35,6 +35,7 @@ public class BackupService
new(fileNames.UnlockFileCustomize),
new(fileNames.UnlockFileItems),
new(fileNames.FavoriteFile),
new(fileNames.DesignColorFile),
};
list.AddRange(fileNames.Designs());

View file

@ -16,6 +16,7 @@ public class FilenameService
public readonly string UnlockFileCustomize;
public readonly string UnlockFileItems;
public readonly string FavoriteFile;
public readonly string DesignColorFile;
public FilenameService(DalamudPluginInterface pi)
{
@ -28,6 +29,7 @@ public class FilenameService
UnlockFileItems = Path.Combine(ConfigDirectory, "unlocks_items.json");
DesignDirectory = Path.Combine(ConfigDirectory, "designs");
FavoriteFile = Path.Combine(ConfigDirectory, "favorites.json");
DesignColorFile = Path.Combine(ConfigDirectory, "design_colors.json");
}

View file

@ -106,7 +106,8 @@ public static class ServiceManager
.AddSingleton<AutoDesignManager>()
.AddSingleton<AutoDesignApplier>()
.AddSingleton<FixedDesignMigrator>()
.AddSingleton<DesignConverter>();
.AddSingleton<DesignConverter>()
.AddSingleton<DesignColors>();
private static IServiceCollection AddState(this IServiceCollection services)
=> services.AddSingleton<StateManager>()
@ -143,7 +144,8 @@ public static class ServiceManager
.AddSingleton<SetPanel>()
.AddSingleton<IdentifierDrawer>()
.AddSingleton<GlamourerChangelog>()
.AddSingleton<DesignQuickBar>();
.AddSingleton<DesignQuickBar>()
.AddSingleton<DesignColorUi>();
private static IServiceCollection AddApi(this IServiceCollection services)
=> services.AddSingleton<CommandService>()