예제 #1
0
void GafferSceneTest::testPathMatcherRawIterator()
{
	vector<InternedString> root;
	vector<InternedString> a = assign::list_of( "a" );
	vector<InternedString> ab = assign::list_of( "a" )( "b" );
	vector<InternedString> abc = assign::list_of( "a" )( "b" )( "c" );

	PathMatcher m;
	PathMatcher::RawIterator it = m.begin();
	GAFFERTEST_ASSERT( it == m.end() );

	m.addPath( abc );
	it = m.begin();
	GAFFERTEST_ASSERT( *it == root );
	GAFFERTEST_ASSERT( it.exactMatch() == false );
	GAFFERTEST_ASSERT( it != m.end() );
	++it;
	GAFFERTEST_ASSERT( *it == a );
	GAFFERTEST_ASSERT( it.exactMatch() == false );
	GAFFERTEST_ASSERT( it != m.end() );
	++it;
	GAFFERTEST_ASSERT( *it == ab );
	GAFFERTEST_ASSERT( it.exactMatch() == false );
	GAFFERTEST_ASSERT( it != m.end() );
	++it;
	GAFFERTEST_ASSERT( *it == abc );
	GAFFERTEST_ASSERT( it.exactMatch() == true );
	GAFFERTEST_ASSERT( it != m.end() );
	++it;
	GAFFERTEST_ASSERT( it == m.end() );
}
예제 #2
0
void expand( Context *context, const PathMatcher &paths, bool expandAncestors )
{
	GafferScene::PathMatcherData *expandedPaths = const_cast<GafferScene::PathMatcherData *>( context->get<GafferScene::PathMatcherData>( g_expandedPathsName, nullptr ) );
	if( !expandedPaths )
	{
		expandedPaths = new GafferScene::PathMatcherData();
		context->set( g_expandedPathsName, expandedPaths );
	}

	GafferScene::PathMatcher &expanded = expandedPaths->writable();

	bool needUpdate = false;
	if( expandAncestors )
	{
		for( GafferScene::PathMatcher::RawIterator it = paths.begin(), eIt = paths.end(); it != eIt; ++it )
		{
			needUpdate |= expanded.addPath( *it );
		}
	}
	else
	{
		for( GafferScene::PathMatcher::Iterator it = paths.begin(), eIt = paths.end(); it != eIt; ++it )
		{
			needUpdate |= expanded.addPath( *it );
		}
	}

	if( needUpdate )
	{
		// We 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
		context->changedSignal()( context, g_expandedPathsName );
	}
}
예제 #3
0
MurmurHash SharedDataHolder<PathMatcher>::hash() const
{
	IECore::MurmurHash result;

	HashStack stack;
	PathMatcher m = readable();
	for( PathMatcher::RawIterator it = m.begin(), eIt = m.end(); it != eIt; ++it )
	{
		// The iterator is recursive, so we use a stack to keep
		// track of where we are. Resize the stack to match our
		// current depth. The required size has the +1 because
		// we need a stack entry for the root item.
		size_t requiredStackSize = it->size() + 1;
		if( requiredStackSize > stack.size() )
		{
			// Going a level deeper.
			stack.push( HashNodes() );
			assert( stack.size() == requiredStackSize );
		}
		else if( requiredStackSize < stack.size() )
		{
			// Returning from recursion to the child nodes.
			// Output the hashes for the children we visited
			// and stored on the stack previously.
			popHashNodes( stack, requiredStackSize, result );
		}

		stack.top().push_back( HashNode( it->size() ? it->back().c_str() : "", it.exactMatch() ) );
	}
	popHashNodes( stack, 0, result );

	return result;
}
예제 #4
0
bool SceneGadget::objectAt( const IECore::LineSegment3f &lineInGadgetSpace, GafferScene::ScenePlug::ScenePath &path ) const
{
	std::vector<IECoreGL::HitRecord> selection;
	{
		ViewportGadget::SelectionScope selectionScope( lineInGadgetSpace, this, selection, IECoreGL::Selector::IDRender );
		renderScene();
	}

	if( !selection.size() )
	{
		return false;
	}

	float depthMin = selection[0].depthMin;
	unsigned int name = selection[0].name;
	for( const auto &i : selection )
	{
		if( i.depthMin < depthMin )
		{
			depthMin = i.depthMin;
			name = i.name;
		}
	}

	PathMatcher paths = convertSelection( new UIntVectorData( { name } ) );
	if( paths.isEmpty() )
	{
		return false;
	}

	path = *PathMatcher::Iterator( paths.begin() );
	return true;
}
예제 #5
0
void GafferSceneTest::testPathMatcherIteratorPrune()
{
	vector<InternedString> root;
	vector<InternedString> abc = assign::list_of( "a" )( "b" )( "c" );

	// Prune an empty iterator range.
	PathMatcher m;
	PathMatcher::Iterator it = m.begin();
	GAFFERTEST_ASSERT( it == m.end() );
	it.prune();
	GAFFERTEST_ASSERT( it == m.end() );

	// Prune the root iterator itself.
	m.addPath( root );
	it = m.begin();
	GAFFERTEST_ASSERT( *it == root );
	GAFFERTEST_ASSERT( it != m.end() );
	it.prune();
	GAFFERTEST_ASSERT( *it == root );
	GAFFERTEST_ASSERT( it != m.end() );
	++it;
	GAFFERTEST_ASSERT( it == m.end() );

	// As above, but actually with some
	// descendants to be pruned.
	m.addPath( abc );
	it = m.begin();
	GAFFERTEST_ASSERT( *it == root );
	GAFFERTEST_ASSERT( it != m.end() );
	it.prune();
	GAFFERTEST_ASSERT( *it == root );
	GAFFERTEST_ASSERT( it != m.end() );
	++it;
	GAFFERTEST_ASSERT( it == m.end() );

}
예제 #6
0
IECore::PathMatcher SceneGadget::convertSelection( IECore::UIntVectorDataPtr ids ) const
{
	CompoundDataMap parameters = { { "selection", ids } };
	if( m_selectionMask )
	{
		parameters["mask"] = m_selectionMask;
	}

	auto pathsData = static_pointer_cast<PathMatcherData>(
		m_renderer->command(
			"gl:querySelection",
			parameters
		)
	);

	PathMatcher result = pathsData->readable();

	// Unexpanded locations are represented with
	// objects named __unexpandedChildren__ to allow
	// locations to have an object _and_ children.
	// We want to replace any such locations with their
	// parent location.
	const InternedString unexpandedChildren = "__unexpandedChildren__";
	vector<InternedString> parent;

	PathMatcher toAdd;
	PathMatcher toRemove;
	for( PathMatcher::Iterator it = result.begin(), eIt = result.end(); it != eIt; ++it )
	{
		if( it->size() && it->back() == unexpandedChildren )
		{
			toRemove.addPath( *it );
			parent.assign( it->begin(), it->end() - 1 );
			toAdd.addPath( parent );
		}
	}

	result.addPaths( toAdd );
	result.removePaths( toRemove );

	return result;
}