示例#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;
}
示例#2
0
文件: Prune.cpp 项目: boberfly/gaffer
void Prune::hashChildNames( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const
{
	FilterPlug::SceneScope sceneScope( context, inPlug() );
	const Filter::Result m = (Filter::Result)filterPlug()->getValue();

	if( m & Filter::ExactMatch )
	{
		h = inPlug()->childNamesPlug()->defaultValue()->Object::hash();
	}
	else if( m & Filter::DescendantMatch )
	{
		// we might be computing new childnames for this level.
		FilteredSceneProcessor::hashChildNames( path, context, parent, h );

		ConstInternedStringVectorDataPtr inputChildNamesData = inPlug()->childNamesPlug()->getValue();
		const vector<InternedString> &inputChildNames = inputChildNamesData->readable();

		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 );
			filterPlug()->hash( h );
		}
	}
	else
	{
		// pass through
		h = inPlug()->childNamesPlug()->hash();
	}
}
示例#3
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();
	}
}
示例#4
0
IECore::MurmurHash SceneNode::hashOfTransformedChildBounds( const ScenePath &path, const ScenePlug *out, const IECore::InternedStringVectorData *childNamesData ) const
{
	ConstInternedStringVectorDataPtr computedChildNames;
	if( !childNamesData )
	{
		computedChildNames = out->childNames( path );
		childNamesData = computedChildNames.get();
	}
	const vector<InternedString> &childNames = childNamesData->readable();

	IECore::MurmurHash result;
	if( childNames.size() )
	{
		ContextPtr tmpContext = new Context( *Context::current(), Context::Borrowed );
		Context::Scope scopedContext( tmpContext.get() );

		ScenePath childPath( path );
		childPath.push_back( InternedString() ); // room for the child name
		for( vector<InternedString>::const_iterator it = childNames.begin(); it != childNames.end(); it++ )
		{
			childPath[path.size()] = *it;
			tmpContext->set( ScenePlug::scenePathContextName, childPath );
			out->boundPlug()->hash( result );
			out->transformPlug()->hash( result );
		}
	}
	else
	{
		result.append( typeId() );
		result.append( "emptyBound" );
	}
	return result;
}
示例#5
0
GafferScene::ConstPathMatcherDataPtr Duplicate::computeBranchSet( const ScenePath &parentPath, const IECore::InternedString &setName, const Gaffer::Context *context ) const
{
	ConstPathMatcherDataPtr inputSetData = inPlug()->set( setName );
	const PathMatcher &inputSet = inputSetData->readable();
	if( inputSet.isEmpty() )
	{
		return outPlug()->setPlug()->defaultValue();
	}

	PathMatcher subTree = inputSet.subTree( targetPlug()->getValue() );
	if( subTree.isEmpty() )
	{
		return outPlug()->setPlug()->defaultValue();
	}

	ConstInternedStringVectorDataPtr childNamesData = childNamesPlug()->getValue();
	const vector<InternedString> &childNames = childNamesData->readable();

	PathMatcherDataPtr resultData = new PathMatcherData;
	PathMatcher &result = resultData->writable();
	ScenePath prefix( 1 );
	for( vector<InternedString>::const_iterator it = childNames.begin(), eIt = childNames.end(); it != eIt; ++it )
	{
		prefix.back() = *it;
		result.addPaths( subTree, prefix );
	}

	return resultData;
}
示例#6
0
Imath::Box3f SceneNode::unionOfTransformedChildBounds( const ScenePath &path, const ScenePlug *out, const IECore::InternedStringVectorData *childNamesData ) const
{
	ConstInternedStringVectorDataPtr computedChildNames;
	if( !childNamesData )
	{
		computedChildNames = out->childNames( path );
		childNamesData = computedChildNames.get();
	}
	const vector<InternedString> &childNames = childNamesData->readable();

	Box3f result;
	if( childNames.size() )
	{
		ContextPtr tmpContext = new Context( *Context::current(), Context::Borrowed );
		Context::Scope scopedContext( tmpContext.get() );

		ScenePath childPath( path );
		childPath.push_back( InternedString() ); // room for the child name
		for( vector<InternedString>::const_iterator it = childNames.begin(); it != childNames.end(); it++ )
		{
			childPath[path.size()] = *it;
			tmpContext->set( ScenePlug::scenePathContextName, childPath );
			Box3f childBound = out->boundPlug()->getValue();
			childBound = transform( childBound, out->transformPlug()->getValue() );
			result.extendBy( childBound );
		}
	}
	return result;
}
示例#7
0
		virtual task *execute()
		{				
			
			ContextPtr context = new Context( *m_context );
			context->set( ScenePlug::scenePathContextName, m_scenePath );
			Context::Scope scopedContext( context );
			
			m_scenePlug->transformPlug()->getValue();
			m_scenePlug->boundPlug()->getValue();
			m_scenePlug->attributesPlug()->getValue();
			m_scenePlug->objectPlug()->getValue();
				
			ConstInternedStringVectorDataPtr childNamesData = m_scenePlug->childNamesPlug()->getValue();
			const vector<InternedString> &childNames = childNamesData->readable();
			
			set_ref_count( 1 + childNames.size() );
			
			ScenePlug::ScenePath childPath = m_scenePath;
			childPath.push_back( InternedString() ); // space for the child name
			for( vector<InternedString>::const_iterator it = childNames.begin(), eIt = childNames.end(); it != eIt; it++ )
			{
				childPath[m_scenePath.size()] = *it;
				SceneTraversalTask *t = new( allocate_child() ) SceneTraversalTask( m_scenePlug, m_context, childPath );
				spawn( *t );
			}
			
			wait_for_all();
			
			return 0;
		}
