feat: improve interactions with active HUD layout

Trying to preview different saved was more difficult than it
needed to be since after importing a layout, the user needed to
swap to another layout and then back to the original one in order
to see the changes. I changed this so that if a user imports a
layout to the currently active HUD slot, the plugin automatically
swaps to another HUD slot and back.

As a part of this also refined the general slot UI so that the
active slot is indicated in the slot selection UI for saving a
layout to game data.
This commit is contained in:
Zacharie Day 2020-09-15 20:15:07 -04:00 committed by Anna
parent 38907f2cd8
commit 67a3b5caf3
2 changed files with 51 additions and 19 deletions

View File

@ -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 {

View File

@ -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<Guid, Layout> 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();
}
}