Thanks! It does indeed seem like prim.GetPrimStack
is the entry point to getting all ‘opinions’ on the primitive.
from pxr import Sdf
symbol = {
Sdf.SpecifierDef: "Def ", # Defines a concrete prim
Sdf.SpecifierOver: "Over ", # Overrides an existing prim
Sdf.SpecifierClass: "Class ", # Define an abstract prim
}
prims = stage.TraverseAll()
for prim in prims:
for prim_spec in prim.GetPrimStack():
print(f"layer: {prim_spec.layer.identifier}")
print(f"{symbol[prim_spec.specifier]} {prim_spec.path}")
attributes = prim_spec.attributes
for attr in attributes:
print(f" - {attr.name} -> {attr.default}")
(Of course the above will be slow for very large scenes)
This would e.g. print something like:
layer: path/to/data/asset.usd
Def /root
layer: path/to/look.usd
Over /root
layer: path/to/data/model.usd
Over /root
layer: path/to/look.usd
Over /root/Cube1
layer: path/to/data/model.usd
Def /root/Cube1
layer: path/to/look.usd
Def /mtl
layer: path/to/look.usd
Def /mtl/UsdPreviewSurface1
- outputs:surface -> None
layer: path/to/look.usd
Def /mtl/UsdPreviewSurface1/UsdPreviewSurface1
- info:id -> UsdPreviewSurface
- outputs:surface -> None
Note that the above example does not print relationships - those are accessible through prim_spec.relationships
(or GetRelationships()
in C++) - so let’s add those.
And with some slight modification to not show anything that doesn’t directly specify an opinion on the prim itself using SdfSpec.IsInert()
we get to:
from pxr import Sdf
symbol = {
Sdf.SpecifierDef: "Def ", # Defines a concrete prim
Sdf.SpecifierOver: "Over ", # Overrides an existing prim
Sdf.SpecifierClass: "Class ", # Define an abstract prim
}
prims = stage.TraverseAll()
for prim in prims:
for prim_spec in prim.GetPrimStack():
if prim_spec.IsInert(ignoreChildren=True):
continue
print(f"{symbol[prim_spec.specifier]} {prim_spec.path}".ljust(60, " ") + f"<-- {prim_spec.layer.identifier}")
attributes = prim_spec.attributes
for attr in attributes:
print(f" - {attr.name} -> {attr.default}")
for relationship in prim_spec.relationships:
target_paths = relationship.targetPathList
print(f" > {relationship.name} -- {target_paths}")
Printing:
Def /root <-- path/to/asset.usd
Over /root/Cube1 <-- path/to/look.usd
> material:binding -- [/mtl/UsdPreviewSurface1]
Def /root/Cube1 <-- path/to/model.usd
Def /mtl <-- path/to/look.usd
Def /mtl/UsdPreviewSurface1 <-- path/to/look.usd
- outputs:surface -> None
Def /mtl/UsdPreviewSurface1/UsdPreviewSurface1 <-- path/to/look.usd
- info:id -> UsdPreviewSurface
- outputs:surface -> None
Again, these are just simple debug tests to learn about the USD API but might help others on their way.
Question: How to remove authored opinions / prim specs?
The question now becomes how do I tweak these opinions / prim specs and thereby actually adjust the contents in the layers. So Questions:
- I want to remove an attribute/property opinion in a specific layer. How would I do so?
- I want to remove a prim definition. How would I do so?
It seems SdfLayer
has some remove methods that take PrimSpecs or PropertySpecs, like SdfLayer.RemovePrimIfInert but they seem focused on the “if inert” cases. How do I actually remove a particular Attribute Spec opinion or a Prim Spec opinion.
I can find remove_prim_spec
in the omniverse docs but how to that natively through USD?