/// Generic list of objects access, possibly searching up or down from the current context /// /// Note that the template wrapper method should generally be used to have the correct return type, void DAGNode::getObjects(const sofa::core::objectmodel::ClassInfo& class_info, GetObjectsCallBack& container, const sofa::core::objectmodel::TagSet& tags, SearchDirection dir) const { if (dir == SearchRoot) { if (!getParents().empty()) { getRootContext()->getObjects(class_info, container, tags, dir); return; } else dir = SearchDown; // we are the root, search down from here. } if (dir != SearchParents) for (ObjectIterator it = this->object.begin(); it != this->object.end(); ++it) { core::objectmodel::BaseObject* obj = it->get(); void* result = class_info.dynamicCast(obj); if (result != NULL && (tags.empty() || (obj)->getTags().includes(tags))) container(result); } { switch(dir) { case Local: break; case SearchParents: case SearchUp: { // WORK IN PROGRESS // TODO: manage diamond setups to avoid multiple getObjects() calls on a Node... Parents parents = getParents(); for (Parents::iterator it = parents.begin(); it!=parents.end(); it++) dynamic_cast<Node*>(*it)->getObjects(class_info, container, tags, SearchUp); } break; case SearchDown: for(ChildIterator it = child.begin(); it != child.end(); ++it) { if ((*it)->isActive()) (*it)->getObjects(class_info, container, tags, dir); } break; case SearchRoot: std::cerr << "SearchRoot SHOULD NOT BE POSSIBLE HERE!\n"; break; } } }
/// Test if the given node is a parent of this node. bool DAGNode::hasParent(const BaseNode* node) const { Parents p = getParents(); return (p.end() != std::find(p.begin(), p.end(), node)); }
/// Generic object access, given a path from the current context /// /// Note that the template wrapper method should generally be used to have the correct return type, void* DAGNode::getObject(const sofa::core::objectmodel::ClassInfo& class_info, const std::string& path) const { if (path.empty()) { // local object return Node::getObject(class_info, Local); } else if (path[0] == '/') { // absolute path; let's start from root Parents parents = getParents(); if (parents.empty()) return getObject(class_info,std::string(path,1)); else return getRootContext()->getObject(class_info,path); } else if (std::string(path,0,2)==std::string("./")) { std::string newpath = std::string(path, 2); while (!newpath.empty() && path[0] == '/') newpath.erase(0); return getObject(class_info,newpath); } else if (std::string(path,0,3)==std::string("../")) { // tricky case: // let's test EACH parent and return the first object found (if any) std::string newpath = std::string(path, 3); while (!newpath.empty() && path[0] == '/') newpath.erase(0); Parents parents = getParents(); if (!parents.empty()) { for (Parents::iterator it = parents.begin(); it!=parents.end(); it++) { void* obj = dynamic_cast<Node*>(*it)->getObject(class_info,newpath); if (obj) return obj; } return 0; // not found in any parent node at all } else return getObject(class_info,newpath); } else { std::string::size_type pend = path.find('/'); if (pend == std::string::npos) pend = path.length(); std::string name ( path, 0, pend ); Node* child = getChild(name); if (child) { while (pend < path.length() && path[pend] == '/') ++pend; return child->getObject(class_info, std::string(path, pend)); } else if (pend < path.length()) { //std::cerr << "ERROR: child node "<<name<<" not found in "<<getPathName()<<std::endl; return NULL; } else { core::objectmodel::BaseObject* obj = simulation::Node::getObject(name); if (obj == NULL) { //std::cerr << "ERROR: object "<<name<<" not found in "<<getPathName()<<std::endl; return NULL; } else { void* result = class_info.dynamicCast(obj); if (result == NULL) { std::cerr << "ERROR: object "<<name<<" in "<<getPathName()<<" does not implement class "<<class_info.name()<<std::endl; return NULL; } else { return result; } } } } }
/// Generic object access, possibly searching up or down from the current context /// /// Note that the template wrapper method should generally be used to have the correct return type, void* DAGNode::getObject(const sofa::core::objectmodel::ClassInfo& class_info, const sofa::core::objectmodel::TagSet& tags, SearchDirection dir) const { if (dir == SearchRoot) { if (!getParents().empty()) return getRootContext()->getObject(class_info, tags, dir); else dir = SearchDown; // we are the root, search down from here. } void *result = NULL; #ifdef DEBUG_GETOBJECT std::string cname = class_info.name(); if (cname != std::string("N4sofa4core6ShaderE")) std::cout << "DAGNode: search for object of type " << class_info.name() << std::endl; std::string gname = "N4sofa9component8topology32TetrahedronSetGeometryAlgorithms"; bool isg = cname.length() >= gname.length() && std::string(cname, 0, gname.length()) == gname; #endif if (dir != SearchParents) for (ObjectIterator it = this->object.begin(); it != this->object.end(); ++it) { core::objectmodel::BaseObject* obj = it->get(); if (tags.empty() || (obj)->getTags().includes(tags)) { #ifdef DEBUG_GETOBJECT if (isg) std::cout << "DAGNode: testing object " << (obj)->getName() << " of type " << (obj)->getClassName() << std::endl; #endif result = class_info.dynamicCast(obj); if (result != NULL) { #ifdef DEBUG_GETOBJECT std::cout << "DAGNode: found object " << (obj)->getName() << " of type " << (obj)->getClassName() << std::endl; #endif break; } } } if (result == NULL) { switch(dir) { case Local: break; case SearchParents: case SearchUp: { Parents parents = getParents(); if (!parents.empty()) for (Parents::iterator it = parents.begin(); it!=parents.end() && !result; it++) result = dynamic_cast<Node*>(*it)->getObject(class_info, tags, SearchUp); } break; case SearchDown: for(ChildIterator it = child.begin(); it != child.end(); ++it) { result = (*it)->getObject(class_info, tags, dir); if (result != NULL) break; } break; case SearchRoot: std::cerr << "SearchRoot SHOULD NOT BE POSSIBLE HERE!\n"; break; } } return result; }