Resize collision node instead of root node in DtrBar (#1494)

This commit is contained in:
nebel 2023-10-21 03:19:37 +09:00 committed by GitHub
parent 3fb5bcc348
commit 6ba31d2752
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using Dalamud.Configuration.Internal; using Dalamud.Configuration.Internal;
using Dalamud.Game.Addon;
using Dalamud.Game.Addon.Events; using Dalamud.Game.Addon.Events;
using Dalamud.Game.Addon.Lifecycle; using Dalamud.Game.Addon.Lifecycle;
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes; using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
@ -46,6 +45,7 @@ internal sealed unsafe class DtrBar : IDisposable, IServiceType, IDtrBar
private readonly AddonLifecycleEventListener dtrPostDrawListener; private readonly AddonLifecycleEventListener dtrPostDrawListener;
private readonly AddonLifecycleEventListener dtrPostRequestedUpdateListener; private readonly AddonLifecycleEventListener dtrPostRequestedUpdateListener;
private readonly AddonLifecycleEventListener dtrPreFinalizeListener;
private readonly ConcurrentBag<DtrBarEntry> newEntries = new(); private readonly ConcurrentBag<DtrBarEntry> newEntries = new();
private readonly List<DtrBarEntry> entries = new(); private readonly List<DtrBarEntry> entries = new();
@ -53,15 +53,18 @@ internal sealed unsafe class DtrBar : IDisposable, IServiceType, IDtrBar
private readonly Dictionary<uint, List<IAddonEventHandle>> eventHandles = new(); private readonly Dictionary<uint, List<IAddonEventHandle>> eventHandles = new();
private uint runningNodeIds = BaseNodeId; private uint runningNodeIds = BaseNodeId;
private float entryStartPos = float.NaN;
[ServiceManager.ServiceConstructor] [ServiceManager.ServiceConstructor]
private DtrBar() private DtrBar()
{ {
this.dtrPostDrawListener = new AddonLifecycleEventListener(AddonEvent.PostDraw, "_DTR", this.OnDtrPostDraw); this.dtrPostDrawListener = new AddonLifecycleEventListener(AddonEvent.PostDraw, "_DTR", this.FixCollision);
this.dtrPostRequestedUpdateListener = new AddonLifecycleEventListener(AddonEvent.PostRequestedUpdate, "_DTR", this.OnAddonRequestedUpdateDetour); this.dtrPostRequestedUpdateListener = new AddonLifecycleEventListener(AddonEvent.PostRequestedUpdate, "_DTR", this.FixCollision);
this.dtrPreFinalizeListener = new AddonLifecycleEventListener(AddonEvent.PreFinalize, "_DTR", this.PreFinalize);
this.addonLifecycle.RegisterListener(this.dtrPostDrawListener); this.addonLifecycle.RegisterListener(this.dtrPostDrawListener);
this.addonLifecycle.RegisterListener(this.dtrPostRequestedUpdateListener); this.addonLifecycle.RegisterListener(this.dtrPostRequestedUpdateListener);
this.addonLifecycle.RegisterListener(this.dtrPreFinalizeListener);
this.framework.Update += this.Update; this.framework.Update += this.Update;
@ -102,6 +105,7 @@ internal sealed unsafe class DtrBar : IDisposable, IServiceType, IDtrBar
{ {
this.addonLifecycle.UnregisterListener(this.dtrPostDrawListener); this.addonLifecycle.UnregisterListener(this.dtrPostDrawListener);
this.addonLifecycle.UnregisterListener(this.dtrPostRequestedUpdateListener); this.addonLifecycle.UnregisterListener(this.dtrPostRequestedUpdateListener);
this.addonLifecycle.UnregisterListener(this.dtrPreFinalizeListener);
foreach (var entry in this.entries) foreach (var entry in this.entries)
this.RemoveNode(entry.TextNode); this.RemoveNode(entry.TextNode);
@ -185,11 +189,10 @@ internal sealed unsafe class DtrBar : IDisposable, IServiceType, IDtrBar
var collisionNode = dtr->GetNodeById(17); var collisionNode = dtr->GetNodeById(17);
if (collisionNode == null) return; if (collisionNode == null) return;
// If we are drawing backwards, we should start from the right side of the collision node. That is, // We haven't calculated the native size yet, so we don't know where to start positioning.
// collisionNode->X + collisionNode->Width. if (float.IsNaN(this.entryStartPos)) return;
var runningXPos = this.configuration.DtrSwapDirection
? collisionNode->X + collisionNode->Width var runningXPos = this.entryStartPos;
: collisionNode->X;
foreach (var data in this.entries) foreach (var data in this.entries)
{ {
@ -255,56 +258,61 @@ internal sealed unsafe class DtrBar : IDisposable, IServiceType, IDtrBar
} }
} }
private void OnDtrPostDraw(AddonEvent eventType, AddonArgs addonInfo) private void FixCollision(AddonEvent eventType, AddonArgs addonInfo)
{ {
var addon = (AtkUnitBase*)addonInfo.Addon; var addon = (AtkUnitBase*)addonInfo.Addon;
if (addon->RootNode is null || addon->UldManager.NodeList is null) return;
this.UpdateNodePositions(addon); float minX = addon->RootNode->Width;
var additionalWidth = 0;
AtkResNode* collisionNode = null;
if (!this.configuration.DtrSwapDirection) foreach (var index in Enumerable.Range(0, addon->UldManager.NodeListCount))
{ {
var targetSize = (ushort)this.CalculateTotalSize(); var node = addon->UldManager.NodeList[index];
var sizeDelta = MathF.Round((targetSize - addon->RootNode->Width) * addon->RootNode->ScaleX); if (node->IsVisible)
if (addon->RootNode->Width != targetSize)
{ {
addon->RootNode->SetWidth(targetSize); var nodeId = node->NodeID;
addon->SetX((short)(addon->GetX() - sizeDelta)); var nodeType = node->Type;
// force a RequestedUpdate immediately to force the game to right-justify it immediately. if (nodeType == NodeType.Collision)
addon->OnUpdate(AtkStage.GetSingleton()->GetNumberArrayData(), AtkStage.GetSingleton()->GetStringArrayData()); {
collisionNode = node;
}
else if (nodeId >= BaseNodeId)
{
// Dalamud-created node
additionalWidth += node->Width + this.configuration.DtrSpacing;
}
else if ((nodeType == NodeType.Res || (ushort)nodeType >= 1000) &&
(node->ChildNode == null || node->ChildNode->IsVisible))
{
// Native top-level node. These are are either res nodes or button components.
// Both the node and its child (if it has one) must be visible for the node to be counted.
minX = MathF.Min(minX, node->X);
} }
} }
} }
private void UpdateNodePositions(AtkUnitBase* addon) if (collisionNode == null) return;
{
// If we grow to the right, we need to left-justify the original elements.
// else if we grow to the left, the game right-justifies it for us.
if (this.configuration.DtrSwapDirection)
{
var targetSize = (ushort)this.CalculateTotalSize();
addon->RootNode->SetWidth(targetSize);
var sizeOffset = addon->GetNodeById(17)->GetX();
var node = addon->RootNode->ChildNode; var nativeWidth = addon->RootNode->Width - (int)minX;
while (node is not null) var targetX = minX - (this.configuration.DtrSwapDirection ? 0 : additionalWidth);
var targetWidth = (ushort)(nativeWidth + additionalWidth);
if (collisionNode->Width != targetWidth || collisionNode->X != targetX)
{ {
if (node->NodeID < 1000 && node->IsVisible) collisionNode->SetWidth(targetWidth);
{ collisionNode->SetX(targetX);
node->SetX(node->GetX() - sizeOffset);
} }
node = node->PrevSiblingNode; // If we are drawing backwards, we should start from the right side of the native nodes.
} this.entryStartPos = this.configuration.DtrSwapDirection ? minX + nativeWidth : minX;
}
} }
private void OnAddonRequestedUpdateDetour(AddonEvent eventType, AddonArgs addonInfo) private void PreFinalize(AddonEvent type, AddonArgs args)
{ {
var addon = (AtkUnitBase*)addonInfo.Addon; this.entryStartPos = float.NaN;
this.UpdateNodePositions(addon);
} }
/// <summary> /// <summary>
@ -340,28 +348,6 @@ internal sealed unsafe class DtrBar : IDisposable, IServiceType, IDtrBar
} }
} }
// Calculates the total width the dtr bar should be
private float CalculateTotalSize()
{
var addon = this.GetDtr();
if (addon is null || addon->RootNode is null || addon->UldManager.NodeList is null) return 0;
var totalSize = 0.0f;
foreach (var index in Enumerable.Range(0, addon->UldManager.NodeListCount))
{
var node = addon->UldManager.NodeList[index];
// Node 17 is the default CollisionNode that fits over the existing elements
if (node->NodeID is 17) totalSize += node->Width;
// Node > 1000, are our custom nodes
if (node->NodeID is > 1000 && node->IsVisible) totalSize += node->Width + this.configuration.DtrSpacing;
}
return totalSize;
}
private bool AddNode(AtkTextNode* node) private bool AddNode(AtkTextNode* node)
{ {
var dtr = this.GetDtr(); var dtr = this.GetDtr();