diff --git a/Penumbra/CommandHandler.cs b/Penumbra/CommandHandler.cs index 484dd954..db8d9aca 100644 --- a/Penumbra/CommandHandler.cs +++ b/Penumbra/CommandHandler.cs @@ -12,6 +12,7 @@ using Penumbra.Interop.Services; using Penumbra.Mods; using Penumbra.Mods.Manager; using Penumbra.UI; +using Penumbra.UI.Knowledge; namespace Penumbra; @@ -29,11 +30,12 @@ public class CommandHandler : IDisposable, IApiService private readonly CollectionManager _collectionManager; private readonly Penumbra _penumbra; private readonly CollectionEditor _collectionEditor; + private readonly KnowledgeWindow _knowledgeWindow; public CommandHandler(IFramework framework, ICommandManager commandManager, IChatGui chat, RedrawService redrawService, - Configuration config, - ConfigWindow configWindow, ModManager modManager, CollectionManager collectionManager, ActorManager actors, Penumbra penumbra, - CollectionEditor collectionEditor) + Configuration config, ConfigWindow configWindow, ModManager modManager, CollectionManager collectionManager, ActorManager actors, + Penumbra penumbra, + CollectionEditor collectionEditor, KnowledgeWindow knowledgeWindow) { _commandManager = commandManager; _redrawService = redrawService; @@ -45,6 +47,7 @@ public class CommandHandler : IDisposable, IApiService _chat = chat; _penumbra = penumbra; _collectionEditor = collectionEditor; + _knowledgeWindow = knowledgeWindow; framework.RunOnFrameworkThread(() => { if (_commandManager.Commands.ContainsKey(CommandName)) @@ -69,7 +72,7 @@ public class CommandHandler : IDisposable, IApiService var argumentList = arguments.Split(' ', 2); arguments = argumentList.Length == 2 ? argumentList[1] : string.Empty; - var _ = argumentList[0].ToLowerInvariant() switch + _ = argumentList[0].ToLowerInvariant() switch { "window" => ToggleWindow(arguments), "enable" => SetPenumbraState(arguments, true), @@ -83,6 +86,7 @@ public class CommandHandler : IDisposable, IApiService "collection" => SetCollection(arguments), "mod" => SetMod(arguments), "bulktag" => SetTag(arguments), + "knowledge" => HandleKnowledge(arguments), _ => PrintHelp(argumentList[0]), }; } @@ -304,7 +308,7 @@ public class CommandHandler : IDisposable, IApiService identifiers = _actors.FromUserString(split[2], false); } } - catch (ActorManager.IdentifierParseError e) + catch (ActorIdentifierFactory.IdentifierParseError e) { _chat.Print(new SeStringBuilder().AddText("The argument ").AddRed(split[2], true) .AddText($" could not be converted to an identifier. {e.Message}") @@ -619,4 +623,10 @@ public class CommandHandler : IDisposable, IApiService if (_config.PrintSuccessfulCommandsToChat) _chat.Print(text()); } + + private bool HandleKnowledge(string arguments) + { + _knowledgeWindow.Toggle(); + return true; + } } diff --git a/Penumbra/UI/Knowledge/IKnowledgeTab.cs b/Penumbra/UI/Knowledge/IKnowledgeTab.cs new file mode 100644 index 00000000..568d5fda --- /dev/null +++ b/Penumbra/UI/Knowledge/IKnowledgeTab.cs @@ -0,0 +1,8 @@ +namespace Penumbra.UI.Knowledge; + +public interface IKnowledgeTab +{ + public ReadOnlySpan Name { get; } + public ReadOnlySpan SearchTags { get; } + public void Draw(); +} diff --git a/Penumbra/UI/Knowledge/KnowledgeWindow.cs b/Penumbra/UI/Knowledge/KnowledgeWindow.cs new file mode 100644 index 00000000..de1b36b8 --- /dev/null +++ b/Penumbra/UI/Knowledge/KnowledgeWindow.cs @@ -0,0 +1,55 @@ +using System.Text.Unicode; +using Dalamud.Interface.Utility.Raii; +using Dalamud.Interface.Windowing; +using Dalamud.Memory; +using ImGuiNET; +using OtterGui.Services; +using OtterGui.Text; + +namespace Penumbra.UI.Knowledge; + +/// Draw the progress information for import. +public sealed class KnowledgeWindow() : Window("Penumbra Knowledge Window"), IUiService +{ + private readonly IReadOnlyList _tabs = + [ + new RaceCodeTab(), + ]; + + private IKnowledgeTab? _selected; + private readonly byte[] _filterStore = new byte[256]; + + private TerminatedByteString _filter = TerminatedByteString.Empty; + + public override void Draw() + { + DrawSelector(); + ImUtf8.SameLineInner(); + DrawMain(); + } + + private void DrawSelector() + { + using var child = ImUtf8.Child("KnowledgeSelector"u8, new Vector2(250 * ImUtf8.GlobalScale, ImGui.GetContentRegionAvail().Y), true); + if (!child) + return; + + ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X); + ImUtf8.InputText("##Filter"u8, _filterStore, out _filter, "Filter..."u8); + + foreach (var tab in _tabs) + { + if (ImUtf8.Selectable(tab.Name, _selected == tab)) + _selected = tab; + } + } + + private void DrawMain() + { + using var child = ImUtf8.Child("KnowledgeMain"u8, ImGui.GetContentRegionAvail(), true); + if (!child || _selected == null) + return; + + _selected.Draw(); + } +} diff --git a/Penumbra/UI/Knowledge/RaceCodeTab.cs b/Penumbra/UI/Knowledge/RaceCodeTab.cs new file mode 100644 index 00000000..988506dd --- /dev/null +++ b/Penumbra/UI/Knowledge/RaceCodeTab.cs @@ -0,0 +1,42 @@ +using ImGuiNET; +using OtterGui.Text; +using Penumbra.GameData.Enums; + +namespace Penumbra.UI.Knowledge; + +public sealed class RaceCodeTab : IKnowledgeTab +{ + public ReadOnlySpan Name + => "Race Codes"u8; + + public ReadOnlySpan SearchTags + => "deformersracecodesmodel"u8; + + public void Draw() + { + using var table = ImUtf8.Table("table"u8, 4, ImGuiTableFlags.SizingFixedFit); + if (!table) + return; + + ImUtf8.TableHeader("Race Code"u8); + ImUtf8.TableHeader("Race"u8); + ImUtf8.TableHeader("Gender"u8); + ImUtf8.TableHeader("NPC"u8); + + foreach (var genderRace in Enum.GetValues()) + { + ImGui.TableNextColumn(); + ImUtf8.Text(genderRace.ToRaceCode()); + + var (gender, race) = genderRace.Split(); + ImGui.TableNextColumn(); + ImUtf8.Text($"{race}"); + + ImGui.TableNextColumn(); + ImUtf8.Text($"{gender}"); + + ImGui.TableNextColumn(); + ImUtf8.Text(((ushort)genderRace & 0xF) != 1 ? "NPC"u8 : "Normal"u8); + } + } +} diff --git a/Penumbra/UI/WindowSystem.cs b/Penumbra/UI/WindowSystem.cs index 72ac0d01..6d382ad4 100644 --- a/Penumbra/UI/WindowSystem.cs +++ b/Penumbra/UI/WindowSystem.cs @@ -3,6 +3,7 @@ using Dalamud.Interface.Windowing; using Dalamud.Plugin; using OtterGui.Services; using Penumbra.UI.AdvancedWindow; +using Penumbra.UI.Knowledge; using Penumbra.UI.Tabs.Debug; namespace Penumbra.UI; @@ -14,20 +15,24 @@ public class PenumbraWindowSystem : IDisposable, IUiService private readonly FileDialogService _fileDialog; public readonly ConfigWindow Window; public readonly PenumbraChangelog Changelog; + public readonly KnowledgeWindow KnowledgeWindow; public PenumbraWindowSystem(IDalamudPluginInterface pi, Configuration config, PenumbraChangelog changelog, ConfigWindow window, - LaunchButton _, ModEditWindow editWindow, FileDialogService fileDialog, ImportPopup importPopup, DebugTab debugTab) + LaunchButton _, ModEditWindow editWindow, FileDialogService fileDialog, ImportPopup importPopup, DebugTab debugTab, + KnowledgeWindow knowledgeWindow) { - _uiBuilder = pi.UiBuilder; - _fileDialog = fileDialog; - Changelog = changelog; - Window = window; - _windowSystem = new WindowSystem("Penumbra"); + _uiBuilder = pi.UiBuilder; + _fileDialog = fileDialog; + KnowledgeWindow = knowledgeWindow; + Changelog = changelog; + Window = window; + _windowSystem = new WindowSystem("Penumbra"); _windowSystem.AddWindow(changelog.Changelog); _windowSystem.AddWindow(window); _windowSystem.AddWindow(editWindow); _windowSystem.AddWindow(importPopup); _windowSystem.AddWindow(debugTab); + _windowSystem.AddWindow(KnowledgeWindow); _uiBuilder.OpenMainUi += Window.Toggle; _uiBuilder.OpenConfigUi += Window.OpenSettings; _uiBuilder.Draw += _windowSystem.Draw;