feat: cache dresser and show what's available

This commit is contained in:
Anna 2021-12-09 04:07:58 -05:00
parent 31e2002696
commit c08c8a6123
Signed by: anna
GPG Key ID: 0B391D8F06FCD9E0
6 changed files with 162 additions and 37 deletions

View File

@ -13,6 +13,7 @@ namespace Glamaholic {
public bool ShowExamineMenu = true; public bool ShowExamineMenu = true;
public bool ShowTryOnMenu = true; public bool ShowTryOnMenu = true;
public bool ShowKofiButton = true; public bool ShowKofiButton = true;
public bool ItemFilterShowObtainedOnly;
internal static void SanitisePlate(SavedPlate plate) { internal static void SanitisePlate(SavedPlate plate) {
var valid = Enum.GetValues<PlateSlot>(); var valid = Enum.GetValues<PlateSlot>();

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -59,9 +60,13 @@ namespace Glamaholic {
this._examineNamePtr = this.Plugin.SigScanner.GetStaticAddressFromSig(Signatures.ExamineNamePointer); this._examineNamePtr = this.Plugin.SigScanner.GetStaticAddressFromSig(Signatures.ExamineNamePointer);
this.Plugin.ChatGui.ChatMessage += this.OnChat; this.Plugin.ChatGui.ChatMessage += this.OnChat;
this.Plugin.ClientState.Login += OnLogin;
this.Plugin.Framework.Update += this.OnFrameworkUpdate;
} }
public void Dispose() { public void Dispose() {
this.Plugin.Framework.Update -= this.OnFrameworkUpdate;
this.Plugin.ClientState.Login -= OnLogin;
this.Plugin.ChatGui.ChatMessage -= this.OnChat; this.Plugin.ChatGui.ChatMessage -= this.OnChat;
} }
@ -74,6 +79,22 @@ namespace Glamaholic {
isHandled = true; isHandled = true;
} }
} }
private static void OnLogin(object? sender, EventArgs e) {
_dresserContents = null;
}
private bool _wasEditing;
private void OnFrameworkUpdate(Dalamud.Game.Framework framework) {
var editing = Util.IsEditingPlate(this.Plugin.GameGui);
if (!this._wasEditing && editing) {
// cache dresser
var unused = DresserContents;
}
this._wasEditing = editing;
}
internal unsafe bool ArmoireLoaded => *(byte*) this._armoirePtr > 0; internal unsafe bool ArmoireLoaded => *(byte*) this._armoirePtr > 0;
@ -81,8 +102,15 @@ namespace Glamaholic {
? null ? null
: MemoryHelper.ReadStringNullTerminated(this._examineNamePtr); : MemoryHelper.ReadStringNullTerminated(this._examineNamePtr);
private static readonly Stopwatch DresserTimer = new();
private static List<GlamourItem>? _dresserContents;
internal static unsafe List<GlamourItem> DresserContents { internal static unsafe List<GlamourItem> DresserContents {
get { get {
if (_dresserContents != null && DresserTimer.Elapsed < TimeSpan.FromSeconds(1)) {
return _dresserContents;
}
var list = new List<GlamourItem>(); var list = new List<GlamourItem>();
var agents = Framework.Instance()->GetUiModule()->GetAgentModule(); var agents = Framework.Instance()->GetUiModule()->GetAgentModule();
@ -91,7 +119,7 @@ namespace Glamaholic {
var itemsStart = *(IntPtr*) ((IntPtr) dresserAgent + 0x28); var itemsStart = *(IntPtr*) ((IntPtr) dresserAgent + 0x28);
if (itemsStart == IntPtr.Zero) { if (itemsStart == IntPtr.Zero) {
return list; return _dresserContents ?? list;
} }
for (var i = 0; i < 400; i++) { for (var i = 0; i < 400; i++) {
@ -103,6 +131,9 @@ namespace Glamaholic {
list.Add(glamItem); list.Add(glamItem);
} }
_dresserContents = list;
DresserTimer.Restart();
return list; return list;
} }
} }

View File

@ -1,5 +1,6 @@
using Dalamud.Data; using Dalamud.Data;
using Dalamud.Game; using Dalamud.Game;
using Dalamud.Game.ClientState;
using Dalamud.Game.Command; using Dalamud.Game.Command;
using Dalamud.Game.Gui; using Dalamud.Game.Gui;
using Dalamud.IoC; using Dalamud.IoC;
@ -16,12 +17,18 @@ namespace Glamaholic {
[PluginService] [PluginService]
internal ChatGui ChatGui { get; init; } internal ChatGui ChatGui { get; init; }
[PluginService]
internal ClientState ClientState { get; init; }
[PluginService] [PluginService]
internal CommandManager CommandManager { get; init; } internal CommandManager CommandManager { get; init; }
[PluginService] [PluginService]
internal DataManager DataManager { get; init; } internal DataManager DataManager { get; init; }
[PluginService]
internal Framework Framework { get; init; }
[PluginService] [PluginService]
internal GameGui GameGui { get; init; } internal GameGui GameGui { get; init; }

View File

@ -83,18 +83,16 @@ namespace Glamaholic.Ui {
ImGui.SameLine(); ImGui.SameLine();
ImGui.PushFont(UiBuilder.IconFont);
if (!alt.IsDyeable) { if (!alt.IsDyeable) {
ImGui.PushStyleColor(ImGuiCol.Text, ImGui.GetStyle().Colors[(int) ImGuiCol.TextDisabled]); ImGui.PushStyleColor(ImGuiCol.Text, ImGui.GetStyle().Colors[(int) ImGuiCol.TextDisabled]);
} }
ImGui.TextUnformatted(FontAwesomeIcon.FillDrip.ToIconString()); Util.TextIcon(FontAwesomeIcon.FillDrip);
if (!alt.IsDyeable) { if (!alt.IsDyeable) {
ImGui.PopStyleColor(); ImGui.PopStyleColor();
} }
ImGui.PopFont();
ImGui.SameLine(); ImGui.SameLine();
ImGui.TextUnformatted(alt.Name); ImGui.TextUnformatted(alt.Name);
} }

View File

@ -50,13 +50,13 @@ namespace Glamaholic.Ui {
private string _importInput = string.Empty; private string _importInput = string.Empty;
private Exception? _importError; private Exception? _importError;
private bool _deleteConfirm; private bool _deleteConfirm;
private readonly Stopwatch _shareTimer = new();
private bool _editing; private bool _editing;
private SavedPlate? _editingPlate; private SavedPlate? _editingPlate;
private string _itemFilter = string.Empty; private string _itemFilter = string.Empty;
private string _dyeFilter = string.Empty; private string _dyeFilter = string.Empty;
private string _ecImport = string.Empty; private string _ecImport = string.Empty;
private volatile bool _ecImporting; private volatile bool _ecImporting;
private readonly Dictionary<string, Stopwatch> _timedMessages = new();
internal MainInterface(PluginUi ui) { internal MainInterface(PluginUi ui) {
this.Ui = ui; this.Ui = ui;
@ -474,6 +474,15 @@ namespace Glamaholic.Ui {
ImGui.SetKeyboardFocusHere(); ImGui.SetKeyboardFocusHere();
} }
if (GameFunctions.DresserContents.Count > 0) {
if (ImGui.Checkbox("Only show items in the armoire/dresser", ref this.Ui.Plugin.Config.ItemFilterShowObtainedOnly)) {
this.Ui.Plugin.SaveConfig();
this.FilterItems(slot);
}
ImGui.Separator();
}
if (ImGui.BeginChild("item search", new Vector2(250, 450), false, ImGuiWindowFlags.HorizontalScrollbar)) { if (ImGui.BeginChild("item search", new Vector2(250, 450), false, ImGuiWindowFlags.HorizontalScrollbar)) {
uint? id; uint? id;
if (plate.Items.TryGetValue(slot, out var slotMirage)) { if (plate.Items.TryGetValue(slot, out var slotMirage)) {
@ -482,15 +491,25 @@ namespace Glamaholic.Ui {
id = null; id = null;
} }
if (ImGui.Selectable("None (keep existing)", id == null)) { if (ImGui.Selectable("##none-keep", id == null)) {
plate.Items.Remove(slot); plate.Items.Remove(slot);
ImGui.CloseCurrentPopup(); ImGui.CloseCurrentPopup();
} }
if (ImGui.Selectable("None (remove existing)", id == 0)) { ImGui.SameLine();
Util.TextIcon(FontAwesomeIcon.Box);
ImGui.SameLine();
ImGui.TextUnformatted("None (keep existing)");
if (ImGui.Selectable("##none-remove)", id == 0)) {
plate.Items[slot] = new SavedGlamourItem(); plate.Items[slot] = new SavedGlamourItem();
ImGui.CloseCurrentPopup(); ImGui.CloseCurrentPopup();
} }
ImGui.SameLine();
Util.TextIcon(FontAwesomeIcon.Box);
ImGui.SameLine();
ImGui.TextUnformatted("None (remove existing)");
var clipper = new ImGuiListClipperPtr(ImGuiNative.ImGuiListClipper_ImGuiListClipper()); var clipper = new ImGuiListClipperPtr(ImGuiNative.ImGuiListClipper_ImGuiListClipper());
@ -499,7 +518,7 @@ namespace Glamaholic.Ui {
for (var i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) { for (var i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
var item = this.FilteredItems[i]; var item = this.FilteredItems[i];
if (ImGui.Selectable($"{item.Name}##{item.RowId}", item.RowId == id)) { if (ImGui.Selectable($"##{item.RowId}", item.RowId == id)) {
if (!plate.Items.ContainsKey(slot)) { if (!plate.Items.ContainsKey(slot)) {
plate.Items[slot] = new SavedGlamourItem(); plate.Items[slot] = new SavedGlamourItem();
} }
@ -515,6 +534,24 @@ namespace Glamaholic.Ui {
if (Util.IsItemMiddleOrCtrlClicked()) { if (Util.IsItemMiddleOrCtrlClicked()) {
this.Ui.AlternativeFinders.Add(new AlternativeFinder(this.Ui, item)); this.Ui.AlternativeFinders.Add(new AlternativeFinder(this.Ui, item));
} }
ImGui.SameLine();
var has = GameFunctions.DresserContents.Any(saved => saved.ItemId % Util.HqItemOffset == item.RowId) || this.Ui.Plugin.Functions.IsInArmoire(item.RowId);
if (!has) {
ImGui.PushStyleColor(ImGuiCol.Text, ImGui.GetStyle().Colors[(int) ImGuiCol.TextDisabled]);
}
Util.TextIcon(FontAwesomeIcon.Box);
if (!has) {
ImGui.PopStyleColor();
}
ImGui.SameLine();
ImGui.TextUnformatted($"{item.Name}");
} }
} }
@ -524,7 +561,7 @@ namespace Glamaholic.Ui {
ImGui.EndPopup(); ImGui.EndPopup();
} }
private unsafe void DrawIcon(PlateSlot slot, SavedPlate plate, bool editingPlate, int iconSize, int paddingSize) { private unsafe void DrawIcon(PlateSlot slot, SavedPlate plate, int iconSize, int paddingSize) {
var drawCursor = ImGui.GetCursorScreenPos(); var drawCursor = ImGui.GetCursorScreenPos();
var tooltip = slot.Name(); var tooltip = slot.Name();
ImGui.BeginGroup(); ImGui.BeginGroup();
@ -534,7 +571,7 @@ namespace Glamaholic.Ui {
var borderColour = *ImGui.GetStyleColorVec4(ImGuiCol.Border); var borderColour = *ImGui.GetStyleColorVec4(ImGuiCol.Border);
// check for item // check for item
if (mirage != null && mirage.ItemId != 0 && editingPlate) { if (mirage != null && mirage.ItemId != 0 && GameFunctions.DresserContents.Count > 0) {
var has = GameFunctions.DresserContents.Any(saved => saved.ItemId % Util.HqItemOffset == mirage.ItemId) || this.Ui.Plugin.Functions.IsInArmoire(mirage.ItemId); var has = GameFunctions.DresserContents.Any(saved => saved.ItemId % Util.HqItemOffset == mirage.ItemId) || this.Ui.Plugin.Functions.IsInArmoire(mirage.ItemId);
if (!has) { if (!has) {
borderColour = ImGuiColors.DalamudYellow; borderColour = ImGuiColors.DalamudYellow;
@ -631,7 +668,7 @@ namespace Glamaholic.Ui {
} }
} }
private void DrawPlatePreview(bool editingPlate, SavedPlate plate) { private void DrawPlatePreview(SavedPlate plate) {
const int paddingSize = 12; const int paddingSize = 12;
if (!ImGui.BeginTable("plate item preview", 2, ImGuiTableFlags.SizingFixedFit)) { if (!ImGui.BeginTable("plate item preview", 2, ImGuiTableFlags.SizingFixedFit)) {
@ -640,9 +677,9 @@ namespace Glamaholic.Ui {
foreach (var (left, right) in LeftSide.Zip(RightSide)) { foreach (var (left, right) in LeftSide.Zip(RightSide)) {
ImGui.TableNextColumn(); ImGui.TableNextColumn();
this.DrawIcon(left, plate, editingPlate, IconSize, paddingSize); this.DrawIcon(left, plate, IconSize, paddingSize);
ImGui.TableNextColumn(); ImGui.TableNextColumn();
this.DrawIcon(right, plate, editingPlate, IconSize, paddingSize); this.DrawIcon(right, plate, IconSize, paddingSize);
} }
ImGui.EndTable(); ImGui.EndTable();
@ -655,6 +692,10 @@ namespace Glamaholic.Ui {
ImGui.TableNextColumn(); ImGui.TableNextColumn();
if (Util.IconButton(FontAwesomeIcon.Check, tooltip: "Apply")) { if (Util.IconButton(FontAwesomeIcon.Check, tooltip: "Apply")) {
if (!Util.IsEditingPlate(this.Ui.Plugin.GameGui)) {
this.AddTimedMessage("The in-game plate editor must be open.");
}
this.Ui.Plugin.Functions.LoadPlate(plate); this.Ui.Plugin.Functions.LoadPlate(plate);
} }
@ -678,13 +719,13 @@ namespace Glamaholic.Ui {
ImGui.TableNextColumn(); ImGui.TableNextColumn();
if (Util.IconButton(FontAwesomeIcon.ShareAltSquare, tooltip: "Share")) { if (Util.IconButton(FontAwesomeIcon.ShareAltSquare, tooltip: "Share")) {
ImGui.SetClipboardText(JsonConvert.SerializeObject(plate)); ImGui.SetClipboardText(JsonConvert.SerializeObject(plate));
this._shareTimer.Start(); this.AddTimedMessage("Copied to clipboard.");
} }
ImGui.EndTable(); ImGui.EndTable();
} }
private void DrawPlateDetail(bool editingPlate) { private void DrawPlateDetail() {
if (!ImGui.BeginChild("plate detail")) { if (!ImGui.BeginChild("plate detail")) {
return; return;
} }
@ -692,14 +733,14 @@ namespace Glamaholic.Ui {
if (this._selectedPlate > -1 && this._selectedPlate < this.Ui.Plugin.Config.Plates.Count) { if (this._selectedPlate > -1 && this._selectedPlate < this.Ui.Plugin.Config.Plates.Count) {
var plate = this._editingPlate ?? this.Ui.Plugin.Config.Plates[this._selectedPlate]; var plate = this._editingPlate ?? this.Ui.Plugin.Config.Plates[this._selectedPlate];
this.DrawPlatePreview(editingPlate, plate); this.DrawPlatePreview(plate);
var renameWasVisible = this._showRename; var renameWasVisible = this._showRename;
this.DrawPlateButtons(plate); this.DrawPlateButtons(plate);
if (this._shareTimer.IsRunning) { foreach (var (msg, _) in this._timedMessages) {
Util.TextUnformattedWrapped("Copied to clipboard."); Util.TextUnformattedWrapped(msg);
} }
if (this._showRename && Util.DrawTextInput("plate-rename", ref this._renameInput, flags: ImGuiInputTextFlags.AutoSelectAll)) { if (this._showRename && Util.DrawTextInput("plate-rename", ref this._renameInput, flags: ImGuiInputTextFlags.AutoSelectAll)) {
@ -712,12 +753,6 @@ namespace Glamaholic.Ui {
ImGui.SetKeyboardFocusHere(); ImGui.SetKeyboardFocusHere();
} }
if (!this.Ui.Plugin.Functions.ArmoireLoaded) {
ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudYellow);
Util.TextUnformattedWrapped("The Armoire is not loaded. Open it once to enable glamours from the Armoire.");
ImGui.PopStyleColor();
}
if (this._editing) { if (this._editing) {
Util.TextUnformattedWrapped("Click an item to edit it. Right-click to dye."); Util.TextUnformattedWrapped("Click an item to edit it. Right-click to dye.");
@ -738,39 +773,74 @@ namespace Glamaholic.Ui {
ImGui.EndChild(); ImGui.EndChild();
} }
private void DrawInner() { private void DrawWarnings() {
var editingPlate = Util.IsEditingPlate(this.Ui.Plugin.GameGui); var warnings = new List<string>();
if (!this.Ui.Plugin.Functions.ArmoireLoaded) {
warnings.Add("The Armoire is not loaded. Open it once to enable glamours from the Armoire.");
}
if (GameFunctions.DresserContents.Count == 0) {
warnings.Add("Glamour Dresser is empty or has not been opened. Glamaholic will not know which items you have.");
}
if (warnings.Count == 0) {
return;
}
ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudYellow);
var header = ImGui.CollapsingHeader($"Warnings ({warnings.Count})###warnings");
ImGui.PopStyleColor();
if (!header) {
return;
}
for (var i = 0; i < warnings.Count; i++) {
if (i != 0) {
ImGui.Separator();
}
Util.TextUnformattedWrapped(warnings[i]);
}
}
private void DrawInner() {
this.DrawMenuBar(); this.DrawMenuBar();
if (!editingPlate) { this.DrawWarnings();
ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudYellow);
Util.TextUnformattedWrapped("Glamour Plate editor is not open. Certain functions will not work.");
ImGui.PopStyleColor();
}
this.DrawPlateList(); this.DrawPlateList();
ImGui.SameLine(); ImGui.SameLine();
this.DrawPlateDetail(editingPlate); this.DrawPlateDetail();
ImGui.End(); ImGui.End();
} }
private void HandleTimers() { private void HandleTimers() {
if (this._shareTimer.Elapsed > TimeSpan.FromSeconds(5)) { var keys = this._timedMessages.Keys.ToArray();
this._shareTimer.Reset(); foreach (var key in keys) {
if (this._timedMessages[key].Elapsed > TimeSpan.FromSeconds(5)) {
this._timedMessages.Remove(key);
}
} }
} }
private void AddTimedMessage(string message) {
var timer = new Stopwatch();
timer.Start();
this._timedMessages[message] = timer;
}
internal void SwitchPlate(int idx, bool scrollTo = false) { internal void SwitchPlate(int idx, bool scrollTo = false) {
this._selectedPlate = idx; this._selectedPlate = idx;
this._scrollToSelected = scrollTo; this._scrollToSelected = scrollTo;
this._renameInput = string.Empty; this._renameInput = string.Empty;
this._showRename = false; this._showRename = false;
this._deleteConfirm = false; this._deleteConfirm = false;
this._shareTimer.Reset(); this._timedMessages.Clear();
this.ResetEditing(); this.ResetEditing();
} }
@ -783,7 +853,19 @@ namespace Glamaholic.Ui {
private void FilterItems(PlateSlot slot) { private void FilterItems(PlateSlot slot) {
var filter = this._itemFilter.ToLowerInvariant(); var filter = this._itemFilter.ToLowerInvariant();
this.FilteredItems = this.Items
IEnumerable<Item> items;
if (GameFunctions.DresserContents.Count > 0 && this.Ui.Plugin.Config.ItemFilterShowObtainedOnly) {
var sheet = this.Ui.Plugin.DataManager.GetExcelSheet<Item>()!;
items = GameFunctions.DresserContents
.Select(item => sheet.GetRow(item.ItemId))
.Where(item => item != null)
.Cast<Item>();
} else {
items = this.Items;
}
this.FilteredItems = items
.Where(item => !Util.IsItemSkipped(item)) .Where(item => !Util.IsItemSkipped(item))
.Where(item => Util.MatchesSlot(item.EquipSlotCategory.Value!, slot)) .Where(item => Util.MatchesSlot(item.EquipSlotCategory.Value!, slot))
.Where(item => this._itemFilter.Length == 0 || item.Name.RawString.ToLowerInvariant().Contains(filter)) .Where(item => this._itemFilter.Length == 0 || item.Name.RawString.ToLowerInvariant().Contains(filter))

View File

@ -160,5 +160,11 @@ namespace Glamaholic {
_ => name.Length == 0 || name.StartsWith("Dated"), _ => name.Length == 0 || name.StartsWith("Dated"),
}; };
} }
internal static void TextIcon(FontAwesomeIcon icon) {
ImGui.PushFont(UiBuilder.IconFont);
ImGui.TextUnformatted(icon.ToIconString());
ImGui.PopFont();
}
} }
} }