From 6567eb7c805e4c16bc309990c83f1902c0a83256 Mon Sep 17 00:00:00 2001 From: goat Date: Tue, 14 Apr 2020 22:21:33 +0200 Subject: [PATCH] feat: new item search window --- Dalamud/Dalamud.cs | 63 +++++----- Dalamud/Interface/ItemSearchWindow.cs | 169 ++++++++++++++++++++++++++ 2 files changed, 200 insertions(+), 32 deletions(-) create mode 100644 Dalamud/Interface/ItemSearchWindow.cs diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index 58e67d505..08394abd6 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -320,6 +320,17 @@ namespace Dalamud { this.isImguiDrawPluginWindow = this.pluginWindow != null && this.pluginWindow.Draw(); } + if (this.isImguiDrawItemSearchWindow) + { + this.isImguiDrawItemSearchWindow = this.itemSearchCommandWindow != null && this.itemSearchCommandWindow.Draw(); + + if (this.isImguiDrawItemSearchWindow == false) + { + this.itemSearchCommandWindow?.Dispose(); + this.itemSearchCommandWindow = null; + } + } + if (this.isImguiDrawCreditsWindow) { this.isImguiDrawCreditsWindow = this.creditsWindow != null && this.creditsWindow.Draw(); @@ -519,43 +530,31 @@ namespace Dalamud { Framework.Gui.SetBgm(ushort.Parse(arguments)); } + private ItemSearchWindow itemSearchCommandWindow; + private bool isImguiDrawItemSearchWindow; + private void OnItemLinkCommand(string command, string arguments) { - var exactSearch = false; - if (arguments.StartsWith("+")) - { - exactSearch = true; - arguments = arguments.Substring(1); - } + this.itemSearchCommandWindow = new ItemSearchWindow(this.Data, new UiBuilder(this.InterfaceManager, "ItemSearcher")); + this.itemSearchCommandWindow.OnItemChosen += (sender, item) => { + var hexData = new byte[] { + 0x02, 0x13, 0x06, 0xFE, 0xFF, 0xF3, 0xF3, 0xF3, 0x03, 0x02, 0x27, 0x07, 0x03, 0xF2, 0x3A, 0x2F, + 0x02, 0x01, 0x03, 0x02, 0x13, 0x06, 0xFE, 0xFF, 0xFF, 0x7B, 0x1A, 0x03, 0xEE, 0x82, 0xBB, 0x02, + 0x13, 0x02, 0xEC, 0x03 + }; - Task.Run(async () => { - try { - dynamic results = await XivApi.Search(arguments, "Item", 1, exactSearch); - var itemId = (short) results.Results[0].ID; - var itemName = (string)results.Results[0].Name; + var endTag = new byte[] { + 0x02, 0x27, 0x07, 0xCF, 0x01, 0x01, 0x01, 0xFF, 0x01, 0x03, 0x02, 0x13, 0x02, 0xEC, 0x03 + }; - var hexData = new byte[] { - 0x02, 0x13, 0x06, 0xFE, 0xFF, 0xF3, 0xF3, 0xF3, 0x03, 0x02, 0x27, 0x07, 0x03, 0xF2, 0x3A, 0x2F, - 0x02, 0x01, 0x03, 0x02, 0x13, 0x06, 0xFE, 0xFF, 0xFF, 0x7B, 0x1A, 0x03, 0xEE, 0x82, 0xBB, 0x02, - 0x13, 0x02, 0xEC, 0x03 - }; + BitConverter.GetBytes((short) item.RowId).Reverse().ToArray().CopyTo(hexData, 14); - var endTag = new byte[] { - 0x02, 0x27, 0x07, 0xCF, 0x01, 0x01, 0x01, 0xFF, 0x01, 0x03, 0x02, 0x13, 0x02, 0xEC, 0x03 - }; + hexData = hexData.Concat(Encoding.UTF8.GetBytes(item.Name)).Concat(endTag).ToArray(); - BitConverter.GetBytes(itemId).Reverse().ToArray().CopyTo(hexData, 14); - - hexData = hexData.Concat(Encoding.UTF8.GetBytes(itemName)).Concat(endTag).ToArray(); - - Framework.Gui.Chat.PrintChat(new XivChatEntry { - MessageBytes = hexData - }); - } - catch { - Framework.Gui.Chat.PrintError(Loc.Localize("DalamudItemNotFound", "Could not find item.")); - } - - }); + this.Framework.Gui.Chat.PrintChat(new XivChatEntry { + MessageBytes = hexData + }); + }; + this.isImguiDrawItemSearchWindow = true; } #if DEBUG diff --git a/Dalamud/Interface/ItemSearchWindow.cs b/Dalamud/Interface/ItemSearchWindow.cs new file mode 100644 index 000000000..15da2b609 --- /dev/null +++ b/Dalamud/Interface/ItemSearchWindow.cs @@ -0,0 +1,169 @@ +using System; +using System.Collections.Generic; +using System.Data.SqlTypes; +using System.Linq; +using System.Net.Mime; +using System.Numerics; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using CheapLoc; +using Dalamud.Data; +using Dalamud.Data.LuminaExtensions; +using Dalamud.Game.ClientState.Actors.Types; +using Dalamud.Game.ClientState.Actors.Types.NonPlayer; +using ImGuiNET; +using ImGuiScene; +using Lumina.Excel.GeneratedSheets; +using Serilog; +using Item = Dalamud.Data.TransientSheet.Item; + +namespace Dalamud.Interface +{ + class ItemSearchWindow : IDisposable + { + private readonly DataManager data; + private readonly UiBuilder builder; + + private string lastSearchText = string.Empty; + private string searchText = string.Empty; + + private int lastKind = 0; + private int currentKind = 0; + + private int selectedItemIndex = -1; + private TextureWrap selectedItemTex; + + private CancellationTokenSource searchCancelTokenSource; + private ValueTask> searchTask; + private List luminaItems; + + public event EventHandler OnItemChosen; + + public ItemSearchWindow(DataManager data, UiBuilder builder) { + this.data = data; + this.builder = builder; + + while (!data.IsDataReady) + Thread.Sleep(1); + + this.luminaItems = this.data.GetExcelSheet().GetRows(); + } + + public bool Draw() { + ImGui.SetNextWindowSize(new Vector2(500, 500), ImGuiCond.FirstUseEver); + + var isOpen = true; + + if (!ImGui.Begin(Loc.Localize("DalamudItemSelectHeader", "Select an item"), ref isOpen, ImGuiWindowFlags.NoCollapse)) + { + ImGui.End(); + return false; + } + + // Main window + ImGui.AlignTextToFramePadding(); + + ImGui.Text(Loc.Localize("DalamudItemSelect", "Please select an item.")); + if (this.selectedItemTex != null) { + ImGui.Text(" "); + + ImGui.SetCursorPosY(200f); + ImGui.SameLine(); + ImGui.Image(this.selectedItemTex.ImGuiHandle, new Vector2(40, 40)); + } else { + ImGui.Text(" "); + } + + ImGui.Separator(); + + + ImGui.Text("Search: "); + ImGui.SameLine(); + ImGui.InputText("##searchbox", ref this.searchText, 32); + + var kinds = new List {Loc.Localize("DalamudItemSelectAll", "All")}; + kinds.AddRange(this.data.GetExcelSheet().GetRows().Where(x => !string.IsNullOrEmpty(x.Name)).Select(x => x.Name)); + ImGui.Text(Loc.Localize("DalamudItemSelectCategory", "Category: ")); + ImGui.SameLine(); + ImGui.Combo("##kindbox", ref this.currentKind, kinds.ToArray(), + kinds.Count); + + + var windowSize = ImGui.GetWindowSize(); + ImGui.BeginChild("scrolling", new Vector2(0, windowSize.Y - ImGui.GetCursorPosY() - 40), true, ImGuiWindowFlags.HorizontalScrollbar); + + ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(0, 0)); + + if (!string.IsNullOrEmpty(this.searchText) || this.currentKind != 0) { + if (this.lastSearchText != this.searchText || this.lastKind != this.currentKind) { + this.lastSearchText = this.searchText; + this.lastKind = this.currentKind; + + this.searchCancelTokenSource?.Cancel(); + + this.searchCancelTokenSource = new CancellationTokenSource(); + + var asyncEnum = this.luminaItems.ToAsyncEnumerable(); + + if (!string.IsNullOrEmpty(this.searchText)) { + Log.Debug("Searching for " + this.searchText); + asyncEnum = asyncEnum.Where( + x => (x.Name.ToLower().Contains(this.searchText.ToLower()) || + int.TryParse(this.searchText, out var parsedId) && + parsedId == x.RowId)); + } + + if (this.currentKind != 0) { + Log.Debug("Searching for C" + this.currentKind); + asyncEnum = asyncEnum.Where(x => x.ItemSearchCategory == this.currentKind); + } + + this.selectedItemIndex = -1; + this.selectedItemTex?.Dispose(); + this.selectedItemTex = null; + + this.searchTask = asyncEnum.ToListAsync(this.searchCancelTokenSource.Token); + } + + if (this.searchTask.IsCompletedSuccessfully) { + for (var i = 0; i < this.searchTask.Result.Count; i++) { + if (ImGui.Selectable(this.searchTask.Result[i].Name, this.selectedItemIndex == i)) { + this.selectedItemIndex = i; + + var iconTex = this.data.GetIcon(this.searchTask.Result[i].Icon); + this.selectedItemTex?.Dispose(); + this.selectedItemTex = + this.builder.LoadImageRaw(iconTex.GetRgbaImageData(), iconTex.Header.Width, + iconTex.Header.Height, 4); + } + } + } + } else { + ImGui.TextColored(new Vector4(0.86f, 0.86f, 0.86f, 1.00f), Loc.Localize("DalamudItemSelectHint", "Type to start searching...")); + + this.selectedItemIndex = -1; + this.selectedItemTex?.Dispose(); + this.selectedItemTex = null; + } + + ImGui.PopStyleVar(); + + ImGui.EndChild(); + + if (ImGui.Button(Loc.Localize("Choose", "Choose"))) { + OnItemChosen?.Invoke(this, this.searchTask.Result[this.selectedItemIndex]); + this.selectedItemTex?.Dispose(); + isOpen = false; + } + + ImGui.End(); + + return isOpen; + } + + public void Dispose() { + this.selectedItemTex?.Dispose(); + } + } +}