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();