예제 #1
0
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;
}
예제 #2
0
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;
}
예제 #3
0
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;
}
예제 #4
0
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;
}
예제 #5
0
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 );
}
예제 #7
0
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 );
}
예제 #8
0
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);
}