diff --git a/Dalamud/Game/Gui/Dtr/DtrBar.cs b/Dalamud/Game/Gui/Dtr/DtrBar.cs index 81339b6aa..0cb5bde88 100644 --- a/Dalamud/Game/Gui/Dtr/DtrBar.cs +++ b/Dalamud/Game/Gui/Dtr/DtrBar.cs @@ -14,6 +14,7 @@ using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Client.Graphics; using FFXIVClientStructs.FFXIV.Client.System.Memory; +using FFXIVClientStructs.FFXIV.Client.System.String; using FFXIVClientStructs.FFXIV.Component.GUI; namespace Dalamud.Game.Gui.Dtr; @@ -51,6 +52,8 @@ internal sealed unsafe class DtrBar : IInternalDisposableService, IDtrBar private readonly List entries = new(); private readonly Dictionary> eventHandles = new(); + + private Utf8String* emptyString; private uint runningNodeIds = BaseNodeId; private float entryStartPos = float.NaN; @@ -111,10 +114,16 @@ internal sealed unsafe class DtrBar : IInternalDisposableService, IDtrBar this.addonLifecycle.UnregisterListener(this.dtrPreFinalizeListener); foreach (var entry in this.entries) - this.RemoveNode(entry.TextNode); + this.RemoveEntry(entry); this.entries.Clear(); this.framework.Update -= this.Update; + + if (this.emptyString != null) + { + this.emptyString->Dtor(); + this.emptyString = null; + } } /// @@ -124,12 +133,23 @@ internal sealed unsafe class DtrBar : IInternalDisposableService, IDtrBar { foreach (var data in this.entries.Where(d => d.ShouldBeRemoved)) { - this.RemoveNode(data.TextNode); + this.RemoveEntry(data); } this.entries.RemoveAll(d => d.ShouldBeRemoved); } + /// + /// Remove native resources for the specified entry. + /// + /// The resources to remove. + internal void RemoveEntry(DtrBarEntry toRemove) + { + this.RemoveNode(toRemove.TextNode); + toRemove.Storage->Dtor(true); + toRemove.Storage = null; + } + /// /// Check whether an entry with the specified title exists. /// @@ -204,7 +224,15 @@ internal sealed unsafe class DtrBar : IInternalDisposableService, IDtrBar if (data is { Dirty: true, Added: true, Text: not null, TextNode: not null }) { var node = data.TextNode; - node->SetText(data.Text.Encode()); + + if (data.Storage == null) + { + data.Storage = Utf8String.CreateEmpty(); + } + + data.Storage->SetString(data.Text.EncodeWithNullTerminator()); + node->SetText(data.Storage->StringPtr); + ushort w = 0, h = 0; if (!isHide) @@ -427,7 +455,10 @@ internal sealed unsafe class DtrBar : IInternalDisposableService, IDtrBar newTextNode->TextFlags = (byte)TextFlags.Edge; newTextNode->TextFlags2 = 0; - newTextNode->SetText(" "); + if (this.emptyString == null) + this.emptyString = Utf8String.FromString(" "); + + newTextNode->SetText(this.emptyString->StringPtr); newTextNode->TextColor = new ByteColor { R = 255, G = 255, B = 255, A = 255 }; newTextNode->EdgeColor = new ByteColor { R = 142, G = 106, B = 12, A = 255 }; diff --git a/Dalamud/Game/Gui/Dtr/DtrBarEntry.cs b/Dalamud/Game/Gui/Dtr/DtrBarEntry.cs index 1cc51cfe4..33e9b26e3 100644 --- a/Dalamud/Game/Gui/Dtr/DtrBarEntry.cs +++ b/Dalamud/Game/Gui/Dtr/DtrBarEntry.cs @@ -4,6 +4,7 @@ using Dalamud.Configuration.Internal; using Dalamud.Game.Text.SeStringHandling; using Dalamud.Utility; +using FFXIVClientStructs.FFXIV.Client.System.String; using FFXIVClientStructs.FFXIV.Component.GUI; namespace Dalamud.Game.Gui.Dtr; @@ -149,6 +150,11 @@ public sealed unsafe class DtrBarEntry : IDisposable, IDtrBarEntry /// Gets or sets the internal text node of this entry. /// internal AtkTextNode* TextNode { get; set; } + + /// + /// Gets or sets the storage for the text of this entry. + /// + internal Utf8String* Storage { get; set; } /// /// Gets a value indicating whether this entry should be removed. diff --git a/lib/FFXIVClientStructs b/lib/FFXIVClientStructs index dabb0e6d7..78aa8890d 160000 --- a/lib/FFXIVClientStructs +++ b/lib/FFXIVClientStructs @@ -1 +1 @@ -Subproject commit dabb0e6d774eca86b7161317324974f530f6745e +Subproject commit 78aa8890dbfdec9bc4bcadf9630892439a446404