diff --git a/Dalamud/Configuration/Internal/DalamudConfiguration.cs b/Dalamud/Configuration/Internal/DalamudConfiguration.cs
index 4405a11a7..3d2b58683 100644
--- a/Dalamud/Configuration/Internal/DalamudConfiguration.cs
+++ b/Dalamud/Configuration/Internal/DalamudConfiguration.cs
@@ -261,6 +261,15 @@ namespace Dalamud.Configuration.Internal
///
public int DtrSpacing { get; set; } = 10;
+ ///
+ /// Gets or sets a value indicating whether to swap the
+ /// direction in which elements are drawn in the DTR.
+ /// False indicates that elements will be drawn from the end of
+ /// the left side of the Server Info bar, and continue leftwards.
+ /// True indicates the opposite.
+ ///
+ public bool DtrSwapDirection { get; set; } = false;
+
///
/// Gets or sets a value indicating whether the title screen menu is shown.
///
diff --git a/Dalamud/Game/Gui/Dtr/DtrBar.cs b/Dalamud/Game/Gui/Dtr/DtrBar.cs
index 7ba210179..406cc48d2 100644
--- a/Dalamud/Game/Gui/Dtr/DtrBar.cs
+++ b/Dalamud/Game/Gui/Dtr/DtrBar.cs
@@ -19,8 +19,10 @@ namespace Dalamud.Game.Gui.Dtr
[InterfaceVersion("1.0")]
public sealed unsafe class DtrBar : IDisposable
{
+ private const uint BaseNodeId = 1000;
+
private List entries = new();
- private uint runningNodeIds = 1000;
+ private uint runningNodeIds = BaseNodeId;
///
/// Initializes a new instance of the class.
@@ -130,12 +132,21 @@ namespace Dalamud.Game.Gui.Dtr
// The collision node on the DTR element is always the width of its content
if (dtr->UldManager.NodeList == null) return;
+
+ // If we have an unmodified DTR but still have entries, we need to
+ // work to reset our state.
+ if (!this.CheckForDalamudNodes())
+ this.RecreateNodes();
+
var collisionNode = dtr->UldManager.NodeList[1];
if (collisionNode == null) return;
- var runningXPos = collisionNode->X;
var configuration = Service.Get();
+ // If we are drawing backwards, we should start from the right side of the collision node. That is,
+ // collisionNode->X + collisionNode->Width.
+ var runningXPos = configuration.DtrSwapDirection ? collisionNode->X + collisionNode->Width : collisionNode->X;
+
for (var i = 0; i < this.entries.Count; i++)
{
var data = this.entries[i];
@@ -168,14 +179,52 @@ namespace Dalamud.Game.Gui.Dtr
if (!isHide)
{
- runningXPos -= data.TextNode->AtkResNode.Width + configuration.DtrSpacing;
- data.TextNode->AtkResNode.SetPositionFloat(runningXPos, 2);
+ var elementWidth = data.TextNode->AtkResNode.Width + configuration.DtrSpacing;
+
+ if (configuration.DtrSwapDirection)
+ {
+ data.TextNode->AtkResNode.SetPositionFloat(runningXPos, 2);
+ runningXPos += elementWidth;
+ }
+ else
+ {
+ runningXPos -= elementWidth;
+ data.TextNode->AtkResNode.SetPositionFloat(runningXPos, 2);
+ }
}
this.entries[i] = data;
}
}
+ ///
+ /// Checks if there are any Dalamud nodes in the DTR.
+ ///
+ /// True if there are nodes with an ID > 1000.
+ private bool CheckForDalamudNodes()
+ {
+ var dtr = GetDtr();
+ if (dtr == null || dtr->RootNode == null) return false;
+
+ for (int i = 0; i < dtr->UldManager.NodeListCount; i++)
+ {
+ if (dtr->UldManager.NodeList[i]->NodeID > 1000)
+ return true;
+ }
+
+ return false;
+ }
+
+ private void RecreateNodes()
+ {
+ this.runningNodeIds = BaseNodeId;
+ foreach (var entry in this.entries)
+ {
+ entry.TextNode = this.MakeNode(++this.runningNodeIds);
+ entry.Added = false;
+ }
+ }
+
private bool AddNode(AtkTextNode* node)
{
var dtr = GetDtr();
diff --git a/Dalamud/Interface/Internal/Windows/SettingsWindow.cs b/Dalamud/Interface/Internal/Windows/SettingsWindow.cs
index e4c6281da..d02dae56d 100644
--- a/Dalamud/Interface/Internal/Windows/SettingsWindow.cs
+++ b/Dalamud/Interface/Internal/Windows/SettingsWindow.cs
@@ -49,6 +49,7 @@ namespace Dalamud.Interface.Internal.Windows
private List? dtrOrder;
private List? dtrIgnore;
private int dtrSpacing;
+ private bool dtrSwapDirection;
private List thirdRepoList;
private bool thirdRepoListChanged;
@@ -99,6 +100,7 @@ namespace Dalamud.Interface.Internal.Windows
this.doTsm = configuration.ShowTsm;
this.dtrSpacing = configuration.DtrSpacing;
+ this.dtrSwapDirection = configuration.DtrSwapDirection;
this.doPluginTest = configuration.DoPluginTest;
this.thirdRepoList = configuration.ThirdRepoList.Select(x => x.Clone()).ToList();
@@ -416,6 +418,10 @@ namespace Dalamud.Interface.Internal.Windows
ImGui.Text(Loc.Localize("DalamudSettingServerInfoBarSpacing", "Server Info Bar spacing"));
ImGui.TextColored(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingServerInfoBarSpacingHint", "Configure the amount of space between entries in the server info bar here."));
ImGui.SliderInt("Spacing", ref this.dtrSpacing, 0, 40);
+
+ ImGui.Text(Loc.Localize("DalamudSettingServerInfoBarDirection", "Server Info Bar direction"));
+ ImGui.TextColored(ImGuiColors.DalamudGrey, Loc.Localize("DalamudSettingServerInfoBarDirectionHint", "If checked, the Server Info Bar elements will expand to the right instead of the left."));
+ ImGui.Checkbox("Swap Direction", ref this.dtrSwapDirection);
}
private void DrawExperimentalTab()
@@ -823,6 +829,7 @@ namespace Dalamud.Interface.Internal.Windows
this.dtrIgnore = configuration.DtrIgnore;
configuration.DtrSpacing = this.dtrSpacing;
+ configuration.DtrSwapDirection = this.dtrSwapDirection;
configuration.DoPluginTest = this.doPluginTest;
configuration.ThirdRepoList = this.thirdRepoList.Select(x => x.Clone()).ToList();