Traversing a Stage

This tutorial covers API for traversing the composed prims on a UsdStage. This is the typical pattern for implementing imaging clients, USD importers to other DCC applications, etc. We will use the layers produced in Referencing Layers. You will need the referenced layer, HelloWorld.usda, and the referencing layer, RefExample.usda, which are in the USD/extras/usd/tutorials/traversingStage folder. Please copy that folder to a working directory and make its contents writable.

  1. Open RefExample.usda in usdview and bring up the interpreter by hitting i or the Window ‣ Interpreter menu item.

  2. The interpreter has a built-in usdviewApi object that contains a number of convenient variables and functions for working with usdview and the UsdStage it has open.

    The simplest place to start is with Usd.Stage.Traverse(); a generator which yields prims from the stage in depth-first-traversal order.

    >>> [x for x in usdviewApi.stage.Traverse()]
    [Usd.Prim(</refSphere>), Usd.Prim(</refSphere/world>),
     Usd.Prim(</refSphere2>), Usd.Prim(</refSphere2/world>)]
    

    You can filter as you would any other Python generator:

    >>> [x for x in usdviewApi.stage.Traverse() if UsdGeom.Sphere(x)]
    [Usd.Prim(</refSphere/world>), Usd.Prim(</refSphere2/world>)]
    
  3. For more involved traversals, the Usd.PrimRange() exposes pre- and post-order prim visitations.

    >>> primIter = iter(Usd.PrimRange.PreAndPostVisit(usdviewApi.stage.GetPseudoRoot()))
    >>> for x in primIter: print(x, primIter.IsPostVisit())
    Usd.Prim(</>) False
    Usd.Prim(</refSphere>) False
    Usd.Prim(</refSphere/world>) False
    Usd.Prim(</refSphere/world>) True
    Usd.Prim(</refSphere>) True
    Usd.Prim(</refSphere2>) False
    Usd.Prim(</refSphere2/world>) False
    Usd.Prim(</refSphere2/world>) True
    Usd.Prim(</refSphere2>) True
    Usd.Prim(</>) True
    
  4. Usd.PrimRange also makes prim-flag predicates available. In fact, Usd.Stage.Traverse() is really a convenience method that performs pre-order visitations on all the prims in the composed scenegraph that are active, defined, loaded, and concrete.

    In Referencing Layers, we touched upon what it means for a prim to be defined, i.e., it is backed by a def rather than an over. The concepts of being loaded and concrete respectively correlate to payloads (composition boundaries across which scene description does not get composed unless explicitly requested) and classes (abstract prims whose opinions apply to all prims which inherit from them). We will discuss these operators more in depth in a future tutorial. Here we consider activation/deactivation semantics with usdview.

    Select refSphere2 in the tree view on the left and choose Edit ‣ Deactivate from the menu. The result should look like this.

    http://openusd.org/images/tut_traversing_stage_refexample.png

    You can inspect the contents of the session layer in the interpreter to see the authored deactivation opinion.

    >>> print(usdviewApi.stage.GetSessionLayer().ExportToString())
    #usda 1.0
    
    over "refSphere2" (
        active = false
    )
    {
    }
    

    In USD, a session layer holds transient opinions for the current working session that a user would not want to commit to the asset and thereby affect downstream departments.

    Now Traverse() will not visit refSphere2 or any of its namespace children, and renderers do not draw it.

    >>> [x for x in usdviewApi.stage.Traverse()]
    [Usd.Prim(</refSphere>), Usd.Prim(</refSphere/world>)]
    

    While we can still see refSphere2 as an inactive prim on the stage, its children no longer have any presence in the composed scenegraph. We can use TraverseAll() to get an iterator with no predicates applied to verify this.

    >>> [x for x in usdviewApi.stage.TraverseAll()]
    [Usd.Prim(</refSphere>), Usd.Prim(</refSphere/world>),
     Usd.Prim(</refSphere2>)]