// Copyright (C) 2010, Guy Barrand. All rights reserved. // See the file tools.license for terms. // // Helper functions to handle node(s) paths in a scene graph. // #ifndef tools_sg_path #define tools_sg_path #include "node" #include "noderef" namespace tools { namespace sg { typedef std::vector path_t; inline bool parent_class(const path_t& a_path,std::string& a_class) { if(a_path.size()<2) {a_class.clear();return false;} node* parent = a_path[a_path.size()-2]; a_class = parent->s_cls(); return true; } template inline NODE* rfind(const path_t& a_path) { path_t::const_reverse_iterator it; for(it=a_path.rbegin();it!=a_path.rend();++it){ if(NODE* par = safe_cast(*(*it))) return par; } return 0; } template inline NODE* tail(const path_t& a_path) { if(a_path.empty()) return 0; node* _node = a_path[a_path.size()-1]; return safe_cast(*_node); } inline bool remove_tail(path_t& a_path) { if(a_path.empty()) return false; a_path.resize(a_path.size()-1); return true; } template inline CONTAINER* container(const path_t& a_path) { if(a_path.size()<2) return 0; node* parent = a_path[a_path.size()-2]; return safe_cast(*parent); } template inline CONTAINER* container_container(const path_t& a_path) { if(a_path.size()<3) return 0; node* parent = a_path[a_path.size()-3]; return safe_cast(*parent); } template inline bool rfind(const path_t& a_path,const node& a_from, CONTAINER*& a_container,WHAT*& a_what, int& a_container_index){ node* from = (node*)&a_from; path_t::size_type sz = a_path.size(); for(size_t index=1;index(*_node); if(a_container) { //the below does not compile. //a_what = a_container->rsearch_from(from); //if(a_what) return true; void* p = a_container->rsearch_from(from,WHAT::s_class(),false); if(p) { a_what = (WHAT*)p; a_container_index = int(sz-index-1); return true; } from = a_container; } else if(noderef* _ref = safe_cast(*_node)) { from = _ref; } else { // weird case : break; } } a_what = 0; a_container = 0; a_container_index = -1; return false; } template inline bool find_top(const path_t& a_path,const node& a_from, CONTAINER*& a_container,WHAT*& a_what, int& a_container_index){ a_what = 0; a_container = 0; a_container_index = -1; path_t _path = a_path; node* from = (node*)&a_from; while(true) { CONTAINER* container; WHAT* what; int idx; //index in path of container. if(!sg::rfind(_path,*from,container,what,idx)) { break; } a_container = container; a_what = what; a_container_index = idx; _path.resize(idx+1); _path.push_back(what); from = what; } return a_container?true:false; } typedef std::vector paths_t; }} #endif