Initial commit: AetherBags + KamiToolKit for FC Gitea
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,199 @@
|
||||
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--;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user