Ejemplo n.º 1
0
		bool pathFromSelectionIdWalk( GLuint selectionId, ScenePlug::ScenePath &path ) const
		{
			if( m_selectionId == selectionId )
			{
				path.push_back( m_name );
				return true;
			}
			else
			{
				for( std::vector<SceneGraph *>::const_iterator it = m_children.begin(), eIt = m_children.end(); it != eIt; ++it )
				{
					/// \todo Should be able to prune recursion based on knowledge that child
					/// selection ids are always greater than parent selection ids.
					if( (*it)->pathFromSelectionIdWalk( selectionId, path ) )
					{
						if( m_name != IECore::InternedString() )
						{
							path.push_back( m_name );
						}
						return true;
					}
				}
			}

			return false;
		}
Ejemplo n.º 2
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;
		}
Ejemplo n.º 3
0
		void path( ScenePlug::ScenePath &p )
		{
			if( !m_parent )
			{
				return;
			}
			m_parent->path( p );
			p.push_back( m_name );
		}
Ejemplo n.º 4
0
void ScenePlug::stringToPath( const std::string &s, ScenePlug::ScenePath &path )
{
	typedef boost::tokenizer<boost::char_separator<char> > Tokenizer;
	Tokenizer tokenizer( s, boost::char_separator<char>( "/" ) );	
	for( Tokenizer::const_iterator it = tokenizer.begin(), eIt = tokenizer.end(); it != eIt; it++ )
	{
		path.push_back( *it );
	}
}
Ejemplo n.º 5
0
		void operator()( const tbb::blocked_range<int> &range ) const
		{
			for( int i=range.begin(); i!=range.end(); ++i )
			{
				ScenePlug::ScenePath childScenePath = m_parent.m_scenePath;
				childScenePath.push_back( m_childNames[i] );
				SceneProceduralPtr sceneProcedural = new SceneProcedural( m_parent, childScenePath );
				m_childProcedurals[ i ] = sceneProcedural;
			}
		}
Ejemplo n.º 6
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 );
	}
}
Ejemplo n.º 7
0
		void applySelectionWalk( const PathMatcher &selection, const ScenePlug::ScenePath &path, bool check )
		{
			const unsigned m = check ? selection.match( path ) : 0;

			m_selected = m & Filter::ExactMatch;

			ScenePlug::ScenePath childPath = path;
			childPath.push_back( IECore::InternedString() ); // space for the child name
			for( std::vector<SceneGraph *>::const_iterator it = m_children.begin(), eIt = m_children.end(); it != eIt; ++it )
			{
				childPath.back() = (*it)->m_name;
				(*it)->applySelectionWalk( selection, childPath, m & Filter::DescendantMatch );
			}
		}
