diff --git a/Dalamud/Game/Gui/Dtr/DtrBarEntry.cs b/Dalamud/Game/Gui/Dtr/DtrBarEntry.cs
index a2fa73ec6..651f59b1b 100644
--- a/Dalamud/Game/Gui/Dtr/DtrBarEntry.cs
+++ b/Dalamud/Game/Gui/Dtr/DtrBarEntry.cs
@@ -26,12 +26,12 @@ public interface IReadOnlyDtrBarEntry
///
/// Gets the text of this entry.
///
- public SeString Text { get; }
+ public SeString? Text { get; }
///
/// Gets a tooltip to be shown when the user mouses over the dtr entry.
///
- public SeString Tooltip { get; }
+ public SeString? Tooltip { get; }
///
/// Gets a value indicating whether this entry should be shown.
diff --git a/Dalamud/Interface/ImGuiSeStringRenderer/Internal/SeStringRenderer.cs b/Dalamud/Interface/ImGuiSeStringRenderer/Internal/SeStringRenderer.cs
index bdd1f30d8..380afc6c9 100644
--- a/Dalamud/Interface/ImGuiSeStringRenderer/Internal/SeStringRenderer.cs
+++ b/Dalamud/Interface/ImGuiSeStringRenderer/Internal/SeStringRenderer.cs
@@ -225,13 +225,8 @@ internal unsafe class SeStringRenderer : IInternalDisposableService
this.fragments.Clear();
this.colorStackSet.Initialize(ref state);
- // Handle cases where ImGui.AlignTextToFramePadding has been called.
- var pCurrentWindow = *(nint*)(ImGui.GetCurrentContext() + ImGuiContextCurrentWindowOffset);
- var pWindowDc = pCurrentWindow + ImGuiWindowDcOffset;
- var currLineTextBaseOffset = *(float*)(pWindowDc + ImGuiWindowTempDataCurrLineTextBaseOffset);
-
// Analyze the provided SeString and break it up to text fragments.
- this.CreateTextFragments(ref state, currLineTextBaseOffset);
+ this.CreateTextFragments(ref state);
var fragmentSpan = CollectionsMarshal.AsSpan(this.fragments);
// Calculate size.
@@ -245,6 +240,18 @@ internal unsafe class SeStringRenderer : IInternalDisposableService
state.SplitDrawList();
+ // Handle cases where ImGui.AlignTextToFramePadding has been called.
+ var pCurrentWindow = *(nint*)(ImGui.GetCurrentContext() + ImGuiContextCurrentWindowOffset);
+ var pWindowDc = pCurrentWindow + ImGuiWindowDcOffset;
+ var currLineTextBaseOffset = *(float*)(pWindowDc + ImGuiWindowTempDataCurrLineTextBaseOffset);
+ var itemSize = size;
+ if (currLineTextBaseOffset != 0f)
+ {
+ itemSize.Y += 2 * currLineTextBaseOffset;
+ foreach (ref var f in fragmentSpan)
+ f.Offset += new Vector2(0, currLineTextBaseOffset);
+ }
+
// Draw all text fragments.
var lastRune = default(Rune);
foreach (ref var f in fragmentSpan)
@@ -259,7 +266,7 @@ internal unsafe class SeStringRenderer : IInternalDisposableService
// Create an ImGui item, if a target draw list is not manually set.
if (drawParams.TargetDrawList is null)
- ImGui.Dummy(size);
+ ImGui.Dummy(itemSize);
// Handle link interactions.
var clicked = false;
@@ -296,7 +303,7 @@ internal unsafe class SeStringRenderer : IInternalDisposableService
if (!invisibleButtonDrawn)
{
ImGui.SetCursorScreenPos(state.ScreenOffset);
- clicked = ImGui.InvisibleButton("##text", size, buttonFlags);
+ clicked = ImGui.InvisibleButton("##text", itemSize, buttonFlags);
}
ImGui.PopID();
@@ -369,12 +376,10 @@ internal unsafe class SeStringRenderer : IInternalDisposableService
/// Creates text fragment, taking line and word breaking into account.
/// Draw state.
- /// Y offset adjustment for all text fragments. Used to honor
- /// .
- private void CreateTextFragments(ref SeStringDrawState state, float baseY)
+ private void CreateTextFragments(ref SeStringDrawState state)
{
var prev = 0;
- var xy = new Vector2(0, baseY);
+ var xy = Vector2.Zero;
var w = 0f;
var link = -1;
foreach (var (breakAt, mandatory) in new LineBreakEnumerator(state.Span, UtfEnumeratorFlags.Utf8SeString))
diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/SeStringRendererTestWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/SeStringRendererTestWidget.cs
index 2119ebc4d..17aba0c71 100644
--- a/Dalamud/Interface/Internal/Windows/Data/Widgets/SeStringRendererTestWidget.cs
+++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/SeStringRendererTestWidget.cs
@@ -38,6 +38,7 @@ internal unsafe class SeStringRendererTestWidget : IDataWindowWidget
private SeStringDrawParams style;
private bool interactable;
private bool useEntity;
+ private bool alignToFramePadding;
///
public string DisplayName { get; init; } = "SeStringRenderer Test";
@@ -56,6 +57,7 @@ internal unsafe class SeStringRendererTestWidget : IDataWindowWidget
this.logkind = null;
this.testString = string.Empty;
this.interactable = this.useEntity = true;
+ this.alignToFramePadding = false;
this.Ready = true;
}
@@ -143,6 +145,11 @@ internal unsafe class SeStringRendererTestWidget : IDataWindowWidget
if (ImGui.Checkbox("Use Entity Replacements", ref t))
this.useEntity = t;
+ ImGui.SameLine();
+ t = this.alignToFramePadding;
+ if (ImGui.Checkbox("Align to Frame Padding", ref t))
+ this.alignToFramePadding = t;
+
if (ImGui.CollapsingHeader("LogKind Preview"))
{
if (this.logkind is null)
@@ -284,7 +291,9 @@ internal unsafe class SeStringRendererTestWidget : IDataWindowWidget
if (this.testString == string.Empty && this.testStringBuffer.Length != 0)
this.testString = Encoding.UTF8.GetString(this.testStringBuffer.DataSpan);
- ImGui.Separator();
+ if (this.alignToFramePadding)
+ ImGui.AlignTextToFramePadding();
+
if (this.interactable)
{
if (ImGuiHelpers.CompileSeStringWrapped(this.testString, this.style, new("this is an ImGui id")) is
@@ -294,15 +303,30 @@ internal unsafe class SeStringRendererTestWidget : IDataWindowWidget
Clicked: var clicked
})
{
+ ImGui.Separator();
+ if (this.alignToFramePadding)
+ ImGui.AlignTextToFramePadding();
ImGui.TextUnformatted($"Hovered[{offset}]: {new ReadOnlySeStringSpan(envelope).ToString()}; {payload}");
if (clicked && payload is DalamudLinkPayload { Plugin: "test" } dlp)
Util.OpenLink(dlp.ExtraString);
}
+ else
+ {
+ ImGui.Separator();
+ if (this.alignToFramePadding)
+ ImGui.AlignTextToFramePadding();
+ ImGuiHelpers.CompileSeStringWrapped("If a link is hovered, it will be displayed here.", this.style);
+ }
}
else
{
ImGuiHelpers.CompileSeStringWrapped(this.testString, this.style);
}
+
+ ImGui.Separator();
+ if (this.alignToFramePadding)
+ ImGui.AlignTextToFramePadding();
+ ImGuiHelpers.CompileSeStringWrapped("Extra line for alignment testing.", this.style);
}
private SeStringReplacementEntity GetEntity(scoped in SeStringDrawState state, int byteOffset)