mirror of
https://github.com/goatcorp/Dalamud.git
synced 2026-01-02 05:43:40 +01:00
chore: convert Dalamud to file-scoped namespaces
This commit is contained in:
parent
b093323acc
commit
987ff8dc8f
368 changed files with 55081 additions and 55450 deletions
|
|
@ -10,314 +10,313 @@ using FFXIVClientStructs.FFXIV.Client.System.Memory;
|
|||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||
using Serilog;
|
||||
|
||||
namespace Dalamud.Game.Gui.Dtr
|
||||
namespace Dalamud.Game.Gui.Dtr;
|
||||
|
||||
/// <summary>
|
||||
/// Class used to interface with the server info bar.
|
||||
/// </summary>
|
||||
[PluginInterface]
|
||||
[InterfaceVersion("1.0")]
|
||||
[ServiceManager.BlockingEarlyLoadedService]
|
||||
public sealed unsafe class DtrBar : IDisposable, IServiceType
|
||||
{
|
||||
/// <summary>
|
||||
/// Class used to interface with the server info bar.
|
||||
/// </summary>
|
||||
[PluginInterface]
|
||||
[InterfaceVersion("1.0")]
|
||||
[ServiceManager.BlockingEarlyLoadedService]
|
||||
public sealed unsafe class DtrBar : IDisposable, IServiceType
|
||||
private const uint BaseNodeId = 1000;
|
||||
|
||||
[ServiceManager.ServiceDependency]
|
||||
private readonly Framework framework = Service<Framework>.Get();
|
||||
|
||||
[ServiceManager.ServiceDependency]
|
||||
private readonly GameGui gameGui = Service<GameGui>.Get();
|
||||
|
||||
[ServiceManager.ServiceDependency]
|
||||
private readonly DalamudConfiguration configuration = Service<DalamudConfiguration>.Get();
|
||||
|
||||
private List<DtrBarEntry> entries = new();
|
||||
private uint runningNodeIds = BaseNodeId;
|
||||
|
||||
[ServiceManager.ServiceConstructor]
|
||||
private DtrBar()
|
||||
{
|
||||
private const uint BaseNodeId = 1000;
|
||||
this.framework.Update += this.Update;
|
||||
|
||||
[ServiceManager.ServiceDependency]
|
||||
private readonly Framework framework = Service<Framework>.Get();
|
||||
this.configuration.DtrOrder ??= new List<string>();
|
||||
this.configuration.DtrIgnore ??= new List<string>();
|
||||
this.configuration.Save();
|
||||
}
|
||||
|
||||
[ServiceManager.ServiceDependency]
|
||||
private readonly GameGui gameGui = Service<GameGui>.Get();
|
||||
/// <summary>
|
||||
/// Get a DTR bar entry.
|
||||
/// This allows you to add your own text, and users to sort it.
|
||||
/// </summary>
|
||||
/// <param name="title">A user-friendly name for sorting.</param>
|
||||
/// <param name="text">The text the entry shows.</param>
|
||||
/// <returns>The entry object used to update, hide and remove the entry.</returns>
|
||||
/// <exception cref="ArgumentException">Thrown when an entry with the specified title exists.</exception>
|
||||
public DtrBarEntry Get(string title, SeString? text = null)
|
||||
{
|
||||
if (this.entries.Any(x => x.Title == title))
|
||||
throw new ArgumentException("An entry with the same title already exists.");
|
||||
|
||||
[ServiceManager.ServiceDependency]
|
||||
private readonly DalamudConfiguration configuration = Service<DalamudConfiguration>.Get();
|
||||
var node = this.MakeNode(++this.runningNodeIds);
|
||||
var entry = new DtrBarEntry(title, node);
|
||||
entry.Text = text;
|
||||
|
||||
private List<DtrBarEntry> entries = new();
|
||||
private uint runningNodeIds = BaseNodeId;
|
||||
// Add the entry to the end of the order list, if it's not there already.
|
||||
if (!this.configuration.DtrOrder!.Contains(title))
|
||||
this.configuration.DtrOrder!.Add(title);
|
||||
this.entries.Add(entry);
|
||||
this.ApplySort();
|
||||
|
||||
[ServiceManager.ServiceConstructor]
|
||||
private DtrBar()
|
||||
return entry;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
foreach (var entry in this.entries)
|
||||
this.RemoveNode(entry.TextNode);
|
||||
|
||||
this.entries.Clear();
|
||||
this.framework.Update -= this.Update;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove nodes marked as "should be removed" from the bar.
|
||||
/// </summary>
|
||||
internal void HandleRemovedNodes()
|
||||
{
|
||||
foreach (var data in this.entries.Where(d => d.ShouldBeRemoved))
|
||||
{
|
||||
this.framework.Update += this.Update;
|
||||
|
||||
this.configuration.DtrOrder ??= new List<string>();
|
||||
this.configuration.DtrIgnore ??= new List<string>();
|
||||
this.configuration.Save();
|
||||
this.RemoveNode(data.TextNode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a DTR bar entry.
|
||||
/// This allows you to add your own text, and users to sort it.
|
||||
/// </summary>
|
||||
/// <param name="title">A user-friendly name for sorting.</param>
|
||||
/// <param name="text">The text the entry shows.</param>
|
||||
/// <returns>The entry object used to update, hide and remove the entry.</returns>
|
||||
/// <exception cref="ArgumentException">Thrown when an entry with the specified title exists.</exception>
|
||||
public DtrBarEntry Get(string title, SeString? text = null)
|
||||
{
|
||||
if (this.entries.Any(x => x.Title == title))
|
||||
throw new ArgumentException("An entry with the same title already exists.");
|
||||
this.entries.RemoveAll(d => d.ShouldBeRemoved);
|
||||
}
|
||||
|
||||
var node = this.MakeNode(++this.runningNodeIds);
|
||||
var entry = new DtrBarEntry(title, node);
|
||||
entry.Text = text;
|
||||
|
||||
// Add the entry to the end of the order list, if it's not there already.
|
||||
if (!this.configuration.DtrOrder!.Contains(title))
|
||||
this.configuration.DtrOrder!.Add(title);
|
||||
this.entries.Add(entry);
|
||||
this.ApplySort();
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
foreach (var entry in this.entries)
|
||||
this.RemoveNode(entry.TextNode);
|
||||
|
||||
this.entries.Clear();
|
||||
this.framework.Update -= this.Update;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove nodes marked as "should be removed" from the bar.
|
||||
/// </summary>
|
||||
internal void HandleRemovedNodes()
|
||||
{
|
||||
foreach (var data in this.entries.Where(d => d.ShouldBeRemoved))
|
||||
{
|
||||
this.RemoveNode(data.TextNode);
|
||||
}
|
||||
|
||||
this.entries.RemoveAll(d => d.ShouldBeRemoved);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check whether an entry with the specified title exists.
|
||||
/// </summary>
|
||||
/// <param name="title">The title to check for.</param>
|
||||
/// <returns>Whether or not an entry with that title is registered.</returns>
|
||||
internal bool HasEntry(string title) => this.entries.Any(x => x.Title == title);
|
||||
|
||||
/// <summary>
|
||||
/// Dirty the DTR bar entry with the specified title.
|
||||
/// </summary>
|
||||
/// <param name="title">Title of the entry to dirty.</param>
|
||||
/// <returns>Whether the entry was found.</returns>
|
||||
internal bool MakeDirty(string title)
|
||||
{
|
||||
var entry = this.entries.FirstOrDefault(x => x.Title == title);
|
||||
if (entry == null)
|
||||
return false;
|
||||
|
||||
entry.Dirty = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reapply the DTR entry ordering from <see cref="DalamudConfiguration"/>.
|
||||
/// </summary>
|
||||
internal void ApplySort()
|
||||
{
|
||||
// Sort the current entry list, based on the order in the configuration.
|
||||
var positions = this.configuration
|
||||
.DtrOrder!
|
||||
.Select(entry => (entry, index: this.configuration.DtrOrder!.IndexOf(entry)))
|
||||
.ToDictionary(x => x.entry, x => x.index);
|
||||
|
||||
this.entries.Sort((x, y) =>
|
||||
{
|
||||
var xPos = positions.TryGetValue(x.Title, out var xIndex) ? xIndex : int.MaxValue;
|
||||
var yPos = positions.TryGetValue(y.Title, out var yIndex) ? yIndex : int.MaxValue;
|
||||
return xPos.CompareTo(yPos);
|
||||
});
|
||||
}
|
||||
|
||||
private AtkUnitBase* GetDtr() => (AtkUnitBase*)this.gameGui.GetAddonByName("_DTR", 1).ToPointer();
|
||||
|
||||
private void Update(Framework unused)
|
||||
{
|
||||
this.HandleRemovedNodes();
|
||||
|
||||
var dtr = this.GetDtr();
|
||||
if (dtr == null) return;
|
||||
|
||||
// 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;
|
||||
|
||||
// If we are drawing backwards, we should start from the right side of the collision node. That is,
|
||||
// collisionNode->X + collisionNode->Width.
|
||||
var runningXPos = this.configuration.DtrSwapDirection
|
||||
? collisionNode->X + collisionNode->Width
|
||||
: collisionNode->X;
|
||||
|
||||
for (var i = 0; i < this.entries.Count; i++)
|
||||
{
|
||||
var data = this.entries[i];
|
||||
var isHide = this.configuration.DtrIgnore!.Any(x => x == data.Title) || !data.Shown;
|
||||
|
||||
if (data.Dirty && data.Added && data.Text != null && data.TextNode != null)
|
||||
{
|
||||
var node = data.TextNode;
|
||||
node->SetText(data.Text?.Encode());
|
||||
ushort w = 0, h = 0;
|
||||
|
||||
if (isHide)
|
||||
{
|
||||
node->AtkResNode.ToggleVisibility(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
node->AtkResNode.ToggleVisibility(true);
|
||||
node->GetTextDrawSize(&w, &h, node->NodeText.StringPtr);
|
||||
node->AtkResNode.SetWidth(w);
|
||||
}
|
||||
|
||||
data.Dirty = false;
|
||||
}
|
||||
|
||||
if (!data.Added)
|
||||
{
|
||||
data.Added = this.AddNode(data.TextNode);
|
||||
}
|
||||
|
||||
if (!isHide)
|
||||
{
|
||||
var elementWidth = data.TextNode->AtkResNode.Width + this.configuration.DtrSpacing;
|
||||
|
||||
if (this.configuration.DtrSwapDirection)
|
||||
{
|
||||
data.TextNode->AtkResNode.SetPositionFloat(runningXPos, 2);
|
||||
runningXPos += elementWidth;
|
||||
}
|
||||
else
|
||||
{
|
||||
runningXPos -= elementWidth;
|
||||
data.TextNode->AtkResNode.SetPositionFloat(runningXPos, 2);
|
||||
}
|
||||
}
|
||||
|
||||
this.entries[i] = data;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if there are any Dalamud nodes in the DTR.
|
||||
/// </summary>
|
||||
/// <returns>True if there are nodes with an ID > 1000.</returns>
|
||||
private bool CheckForDalamudNodes()
|
||||
{
|
||||
var dtr = this.GetDtr();
|
||||
if (dtr == null || dtr->RootNode == null) return false;
|
||||
|
||||
for (var i = 0; i < dtr->UldManager.NodeListCount; i++)
|
||||
{
|
||||
if (dtr->UldManager.NodeList[i]->NodeID > 1000)
|
||||
return true;
|
||||
}
|
||||
/// <summary>
|
||||
/// Check whether an entry with the specified title exists.
|
||||
/// </summary>
|
||||
/// <param name="title">The title to check for.</param>
|
||||
/// <returns>Whether or not an entry with that title is registered.</returns>
|
||||
internal bool HasEntry(string title) => this.entries.Any(x => x.Title == title);
|
||||
|
||||
/// <summary>
|
||||
/// Dirty the DTR bar entry with the specified title.
|
||||
/// </summary>
|
||||
/// <param name="title">Title of the entry to dirty.</param>
|
||||
/// <returns>Whether the entry was found.</returns>
|
||||
internal bool MakeDirty(string title)
|
||||
{
|
||||
var entry = this.entries.FirstOrDefault(x => x.Title == title);
|
||||
if (entry == null)
|
||||
return false;
|
||||
}
|
||||
|
||||
private void RecreateNodes()
|
||||
entry.Dirty = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reapply the DTR entry ordering from <see cref="DalamudConfiguration"/>.
|
||||
/// </summary>
|
||||
internal void ApplySort()
|
||||
{
|
||||
// Sort the current entry list, based on the order in the configuration.
|
||||
var positions = this.configuration
|
||||
.DtrOrder!
|
||||
.Select(entry => (entry, index: this.configuration.DtrOrder!.IndexOf(entry)))
|
||||
.ToDictionary(x => x.entry, x => x.index);
|
||||
|
||||
this.entries.Sort((x, y) =>
|
||||
{
|
||||
this.runningNodeIds = BaseNodeId;
|
||||
foreach (var entry in this.entries)
|
||||
var xPos = positions.TryGetValue(x.Title, out var xIndex) ? xIndex : int.MaxValue;
|
||||
var yPos = positions.TryGetValue(y.Title, out var yIndex) ? yIndex : int.MaxValue;
|
||||
return xPos.CompareTo(yPos);
|
||||
});
|
||||
}
|
||||
|
||||
private AtkUnitBase* GetDtr() => (AtkUnitBase*)this.gameGui.GetAddonByName("_DTR", 1).ToPointer();
|
||||
|
||||
private void Update(Framework unused)
|
||||
{
|
||||
this.HandleRemovedNodes();
|
||||
|
||||
var dtr = this.GetDtr();
|
||||
if (dtr == null) return;
|
||||
|
||||
// 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;
|
||||
|
||||
// If we are drawing backwards, we should start from the right side of the collision node. That is,
|
||||
// collisionNode->X + collisionNode->Width.
|
||||
var runningXPos = this.configuration.DtrSwapDirection
|
||||
? collisionNode->X + collisionNode->Width
|
||||
: collisionNode->X;
|
||||
|
||||
for (var i = 0; i < this.entries.Count; i++)
|
||||
{
|
||||
var data = this.entries[i];
|
||||
var isHide = this.configuration.DtrIgnore!.Any(x => x == data.Title) || !data.Shown;
|
||||
|
||||
if (data.Dirty && data.Added && data.Text != null && data.TextNode != null)
|
||||
{
|
||||
entry.TextNode = this.MakeNode(++this.runningNodeIds);
|
||||
entry.Added = false;
|
||||
}
|
||||
}
|
||||
var node = data.TextNode;
|
||||
node->SetText(data.Text?.Encode());
|
||||
ushort w = 0, h = 0;
|
||||
|
||||
private bool AddNode(AtkTextNode* node)
|
||||
{
|
||||
var dtr = this.GetDtr();
|
||||
if (dtr == null || dtr->RootNode == null || dtr->UldManager.NodeList == null || node == null) return false;
|
||||
if (isHide)
|
||||
{
|
||||
node->AtkResNode.ToggleVisibility(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
node->AtkResNode.ToggleVisibility(true);
|
||||
node->GetTextDrawSize(&w, &h, node->NodeText.StringPtr);
|
||||
node->AtkResNode.SetWidth(w);
|
||||
}
|
||||
|
||||
var lastChild = dtr->RootNode->ChildNode;
|
||||
while (lastChild->PrevSiblingNode != null) lastChild = lastChild->PrevSiblingNode;
|
||||
Log.Debug($"Found last sibling: {(ulong)lastChild:X}");
|
||||
lastChild->PrevSiblingNode = (AtkResNode*)node;
|
||||
node->AtkResNode.ParentNode = lastChild->ParentNode;
|
||||
node->AtkResNode.NextSiblingNode = lastChild;
|
||||
|
||||
dtr->RootNode->ChildCount = (ushort)(dtr->RootNode->ChildCount + 1);
|
||||
Log.Debug("Set last sibling of DTR and updated child count");
|
||||
|
||||
dtr->UldManager.UpdateDrawNodeList();
|
||||
Log.Debug("Updated node draw list");
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool RemoveNode(AtkTextNode* node)
|
||||
{
|
||||
var dtr = this.GetDtr();
|
||||
if (dtr == null || dtr->RootNode == null || dtr->UldManager.NodeList == null || node == null) return false;
|
||||
|
||||
var tmpPrevNode = node->AtkResNode.PrevSiblingNode;
|
||||
var tmpNextNode = node->AtkResNode.NextSiblingNode;
|
||||
|
||||
// if (tmpNextNode != null)
|
||||
tmpNextNode->PrevSiblingNode = tmpPrevNode;
|
||||
if (tmpPrevNode != null)
|
||||
tmpPrevNode->NextSiblingNode = tmpNextNode;
|
||||
node->AtkResNode.Destroy(true);
|
||||
|
||||
dtr->RootNode->ChildCount = (ushort)(dtr->RootNode->ChildCount - 1);
|
||||
Log.Debug("Set last sibling of DTR and updated child count");
|
||||
dtr->UldManager.UpdateDrawNodeList();
|
||||
Log.Debug("Updated node draw list");
|
||||
return true;
|
||||
}
|
||||
|
||||
private AtkTextNode* MakeNode(uint nodeId)
|
||||
{
|
||||
var newTextNode = (AtkTextNode*)IMemorySpace.GetUISpace()->Malloc((ulong)sizeof(AtkTextNode), 8);
|
||||
if (newTextNode == null)
|
||||
{
|
||||
Log.Debug("Failed to allocate memory for text node");
|
||||
return null;
|
||||
data.Dirty = false;
|
||||
}
|
||||
|
||||
IMemorySpace.Memset(newTextNode, 0, (ulong)sizeof(AtkTextNode));
|
||||
newTextNode->Ctor();
|
||||
if (!data.Added)
|
||||
{
|
||||
data.Added = this.AddNode(data.TextNode);
|
||||
}
|
||||
|
||||
newTextNode->AtkResNode.NodeID = nodeId;
|
||||
newTextNode->AtkResNode.Type = NodeType.Text;
|
||||
newTextNode->AtkResNode.Flags = (short)(NodeFlags.AnchorLeft | NodeFlags.AnchorTop);
|
||||
newTextNode->AtkResNode.DrawFlags = 12;
|
||||
newTextNode->AtkResNode.SetWidth(22);
|
||||
newTextNode->AtkResNode.SetHeight(22);
|
||||
newTextNode->AtkResNode.SetPositionFloat(-200, 2);
|
||||
if (!isHide)
|
||||
{
|
||||
var elementWidth = data.TextNode->AtkResNode.Width + this.configuration.DtrSpacing;
|
||||
|
||||
newTextNode->LineSpacing = 12;
|
||||
newTextNode->AlignmentFontType = 5;
|
||||
newTextNode->FontSize = 14;
|
||||
newTextNode->TextFlags = (byte)TextFlags.Edge;
|
||||
newTextNode->TextFlags2 = 0;
|
||||
if (this.configuration.DtrSwapDirection)
|
||||
{
|
||||
data.TextNode->AtkResNode.SetPositionFloat(runningXPos, 2);
|
||||
runningXPos += elementWidth;
|
||||
}
|
||||
else
|
||||
{
|
||||
runningXPos -= elementWidth;
|
||||
data.TextNode->AtkResNode.SetPositionFloat(runningXPos, 2);
|
||||
}
|
||||
}
|
||||
|
||||
newTextNode->SetText(" ");
|
||||
|
||||
newTextNode->TextColor.R = 255;
|
||||
newTextNode->TextColor.G = 255;
|
||||
newTextNode->TextColor.B = 255;
|
||||
newTextNode->TextColor.A = 255;
|
||||
|
||||
newTextNode->EdgeColor.R = 142;
|
||||
newTextNode->EdgeColor.G = 106;
|
||||
newTextNode->EdgeColor.B = 12;
|
||||
newTextNode->EdgeColor.A = 255;
|
||||
|
||||
return newTextNode;
|
||||
this.entries[i] = data;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if there are any Dalamud nodes in the DTR.
|
||||
/// </summary>
|
||||
/// <returns>True if there are nodes with an ID > 1000.</returns>
|
||||
private bool CheckForDalamudNodes()
|
||||
{
|
||||
var dtr = this.GetDtr();
|
||||
if (dtr == null || dtr->RootNode == null) return false;
|
||||
|
||||
for (var 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 = this.GetDtr();
|
||||
if (dtr == null || dtr->RootNode == null || dtr->UldManager.NodeList == null || node == null) return false;
|
||||
|
||||
var lastChild = dtr->RootNode->ChildNode;
|
||||
while (lastChild->PrevSiblingNode != null) lastChild = lastChild->PrevSiblingNode;
|
||||
Log.Debug($"Found last sibling: {(ulong)lastChild:X}");
|
||||
lastChild->PrevSiblingNode = (AtkResNode*)node;
|
||||
node->AtkResNode.ParentNode = lastChild->ParentNode;
|
||||
node->AtkResNode.NextSiblingNode = lastChild;
|
||||
|
||||
dtr->RootNode->ChildCount = (ushort)(dtr->RootNode->ChildCount + 1);
|
||||
Log.Debug("Set last sibling of DTR and updated child count");
|
||||
|
||||
dtr->UldManager.UpdateDrawNodeList();
|
||||
Log.Debug("Updated node draw list");
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool RemoveNode(AtkTextNode* node)
|
||||
{
|
||||
var dtr = this.GetDtr();
|
||||
if (dtr == null || dtr->RootNode == null || dtr->UldManager.NodeList == null || node == null) return false;
|
||||
|
||||
var tmpPrevNode = node->AtkResNode.PrevSiblingNode;
|
||||
var tmpNextNode = node->AtkResNode.NextSiblingNode;
|
||||
|
||||
// if (tmpNextNode != null)
|
||||
tmpNextNode->PrevSiblingNode = tmpPrevNode;
|
||||
if (tmpPrevNode != null)
|
||||
tmpPrevNode->NextSiblingNode = tmpNextNode;
|
||||
node->AtkResNode.Destroy(true);
|
||||
|
||||
dtr->RootNode->ChildCount = (ushort)(dtr->RootNode->ChildCount - 1);
|
||||
Log.Debug("Set last sibling of DTR and updated child count");
|
||||
dtr->UldManager.UpdateDrawNodeList();
|
||||
Log.Debug("Updated node draw list");
|
||||
return true;
|
||||
}
|
||||
|
||||
private AtkTextNode* MakeNode(uint nodeId)
|
||||
{
|
||||
var newTextNode = (AtkTextNode*)IMemorySpace.GetUISpace()->Malloc((ulong)sizeof(AtkTextNode), 8);
|
||||
if (newTextNode == null)
|
||||
{
|
||||
Log.Debug("Failed to allocate memory for text node");
|
||||
return null;
|
||||
}
|
||||
|
||||
IMemorySpace.Memset(newTextNode, 0, (ulong)sizeof(AtkTextNode));
|
||||
newTextNode->Ctor();
|
||||
|
||||
newTextNode->AtkResNode.NodeID = nodeId;
|
||||
newTextNode->AtkResNode.Type = NodeType.Text;
|
||||
newTextNode->AtkResNode.Flags = (short)(NodeFlags.AnchorLeft | NodeFlags.AnchorTop);
|
||||
newTextNode->AtkResNode.DrawFlags = 12;
|
||||
newTextNode->AtkResNode.SetWidth(22);
|
||||
newTextNode->AtkResNode.SetHeight(22);
|
||||
newTextNode->AtkResNode.SetPositionFloat(-200, 2);
|
||||
|
||||
newTextNode->LineSpacing = 12;
|
||||
newTextNode->AlignmentFontType = 5;
|
||||
newTextNode->FontSize = 14;
|
||||
newTextNode->TextFlags = (byte)TextFlags.Edge;
|
||||
newTextNode->TextFlags2 = 0;
|
||||
|
||||
newTextNode->SetText(" ");
|
||||
|
||||
newTextNode->TextColor.R = 255;
|
||||
newTextNode->TextColor.G = 255;
|
||||
newTextNode->TextColor.B = 255;
|
||||
newTextNode->TextColor.A = 255;
|
||||
|
||||
newTextNode->EdgeColor.R = 142;
|
||||
newTextNode->EdgeColor.G = 106;
|
||||
newTextNode->EdgeColor.B = 12;
|
||||
newTextNode->EdgeColor.A = 255;
|
||||
|
||||
return newTextNode;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,91 +3,90 @@
|
|||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||
|
||||
namespace Dalamud.Game.Gui.Dtr
|
||||
namespace Dalamud.Game.Gui.Dtr;
|
||||
|
||||
/// <summary>
|
||||
/// Class representing an entry in the server info bar.
|
||||
/// </summary>
|
||||
public sealed unsafe class DtrBarEntry : IDisposable
|
||||
{
|
||||
private bool shownBacking = true;
|
||||
private SeString? textBacking = null;
|
||||
|
||||
/// <summary>
|
||||
/// Class representing an entry in the server info bar.
|
||||
/// Initializes a new instance of the <see cref="DtrBarEntry"/> class.
|
||||
/// </summary>
|
||||
public sealed unsafe class DtrBarEntry : IDisposable
|
||||
/// <param name="title">The title of the bar entry.</param>
|
||||
/// <param name="textNode">The corresponding text node.</param>
|
||||
internal DtrBarEntry(string title, AtkTextNode* textNode)
|
||||
{
|
||||
private bool shownBacking = true;
|
||||
private SeString? textBacking = null;
|
||||
this.Title = title;
|
||||
this.TextNode = textNode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DtrBarEntry"/> class.
|
||||
/// </summary>
|
||||
/// <param name="title">The title of the bar entry.</param>
|
||||
/// <param name="textNode">The corresponding text node.</param>
|
||||
internal DtrBarEntry(string title, AtkTextNode* textNode)
|
||||
/// <summary>
|
||||
/// Gets the title of this entry.
|
||||
/// </summary>
|
||||
public string Title { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the text of this entry.
|
||||
/// </summary>
|
||||
public SeString? Text
|
||||
{
|
||||
get => this.textBacking;
|
||||
set
|
||||
{
|
||||
this.Title = title;
|
||||
this.TextNode = textNode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the title of this entry.
|
||||
/// </summary>
|
||||
public string Title { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the text of this entry.
|
||||
/// </summary>
|
||||
public SeString? Text
|
||||
{
|
||||
get => this.textBacking;
|
||||
set
|
||||
{
|
||||
this.textBacking = value;
|
||||
this.Dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this entry is visible.
|
||||
/// </summary>
|
||||
public bool Shown
|
||||
{
|
||||
get => this.shownBacking;
|
||||
set
|
||||
{
|
||||
this.shownBacking = value;
|
||||
this.Dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the internal text node of this entry.
|
||||
/// </summary>
|
||||
internal AtkTextNode* TextNode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this entry should be removed.
|
||||
/// </summary>
|
||||
internal bool ShouldBeRemoved { get; private set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this entry is dirty.
|
||||
/// </summary>
|
||||
internal bool Dirty { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this entry has just been added.
|
||||
/// </summary>
|
||||
internal bool Added { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Remove this entry from the bar.
|
||||
/// You will need to re-acquire it from DtrBar to reuse it.
|
||||
/// </summary>
|
||||
public void Remove()
|
||||
{
|
||||
this.ShouldBeRemoved = true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
this.Remove();
|
||||
this.textBacking = value;
|
||||
this.Dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this entry is visible.
|
||||
/// </summary>
|
||||
public bool Shown
|
||||
{
|
||||
get => this.shownBacking;
|
||||
set
|
||||
{
|
||||
this.shownBacking = value;
|
||||
this.Dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the internal text node of this entry.
|
||||
/// </summary>
|
||||
internal AtkTextNode* TextNode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this entry should be removed.
|
||||
/// </summary>
|
||||
internal bool ShouldBeRemoved { get; private set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this entry is dirty.
|
||||
/// </summary>
|
||||
internal bool Dirty { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this entry has just been added.
|
||||
/// </summary>
|
||||
internal bool Added { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Remove this entry from the bar.
|
||||
/// You will need to re-acquire it from DtrBar to reuse it.
|
||||
/// </summary>
|
||||
public void Remove()
|
||||
{
|
||||
this.ShouldBeRemoved = true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
this.Remove();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue