First iteration of fixing designs for characters.

This commit is contained in:
Ottermandias 2021-09-06 23:37:05 +02:00
parent c9f46575a1
commit 8a589686a8
6 changed files with 338 additions and 12 deletions

View file

@ -0,0 +1,162 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Dalamud.Game.ClientState.Objects.Enums;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Logging;
using Glamourer.FileSystem;
using Penumbra.GameData.Enums;
namespace Glamourer.Designs
{
public class FixedDesigns : IDisposable
{
public class FixedDesign
{
public string Name;
public Design Design;
public bool Enabled;
public GlamourerConfig.FixedDesign ToSave()
=> new()
{
Name = Name,
Path = Design.FullName(),
Enabled = Enabled,
};
public FixedDesign(string name, Design design, bool enabled)
{
Name = name;
Design = design;
Enabled = enabled;
}
}
public List<FixedDesign> Data;
public Dictionary<string, FixedDesign> EnabledDesigns;
public bool EnableDesign(FixedDesign design)
{
var changes = !design.Enabled;
if (EnabledDesigns.TryGetValue(design.Name, out var oldDesign))
{
oldDesign.Enabled = false;
changes = true;
}
else
{
Glamourer.PlayerWatcher.AddPlayerToWatch(design.Name);
}
EnabledDesigns[design.Name] = design;
design.Enabled = true;
if (Dalamud.Objects.FirstOrDefault(o => o.ObjectKind == ObjectKind.Player && o.Name.ToString() == design.Name)
is Character character)
OnPlayerChange(character);
return changes;
}
public bool DisableDesign(FixedDesign design)
{
if (!design.Enabled)
return false;
design.Enabled = false;
EnabledDesigns.Remove(design.Name);
Glamourer.PlayerWatcher.RemovePlayerFromWatch(design.Name);
return true;
}
public FixedDesigns(DesignManager designs)
{
Data = new List<FixedDesign>(Glamourer.Config.FixedDesigns.Count);
EnabledDesigns = new Dictionary<string, FixedDesign>(Glamourer.Config.FixedDesigns.Count);
Glamourer.PlayerWatcher.PlayerChanged += OnPlayerChange;
var changes = false;
for (var i = 0; i < Glamourer.Config.FixedDesigns.Count; ++i)
{
var save = Glamourer.Config.FixedDesigns[i];
if (designs.FileSystem.Find(save.Path, out var d) && d is Design design)
{
Data.Add(new FixedDesign(save.Name, design, save.Enabled));
if (save.Enabled)
changes |= EnableDesign(Data.Last());
}
else
{
PluginLog.Warning($"{save.Path} does not exist anymore, removing {save.Name} from fixed designs.");
Glamourer.Config.FixedDesigns.RemoveAt(i--);
changes = true;
}
}
if (changes)
Glamourer.Config.Save();
}
private void OnPlayerChange(Character character)
{
var name = character.Name.ToString();
if (EnabledDesigns.TryGetValue(name, out var design))
{
PluginLog.Debug("Redrawing {CharacterName} with {DesignName}.", name, design.Design.FullName());
design.Design.Data.Apply(character);
Glamourer.PlayerWatcher.UpdatePlayerWithoutEvent(character);
Glamourer.Penumbra.RedrawObject(character, RedrawType.WithSettings, false);
}
}
public void Add(string name, Design design, bool enabled = false)
{
Data.Add(new FixedDesign(name, design, enabled));
Glamourer.Config.FixedDesigns.Add(Data.Last().ToSave());
if (enabled)
EnableDesign(Data.Last());
Glamourer.Config.Save();
}
public void Remove(FixedDesign design)
{
var idx = Data.IndexOf(design);
if (idx < 0)
return;
Data.RemoveAt(idx);
Glamourer.Config.FixedDesigns.RemoveAt(idx);
if (design.Enabled)
{
EnabledDesigns.Remove(design.Name);
Glamourer.PlayerWatcher.RemovePlayerFromWatch(design.Name);
}
Glamourer.Config.Save();
}
public void Move(FixedDesign design, int newIdx)
{
if (newIdx < 0)
newIdx = 0;
if (newIdx >= Data.Count)
newIdx = Data.Count - 1;
var idx = Data.IndexOf(design);
if (idx < 0 || idx == newIdx)
return;
Data.RemoveAt(idx);
Data.Insert(newIdx, design);
Glamourer.Config.FixedDesigns.RemoveAt(idx);
Glamourer.Config.FixedDesigns.Insert(newIdx, design.ToSave());
Glamourer.Config.Save();
}
public void Dispose()
{
Glamourer.Config.FixedDesigns = Data.Select(d => d.ToSave()).ToList();
Glamourer.Config.Save();
}
}
}

