Optimize child removal to constant time

This commit is contained in:
Lars Mueller 2024-01-05 21:28:20 +01:00
parent fb4ee6ac93
commit bd9f3aaa52
1 changed files with 21 additions and 23 deletions

View File

@ -15,6 +15,7 @@
#include "matrix4.h" #include "matrix4.h"
#include "IAttributes.h" #include "IAttributes.h"
#include <list> #include <list>
#include <optional>
namespace irr namespace irr
{ {
@ -276,30 +277,29 @@ namespace scene
child->grab(); child->grab();
child->remove(); // remove from old parent child->remove(); // remove from old parent
Children.push_back(child); Children.push_back(child);
child->Iterator = Children.end();
(*child->Iterator)--;
child->Parent = this; child->Parent = this;
} }
} }
//! Removes a child from this scene node. //! Removes a child from this scene node.
/** If found in the children list, the child pointer is also /**
dropped and might be deleted if no other grab exists.
\param child A pointer to the child which shall be removed. \param child A pointer to the child which shall be removed.
\return True if the child was removed, and false if not, \return True if the child was removed, and false if not,
e.g. because it couldn't be found in the children list. */ e.g. because it belongs to a different parent or no parent. */
virtual bool removeChild(ISceneNode* child) virtual bool removeChild(ISceneNode* child)
{ {
ISceneNodeList::iterator it = Children.begin(); if (child->Parent != this)
for (; it != Children.end(); ++it) return false;
if ((*it) == child)
{
(*it)->Parent = 0;
(*it)->drop();
Children.erase(it);
return true;
}
return false; auto it = child->Iterator.value();
child->Iterator = std::nullopt;
child->Parent = nullptr;
child->drop();
Children.erase(it);
return true;
} }
@ -309,13 +309,11 @@ namespace scene
*/ */
virtual void removeAll() virtual void removeAll()
{ {
ISceneNodeList::iterator it = Children.begin(); for (auto &child : Children) {
for (; it != Children.end(); ++it) child->Parent = nullptr;
{ child->Iterator = std::nullopt;
(*it)->Parent = 0; child->drop();
(*it)->drop();
} }
Children.clear(); Children.clear();
} }
@ -508,10 +506,8 @@ namespace scene
grab(); grab();
remove(); remove();
Parent = newParent; if (newParent)
newParent->addChild(this);
if (Parent)
Parent->addChild(this);
drop(); drop();
} }
@ -621,6 +617,8 @@ namespace scene
//! Pointer to the parent //! Pointer to the parent
ISceneNode* Parent; ISceneNode* Parent;
std::optional<ISceneNodeList::iterator> Iterator;
//! List of all children of this node //! List of all children of this node
std::list<ISceneNode*> Children; std::list<ISceneNode*> Children;