Ejemplo n.º 8
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 );
	}
}
Ejemplo n.º 9
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;
}
Ejemplo n.º 10
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;
}
Ejemplo n.º 11
0
bool GafferScene::SceneAlgo::visible( 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 )
	{
		p.push_back( *it );
		pathScope.setPath( p );

		ConstCompoundObjectPtr attributes = scene->attributesPlug()->getValue();
		const BoolData *visibilityData = attributes->member<BoolData>( "scene:visible" );
		if( visibilityData && !visibilityData->readable() )
		{
			return false;
		}
	}

	return true;
}
Ejemplo n.º 12
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;
}
Ejemplo n.º 13
0
bool GafferScene::visible( 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 )
	{
		p.push_back( *it );
		context->set( ScenePlug::scenePathContextName, p );

		ConstCompoundObjectPtr attributes = scene->attributesPlug()->getValue();
		const BoolData *visibilityData = attributes->member<BoolData>( "scene:visible" );
		if( visibilityData && !visibilityData->readable() )
		{
			return false;
		}
	}

	return true;
}
Ejemplo n.º 14
0
void SceneView::expandSelection()
{
	Context::Scope scopedContext( getContext() );

	RenderableGadget::Selection &selection = m_renderableGadget->getSelection();
	
	vector<string> pathsToSelect;
	vector<const string *> pathsToDeselect;
	IECore::PathMatcherData *expandedData = expandedPaths();
	PathMatcher &expanded = expandedData->writable();
	
	bool needUpdate = false;
	for( RenderableGadget::Selection::const_iterator it = selection.begin(), eIt = selection.end(); it != eIt; it++ )
	{
		if( expanded.addPath( *it ) )
		{
			needUpdate = true;
			
			/// \todo Maybe if RenderableGadget used PathMatcher for specifying selection, and
			/// we had a nice means of getting ScenePaths out of PathMatcher, we wouldn't need
			/// to do all this string manipulation.
			typedef boost::tokenizer<boost::char_separator<char> > Tokenizer;
			Tokenizer pathTokenizer( *it, boost::char_separator<char>( "/" ) );	
			ScenePlug::ScenePath path;
			for( Tokenizer::const_iterator pIt = pathTokenizer.begin(), pEIt = pathTokenizer.end(); pIt != pEIt; pIt++ )
			{
				path.push_back( *pIt );
			}
			
			ConstInternedStringVectorDataPtr childNamesData = preprocessedInPlug<ScenePlug>()->childNames( path );
			const vector<InternedString> &childNames = childNamesData->readable();
			if( childNames.size() )
			{
				pathsToDeselect.push_back( &(*it) );
				for( vector<InternedString>::const_iterator cIt = childNames.begin(), ceIt = childNames.end(); cIt != ceIt; cIt++ )
				{
					if( *(*it).rbegin() != '/' )
					{
						pathsToSelect.push_back( *it + "/" + cIt->string() );
					}
					else
					{
						pathsToSelect.push_back( *it + cIt->string() );
					}
				}
			}
		}
	}
	
	for( vector<string>::const_iterator it = pathsToSelect.begin(), eIt = pathsToSelect.end(); it != eIt; it++ )
	{
		selection.insert( *it );
	}
	for( vector<const string *>::const_iterator it = pathsToDeselect.begin(), eIt = pathsToDeselect.end(); it != eIt; it++ )
	{
		selection.erase( **it );
	}
	
	if( needUpdate )
	{
		// we were naughty and modified the expanded paths in place (to avoid
		// unecessary copying), so the context doesn't know they've changed.
		// so we emit the changed signal ourselves. this will then trigger update()
		// via contextChanged().
		getContext()->changedSignal()( getContext(), "ui:scene:expandedPaths" );
		// and this will trigger a selection update also via contextChanged().
		transferSelectionToContext();
	}
}
Ejemplo n.º 15
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() );
	}	
}
Ejemplo n.º 16
0
		virtual task *execute()
		{
			ContextPtr context = new Context( *m_context, Context::Borrowed );
			context->set( ScenePlug::scenePathContextName, m_scenePath );
			Context::Scope scopedContext( context.get() );

			// we need the attributes so we can terminate recursion at invisible locations, so
			// we might as well store them in the scene graph, along with the hash:

			m_sceneGraph->m_attributesHash = m_scene->attributesPlug()->hash();

			// use the precomputed hash in getValue() to save a bit of time:

			m_sceneGraph->m_attributes = m_scene->attributesPlug()->getValue( &m_sceneGraph->m_attributesHash );
			const BoolData *visibilityData = m_sceneGraph->m_attributes->member<BoolData>( SceneInterface::visibilityName );
			if( visibilityData && !visibilityData->readable() )
			{
				// terminate recursion for invisible locations
				return NULL;
			}

			// store the hash of the child names so we know when they change:
			m_sceneGraph->m_childNamesHash = m_scene->childNamesPlug()->hash();

			// compute child names:
			IECore::ConstInternedStringVectorDataPtr childNamesData = m_scene->childNamesPlug()->getValue( &m_sceneGraph->m_childNamesHash );

			std::vector<IECore::InternedString> childNames = childNamesData->readable();
			if( childNames.empty() )
			{
				// nothing more to do
				return NULL;
			}

			// sort the child names so we can compare child name lists easily in ChildNamesUpdateTask:
			std::sort( childNames.begin(), childNames.end() );

			// add children for this location:
			std::vector<InteractiveRender::SceneGraph *> children;
			for( std::vector<IECore::InternedString>::const_iterator it = childNames.begin(), eIt = childNames.end(); it != eIt; ++it )
			{
				SceneGraph *child = new SceneGraph();
				child->m_name = *it;
				child->m_parent = m_sceneGraph;
				children.push_back( child );
			}

			// spawn child tasks:
			set_ref_count( 1 + children.size() );
			ScenePlug::ScenePath childPath = m_scenePath;
			childPath.push_back( IECore::InternedString() ); // space for the child name
			for( std::vector<SceneGraph *>::const_iterator it = children.begin(), eIt = children.end(); it != eIt; ++it )
			{
				childPath.back() = (*it)->m_name;
				SceneGraphBuildTask *t = new( allocate_child() ) SceneGraphBuildTask(
					m_scene,
					m_context,
					(*it),
					childPath
				);

				spawn( *t );
			}

			wait_for_all();

			// add visible children to m_sceneGraph->m_children:
			for( std::vector<SceneGraph *>::const_iterator it = children.begin(), eIt = children.end(); it != eIt; ++it )
			{
				const BoolData *visibilityData = (*it)->m_attributes->member<BoolData>( SceneInterface::visibilityName );
				if( visibilityData && !visibilityData->readable() )
				{
					continue;
				}
				m_sceneGraph->m_children.push_back( *it );
			}

			return NULL;
		}
