/// Find an object given its name core::objectmodel::BaseObject* Node::getObject(const std::string& name) const { for (ObjectIterator it = object.begin(), itend = object.end(); it != itend; ++it) if ((*it)->getName() == name) return it->get(); return NULL; }
/// 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; } } }
/// 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 GNode::getObjects(const sofa::core::objectmodel::ClassInfo& class_info, GetObjectsCallBack& container, const sofa::core::objectmodel::TagSet& tags, SearchDirection dir) const { if (dir == SearchRoot) { if (parent() != NULL) { if (parent()->isActive()) { parent()->getObjects(class_info, container, tags, dir); return; } else 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: if (parent()) parent()->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; } } }
void AvidInfo::GetAvidTaggedValues(MetadataSet *parent_set, const mxfKey *item_key, vector<AvidTaggedValue*> *tags) { if (!parent_set->haveItem(item_key)) return; ObjectIterator *iter = parent_set->getStrongRefArrayItem(item_key); if (!iter) return; while (iter->next()) { AvidTaggedValue *tag = GetAvidTaggedValue(iter->get()); if (tag) tags->push_back(tag); } delete iter; }
/// 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* GNode::getObject(const sofa::core::objectmodel::ClassInfo& class_info, const sofa::core::objectmodel::TagSet& tags, SearchDirection dir) const { if (dir == SearchRoot) { if (parent() != NULL) return parent()->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 << "GNODE: 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 << "GNODE: testing object " << (obj)->getName() << " of type " << (obj)->getClassName() << std::endl; #endif result = class_info.dynamicCast(obj); if (result != NULL) { #ifdef DEBUG_GETOBJECT std::cout << "GNODE: found object " << (obj)->getName() << " of type " << (obj)->getClassName() << std::endl; #endif break; } } } if (result == NULL) { switch(dir) { case Local: break; case SearchParents: case SearchUp: if (parent()) result = parent()->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; }
void* Node::findLinkDestClass(const core::objectmodel::BaseClass* destType, const std::string& path, const core::objectmodel::BaseLink* link) { std::string pathStr; if (link) { if (!link->parseString(path,&pathStr)) return NULL; } else { if (!BaseLink::ParseString(path,&pathStr,NULL,this)) return NULL; } #ifdef DEBUG_LINK std::cout << "LINK: Looking for " << destType->className << "<" << destType->templateName << "> " << pathStr << " from Node " << getName() << std::endl; #endif std::size_t ppos = 0; std::size_t psize = pathStr.size(); if (ppos == psize || (ppos == psize-2 && pathStr[ppos] == '[' && pathStr[ppos+1] == ']')) // self-reference { #ifdef DEBUG_LINK std::cout << " self-reference link." << std::endl; #endif if (!link || !link->getOwnerBase()) return destType->dynamicCast(this); return destType->dynamicCast(link->getOwnerBase()); } Node* node = this; BaseObject* master = NULL; bool based = false; if (ppos < psize && pathStr[ppos] == '[') // relative index in the list of objects { if (pathStr[psize-1] != ']') { serr << "Invalid index-based path \"" << path << "\"" << sendl; return NULL; } int index = atoi(pathStr.c_str()+ppos+1); #ifdef DEBUG_LINK std::cout << " index-based path to " << index << std::endl; #endif ObjectReverseIterator it = object.rbegin(); ObjectReverseIterator itend = object.rend(); if (link && link->getOwnerBase()) { // index from last Base* b = link->getOwnerBase(); while (it != itend && *it != b) ++it; } while (it != itend && index < 0) { ++it; ++index; } if (it == itend) return NULL; #ifdef DEBUG_LINK std::cout << " found " << it->get()->getTypeName() << " " << it->get()->getName() << "." << std::endl; #endif return destType->dynamicCast(it->get()); } else if (ppos < psize && pathStr[ppos] == '/') // absolute path { #ifdef DEBUG_LINK std::cout << " absolute path" << std::endl; #endif node = dynamic_cast<Node*>(this->getRoot()); if (!node) return NULL; ++ppos; based = true; } while(ppos < psize) { if ((ppos+1 < psize && pathStr.substr(ppos,2) == "./") || pathStr.substr(ppos) == ".") { // this must be this node #ifdef DEBUG_LINK std::cout << " to current node" << std::endl; #endif ppos += 2; based = true; } else if ((ppos+2 < psize && pathStr.substr(ppos,3) == "../") // relative || pathStr.substr(ppos) == "..") { ppos += 3; if (master) { master = master->getMaster(); #ifdef DEBUG_LINK std::cout << " to master object " << master->getName() << std::endl; #endif } else { Parents parents = node->getParents(); if (parents.empty()) return NULL; node = dynamic_cast<Node*>(parents[0]); // TODO: explore other parents if (!node) return NULL; #ifdef DEBUG_LINK std::cout << " to parent node " << node->getName() << std::endl; #endif } based = true; } else if (pathStr[ppos] == '/') { // extra / #ifdef DEBUG_LINK std::cout << " extra '/'" << std::endl; #endif ppos += 1; } else { std::size_t p2pos = pathStr.find('/',ppos); if (p2pos == std::string::npos) p2pos = psize; std::string name = pathStr.substr(ppos,p2pos-ppos); ppos = p2pos+1; if (master) { #ifdef DEBUG_LINK std::cout << " to slave object " << name << std::endl; #endif master = master->getSlave(name); if (!master) return NULL; } else { for (;;) { BaseObject* obj = node->getObject(name); Node* child = node->getChild(name); if (child) { node = child; #ifdef DEBUG_LINK std::cout << " to child node " << name << std::endl; #endif break; } else if (obj) { master = obj; #ifdef DEBUG_LINK std::cout << " to object " << name << std::endl; #endif break; } if (based) return NULL; // this can still be found from an ancestor node Parents parents = node->getParents(); if (parents.empty()) return NULL; node = dynamic_cast<Node*>(parents[0]); // TODO: explore other parents if (!node) return NULL; #ifdef DEBUG_LINK std::cout << " looking in ancestor node " << node->getName() << std::endl; #endif } } based = true; } } if (master) { #ifdef DEBUG_LINK std::cout << " found " << master->getTypeName() << " " << master->getName() << "." << std::endl; #endif return destType->dynamicCast(master); } else { void* r = destType->dynamicCast(node); if (r) { #ifdef DEBUG_LINK std::cout << " found node " << node->getName() << "." << std::endl; #endif return r; } for (ObjectIterator it = node->object.begin(), itend = node->object.end(); it != itend; ++it) { BaseObject* obj = it->get(); void *o = destType->dynamicCast(obj); if (!o) continue; #ifdef DEBUG_LINK std::cout << " found " << obj->getTypeName() << " " << obj->getName() << "." << std::endl; #endif if (!r) r = o; else return NULL; // several objects are possible, this is an ambiguous path } if (r) return r; // no object found, we look in parent nodes if the searched class is one of the known standard single components (state, topology, ...) if (destType->hasParent(sofa::core::BaseState::GetClass())) return destType->dynamicCast(node->getState()); else if (destType->hasParent(core::topology::BaseMeshTopology::GetClass())) return destType->dynamicCast(node->getMeshTopology()); else if (destType->hasParent(core::topology::Topology::GetClass())) return destType->dynamicCast(node->getTopology()); else if (destType->hasParent(core::visual::Shader::GetClass())) return destType->dynamicCast(node->getShader()); else if (destType->hasParent(core::behavior::BaseAnimationLoop::GetClass())) return destType->dynamicCast(node->getAnimationLoop()); else if (destType->hasParent(core::behavior::OdeSolver::GetClass())) return destType->dynamicCast(node->getOdeSolver()); else if (destType->hasParent(core::collision::Pipeline::GetClass())) return destType->dynamicCast(node->getCollisionPipeline()); else if (destType->hasParent(core::visual::VisualLoop::GetClass())) return destType->dynamicCast(node->getVisualLoop()); return NULL; } }