Files
2025-12-05 08:54:02 +01:00

145 lines
4.0 KiB
Plaintext

// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
//
// Helper functions to search node(s) in a scene graph.
//
#ifndef tools_sg_search
#define tools_sg_search
#include "search_action"
#include "node"
namespace tools {
namespace sg {
template <class NODE>
inline NODE* find_first_node_of_class(std::ostream& a_out,node& a_from) {
search_action action(a_out);
action.reset();
action.set_what(search_action::search_node_of_class);
action.set_stop_at_first(true);
action.set_class(NODE::s_class());
a_from.search(action);
const std::vector<void*>& _objs = action.objs();
if(_objs.empty()) return 0;
return (NODE*)_objs[0];
}
inline node* find_first_node_with_class(std::ostream& a_out,node& a_from,const std::string& a_class) {
search_action action(a_out);
action.reset();
action.set_what(search_action::search_node_of_class);
action.set_stop_at_first(true);
action.set_class(a_class);
a_from.search(action);
const std::vector<void*>& _objs = action.objs();
if(_objs.empty()) return 0;
return (node*)_objs[0];
}
}}
#include "path"
namespace tools {
namespace sg {
inline const path_t& find_path(search_action& a_action,node& a_from,node& a_node,bool a_verbose) {
a_action.reset();
a_action.set_what(search_action::search_path_to_node);
a_action.set_node(&a_node);
a_from.search(a_action);
if(!a_action.done()) {
if(a_verbose) {
a_action.out() << "tools::sg::find_path :"
<< " not found node of class " << a_node.s_cls()
<< " from head node of class " << a_from.s_cls()
<< std::endl;
}
a_action.clear_path();
return a_action.path();
}
if(a_verbose) {
a_action.out() << "tools::sg::find_path :"
<< " found node of class " << a_node.s_cls()
<< " from head node of class " << a_from.s_cls()
<< std::endl;
}
const path_t& path = a_action.path();
if(path.empty()) {
if(a_verbose) {
a_action.out() << "tools::sg::find_path :"
<< " node has no path !"
<< std::endl;
}
return path;
}
if(&a_node!=path[path.size()-1]) {
a_action.out() << "tools::sg::find_path :"
<< " node / path tail mismatch !"
<< " node " << a_node.s_cls()
<< " tail " << path[path.size()-1]->s_cls()
<< std::endl;
a_action.clear_path();
return a_action.path();
}
return path;
}
inline const search_action::paths_t& find_paths(search_action& a_action,node& a_from,const std::string& a_class){
a_action.reset();
a_action.set_what(search_action::search_path_to_node_of_class);
a_action.set_class(a_class);
a_from.search(a_action);
return a_action.paths();
}
template <class NODE>
inline const search_action::paths_t& find_paths(search_action& a_action,node& a_from){
a_action.reset();
a_action.set_what(search_action::search_path_to_node_of_class);
a_action.set_class(NODE::s_class());
a_from.search(a_action);
return a_action.paths();
}
template <class NODE>
inline NODE* find_ancestor(std::ostream& a_out,node& a_from,node& a_node,bool a_verbose) {
search_action action(a_out);
return rfind<NODE>(find_path(action,a_from,a_node,a_verbose));
}
template <class CONTAINER>
inline CONTAINER* find_container(std::ostream& a_out,node& a_from,node& a_node,bool a_verbose) {
search_action action(a_out);
return container<CONTAINER>(find_path(action,a_from,a_node,a_verbose));
}
template <class NODE>
inline NODE* search_node(std::ostream& a_out,node& a_from) {
search_action sa(a_out);
const paths_t& paths = find_paths<NODE>(sa,a_from);
tools_vforcit(path_t,paths,it) {
NODE* _node = tail<NODE>(*it);
if(_node) return _node;
}
return 0;
}
template <class SELECTABLE>
inline SELECTABLE* search_selectable(std::ostream& a_out,node& a_from) {
search_action sa(a_out);
const paths_t& paths = find_paths<SELECTABLE>(sa,a_from);
tools_vforcit(path_t,paths,it) {
SELECTABLE* _node = tail<SELECTABLE>(*it);
if(_node && _node->border_visible.value()) return _node;
}
return 0;
}
}}
#endif