Example #1
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;
}
Example #2
0
void outputCameras( const ScenePlug *scene, const IECore::CompoundObject *globals, IECore::Renderer *renderer )
{
	ConstPathMatcherDataPtr cameraSetData =  scene->set( "__cameras" );
	const PathMatcher &cameraSet = cameraSetData->readable();

	// Output all the cameras, skipping the primary one - we need to output this
	// last, as that's how cortex determines the primary camera.
	ScenePlug::ScenePath primaryCameraPath;
	if( const StringData *primaryCameraPathData = globals->member<StringData>( "option:render:camera" ) )
	{
		ScenePlug::stringToPath( primaryCameraPathData->readable(), primaryCameraPath );
	}

	for( PathMatcher::Iterator it = cameraSet.begin(), eIt = cameraSet.end(); it != eIt; ++it )
	{
		if( *it != primaryCameraPath )
		{
			outputCamera( scene, *it, globals, renderer );
		}
	}

	// Output the primary camera, or a default if it doesn't exist.

	outputCamera( scene, globals, renderer );

}
Example #3
0
GafferScene::ConstPathMatcherDataPtr Group::computeSet( const IECore::InternedString &setName, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	InternedString groupName = namePlug()->getValue();

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

	PathMatcherDataPtr resultData = new PathMatcherData;
	PathMatcher &result = resultData->writable();
	for( size_t i = 0, e = inPlugs()->children().size(); i < e; i++ )
	{
		ConstPathMatcherDataPtr inputSetData = inPlugs()->getChild<ScenePlug>( i )->setPlug()->getValue();
		const PathMatcher &inputSet = inputSetData->readable();

		const CompoundData *forwardMapping = static_cast<const IECore::CompoundData *>( forwardMappings->members()[i].get() );

		/// \todo If PathMatcher allowed access to the internal nodes, and allowed them to be shared between
		/// matchers, we could be much more efficient here by making a new matcher which referenced the contents
		/// of the input matchers.
		vector<InternedString> outputPath; outputPath.push_back( groupName );
		for( PathMatcher::Iterator pIt = inputSet.begin(), peIt = inputSet.end(); pIt != peIt; ++pIt )
		{
			const vector<InternedString> &inputPath = *pIt;
			if( !inputPath.size() )
			{
				continue;
			}

			const InternedStringData *outputName = forwardMapping->member<InternedStringData>( inputPath[0] );
			if( !outputName )
			{
				// Getting here indicates either a bug in computeMapping() or an inconsistency in one
				// of our inputs whereby a forward declaration has been made with a name which isn't
				// in childNames( "/" ). The second case can occur in practice when an input is being
				// connected or disconnected - because our inputs are CompoundPlugs, part way through
				// the setInput() process the child connections for globalsPlug() and childNamesPlug()
				// will not correspond, leading us here. This problem occurs in InteractiveRenderManRenderTest
				// when the scene is being updated from a plugDirtiedSignal() which is emitted when one
				// child plug has been disconnected, but before the other one has. The real solution to
				// this would be to properly batch up dirty signals so that only a single signal is
				// emitted for the parent after all signals for the children have been emitted. Then we
				// would only ever be called in a consistent connection state.
				/// \todo Now we have proper batching of dirty propagation we should remove this workaround,
				/// reverting to a call to forwardMapping->member<InternedStringData>( inputName, true ),
				/// which will throw when an error is detected.
				continue;
			}

			outputPath.resize( 2 );
			outputPath[1] = outputName->readable();
			outputPath.insert( outputPath.end(), inputPath.begin() + 1, inputPath.end() );

			result.addPath( outputPath );
		}
	}

	return resultData;
}
Example #4
0
void outputClippingPlanes( const ScenePlug *scene, const IECore::CompoundObject *globals, IECore::Renderer *renderer )
{
	ConstPathMatcherDataPtr clippingPlanesSetData = scene->set( "__clippingPlanes" );
	const PathMatcher &clippingPlanesSet = clippingPlanesSetData->readable();

	for( PathMatcher::Iterator it = clippingPlanesSet.begin(), eIt = clippingPlanesSet.end(); it != eIt; ++it )
	{
		outputClippingPlane( scene, *it, renderer );
	}
}
Example #5
0
void outputCoordinateSystems( const ScenePlug *scene, const IECore::CompoundObject *globals, IECore::Renderer *renderer )
{
	ConstPathMatcherDataPtr coordinateSystemSetData = scene->set( "__coordinateSystems" );
	const PathMatcher &coordinateSystemSet = coordinateSystemSetData->readable();

	for( PathMatcher::Iterator it = coordinateSystemSet.begin(), eIt = coordinateSystemSet.end(); it != eIt; ++it )
	{
		outputCoordinateSystem( scene, *it, renderer );
	}
}
Example #6
0
void outputLights( const ScenePlug *scene, const IECore::CompoundObject *globals, IECore::Renderer *renderer )
{
	ConstPathMatcherDataPtr lightSetData = scene->set( "__lights" );
	const PathMatcher &lightSet = lightSetData->readable();

	for( PathMatcher::Iterator it = lightSet.begin(), eIt = lightSet.end(); it != eIt; ++it )
	{
		outputLight( scene, *it, renderer );
	}
}
Example #7
0
GafferScene::ConstPathMatcherDataPtr Set::computeSet( const IECore::InternedString &setName, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	const std::string allSets = " " + namePlug()->getValue() + " ";
	const std::string setNameToFind = " " + setName.string() + " ";
	if( allSets.find( setNameToFind ) == std::string::npos )
	{
		return inPlug()->setPlug()->getValue();
	}

	ConstPathMatcherDataPtr pathMatcher = pathMatcherPlug()->getValue();
	switch( modePlug()->getValue() )
	{
		case Add : {
			ConstPathMatcherDataPtr inputSet = inPlug()->setPlug()->getValue();
			if( !inputSet->readable().isEmpty() )
			{
				PathMatcherDataPtr result = inputSet->copy();
				result->writable().addPaths( pathMatcher->readable() );
				return result;
			}
			// Input set empty - fall through to create mode.
		}
		case Create : {
			return pathMatcher;
		}
		case Remove :
		default : {
			ConstPathMatcherDataPtr inputSet = inPlug()->setPlug()->getValue();
			if( inputSet->readable().isEmpty() )
			{
				return inputSet;
			}
			PathMatcherDataPtr result = inputSet->copy();
			result->writable().removePaths( pathMatcher->readable() );
			return result;
		}
	}
}
Example #8
0
GafferScene::ConstPathMatcherDataPtr BranchCreator::computeSet( const IECore::InternedString &setName, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	ConstPathMatcherDataPtr inputSetData = inPlug()->set( setName );

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

	ScenePlug::ScenePath parentPath = mapping->member<InternedStringVectorData>( g_parentKey )->readable();

	ConstPathMatcherDataPtr branchSetData = computeBranchSet( parentPath, setName, context );
	if( !branchSetData )
	{
		return inputSetData;
	}

	const PathMatcher &branchSet = branchSetData->readable();
	if( branchSet.isEmpty() )
	{
		return inputSetData;
	}

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

	PathMatcherDataPtr outputSetData = inputSetData->copy();
	PathMatcher &outputSet = outputSetData->writable();

	vector<InternedString> outputPrefix( parentPath );
	for( PathMatcher::RawIterator pIt = branchSet.begin(), peIt = branchSet.end(); pIt != peIt; ++pIt )
	{
		const ScenePlug::ScenePath &branchPath = *pIt;
		if( !branchPath.size() )
		{
			continue; // Skip root
		}
		assert( branchPath.size() == 1 );

		const InternedStringData *outputName = forwardMapping->member<InternedStringData>( branchPath[0], /* throwExceptions = */ true );

		outputPrefix.resize( parentPath.size() + 1 );
		outputPrefix.back() = outputName->readable();
		outputSet.addPaths( branchSet.subTree( *pIt ), outputPrefix );

		pIt.prune(); // We only want to visit the first level
	}

	return outputSetData;
}
Example #9
0
unsigned PathFilter::computeMatch( const ScenePlug *scene, const Gaffer::Context *context ) const
{
	typedef IECore::TypedData<ScenePlug::ScenePath> ScenePathData;
	const ScenePathData *pathData = context->get<ScenePathData>( ScenePlug::scenePathContextName, nullptr );
	if( pathData )
	{
		// If we have a precomputed PathMatcher, we use that to compute matches, otherwise
		// we grab the PathMatcher from the intermediate plug (which is a bit more expensive
		// as it involves graph evaluations):

		ConstPathMatcherDataPtr pathMatcher = m_pathMatcher ? m_pathMatcher : pathMatcherPlug()->getValue();
		return pathMatcher->readable().match( pathData->readable() );
	}
	return NoMatch;
}
Example #10
0
GafferScene::ConstPathMatcherDataPtr Prune::computeSet( const IECore::InternedString &setName, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	ConstPathMatcherDataPtr inputSetData = inPlug()->setPlug()->getValue();
	const PathMatcher &inputSet = inputSetData->readable();
	if( inputSet.isEmpty() )
	{
		return inputSetData;
	}

	PathMatcherDataPtr outputSetData = inputSetData->copy();
	PathMatcher &outputSet = outputSetData->writable();

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

	for( PathMatcher::RawIterator pIt = inputSet.begin(), peIt = inputSet.end(); pIt != peIt; )
	{
		sceneScope.set( ScenePlug::scenePathContextName, *pIt );
		const int m = filterPlug()->getValue();
		if( m & ( Filter::ExactMatch | Filter::AncestorMatch ) )
		{
			// This path and all below it are pruned, so we can
			// ignore it and prune the traversal to the descendant
			// paths.
			outputSet.prune( *pIt );
			pIt.prune();
			++pIt;
		}
		else if( m & Filter::DescendantMatch )
		{
			// This path isn't pruned, so we continue our traversal
			// as normal to find out which descendants _are_ pruned.
			++pIt;
		}
		else
		{
			// This path isn't pruned, and neither is anything
			// below it. We can avoid retesting the filter for
			// all descendant paths, since we know they're not
			// pruned.
			assert( m == Filter::NoMatch );
			pIt.prune();
			++pIt;
		}
	}

	return outputSetData;
}
Example #11
0
unsigned SetFilter::computeMatch( const ScenePlug *scene, const Gaffer::Context *context ) const
{
	if( !scene )
	{
		return NoMatch;
	}

	const ScenePlug::ScenePath &path = context->get<ScenePlug::ScenePath>( ScenePlug::scenePathContextName );

	// See explanatory comments in hashMatch().
	ContextPtr tmpContext = new Context( *context, Context::Borrowed );
	tmpContext->remove( Filter::inputSceneContextName );
	tmpContext->remove( ScenePlug::scenePathContextName );
	Context::Scope scopedContext( tmpContext.get() );

	ConstPathMatcherDataPtr set = scene->set( setPlug()->getValue() );

	return set->readable().match( path );
}
Example #12
0
GafferScene::ConstPathMatcherDataPtr Isolate::computeSet( const IECore::InternedString &setName, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	ConstPathMatcherDataPtr inputSetData = inPlug()->setPlug()->getValue();
	const PathMatcher &inputSet = inputSetData->readable();
	if( inputSet.isEmpty() )
	{
		return inputSetData;
	}

	PathMatcherDataPtr outputSetData = new PathMatcherData;
	PathMatcher &outputSet = outputSetData->writable();

	ContextPtr tmpContext = filterContext( context );
	Context::Scope scopedContext( tmpContext.get() );

	const std::string fromString = fromPlug()->getValue();
	ScenePlug::ScenePath fromPath; ScenePlug::stringToPath( fromString, fromPath );

	for( PathMatcher::RawIterator pIt = inputSet.begin(), peIt = inputSet.end(); pIt != peIt; )
	{
		tmpContext->set( ScenePlug::scenePathContextName, *pIt );
		const int m = filterPlug()->getValue();
		if( m & ( Filter::ExactMatch | Filter::AncestorMatch ) )
		{
			// We want to keep everything below this point, and
			// we can speed things up by not checking the filter
			// for our descendants.
			PathMatcher::RawIterator next = pIt; next.prune(); ++next;
			while( pIt != next )
			{
				if( pIt.exactMatch() )
				{
					outputSet.addPath( *pIt );
				}
				++pIt;
			}
		}
		else if( m & Filter::DescendantMatch )
		{
			// We might be removing things below here,
			// so just continue our iteration normally
			// so we can find out.
			if( pIt.exactMatch() )
			{
				outputSet.addPath( *pIt );
			}
			++pIt;
		}
		else
		{
			assert( m == Filter::NoMatch );
			if( boost::starts_with( *pIt, fromPath ) )
			{
				// Not going to keep anything below
				// here, so we can prune traversal
				// entirely.
				pIt.prune();
			}
			else if( pIt.exactMatch() )
			{
				outputSet.addPath( *pIt );
			}
			++pIt;
		}
	}

	return outputSetData;
}
Example #13
0
void InteractiveRender::outputLightsInternal( const IECore::CompoundObject *globals, bool editing )
{
	// Get the paths to all the lights
	ConstPathMatcherDataPtr lightSet = inPlug()->set( "__lights" );

	std::vector<std::string> lightPaths;
	lightSet->readable().paths( lightPaths );

	// Create or update lights in the renderer as necessary

	for( vector<string>::const_iterator it = lightPaths.begin(), eIt = lightPaths.end(); it != eIt; ++it )
	{
		ScenePlug::ScenePath path;
		ScenePlug::stringToPath( *it, path );

		if( !editing )
		{
			// defining the scene for the first time
			if( outputLight( inPlug(), path, m_renderer.get() ) )
			{
				m_lightHandles.insert( *it );
			}
		}
		else
		{
			if( m_lightHandles.find( *it ) != m_lightHandles.end() )
			{
				// we've already output this light - update it
				bool visible = false;
				{
					EditBlock edit( m_renderer.get(), "light", CompoundDataMap() );
					visible = outputLight( inPlug(), path, m_renderer.get() );
				}
				// we may have turned it off before, and need to turn
				// it back on, or it may have been hidden and we need
				// to turn it off.
				{
					EditBlock edit( m_renderer.get(), "attribute", CompoundDataMap() );
					m_renderer->illuminate( *it, visible );
				}
			}
			else
			{
				// we've not seen this light before - create a new one
				EditBlock edit( m_renderer.get(), "attribute", CompoundDataMap() );
				if( outputLight( inPlug(), path, m_renderer.get() ) )
				{
					m_lightHandles.insert( *it );
				}
			}
		}
	}

	// Turn off any lights we don't want any more

	for( LightHandles::const_iterator it = m_lightHandles.begin(), eIt = m_lightHandles.end(); it != eIt; ++it )
	{
		if( !lightSet || !(lightSet->readable().match( *it ) & Filter::ExactMatch) )
		{
			EditBlock edit( m_renderer.get(), "attribute", CompoundDataMap() );
			m_renderer->illuminate( *it, false );
		}
	}
}
Example #14
0
GafferScene::ConstPathMatcherDataPtr Isolate::computeSet( const IECore::InternedString &setName, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	ConstPathMatcherDataPtr inputSetData = inPlug()->setPlug()->getValue();
	if(
		( setName == g_lightsSetName && keepLightsPlug()->getValue() ) ||
		( setName == g_camerasSetName && keepCamerasPlug()->getValue() )
	)
	{
		return inputSetData;
	}

	const PathMatcher &inputSet = inputSetData->readable();
	if( inputSet.isEmpty() )
	{
		return inputSetData;
	}

	PathMatcherDataPtr outputSetData = inputSetData->copy();
	PathMatcher &outputSet = outputSetData->writable();

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

	const std::string fromString = fromPlug()->getValue();
	ScenePlug::ScenePath fromPath; ScenePlug::stringToPath( fromString, fromPath );

	const SetsToKeep setsToKeep( this );

	for( PathMatcher::RawIterator pIt = inputSet.begin(), peIt = inputSet.end(); pIt != peIt; )
	{
		sceneScope.set( ScenePlug::scenePathContextName, *pIt );
		const int m = filterPlug()->getValue() || setsToKeep.match( *pIt );
		if( m & ( Filter::ExactMatch | Filter::AncestorMatch ) )
		{
			// We want to keep everything below this point, so
			// can just prune our iteration.
			pIt.prune();
			++pIt;
		}
		else if( m & Filter::DescendantMatch )
		{
			// We might be removing things below here,
			// so just continue our iteration normally
			// so we can find out.
			++pIt;
		}
		else
		{
			assert( m == Filter::NoMatch );
			if( boost::starts_with( *pIt, fromPath ) )
			{
				// Not going to keep anything below
				// here, so we can prune traversal
				// entirely.
				outputSet.prune( *pIt );
				pIt.prune();
			}
			++pIt;
		}
	}

	return outputSetData;
}