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; }
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() ); }
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; }
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; }
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 ); } }
static void loadSetWalk( const SceneInterface *s, const InternedString &setName, PathMatcher &set, const vector<InternedString> &path ) { if( s->hasTag( setName, SceneInterface::LocalTag ) ) { set.addPath( path ); } // Figure out if we need to recurse by querying descendant tags to see if they include // anything we're interested in. if( !s->hasTag( setName, SceneInterface::DescendantTag ) ) { return; } // Recurse to the children. SceneInterface::NameList childNames; s->childNames( childNames ); vector<InternedString> childPath( path ); childPath.push_back( InternedString() ); // room for the child name for( SceneInterface::NameList::const_iterator it = childNames.begin(), eIt = childNames.end(); it != eIt; ++it ) { ConstSceneInterfacePtr child = s->child( *it ); childPath.back() = *it; loadSetWalk( child.get(), setName, set, childPath ); } }
// we don't actually wrap the existing init, but rather reimplement it // here using clear() and addPath(), so that we can support a mixture // of strings and InternedStringVectorData. static void initWrapper( PathMatcher &m, boost::python::object paths ) { m.clear(); for( size_t i = 0, e = len( paths ); i < e; ++i ) { object path = paths[i]; extract<const char *> stringExtractor( path ); if( stringExtractor.check() ) { m.addPath( stringExtractor() ); } else { IECore::ConstInternedStringVectorDataPtr d = extract<IECore::ConstInternedStringVectorDataPtr>( path ); m.addPath( d->readable() ); } } }
static list paths( const PathMatcher &p ) { std::vector<std::string> paths; p.paths( paths ); list result; for( std::vector<std::string>::const_iterator it = paths.begin(), eIt = paths.end(); it != eIt; it++ ) { result.append( *it ); } return result; }
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; }
status_t PathMatcher :: PutPathsFromMatcher(const PathMatcher & matcher) { TCHECKPOINT; for (HashtableIterator<String, PathMatcherEntry> iter(matcher.GetEntries(), HTIT_FLAG_NOREGISTER); iter.HasData(); iter++) { if (_entries.Put(iter.GetKey(), iter.GetValue()) == B_NO_ERROR) { if (iter.GetValue().GetFilter()()) _numFilters++; } else return B_ERROR; } return B_NO_ERROR; }
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 ); } }
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; }
size_t SceneGadget::objectsAt( const Imath::V3f &corner0InGadgetSpace, const Imath::V3f &corner1InGadgetSpace, IECore::PathMatcher &paths ) const { vector<IECoreGL::HitRecord> selection; { ViewportGadget::SelectionScope selectionScope( corner0InGadgetSpace, corner1InGadgetSpace, this, selection, IECoreGL::Selector::OcclusionQuery ); renderScene(); } UIntVectorDataPtr ids = new UIntVectorData; std::transform( selection.begin(), selection.end(), std::back_inserter( ids->writable() ), []( const IECoreGL::HitRecord &h ) { return h.name; } ); PathMatcher selectedPaths = convertSelection( ids ); paths.addPaths( selectedPaths ); return selectedPaths.size(); }
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; }
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() ); }
static unsigned matchInternedStringVectorData( const PathMatcher &p, const IECore::InternedStringVectorData *d ) { return p.match( d->readable() ); }
static bool addPathInternedStringVectorData( PathMatcher &p, const IECore::InternedStringVectorData *d ) { return p.addPath( d->readable() ); }