mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 18:27:24 +01:00
Add support for custom colors for design display.
This commit is contained in:
parent
ec7a53bee2
commit
2b30a88bf4
13 changed files with 438 additions and 39 deletions
|
|
@ -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,7 +43,8 @@ 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 SortedList<Mod, ModSettings> AssociatedMods { get; private set; } = new();
|
||||
public string Color { get; internal set; } = string.Empty;
|
||||
public SortedList<Mod, ModSettings> AssociatedMods { get; private set; } = new();
|
||||
|
||||
public string Incognito
|
||||
=> Identifier.ToString()[..8];
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
303
Glamourer/Designs/DesignColors.cs
Normal file
303
Glamourer/Designs/DesignColors.cs
Normal 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;
|
||||
}
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Buffers.Text;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Glamourer.Customization;
|
||||
using Glamourer.Services;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,12 +181,22 @@ public class SettingsTab : ITab
|
|||
if (!ImGui.CollapsingHeader("Colors"))
|
||||
return;
|
||||
|
||||
foreach (var color in Enum.GetValues<ColorId>())
|
||||
using (var tree = ImRaii.TreeNode("Custom Design Colors"))
|
||||
{
|
||||
var (defaultColor, name, description) = color.Data();
|
||||
var currentColor = _config.Colors.TryGetValue(color, out var current) ? current : defaultColor;
|
||||
if (Widget.ColorPicker(name, description, currentColor, c => _config.Colors[color] = c, defaultColor))
|
||||
_config.Save();
|
||||
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();
|
||||
var currentColor = _config.Colors.TryGetValue(color, out var current) ? current : defaultColor;
|
||||
if (Widget.ColorPicker(name, description, currentColor, c => _config.Colors[color] = c, defaultColor))
|
||||
_config.Save();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.NewLine();
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ public class BackupService
|
|||
new(fileNames.UnlockFileCustomize),
|
||||
new(fileNames.UnlockFileItems),
|
||||
new(fileNames.FavoriteFile),
|
||||
new(fileNames.DesignColorFile),
|
||||
};
|
||||
|
||||
list.AddRange(fileNames.Designs());
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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>()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue