示例#1
0
IECore::ConstCompoundObjectPtr ImageMetadata::computeProcessedMetadata( const Gaffer::Context *context, const IECore::CompoundObject *inputMetadata ) const
{
	const CompoundDataPlug *p = metadataPlug();
	if ( !p->children().size() )
	{
		return inputMetadata;
	}

	IECore::CompoundObjectPtr result = new IECore::CompoundObject;
	// Since we're not going to modify any existing members (only add new ones),
	// and our result becomes const on returning it, we can directly reference
	// the input members in our result without copying. Be careful not to modify
	// them though!
	result->members() = inputMetadata->members();

	std::string name;
	for ( CompoundDataPlug::MemberPlugIterator it( p ); !it.done(); ++it )
	{
		IECore::DataPtr d = p->memberDataAndName( it->get(), name );
		if ( d )
		{
			result->members()[name] = d;
		}
	}

	return result;
}
示例#2
0
IECore::ConstCompoundObjectPtr Options::computeProcessedGlobals( const Gaffer::Context *context, IECore::ConstCompoundObjectPtr inputGlobals ) const
{
	const CompoundDataPlug *p = optionsPlug();
	if( !p->children().size() )
	{
		return inputGlobals;
	}

	IECore::CompoundObjectPtr result = new IECore::CompoundObject;
	// Since we're not going to modify any existing members (only add new ones),
	// and our result becomes const on returning it, we can directly reference
	// the input members in our result without copying. Be careful not to modify
	// them though!
	result->members() = inputGlobals->members();

	const std::string prefix = computePrefix( context );

	std::string name;
	for( NameValuePlugIterator it( p ); !it.done(); ++it )
	{
		IECore::DataPtr d = p->memberDataAndName( it->get(), name );
		if( d )
		{
			result->members()[prefix + name] = d;
		}
	}

	return result;
}
示例#3
0
IECore::ConstCompoundObjectPtr Set::computeProcessedGlobals( const Gaffer::Context *context, IECore::ConstCompoundObjectPtr inputGlobals ) const
{
	std::string name = namePlug()->getValue();
	if( !name.size() )
	{
		return inputGlobals;
	}

	IECore::CompoundObjectPtr result = new IECore::CompoundObject;
	// Since we're not going to modify any existing members other than the sets,
	// and our result becomes const on returning it, we can directly reference
	// the input members in our result without copying. We have to be careful not
	// to modify the input sets though.
	result->members() = inputGlobals->members();

	CompoundDataPtr sets = new CompoundData;
	if( const CompoundData *inputSets = inputGlobals->member<CompoundData>( "gaffer:sets" ) )
	{
		sets->writable() = inputSets->readable();
	}
	result->members()["gaffer:sets"] = sets;

	ConstObjectPtr set = pathMatcherPlug()->getValue();
	// const cast is acceptable because we're just using it to place a const object into a
	// container that will be treated as const everywhere immediately after return from this method.
	sets->writable()[name] = const_cast<Data *>( static_cast<const Data *>( set.get() ) );

	return result;
}
void StandardLightVisualiser::addEnvLightVisualiser( GroupPtr &output, Color3f multiplier, const std::string &textureName )
{
    IECoreGL::GroupPtr sphereGroup = new IECoreGL::Group();

    Imath::M44f trans;
    trans.scale( V3f( 1, 1, -1 ) );
    trans.rotate( V3f( -0.5 * M_PI, -0.5 * M_PI, 0 ) );
    sphereGroup->setTransform( trans );

    IECoreGL::SpherePrimitivePtr sphere = new IECoreGL::SpherePrimitive();
    sphereGroup->addChild( sphere );

    IECore::CompoundObjectPtr parameters = new CompoundObject;
    parameters->members()["lightMultiplier"] = new Color3fData( multiplier );
    parameters->members()["previewOpacity"] = new FloatData( 1 );
    parameters->members()["mapSampler"] = new StringData( textureName );
    parameters->members()["defaultColor"] = new Color3fData( Color3f( textureName == "" ? 1.0f : 0.0f ) );
    sphereGroup->getState()->add(
        new IECoreGL::ShaderStateComponent( ShaderLoader::defaultShaderLoader(), TextureLoader::defaultTextureLoader(), IECoreGL::Shader::defaultVertexSource(), "", environmentLightDrawFragSource(), parameters )
    );
    sphereGroup->getState()->add(
        new IECoreGL::DoubleSidedStateComponent( false )
    );

    output->addChild( sphereGroup );
}
示例#5
0
IECore::ConstCompoundObjectPtr Attributes::computeGlobals( const Gaffer::Context *context, const ScenePlug *parent ) const
{
	ConstCompoundObjectPtr inputGlobals = inPlug()->globalsPlug()->getValue();
	if( !globalPlug()->getValue() )
	{
		return inputGlobals;
	}

	const CompoundDataPlug *p = attributesPlug();
	IECore::CompoundObjectPtr result = new CompoundObject;
	// Since we're not going to modify any existing members (only add new ones),
	// and our result becomes const on returning it, we can directly reference
	// the input members in our result without copying. Be careful not to modify
	// them though!
	result->members() = inputGlobals->members();

	std::string name;
	for( CompoundDataPlug::MemberPlugIterator it( p ); !it.done(); ++it )
	{
		IECore::DataPtr d = p->memberDataAndName( it->get(), name );
		if( d )
		{
			result->members()["attribute:" + name] = d;
		}
	}

	return result;
}
示例#6
0
IECore::ConstCompoundObjectPtr OSLLight::computeAttributes( const SceneNode::ScenePath &path, const Gaffer::Context *context, const GafferScene::ScenePlug *parent ) const
{
	IECore::CompoundObjectPtr result = new IECore::CompoundObject;

	ConstCompoundObjectPtr shaderAttributes = shaderInPlug()->attributes();
	result->members() = shaderAttributes->members();

	attributesPlug()->fillCompoundObject( result->members() );

	return result;
}
示例#7
0
文件: Outputs.cpp 项目: CRiant/gaffer
IECore::ConstCompoundObjectPtr Outputs::computeProcessedGlobals( const Gaffer::Context *context, IECore::ConstCompoundObjectPtr inputGlobals ) const
{
	const CompoundPlug *dsp = outputsPlug();
	if( !dsp->children().size() )
	{
		return inputGlobals;
	}

	IECore::CompoundObjectPtr result = new IECore::CompoundObject;
	// Since we're not going to modify any existing members (only add new ones),
	// and our result becomes const on returning it, we can directly reference
	// the input members in our result without copying. Be careful not to modify
	// them though!
	result->members() = inputGlobals->members();

	// add our outputs to the result
	for( InputCompoundPlugIterator it( dsp ); it != it.end(); it++ )
	{
		const CompoundPlug *outputPlug = it->get();
		if( outputPlug->getChild<BoolPlug>( "active" )->getValue() )
		{
			// backwards compatibility with old plug layout
			const StringPlug *namePlug = outputPlug->getChild<StringPlug>( "label" );
			if( !namePlug )
			{
				namePlug = outputPlug->getChild<StringPlug>( "name" );
			}
			const std::string name = namePlug->getValue();

			const StringPlug *fileNamePlug = outputPlug->getChild<StringPlug>( "fileName" );
			if( !fileNamePlug )
			{
				// backwards compatibility with old plug layout
				fileNamePlug = outputPlug->getChild<StringPlug>( "name" );
			}
			const std::string fileName = fileNamePlug->getValue();

			const std::string type = outputPlug->getChild<StringPlug>( "type" )->getValue();
			const std::string data = outputPlug->getChild<StringPlug>( "data" )->getValue();
			if( name.size() && fileName.size() && type.size() && data.size() )
			{
				DisplayPtr d = new Display( fileName, type, data );
				outputPlug->getChild<CompoundDataPlug>( "parameters" )->fillCompoundData( d->parameters() );
				result->members()["output:" + name] = d;
			}
		}
	}

	return result;
}
示例#8
0
IECore::CompoundObjectPtr ScenePlug::fullAttributes( const ScenePath &scenePath ) const
{
	ContextPtr tmpContext = new Context( *Context::current(), Context::Borrowed );
	Context::Scope scopedContext( tmpContext.get() );

	IECore::CompoundObjectPtr result = new IECore::CompoundObject;
	IECore::CompoundObject::ObjectMap &resultMembers = result->members();
	ScenePath path( scenePath );
	while( path.size() )
	{
		tmpContext->set( scenePathContextName, path );
		IECore::ConstCompoundObjectPtr a = attributesPlug()->getValue();
		const IECore::CompoundObject::ObjectMap &aMembers = a->members();
		for( IECore::CompoundObject::ObjectMap::const_iterator it = aMembers.begin(), eIt = aMembers.end(); it != eIt; it++ )
		{
			if( resultMembers.find( it->first ) == resultMembers.end() )
			{
				resultMembers.insert( *it );
			}
		}		
		path.pop_back();
	}
	
	return result;
}
示例#9
0
IECore::ConstCompoundObjectPtr SubTree::computeGlobals( const Gaffer::Context *context, const ScenePlug *parent ) const
{
	IECore::CompoundObjectPtr result = inPlug()->globalsPlug()->getValue()->copy();

	const IECore::CompoundData *inputForwardDeclarations = result->member<IECore::CompoundData>( "gaffer:forwardDeclarations" );
	if( inputForwardDeclarations )
	{
		std::string root = rootPlug()->getValue();
		if( !root.size() || root[root.size()-1] != '/' )
		{
			root += "/";
		}

		IECore::CompoundDataPtr forwardDeclarations = new IECore::CompoundData;
		for( IECore::CompoundDataMap::const_iterator it = inputForwardDeclarations->readable().begin(), eIt = inputForwardDeclarations->readable().end(); it != eIt; it++ )
		{
			const IECore::InternedString &inputPath = it->first;
			if( inputPath.string().compare( 0, root.size(), root ) == 0 )
			{
				std::string outputPath( inputPath, root.size()-1 );
				forwardDeclarations->writable()[outputPath] = it->second;
			}
		}
		result->members()["gaffer:forwardDeclarations"] = forwardDeclarations;
	}

	return result;
}
IECoreGL::ConstRenderablePtr StandardLightVisualiser::pointRays()
{
    IECoreGL::GroupPtr group = new IECoreGL::Group();
    addWireframeCurveState( group.get() );

    IECore::CompoundObjectPtr parameters = new CompoundObject;
    parameters->members()["aimType"] = new IntData( 1 );
    group->getState()->add(
        new IECoreGL::ShaderStateComponent( ShaderLoader::defaultShaderLoader(), TextureLoader::defaultTextureLoader(), faceCameraVertexSource(), "", IECoreGL::Shader::constantFragmentSource(), parameters )
    );

    IntVectorDataPtr vertsPerCurve = new IntVectorData;
    V3fVectorDataPtr p = new V3fVectorData;

    const int numRays = 8;
    for( int i = 0; i < numRays; ++i )
    {
        const float angle = M_PI * 2.0f * float(i)/(float)numRays;
        const V2f dir( cos( angle ), sin( angle ) );
        addRay( dir * .5, dir * 1, vertsPerCurve->writable(), p->writable() );
    }

    IECoreGL::CurvesPrimitivePtr curves = new IECoreGL::CurvesPrimitive( IECore::CubicBasisf::linear(), false, vertsPerCurve );
    curves->addPrimitiveVariable( "P", IECore::PrimitiveVariable( IECore::PrimitiveVariable::Vertex, p ) );
    curves->addPrimitiveVariable( "Cs", IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new Color3fData( Color3f( 1.0f, 0.835f, 0.07f ) ) ) );

    group->addChild( curves );

    return group;
}
示例#11
0
IECore::ConstCompoundObjectPtr DeleteGlobals::computeProcessedGlobals( const Gaffer::Context *context, IECore::ConstCompoundObjectPtr inputGlobals ) const
{
	if( inputGlobals->members().empty() )
	{
		return inputGlobals;
	}

	const std::string names = namesPlug()->getValue();
	const bool invert = invertNamesPlug()->getValue();
	if( !invert && !names.size() )
	{
		return inputGlobals;
	}

	const std::string prefix = namePrefix();

	IECore::CompoundObjectPtr result = new IECore::CompoundObject;
	for( IECore::CompoundObject::ObjectMap::const_iterator it = inputGlobals->members().begin(), eIt = inputGlobals->members().end(); it != eIt; ++it )
	{
		bool keep = true;
		if( boost::starts_with( it->first.c_str(), prefix ) )
		{
			if( matchMultiple( it->first.c_str() + prefix.size(), names.c_str() ) != invert )
			{
				keep = false;
			}
		}
		if( keep )
		{
			result->members()[it->first] = it->second;
		}
	}

	return result;
}
示例#12
0
IECore::ConstCompoundObjectPtr DeleteImageMetadata::computeProcessedMetadata( const Gaffer::Context *context, const IECore::CompoundObject *inputMetadata ) const
{
	if ( inputMetadata->members().empty() )
	{
		return inputMetadata;
	}

	const std::string names = namesPlug()->getValue();
	const bool invert = invertNamesPlug()->getValue();
	if ( !invert && !names.size() )
	{
		return inputMetadata;
	}

	IECore::CompoundObjectPtr result = new IECore::CompoundObject;
	for ( IECore::CompoundObject::ObjectMap::const_iterator it = inputMetadata->members().begin(), eIt = inputMetadata->members().end(); it != eIt; ++it )
	{
		bool keep = true;
		if ( StringAlgo::matchMultiple( it->first.c_str(), names.c_str() ) != invert )
		{
			keep = false;
		}

		if ( keep )
		{
			result->members()[it->first] = it->second;
		}
	}

	return result;
}
示例#13
0
IECore::ConstCompoundObjectPtr CopyImageMetadata::computeProcessedMetadata( const Gaffer::Context *context, const IECore::CompoundObject *inputMetadata ) const
{
	ConstCompoundObjectPtr copyFrom = copyFromPlug()->metadataPlug()->getValue();
	if ( copyFrom->members().empty() )
	{
		return inputMetadata;
	}

	const std::string names = namesPlug()->getValue();
	const bool invert = invertNamesPlug()->getValue();
	if ( !invert && !names.size() )
	{
		return inputMetadata;
	}

	IECore::CompoundObjectPtr result = inputMetadata->copy();
	for ( IECore::CompoundObject::ObjectMap::const_iterator it = copyFrom->members().begin(), eIt = copyFrom->members().end(); it != eIt; ++it )
	{
		bool copy = false;
		if ( matchMultiple( it->first.c_str(), names.c_str() ) != invert )
		{
			copy = true;
		}
		
		if ( copy )
		{
			result->members()[it->first] = it->second;
		}
	}
	
	return result;
}
示例#14
0
IECore::ConstCompoundObjectPtr Shader::attributes( const Gaffer::Plug *output ) const
{
	IECore::CompoundObjectPtr result = new IECore::CompoundObject;
	NetworkBuilder networkBuilder( output );
	if( networkBuilder.network()->size() )
	{
		std::string attr = typePlug()->getValue();
		std::string postfix = attributeSuffixPlug()->getValue();
		if( postfix != "" )
		{
			attr += ":" + postfix;
		}
		result->members()[attr] = boost::const_pointer_cast<IECoreScene::ShaderNetwork>( networkBuilder.network() );
	}
	return result;
}
示例#15
0
IECore::ConstCompoundObjectPtr Light::computeAttributes( const SceneNode::ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	IECore::CompoundObjectPtr result = new IECore::CompoundObject;

	std::string lightAttribute = "light";

	IECoreScene::ShaderNetworkPtr lightShaders = computeLight( context );
	if( const IECoreScene::Shader *shader = lightShaders->outputShader() )
	{
		lightAttribute = shader->getType();
	}

	result->members()[lightAttribute] = lightShaders;

	return result;
}
示例#16
0
文件: Options.cpp 项目: daevid/gaffer
IECore::ConstCompoundObjectPtr Options::computeProcessedGlobals( const Gaffer::Context *context, IECore::ConstCompoundObjectPtr inputGlobals ) const
{
	IECore::CompoundObjectPtr result = inputGlobals->copy();
	const CompoundDataPlug *p = optionsPlug();

	std::string name;
	for( CompoundDataPlug::MemberPlugIterator it( p ); it != it.end(); ++it )
	{
		IECore::DataPtr d = p->memberDataAndName( it->get(), name );
		if( d )
		{
			result->members()["option:" + name] = d;
		}
	}

	return result;
}
void StandardLightVisualiser::addAreaLightVisualiser( IECoreGL::ConstStatePtr &state, Color3f multiplier, const std::string &textureName, bool flipNormal, bool doubleSided, bool sphericalProjection, const M44f &projectionTransform )
{
    IECore::CompoundObjectPtr parameters = new CompoundObject;
    parameters->members()["lightMultiplier"] = new Color3fData( multiplier );
    parameters->members()["previewOpacity"] = new FloatData( 1 );
    parameters->members()["mapSampler"] = new StringData( textureName );
    parameters->members()["defaultColor"] = new Color3fData( Color3f( textureName == "" ? 1.0f : 0.0f ) );
    parameters->members()["flipNormal"] = new BoolData( flipNormal );
    parameters->members()["doubleSided"] = new BoolData( doubleSided );
    parameters->members()["sphericalProjection"] = new BoolData( sphericalProjection );
    parameters->members()["projectionTransform"] = new M44fData( projectionTransform );
    IECoreGL::StatePtr newState = new IECoreGL::State( false );
    newState->add(
        new IECoreGL::ShaderStateComponent( ShaderLoader::defaultShaderLoader(), TextureLoader::defaultTextureLoader(), areaLightDrawVertexSource(), "", areaLightDrawFragSource(), parameters )
    );
    state = newState;
}
IECoreGL::ConstRenderablePtr StandardLightVisualiser::spotlightCone( float innerAngle, float outerAngle, float lensRadius )
{
    IECoreGL::GroupPtr group = new IECoreGL::Group();
    addWireframeCurveState( group.get() );

    group->getState()->add( new IECoreGL::CurvesPrimitive::GLLineWidth( 1.0f ) );

    IECore::CompoundObjectPtr parameters = new CompoundObject;
    parameters->members()["aimType"] = new IntData( 0 );
    group->getState()->add(
        new IECoreGL::ShaderStateComponent( ShaderLoader::defaultShaderLoader(), TextureLoader::defaultTextureLoader(), faceCameraVertexSource(), "", IECoreGL::Shader::constantFragmentSource(), parameters )
    );

    IntVectorDataPtr vertsPerCurve = new IntVectorData;
    V3fVectorDataPtr p = new V3fVectorData;
    addCone( innerAngle, lensRadius, vertsPerCurve->writable(), p->writable() );

    IECoreGL::CurvesPrimitivePtr curves = new IECoreGL::CurvesPrimitive( IECore::CubicBasisf::linear(), false, vertsPerCurve );
    curves->addPrimitiveVariable( "P", IECore::PrimitiveVariable( IECore::PrimitiveVariable::Vertex, p ) );
    curves->addPrimitiveVariable( "Cs", IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new Color3fData( Color3f( 1.0f, 0.835f, 0.07f ) ) ) );

    group->addChild( curves );

    if( fabs( innerAngle - outerAngle ) > 0.1 )
    {
        IECoreGL::GroupPtr outerGroup = new Group;
        outerGroup->getState()->add( new IECoreGL::CurvesPrimitive::GLLineWidth( 0.5f ) );

        IntVectorDataPtr vertsPerCurve = new IntVectorData;
        V3fVectorDataPtr p = new V3fVectorData;
        addCone( outerAngle, lensRadius, vertsPerCurve->writable(), p->writable() );

        IECoreGL::CurvesPrimitivePtr curves = new IECoreGL::CurvesPrimitive( IECore::CubicBasisf::linear(), false, vertsPerCurve );
        curves->addPrimitiveVariable( "P", IECore::PrimitiveVariable( IECore::PrimitiveVariable::Vertex, p ) );
        curves->addPrimitiveVariable( "Cs", IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new Color3fData( Color3f( 1.0f, 0.835f, 0.07f ) ) ) );

        outerGroup->addChild( curves );

        group->addChild( outerGroup );
    }

    return group;
}
示例#19
0
文件: Group.cpp 项目: 7on7on/gaffer
IECore::ConstCompoundObjectPtr Group::computeGlobals( const Gaffer::Context *context, const ScenePlug *parent ) const
{
	IECore::CompoundObjectPtr result = inPlug()->globalsPlug()->getValue()->copy();
	
	std::string groupName = namePlug()->getValue();

	ConstCompoundObjectPtr mapping = staticPointerCast<const CompoundObject>( inputMappingPlug()->getValue() );
	const ObjectVector *forwardMappings = mapping->member<ObjectVector>( "__GroupForwardMappings", true /* throw if missing */ );

	IECore::CompoundDataPtr forwardDeclarations = new IECore::CompoundData;
	for( size_t i = 0, e = m_inPlugs.inputs().size(); i < e; i++ )
	{
		const CompoundData *forwardMapping = static_cast<const IECore::CompoundData *>( forwardMappings->members()[i].get() );
		ConstCompoundObjectPtr inputGlobals = m_inPlugs.inputs()[i]->globalsPlug()->getValue();
		const CompoundData *inputForwardDeclarations = inputGlobals->member<CompoundData>( "gaffer:forwardDeclarations" );
		if( inputForwardDeclarations )
		{
			for( CompoundDataMap::const_iterator it = inputForwardDeclarations->readable().begin(), eIt = inputForwardDeclarations->readable().end(); it != eIt; it++ )
			{
				/// \todo This would all be much nicer if the forward declarations data structure
				/// used ScenePlug::ScenePaths or something similar - then we could ditch all the
				/// string munging.
				const InternedString &inputPath = it->first;
				size_t secondSlashPos = inputPath.string().find( '/', 1 );
				const std::string inputName( inputPath.string(), 1, secondSlashPos - 1 );
				const InternedString &outputName = forwardMapping->member<InternedStringData>( inputName, true /* throw if missing */ )->readable();
				std::string outputPath = std::string( "/" ) + groupName + "/" + outputName.string();
				if( secondSlashPos != string::npos )
				{
					outputPath += inputPath.string().substr( secondSlashPos );
				}
				forwardDeclarations->writable()[outputPath] = it->second;
			}
		}
	}
	result->members()["gaffer:forwardDeclarations"] = forwardDeclarations;
	
	return result;
}
示例#20
0
文件: Light.cpp 项目: cnpinto/gaffer
IECore::ConstCompoundObjectPtr Light::computeAttributes( const SceneNode::ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	IECore::CompoundObjectPtr result = new IECore::CompoundObject;

	std::string lightAttribute = "light";

	IECore::ObjectVectorPtr lightShaders = computeLight( context );
	if( lightShaders->members().size() > 0 )
	{
		IECore::LightPtr light = IECore::runTimeCast< IECore::Light >(
			lightShaders->members()[ lightShaders->members().size() - 1 ] );
		std::string lightName = light->getName();
		size_t colon = lightName.find( ":" );
		if( colon != std::string::npos )
		{
			lightAttribute = lightName.substr( 0, colon ) + ":light";
		}
	}

	result->members()[lightAttribute] = lightShaders;

	return result;
}
IECoreGL::ConstRenderablePtr StandardLightVisualiser::ray()
{
    IECoreGL::GroupPtr group = new IECoreGL::Group();
    addWireframeCurveState( group.get() );

    IECore::CompoundObjectPtr parameters = new CompoundObject;
    parameters->members()["aimType"] = new IntData( 0 );
    group->getState()->add(
        new IECoreGL::ShaderStateComponent( ShaderLoader::defaultShaderLoader(), TextureLoader::defaultTextureLoader(), faceCameraVertexSource(), "", IECoreGL::Shader::constantFragmentSource(), parameters )
    );

    IntVectorDataPtr vertsPerCurve = new IntVectorData;
    V3fVectorDataPtr p = new V3fVectorData;
    addRay( V2f( 0 ), V2f( 1, 0 ), vertsPerCurve->writable(), p->writable() );

    IECoreGL::CurvesPrimitivePtr curves = new IECoreGL::CurvesPrimitive( IECore::CubicBasisf::linear(), false, vertsPerCurve );
    curves->addPrimitiveVariable( "P", IECore::PrimitiveVariable( IECore::PrimitiveVariable::Vertex, p ) );
    curves->addPrimitiveVariable( "Cs", IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new Color3fData( Color3f( 1.0f, 0.835f, 0.07f ) ) ) );

    group->addChild( curves );

    return group;
}
示例#22
0
IECore::ConstCompoundObjectPtr BranchCreator::computeGlobals( const Gaffer::Context *context, const ScenePlug *parent ) const
{
	ConstCompoundObjectPtr inputGlobals = inPlug()->globalsPlug()->getValue();

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

	const CompoundData *branchSets = NULL;
	ConstCompoundObjectPtr branchGlobals = computeBranchGlobals( mapping->member<InternedStringVectorData>( g_parentKey )->readable(), context );
	if( branchGlobals )
	{
		branchSets = branchGlobals->member<CompoundData>( "gaffer:sets", /* throwExceptions = */ false );
	}
	if( !branchSets )
	{
		return inputGlobals;
	}

	IECore::CompoundObjectPtr outputGlobals = new CompoundObject;
	// Shallow copy of the input, because most of it will remain unchanged.
	outputGlobals->members() = inputGlobals->members();
	// Deep copy of the input sets, because we'll be modifying them.
	const CompoundData *inputSets = inputGlobals->member<CompoundData>( "gaffer:sets", /* throwExeptions = */ false );
	CompoundDataPtr outputSets = inputSets ? inputSets->copy() : new CompoundData;
	outputGlobals->members()["gaffer:sets"] = outputSets;

	const CompoundData *forwardMapping = mapping->member<CompoundData>( g_forwardMappingKey );

	string parentString;
	ScenePlug::pathToString( mapping->member<InternedStringVectorData>( g_parentKey )->readable(), parentString );
	if( !boost::ends_with( parentString, "/" ) )
	{
		parentString += "/";
	}

	for( CompoundDataMap::const_iterator it = branchSets->readable().begin(), eIt = branchSets->readable().end(); it != eIt; ++it )
	{
		const PathMatcher &branchSet = static_cast<const PathMatcherData *>( it->second.get() )->readable();
		PathMatcher &outputSet = outputSets->member<PathMatcherData>( it->first, /* throwExceptions = */ false, /* createIfMissing = */ true )->writable();

		/// \todo If PathMatcher allowed us to rename nodes and merge in other PathMatchers, this could
		/// be much more efficient.
		vector<string> branchPaths;
		branchSet.paths( branchPaths );
		for( vector<string>::const_iterator pIt = branchPaths.begin(), peIt = branchPaths.end(); pIt != peIt; ++pIt )
		{
			const string &branchPath = *pIt;
			const size_t secondSlashPos = branchPath.find( '/', 1 );
			const std::string branchName( branchPath, 1, secondSlashPos - 1 );
			const InternedStringData *outputName = forwardMapping->member<InternedStringData>( branchName );
			if( !outputName )
			{
				// See comments in Group::computeGlobals().
				continue;
			}

			std::string outputPath = parentString + outputName->readable().string();
			if( secondSlashPos != string::npos )
			{
				outputPath += branchPath.substr( secondSlashPos );
			}
			outputSet.addPath( outputPath );
		}
	}

	return outputGlobals;
}
IECoreGL::ConstRenderablePtr StandardLightVisualiser::colorIndicator( const Imath::Color3f &color, bool faceCamera )
{

    float maxChannel = std::max( color[0], std::max( color[1], color[2] ) );
    float exposure = 0;
    Imath::Color3f indicatorColor = color;
    if( maxChannel > 1 )
    {
        indicatorColor = color / maxChannel;
        exposure = log( maxChannel ) / log( 2 );
    }
    IECoreGL::GroupPtr group = new IECoreGL::Group();
    IECoreGL::GroupPtr wirelessGroup = new IECoreGL::Group();

    IECore::CompoundObjectPtr parameters = new CompoundObject;
    parameters->members()["aimType"] = new IntData( 1 );
    group->getState()->add(
        new IECoreGL::ShaderStateComponent( ShaderLoader::defaultShaderLoader(), TextureLoader::defaultTextureLoader(), faceCamera ? faceCameraVertexSource() : "", "", IECoreGL::Shader::constantFragmentSource(), parameters )
    );

    wirelessGroup->getState()->add( new IECoreGL::Primitive::DrawWireframe( false ) );

    float indicatorRad = 0.3;
    int indicatorAxis = faceCamera ? 0 : 2;

    {
        IntVectorDataPtr vertsPerPoly = new IntVectorData;
        IntVectorDataPtr vertIds = new IntVectorData;
        V3fVectorDataPtr p = new V3fVectorData;

        addSolidArc( indicatorAxis, V3f( 0 ), indicatorRad, indicatorRad * 0.9, 0, 1, vertsPerPoly->writable(), vertIds->writable(), p->writable() );

        IECore::MeshPrimitivePtr mesh = new IECore::MeshPrimitive( vertsPerPoly, vertIds, "linear", p );
        mesh->variables["N"] = IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new V3fData( V3f( 0 ) ) );
        mesh->variables["Cs"] = IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new Color3fData( indicatorColor ) );
        ToGLMeshConverterPtr meshConverter = new ToGLMeshConverter( mesh );
        group->addChild( IECore::runTimeCast<IECoreGL::Renderable>( meshConverter->convert() ) );
    }
    {
        IntVectorDataPtr vertsPerPoly = new IntVectorData;
        IntVectorDataPtr vertIds = new IntVectorData;
        V3fVectorDataPtr p = new V3fVectorData;

        addSolidArc( indicatorAxis, V3f( 0 ), indicatorRad * 0.4, 0.0, 0, 1, vertsPerPoly->writable(), vertIds->writable(), p->writable() );

        for( int i = 0; i < exposure && i < 20; i++ )
        {
            float startAngle = 1 - pow( 0.875, i );
            float endAngle = 1 - pow( 0.875, std::min( i+1.0, (double)exposure ) );
            float maxEndAngle = 1 - pow( 0.875, i+1.0);
            float sectorScale = ( maxEndAngle - startAngle - 0.008 ) / ( maxEndAngle - startAngle );
            addSolidArc( indicatorAxis, V3f( 0 ), indicatorRad * 0.85, indicatorRad * 0.45, startAngle, startAngle + ( endAngle - startAngle ) * sectorScale, vertsPerPoly->writable(), vertIds->writable(), p->writable() );
        }

        IECore::MeshPrimitivePtr mesh = new IECore::MeshPrimitive( vertsPerPoly, vertIds, "linear", p );
        mesh->variables["N"] = IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new V3fData( V3f( 0 ) ) );
        mesh->variables["Cs"] = IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new Color3fData( indicatorColor ) );
        ToGLMeshConverterPtr meshConverter = new ToGLMeshConverter( mesh );
        wirelessGroup->addChild( IECore::runTimeCast<IECoreGL::Renderable>( meshConverter->convert() ) );
    }

    // For exposures greater than 20, draw an additional solid bar of a darker color at the very end, without any segment dividers
    if( exposure > 20 )
    {
        IntVectorDataPtr vertsPerPoly = new IntVectorData;
        IntVectorDataPtr vertIds = new IntVectorData;
        V3fVectorDataPtr p = new V3fVectorData;

        float startAngle = 1 - pow( 0.875, 20 );
        float endAngle = 1 - pow( 0.875, (double)exposure );
        addSolidArc( indicatorAxis, V3f( 0 ), indicatorRad * 0.85, indicatorRad * 0.45, startAngle, endAngle, vertsPerPoly->writable(), vertIds->writable(), p->writable() );

        IECore::MeshPrimitivePtr mesh = new IECore::MeshPrimitive( vertsPerPoly, vertIds, "linear", p );
        mesh->variables["N"] = IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new V3fData( V3f( 0 ) ) );
        mesh->variables["Cs"] = IECore::PrimitiveVariable( IECore::PrimitiveVariable::Constant, new Color3fData( 0.5f * indicatorColor ) );
        ToGLMeshConverterPtr meshConverter = new ToGLMeshConverter( mesh );
        wirelessGroup->addChild( IECore::runTimeCast<IECoreGL::Renderable>( meshConverter->convert() ) );
    }

    group->addChild( wirelessGroup );

    return group;
}