示例#8
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 );
}
示例#9
0
void SceneWriter::writeLocation( const GafferScene::ScenePlug *scene, const ScenePlug::ScenePath &scenePath, Context *context, IECore::SceneInterface *output, double time ) const
{
	context->set( ScenePlug::scenePathContextName, scenePath );

	ConstCompoundObjectPtr attributes = scene->attributesPlug()->getValue();
	for( CompoundObject::ObjectMap::const_iterator it = attributes->members().begin(), eIt = attributes->members().end(); it != eIt; it++ )
	{
		output->writeAttribute( it->first, it->second.get(), time );
	}

	if( scenePath.empty() )
	{
		ConstCompoundObjectPtr globals = scene->globalsPlug()->getValue();
		output->writeAttribute( "gaffer:globals", globals.get(), time );
	}

	ConstObjectPtr object = scene->objectPlug()->getValue();

	if( object->typeId() != IECore::NullObjectTypeId && scenePath.size() > 0 )
	{
		output->writeObject( object.get(), time );
	}

	Imath::Box3f b = scene->boundPlug()->getValue();

	output->writeBound( Imath::Box3d( Imath::V3f( b.min ), Imath::V3f( b.max ) ), time );

	if( scenePath.size() )
	{
		Imath::M44f t = scene->transformPlug()->getValue();
		Imath::M44d transform(
			t[0][0], t[0][1], t[0][2], t[0][3],
			t[1][0], t[1][1], t[1][2], t[1][3],
			t[2][0], t[2][1], t[2][2], t[2][3],
			t[3][0], t[3][1], t[3][2], t[3][3]
		);

		output->writeTransform( new IECore::M44dData( transform ), time );
	}

	ConstInternedStringVectorDataPtr childNames = scene->childNamesPlug()->getValue();

	ScenePlug::ScenePath childScenePath = scenePath;
	childScenePath.push_back( InternedString() );
	for( vector<InternedString>::const_iterator it=childNames->readable().begin(); it!=childNames->readable().end(); it++ )
	{
		childScenePath[scenePath.size()] = *it;

		SceneInterfacePtr outputChild = output->child( *it, SceneInterface::CreateIfMissing );

		writeLocation( scene, childScenePath, context, outputChild.get(), time );
	}
}
示例#10
0
void ScenePath::doChildren( std::vector<PathPtr> &children ) const
{
	Context::Scope scopedContext( m_context.get() );
	ConstInternedStringVectorDataPtr childNamesData = m_scene->childNames( names() );
	const std::vector<InternedString> &childNames = childNamesData->readable();
	ScenePlug::ScenePath childPath( names() );
	childPath.push_back( InternedString() ); // for the child name
	children.reserve( childNames.size() );
	for( std::vector<InternedString>::const_iterator it = childNames.begin(), eIt = childNames.end(); it != eIt; ++it )
	{
		childPath.back() = *it;
		children.push_back( new ScenePath( m_scene, m_context, childPath, root(), const_cast<PathFilter *>( getFilter() ) ) );
	}
}
示例#11
0
void SetVisualiser::compute( Gaffer::ValuePlug *output, const Gaffer::Context *context ) const
{
	if( output == outSetsPlug() )
	{
		const StringAlgo::MatchPattern requestedSetsPattern = setsPlug()->getValue();

		std::vector<InternedString> names;
		std::vector<Color3f> colors;

		if( !requestedSetsPattern.empty() )
		{
			const std::vector<Override> overrides = unpackOverrides( colorOverridesPlug() );

			ConstInternedStringVectorDataPtr allSetNamesData = inPlug()->setNames();

			// Sorting now makes everything easier, otherwise you have to
			// sort parallel arrays later, which is a pain.
			std::vector<InternedString> allNames = allSetNamesData->readable();
			std::sort( allNames.begin(), allNames.end(), internedStringCompare );

			for( auto &name : allNames )
			{
				// Gaffer has some internal sets that begin with the '__'
				// prefix. These are usually Lights, Cameras, etc... We filter
				// these out as they most of their objects don't even draw in
				// the viewer in a meaningful way for visualising set Membership
				if( boost::starts_with( name.string(), "__" ) )
				{
					continue;
				}

				if( StringAlgo::matchMultiple( name, requestedSetsPattern ) )
				{
					names.push_back( name );
					colors.push_back( colorForSetName( name, overrides ) );
				}
			}
		}

		CompoundDataPtr data = new CompoundData();
		data->writable()["names"] = new InternedStringVectorData( names );
		data->writable()["colors"] = new Color3fVectorData( colors );
		static_cast<AtomicCompoundDataPlug *>( output )->setValue( data );
	}
	else
	{
		SceneElementProcessor::compute( output, context );
	}
}
示例#12
0
bool SceneView::expandWalk( const std::string &path, size_t depth, PathMatcher &expanded, RenderableGadget::Selection &selected )
{
	bool result = false;
	
	ScenePlug::ScenePath scenePath;
	ScenePlug::stringToPath( path, scenePath );
	ConstInternedStringVectorDataPtr childNamesData = preprocessedInPlug<ScenePlug>()->childNames( scenePath );
	const vector<InternedString> &childNames = childNamesData->readable();

	if( childNames.size() )
	{
		// expand ourselves to show our children, and make sure we're
		// not selected - we only want selection at the leaf levels of
		// our expansion.
		result |= expanded.addPath( path );
		result |= selected.erase( path );
		for( vector<InternedString>::const_iterator cIt = childNames.begin(), ceIt = childNames.end(); cIt != ceIt; cIt++ )
		{
			std::string childPath( path );
			if( *childPath.rbegin() != '/' )
			{
				childPath += '/';
			}
			childPath += cIt->string();
			if( depth == 1 )
			{
				// at the bottom of the expansion - just select the child
				result |= selected.insert( childPath ).second;
			}
			else
			{
				// continue the expansion
				result |= expandWalk( childPath, depth - 1, expanded, selected );
			}
		}
	}
	else
	{
		// we have no children, just make sure we're selected to mark the
		// leaf of the expansion.
		result |= selected.insert( path ).second;
	}

	return result;
}
示例#13
0
文件: Set.cpp 项目: boberfly/gaffer
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;
}
示例#14
0
IECore::ConstCompoundDataPtr GafferScene::sets( const ScenePlug *scene )
{
	ConstInternedStringVectorDataPtr setNamesData = scene->setNamesPlug()->getValue();
	std::vector<GafferScene::ConstPathMatcherDataPtr> setsVector;
	setsVector.resize( setNamesData->readable().size(), NULL );

	Sets setsCompute( scene, setNamesData->readable(), setsVector );
	parallel_for( tbb::blocked_range<size_t>( 0, setsVector.size() ), setsCompute );

	CompoundDataPtr result = new CompoundData;
	for( size_t i = 0, e = setsVector.size(); i < e; ++i )
	{
		// The const_pointer_cast is ok because we're just using it to put the set into
		// a container that will be const on return - we never modify the set itself.
		result->writable()[setNamesData->readable()[i]] = boost::const_pointer_cast<GafferScene::PathMatcherData>( setsVector[i] );
	}
	return result;
}
示例#15
0
void InteractiveRender::updateShadersWalk( const ScenePlug::ScenePath &path )
{
	/// \todo Keep a track of the hashes of the shaders at each path,
	/// and use it to only update the shaders when they've changed.
	ConstCompoundObjectPtr attributes = inPlug()->attributes( path );

	// terminate recursion for invisible locations
	ConstBoolDataPtr visibility = attributes->member<BoolData>( SceneInterface::visibilityName );
	if( visibility && ( !visibility->readable() ) )
	{
		return;
	}

	ConstObjectVectorPtr shader = attributes->member<ObjectVector>( "shader" );
	if( shader )
	{
		std::string name;
		ScenePlug::pathToString( path, name );

		CompoundDataMap parameters;
		parameters["exactscopename"] = new StringData( name );
		{
			EditBlock edit( m_renderer.get(), "attribute", parameters );

			for( ObjectVector::MemberContainer::const_iterator it = shader->members().begin(), eIt = shader->members().end(); it != eIt; it++ )
			{
				const StateRenderable *s = runTimeCast<const StateRenderable>( it->get() );
				if( s )
				{
					s->render( m_renderer.get() );
				}
			}
		}
	}

	ConstInternedStringVectorDataPtr childNames = inPlug()->childNames( path );
	ScenePlug::ScenePath childPath = path;
	childPath.push_back( InternedString() ); // for the child name
	for( vector<InternedString>::const_iterator it=childNames->readable().begin(); it!=childNames->readable().end(); it++ )
	{
		childPath[path.size()] = *it;
		updateShadersWalk( childPath );
	}
}
示例#16
0
Imath::M44f Duplicate::computeBranchTransform( const ScenePath &parentPath, const ScenePath &branchPath, const Gaffer::Context *context ) const
{
	ScenePath source;
	sourcePath( branchPath, source );
	Imath::M44f result = inPlug()->transform( source );
	if( branchPath.size() == 1 )
	{
		const Imath::M44f matrix = transformPlug()->matrix();
		ConstInternedStringVectorDataPtr childNamesData = childNamesPlug()->getValue();
		const vector<InternedString> &childNames = childNamesData->readable();

		size_t i = 0;
		do
		{
			result = result * matrix;
		} while( i < childNames.size() && branchPath[0] != childNames[i++] );
	}
	return result;
}
示例#17
0
void SetVisualiser::hashProcessedAttributes( const ScenePath &path, const Gaffer::Context *context, MurmurHash &h ) const
{
	ConstCompoundDataPtr outSetsData = outSetsPlug()->getValue();

	outSetsData->hash( h );
	includeInheritedPlug()->hash( h );

	// We also need to consider each of our candidate sets membership
	// definition (which we didn't need to when computing outSets).
	// outSetsData is map of names -> colors.
	ConstInternedStringVectorDataPtr setNames = outSetsData->member<InternedStringVectorData>( "names" );
	for( auto &setName : setNames->readable() )
	{
		h.append( inPlug()->setHash( setName ) );
	}

	h.append( path.data(), path.size() );
	stripeWidthPlug()->hash( h );
}
示例#18
0
bool GafferScene::SceneAlgo::exists( const ScenePlug *scene, const ScenePlug::ScenePath &path )
{
	ScenePlug::PathScope pathScope( Context::current() );

	ScenePlug::ScenePath p; p.reserve( path.size() );
	for( ScenePlug::ScenePath::const_iterator it = path.begin(), eIt = path.end(); it != eIt; ++it )
	{
		pathScope.setPath( p );
		ConstInternedStringVectorDataPtr childNamesData = scene->childNamesPlug()->getValue();
		const vector<InternedString> &childNames = childNamesData->readable();
		if( find( childNames.begin(), childNames.end(), *it ) == childNames.end() )
		{
			return false;
		}
		p.push_back( *it );
	}

	return true;
}
示例#19
0
bool GafferScene::exists( const ScenePlug *scene, const ScenePlug::ScenePath &path )
{
	ContextPtr context = new Context( *Context::current(), Context::Borrowed );
	Context::Scope scopedContext( context.get() );

	ScenePlug::ScenePath p; p.reserve( path.size() );
	for( ScenePlug::ScenePath::const_iterator it = path.begin(), eIt = path.end(); it != eIt; ++it )
	{
		context->set( ScenePlug::scenePathContextName, p );
		ConstInternedStringVectorDataPtr childNamesData = scene->childNamesPlug()->getValue();
		const vector<InternedString> &childNames = childNamesData->readable();
		if( find( childNames.begin(), childNames.end(), *it ) == childNames.end() )
		{
			return false;
		}
		p.push_back( *it );
	}

	return true;
}
示例#20
0
bool SceneView::expandWalk( const GafferScene::ScenePlug::ScenePath &path, size_t depth, PathMatcher &expanded, PathMatcher &selected )
{
	bool result = false;

	ConstInternedStringVectorDataPtr childNamesData = preprocessedInPlug<ScenePlug>()->childNames( path );
	const vector<InternedString> &childNames = childNamesData->readable();

	if( childNames.size() )
	{
		// expand ourselves to show our children, and make sure we're
		// not selected - we only want selection at the leaf levels of
		// our expansion.
		result |= expanded.addPath( path );
		result |= selected.removePath( path );

		ScenePlug::ScenePath childPath = path;
		childPath.push_back( InternedString() ); // room for the child name
		for( vector<InternedString>::const_iterator cIt = childNames.begin(), ceIt = childNames.end(); cIt != ceIt; cIt++ )
		{
			childPath.back() = *cIt;
			if( depth == 1 )
			{
				// at the bottom of the expansion - just select the child
				result |= selected.addPath( childPath );
			}
			else
			{
				// continue the expansion
				result |= expandWalk( childPath, depth - 1, expanded, selected );
			}
		}
	}
	else
	{
		// we have no children, just make sure we're selected to mark the
		// leaf of the expansion.
		result |= selected.addPath( path );
	}

	return result;
}
示例#21
0
void Isolate::hashChildNames( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const
{
	const SetsToKeep setsToKeep( this );

	FilterPlug::SceneScope sceneScope( context, inPlug() );

	if( mayPruneChildren( path, filterPlug()->getValue(), setsToKeep ) )
	{
		// we might be computing new childnames for this level.
		FilteredSceneProcessor::hashChildNames( path, context, parent, h );

		const IECore::MurmurHash inputChildNamesHash = inPlug()->childNamesPlug()->hash();
		h.append( inputChildNamesHash );

		ConstInternedStringVectorDataPtr inputChildNamesData = inPlug()->childNamesPlug()->getValue( &inputChildNamesHash );
		const vector<InternedString> &inputChildNames = inputChildNamesData->readable();

		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;
			const unsigned m = setsToKeep.match( childPath );
			if( m == Filter::NoMatch )
			{
				sceneScope.set( ScenePlug::scenePathContextName, childPath );
				filterPlug()->hash( h );
			}
			else
			{
				h.append( 0 );
			}
		}
	}
	else
	{
		// pass through
		h = inPlug()->childNamesPlug()->hash();
	}
}
示例#22
0
文件: Group.cpp 项目: mor-vfx/gaffer
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;
}
示例#23
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;
}
示例#24
0
文件: Prune.cpp 项目: boberfly/gaffer
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();
	}
}
示例#25
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;
}
示例#26
0
void SceneProcedural::render( Renderer *renderer ) const
{
	tbb::task_scheduler_init tsi( tbb::task_scheduler_init::deferred );
	initializeTaskScheduler( tsi );

	Context::Scope scopedContext( m_context.get() );

	std::string name;
	ScenePlug::pathToString( m_scenePath, name );

	/// \todo See above.
	try
	{

		// get all the attributes, and early out if we're not visibile

		const BoolData *visibilityData = m_attributesObject->member<BoolData>( g_visibleAttributeName );
		if( visibilityData && !visibilityData->readable() )
		{

			if( !m_rendered )
			{
				decrementPendingProcedurals();
			}
			m_rendered = true;
			return;
		}

		// if we are visible then make an attribute block to contain everything, set the name
		// and get on with generating things.

		AttributeBlock attributeBlock( renderer );

		renderer->setAttribute( "name", new StringData( name ) );

		// transform

		std::set<float> transformTimes;
		motionTimes( ( m_options.transformBlur && m_attributes.transformBlur ) ? m_attributes.transformBlurSegments : 0, transformTimes );
		{
			ContextPtr timeContext = new Context( *m_context, Context::Borrowed );
			Context::Scope scopedTimeContext( timeContext.get() );

			MotionBlock motionBlock( renderer, transformTimes, transformTimes.size() > 1 );

			for( std::set<float>::const_iterator it = transformTimes.begin(), eIt = transformTimes.end(); it != eIt; it++ )
			{
				timeContext->setFrame( *it );
				renderer->concatTransform( m_scenePlug->transformPlug()->getValue() );
			}
		}

		// attributes

		outputAttributes( m_attributesObject.get(), renderer );

		// object

		std::set<float> deformationTimes;
		motionTimes( ( m_options.deformationBlur && m_attributes.deformationBlur ) ? m_attributes.deformationBlurSegments : 0, deformationTimes );
		{
			ContextPtr timeContext = new Context( *m_context, Context::Borrowed );
			Context::Scope scopedTimeContext( timeContext.get() );

			unsigned timeIndex = 0;
			for( std::set<float>::const_iterator it = deformationTimes.begin(), eIt = deformationTimes.end(); it != eIt; it++, timeIndex++ )
			{
				timeContext->setFrame( *it );
				ConstObjectPtr object = m_scenePlug->objectPlug()->getValue();
				if( const Primitive *primitive = runTimeCast<const Primitive>( object.get() ) )
				{
					if( deformationTimes.size() > 1 && timeIndex == 0 )
					{
						renderer->motionBegin( deformationTimes );
					}

						primitive->render( renderer );

					if( deformationTimes.size() > 1 && timeIndex == deformationTimes.size() - 1 )
					{
						renderer->motionEnd();
					}
				}
				else if( const VisibleRenderable* renderable = runTimeCast< const VisibleRenderable >( object.get() ) )
				{
					renderable->render( renderer );
					break; // no motion blur for these chappies.
				}

			}
		}

		// children

		ConstInternedStringVectorDataPtr childNames = m_scenePlug->childNamesPlug()->getValue();
		if( childNames->readable().size() )
		{
			// Creating a SceneProcedural involves an attribute/bound evaluation, which are
			// potentially expensive, so we're parallelizing them.

			// allocate space for child procedurals:
			SceneProceduralCreate::SceneProceduralContainer childProcedurals( childNames->readable().size() );

			// create procedurals in parallel:
			SceneProceduralCreate s(
				childProcedurals,
				*this,
				childNames->readable()
			);
			tbb::parallel_for( tbb::blocked_range<int>( 0, childNames->readable().size() ), s );

			// send to the renderer in series:

			std::vector<SceneProceduralPtr>::const_iterator procIt = childProcedurals.begin(), procEit = childProcedurals.end();
			for( ; procIt != procEit; ++procIt )
			{
				renderer->procedural( *procIt );
			}
		}
	}
	catch( const std::exception &e )
	{
		IECore::msg( IECore::Msg::Error, "SceneProcedural::render() " + name, e.what() );
	}
	if( !m_rendered )
	{
		decrementPendingProcedurals();
	}
	m_rendered = true;
}
示例#27
0
void SceneProcedural::render( RendererPtr renderer ) const
{	
	Context::Scope scopedContext( m_context );
	
	/// \todo See above.
	try
	{
	
		// get all the attributes, and early out if we're not visibile
	
		ConstCompoundObjectPtr attributes = m_scenePlug->attributesPlug()->getValue();
		const BoolData *visibilityData = attributes->member<BoolData>( "gaffer:visibility" );
		if( visibilityData && !visibilityData->readable() )
		{
			return;
		}

		// if we are visible then make an attribute block to contain everything, set the name
		// and get on with generating things.

		AttributeBlock attributeBlock( renderer );

		std::string name = "";
		for( ScenePlug::ScenePath::const_iterator it = m_scenePath.begin(), eIt = m_scenePath.end(); it != eIt; it++ )
		{
			name += "/" + it->string();
		}
		renderer->setAttribute( "name", new StringData( name ) );

		// transform
		
		std::set<float> transformTimes;
		motionTimes( ( m_options.transformBlur && m_attributes.transformBlur ) ? m_attributes.transformBlurSegments : 0, transformTimes );
		{
			ContextPtr timeContext = new Context( *m_context );
			Context::Scope scopedTimeContext( timeContext );
			
			MotionBlock motionBlock( renderer, transformTimes, transformTimes.size() > 1 );
			
			for( std::set<float>::const_iterator it = transformTimes.begin(), eIt = transformTimes.end(); it != eIt; it++ )
			{
				timeContext->setFrame( *it );
				renderer->concatTransform( m_scenePlug->transformPlug()->getValue() );
			}
		}
		
		// attributes
		
		for( CompoundObject::ObjectMap::const_iterator it = attributes->members().begin(), eIt = attributes->members().end(); it != eIt; it++ )
		{
			if( const StateRenderable *s = runTimeCast<const StateRenderable>( it->second.get() ) )
			{
				s->render( renderer );
			}
			else if( const ObjectVector *o = runTimeCast<const ObjectVector>( it->second.get() ) )
			{
				for( ObjectVector::MemberContainer::const_iterator it = o->members().begin(), eIt = o->members().end(); it != eIt; it++ )
				{
					const StateRenderable *s = runTimeCast<const StateRenderable>( it->get() );
					if( s )
					{
						s->render( renderer );
					}
				}
			}
			else if( const Data *d = runTimeCast<const Data>( it->second.get() ) )
			{
				renderer->setAttribute( it->first, d );
			}
		}
		
		// object
		
		std::set<float> deformationTimes;
		motionTimes( ( m_options.deformationBlur && m_attributes.deformationBlur ) ? m_attributes.deformationBlurSegments : 0, deformationTimes );
		{
			ContextPtr timeContext = new Context( *m_context );
			Context::Scope scopedTimeContext( timeContext );
		
			unsigned timeIndex = 0;
			for( std::set<float>::const_iterator it = deformationTimes.begin(), eIt = deformationTimes.end(); it != eIt; it++, timeIndex++ )
			{
				timeContext->setFrame( *it );
				ConstObjectPtr object = m_scenePlug->objectPlug()->getValue();
				if( const Primitive *primitive = runTimeCast<const Primitive>( object.get() ) )
				{
					if( deformationTimes.size() > 1 && timeIndex == 0 )
					{
						renderer->motionBegin( deformationTimes );
					}
						
						primitive->render( renderer );
					
					if( deformationTimes.size() > 1 && timeIndex == deformationTimes.size() - 1 )
					{
						renderer->motionEnd();
					}
				}
				else if( const Camera *camera = runTimeCast<const Camera>( object.get() ) )
				{
					/// \todo This absolutely does not belong here, but until we have
					/// a mechanism for drawing manipulators, we don't have any other
					/// means of visualising the cameras.
					if( renderer->isInstanceOf( "IECoreGL::Renderer" ) )
					{
						drawCamera( camera, renderer.get() );
					}
					break; // no motion blur for these chappies.
				}
				else if( const Light *light = runTimeCast<const Light>( object.get() ) )
				{
					/// \todo This doesn't belong here.
					if( renderer->isInstanceOf( "IECoreGL::Renderer" ) )
					{
						drawLight( light, renderer.get() );
					}
					break; // no motion blur for these chappies.
				}
				else if( const VisibleRenderable* renderable = runTimeCast< const VisibleRenderable >( object.get() ) )
				{
					renderable->render( renderer );
					break; // no motion blur for these chappies.
				}
			
			}
		}
	
		// children

		ConstInternedStringVectorDataPtr childNames = m_scenePlug->childNamesPlug()->getValue();
		if( childNames->readable().size() )
		{		
			bool expand = true;
			if( m_pathsToExpand )
			{
				expand = m_pathsToExpand->readable().match( m_scenePath ) & Filter::ExactMatch;
			}
			
			if( !expand )
			{
				renderer->setAttribute( "gl:primitive:wireframe", new BoolData( true ) );
				renderer->setAttribute( "gl:primitive:solid", new BoolData( false ) );
				renderer->setAttribute( "gl:curvesPrimitive:useGLLines", new BoolData( true ) );
				Box3f b = m_scenePlug->boundPlug()->getValue();
				CurvesPrimitive::createBox( b )->render( renderer );	
			}
			else
			{
				ScenePlug::ScenePath childScenePath = m_scenePath;
				childScenePath.push_back( InternedString() ); // for the child name
				for( vector<InternedString>::const_iterator it=childNames->readable().begin(); it!=childNames->readable().end(); it++ )
				{
					childScenePath[m_scenePath.size()] = *it;
					renderer->setAttribute( "name", new StringData( *it ) );
					renderer->procedural( new SceneProcedural( *this, childScenePath ) );
				}
			}	
		}
	}
	catch( const std::exception &e )
	{
		IECore::msg( IECore::Msg::Error, "SceneProcedural::render()", e.what() );
	}	
}
示例#28
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 );
}
示例#29
0
SceneInterfacePtr LinkedScene::scene( const Path &path, MissingBehaviour missingBehaviour )
{
	if ( missingBehaviour == SceneInterface::CreateIfMissing )
	{
		throw Exception( "createIfMissing is not supported!" );
	}

	SceneInterfacePtr s = m_mainScene->scene( SceneInterface::rootPath );

	Path::const_iterator pIt;
	/// first try to get as close as possible using the m_mainScene...
	for ( pIt = path.begin(); pIt != path.end(); pIt++ )
	{
		SceneInterfacePtr n = s->child( *pIt, SceneInterface::NullIfMissing );
		if ( !n )
		{
			break;
		}
		s = n;
	}
	ConstSceneInterfacePtr l = 0;
	int linkDepth = 0;
	bool atLink = false;
	bool timeRemapped = false;
	
	if ( s->hasAttribute( fileNameLinkAttribute ) && s->hasAttribute( rootLinkAttribute ) )
	{
		atLink = true;
		timeRemapped = s->hasAttribute( timeLinkAttribute );
		ConstStringDataPtr fileName = runTimeCast< const StringData >( s->readAttribute( fileNameLinkAttribute, 0 ) );
		ConstInternedStringVectorDataPtr root = runTimeCast< const InternedStringVectorData >( s->readAttribute( rootLinkAttribute, 0 ) );
		
		l = expandLink( fileName.get(), root.get(), linkDepth );
		if (!l)
		{
			atLink = false;
			timeRemapped = false;
		}
	}
	else if( s->hasAttribute( linkAttribute ) )
	{
		atLink = true;
		ConstCompoundDataPtr d = runTimeCast< const CompoundData >( s->readAttribute( linkAttribute, 0 ) );
		l = expandLink( d->member< const StringData >( g_fileName ), d->member< const InternedStringVectorData >( g_root ), linkDepth );
		if ( !l )
		{
			atLink = false;
		}
	}

	if ( pIt != path.end() )
	{
		if ( !atLink )
		{
			if ( missingBehaviour == SceneInterface::NullIfMissing )
			{
				return 0;
			}
			throw Exception( "Could not find child '" + pIt->value() + "'"  );
		}

		for ( ; pIt != path.end(); pIt++ )
		{
			l = l->child( *pIt, missingBehaviour );
			if ( !l )
			{
				return 0;
			}
		}
		atLink = false;
	}
	return new LinkedScene( s, l, linkDepth, m_readOnly, atLink, timeRemapped );
}
示例#30
0
文件: Group.cpp 项目: mor-vfx/gaffer
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;
}