200 lines
6.8 KiB
C#
200 lines
6.8 KiB
C#
using System;
|
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
|
|
|
namespace KamiToolKit.Classes;
|
|
|
|
public enum NodePosition {
|
|
BeforeTarget,
|
|
AfterTarget,
|
|
BeforeAllSiblings,
|
|
AfterAllSiblings,
|
|
AsLastChild,
|
|
AsFirstChild,
|
|
}
|
|
|
|
internal static unsafe class NodeLinker {
|
|
internal static void AttachNode(AtkResNode* node, AtkResNode* attachTargetNode, NodePosition position) {
|
|
switch (position) {
|
|
case NodePosition.BeforeTarget:
|
|
EmplaceBefore(node, attachTargetNode);
|
|
break;
|
|
|
|
case NodePosition.AfterTarget:
|
|
EmplaceAfter(node, attachTargetNode);
|
|
break;
|
|
|
|
case NodePosition.BeforeAllSiblings:
|
|
EmplaceBeforeSiblings(node, attachTargetNode);
|
|
break;
|
|
|
|
case NodePosition.AfterAllSiblings:
|
|
EmplaceAfterSiblings(node, attachTargetNode);
|
|
break;
|
|
|
|
case NodePosition.AsLastChild:
|
|
EmplaceAsLastChild(node, attachTargetNode);
|
|
break;
|
|
|
|
case NodePosition.AsFirstChild:
|
|
EmplaceAsFirstChild(node, attachTargetNode);
|
|
break;
|
|
|
|
default:
|
|
throw new ArgumentOutOfRangeException(nameof(position), position, null);
|
|
}
|
|
}
|
|
|
|
private static void EmplaceBefore(AtkResNode* node, AtkResNode* attachTargetNode) {
|
|
node->ParentNode = attachTargetNode->ParentNode;
|
|
|
|
// Target node is the head of the nodelist, we will be the new head.
|
|
if (attachTargetNode->NextSiblingNode is null) {
|
|
attachTargetNode->ParentNode->ChildNode = node;
|
|
}
|
|
|
|
// We have a node that will be before us
|
|
if (attachTargetNode->NextSiblingNode is not null) {
|
|
attachTargetNode->NextSiblingNode->PrevSiblingNode = node;
|
|
node->NextSiblingNode = attachTargetNode->NextSiblingNode;
|
|
}
|
|
|
|
attachTargetNode->NextSiblingNode = node;
|
|
node->PrevSiblingNode = attachTargetNode;
|
|
|
|
if (attachTargetNode->ParentNode->GetNodeType() is not NodeType.Component) {
|
|
attachTargetNode->ParentNode->ChildCount++;
|
|
}
|
|
}
|
|
|
|
private static void EmplaceAfter(AtkResNode* node, AtkResNode* attachTargetNode) {
|
|
node->ParentNode = attachTargetNode->ParentNode;
|
|
|
|
// We have a node that will be after us
|
|
if (attachTargetNode->PrevSiblingNode is not null) {
|
|
attachTargetNode->PrevSiblingNode->NextSiblingNode = node;
|
|
node->PrevSiblingNode = attachTargetNode->PrevSiblingNode;
|
|
}
|
|
|
|
attachTargetNode->PrevSiblingNode = node;
|
|
node->NextSiblingNode = attachTargetNode;
|
|
|
|
if (attachTargetNode->ParentNode->GetNodeType() is not NodeType.Component) {
|
|
attachTargetNode->ParentNode->ChildCount++;
|
|
}
|
|
}
|
|
|
|
private static void EmplaceBeforeSiblings(AtkResNode* node, AtkResNode* attachTargetNode) {
|
|
var current = attachTargetNode;
|
|
var previous = current;
|
|
|
|
while (current is not null) {
|
|
previous = current;
|
|
current = current->NextSiblingNode;
|
|
}
|
|
|
|
if (previous is not null) {
|
|
EmplaceBefore(node, previous);
|
|
}
|
|
|
|
if (attachTargetNode->ParentNode->GetNodeType() is not NodeType.Component) {
|
|
attachTargetNode->ParentNode->ChildCount++;
|
|
}
|
|
}
|
|
|
|
private static void EmplaceAfterSiblings(AtkResNode* node, AtkResNode* attachTargetNode) {
|
|
var current = attachTargetNode;
|
|
var previous = current;
|
|
|
|
while (current is not null) {
|
|
previous = current;
|
|
current = current->PrevSiblingNode;
|
|
}
|
|
|
|
if (previous is not null) {
|
|
EmplaceAfter(node, previous);
|
|
}
|
|
|
|
if (attachTargetNode->ParentNode->GetNodeType() is not NodeType.Component) {
|
|
attachTargetNode->ParentNode->ChildCount++;
|
|
}
|
|
}
|
|
|
|
private static void EmplaceAsLastChild(AtkResNode* node, AtkResNode* attachTargetNode) {
|
|
// If the child list is empty
|
|
if (attachTargetNode->ChildNode is null && attachTargetNode->GetNodeType() is not NodeType.Component) {
|
|
if (attachTargetNode->GetNodeType() is not NodeType.Component) {
|
|
attachTargetNode->ChildNode = node;
|
|
node->ParentNode = attachTargetNode;
|
|
attachTargetNode->ChildCount++;
|
|
}
|
|
else {
|
|
node->ParentNode = attachTargetNode;
|
|
}
|
|
}
|
|
// Else Add to the List
|
|
else {
|
|
var currentNode = attachTargetNode->ChildNode;
|
|
while (currentNode is not null && currentNode->PrevSiblingNode != null) {
|
|
currentNode = currentNode->PrevSiblingNode;
|
|
}
|
|
|
|
node->ParentNode = attachTargetNode;
|
|
node->NextSiblingNode = currentNode;
|
|
|
|
if (currentNode is not null) {
|
|
currentNode->PrevSiblingNode = node;
|
|
}
|
|
|
|
if (attachTargetNode->GetNodeType() is not NodeType.Component) {
|
|
attachTargetNode->ChildCount++;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void EmplaceAsFirstChild(AtkResNode* node, AtkResNode* attachTargetNode) {
|
|
// If the child list is empty
|
|
if (attachTargetNode->ChildNode is null && attachTargetNode->ChildCount is 0) {
|
|
if (attachTargetNode->GetNodeType() is not NodeType.Component) {
|
|
attachTargetNode->ChildNode = node;
|
|
node->ParentNode = attachTargetNode;
|
|
attachTargetNode->ChildCount++;
|
|
}
|
|
else {
|
|
node->ParentNode = attachTargetNode;
|
|
}
|
|
}
|
|
// Else Add to the List as the First Child
|
|
else {
|
|
if (attachTargetNode->GetNodeType() is not NodeType.Component) {
|
|
attachTargetNode->ChildNode->NextSiblingNode = node;
|
|
node->PrevSiblingNode = attachTargetNode->ChildNode;
|
|
attachTargetNode->ChildNode = node;
|
|
node->ParentNode = attachTargetNode;
|
|
attachTargetNode->ChildCount++;
|
|
}
|
|
else {
|
|
node->PrevSiblingNode = attachTargetNode->ChildNode;
|
|
node->ParentNode = attachTargetNode;
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void DetachNode(AtkResNode* node) {
|
|
if (node is null) return;
|
|
if (node->ParentNode is null) return;
|
|
|
|
if (node->ParentNode->ChildNode == node)
|
|
node->ParentNode->ChildNode = node->PrevSiblingNode;
|
|
|
|
if (node->PrevSiblingNode != null)
|
|
node->PrevSiblingNode->NextSiblingNode = node->NextSiblingNode;
|
|
|
|
if (node->NextSiblingNode != null)
|
|
node->NextSiblingNode->PrevSiblingNode = node->PrevSiblingNode;
|
|
|
|
if (node->ParentNode->GetNodeType() is not NodeType.Component) {
|
|
node->ParentNode->ChildCount--;
|
|
}
|
|
}
|
|
}
|