View file

@ -24,7 +24,8 @@ namespace Glamourer
public static IPlayerWatcher PlayerWatcher = null!;
public static ICustomizationManager Customization = null!;
private readonly Interface _interface;
public DesignManager Designs;
public readonly DesignManager Designs;
public readonly FixedDesigns FixedDesigns;
public static string Version = string.Empty;
@ -39,6 +40,10 @@ namespace Glamourer
Designs = new DesignManager();
Penumbra = new PenumbraAttach(Config.AttachToPenumbra);
PlayerWatcher = PlayerWatchFactory.Create(Dalamud.Framework, Dalamud.ClientState, Dalamud.Objects);
FixedDesigns = new FixedDesigns(Designs);
if (Config.ApplyFixedDesigns)
PlayerWatcher.Enable();
Dalamud.Commands.AddHandler("/glamourer", new CommandInfo(OnGlamourer)
{
@ -190,6 +195,7 @@ namespace Glamourer
public void Dispose()
{
FixedDesigns.Dispose();
Penumbra.Dispose();
PlayerWatcher.Dispose();
_interface.Dispose();

View file

@ -1,24 +1,35 @@
using Dalamud.Configuration;
using System.Collections.Generic;
using Dalamud.Configuration;
namespace Glamourer
{
public class GlamourerConfig : IPluginConfiguration
{
public struct FixedDesign
{
public string Name;
public string Path;
public bool Enabled;
}
public int Version { get; set; } = 1;
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 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 List<FixedDesign> FixedDesigns { get; set; } = new();
public void Save()
=> Dalamud.PluginInterface.SavePluginConfig(this);

View file

@ -88,6 +88,7 @@ namespace Glamourer.Gui
DrawPlayerTab();
DrawSaves();
DrawFixedDesignsTab();
DrawConfigTab();
}
finally

View file

@ -54,9 +54,7 @@ namespace Glamourer.Gui
}
if (ImGui.Button(buttonLabel))
{
Glamourer.Penumbra.Reattach(true);
}
if (ImGui.IsItemHovered())
ImGui.SetTooltip(
@ -86,17 +84,25 @@ namespace Glamourer.Gui
{
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.",

View file

@ -0,0 +1,140 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using Dalamud.Interface;
using Glamourer.Designs;
using Glamourer.FileSystem;
using ImGuiNET;
namespace Glamourer.Gui
{
internal partial class Interface
{
private const string FixDragDropLabel = "##FixDragDrop";
private List<string>? _fullPathCache;
private string _newFixCharacterName = string.Empty;
private string _newFixDesignPath = string.Empty;
private Design? _newFixDesign;
private int _fixDragDropIdx = -1;
private static unsafe bool IsDropping()
=> ImGui.AcceptDragDropPayload(FixDragDropLabel).NativePtr != null;
private void DrawFixedDesignsTab()
{
using var raii = new ImGuiRaii();
if (!raii.Begin(() => ImGui.BeginTabItem("Fixed Designs"), ImGui.EndTabItem))
{
_fullPathCache = null;
_newFixDesign = null;
_newFixDesignPath = string.Empty;
return;
}
_fullPathCache ??= _plugin.FixedDesigns.Data.Select(d => d.Design.FullName()).ToList();
raii.Begin(() => ImGui.BeginTable("##FixedTable", 3), ImGui.EndTable);
var buttonWidth = 23.5f * ImGuiHelpers.GlobalScale;
ImGui.TableSetupColumn("##DeleteColumn", ImGuiTableColumnFlags.WidthFixed, 2 * buttonWidth);
ImGui.TableSetupColumn("Character", ImGuiTableColumnFlags.WidthFixed, 200 * ImGuiHelpers.GlobalScale);
ImGui.TableSetupColumn("Design", ImGuiTableColumnFlags.WidthStretch);
ImGui.TableHeadersRow();
var xPos = 0f;
for (var i = 0; i < _fullPathCache.Count; ++i)
{
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);
}
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.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(path);
}
ImGui.TableNextRow();
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, false);
_newFixCharacterName = string.Empty;
_newFixDesignPath = string.Empty;
_newFixDesign = null;
}
raii.PopFonts();
ImGui.TableNextColumn();
ImGui.SetNextItemWidth(200 * ImGuiHelpers.GlobalScale);
ImGui.InputTextWithHint("##NewFix", "Enter new Character", ref _newFixCharacterName, 32);
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<Design>())
{
var fullName = design.FullName();
ImGui.SetNextItemWidth(-1);
if (!ImGui.Selectable($"{fullName}##NewFixDesign", fullName == _newFixDesignPath))
continue;
_newFixDesignPath = fullName;
_newFixDesign = design;
}
}
}
}