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.