How to get prim paths using an expression without creating a collection

Using the USD API, is it possible to get prim paths in a stage using Sdf.PathExpression without creating a collection?
I’d like to find prims of a certain type with glob-style wildcard patterns in the path such as /cameras/* and {isa:Camera}, but I can only find examples of this being used with collections.
It’s possible to do this in Houdini like this for example:

rule = hou.LopSelectionRule(pattern='/cameras/* & %type(Camera)')
prim_paths = rule.expandedPaths(stage=hou.selectedNodes()[0].stage())

Here’s the most relevant documentation I could find:
https://openusd.org/release/user_guides/collections_and_patterns.html
https://openusd.org/release/api/class_sdf_path_expression.html

You can do this using SdfMakePathExpressionEval::MakeIncrementalSearcher, passing UsdGetCollectionPredicateLibrary as the predicate library, and doing your own stage traversal. If a result’s IsConstant method returns true, you can call PruneChildren to prune off branches of the stage which can’t match. UsdGetCollectionPredicateLibrary needs to be passed a struct with an operator() which returns a prim given an SdfPath.

Jerry

2 Likes

Thank you Jerry! Is this available in Python? I can’t get it working.

I came across the same problem with Python. There seems to be no Python binding for SdfMakePathExpressionEval, so I couldn’t get this to work and had to do it in C++.

I would point out though, that using the Collection method, iit seems that there’s no requirement for the Collection to be in the same stage as the prims you’re matching, so, at your own risk…

def match(stage, pattern):
  temp_stage = Usd.Stage.CreateInMemory()
  c = temp_stage.DefinePrim(Sdf.Path("/c"))
  e = Usd.CollectionAPI.Apply(c, "t:collection")
  m = e.CreateMembershipExpressionAttr()
  m.Set(Sdf.PathExpression(pattern))
  o = Usd.CollectionAPI.ComputeIncludedObjects(e.ComputeMembershipQuery(), stage)
  return [p.GetPath() for p in o]

Jerry

1 Like

Interesting, I’ll give that a try.