diff --git a/HellionChat/Plugin.cs b/HellionChat/Plugin.cs index 8186012..bbfad53 100755 --- a/HellionChat/Plugin.cs +++ b/HellionChat/Plugin.cs @@ -98,7 +98,7 @@ public sealed class Plugin : IAsyncDalamudPlugin internal Ui.Windows.MainWindow MainWindow { get; private set; } = null!; internal Ui.Windows.SettingsWindow SettingsWindow { get; private set; } = null!; public DbViewer DbViewer { get; private set; } = null!; - internal InputPreview InputPreview { get; private set; } = null!; + internal static InputPreview InputPreview { get; private set; } = null!; internal CommandHelpWindow CommandHelpWindow { get; private set; } = null!; public SeStringDebugger SeStringDebugger { get; private set; } = null!; public FirstRunWizard FirstRunWizard { get; private set; } = null!; diff --git a/HellionChat/PluginLifecycle.cs b/HellionChat/PluginLifecycle.cs index be02506..855d24a 100644 --- a/HellionChat/PluginLifecycle.cs +++ b/HellionChat/PluginLifecycle.cs @@ -61,7 +61,7 @@ internal sealed class PluginLifecycle : IAsyncDisposable plugin.WindowSystem.AddWindow(plugin.MainWindow); plugin.WindowSystem.AddWindow(plugin.SettingsWindow); plugin.WindowSystem.AddWindow(plugin.DbViewer); - plugin.WindowSystem.AddWindow(plugin.InputPreview); + plugin.WindowSystem.AddWindow(Plugin.InputPreview); plugin.WindowSystem.AddWindow(plugin.CommandHelpWindow); plugin.WindowSystem.AddWindow(plugin.SeStringDebugger); plugin.WindowSystem.AddWindow(plugin.DebuggerWindow); diff --git a/HellionChat/Ui/Components/InputBar.cs b/HellionChat/Ui/Components/InputBar.cs index 384d404..502c607 100644 --- a/HellionChat/Ui/Components/InputBar.cs +++ b/HellionChat/Ui/Components/InputBar.cs @@ -37,6 +37,7 @@ internal sealed class InputBar private string _pendingMessage = string.Empty; private bool _isFocused; + private bool _wasInputTextHovered; private bool? _isFocusedOverride; // Test-only; null = honour per-frame Draw() value. public bool Activate; @@ -74,6 +75,10 @@ internal sealed class InputBar // rest of the component doesn't need. public bool IsFocused => _isFocusedOverride ?? _isFocused; + // Sampled in DrawInputField() right after ImGui.InputText so the value + // reflects the text widget, not a later QuickButton item. + public bool WasInputTextHovered => _wasInputTextHovered; + public void ClearBuffer() => _pendingMessage = string.Empty; // BufferCapacity is an ImGui UX limit, not a protocol constraint. We @@ -235,6 +240,7 @@ internal sealed class InputBar TrySend(activeTab); } _isFocused = ImGui.IsItemFocused(); + _wasInputTextHovered = ImGui.IsItemHovered(); } // v1.5.6 character-level slash-detect: fires on every edit so CommandHelpWindow diff --git a/HellionChat/Ui/InputPreview.cs b/HellionChat/Ui/InputPreview.cs index 12fa020..28af46e 100644 --- a/HellionChat/Ui/InputPreview.cs +++ b/HellionChat/Ui/InputPreview.cs @@ -141,7 +141,7 @@ internal sealed class InputPreview : Window DrawPreview(); } - private void CalculatePreviewHeight() + internal void CalculatePreviewHeight() { // Pre-draw offscreen once to measure actual rendered height; value is // consumed next frame by PreDraw() for window sizing. @@ -162,7 +162,7 @@ internal sealed class InputPreview : Window PreviewHeight += IsWindowMode ? ImGui.GetStyle().WindowPadding.Y * 2 : 0; } - private void DrawPreview() + internal void DrawPreview() { using (ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero)) { diff --git a/HellionChat/Ui/Windows/MainWindow.cs b/HellionChat/Ui/Windows/MainWindow.cs index a434eb7..d81bfe3 100644 --- a/HellionChat/Ui/Windows/MainWindow.cs +++ b/HellionChat/Ui/Windows/MainWindow.cs @@ -1,5 +1,6 @@ using System.Numerics; using Dalamud.Bindings.ImGui; +using Dalamud.Interface.Utility; using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Windowing; using HellionChat.Util; @@ -138,12 +139,51 @@ internal sealed class MainWindow : Window { var inputHeight = Components.InputBar.Height; - using (var messages = ImRaii.Child("##hellion-main-area", new Vector2(-1f, -inputHeight))) + // Shrink the message child when Inside-mode preview is active so the + // inline preview block does not overlap the message list. PreviewHeight + // lags one frame behind on the very first keystroke (same as v1.5.6). + var previewHeight = + Plugin.Config.PreviewPosition is PreviewPosition.Inside + && Plugin.InputPreview.IsDrawable + ? Plugin.InputPreview.PreviewHeight + : 0f; + + using ( + var messages = ImRaii.Child( + "##hellion-main-area", + new Vector2(-1f, -(inputHeight + previewHeight)) + ) + ) { if (messages.Success) _messages.Draw(_activeTab!); } + // Inside-mode inline render: measure first so PreviewHeight is fresh + // for the next frame's reservation, then draw between messages and input. + if ( + Plugin.Config.PreviewPosition is PreviewPosition.Inside + && Plugin.InputPreview.IsDrawable + ) + { + Plugin.InputPreview.CalculatePreviewHeight(); + Plugin.InputPreview.DrawPreview(); + } + _input.Draw(_activeTab); + + // Tooltip-mode: sampled hover-state from InputBar reflects the actual + // InputText widget (after-Draw IsItemHovered would target a QuickButton). + // ImRaii.Tooltip has no Success guard — BeginTooltip always runs in ctor. + if ( + Plugin.Config.PreviewPosition is PreviewPosition.Tooltip + && Plugin.InputPreview.IsDrawable + && _input.WasInputTextHovered + ) + { + ImGui.SetNextWindowSize(new Vector2(500 * ImGuiHelpers.GlobalScale, -1)); + using var tooltip = ImRaii.Tooltip(); + Plugin.InputPreview.DrawPreview(); + } } }