OP_Node *LiveScene::retrieveChild( const Name &name, Path &contentPath, MissingBehaviour missingBehaviour ) const { OP_Node *node = retrieveNode( false, missingBehaviour ); OP_Node *contentBaseNode = retrieveNode( true, missingBehaviour ); if ( !node || !contentBaseNode ) { return 0; } OBJ_Node *objNode = node->castToOBJNode(); OBJ_Node *contentNode = contentBaseNode->castToOBJNode(); // check subnet children if ( node->isManager() || ( objNode && objNode->getObjectType() == OBJ_SUBNET ) ) { for ( int i=0; i < node->getNchildren(); ++i ) { OBJ_Node *child = node->getChild( i )->castToOBJNode(); // the contentNode is actually an extension of ourself if ( child == contentNode ) { continue; } if ( child && child->getName().equal( name.c_str() ) && !hasInput( child ) ) { return child; } } } if ( contentNode ) { // check connected outputs for ( unsigned i=0; i < contentNode->nOutputs(); ++i ) { OP_Node *child = contentNode->getOutput( i ); if ( child->getName().equal( name.c_str() ) ) { return child; } } // check child shapes within the geo if ( contentNode->getObjectType() == OBJ_GEOMETRY ) { OP_Context context( adjustedDefaultTime() ); if ( const GU_Detail *geo = contentNode->getRenderGeometry( context, false ) ) { GA_ROAttributeRef nameAttrRef = geo->findStringTuple( GA_ATTRIB_PRIMITIVE, "name" ); if ( nameAttrRef.isValid() ) { const GA_Attribute *nameAttr = nameAttrRef.getAttribute(); const GA_AIFSharedStringTuple *tuple = nameAttr->getAIFSharedStringTuple(); GA_Size numStrings = tuple->getTableEntries( nameAttr ); for ( GA_Size i=0; i < numStrings; ++i ) { GA_StringIndexType validatedIndex = tuple->validateTableHandle( nameAttr, i ); if ( validatedIndex < 0 ) { continue; } const char *currentName = tuple->getTableString( nameAttr, validatedIndex ); const char *match = matchPath( currentName ); if ( match && *match != *emptyString ) { std::pair<const char *, size_t> childMarker = nextWord( match ); std::string child( childMarker.first, childMarker.second ); if ( name == child ) { size_t contentSize = ( m_contentIndex ) ? m_path.size() - m_contentIndex : 0; if ( contentSize ) { contentPath.resize( contentSize ); std::copy( m_path.begin() + m_contentIndex, m_path.end(), contentPath.begin() ); } contentPath.push_back( name ); return contentNode; } } } } } } } if ( missingBehaviour == SceneInterface::ThrowIfMissing ) { Path p; path( p ); std::string pStr; pathToString( p, pStr ); throw Exception( "IECoreHoudini::LiveScene::retrieveChild: Path \"" + pStr + "\" has no child named " + name.string() + "." ); } return 0; }
void LiveScene::childNames( NameList &childNames ) const { OP_Node *node = retrieveNode(); OBJ_Node *objNode = node->castToOBJNode(); OBJ_Node *contentNode = retrieveNode( true )->castToOBJNode(); // add subnet children if ( node->isManager() || ( objNode && objNode->getObjectType() == OBJ_SUBNET ) ) { for ( int i=0; i < node->getNchildren(); ++i ) { OBJ_Node *child = node->getChild( i )->castToOBJNode(); // ignore children that have incoming connections, as those are actually grandchildren // also ignore the contentNode, which is actually an extension of ourself if ( child && child != contentNode && !hasInput( child ) ) { childNames.push_back( Name( child->getName() ) ); } } } if ( !contentNode ) { return; } // add connected outputs for ( unsigned i=0; i < contentNode->nOutputs(); ++i ) { childNames.push_back( Name( contentNode->getOutput( i )->getName() ) ); } // add child shapes within the geometry if ( contentNode->getObjectType() == OBJ_GEOMETRY ) { OP_Context context( adjustedDefaultTime() ); const GU_Detail *geo = contentNode->getRenderGeometry( context, false ); if ( !geo ) { return; } GA_ROAttributeRef nameAttrRef = geo->findStringTuple( GA_ATTRIB_PRIMITIVE, "name" ); if ( !nameAttrRef.isValid() ) { return; } const GA_Attribute *nameAttr = nameAttrRef.getAttribute(); const GA_AIFSharedStringTuple *tuple = nameAttr->getAIFSharedStringTuple(); GA_Size numStrings = tuple->getTableEntries( nameAttr ); for ( GA_Size i=0; i < numStrings; ++i ) { GA_StringIndexType validatedIndex = tuple->validateTableHandle( nameAttr, i ); if ( validatedIndex < 0 ) { continue; } const char *currentName = tuple->getTableString( nameAttr, validatedIndex ); const char *match = matchPath( currentName ); if ( match && *match != *emptyString ) { std::pair<const char *, size_t> childMarker = nextWord( match ); std::string child( childMarker.first, childMarker.second ); if ( std::find( childNames.begin(), childNames.end(), child ) == childNames.end() ) { childNames.push_back( child ); } } } } }