// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors. // All rights reserved. // Code licensed under the BSD License. // http://www.anki3d.org/LICENSE namespace anki { template void Hierarchy::destroy() { if(m_parent != nullptr) { m_parent->removeChild(getSelf()); m_parent = nullptr; } // Remove all children (fast version) auto it = m_children.getBegin(); auto end = m_children.getEnd(); for(; it != end; ++it) { Value* child = *it; child->m_parent = nullptr; } m_children.destroy(); } template void Hierarchy::addChild(Value* child) { ANKI_ASSERT(child != nullptr && "Null arg"); ANKI_ASSERT(child != getSelf() && "Cannot put itself"); ANKI_ASSERT(child->m_parent == nullptr && "Child already has parent"); ANKI_ASSERT(child->findChild(getSelf()) == child->m_children.getEnd() && "Cyclic add"); ANKI_ASSERT(findChild(child) == m_children.getEnd() && "Already has that child"); child->m_parent = getSelf(); m_children.emplaceBack(child); } template void Hierarchy::removeChild(Value* child) { ANKI_ASSERT(child != nullptr && "Null arg"); ANKI_ASSERT(child->m_parent == getSelf() && "Child has other parent"); typename Container::Iterator it = findChild(child); ANKI_ASSERT(it != m_children.getEnd() && "Child not found"); m_children.erase(it); child->m_parent = nullptr; } template template FunctorContinue Hierarchy::visitChildren(TVisitorFunc vis) { auto it = m_children.getBegin(); FunctorContinue cont = FunctorContinue::kContinue; for(; it != m_children.getEnd() && cont == FunctorContinue::kContinue; it++) { cont = vis(*(*it)); if(cont == FunctorContinue::kContinue) { cont = (*it)->visitChildren(vis); } } return cont; } template template void Hierarchy::visitThisAndChildren(TVisitorFunc vis) { const FunctorContinue cont = vis(*getSelf()); if(cont == FunctorContinue::kContinue) { visitChildren(vis); } } template template void Hierarchy::visitTree(TVisitorFunc vis) { // Move to root Value* root = getSelf(); while(root->m_parent != nullptr) { root = root->m_parent; } root->visitThisAndChildren(vis); } template template FunctorContinue Hierarchy::visitChildrenMaxDepth(I maxDepth, TVisitorFunc vis) { ANKI_ASSERT(maxDepth >= 0); --maxDepth; FunctorContinue cont = FunctorContinue::kContinue; auto it = m_children.getBegin(); for(; it != m_children.getEnd() && cont == FunctorContinue::kContinue; ++it) { cont = vis(*(*it)); if(cont == FunctorContinue::kContinue && maxDepth >= 0) { cont = (*it)->visitChildrenMaxDepth(maxDepth, vis); } } return cont; } } // end namespace anki