IECore::ConstCompoundObjectPtr SceneReader::computeGlobals( const Gaffer::Context *context, const ScenePlug *parent ) const { ConstSceneInterfacePtr s = scene( ScenePath() ); if( !s ) { return parent->globalsPlug()->defaultValue(); } CompoundObjectPtr result = new CompoundObject; // figure out which tags we want to convert into sets vector<InternedString> allTags; s->readTags( allTags, SceneInterface::LocalTag | SceneInterface::DescendantTag ); const std::string setsString = setsPlug()->getValue(); Tokenizer setsTokenizer( setsString, boost::char_separator<char>( " " ) ); vector<InternedString> tagsToLoadAsSets; for( vector<InternedString>::const_iterator tIt = allTags.begin(), tEIt = allTags.end(); tIt != tEIt; ++tIt ) { for( Tokenizer::const_iterator sIt = setsTokenizer.begin(), sEIt = setsTokenizer.end(); sIt != sEIt; ++sIt ) { if( match( tIt->value(), *sIt ) ) { tagsToLoadAsSets.push_back( *tIt ); } } } // sort so that we can use lower_bound() in loadSetsWalk(). sort( tagsToLoadAsSets.begin(), tagsToLoadAsSets.end() ); // make sets for each of them, and then defer to loadSetsWalk() // to do the work. IECore::CompoundDataPtr sets = result->member<IECore::CompoundData>( "gaffer:sets", /* throwExceptions = */ false, /* createIfMissing = */ true ); vector<PathMatcher *> pathMatchers; for( vector<InternedString>::const_iterator it = tagsToLoadAsSets.begin(), eIt = tagsToLoadAsSets.end(); it != eIt; ++it ) { PathMatcherDataPtr d = sets->member<PathMatcherData>( *it, /* throwExceptions = */ false, /* createIfMissing = */ true ); pathMatchers.push_back( &(d->writable()) ); } loadSetsWalk( s.get(), tagsToLoadAsSets, pathMatchers, vector<InternedString>() ); return result; }
IECore::ConstInternedStringVectorDataPtr SceneReader::computeChildNames( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const { ConstSceneInterfacePtr s = scene( path ); if( !s ) { return parent->childNamesPlug()->defaultValue(); } // get the child names InternedStringVectorDataPtr resultData = new InternedStringVectorData; vector<InternedString> &result = resultData->writable(); s->childNames( result ); // filter out any which don't have the right tags std::string tagsString = tagsPlug()->getValue(); if( !tagsString.empty() ) { typedef boost::tokenizer<boost::char_separator<char> > Tokenizer; Tokenizer tagsTokenizer( tagsString, boost::char_separator<char>( " " ) ); vector<InternedString> tags; std::copy( tagsTokenizer.begin(), tagsTokenizer.end(), back_inserter( tags ) ); vector<InternedString>::iterator newResultEnd = result.begin(); SceneInterface::NameList childTags; for( vector<InternedString>::const_iterator cIt = result.begin(), cEIt = result.end(); cIt != cEIt; ++cIt ) { ConstSceneInterfacePtr child = s->child( *cIt ); childTags.clear(); child->readTags( childTags, IECore::SceneInterface::EveryTag ); bool childMatches = false; for( SceneInterface::NameList::const_iterator tIt = childTags.begin(), tEIt = childTags.end(); tIt != tEIt; ++tIt ) { if( find( tags.begin(), tags.end(), *tIt ) != tags.end() ) { childMatches = true; break; } } if( childMatches ) { *newResultEnd++ = *cIt; } } result.erase( newResultEnd, result.end() ); } return resultData; }
IECore::ConstInternedStringVectorDataPtr SceneReader::computeSetNames( const Gaffer::Context *context, const ScenePlug *parent ) const { ConstSceneInterfacePtr s = scene( ScenePath() ); if( !s ) { return parent->setNamesPlug()->defaultValue(); } InternedStringVectorDataPtr result = new InternedStringVectorData(); s->readTags( result->writable(), SceneInterface::LocalTag | SceneInterface::DescendantTag ); return result; }
IECore::ConstCompoundObjectPtr SceneReader::computeAttributes( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const { std::string fileName = fileNamePlug()->getValue(); if( !fileName.size() ) { return parent->attributesPlug()->defaultValue(); } ConstSceneInterfacePtr s = SharedSceneInterfaces::get( fileName ); s = s->scene( path ); // read attributes SceneInterface::NameList nameList; s->attributeNames( nameList ); CompoundObjectPtr result = new CompoundObject; for( SceneInterface::NameList::iterator it = nameList.begin(); it != nameList.end(); ++it ) { // these internal attributes should be ignored: if( *it == SceneCache::animatedObjectTopologyAttribute ) { continue; } if( *it == SceneCache::animatedObjectPrimVarsAttribute ) { continue; } // the const cast is ok, because we're only using it to put the object into a CompoundObject that will // be treated as forever const after being returned from this function. result->members()[ std::string( *it ) ] = constPointerCast<Object>( s->readAttribute( *it, context->getFrame() / g_frameRate ) ); } // read tags and turn them into attributes of the form "user:tag:tagName" nameList.clear(); s->readTags( nameList, IECore::SceneInterface::LocalTag ); for( SceneInterface::NameList::const_iterator it = nameList.begin(); it != nameList.end(); ++it ) { if( it->string().compare( 0, 11, "ObjectType:" ) == 0 ) { continue; } result->members()["user:tag:"+it->string()] = g_trueBoolData; } return result; }
void SceneReader::hashAttributes( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const { ConstSceneInterfacePtr s = scene( path ); if( !s ) { h = parent->attributesPlug()->defaultValue()->Object::hash(); return; } SceneInterface::NameList attributeNames; s->attributeNames( attributeNames ); SceneInterface::NameList tagNames; s->readTags( tagNames, IECore::SceneInterface::LocalTag ); if( !attributeNames.size() && !tagNames.size() ) { h = parent->attributesPlug()->defaultValue()->Object::hash(); return; } FileSource::hashAttributes( path, context, parent, h ); bool animated = false; const SampledSceneInterface *ss = runTimeCast<const SampledSceneInterface>( s.get() ); if( !ss ) { animated = true; } else { for( SceneInterface::NameList::iterator it = attributeNames.begin(); it != attributeNames.end(); ++it ) { if( ss->numAttributeSamples( *it ) > 1 ) { animated = true; break; } } } if( animated ) { h.append( context->getFrame() ); } }
void OBJ_SceneCacheTransform::readTags( const OP_Node *node, SceneInterface::NameList &tags, int filter ) { // make sure its a SceneCacheNode if ( !node->hasParm( pFile.getToken() ) || !node->hasParm( pRoot.getToken() ) ) { return; } const SceneCacheNode<OP_Node> *sceneNode = reinterpret_cast< const SceneCacheNode<OP_Node>* >( node ); /// \todo: do we need to ensure the file exists first? ConstSceneInterfacePtr scene = OBJ_SceneCacheTransform::scene( sceneNode->getFile(), sceneNode->getPath() ); if ( !scene ) { return; } scene->readTags( tags, filter ); }
void SceneCacheNode<BaseType>::buildTagFilterMenu( void *data, PRM_Name *menu, int maxSize, const PRM_SpareData *, const PRM_Parm * ) { SceneCacheNode<BaseType> *node = reinterpret_cast<SceneCacheNode<BaseType>*>( data ); if ( !node ) { return; } menu[0].setToken( "*" ); menu[0].setLabel( "*" ); std::string file; if ( !node->ensureFile( file ) ) { // mark the end of our menu menu[1].setToken( 0 ); return; } ConstSceneInterfacePtr scene = node->scene( file, node->getPath() ); if ( !scene ) { // mark the end of our menu menu[1].setToken( 0 ); return; } SceneInterface::NameList tags; scene->readTags( tags ); std::vector<std::string> tagStrings; for ( SceneInterface::NameList::const_iterator it=tags.begin(); it != tags.end(); ++it ) { tagStrings.push_back( *it ); } node->createMenu( menu, tagStrings ); }
void LinkedScene::writeAttribute( const Name &name, const Object *attribute, double time ) { if ( m_readOnly ) { throw Exception( "No write access to scene file!" ); } if ( name == linkAttribute ) { bool firstTime = !m_mainScene->hasAttribute( fileNameLinkAttribute ); if ( firstTime ) { // if it's the first time, we better check if this level already has objects, tags or children // and raise exceptions to prevent weird configurations... if ( m_mainScene->hasObject() ) { throw Exception( "Links to external scenes cannot be created on locations where there's already an object saved!" ); } NameList names; m_mainScene->childNames( names ); if ( names.size() ) { throw Exception( "Links to external scenes cannot be created on locations where there are already child locations!" ); } } // we are creating a link! const CompoundData *d = runTimeCast< const CompoundData >(attribute); if ( !d ) { throw Exception( "SceneInterface:link attribute must be of type CompoundData!" ); } // open the linked scene int linkDepth; ConstDoubleDataPtr timeData = d->member< const DoubleData >( g_time ); const StringData *fileName = d->member< const StringData >( g_fileName ); const InternedStringVectorData *sceneRoot = d->member< const InternedStringVectorData >( g_root ); ConstSceneInterfacePtr linkedScene = expandLink( fileName, sceneRoot, linkDepth ); if ( !linkedScene ) { throw Exception( "Trying to store a broken link!" ); } // get the bounds of the linked scene const SampledSceneInterface *sampledScene = runTimeCast< const SampledSceneInterface >(linkedScene.get()); if ( sampledScene && !timeData ) { // When there's no time remapping we get all the bounding box samples from the linked scene, using the same time. if ( firstTime ) { size_t bounds = sampledScene->numBoundSamples(); for ( size_t b = 0; b < bounds; b++ ) { m_mainScene->writeBound( sampledScene->readBoundAtSample(b), sampledScene->boundSampleTime(b) ); } } } else { /// we store just the current bounding box if ( timeData ) { m_mainScene->writeBound( linkedScene->readBound(timeData->readable()), time ); } else { m_mainScene->writeBound( linkedScene->readBound(time), time ); } } if ( firstTime ) { // save the tags from the linked file to the current location so it gets propagated to the root. NameList tags; // Check if the position of the file we are trying to link to, has ancestor tags. // This situation is undesirable, as it will make LinkedScene return inconsistent ancestor tags before and after the link location. linkedScene->readTags(tags, SceneInterface::AncestorTag ); if ( tags.size() ) { std::string pathStr; SceneInterface::pathToString( sceneRoot->readable(), pathStr ); msg( Msg::Warning, "LinkedScene::writeAttribute", ( boost::format( "Detected ancestor tags while creating link to file %s at location %s." ) % fileName->readable() % pathStr ).str() ); } tags.clear(); /// copy all descendent and local tags as descendent tags (so we can distinguish from tags added in the LinkedScene) linkedScene->readTags(tags, SceneInterface::LocalTag|SceneInterface::DescendantTag ); static_cast< SceneCache *>(m_mainScene.get())->writeTags(tags, true); m_mainScene->writeAttribute( fileNameLinkAttribute, d->member< const StringData >( g_fileName ), time ); m_mainScene->writeAttribute( rootLinkAttribute, d->member< const InternedStringVectorData >( g_root ), time ); } /// we keep the information this level has a link, so we can prevent attempts to /// create children or save objects at this level. m_atLink = true; if( timeData ) { m_mainScene->writeAttribute( timeLinkAttribute, timeData, time ); } return; } m_mainScene->writeAttribute(name,attribute,time); }