From 592892e45af2b795342e976ec4d05c8b119c8657 Mon Sep 17 00:00:00 2001 From: Infi Date: Mon, 20 May 2024 06:25:54 +0200 Subject: [PATCH] - New option to limit minimum preview length - New option only preview with parameters - Improve preview drawing modes - Prevent null ref on plugin load --- ChatTwo/Configuration.cs | 4 + ChatTwo/GameFunctions/Chat.cs | 2 +- ChatTwo/Plugin.cs | 1 + ChatTwo/Resources/Language.Designer.cs | 40 ++++++++- ChatTwo/Resources/Language.resx | 16 +++- ChatTwo/Ui/ChatLogWindow.cs | 8 +- ChatTwo/Ui/InputPreview.cs | 106 +++++++++++++---------- ChatTwo/Ui/SettingsTabs/Miscellaneous.cs | 16 +++- 8 files changed, 140 insertions(+), 53 deletions(-) diff --git a/ChatTwo/Configuration.cs b/ChatTwo/Configuration.cs index fe46f43..766317f 100755 --- a/ChatTwo/Configuration.cs +++ b/ChatTwo/Configuration.cs @@ -25,6 +25,8 @@ internal class Configuration : IPluginConfiguration public bool HideSameTimestamps; public bool ShowNoviceNetwork; public bool SidebarTabView; + public bool OnlyPreviewIf; + public int PreviewMinimum = 1; public PreviewPosition PreviewPosition = PreviewPosition.Inside; public CommandHelpSide CommandHelpSide = CommandHelpSide.None; public KeybindMode KeybindMode = KeybindMode.Strict; @@ -79,6 +81,8 @@ internal class Configuration : IPluginConfiguration HideSameTimestamps = other.HideSameTimestamps; ShowNoviceNetwork = other.ShowNoviceNetwork; SidebarTabView = other.SidebarTabView; + OnlyPreviewIf = other.OnlyPreviewIf; + PreviewMinimum = other.PreviewMinimum; PreviewPosition = other.PreviewPosition; CommandHelpSide = other.CommandHelpSide; KeybindMode = other.KeybindMode; diff --git a/ChatTwo/GameFunctions/Chat.cs b/ChatTwo/GameFunctions/Chat.cs index cda932a..bb94c12 100755 --- a/ChatTwo/GameFunctions/Chat.cs +++ b/ChatTwo/GameFunctions/Chat.cs @@ -461,7 +461,7 @@ internal sealed unsafe class Chat : IDisposable private byte ChatLogRefreshDetour(IntPtr log, ushort eventId, AtkValue* value) { - if (Plugin.ChatLogWindow.CurrentTab is { InputDisabled: true }) + if (Plugin is { ChatLogWindow.CurrentTab.InputDisabled: true }) return ChatLogRefreshHook!.Original(log, eventId, value); if (eventId != 0x31 || value == null || value->UInt is not (0x05 or 0x0C)) diff --git a/ChatTwo/Plugin.cs b/ChatTwo/Plugin.cs index a2c0021..1e6359a 100755 --- a/ChatTwo/Plugin.cs +++ b/ChatTwo/Plugin.cs @@ -152,6 +152,7 @@ public sealed class Plugin : IDalamudPlugin WindowSystem?.RemoveAllWindows(); ChatLogWindow?.Dispose(); + InputPreview?.Dispose(); SettingsWindow?.Dispose(); DebuggerWindow?.Dispose(); SeStringDebugger?.Dispose(); diff --git a/ChatTwo/Resources/Language.Designer.cs b/ChatTwo/Resources/Language.Designer.cs index 8e9b190..6c64de9 100755 --- a/ChatTwo/Resources/Language.Designer.cs +++ b/ChatTwo/Resources/Language.Designer.cs @@ -2400,7 +2400,7 @@ namespace ChatTwo.Resources { } /// - /// Looks up a localized string similar to A preview wih all emote, auto-translate encoded as they appear in chat. + /// Looks up a localized string similar to Displays a preview with special parameter evaluated, like emotes and <item>. /// internal static string Options_Preview_Description { get { @@ -2427,7 +2427,7 @@ namespace ChatTwo.Resources { } /// - /// Looks up a localized string similar to Input preview. + /// Looks up a localized string similar to Text preview. /// internal static string Options_Preview_Name { get { @@ -2462,6 +2462,42 @@ namespace ChatTwo.Resources { } } + /// + /// Looks up a localized string similar to Show only if the text length is greater-than or equal. + /// + internal static string Options_PreviewMinimum_Description { + get { + return ResourceManager.GetString("Options_PreviewMinimum_Description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Minimum input length. + /// + internal static string Options_PreviewMinimum_Name { + get { + return ResourceManager.GetString("Options_PreviewMinimum_Name", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Show only if the text contains special parameter. + /// + internal static string Options_PreviewOnlyIf_Description { + get { + return ResourceManager.GetString("Options_PreviewOnlyIf_Description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Only with parameter. + /// + internal static string Options_PreviewOnlyIf_Name { + get { + return ResourceManager.GetString("Options_PreviewOnlyIf_Name", resourceCulture); + } + } + /// /// Looks up a localized string similar to Replaces words with their emote version, currently supports BetterTTV. /// diff --git a/ChatTwo/Resources/Language.resx b/ChatTwo/Resources/Language.resx index a9ce015..c68747e 100644 --- a/ChatTwo/Resources/Language.resx +++ b/ChatTwo/Resources/Language.resx @@ -1052,10 +1052,10 @@ Emotes available: - A preview wih all emote, auto-translate encoded as they appear in chat + Displays a preview with special parameter evaluated, like emotes and <item> - Input preview + Text preview None @@ -1075,4 +1075,16 @@ Tooltip + + Only with parameter + + + Show only if the text contains special parameter + + + Minimum input length + + + Show only if the text length is greater-than or equal + diff --git a/ChatTwo/Ui/ChatLogWindow.cs b/ChatTwo/Ui/ChatLogWindow.cs index 96e5cbe..7886d75 100644 --- a/ChatTwo/Ui/ChatLogWindow.cs +++ b/ChatTwo/Ui/ChatLogWindow.cs @@ -501,6 +501,7 @@ public sealed class ChatLogWindow : Window DrawAutoComplete(); } + private static bool IsChatMode => Plugin.Config.PreviewPosition is PreviewPosition.Inside or PreviewPosition.Tooltip; private unsafe void DrawChatLog() { // Position change has applied, so we set it to null again @@ -517,7 +518,7 @@ public sealed class ChatLogWindow : Window LastViewport = ImGui.GetWindowViewport().NativePtr; WasDocked = ImGui.IsWindowDocked(); - if (Plugin.Config.PreviewPosition is PreviewPosition.Inside or PreviewPosition.Tooltip) + if (IsChatMode && Plugin.InputPreview.IsDrawable) Plugin.InputPreview.CalculatePreview(); var currentTab = Plugin.Config.SidebarTabView ? DrawTabSidebar() : DrawTabBar(); @@ -526,7 +527,7 @@ public sealed class ChatLogWindow : Window if (currentTab > -1 && currentTab < Plugin.Config.Tabs.Count) activeTab = Plugin.Config.Tabs[currentTab]; - if (Plugin.Config.PreviewPosition is PreviewPosition.Inside) + if (Plugin.Config.PreviewPosition is PreviewPosition.Inside && Plugin.InputPreview.IsDrawable) Plugin.InputPreview.DrawPreview(); using (ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)) @@ -701,7 +702,8 @@ public sealed class ChatLogWindow : Window ImGui.InputTextWithHint("##chat2-input", isChatEnabled ? "": Language.ChatLog_DisabledInput, ref Chat, 500, flags, Callback); } - if (Plugin.Config.PreviewPosition is PreviewPosition.Tooltip && !string.IsNullOrEmpty(Chat) && ImGui.IsItemHovered()) + var tooltipDraw = Plugin.Config.PreviewPosition is PreviewPosition.Tooltip && Plugin.InputPreview.IsDrawable; + if (tooltipDraw && ImGui.IsItemHovered()) { ImGui.SetNextWindowSize(new Vector2(500 * ImGuiHelpers.GlobalScale, -1)); using var tooltip = ImRaii.Tooltip(); diff --git a/ChatTwo/Ui/InputPreview.cs b/ChatTwo/Ui/InputPreview.cs index d738a0a..133fba4 100644 --- a/ChatTwo/Ui/InputPreview.cs +++ b/ChatTwo/Ui/InputPreview.cs @@ -9,6 +9,7 @@ using Dalamud.Game.Text.SeStringHandling; using Dalamud.Game.Text.SeStringHandling.Payloads; using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Windowing; +using Dalamud.Plugin.Services; using ImGuiNET; namespace ChatTwo.Ui; @@ -17,14 +18,17 @@ public class InputPreview : Window { private ChatLogWindow LogWindow { get; } + private bool Drawing; + private bool HasEvaluation; internal float PreviewHeight; private int LastLength; private Message? PreviewMessage; - private bool NextChunkIsAutoTranslate; private int CursorPosition; - public int SelectedCursorPos = -1; + private bool NextChunkIsAutoTranslate; + + internal int SelectedCursorPos = -1; internal InputPreview(ChatLogWindow logWindow) : base("##chat2-inputpreview") { @@ -36,6 +40,49 @@ public class InputPreview : Window RespectCloseHotkey = false; DisableWindowSounds = true; IsOpen = true; + + Plugin.Framework.Update += UpdateConditionCheck; + } + + public void Dispose() + { + Plugin.Framework.Update -= UpdateConditionCheck; + } + + private bool ValidDraw => !string.IsNullOrEmpty(LogWindow.Chat) && LogWindow.Chat.Length >= Plugin.Config.PreviewMinimum; + private void UpdateConditionCheck(IFramework framework) + { + Drawing = ValidDraw; + if (!Drawing) + { + LastLength = 0; + PreviewHeight = 0; + PreviewMessage = null; + HasEvaluation = false; + + return; + } + + if (PreviewMessage == null || LastLength != LogWindow.Chat.Length) + { + LastLength = LogWindow.Chat.Length; + + var bytes = Encoding.UTF8.GetBytes(LogWindow.Chat.Trim()); + AutoTranslate.ReplaceWithPayload(ref bytes); + + var chunks = ChunkUtil.ToChunks(SeString.Parse(bytes), ChunkSource.Content, ChatType.Say).ToList(); + PreviewMessage = Message.FakeMessage(chunks, new ChatCode((ushort)XivChatType.Say)); + PreviewMessage.DecodeTextParam(); + } + HasEvaluation = !Plugin.Config.OnlyPreviewIf || PreviewMessage.Content.Count > 1; + } + + internal bool IsDrawable => ValidDraw && HasEvaluation; + + private static bool IsWindowMode => Plugin.Config.PreviewPosition is PreviewPosition.Top or PreviewPosition.Bottom; + public override bool DrawConditions() + { + return IsWindowMode && IsDrawable; } public override void PreDraw() @@ -56,11 +103,6 @@ public class InputPreview : Window PositionCondition = ImGuiCond.Always; } - public override bool DrawConditions() - { - return Plugin.Config.PreviewPosition is PreviewPosition.Top or PreviewPosition.Bottom && !string.IsNullOrEmpty(LogWindow.Chat); - } - public override void Draw() { CalculatePreview(); @@ -71,54 +113,30 @@ public class InputPreview : Window { // We Pre-draw this once to get the actual height :HideThePain: PreviewHeight = 0; - if (!string.IsNullOrEmpty(LogWindow.Chat)) + + var pos = ImGui.GetCursorPos(); + ImGui.SetCursorPos(new Vector2(-500, -500)); + var before = ImGui.GetCursorPosY(); + using (ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)) { - if (PreviewMessage == null || LastLength != LogWindow.Chat.Length) - { - LastLength = LogWindow.Chat.Length; - - var bytes = Encoding.UTF8.GetBytes(LogWindow.Chat.Trim()); - AutoTranslate.ReplaceWithPayload(ref bytes); - - var chunks = ChunkUtil.ToChunks(SeString.Parse(bytes), ChunkSource.Content, ChatType.Say).ToList(); - PreviewMessage = Message.FakeMessage(chunks, new ChatCode((ushort)XivChatType.Say)); - PreviewMessage.DecodeTextParam(); - } - - var pos = ImGui.GetCursorPos(); - ImGui.SetCursorPos(new Vector2(-500, -500)); - var before = ImGui.GetCursorPosY(); - using (ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)) - { - ImGui.TextUnformatted(Language.Options_Preview_Header); - DrawChunksPreview(PreviewMessage.Content); - } - var after = ImGui.GetCursorPosY(); - ImGui.SetCursorPos(pos); - - PreviewHeight = after - before; - PreviewHeight += Plugin.Config.PreviewPosition is not PreviewPosition.Inside - ? ImGui.GetStyle().WindowPadding.Y * 2 - : 0; - } - else - { - LastLength = 0; - PreviewMessage = null; + ImGui.TextUnformatted(Language.Options_Preview_Header); + DrawChunksPreview(PreviewMessage!.Content); } + var after = ImGui.GetCursorPosY(); + ImGui.SetCursorPos(pos); + + PreviewHeight = after - before; + PreviewHeight += IsWindowMode ? ImGui.GetStyle().WindowPadding.Y * 2 : 0; } internal void DrawPreview() { - if (PreviewMessage == null) - return; - using (ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)) { ImGui.TextUnformatted(Language.Options_Preview_Header); var handler = LogWindow.HandlerLender.Borrow(); - DrawChunksPreview(PreviewMessage.Content, handler, unique: 10000); + DrawChunksPreview(PreviewMessage!.Content, handler, unique: 10000); handler.Draw(); } } diff --git a/ChatTwo/Ui/SettingsTabs/Miscellaneous.cs b/ChatTwo/Ui/SettingsTabs/Miscellaneous.cs index 03944f3..f9e3d1b 100755 --- a/ChatTwo/Ui/SettingsTabs/Miscellaneous.cs +++ b/ChatTwo/Ui/SettingsTabs/Miscellaneous.cs @@ -22,6 +22,9 @@ internal sealed class Miscellaneous(Configuration mutable) : ISettingsTab } ImGuiUtil.HelpText(string.Format(Language.Options_Language_Description, Plugin.PluginName)); + + ImGui.Spacing(); + ImGui.Separator(); ImGui.Spacing(); using (var combo = ImGuiUtil.BeginComboVertical(Language.Options_Preview_Name, Mutable.PreviewPosition.Name())) @@ -33,10 +36,21 @@ internal sealed class Miscellaneous(Configuration mutable) : ISettingsTab Mutable.PreviewPosition = position; } } - ImGuiUtil.HelpText(Language.Options_Preview_Description); ImGui.Spacing(); + if (Mutable.PreviewPosition is not PreviewPosition.None) + { + ImGuiUtil.OptionCheckbox(ref Mutable.OnlyPreviewIf, Language.Options_PreviewOnlyIf_Name, Language.Options_PreviewOnlyIf_Description); + ImGui.Spacing(); + if (ImGuiUtil.InputIntVertical(Language.Options_PreviewMinimum_Name, Language.Options_PreviewMinimum_Description, ref Mutable.PreviewMinimum)) + Mutable.PreviewMinimum = Math.Clamp(Mutable.PreviewMinimum, 1, 250); + } + + ImGui.Spacing(); + ImGui.Separator(); + ImGui.Spacing(); + using (var combo = ImGuiUtil.BeginComboVertical(Language.Options_CommandHelpSide_Name, Mutable.CommandHelpSide.Name())) { if (combo)