Ejemplo n.º 17
0
		virtual task *execute()
		{
			ContextPtr context = new Context( *m_context, Context::Borrowed );
			context->set( ScenePlug::scenePathContextName, m_scenePath );
			Context::Scope scopedContext( context.get() );

			IECore::MurmurHash childNamesHash = m_scene->childNamesPlug()->hash();

			if( childNamesHash != m_sceneGraph->m_childNamesHash )
			{
				// child names have changed - we need to update m_locationPresent on the children:
				m_sceneGraph->m_childNamesHash = childNamesHash;

				// read updated child names:
				IECore::ConstInternedStringVectorDataPtr childNamesData = m_scene->childNamesPlug()->getValue( &m_sceneGraph->m_childNamesHash );
				std::vector<IECore::InternedString> childNames = childNamesData->readable();

				// m_sceneGraph->m_children should be sorted by name. Sort this list too so we can
				// compare the two easily:
				std::sort( childNames.begin(), childNames.end() );

				std::vector<InternedString>::iterator childNamesBegin = childNames.begin();
				for( std::vector<SceneGraph *>::const_iterator it = m_sceneGraph->m_children.begin(), eIt = m_sceneGraph->m_children.end(); it != eIt; ++it )
				{
					// try and find the current child name in the list of child names:
					std::vector<InternedString>::iterator nameIt = std::find( childNamesBegin, childNames.end(), (*it)->m_name );
					if( nameIt != childNames.end() )
					{
						// ok, it's there - mark this child as still present
						(*it)->m_locationPresent = true;

						// As both the name lists are sorted, no further child names will be found beyond nameIt
						// in the list, nor will they be found at nameIt as there shouldn't be any duplicates.
						// This means we can move the start of the child names list one position past nameIt
						// to save a bit of time:
						/// \todo Note that if all the children have changed names, we never end up in here, and
						/// we will end up with quadratic behaviour calling find (a linear search N times).
						childNamesBegin = nameIt;
						++childNamesBegin;
					}
					else
					{
						(*it)->m_locationPresent = false;
					}
				}
			}

			// count children currently present in the scene:
			size_t numPresentChildren = 0;
			for( std::vector<SceneGraph *>::const_iterator it = m_sceneGraph->m_children.begin(), eIt = m_sceneGraph->m_children.end(); it != eIt; ++it )
			{
				numPresentChildren += (*it)->m_locationPresent;
			}

			// spawn child tasks:
			set_ref_count( 1 + numPresentChildren );
			ScenePlug::ScenePath childPath = m_scenePath;
			childPath.push_back( IECore::InternedString() ); // space for the child name
			for( std::vector<SceneGraph *>::const_iterator it = m_sceneGraph->m_children.begin(), eIt = m_sceneGraph->m_children.end(); it != eIt; ++it )
			{
				if( (*it)->m_locationPresent )
				{
					childPath.back() = (*it)->m_name;
					ChildNamesUpdateTask *t = new( allocate_child() ) ChildNamesUpdateTask(
						m_scene,
						m_context,
						(*it),
						childPath
					);

					spawn( *t );
				}
			}
			wait_for_all();

			return NULL;
		}
