Esempio n. 1
0
IECore::ConstInternedStringVectorDataPtr DeleteSets::computeSetNames( const Gaffer::Context *context, const ScenePlug *parent ) const
{
	ConstInternedStringVectorDataPtr inputSetNamesData = inPlug()->setNamesPlug()->getValue();
	const std::vector<InternedString> &inputSetNames = inputSetNamesData->readable();
	if( inputSetNames.empty() )
	{
		return inputSetNamesData;
	}

	InternedStringVectorDataPtr outputSetNamesData = new InternedStringVectorData;
	std::vector<InternedString> &outputSetNames = outputSetNamesData->writable();

	const std::string names = namesPlug()->getValue();
	const bool invert = invertNamesPlug()->getValue();

	for( std::vector<InternedString>::const_iterator it = inputSetNames.begin(); it != inputSetNames.end(); ++it )
	{
		if( StringAlgo::matchMultiple( *it, names ) != (!invert) )
		{
			outputSetNames.push_back( *it );
		}
	}

	return outputSetNamesData;
}
Esempio n. 2
0
IECore::ConstInternedStringVectorDataPtr Isolate::computeChildNames( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	ContextPtr tmpContext = filterContext( context );
	Context::Scope scopedContext( tmpContext.get() );

	if( mayPruneChildren( path, filterPlug()->getValue() ) )
	{
		// we may need to delete one or more of our children
		ConstInternedStringVectorDataPtr inputChildNamesData = inPlug()->childNamesPlug()->getValue();
		const vector<InternedString> &inputChildNames = inputChildNamesData->readable();

		InternedStringVectorDataPtr outputChildNamesData = new InternedStringVectorData;
		vector<InternedString> &outputChildNames = outputChildNamesData->writable();

		ScenePath childPath = path;
		childPath.push_back( InternedString() ); // for the child name
		for( vector<InternedString>::const_iterator it = inputChildNames.begin(), eIt = inputChildNames.end(); it != eIt; it++ )
		{
			childPath[path.size()] = *it;
			tmpContext->set( ScenePlug::scenePathContextName, childPath );
			if( filterPlug()->getValue() != Filter::NoMatch )
			{
				outputChildNames.push_back( *it );
			}
		}

		return outputChildNamesData;
	}
	else
	{
		// pass through
		return inPlug()->childNamesPlug()->getValue();
	}
}
Esempio n. 3
0
IECore::ConstInternedStringVectorDataPtr Instancer::computeBranchChildNames( const ScenePath &parentPath, const ScenePath &branchPath, const Gaffer::Context *context ) const
{
	if( branchPath.size() == 0 )
	{
		std::string name = namePlug()->getValue();
		if( !name.size() )
		{
			return outPlug()->childNamesPlug()->defaultValue();
		}
		ConstV3fVectorDataPtr p = sourcePoints( parentPath );
		if( !p || !p->readable().size() )
		{
			return outPlug()->childNamesPlug()->defaultValue();
		}
		
		InternedStringVectorDataPtr result = new InternedStringVectorData();
		for( size_t i=0; i<p->readable().size(); i++ )
		{
			result->writable().push_back( boost::lexical_cast<string>( i ) );
		}
		
		return result;
	}
	else
	{
		ContextPtr ic = instanceContext( context, branchPath );
		Context::Scope scopedContext( ic );
		return instancePlug()->childNamesPlug()->getValue();
	}
}
Esempio n. 4
0
IECore::CompoundDataPtr LinkedScene::linkAttributeData( const SceneInterface *scene )
{
	std::string f = scene->fileName();
	InternedStringVectorDataPtr r = new InternedStringVectorData();
	scene->path( r->writable() );
	CompoundDataPtr d = new CompoundData();
	d->writable()[g_fileName] = new StringData(f);
	d->writable()[g_root] = r;
	return d;
}
Esempio n. 5
0
void Duplicate::compute( ValuePlug *output, const Context *context ) const
{
	if( output == outParentPlug() )
	{
		ScenePath target;
		ScenePlug::stringToPath( targetPlug()->getValue(), target );
		string parent;
		for( size_t i = 0; i < target.size(); ++i )
		{
			parent += "/";
			if( i < target.size() - 1 )
			{
				parent += target[i];
			}
		}
		static_cast<StringPlug *>( output )->setValue( parent );
		return;
	}
	else if( output == childNamesPlug() )
	{
		// get the path to our target.
		ScenePath target;
		ScenePlug::stringToPath( targetPlug()->getValue(), target );

		// throw if the target path doesn't exist in the input. we need to compute the input child names at the
		// parent for this, but it's not necessary to represent that in the hash, because it doesn't actually
		// affect our result (if we throw we will have no result).
		ScenePath parent( target ); parent.pop_back();
		ConstInternedStringVectorDataPtr parentChildNamesData = inPlug()->childNames( parent );
		vector<InternedString> parentChildNames = parentChildNamesData->readable();
		if( find( parentChildNames.begin(), parentChildNames.end(), target.back() ) == parentChildNames.end() )
		{
			throw Exception( boost::str( boost::format( "Target \"%s\" does not exist" ) % target.back().string() ) );
		}
		
		// go ahead and generate our childnames by incrementing a numeric suffix on
		// the target name.
		std::string stem;
		int suffix = numericSuffix( target.back(), 0, &stem );
		
		InternedStringVectorDataPtr childNames = new InternedStringVectorData;
		
		boost::format formatter( "%s%d" );
		int copies = copiesPlug()->getValue();
		for( int i = 0; i < copies; ++i )
		{
			childNames->writable().push_back( boost::str( formatter % stem % ++suffix ) );
		}		
		
		static_cast<InternedStringVectorDataPlug *>( output )->setValue( childNames );
		return;
	}

	BranchCreator::compute( output, context );
}
Esempio n. 6
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;
}
Esempio n. 7
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;
}
Esempio n. 8
0
IECore::ConstInternedStringVectorDataPtr AlembicSource::computeChildNames( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	if( AlembicInputPtr i = inputForPath( path ) )
	{
		ConstStringVectorDataPtr c = i->childNames();
		InternedStringVectorDataPtr result = new InternedStringVectorData;
		result->writable().insert( result->writable().end(), c->readable().begin(), c->readable().end() );
		return result;
	}
	else
	{
		return parent->childNamesPlug()->defaultValue();
	}
}
Esempio n. 9
0
IECore::ConstInternedStringVectorDataPtr CompoundObjectSource::computeChildNames( const ScenePath &path, const Gaffer::Context *context, const GafferScene::ScenePlug *parent ) const
{
	ConstCompoundObjectPtr entry = entryForPath( path );
	ConstCompoundObjectPtr children = entry->member<CompoundObject>( "children" );
	if( !children )
	{
		return outPlug()->childNamesPlug()->defaultValue();
	}
	InternedStringVectorDataPtr result = new InternedStringVectorData;
	for( CompoundObject::ObjectMap::const_iterator it = children->members().begin(); it!=children->members().end(); it++ )
	{
		result->writable().push_back( it->first.value() );
	}
	return result;
}
Esempio n. 10
0
IECore::ConstInternedStringVectorDataPtr SceneReader::computeChildNames( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	std::string fileName = fileNamePlug()->getValue();
	if( !fileName.size() )
	{
		return parent->childNamesPlug()->defaultValue();
	}
	
	ConstSceneInterfacePtr s = SharedSceneInterfaces::get( fileName );
	s = s->scene( path );

	InternedStringVectorDataPtr result = new InternedStringVectorData;
	s->childNames( result->writable() );
	
	return result;
}
Esempio n. 11
0
Gaffer::ContextPtr Instancer::instanceContext( const Gaffer::Context *parentContext, const ScenePath &branchPath ) const
{
	if( branchPath.size() == 0 )
	{
		return 0;
	}
	
	ContextPtr result = new Context( *parentContext );

	InternedStringVectorDataPtr instancePath = new InternedStringVectorData;
	instancePath->writable().insert( instancePath->writable().end(), branchPath.begin() + 1, branchPath.end() );
	result->set( ScenePlug::scenePathContextName, instancePath.get() );
	
	result->set( "instancer:id", instanceIndex( branchPath ) );
	
	return result;
}
IECore::ConstInternedStringVectorDataPtr CompoundObjectSource::computeSetNames( const Gaffer::Context *context, const GafferScene::ScenePlug *parent ) const
{
	ConstCompoundObjectPtr compoundObject = inObject();

	if( ConstCompoundObjectPtr sets = compoundObject->member<CompoundObject>( "sets" ) )
	{
		InternedStringVectorDataPtr resultData = new InternedStringVectorData;
		std::vector<InternedString> &result = resultData->writable();
		for( CompoundObject::ObjectMap::const_iterator it = sets->members().begin(), eIt = sets->members().end(); it != eIt; ++it )
		{
			result.push_back( it->first );
		}
		return resultData;
	}

	return outPlug()->setNamesPlug()->defaultValue();
}
Esempio n. 13
0
IECore::ConstInternedStringVectorDataPtr Set::computeSetNames( const Gaffer::Context *context, const ScenePlug *parent ) const
{
	ConstInternedStringVectorDataPtr inNamesData = inPlug()->setNamesPlug()->getValue();

	const std::string &names = namePlug()->getValue();
	if( !names.size() )
	{
		return inNamesData;
	}

	if( modePlug()->getValue() == Remove )
	{
		return inNamesData;
	}

	vector<InternedString> tokenizedNames;
	StringAlgo::tokenize( names, ' ', tokenizedNames );

	// specific logic if we have only one item, to avoid the more complex logic of adding two lists together
	if( tokenizedNames.size() == 1 ) {
		const std::vector<InternedString> &inNames = inNamesData->readable();
		if( std::find( inNames.begin(), inNames.end(), tokenizedNames[0] ) != inNames.end() )
		{
			return inNamesData;
		}

		InternedStringVectorDataPtr resultData = inNamesData->copy();
		resultData->writable().push_back( tokenizedNames[0] );
		return resultData;
	}

	// inserting the new names into the vector
	// while making sure we don't have duplicates
	InternedStringVectorDataPtr resultData = inNamesData->copy();

	std::vector<InternedString> &result = resultData->writable();
	result.reserve( result.size() + tokenizedNames.size() );
	std::copy( tokenizedNames.begin(), tokenizedNames.end(), std::back_inserter( result ) );
	std::sort( result.begin(), result.end() );
	std::vector<InternedString>::iterator it;
	it = std::unique( result.begin(), result.end() );
	result.resize( std::distance( result.begin(), it ) );

	return resultData;
}
Esempio n. 14
0
IECore::ConstInternedStringVectorDataPtr Seeds::computeBranchChildNames( const ScenePath &parentPath, const ScenePath &branchPath, const Gaffer::Context *context ) const
{
	if( branchPath.size() == 0 )
	{
		std::string name = namePlug()->getValue();
		if( name.empty() )
		{
			return outPlug()->childNamesPlug()->defaultValue();
		}
		InternedStringVectorDataPtr result = new InternedStringVectorData();
		result->writable().push_back( name );
		return result;
	}
	else
	{
		return outPlug()->childNamesPlug()->defaultValue();
	}
}
Esempio n. 15
0
IECore::ConstInternedStringVectorDataPtr Grid::computeChildNames( const SceneNode::ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	if( path.size() <= 1 )
	{
		InternedStringVectorDataPtr resultData = new InternedStringVectorData;
		std::vector<InternedString> &result = resultData->writable();
		if( path.size() == 0 )
		{
			result.push_back( namePlug()->getValue() );
		}
		else
		{
			result.push_back( g_gridLinesName );
			result.push_back( g_centerLinesName );
			result.push_back( g_borderLinesName );
		}
		return resultData;
	}

	return outPlug()->childNamesPlug()->defaultValue();
}
Esempio n. 16
0
IECore::ConstInternedStringVectorDataPtr Instancer::computeBranchChildNames( const ScenePath &parentPath, const ScenePath &branchPath, const Gaffer::Context *context ) const
{
	if( branchPath.size() == 0 )
	{
		// "/"
		std::string name = namePlug()->getValue();
		if( name.empty() )
		{
			return outPlug()->childNamesPlug()->defaultValue();
		}
		InternedStringVectorDataPtr result = new InternedStringVectorData();
		result->writable().push_back( name );
		return result;
	}
	else if( branchPath.size() == 1 )
	{
		ConstV3fVectorDataPtr p = sourcePoints( parentPath );
		if( !p || !p->readable().size() )
		{
			return outPlug()->childNamesPlug()->defaultValue();
		}

		const size_t s = p->readable().size();
		InternedStringVectorDataPtr resultData = new InternedStringVectorData();
		vector<InternedString> &result = resultData->writable();
		result.resize( s );

		for( size_t i = 0; i < s ; ++i )
		{
			result[i] = InternedString( i );
		}

		return resultData;
	}
	else
	{
		InstanceScope instanceScope( context, branchPath );
		return instancePlug()->childNamesPlug()->getValue();
	}
}
Esempio n. 17
0
IECore::ConstInternedStringVectorDataPtr Group::computeChildNames( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	std::string groupName = namePlug()->getValue();

	if( path.size() == 0 )
	{
		InternedStringVectorDataPtr result = new InternedStringVectorData();
		result->writable().push_back( groupName );
		return result;
	}
	else if( path.size() == 1 )
	{
		ConstCompoundObjectPtr mapping = boost::static_pointer_cast<const CompoundObject>( mappingPlug()->getValue() );
		return mapping->member<InternedStringVectorData>( "__GroupChildNames" );
	}
	else
	{
		const ScenePlug *sourcePlug = 0;
		ScenePath source = sourcePath( path, groupName, &sourcePlug );
		return sourcePlug->childNames( source );
	}
}
Esempio n. 18
0
IECore::ConstInternedStringVectorDataPtr Group::computeSetNames( const Gaffer::Context *context, const ScenePlug *parent ) const
{
	InternedStringVectorDataPtr resultData = new InternedStringVectorData;
	vector<InternedString> &result = resultData->writable();
	for( ScenePlugIterator it( inPlugs() ); it != it.end(); ++it )
	{
		// This naive approach to merging set names preserves the order of the incoming names,
		// but at the expense of using linear search. We assume that the number of sets is small
		// enough and the InternedString comparison fast enough that this is OK.
		ConstInternedStringVectorDataPtr inputSetNamesData = (*it)->setNamesPlug()->getValue();
		const vector<InternedString> &inputSetNames = inputSetNamesData->readable();
		for( vector<InternedString>::const_iterator it = inputSetNames.begin(), eIt = inputSetNames.end(); it != eIt; ++it )
		{
			if( std::find( result.begin(), result.end(), *it ) == result.end() )
			{
				result.push_back( *it );
			}
		}
	}

	return resultData;
}
Esempio n. 19
0
IECore::ConstInternedStringVectorDataPtr BranchCreator::computeSetNames( const Gaffer::Context *context, const ScenePlug *parent ) const
{
	ConstInternedStringVectorDataPtr inputSetNamesData = inPlug()->setNamesPlug()->getValue();

	ConstCompoundDataPtr mapping = boost::static_pointer_cast<const CompoundData>( mappingPlug()->getValue() );
	if( !mapping->readable().size() )
	{
		return inputSetNamesData;
	}

	ConstInternedStringVectorDataPtr branchSetNamesData = computeBranchSetNames( mapping->member<InternedStringVectorData>( g_parentKey )->readable(), context );
	if( !branchSetNamesData )
	{
		return inputSetNamesData;
	}

	const vector<InternedString> &branchSetNames = branchSetNamesData->readable();
	if( !branchSetNames.size() )
	{
		return inputSetNamesData;
	}

	InternedStringVectorDataPtr resultData = inputSetNamesData->copy();
	vector<InternedString> &result = resultData->writable();

	// This naive approach to merging set names preserves the order of the incoming names,
	// but at the expense of using linear search. We assume that the number of sets is small
	// enough and the InternedString comparison fast enough that this is OK.
	for( vector<InternedString>::const_iterator it = branchSetNames.begin(), eIt = branchSetNames.end(); it != eIt; ++it )
	{
		if( std::find( result.begin(), result.end(), *it ) == result.end() )
		{
			result.push_back( *it );
		}
	}

	return resultData;
}
Esempio n. 20
0
IECore::ConstInternedStringVectorDataPtr Prune::computeChildNames( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	FilterPlug::SceneScope sceneScope( context, inPlug() );
	const Filter::Result m = (Filter::Result)filterPlug()->getValue();

	if( m & Filter::ExactMatch  )
	{
		return inPlug()->childNamesPlug()->defaultValue();
	}
	else if( m & Filter::DescendantMatch )
	{
		// we may need to delete one or more of our children
		ConstInternedStringVectorDataPtr inputChildNamesData = inPlug()->childNamesPlug()->getValue();
		const vector<InternedString> &inputChildNames = inputChildNamesData->readable();

		InternedStringVectorDataPtr outputChildNamesData = new InternedStringVectorData;
		vector<InternedString> &outputChildNames = outputChildNamesData->writable();

		ScenePath childPath = path;
		childPath.push_back( InternedString() ); // for the child name
		for( vector<InternedString>::const_iterator it = inputChildNames.begin(), eIt = inputChildNames.end(); it != eIt; ++it )
		{
			childPath[path.size()] = *it;
			sceneScope.set( ScenePlug::scenePathContextName, childPath );
			if( !(filterPlug()->getValue() & Filter::ExactMatch) )
			{
				outputChildNames.push_back( *it );
			}
		}

		return outputChildNamesData;
	}
	else
	{
		// pass through
		return inPlug()->childNamesPlug()->getValue();
	}
}
Esempio n. 21
0
void Duplicate::compute( ValuePlug *output, const Context *context ) const
{
	if( output == outParentPlug() )
	{
		ScenePath target;
		ScenePlug::stringToPath( targetPlug()->getValue(), target );
		string parent;
		for( size_t i = 0; i < target.size(); ++i )
		{
			parent += "/";
			if( i < target.size() - 1 )
			{
				parent += target[i];
			}
		}
		static_cast<StringPlug *>( output )->setValue( parent );
		return;
	}
	else if( output == childNamesPlug() )
	{
		// get the path to our target.
		ScenePath target;
		ScenePlug::stringToPath( targetPlug()->getValue(), target );

		// throw if the target path doesn't exist in the input. we need to compute the input child names at the
		// parent for this, but it's not necessary to represent that in the hash, because it doesn't actually
		// affect our result (if we throw we will have no result).
		ScenePath parent( target ); parent.pop_back();
		ConstInternedStringVectorDataPtr parentChildNamesData = inPlug()->childNames( parent );
		vector<InternedString> parentChildNames = parentChildNamesData->readable();
		if( find( parentChildNames.begin(), parentChildNames.end(), target.back() ) == parentChildNames.end() )
		{
			throw Exception( boost::str( boost::format( "Target \"%s\" does not exist" ) % target.back().string() ) );
		}

		// go ahead and generate our childnames.
		// these are composed of a stem and possibly
		// a numeric suffix. we default to deriving
		// these from the name of the target.

		std::string stem;
		int suffix = StringAlgo::numericSuffix( target.back(), 0, &stem );
		suffix++;

		const int copies = copiesPlug()->getValue();
		const std::string name = namePlug()->getValue();

		// if a name is provided explicitly, then
		// it overrides the name and suffix derived
		// from the target.
		if( name.size() )
		{
			std::string nameStem;
			const int nameSuffix = StringAlgo::numericSuffix( name, &nameStem );
			stem = nameStem;
			suffix = copies == 1 ? nameSuffix : max( nameSuffix, 1 );
		}

		InternedStringVectorDataPtr childNamesData = new InternedStringVectorData;
		std::vector<InternedString> &childNames = childNamesData->writable();
		childNames.reserve( copies );

		if( suffix == -1 )
		{
			assert( copies == 1 );
			childNames.push_back( stem );
		}
		else
		{
			boost::format formatter( "%s%d" );
			for( int i = 0; i < copies; ++i )
			{
				childNames.push_back( boost::str( formatter % stem % suffix++ ) );
			}
		}

		static_cast<InternedStringVectorDataPlug *>( output )->setValue( childNamesData );
		return;
	}

	BranchCreator::compute( output, context );
}
Esempio n. 22
0
IECore::ObjectPtr Group::computeMapping( const Gaffer::Context *context ) const
{
	/// \todo It might be more optimal to make our own Object subclass better tailored
	/// for passing the information we want.
	CompoundObjectPtr result = new CompoundObject();

	InternedStringVectorDataPtr childNamesData = new InternedStringVectorData();
	vector<InternedString> &childNames = childNamesData->writable();
	result->members()["__GroupChildNames"] = childNamesData;

	ObjectVectorPtr forwardMappings = new ObjectVector;
	result->members()["__GroupForwardMappings"] = forwardMappings;

	boost::regex namePrefixSuffixRegex( "^(.*[^0-9]+)([0-9]+)$" );
	boost::format namePrefixSuffixFormatter( "%s%d" );

	set<InternedString> allNames;
	for( ScenePlugIterator it( inPlugs() ); it != it.end(); ++it )
	{
		ConstInternedStringVectorDataPtr inChildNamesData = (*it)->childNames( ScenePath() );
		CompoundDataPtr forwardMapping = new CompoundData;
		forwardMappings->members().push_back( forwardMapping );

		const vector<InternedString> &inChildNames = inChildNamesData->readable();
		for( vector<InternedString>::const_iterator cIt = inChildNames.begin(), ceIt = inChildNames.end(); cIt!=ceIt; cIt++ )
		{
			InternedString name = *cIt;
			if( allNames.find( name ) != allNames.end() )
			{
				// uniqueify the name
				/// \todo This code is almost identical to code in GraphComponent::setName(),
				/// is there a sensible place it can be shared? The primary obstacle is that
				/// each use has a different method of storing the existing names.
				string prefix = name;
				int suffix = 1;

				boost::cmatch match;
				if( regex_match( name.value().c_str(), match, namePrefixSuffixRegex ) )
				{
					prefix = match[1];
					suffix = boost::lexical_cast<int>( match[2] );
				}

				do
				{
					name = boost::str( namePrefixSuffixFormatter % prefix % suffix );
					suffix++;
				} while( allNames.find( name ) != allNames.end() );
			}

			allNames.insert( name );
			childNames.push_back( name );
			forwardMapping->writable()[*cIt] = new InternedStringData( name );

			CompoundObjectPtr entry = new CompoundObject;
			entry->members()["n"] = new InternedStringData( *cIt );
			entry->members()["i"] = new IntData( it.base() - inPlugs()->children().begin() );
			result->members()[name] = entry;
		}
	}

	return result;
}
Esempio n. 23
0
/// \todo This mapping is very similar to the one created by the Group node. Perhaps
/// some generalisation of the two could form the basis for a nice unified HierarchyProcessor?
/// In this case I think we would have a custom mapping class rather than just pass around
/// CompoundData, and then parentAndBranchPaths() (or the future version of it) could be a method
/// on the mapping object.
IECore::ConstCompoundDataPtr BranchCreator::computeMapping( const Gaffer::Context *context ) const
{
	// get the parent. currently this is simply retrieving the value of parentPlug(),
	// but if we wanted to support multiple parents in future, here we would find the
	// parent appropriate to the current "scene:path" context entry.
	
	/// \todo We should introduce a plug type which stores its values as a ScenePath directly.
	ScenePlug::ScenePath parent;
	string parentAsString = parentPlug()->getValue();
	if( parentAsString.empty() )
	{
		// no parent specified so no mapping needed
		return static_cast<const CompoundData *>( mappingPlug()->defaultValue() );
	}
	ScenePlug::stringToPath( parentAsString, parent );
	
	// see if we're interested in creating children or not. if we're not
	// we can early out. no innuendo intended.
	
	ConstInternedStringVectorDataPtr branchChildNamesData = computeBranchChildNames( parent, ScenePath(), context );
	if( !branchChildNamesData->readable().size() )
	{
		return static_cast<const CompoundData *>( mappingPlug()->defaultValue() );
	}

	// create our result. in future it might be useful to create our datatype for this,
	// but for now we're just packing everything into a CompoundData.

	CompoundDataPtr result = new CompoundData;
	result->writable()["__BranchCreatorParent"] = new InternedStringVectorData( parent );
	
	// calculate the child names for the result. this is the full list of child names
	// immediately below the parent. we need to be careful to ensure that we rename any
	// branch names which conflict with existing children of the parent.
	
	ConstInternedStringVectorDataPtr inChildNamesData = inPlug()->childNames( parent );
	InternedStringVectorDataPtr childNamesData = new InternedStringVectorData();
	
	const vector<InternedString> &inChildNames = inChildNamesData->readable();
	const vector<InternedString> &branchChildNames = branchChildNamesData->readable();
	vector<InternedString> &childNames = childNamesData->writable();
	
	result->writable()["__BranchCreatorChildNames"] = childNamesData;
	
	set<InternedString> allNames;
	for( vector<InternedString>::const_iterator it = inChildNames.begin(); it != inChildNames.end(); ++it )
	{
		allNames.insert( *it );
		childNames.push_back( *it );
	}
	
	boost::regex namePrefixSuffixRegex( "^(.*[^0-9]+)([0-9]+)$" );
	boost::format namePrefixSuffixFormatter( "%s%d" );

	for( vector<InternedString>::const_iterator it = branchChildNames.begin(); it != branchChildNames.end(); ++it )
	{
		InternedString name = *it;
		if( allNames.find( name ) != allNames.end() )
		{
			// uniqueify the name
			string prefix = name;
			int suffix = 1;
			
			boost::cmatch match;
			if( regex_match( name.value().c_str(), match, namePrefixSuffixRegex ) )
			{
				prefix = match[1];
				suffix = boost::lexical_cast<int>( match[2] );
			}
			
			do
			{
				name = boost::str( namePrefixSuffixFormatter % prefix % suffix );
				suffix++;
			} while( allNames.find( name ) != allNames.end() );
		}
		
		allNames.insert( name );
		childNames.push_back( name );
		
		result->writable()[name] = new InternedStringData( *it );
	}
	
	return result;
}