From 09f0fa2861d2e5dd2dfecdec277cfc80271a29f6 Mon Sep 17 00:00:00 2001 From: AzaezelX Date: Tue, 27 Jan 2026 17:47:19 -0600 Subject: [PATCH] cleanups and a few more utility methods --- Engine/source/core/util/treeObject.h | 188 ++++++++++++++++++++++++--- 1 file changed, 171 insertions(+), 17 deletions(-) diff --git a/Engine/source/core/util/treeObject.h b/Engine/source/core/util/treeObject.h index 0fde074a3..0ddd14a99 100644 --- a/Engine/source/core/util/treeObject.h +++ b/Engine/source/core/util/treeObject.h @@ -32,13 +32,20 @@ class TreeNode : public Vector*> { public: T data; TreeNode* parent; - TreeNode(const T& val = T(), TreeNode* p = NULL) : data(val), parent(p){} + TreeNode(const T& val = T(), TreeNode* p = NULL) : data(val), parent(p) {} virtual ~TreeNode() { deleteChildren(); if (parent) { - parent->remove(this); + for (U32 i = 0; i < parent->size(); i++) + { + if ((*parent)[i] == this) + { + parent->erase(i); + break; + } + } parent = NULL; } } @@ -46,12 +53,14 @@ public: //description logic inline bool isRoot() const { return parent == NULL; } inline bool isLeaf() const { return size() == 0; } - - //parent logic + // Parent logic inline TreeNode* getParent() const { return parent; } + inline void setParent(TreeNode* p) { - if (parent) parent->remove(this); + if (parent == p) return; + + if (parent) parent->removeChild(this); parent = p; if (parent) parent->push_back(this); } @@ -65,10 +74,21 @@ public: } inline void addChild(TreeNode* child) { - if (child) { - child->parent = this; - push_back(child); + if (!child) return; + + // Check if already a child to prevent duplicates + for (U32 i = 0; i < size(); i++) + { + if ((*this)[i] == child) + return; // Already a child } + + // Remove from old parent if needed + if (child->parent && child->parent != this) + child->parent->removeChild(child); + + child->parent = this; + push_back(child); } inline void setChild(U32 i, TreeNode* child) { @@ -80,12 +100,41 @@ public: (*this)[j] = NULL; } + TreeNode* oldChild = (*this)[i]; + if (oldChild == child) return; + + // Unlink old child + if (oldChild) + { + oldChild->parent = NULL; + } + if (child == NULL) { - removeChild(i); + (*this)[i] = NULL; } else { + // Handle moving from different parent vs same parent + if (child->parent && child->parent != this) + { + child->parent->removeChild(child); + } + else if (child->parent == this) + { + // Moving within same parent - find and remove from old slot + for (U32 j = 0; j < size(); j++) + { + if (j != i && (*this)[j] == child) + { + erase(j); + if (j < i) + i--; + break; + } + } + } + (*this)[i] = child; child->parent = this; } @@ -93,8 +142,6 @@ public: inline TreeNode* getChild(U32 i) const { - if (!this) - return NULL; if (i < size()) return (*this)[i]; return NULL; @@ -103,12 +150,28 @@ public: inline void addChildren(const Vector* children) { if (!children) return; - for (U32 i = 0; i < children->size(); i++) { + for (U32 i = 0; i < children->size(); i++) + { TreeNode* child = new TreeNode((*children)[i], this); push_back(child); } } + inline void removeChild(TreeNode* child) + { + if (!child) return; + + for (U32 i = 0; i < size(); i++) + { + if ((*this)[i] == child) + { + child->parent = NULL; + erase(i); + return; + } + } + } + inline void removeChild(U32 i) { if (i < size()) @@ -119,6 +182,62 @@ public: erase(i); } } + inline void replaceChild(TreeNode* oldChild, TreeNode* newChild) + { + if (!oldChild) return; + + for (U32 i = 0; i < size(); i++) + { + if ((*this)[i] == oldChild) + { + oldChild->parent = NULL; + + if (newChild) + { + // Handle moving from different parent vs same parent + if (newChild->parent && newChild->parent != this) + { + newChild->parent->removeChild(newChild); + } + else if (newChild->parent == this) + { + // Moving within same parent - find and remove from old slot + for (U32 j = 0; j < size(); j++) + { + if (j != i && (*this)[j] == newChild) + { + erase(j); + if (j < i) + i--; + break; + } + } + } + + (*this)[i] = newChild; + newChild->parent = this; + } + else + { + (*this)[i] = NULL; + } + return; + } + } + } + + inline void compact() + { + // Remove NULL entries from children array + for (U32 i = 0; i < size(); ) + { + if ((*this)[i] == NULL) + erase(i); + else + i++; + } + } + void operator =(Vector* other) { clear(); addChildren(other); } inline U32 getNumChildren() const { return size(); } @@ -128,13 +247,18 @@ public: Vector*> children; children.reserve(size()); for (U32 i = 0; i < size(); i++) - children.push_back((*this)[i]); + { + if ((*this)[i]) // Skip NULLs + children.push_back((*this)[i]); + } return children; } + inline void deleteChildren() { Vector*> children; - for (U32 i = 0; i < size(); i++) { + for (U32 i = 0; i < size(); i++) + { children.push_back((*this)[i]); } clear(); @@ -156,9 +280,10 @@ public: if (!parent) return siblings; siblings.reserve(parent->size() - 1); - for (U32 i = 0; i < parent->size(); i++) { + for (U32 i = 0; i < parent->size(); i++) + { TreeNode* sibling = (*parent)[i]; - if (sibling != this) + if (sibling && sibling != this) // Skip NULLs siblings.push_back(sibling); } return siblings; @@ -169,6 +294,35 @@ public: inline void setData(const T& val) { data = val; } inline void operator =(const T& val) { data = val; } inline T* getDataPtr() { return &data; } + + // Traversal helpers + inline U32 getDepth() const + { + U32 depth = 0; + TreeNode* current = parent; + while (current) + { + depth++; + current = current->parent; + } + return depth; + } + + inline TreeNode* getRoot() + { + TreeNode* current = this; + while (current->parent) + current = current->parent; + return current; + } + + inline const TreeNode* getRoot() const + { + const TreeNode* current = this; + while (current->parent) + current = current->parent; + return current; + } }; class TreeObject : public SimObject { @@ -213,7 +367,7 @@ public: bool toParent(S32 key, S32 newParentKey); Vector getChildren(S32 key); - S32 getNumChildren(S32 key) {return getChildren(key).size();}; + S32 getNumChildren(S32 key) { return getChildren(key).size(); }; Vector getSiblings(S32 key); S32 getNumSiblings(S32 key) { return getSiblings(key).size(); };