diff --git a/HudSwap/HUD.cs b/HudSwap/HUD.cs index d9ca985..b6ac412 100644 --- a/HudSwap/HUD.cs +++ b/HudSwap/HUD.cs @@ -11,6 +11,7 @@ namespace HudSwap { private const int LAYOUT_SIZE = 0xb40; private delegate IntPtr GetFilePointerDelegate(byte index); + private delegate uint SetHudLayoutDelegate(IntPtr filePtr, uint hudLayout, byte unk0, byte unk1); private readonly GetFilePointerDelegate _getFilePointer; @@ -73,6 +74,16 @@ namespace HudSwap { return this.GetDataPointer() + 0x2c58 + (slotNum * LAYOUT_SIZE); } + public HudSlot GetActiveHudSlot() { + int slotVal = Marshal.ReadInt32(this.GetDataPointer() + 0x5958); + + if (!Enum.IsDefined(typeof(HudSlot), slotVal)) { + throw new IOException($"invalid hud slot in FFXIV memory of ${slotVal}"); + } + + return (HudSlot)slotVal; + } + public byte[] ReadLayout(HudSlot slot) { IntPtr slotPtr = this.GetLayoutPointer(slot); byte[] bytes = new byte[LAYOUT_SIZE]; @@ -87,9 +98,17 @@ namespace HudSwap { if (layout.Length != LAYOUT_SIZE) { throw new ArgumentException($"layout must be {LAYOUT_SIZE} bytes", nameof(layout)); } + IntPtr slotPtr = this.GetLayoutPointer(slot); Marshal.Copy(layout, 0, slotPtr, LAYOUT_SIZE); + + var currentSlot = this.GetActiveHudSlot(); + if (currentSlot == slot) { + this.SelectSlot(currentSlot, true); + } } + + public void WriteLayout(byte[] layout) => WriteLayout(this.GetActiveHudSlot(), layout); } public enum HudSlot { diff --git a/HudSwap/PluginUI.cs b/HudSwap/PluginUI.cs index 0a5c6bf..ba69cf4 100644 --- a/HudSwap/PluginUI.cs +++ b/HudSwap/PluginUI.cs @@ -39,7 +39,10 @@ namespace HudSwap { private string importName = ""; private string renameName = ""; - private Guid selectedLayout = Guid.Empty; + private Guid selectedLayoutId = Guid.Empty; + + private Layout selectedLayout => + selectedLayoutId == Guid.Empty ? null : this.plugin.Config.Layouts2[this.selectedLayoutId]; private int editingConditionIndex = -1; private HudConditionMatch editingCondition; @@ -107,8 +110,8 @@ namespace HudSwap { ImGui.PushItemWidth(-1); if (ImGui.ListBoxHeader("##saved-layouts")) { foreach (KeyValuePair entry in this.plugin.Config.Layouts2) { - if (ImGui.Selectable($"{entry.Value.Name}##{entry.Key}", this.selectedLayout == entry.Key)) { - this.selectedLayout = entry.Key; + if (ImGui.Selectable($"{entry.Value.Name}##{entry.Key}", this.selectedLayoutId == entry.Key)) { + this.selectedLayoutId = entry.Key; this.renameName = entry.Value.Name; this.importName = this.renameName; } @@ -117,27 +120,37 @@ namespace HudSwap { } ImGui.PopItemWidth(); + ImGui.NewLine(); + + const int deleteButtonWidth = 30; + ImGui.SameLine(ImGui.GetWindowContentRegionWidth() - deleteButtonWidth); + ImGui.PushFont(UiBuilder.IconFont); + if (ImGui.Button(FontAwesomeIcon.Trash.ToIconString(), new Vector2(deleteButtonWidth, ImGui.GetTextLineHeight())) && + this.selectedLayoutId != null) { + this.plugin.Config.Layouts2.Remove(this.selectedLayoutId); + this.plugin.Config.HudConditionMatches.RemoveAll(m => m.LayoutId == this.selectedLayoutId); + this.selectedLayoutId = Guid.Empty; + this.renameName = ""; + this.plugin.Config.Save(); + } + ImGui.PopFont(); + ImGui.Text("Copy onto slot..."); + Vector2 slotButtonSize = new Vector2(40, ImGui.GetTextLineHeight()); foreach (HudSlot slot in Enum.GetValues(typeof(HudSlot))) { - string buttonName = $"{(int)slot + 1}##copy"; - if (ImGui.Button(buttonName) && this.selectedLayout != null) { - Layout layout = this.plugin.Config.Layouts2[this.selectedLayout]; - this.plugin.Hud.WriteLayout(slot, layout.Hud.ToArray()); + // Surround the button with parentheses if this is the current slot + string slotText = slot == this.plugin.Hud.GetActiveHudSlot() ? $"({(int)slot + 1})" : ((int)slot + 1).ToString(); + string buttonName = $"{slotText}##copy"; + if (ImGui.Button(buttonName, slotButtonSize) && this.selectedLayout != null) { + this.plugin.Hud.WriteLayout(slot, this.selectedLayout.Hud); } ImGui.SameLine(); } - if (ImGui.Button("Delete") && this.selectedLayout != null) { - this.plugin.Config.Layouts2.Remove(this.selectedLayout); - this.plugin.Config.HudConditionMatches.RemoveAll(m => m.LayoutId == this.selectedLayout); - this.selectedLayout = Guid.Empty; - this.renameName = ""; - this.plugin.Config.Save(); - } ImGui.SameLine(); - if (ImGui.Button("Copy to clipboard") && this.selectedLayout != null) { - if (this.plugin.Config.Layouts2.TryGetValue(this.selectedLayout, out Layout layout)) { + if (ImGui.Button("Clipboard") && this.selectedLayoutId != null) { + if (this.plugin.Config.Layouts2.TryGetValue(this.selectedLayoutId, out Layout layout)) { SharedLayout shared = new SharedLayout(layout); string json = JsonConvert.SerializeObject(shared); ImGui.SetClipboardText(json); @@ -146,10 +159,10 @@ namespace HudSwap { ImGui.InputText("##rename-input", ref this.renameName, 100); ImGui.SameLine(); - if (ImGui.Button("Rename") && this.renameName.Length != 0 && this.selectedLayout != null) { - Layout layout = this.plugin.Config.Layouts2[this.selectedLayout]; + if (ImGui.Button("Rename") && this.renameName.Length != 0 && this.selectedLayoutId != null) { + Layout layout = this.plugin.Config.Layouts2[this.selectedLayoutId]; Layout newLayout = new Layout(this.renameName, layout.Hud, layout.Positions); - this.plugin.Config.Layouts2[this.selectedLayout] = newLayout; + this.plugin.Config.Layouts2[this.selectedLayoutId] = newLayout; this.plugin.Config.Save(); } }