Ejemplo n.º 18
0
		virtual task *execute()
		{
			ScenePlug::PathScope pathScope( m_sceneGadget->m_context.get(), m_scenePath );

			// Update attributes, and compute visibility.

			const bool previouslyVisible = m_sceneGraph->m_visible;
			if( m_dirtyFlags & AttributesDirty )
			{
				const IECore::MurmurHash attributesHash = m_sceneGadget->m_scene->attributesPlug()->hash();
				if( attributesHash != m_sceneGraph->m_attributesHash )
				{
					IECore::ConstCompoundObjectPtr attributes = m_sceneGadget->m_scene->attributesPlug()->getValue( &attributesHash );
					const IECore::BoolData *visibilityData = attributes->member<IECore::BoolData>( "scene:visible" );
					m_sceneGraph->m_visible = visibilityData ? visibilityData->readable() : true;

					IECore::ConstRunTimeTypedPtr glStateCachedTyped = IECoreGL::CachedConverter::defaultCachedConverter()->convert( attributes.get() );
					IECoreGL::ConstStatePtr glStateCached = IECore::runTimeCast<const IECoreGL::State>( glStateCachedTyped );



					IECoreGL::ConstStatePtr visState = NULL;

					deferReferenceRemoval( m_sceneGraph->m_attributesRenderable );
					m_sceneGraph->m_attributesRenderable = AttributeVisualiser::allVisualisations( attributes.get(), visState );

					deferReferenceRemoval( m_sceneGraph->m_state );
					if( visState )
					{
						IECoreGL::StatePtr glState = new IECoreGL::State( *glStateCached );
						glState->add( const_cast< IECoreGL::State* >( visState.get() ) );

						m_sceneGraph->m_state = glState;
					}
					else
					{
						m_sceneGraph->m_state = glStateCached;
					}


					m_sceneGraph->m_attributesHash = attributesHash;
				}
			}

			if( !m_sceneGraph->m_visible )
			{
				// No need to update further since we're not visible.
				return NULL;
			}
			else if( !previouslyVisible )
			{
				// We didn't perform any updates when we were invisible,
				// so we need to update everything now.
				m_dirtyFlags = AllDirty;
			}

			// Update the object - converting it into an IECoreGL::Renderable

			if( m_dirtyFlags & ObjectDirty )
			{
				const IECore::MurmurHash objectHash = m_sceneGadget->m_scene->objectPlug()->hash();
				if( objectHash != m_sceneGraph->m_objectHash )
				{
					IECore::ConstObjectPtr object = m_sceneGadget->m_scene->objectPlug()->getValue( &objectHash );
					deferReferenceRemoval( m_sceneGraph->m_renderable );
					if( !object->isInstanceOf( IECore::NullObjectTypeId ) )
					{
						m_sceneGraph->m_renderable = objectToRenderable( object.get() );
					}
					m_sceneGraph->m_objectHash = objectHash;
				}
			}

			// Update the transform and bound

			if( m_dirtyFlags & TransformDirty )
			{
				m_sceneGraph->m_transform = m_sceneGadget->m_scene->transformPlug()->getValue();
			}

			m_sceneGraph->m_bound = m_sceneGraph->m_renderable ? m_sceneGraph->m_renderable->bound() : Box3f();

			// Update the expansion state

			const bool previouslyExpanded = m_sceneGraph->m_expanded;
			if( m_dirtyFlags & ExpansionDirty )
			{
				m_sceneGraph->m_expanded = m_sceneGadget->m_minimumExpansionDepth >= m_scenePath.size();
				if( !m_sceneGraph->m_expanded )
				{
					m_sceneGraph->m_expanded = m_sceneGadget->m_expandedPaths->readable().match( m_scenePath ) & Filter::ExactMatch;
				}
			}

			// If we're not expanded, then we can early out after creating a bounding box.

			deferReferenceRemoval( m_sceneGraph->m_boundRenderable );
			if( !m_sceneGraph->m_expanded )
			{
				// We're not expanded, so we early out before updating the children.
				// We do however need to see if we have any children, and arrange to
				// draw their bounding box if we do.
				bool haveChildren = m_sceneGraph->m_children.size();
				if( m_dirtyFlags & ChildNamesDirty || !previouslyExpanded )
				{
					IECore::ConstInternedStringVectorDataPtr childNamesData = m_sceneGadget->m_scene->childNamesPlug()->getValue();
					haveChildren = childNamesData->readable().size();
				}

				m_sceneGraph->clearChildren();

				m_sceneGraph->m_bound.extendBy( m_sceneGadget->m_scene->boundPlug()->getValue() );

				if( haveChildren )
				{
					IECore::CurvesPrimitivePtr curvesBound = IECore::CurvesPrimitive::createBox( m_sceneGraph->m_bound );
					m_sceneGraph->m_boundRenderable = boost::static_pointer_cast<const IECoreGL::Renderable>(
						IECoreGL::CachedConverter::defaultCachedConverter()->convert( curvesBound.get() )
					);
				}
				return NULL;
			}

			// We are expanded, so we need to visit all the children
			// and update those too.

			if( !previouslyExpanded )
			{
				m_dirtyFlags = AllDirty;
			}

			// Make sure we have a child for each child name

			if( m_dirtyFlags & ChildNamesDirty )
			{
				IECore::ConstInternedStringVectorDataPtr childNamesData = m_sceneGadget->m_scene->childNamesPlug()->getValue();
				const std::vector<IECore::InternedString> &childNames = childNamesData->readable();
				if( !existingChildNamesValid( childNames ) )
				{
					m_sceneGraph->clearChildren();

					for( std::vector<IECore::InternedString>::const_iterator it = childNames.begin(), eIt = childNames.end(); it != eIt; ++it )
					{
						SceneGraph *child = new SceneGraph();
						child->m_name = *it;
						m_sceneGraph->m_children.push_back( child );
					}

					m_dirtyFlags = AllDirty; // We've made brand new children, so they need a full update.
				}
			}

			// And then update each child

			if( m_sceneGraph->m_children.size() )
			{
				set_ref_count( 1 + m_sceneGraph->m_children.size() );

				ScenePlug::ScenePath childPath = m_scenePath;
				childPath.push_back( IECore::InternedString() ); // space for the child name
				for( std::vector<SceneGraph *>::const_iterator it = m_sceneGraph->m_children.begin(), eIt = m_sceneGraph->m_children.end(); it != eIt; ++it )
				{
					childPath.back() = (*it)->m_name;
					UpdateTask *t = new( allocate_child() ) UpdateTask( m_sceneGadget, *it, m_dirtyFlags, childPath );
					spawn( *t );
				}

				wait_for_all();
			}

			// Finally compute our bound from the child bounds.

			for( std::vector<SceneGraph *>::const_iterator it = m_sceneGraph->m_children.begin(), eIt = m_sceneGraph->m_children.end(); it != eIt; ++it )
			{
				const Box3f childBound = transform( (*it)->m_bound, (*it)->m_transform );
				m_sceneGraph->m_bound.extendBy( childBound );
			}

			return NULL;
		}