main 6a5ca31fae01 cached
165 files
960.8 KB
253.6k tokens
98 symbols
1 requests
Download .txt
Showing preview only (1,016K chars total). Download the full file or copy to clipboard to get everything.
Repository: LucaScheller/VFX-UsdSurvivalGuide
Branch: main
Commit: 6a5ca31fae01
Files: 165
Total size: 960.8 KB

Directory structure:
gitextract_fg3igdvu/

├── .github/
│   └── workflows/
│       └── mdbook.yml
├── .gitignore
├── LICENSE
├── README.md
├── code/
│   ├── core/
│   │   ├── composition.py
│   │   └── elements.py
│   ├── dcc/
│   │   └── houdini.py
│   ├── production/
│   │   ├── caches.py
│   │   └── production.py
│   └── test.py
├── docs/
│   ├── book.toml
│   ├── src/
│   │   ├── SUMMARY.md
│   │   ├── google12b063a902eb5a11.html
│   │   ├── index.md
│   │   ├── media/
│   │   │   ├── UsdSurvivalGuide.psd
│   │   │   └── core/
│   │   │       └── composition/
│   │   │           ├── compositionLIVRPS.excalidraw
│   │   │           └── houdiniCompositionReferenceEncapsulate.webm
│   │   ├── not-found.md
│   │   ├── pages/
│   │   │   ├── contributors.md
│   │   │   ├── core/
│   │   │   │   ├── api.md
│   │   │   │   ├── composition/
│   │   │   │   │   ├── arcs.md
│   │   │   │   │   ├── fundamentals.md
│   │   │   │   │   ├── listeditableops.md
│   │   │   │   │   ├── livrps.md
│   │   │   │   │   ├── overview.md
│   │   │   │   │   ├── pcp.md
│   │   │   │   │   ├── pcpPrimIndex.txt
│   │   │   │   │   └── pcpPrimIndexPig.txt
│   │   │   │   ├── elements/
│   │   │   │   │   ├── animation.md
│   │   │   │   │   ├── collection.md
│   │   │   │   │   ├── data_container.md
│   │   │   │   │   ├── data_type.md
│   │   │   │   │   ├── layer.md
│   │   │   │   │   ├── loading_mechanisms.md
│   │   │   │   │   ├── materials.md
│   │   │   │   │   ├── metadata.md
│   │   │   │   │   ├── notice.md
│   │   │   │   │   ├── overview.md
│   │   │   │   │   ├── path.md
│   │   │   │   │   ├── prim.md
│   │   │   │   │   ├── property.md
│   │   │   │   │   ├── schemas.md
│   │   │   │   │   ├── standalone_utilities.md
│   │   │   │   │   └── transform.md
│   │   │   │   ├── glossary.md
│   │   │   │   ├── overview.md
│   │   │   │   ├── plugins/
│   │   │   │   │   ├── assetresolver.md
│   │   │   │   │   ├── kind.md
│   │   │   │   │   ├── metadata.md
│   │   │   │   │   ├── overview.md
│   │   │   │   │   └── schemas.md
│   │   │   │   ├── profiling/
│   │   │   │   │   ├── debug.md
│   │   │   │   │   ├── overview.md
│   │   │   │   │   └── profiling.md
│   │   │   │   └── resources.md
│   │   │   ├── dcc/
│   │   │   │   ├── houdini/
│   │   │   │   │   ├── approach.md
│   │   │   │   │   ├── faq/
│   │   │   │   │   │   └── overview.md
│   │   │   │   │   ├── fx/
│   │   │   │   │   │   ├── deformingMeshes.md
│   │   │   │   │   │   ├── frustumCulling.md
│   │   │   │   │   │   ├── motionblur.md
│   │   │   │   │   │   ├── overview.md
│   │   │   │   │   │   ├── particles.md
│   │   │   │   │   │   ├── pointinstancers.md
│   │   │   │   │   │   ├── rbd.md
│   │   │   │   │   │   ├── transformspace.md
│   │   │   │   │   │   └── volumes.md
│   │   │   │   │   ├── hda/
│   │   │   │   │   │   └── overview.md
│   │   │   │   │   ├── overview.md
│   │   │   │   │   └── performance/
│   │   │   │   │       └── overview.md
│   │   │   │   └── overview.md
│   │   │   ├── introduction/
│   │   │   │   ├── docs.md
│   │   │   │   ├── future.md
│   │   │   │   ├── motivation.md
│   │   │   │   └── structure.md
│   │   │   └── production/
│   │   │       ├── caches/
│   │   │       │   ├── attribute.md
│   │   │       │   ├── boundingbox.md
│   │   │       │   ├── collection.md
│   │   │       │   ├── composition.md
│   │   │       │   ├── materialbinding.md
│   │   │       │   ├── overview.md
│   │   │       │   └── xform.md
│   │   │       ├── composition.md
│   │   │       ├── concepts.md
│   │   │       ├── faq.md
│   │   │       ├── overview.md
│   │   │       ├── prerequisites.md
│   │   │       └── schemas.md
│   │   └── template.md
│   └── theme/
│       ├── ext/
│       │   ├── css/
│       │   │   ├── custom.css
│       │   │   └── mdbook-admonish.css
│       │   └── js/
│       │       ├── custom.js
│       │       └── mermaid-init.js
│       ├── head.hbs.bkp
│       └── header.hbs
├── docs.bat
├── docs.sh
├── files/
│   ├── composition/
│   │   ├── composition.hipnc
│   │   ├── pixar/
│   │   │   ├── faq/
│   │   │   │   └── WhenCanYouDeleteAReference/
│   │   │   │       ├── assembly.usda
│   │   │   │       ├── assembly_with_all_variants.usda
│   │   │   │       ├── assets.usda
│   │   │   │       ├── shot.usda
│   │   │   │       └── shot_variant_switch.usda
│   │   │   └── glossary/
│   │   │       ├── inherits/
│   │   │       │   ├── Forest.usd
│   │   │       │   └── Trees.usd
│   │   │       ├── references/
│   │   │       │   ├── FlattenedMarbleCollection.usd
│   │   │       │   ├── Marble.usd
│   │   │       │   └── MarbleCollection.usd
│   │   │       └── specializes/
│   │   │           ├── Robot.usd
│   │   │           └── RobotScene.usd
│   │   └── usdSurvivalGuide/
│   │       ├── .gitignore
│   │       └── livrps/
│   │           └── sublayer_valueclip_cache_workflow/
│   │               ├── set_anim_valueclip_stitch_clips.manifest.usd
│   │               ├── set_anim_valueclip_stitch_clips.topology.usd
│   │               ├── set_anim_valueclip_stitch_clips.usd
│   │               ├── valueclip_stitch_clips.manifest.usd
│   │               ├── valueclip_stitch_clips.topology.usd
│   │               └── valueclip_stitch_clips.usd
│   ├── dcc/
│   │   └── houdini/
│   │       ├── RBD/
│   │       │   └── RBD.hipnc
│   │       ├── frustumCulling/
│   │       │   └── frustumCulling.hipnc
│   │       ├── hda/
│   │       │   └── hda.hipnc
│   │       ├── motionblur/
│   │       │   └── MotionBlur.hipnc
│   │       ├── overview.hipnc
│   │       ├── pointInstancer/
│   │       │   └── pointInstancer.hipnc
│   │       ├── points/
│   │       │   ├── points_native.hipnc
│   │       │   ├── pythonWrangle.py
│   │       │   ├── renderPreFrame.py
│   │       │   └── render_attribute_modification.hipnc
│   │       ├── profiling/
│   │       │   ├── report.json
│   │       │   ├── report.trace
│   │       │   └── tracing.hipnc
│   │       ├── timeSamples/
│   │       │   └── GetValueMightBeTimeVarying.hipnc
│   │       ├── transforms/
│   │       │   └── xforms.hipnc
│   │       └── variants/
│   │           └── variants.hipnc
│   └── plugins/
│       ├── kinds/
│       │   └── plugInfo.json
│       ├── metadata/
│       │   └── plugInfo.json
│       └── schemas/
│           ├── codelessSchema/
│           │   ├── build.sh
│           │   ├── dist/
│           │   │   ├── generatedSchema.usda
│           │   │   └── plugInfo.json
│           │   └── schema.usda
│           ├── compiledSchema/
│           │   ├── .gitignore
│           │   ├── CMakeLists.txt
│           │   ├── auxiliary/
│           │   │   ├── __init__.py
│           │   │   ├── module.cpp
│           │   │   └── moduleDeps.cpp
│           │   ├── build.sh
│           │   ├── schema.usda
│           │   └── src/
│           │       ├── __init__.py
│           │       ├── api.h
│           │       ├── complex.cpp
│           │       ├── complex.h
│           │       ├── generatedSchema.usda
│           │       ├── module.cpp
│           │       ├── moduleDeps.cpp
│           │       ├── paramsAPI.cpp
│           │       ├── paramsAPI.h
│           │       ├── plugInfo.json
│           │       ├── simple.cpp
│           │       ├── simple.h
│           │       ├── tokens.cpp
│           │       ├── tokens.h
│           │       ├── wrapComplex.cpp
│           │       ├── wrapParamsAPI.cpp
│           │       ├── wrapSimple.cpp
│           │       └── wrapTokens.cpp
│           └── exampleSchema.usda
└── setup.sh

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/mdbook.yml
================================================
name: Deploy Documentation to GitHub Pages

on:
  push:
    branches: ["main"]
  workflow_dispatch:

permissions:
  contents: read
  pages: write
  id-token: write

concurrency:
  group: "pages"
  cancel-in-progress: false

jobs:

  build:
    runs-on: ubuntu-latest
    env:
      MDBOOK_VERSION: 0.4.28         # MDBOOK_ADMONISH is depends on this exact build.
      MDBOOK_ADMONISH_VERSION: 1.9.0
      MDBOOK_MERMAID_VERSION: 0.12.6
      MDBOOK_SITEMAP_VERSION: 0.1.0
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
      - name: Install mdBook
        run: |
          mkdir ~/tools
          curl -L https://github.com/rust-lang/mdBook/releases/download/v$MDBOOK_VERSION/mdbook-v$MDBOOK_VERSION-x86_64-unknown-linux-gnu.tar.gz | tar xz -C ~/tools
          curl -L https://github.com/tommilligan/mdbook-admonish/releases/download/v$MDBOOK_ADMONISH_VERSION/mdbook-admonish-v$MDBOOK_ADMONISH_VERSION-x86_64-unknown-linux-gnu.tar.gz | tar xz -C ~/tools
          curl -L https://github.com/badboy/mdbook-mermaid/releases/download/v$MDBOOK_MERMAID_VERSION/mdbook-mermaid-v$MDBOOK_MERMAID_VERSION-x86_64-unknown-linux-gnu.tar.gz | tar xz -C ~/tools
          echo ~/tools >> $GITHUB_PATH
      - name: Install static-sitemap-cli
        run: npm install static-sitemap-cli
      - name: Setup Pages
        id: pages
        uses: actions/configure-pages@v5
      - name: Build with mdBook
        run: mdbook build -d book docs
      - name: Generate sitemap
        run: |
          cd docs/book
          npx sscli --no-clean --base https://lucascheller.github.io/VFX-UsdSurvivalGuide
          cd ../..
      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: docs/book

  deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4

================================================
FILE: .gitignore
================================================
workspace
playground
backup
build
tools
docs/book
examples
geo
*.code-workspace
*.vscode
*.so
__pycache__

================================================
FILE: LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: README.md
================================================
![Usd Survival Guide](https://raw.githubusercontent.com/LucaScheller/VFX-UsdSurvivalGuide/main/docs/src/media/UsdSurvivalGuide.png)

## USD Survival Guide
[![Deploy Documentation to GitHub Pages](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/actions/workflows/mdbook.yml/badge.svg)](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/actions/workflows/mdbook.yml)

This repository aims to be a practical onboarding guide to [USD](https://openusd.org/release/index.html) for software developers and pipeline TDs.
For more information what makes this guide unique, see the [motivation](https://lucascheller.github.io/VFX-UsdSurvivalGuide/pages/introduction/motivation.html) section.

Check out the guide's website: [Usd Survival Guide GitHub Pages Website](https://lucascheller.github.io/VFX-UsdSurvivalGuide/)

## Contributing and Acknowledgements

Please consider contributing back to the Usd project in the  official [Usd Repository](https://github.com/PixarAnimationStudios/USD) and via the [Usd User groups](https://wiki.aswf.io/display/WGUSD/USD+Working+Group).

Feel free to fork this repository and share improvements.
If you run into issues, please flag them by [submitting a ticket](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/issues/new).

## Contributors:
For a full list of who contributed to this guide visit:
[Usd Survival Guide - Introduction](https://lucascheller.github.io/VFX-UsdSurvivalGuide/)

================================================
FILE: code/core/composition.py
================================================
#// ANCHOR: compositionEditTarget
from pxr import Sdf, Usd
## Standard way of using edit targets
stage = Usd.Stage.CreateInMemory()
root_layer = stage.GetRootLayer()
a_layer = Sdf.Layer.CreateAnonymous("LayerA")
b_layer = Sdf.Layer.CreateAnonymous("LayerB")
root_layer.subLayerPaths.append(a_layer.identifier)
root_layer.subLayerPaths.append(b_layer.identifier)
# Direct edits to different layers
stage.SetEditTarget(Usd.EditTarget(a_layer))
bicycle_prim = stage.DefinePrim(Sdf.Path("/bicycle"), "Xform")
stage.SetEditTarget(Usd.EditTarget(b_layer))
car_prim = stage.DefinePrim(Sdf.Path("/car"), "Xform")
print(b_layer.ExportToString())
"""Returns:
#sdf 1.4.32
def Xform "car"
{
}
"""
## Reference/Payload Edit Targets
asset_stage = Usd.Stage.CreateInMemory()
cube_prim = asset_stage.DefinePrim(Sdf.Path("/root/RENDER/cube"), "Xform")
asset_layer = asset_stage.GetRootLayer()
shot_stage = Usd.Stage.CreateInMemory()
car_prim = shot_stage.DefinePrim(Sdf.Path("/set/garage/car"), "Xform")
car_prim.GetReferences().AddReference(asset_layer.identifier, Sdf.Path("/root"), Sdf.LayerOffset(10))
# We can't construct edit targets to layers that are not sublayers in the active layer stack.
# Is this a bug? According to the docs https://openusd.org/dev/api/class_usd_edit_target.html it should work.
# shot_stage.SetEditTarget(Usd.EditTarget(asset_layer))
## Variant Edit Targets
from pxr import Sdf, Usd
stage = Usd.Stage.CreateInMemory()
bicycle_prim_path = Sdf.Path("/bicycle")
bicycle_prim = stage.DefinePrim(bicycle_prim_path, "Xform")
variant_sets_api = bicycle_prim.GetVariantSets()
variant_set_api = variant_sets_api.AddVariantSet("color", position=Usd.ListPositionBackOfPrependList)
variant_set_api.AddVariant("colorA")
variant_set_api.SetVariantSelection("colorA")
with variant_set_api.GetVariantEditContext():
    # Anything we write in this edit target context, goes into the variant.
    cube_prim_path = bicycle_prim_path.AppendChild("cube")
    cube_prim = stage.DefinePrim(cube_prim_path, "Cube")
print(stage.GetEditTarget().GetLayer().ExportToString())
"""Returns:
#usda 1.0

def Xform "bicycle" (
    variants = {
        string color = "colorA"
    }
    prepend variantSets = "color"
)
{
    variantSet "color" = {
        "colorA" {
            def Cube "cube"
            {
            }

        }
    }
}
"""
#// ANCHOR_END: compositionEditTarget


#// ANCHOR: compositionEditTargetContext
from pxr import Sdf, Usd
stage = Usd.Stage.CreateInMemory()
root_layer = stage.GetRootLayer()
a_layer = Sdf.Layer.CreateAnonymous("LayerA")
b_layer = Sdf.Layer.CreateAnonymous("LayerB")
root_layer.subLayerPaths.append(a_layer.identifier)
root_layer.subLayerPaths.append(b_layer.identifier)
# Set edit target to a_layer
stage.SetEditTarget(a_layer)
bicycle_prim_path = Sdf.Path("/bicycle")
bicycle_prim = stage.DefinePrim(bicycle_prim_path, "Xform")
edit_target = Usd.EditTarget(b_layer)
with Usd.EditContext(stage, edit_target):
    print("Edit Target Layer:", stage.GetEditTarget().GetLayer()) # Edit Target Layer: Sdf.Find('anon:0x7ff9f4391580:LayerB')
    car_prim_path = Sdf.Path("/car")
    car_prim = stage.DefinePrim(car_prim_path, "Xform")
print("Edit Target Layer:", stage.GetEditTarget().GetLayer()) # Edit Target Layer: Sdf.Find('anon:0x7ff9f4391580:LayerA')
# Verify result
print(a_layer.ExportToString())
"""Returns:
#sdf 1.4.32
def Xform "bicycle"
{
}
"""
print(b_layer.ExportToString())
"""Returns:
#sdf 1.4.32
def Xform "car"
{
}
"""
#// ANCHOR_END: compositionEditTargetContext

#// ANCHOR: compositionListEditableOpsBasics
from pxr import Sdf
# Sdf.ReferenceListOp, Sdf.PayloadListOp, Sdf.PathListOp,
path_list_op = Sdf.PathListOp()
# There are multiple sub-lists, which are just normal Python lists.
# 'prependedItems', 'appendedItems', 'deletedItems', 'explicitItems',
# Legacy sub-lists (do not use these anymore): 'addedItems', 'orderedItems'
# Currently the way these are exposed to Python, you have to re-assign the list, instead of editing it in place.
# So this won't work:
path_list_op.prependedItems.append(Sdf.Path("/cube"))
path_list_op.appendedItems.append(Sdf.Path("/sphere"))
# Instead do this:
path_list_op.prependedItems = [Sdf.Path("/cube")]
path_list_op.appendedItems = [Sdf.Path("/sphere")]
# To clear the list op:
print(path_list_op) # Returns: SdfPathListOp(Prepended Items: [/cube], Appended Items: [/sphere])
path_list_op.Clear()
print(path_list_op) # Returns: SdfPathListOp()
# Repopulate via constructor
path_list_op = Sdf.PathListOp.Create(prependedItems = [Sdf.Path("/cube")], appendedItems = [Sdf.Path("/sphere")])
print(path_list_op) # Returns: SdfPathListOp(Prepended Items: [/cube], Appended Items: [/sphere])
# Add remove items
path_list_op.deletedItems = [Sdf.Path("/sphere")]
print(path_list_op) # Returns: SdfPathListOp(Deleted Items: [/sphere], Prepended Items: [/cube], Appended Items: [/sphere])
# Notice how it just stores lists, it doesn't actually apply them. We'll have a look at that next.

# In the high level API, all the function signatures that work on list-editable ops
# usually take a position kwarg which corresponds to what list to edit and the position (front/back)
Usd.ListPositionFrontOfAppendList
Usd.ListPositionBackOfAppendList
Usd.ListPositionFrontOfPrependList
Usd.ListPositionBackOfPrependList
# We cover how to use this is our 'Composition Arcs' section.
#// ANCHOR_END: compositionListEditableOpsBasics

#// ANCHOR: compositionListEditableOpsMerging
from pxr import Sdf
### Merging basics ###
path_list_op_layer_top = Sdf.PathListOp.Create(deletedItems = [Sdf.Path("/cube")])
path_list_op_layer_middle = Sdf.PathListOp.Create(prependedItems = [Sdf.Path("/disc"), Sdf.Path("/cone")])
path_list_op_layer_bottom = Sdf.PathListOp.Create(prependedItems = [Sdf.Path("/cube")], appendedItems = [Sdf.Path("/cone"),Sdf.Path("/sphere")])

result = Sdf.PathListOp()
result = result.ApplyOperations(path_list_op_layer_top)
result = result.ApplyOperations(path_list_op_layer_middle)
result = result.ApplyOperations(path_list_op_layer_bottom)
# Notice how on merge it makes sure that each sublist does not have the values of the other sublists, just like a Python set()
print(result) # Returns: SdfPathListOp(Deleted Items: [/cube], Prepended Items: [/disc, /cone], Appended Items: [/sphere])
# Get the flattened result. This does not apply the deleteItems, only ApplyOperations does that. 
print(result.GetAddedOrExplicitItems()) # Returns: [Sdf.Path('/disc'), Sdf.Path('/cone'), Sdf.Path('/sphere')]

### Deleted and added items ###
path_list_op_layer_top = Sdf.PathListOp.Create(appendedItems=[Sdf.Path("/disc"), Sdf.Path("/cube")])
path_list_op_layer_middle = Sdf.PathListOp.Create(deletedItems = [Sdf.Path("/cube")])
path_list_op_layer_bottom = Sdf.PathListOp.Create(prependedItems = [Sdf.Path("/cube")], appendedItems = [Sdf.Path("/sphere")])

result = Sdf.PathListOp()
result = result.ApplyOperations(path_list_op_layer_top)
result = result.ApplyOperations(path_list_op_layer_middle)
result = result.ApplyOperations(path_list_op_layer_bottom)
print(result) # Returns: SdfPathListOp(Appended Items: [/sphere, /disc, /cube])
# Since it now was in the explicit list, it got removed.

### Explicit mode ###
# There is also an "explicit" mode. This clears all previous values on merge and marks the list as explicit.
# Once explicit and can't be un-explicited. An explicit list is like a reset, it 
# doesn't know anything about the previous values anymore. All lists that are merged
# after combine the result to be explicit.
path_list_op_layer_top = Sdf.PathListOp.Create(deletedItems = [Sdf.Path("/cube")])
path_list_op_layer_middle = Sdf.PathListOp.CreateExplicit([Sdf.Path("/disc")])
path_list_op_layer_bottom = Sdf.PathListOp.Create(prependedItems = [Sdf.Path("/cube")], appendedItems = [Sdf.Path("/sphere")])

result = Sdf.PathListOp()
result = result.ApplyOperations(path_list_op_layer_top)
result = result.ApplyOperations(path_list_op_layer_middle)
result = result.ApplyOperations(path_list_op_layer_bottom)
print(result, result.isExplicit) # Returns: SdfPathListOp(Explicit Items: [/disc]), True
# Notice how the deletedItems had no effect, as "/cube" is not in the explicit list.

path_list_op_layer_top = Sdf.PathListOp.Create(deletedItems = [Sdf.Path("/cube")])
path_list_op_layer_middle = Sdf.PathListOp.CreateExplicit([Sdf.Path("/disc"), Sdf.Path("/cube")])
path_list_op_layer_bottom = Sdf.PathListOp.Create(prependedItems = [Sdf.Path("/cube")], appendedItems = [Sdf.Path("/sphere")])

result = Sdf.PathListOp()
result = result.ApplyOperations(path_list_op_layer_top)
result = result.ApplyOperations(path_list_op_layer_middle)
result = result.ApplyOperations(path_list_op_layer_bottom)
print(result, result.isExplicit) # Returns: SdfPathListOp(Explicit Items: [/disc]), True
# Since it now was in the explicit list, it got removed.
#// ANCHOR_END: compositionListEditableOpsMerging


#// ANCHOR: compositionArcSublayer
# For sublayering we modify the .subLayerPaths attribute on a layer.
# This is the same for both the high and low level API.
### High Level & Low Level ###
from pxr import Sdf, Usd
stage = Usd.Stage.CreateInMemory()
# Layer onto root layer
layer_a = Sdf.Layer.CreateAnonymous()
layer_b = Sdf.Layer.CreateAnonymous()
root_layer = stage.GetRootLayer()
# Here we pass in the file paths (=layer identifiers).
root_layer.subLayerPaths.append(layer_a.identifier)
root_layer.subLayerPaths.append(layer_b.identifier)
# Once we have added the sublayers, we can also access their layer offsets:
print(root_layer.subLayerOffsets) # Returns: [Sdf.LayerOffset(), Sdf.LayerOffset()]
# Since layer offsets are read only copies, we need to assign a newly created 
# layer offset if we want to modify them. We also can't replace the whole list, as
# it needs to keep a pointer to the array.
layer_offset_a = root_layer.subLayerOffsets[0]
root_layer.subLayerOffsets[0] = Sdf.LayerOffset(offset=layer_offset_a.offset + 10, 
                                                scale=layer_offset_a.scale * 2)
layer_offset_b = root_layer.subLayerOffsets[1]
root_layer.subLayerOffsets[1] = Sdf.LayerOffset(offset=layer_offset_b.offset - 10, 
                                                scale=layer_offset_b.scale * 0.5)
print(root_layer.subLayerOffsets) # Returns: [Sdf.LayerOffset(10, 2), Sdf.LayerOffset(-10, 0.5)]

# If we want to sublayer on the active layer, we just add it there.
layer_c = Sdf.Layer.CreateAnonymous()
active_layer = stage.GetEditTarget().GetLayer()
active_layer.subLayerPaths.append(layer_c.identifier)
#// ANCHOR_END: compositionArcSublayer


#// ANCHOR: compositionArcSublayerHoudini
### High Level & Low Level ###
import loputils
from pxr import Sdf
# Hou LOP Node https://www.sidefx.com/docs/houdini/hom/hou/LopNode.html
# See $HFS/houdini/python3.9libs/loputils.py
"""
def createPythonLayer(node, savepath=None):
    # Tag the layer as "LOP" so we know it was created by LOPs.
    layer = Sdf.Layer.CreateAnonymous('LOP')
    # Add a Houdini Layer Info prim where we can put the save path.
    p = Sdf.CreatePrimInLayer(layer, '/HoudiniLayerInfo')
    p.specifier = Sdf.SpecifierDef
    p.typeName = 'HoudiniLayerInfo'/stage/list_editable_ops/pythonscript6
    if savepath:
        p.customData['HoudiniSavePath'] = hou.text.expandString(savepath)
        p.customData['HoudiniSaveControl'] = 'Explicit'
    # Let everyone know what node created this layer.
    p.customData['HoudiniCreatorNode'] = node.sessionId()
    p.customData['HoudiniEditorNodes'] = Vt.IntArray([node.sessionId()])
    node.addHeldLayer(layer.identifier)
    return layer
"""
# Sublayer onto root layer via Python LOP node
node = hou.pwd()
stage = node.editableStage()
layer = loputils.createPythonLayer(node, '$HIP/myfile.usda')
node.addSubLayer(layer.identifier)
# This doesn't seem to work at the moment, as Houdini does some custom root layer handeling
# print(root_layer.subLayerPaths) # Our added layer does not show up. So we have to use the `sublayer` node.
# root_layer = stage.GetRootLayer()
# root_layer.subLayerOffsets[0] = Sdf.LayerOffset(offset=10, scale=1)

# Sublayer onto active layer via Python LOP node, here we can do the usual.
node = hou.pwd()
layer = node.editableLayer()
layer_a = loputils.createPythonLayer(node, '$HIP/myfile.usda')
layer.subLayerPaths.append(layer_a.identifier)
layer.subLayerOffsets[0] = Sdf.LayerOffset(offset=10, scale=1)

# Since layers are automatically garbage collected once they go out of scope,
# we can tag them to keep them persistently in memory for the active session.
layer_b = Sdf.Layer.CreateAnonymous()
node.addHeldLayer(layer_b.identifier)
# This can then be re-used via the standard anywhere in Houdini.
layer_b = Sdf.Layer.FindOrOpen(layer_b.identifier)
#// ANCHOR_END: compositionArcSublayerHoudini


#// ANCHOR: compositionArcInherit
### High Level ###
from pxr import Sdf, Usd
stage = Usd.Stage.CreateInMemory()
bicycle_prim_path = Sdf.Path("/bicycle")
bicycle_prim = stage.DefinePrim(bicycle_prim_path)
cube_prim_path = Sdf.Path("/cube")
cube_prim = stage.DefinePrim(cube_prim_path, "Cube")
inherits_api = bicycle_prim.GetInherits()
inherits_api.AddInherit(cube_prim_path, position=Usd.ListPositionFrontOfAppendList)
# inherits_api.SetInherits() # Clears the list editable ops and authors an Sdf.PathListOp.CreateExplicit([])
# inherits_api.RemoveInherit(cube_prim_path)
# inherits_api.ClearInherits() # Sdf.PathListOp.Clear()
# inherits_api.GetAllDirectInherits() # Returns all inherits generated in the active layer stack
### Low Level ###
from pxr import Sdf
layer = Sdf.Layer.CreateAnonymous()
bicycle_prim_path = Sdf.Path("/bicycle")
bicycle_prim_spec = Sdf.CreatePrimInLayer(layer, bicycle_prim_path)
bicycle_prim_spec.specifier = Sdf.SpecifierDef
cube_prim_path = Sdf.Path("/cube")
cube_prim_spec = Sdf.CreatePrimInLayer(layer, cube_prim_path)
cube_prim_spec.specifier = Sdf.SpecifierDef
cube_prim_spec.typeName = "Cube"
bicycle_prim_spec.inheritPathList.appendedItems = [cube_prim_path]
#// ANCHOR_END: compositionArcInherit

#// ANCHOR: compositionArcVariant
### High Level ###
from pxr import Sdf, Usd
stage = Usd.Stage.CreateInMemory()

bicycle_prim_path = Sdf.Path("/bicycle")
bicycle_prim = stage.DefinePrim(bicycle_prim_path, "Xform")
## Methods of Usd.VariantSets
# Has: 'HasVariantSet'
# Get: 'GetNames', 'GetVariantSet', 'GetVariantSelection', 'GetAllVariantSelections'
# Set: 'AddVariantSet', 'SetSelection'
variant_sets_api = bicycle_prim.GetVariantSets()
## Methods of Usd.VariantSet
# Has: 'HasAuthoredVariant', 'HasAuthoredVariantSelection'
# Get: 'GetName', 'GetVariantNames', 'GetVariantSelection', 'GetVariantEditContext', 'GetVariantEditTarget'
# Set: 'AddVariant', 'SetVariantSelection'
# Clear: 'BlockVariantSelection', 'ClearVariantSelection'
variant_set_api = variant_sets_api.AddVariantSet("color", position=Usd.ListPositionBackOfPrependList)
variant_set_api.AddVariant("colorA")
# If we want to author on the selected variant, we have to select it first
variant_set_api.SetVariantSelection("colorA")
with variant_set_api.GetVariantEditContext():
    # Anything we write in the context, goes into the variant (prims and properties)
    cube_prim_path = bicycle_prim_path.AppendChild("cube")
    cube_prim = stage.DefinePrim(cube_prim_path, "Cube")
# We can also generate the edit target ourselves, but we still need to set the
# variant selection, seems like a bug. Changing variants is a heavy op ...
variant_set_api.AddVariant("colorB")
variant_set_api.SetVariantSelection("colorB")
variant_prim_path = bicycle_prim_path.AppendVariantSelection("color", "colorB") 
layer = stage.GetEditTarget().GetLayer()
edit_target = Usd.EditTarget.ForLocalDirectVariant(layer, variant_prim_path)
# Or
edit_target = variant_set_api.GetVariantEditTarget()
edit_context = Usd.EditContext(stage, edit_target) 
with edit_context as ctx:
    sphere_prim_path = bicycle_prim_path.AppendChild("sphere")
    sphere_prim = stage.DefinePrim("/bicycle/sphere", "Sphere")
### Low Level ###
from pxr import Sdf
layer = Sdf.Layer.CreateAnonymous()
bicycle_prim_path = Sdf.Path("/bicycle")
bicycle_prim_spec = Sdf.CreatePrimInLayer(layer, bicycle_prim_path)
bicycle_prim_spec.specifier = Sdf.SpecifierDef
bicycle_prim_spec.typeName = "Xform"
# Variants
cube_prim_path = bicycle_prim_path.AppendVariantSelection("color", "colorA").AppendChild("cube")
cube_prim_spec = Sdf.CreatePrimInLayer(layer, cube_prim_path)
cube_prim_spec.specifier = Sdf.SpecifierDef
cube_prim_spec.typeName = "Cube"
sphere_prim_path = bicycle_prim_path.AppendVariantSelection("color", "colorB").AppendChild("sphere")
sphere_prim_spec = Sdf.CreatePrimInLayer(layer, sphere_prim_path)
sphere_prim_spec.specifier = Sdf.SpecifierDef
sphere_prim_spec.typeName = "Sphere"
# Variant Selection
bicycle_prim_spec.variantSelections["color"] = "colorA"

# We can also author the variants via variant specs
layer = Sdf.Layer.CreateAnonymous()
car_prim_path = Sdf.Path("/car")
car_prim_spec = Sdf.CreatePrimInLayer(layer, car_prim_path)
car_prim_spec.specifier = Sdf.SpecifierDef
car_prim_spec.typeName = "Xform"
# Variants
variant_set_spec = Sdf.VariantSetSpec(car_prim_spec, "color")
variant_spec = Sdf.VariantSpec(variant_set_spec, "colorA")
cube_prim_spec = Sdf.PrimSpec(variant_spec.primSpec, "cube", Sdf.SpecifierDef)
cube_prim_spec.typeName = "Cube"
variant_spec = Sdf.VariantSpec(variant_set_spec, "colorB")
cube_prim_spec = Sdf.PrimSpec(variant_spec.primSpec, "sphere", Sdf.SpecifierDef)
cube_prim_spec.typeName = "Sphere"
# Ironically this does not setup the variant set names metadata, so we have to author it ourselves.
car_prim_spec.SetInfo("variantSetNames", Sdf.StringListOp.Create(prependedItems=["color"]))
# Variant Selection
car_prim_spec.variantSelections["color"] = "colorA"
#// ANCHOR_END: compositionArcVariant

#// ANCHOR: compositionArcVariantCopySpec
from pxr import Sdf
# Spawn other layer, this usually comes from other stages, that your DCC creates/owns.
some_other_layer = Sdf.Layer.CreateAnonymous()
root_prim_path = Sdf.Path("/root")
cube_prim_path = Sdf.Path("/root/cube")
cube_prim_spec = Sdf.CreatePrimInLayer(some_other_layer, cube_prim_path)
cube_prim_spec.specifier = Sdf.SpecifierDef
cube_prim_spec.typeName = "Cube"
# Create demo layer
bicycle_prim_path = Sdf.Path("/bicycle")
bicycle_prim_spec = Sdf.CreatePrimInLayer(layer, bicycle_prim_path)
bicycle_prim_spec.specifier = Sdf.SpecifierDef
bicycle_prim_spec.typeName = "Xform"
# Copy content into variant
variant_set_spec = Sdf.VariantSetSpec(bicycle_prim_spec, "color")
variant_spec = Sdf.VariantSpec(variant_set_spec, "colorA")
variant_prim_path = bicycle_prim_path.AppendVariantSelection("color", "colorA")
Sdf.CopySpec(some_other_layer, root_prim_path, layer, variant_prim_path)
# Variant selection
bicycle_prim_spec.SetInfo("variantSetNames", Sdf.StringListOp.Create(prependedItems=["color"]))
bicycle_prim_spec.variantSelections["color"] = "colorA"
#// ANCHOR_END: compositionArcVariantCopySpec

#// ANCHOR: compositionArcVariantCopyHoudini
from pxr import Sdf, Usd

node = hou.pwd()
layer = node.editableLayer()

source_node = node.parm("spare_input0").evalAsNode()
source_stage = source_node.stage()
source_layer = source_node.activeLayer()

with Sdf.ChangeBlock():
    iterator = iter(Usd.PrimRange(source_stage.GetPseudoRoot()))
    for prim in iterator:
        if "GEO" not in prim.GetChildrenNames():
            continue
        iterator.PruneChildren()
        prim_path = prim.GetPath()
        prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
        prim_spec.specifier = Sdf.SpecifierDef
        prim_spec.typeName = "Xform"
        parent_prim_spec = prim_spec.nameParent
        while parent_prim_spec:
            parent_prim_spec.specifier = Sdf.SpecifierDef
            parent_prim_spec.typeName = "Xform"
            parent_prim_spec = parent_prim_spec.nameParent
                    
        # Copy content into variant
        variant_set_spec = Sdf.VariantSetSpec(prim_spec, "model")
        variant_spec = Sdf.VariantSpec(variant_set_spec, "myCoolVariant")
        variant_prim_path = prim_path.AppendVariantSelection("model", "myCoolVariant")
        Sdf.CopySpec(source_layer, prim_path, layer, variant_prim_path)
        # Variant selection
        prim_spec.SetInfo("variantSetNames", Sdf.StringListOp.Create(prependedItems=["model"]))
        prim_spec.variantSelections["model"] = "myCoolVariant"
#// ANCHOR_END: compositionArcVariantCopyHoudini

#// ANCHOR: compositionArcVariantMoveHoudini
from pxr import Sdf, Usd

node = hou.pwd()
layer = node.editableLayer()

source_node = node.parm("spare_input0").evalAsNode()
source_stage = source_node.stage()
source_layer = source_node.activeLayer()

with Sdf.ChangeBlock():
    edit = Sdf.BatchNamespaceEdit()

    iterator = iter(Usd.PrimRange(source_stage.GetPseudoRoot()))
    for prim in iterator:
        if "GEO" not in prim.GetChildrenNames():
            continue
        iterator.PruneChildren()
        prim_path = prim.GetPath()
        prim_spec = layer.GetPrimAtPath(prim_path)
        # Move content into variant
        variant_set_spec = Sdf.VariantSetSpec(prim_spec, "model")
        variant_spec = Sdf.VariantSpec(variant_set_spec, "myCoolVariant")
        variant_prim_path = prim_path.AppendVariantSelection("model", "myCoolVariant")
        edit.Add(prim_path.AppendChild("GEO"), variant_prim_path.AppendChild("GEO"))
        # Variant selection
        prim_spec.SetInfo("variantSetNames", Sdf.StringListOp.Create(prependedItems=["model"]))
        prim_spec.variantSelections["model"] = "myCoolVariant"
        
    if not layer.Apply(edit):
        raise Exception("Failed to apply layer edit!")
#// ANCHOR_END: compositionArcVariantMoveHoudini


#// ANCHOR: compositionArcVariantNested
### High Level ###
from pxr import Sdf, Usd
stage = Usd.Stage.CreateInMemory()

def variant_nested_edit_context(prim, variant_selections, position=Usd.ListPositionBackOfPrependList):
    """Author nested variants
    Args:
        prim (Usd.Prim): The prim to author on.
        variant_selections (list): A list of tuples with [('variant_set_name', 'variant_name')] data.
        position (Usd.ListPosition): The list position of the variant set.
    Returns:
        Usd.EditContext: An edit context manager.
    """
    
    if not variant_selections:
        raise Exception("No valid variant selections defined!")
        
    def _recursive_variant_context(prim, variant_selections, position):
        variant_sets_api = bicycle_prim.GetVariantSets()
        
        variant_selection = variant_selections.pop(-1)
        variant_set_name, variant_name = variant_selection
        
        variant_set_api = variant_sets_api.AddVariantSet(variant_set_name, position=position)
        variant_set_api.AddVariant(variant_name)
        # Be aware, this authors the selection in the variant
        # ToDo make this a context manager that cleans up the selection authoring.
        variant_set_api.SetVariantSelection(variant_name)
        
        if not variant_selections:
            return variant_set_api.GetVariantEditContext()
        else:
            with variant_set_api.GetVariantEditContext():
                return _recursive_variant_context(prim, variant_selections, position)
    
    variant_selections = variant_selections[::-1]
    return _recursive_variant_context(prim, variant_selections, position)

bicycle_prim_path = Sdf.Path("/bicycle")
bicycle_prim = stage.DefinePrim(bicycle_prim_path, "Xform")
# Variants
variant_selections = [("model", "old"), ("LOD", "lowRes")]
edit_context = variant_nested_edit_context(bicycle_prim, variant_selections)
with edit_context as ctx:
    sphere_prim_path = bicycle_prim_path.AppendChild("sphere")
    sphere_prim = stage.DefinePrim("/bicycle/sphere", "Sphere")
variant_selections = [("model", "old"), ("LOD", "highRes")]
edit_context = variant_nested_edit_context(bicycle_prim, variant_selections)
with edit_context as ctx:
    sphere_prim_path = bicycle_prim_path.AppendChild("cube")
    sphere_prim = stage.DefinePrim("/bicycle/cube", "Cube")
variant_selections = [("model", "new"), ("LOD", "lowRes")]
edit_context = variant_nested_edit_context(bicycle_prim, variant_selections)
with edit_context as ctx:
    sphere_prim_path = bicycle_prim_path.AppendChild("cylinder")
    sphere_prim = stage.DefinePrim("/bicycle/cube", "Cylinder")
# Variant selections
# Be sure to explicitly set the overall selection, otherwise if will derive from,
# the nested variant selections.
variant_sets_api = bicycle_prim.GetVariantSets()
variant_sets_api.SetSelection("model", "old")
variant_sets_api.SetSelection("LOD", "lowRes")

### Low Level ###
from pxr import Sdf
layer = Sdf.Layer.CreateAnonymous()
def variant_nested_prim_path(prim_path, variant_selections):
    variant_prim_path = prim_path
    for variant_set_name, variant_name in variant_selections:
        variant_prim_path = variant_prim_path.AppendVariantSelection(variant_set_name, variant_name)
    return variant_prim_path
    
def define_prim_spec(layer, prim_path, type_name):
    prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
    prim_spec.specifier = Sdf.SpecifierDef
    prim_spec.typeName = type_name

bicycle_prim_path = Sdf.Path("/bicycle")
bicycle_prim_spec = Sdf.CreatePrimInLayer(layer, bicycle_prim_path)
bicycle_prim_spec.specifier = Sdf.SpecifierDef
bicycle_prim_spec.typeName = "Xform"
# Variants
variant_selections = [("model", "old"), ("LOD", "lowRes")]
variant_prim_path = variant_nested_prim_path(bicycle_prim_path, variant_selections)
define_prim_spec(layer, variant_prim_path.AppendChild("sphere"), "Sphere")
variant_selections = [("model", "old"), ("LOD", "highRes")]
variant_prim_path = variant_nested_prim_path(bicycle_prim_path, variant_selections)
define_prim_spec(layer, variant_prim_path.AppendChild("cube"), "Cube")
variant_selections = [("model", "new"), ("LOD", "lowRes")]
variant_prim_path = variant_nested_prim_path(bicycle_prim_path, variant_selections)
define_prim_spec(layer, variant_prim_path.AppendChild("cylinder"), "Cylinder")
# Variant selections
# The low level API has the benefit of not setting variant selections
# in the nested variants.
bicycle_prim_spec.variantSelections["model"] = "old"
bicycle_prim_spec.variantSelections["LOD"] = "highRes"
#// ANCHOR_END: compositionArcVariantNested


#// ANCHOR: compositionArcReferenceExternal
### High Level ###
from pxr import Sdf, Usd
stage = Usd.Stage.CreateInMemory()
# Spawn temp layer
reference_layer = Sdf.Layer.CreateAnonymous("ReferenceExample")
reference_bicycle_prim_path = Sdf.Path("/bicycle")
reference_bicycle_prim_spec = Sdf.CreatePrimInLayer(reference_layer, reference_bicycle_prim_path)
reference_bicycle_prim_spec.specifier = Sdf.SpecifierDef
reference_bicycle_prim_spec.typeName = "Cube"
# Set the default prim to use when we specify no primpath. It can't be a prim path, it must be a root prim.
reference_layer.defaultPrim = reference_bicycle_prim_path.name
# Reference
reference_layer_offset = Sdf.LayerOffset(offset=10, scale=1)
reference = Sdf.Reference(reference_layer.identifier, reference_bicycle_prim_path, reference_layer_offset)
# Or: If we don't specify a prim, the default prim will get used, as set above
reference = Sdf.Reference(reference_layer.identifier, layerOffset=reference_layer_offset)
bicycle_prim_path = Sdf.Path("/bicycle")
bicycle_prim = stage.DefinePrim(bicycle_prim_path)
references_api = bicycle_prim.GetReferences()
references_api.AddReference(reference, position=Usd.ListPositionFrontOfAppendList)
# references_api.SetReferences() # Clears the list editable ops and authors an Sdf.ReferenceListOp.CreateExplicit([])
# references_api.RemoveReference(cube_prim_path)
# references_api.ClearReferences() # Sdf.ReferenceListOp.Clear()
### Low Level ###
from pxr import Sdf
# Spawn temp layer
reference_layer = Sdf.Layer.CreateAnonymous("ReferenceExample")
reference_bicycle_prim_path = Sdf.Path("/bicycle")
reference_bicycle_prim_spec = Sdf.CreatePrimInLayer(reference_layer, reference_bicycle_prim_path)
reference_bicycle_prim_spec.specifier = Sdf.SpecifierDef
reference_bicycle_prim_spec.typeName = "Cube"
reference_layer.defaultPrim = reference_bicycle_prim_path.name
# In Houdini add, otherwise the layer will be garbage collected.
# node.addHeldLayer(reference_layer.identifier)
# Reference
layer = Sdf.Layer.CreateAnonymous()
bicycle_prim_path = Sdf.Path("/bicycle")
bicycle_prim_spec = Sdf.CreatePrimInLayer(layer, bicycle_prim_path)
bicycle_prim_spec.specifier = Sdf.SpecifierDef
reference_layer_offset = Sdf.LayerOffset(offset=10, scale=1)
reference = Sdf.Reference(reference_layer.identifier, reference_bicycle_prim_path, reference_layer_offset)
# Or: If we don't specify a prim, the default prim will get used, as set above
reference = Sdf.Reference(reference_layer.identifier, layerOffset=reference_layer_offset)
bicycle_prim_spec.referenceList.appendedItems = [reference]
#// ANCHOR_END: compositionArcReferenceExternal

#// ANCHOR: compositionArcReferenceClass
from pxr import Sdf
ref = Sdf.Reference("/file/path.usd", "/prim/path", Sdf.LayerOffset(offset=10, scale=1))
# The reference object is a read only instance.
print(ref.assetPath) # Returns: "/file/path.usd"
print(ref.primPath) # Returns: "/prim/path"
print(ref.layerOffset) # Returns: Sdf.LayerOffset(offset=10, scale=1)
try: 
    ref.assetPath = "/some/other/file/path.usd"
except Exception:
    print("Read only Sdf.Reference!")
#// ANCHOR_END: compositionArcReferenceClass

#// ANCHOR: compositionArcReferenceInternal
### High Level ###
from pxr import Sdf, Usd
stage = Usd.Stage.CreateInMemory()
# Spawn hierarchy
cube_prim_path = Sdf.Path("/cube")
cube_prim = stage.DefinePrim(cube_prim_path, "Cube")
bicycle_prim_path = Sdf.Path("/bicycle")
bicycle_prim = stage.DefinePrim(bicycle_prim_path)
# Reference
reference_layer_offset = Sdf.LayerOffset(offset=10, scale=1)
reference = Sdf.Reference("", cube_prim_path, reference_layer_offset)
references_api = bicycle_prim.GetReferences()
references_api.AddReference(reference, position=Usd.ListPositionFrontOfAppendList)
# Or:
references_api.AddInternalReference(cube_prim_path, reference_layer_offset, position=Usd.ListPositionFrontOfAppendList)
### Low Level ###
from pxr import Sdf
# Spawn hierarchy
layer = Sdf.Layer.CreateAnonymous()
cube_prim_path = Sdf.Path("/cube")
cube_prim_spec = Sdf.CreatePrimInLayer(layer, cube_prim_path)
cube_prim_spec.specifier = Sdf.SpecifierDef
cube_prim_spec.typeName = "Cube"
bicycle_prim_path = Sdf.Path("/bicycle")
bicycle_prim_spec = Sdf.CreatePrimInLayer(layer, bicycle_prim_path)
bicycle_prim_spec.specifier = Sdf.SpecifierDef
# Reference
reference_layer_offset = Sdf.LayerOffset(offset=10, scale=1)
reference = Sdf.Reference("", cube_prim_path, reference_layer_offset)
bicycle_prim_spec.referenceList.appendedItems = [reference]
#// ANCHOR_END: compositionArcReferenceInternal

#// ANCHOR: compositionArcPayloadClass
from pxr import Sdf
payload = Sdf.Payload("/file/path.usd", "/prim/path", Sdf.LayerOffset(offset=10, scale=1))
# The reference object is a read only instance.
print(payload.assetPath) # Returns: "/file/path.usd"
print(payload.primPath) # Returns: "/prim/path"
print(payload.layerOffset) # Returns: Sdf.LayerOffset(offset=10, scale=1)
try: 
    payload.assetPath = "/some/other/file/path.usd"
except Exception:
    print("Read only Sdf.Payload!")
#// ANCHOR_END: compositionArcPayloadClass


#// ANCHOR: compositionArcPayload
### High Level ###
from pxr import Sdf, Usd
stage = Usd.Stage.CreateInMemory()
# Spawn temp layer
payload_layer = Sdf.Layer.CreateAnonymous("PayloadExample")
payload_bicycle_prim_path = Sdf.Path("/bicycle")
payload_bicycle_prim_spec = Sdf.CreatePrimInLayer(payload_layer, payload_bicycle_prim_path)
payload_bicycle_prim_spec.specifier = Sdf.SpecifierDef
payload_bicycle_prim_spec.typeName = "Cube"
# Set the default prim to use when we specify no primpath. It can't be a prim path, it must be a root prim.
payload_layer.defaultPrim = payload_bicycle_prim_path.name
# Payload
payload_layer_offset = Sdf.LayerOffset(offset=10, scale=1)
payload = Sdf.Payload(payload_layer.identifier, payload_bicycle_prim_path, payload_layer_offset)
# Or: If we don't specify a prim, the default prim will get used, as set above
payload = Sdf.Payload(payload_layer.identifier, layerOffset=payload_layer_offset)
bicycle_prim_path = Sdf.Path("/bicycle")
bicycle_prim = stage.DefinePrim(bicycle_prim_path)
payloads_api = bicycle_prim.GetPayloads()
payloads_api.AddPayload(payload, position=Usd.ListPositionFrontOfAppendList)
# payloads_api.SetPayloads() # Clears the list editable ops and authors an Sdf.PayloadListOp.CreateExplicit([])
# payloads_api.RemovePayload(cube_prim_path)
# payloads_api.ClearPayloads() # Sdf.PayloadListOp.Clear()
### Low Level ###
from pxr import Sdf
# Spawn temp layer
payload_layer = Sdf.Layer.CreateAnonymous("PayLoadExample")
payload_bicycle_prim_path = Sdf.Path("/bicycle")
payload_bicycle_prim_spec = Sdf.CreatePrimInLayer(payload_layer, payload_bicycle_prim_path)
payload_bicycle_prim_spec.specifier = Sdf.SpecifierDef
payload_bicycle_prim_spec.typeName = "Cube"
payload_layer.defaultPrim = payload_bicycle_prim_path.name
# In Houdini add, otherwise the layer will be garbage collected.
# node.addHeldLayer(payload_layer.identifier)
# Payload
layer = Sdf.Layer.CreateAnonymous()
bicycle_prim_path = Sdf.Path("/bicycle")
bicycle_prim_spec = Sdf.CreatePrimInLayer(layer, bicycle_prim_path)
bicycle_prim_spec.specifier = Sdf.SpecifierDef
payload_layer_offset = Sdf.LayerOffset(offset=10, scale=1)
payload = Sdf.Payload(payload_layer.identifier, payload_bicycle_prim_path, payload_layer_offset)
# Or: If we don't specify a prim, the default prim will get used, as set above
payload = Sdf.Payload(payload_layer.identifier, layerOffset=payload_layer_offset)
bicycle_prim_spec.payloadList.appendedItems = [payload]
#// ANCHOR_END: compositionArcPayload


#// ANCHOR: compositionArcSpecialize
### High Level ###
from pxr import Sdf, Usd
stage = Usd.Stage.CreateInMemory()
bicycle_prim_path = Sdf.Path("/bicycle")
bicycle_prim = stage.DefinePrim(bicycle_prim_path)
cube_prim_path = Sdf.Path("/cube")
cube_prim = stage.DefinePrim(cube_prim_path, "Cube")
specializes_api = bicycle_prim.GetSpecializes()
specializes_api.AddSpecialize(cube_prim_path, position=Usd.ListPositionFrontOfAppendList)
# inherits_api.SetSpecializes() # Clears the list editable ops and authors an Sdf.PathListOp.CreateExplicit([])
# inherits_api.RemoveSpecialize(cube_prim_path)
# inherits_api.ClearSpecializes() # Sdf.PathListOp.Clear()
### Low Level ###
from pxr import Sdf
layer = Sdf.Layer.CreateAnonymous()
bicycle_prim_path = Sdf.Path("/bicycle")
bicycle_prim_spec = Sdf.CreatePrimInLayer(layer, bicycle_prim_path)
bicycle_prim_spec.specifier = Sdf.SpecifierDef
cube_prim_path = Sdf.Path("/cube")
cube_prim_spec = Sdf.CreatePrimInLayer(layer, cube_prim_path)
cube_prim_spec.specifier = Sdf.SpecifierDef
cube_prim_spec.typeName = "Cube"
bicycle_prim_spec.specializesList.appendedItems = [cube_prim_path]
#// ANCHOR_END: compositionArcSpecialize


#// ANCHOR: compositionInstanceable
# Check if the active prim is marked as instanceable:
# The prim.IsInstance() checks if it is actually instanced, this
# just checks if the 'instanceable' metadata is set.
prim.IsInstanceable()
# Check if the active prim is an instanced prim:
prim.IsInstance()
# Check if we are inside an instanceable prim:
prim.IsInstanceProxy()
# Check if the active prim is a prototype root prim with the following format /__Prototype_<idx>
prim.IsPrototype()
# For these type of prototype root prims, we can get the instances via:
prim.GetInstances()
# From each instance we can get back to the prototype via
prim.GetPrototype()
# Check if we are in the /__Prototype_<idx> prim:
prim.IsInPrototype()

# When we are within an instance, we can get the prototype via:
if prim.IsInstanceProxy():
    for ancestor_prim_path in prim.GetAncestorsRange():
        ancestor_prim = stage.GetPrimAtPath(ancestor_prim_path)
        if ancestor_prim.IsInstance():
            prototype = ancestor_prim.GetPrototype()
            print(list(prototype.GetInstances()))
            break
#// ANCHOR_END: compositionInstanceable

#// ANCHOR: listEditableOpsLowLevelAPI
from pxr import Sdf
path_list_op = Sdf.PathListOp()
# There are multiple sub-lists, which are just normal Python lists.
# 'prependedItems', 'appendedItems', 'deletedItems', 'explicitItems',
# Legacy sub-lists (do not use these anymore): 'addedItems', 'orderedItems'
# Currently the way these are exposed to Python, you have to re-assign the list, instead of editing it in place.
# So this won't work:
path_list_op.prependedItems.append(Sdf.Path("/cube"))
path_list_op.appendedItems.append(Sdf.Path("/sphere"))
# Instead do this:
path_list_op.prependedItems = [Sdf.Path("/cube")]
path_list_op.appendedItems = [Sdf.Path("/sphere")]
# To clear the list op:
print(path_list_op) # Returns: SdfPathListOp(Prepended Items: [/cube], Appended Items: [/sphere])
path_list_op.Clear()
print(path_list_op) # Returns: SdfPathListOp()
# Repopulate via constructor
path_list_op = Sdf.PathListOp.Create(prependedItems = [Sdf.Path("/cube")], appendedItems = [Sdf.Path("/sphere")])
print(path_list_op) # Returns: SdfPathListOp(Prepended Items: [/cube], Appended Items: [/sphere])
# Add remove items
path_list_op.deletedItems = [Sdf.Path("/sphere")]
print(path_list_op) # Returns: SdfPathListOp(Deleted Items: [/sphere], Prepended Items: [/cube], Appended Items: [/sphere])
# Notice how it just stores lists, it doesn't actually apply them. We'll have a look at that next.
#// ANCHOR_END: listEditableOpsLowLevelAPI

#// ANCHOR: listEditableOpsHighLevelAPI
# For example when editing a relationship:
from pxr import Sdf, Usd
stage = Usd.Stage.CreateInMemory()
yard_prim = stage.DefinePrim("/yard")
car_prim = stage.DefinePrim("/car")
rel = car_prim.CreateRelationship("locationsOfInterest")
rel.AddTarget(yard_prim.GetPath(), position=Usd.ListPositionFrontOfAppendList)
# Result:
"""
def "car"
{
    custom rel locationsOfInterest
    append rel locationsOfInterest = </yard>
}
"""
# The "Set<Function>" signatures write an explicit list:
rel.SetTargets([yard_prim.GetPath()])
# Result:
"""
def "car"
{
    custom rel locationsOfInterest = </yard>
}
"""
#// ANCHOR_END: listEditableOpsHighLevelAPI

#// ANCHOR: listEditableOpsMerging
from pxr import Sdf
### Merging basics ###
path_list_op_layer_top = Sdf.PathListOp.Create(deletedItems = [Sdf.Path("/cube")])
path_list_op_layer_middle = Sdf.PathListOp.Create(prependedItems = [Sdf.Path("/disc"), Sdf.Path("/cone")])
path_list_op_layer_bottom = Sdf.PathListOp.Create(prependedItems = [Sdf.Path("/cube")], appendedItems = [Sdf.Path("/cone"),Sdf.Path("/sphere")])

result = Sdf.PathListOp()
result = result.ApplyOperations(path_list_op_layer_top)
result = result.ApplyOperations(path_list_op_layer_middle)
result = result.ApplyOperations(path_list_op_layer_bottom)
# Notice how on merge it makes sure that each sublist does not have the values of the other sublists, just like a Python set()
print(result) # Returns: SdfPathListOp(Deleted Items: [/cube], Prepended Items: [/disc, /cone], Appended Items: [/sphere])
# Get the flattened result. This does not apply the deleteItems, only ApplyOperations does that. 
print(result.GetAddedOrExplicitItems()) # Returns: [Sdf.Path('/disc'), Sdf.Path('/cone'), Sdf.Path('/sphere')]

### Deleted and added items ###
path_list_op_layer_top = Sdf.PathListOp.Create(appendedItems=[Sdf.Path("/disc"), Sdf.Path("/cube")])
path_list_op_layer_middle = Sdf.PathListOp.Create(deletedItems = [Sdf.Path("/cube")])
path_list_op_layer_bottom = Sdf.PathListOp.Create(prependedItems = [Sdf.Path("/cube")], appendedItems = [Sdf.Path("/sphere")])

result = Sdf.PathListOp()
result = result.ApplyOperations(path_list_op_layer_top)
result = result.ApplyOperations(path_list_op_layer_middle)
result = result.ApplyOperations(path_list_op_layer_bottom)
print(result) # Returns: SdfPathListOp(Appended Items: [/sphere, /disc, /cube])
# Since it now was in the explicit list, it got removed.

### Explicit mode ###
# There is also an "explicit" mode. This clears all previous values on merge and marks the list as explicit.
# Once explicit and can't be un-explicited. An explicit list is like a reset, it 
# doesn't know anything about the previous values anymore. All lists that are merged
# after combine the result to be explicit.
path_list_op_layer_top = Sdf.PathListOp.Create(deletedItems = [Sdf.Path("/cube")])
path_list_op_layer_middle = Sdf.PathListOp.CreateExplicit([Sdf.Path("/disc")])
path_list_op_layer_bottom = Sdf.PathListOp.Create(prependedItems = [Sdf.Path("/cube")], appendedItems = [Sdf.Path("/sphere")])

result = Sdf.PathListOp()
result = result.ApplyOperations(path_list_op_layer_top)
result = result.ApplyOperations(path_list_op_layer_middle)
result = result.ApplyOperations(path_list_op_layer_bottom)
print(result, result.isExplicit) # Returns: SdfPathListOp(Explicit Items: [/disc]), True
# Notice how the deletedItems had no effect, as "/cube" is not in the explicit list.

path_list_op_layer_top = Sdf.PathListOp.Create(deletedItems = [Sdf.Path("/cube")])
path_list_op_layer_middle = Sdf.PathListOp.CreateExplicit([Sdf.Path("/disc"), Sdf.Path("/cube")])
path_list_op_layer_bottom = Sdf.PathListOp.Create(prependedItems = [Sdf.Path("/cube")], appendedItems = [Sdf.Path("/sphere")])

result = Sdf.PathListOp()
result = result.ApplyOperations(path_list_op_layer_top)
result = result.ApplyOperations(path_list_op_layer_middle)
result = result.ApplyOperations(path_list_op_layer_bottom)
print(result, result.isExplicit) # Returns: SdfPathListOp(Explicit Items: [/disc]), True
# Since it now was in the explicit list, it got removed.
#// ANCHOR_END: listEditableOpsMerging

#// ANCHOR: pcpPrimPropertyStack
from pxr import Sdf, Usd
# Create stage with two different layers
stage = Usd.Stage.CreateInMemory()
root_layer = stage.GetRootLayer()
layer_top = Sdf.Layer.CreateAnonymous("exampleTopLayer")
layer_bottom = Sdf.Layer.CreateAnonymous("exampleBottomLayer")
root_layer.subLayerPaths.append(layer_top.identifier)
root_layer.subLayerPaths.append(layer_bottom.identifier)
# Define specs in two different layers
prim_path = Sdf.Path("/cube")
stage.SetEditTarget(layer_top)
prim = stage.DefinePrim(prim_path, "Xform")
prim.SetTypeName("Cube")
stage.SetEditTarget(layer_bottom)
prim = stage.DefinePrim(prim_path, "Xform")
prim.SetTypeName("Cube")
attr = prim.CreateAttribute("debug", Sdf.ValueTypeNames.Float)
attr.Set(5, 10)
# Print the stack (set of layers that contribute data to this prim)
# For prims this returns all the Sdf.PrimSpec objects that contribute to the prim.
print(prim.GetPrimStack()) # Returns: [Sdf.Find('anon:0x7f6e590dc300:exampleTopLayer', '/cube'), 
                           #           Sdf.Find('anon:0x7f6e590dc580:exampleBottomLayer', '/cube')]
# For attributes this returns all the Sdf.AttributeSpec objects that contribute to the attribute.
# If we pass a non default time code value clips will be included in the result.
# This type of function signature is very unique and can't be found anywhere else in USD.
time_code = Usd.TimeCode.Default()
print(attr.GetPropertyStack(1001)) # Returns: [Sdf.Find('anon:0x7f9eade0ae00:exampleBottomLayer', '/cube.debug')]
print(attr.GetPropertyStack(time_code)) # Returns: [Sdf.Find('anon:0x7f9eade0ae00:exampleBottomLayer', '/cube.debug')]
#// ANCHOR_END: pcpPrimPropertyStack


#// ANCHOR: pcpPrimIndex
import os
from subprocess import call
from pxr import Sdf, Usd
stage = Usd.Stage.CreateInMemory()
# Spawn temp layer
reference_layer = Sdf.Layer.CreateAnonymous("ReferenceExample")
reference_bicycle_prim_path = Sdf.Path("/bicycle")
reference_bicycle_prim_spec = Sdf.CreatePrimInLayer(reference_layer, reference_bicycle_prim_path)
reference_bicycle_prim_spec.specifier = Sdf.SpecifierDef
reference_bicycle_prim_spec.typeName = "Cube"
reference_layer_offset = Sdf.LayerOffset(offset=10, scale=1)
reference = Sdf.Reference(reference_layer.identifier, reference_bicycle_prim_path, reference_layer_offset)
bicycle_prim_path = Sdf.Path("/red_bicycle")
bicycle_prim = stage.DefinePrim(bicycle_prim_path)
references_api = bicycle_prim.GetReferences()
references_api.AddReference(reference, position=Usd.ListPositionFrontOfAppendList)
# You'll always want to use the expanded method,
# otherwise you might miss some data sources!
# This is also what the UIs use.
prim = bicycle_prim
print(prim.GetPrimIndex()) 
print(prim.ComputeExpandedPrimIndex())
# Dump the index representation to the dot format and render it to a .svg/.png image.
prim_index = prim.ComputeExpandedPrimIndex()
print(prim_index.DumpToString())
graph_file_path = os.path.expanduser("~/Desktop/usdSurvivalGuide_prim_index.txt")
graph_viz_png_file_path = graph_file_path.replace(".txt", ".png")
graph_viz_svg_file_path = graph_file_path.replace(".txt", ".svg")
prim_index.DumpToDotGraph(graph_file_path, includeMaps=False)
call(["dot", "-Tpng", graph_file_path, "-o", graph_viz_png_file_path])
call(["dot", "-Tsvg", graph_file_path, "-o", graph_viz_svg_file_path])

def iterator_child_nodes(root_node):
    yield root_node
    for child_node in root_node.children:
        for child_child_node in iterator_child_nodes(child_node):
            yield child_child_node

def iterator_parent_nodes(root_node):
    iter_node = root_node
    while iter_node:
        yield iter_node
        iter_node = iter_node.parent
            
print("Pcp Node Refs", dir(prim_index.rootNode))
for child in list(iterator_child_nodes(prim_index.rootNode))[::1]:
    print(child, child.arcType, child.path, child.mapToRoot.MapSourceToTarget(child.path))
""" The arc type will one one of:
Pcp.ArcTypeRoot
Pcp.ArcTypeInherit
Pcp.ArcTypeVariant
Pcp.ArcTypeReference
Pcp.ArcTypeRelocate
Pcp.ArcTypePayload
Pcp.ArcTypeSpecialize
"""
#// ANCHOR_END: pcpPrimIndex


#// ANCHOR: pcpPrimCompositionQuery
from pxr import Sdf, Usd
stage = Usd.Stage.CreateInMemory()
prim = stage.DefinePrim("/pig")
refs_API = prim.GetReferences()
refs_API.AddReference("/opt/hfs19.5/houdini/usd/assets/pig/pig.usd")
print("----")
def _repr(arc):
    print(arc.GetArcType(), 
          "| Introducing Prim Path", arc.GetIntroducingPrimPath() or "-",
          "| Introducing Layer", arc.GetIntroducingLayer() or "-",
          "| Is ancestral", arc.IsAncestral(),
          "| In Root Layer Stack", arc.IsIntroducedInRootLayerStack())
print(">-> Direct Root Layer Arcs")
query = Usd.PrimCompositionQuery.GetDirectRootLayerArcs(prim)
for arc in query.GetCompositionArcs():
    _repr(arc)
print(">-> Direct Inherits")
query = Usd.PrimCompositionQuery.GetDirectInherits(prim)
for arc in query.GetCompositionArcs():
    _repr(arc)
print(">-> Direct References")
query = Usd.PrimCompositionQuery.GetDirectReferences(prim)
for arc in query.GetCompositionArcs():
    _repr(arc)
"""Returns:
>-> Direct Root Layer Arcs
Pcp.ArcTypeRoot | Introducing Prim Path - | Introducing Layer - | Is ancestral False | In Root Layer Stack True
Pcp.ArcTypeReference | Introducing Prim Path /pig | Introducing Layer Sdf.Find('anon:0x7f9b60d56b00:tmp.usda') | Is ancestral False | In Root Layer Stack True
>-> Direct Inherits
Pcp.ArcTypeInherit | Introducing Prim Path /pig | Introducing Layer Sdf.Find('/opt/hfs19.5/houdini/usd/assets/pig/pig.usd') | Is ancestral False | In Root Layer Stack False
Pcp.ArcTypeInherit | Introducing Prim Path /pig | Introducing Layer Sdf.Find('/opt/hfs19.5/houdini/usd/assets/pig/pig.usd') | Is ancestral False | In Root Layer Stack False
>-> Direct References
Pcp.ArcTypeReference | Introducing Prim Path /pig | Introducing Layer Sdf.Find('anon:0x7f9b60d56b00:tmp.usda') | Is ancestral False | In Root Layer Stack True
Pcp.ArcTypeReference | Introducing Prim Path /pig | Introducing Layer Sdf.Find('/opt/hfs19.5/houdini/usd/assets/pig/payload.usdc') | Is ancestral False | In Root Layer Stack False
Pcp.ArcTypeReference | Introducing Prim Path /pig{geo=medium} | Introducing Layer Sdf.Find('/opt/hfs19.5/houdini/usd/assets/pig/mtl.usdc') | Is ancestral False | In Root Layer Stack False
Pcp.ArcTypeReference | Introducing Prim Path /ASSET_geo_variant_1/ASSET | Introducing Layer Sdf.Find('/opt/hfs19.5/houdini/usd/assets/pig/mtl.usdc') | Is ancestral False | In Root Layer Stack False
Pcp.ArcTypeReference | Introducing Prim Path /pig | Introducing Layer Sdf.Find('/opt/hfs19.5/houdini/usd/assets/pig/payload.usdc') | Is ancestral False | In Root Layer Stack False
Pcp.ArcTypeReference | Introducing Prim Path /pig | Introducing Layer Sdf.Find('/opt/hfs19.5/houdini/usd/assets/pig/geo.usdc') | Is ancestral False | In Root Layer Stack False
Pcp.ArcTypeReference | Introducing Prim Path /pig | Introducing Layer Sdf.Find('/opt/hfs19.5/houdini/usd/assets/pig/geo.usdc') | Is ancestral False | In Root Layer Stack False
Pcp.ArcTypeReference | Introducing Prim Path /pig | Introducing Layer Sdf.Find('/opt/hfs19.5/houdini/usd/assets/pig/geo.usdc') | Is ancestral False | In Root Layer Stack False
"""
# Custom filter
# For example let's get all direct payloads, that were not introduced in the active root layer stack.
query_filter = Usd.PrimCompositionQuery.Filter()
query_filter.arcTypeFilter = Usd.PrimCompositionQuery.ArcTypeFilter.Payload
query_filter.dependencyTypeFilter = Usd.PrimCompositionQuery.DependencyTypeFilter.Direct
query_filter.arcIntroducedFilter = Usd.PrimCompositionQuery.ArcIntroducedFilter.All
query_filter.hasSpecsFilter = Usd.PrimCompositionQuery.HasSpecsFilter.HasSpecs
print(">-> Custom Query (Direct payloads not in root layer that have specs)")
query = Usd.PrimCompositionQuery(prim)
query.filter = query_filter
for arc in query.GetCompositionArcs():
    _repr(arc)
"""Returns:
>-> Custom Query (Direct payloads not in root layer that have specs)
Pcp.ArcTypePayload | Introducing Prim Path /pig | Introducing Layer Sdf.Find('/opt/hfs19.5/houdini/usd/assets/pig/pig.usd') | Is ancestral False | In Root Layer Stack False
"""
#// ANCHOR_END: pcpPrimCompositionQuery




================================================
FILE: code/core/elements.py
================================================
"""This file contains all code examples for the 'Core Elements' section.
The following mdBook syntax allows us to sparsely import content:
#// ANCHOR: contentId
def example():
    print("here")
#// ANCHOR_END: contentId
"""

"""api.md"""

#// ANCHOR: apiHighVsLowLevel
### High Level ### (Notice how we still use elements of the low level API)
from pxr import Sdf, Usd
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Xform")
attr = prim.CreateAttribute("tire:size", Sdf.ValueTypeNames.Float)
attr.Set(10)

### Low Level ###
from pxr import Sdf
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/bicycle")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.specifier = Sdf.SpecifierDef
prim_spec.typeName = "Xform"
attr_spec = Sdf.AttributeSpec(prim_spec, "tire:size", Sdf.ValueTypeNames.Float)
attr_spec.default = 10
#// ANCHOR_END: apiHighVsLowLevel

"""path.md"""

#// ANCHOR: pathSummary
from pxr import Sdf
# Prims
prim_path = Sdf.Path("/set/bicycle")
prim_path_str = Sdf.Path("/set/bicycle").pathString # Returns the Python str "/set/bicycle"
# Properties (Attribute/Relationship)
property_path = Sdf.Path("/set/bicycle.size")
property_with_namespace_path = Sdf.Path("/set/bicycle.tire:size")
# Relationship targets
prim_rel_target_path = Sdf.Path("/set.bikes[/set/bicycles]")           # Prim to prim linking (E.g. path collections)
# Variants
variant_path = prim_path.AppendVariantSelection("style", "blue") # Returns: Sdf.Path('/set/bicycle{style=blue}')
variant_path = Sdf.Path('/set/bicycle{style=blue}frame/screws')
#// ANCHOR_END: pathSummary

#// ANCHOR: pathBasics
from pxr import Sdf
path = Sdf.Path("/set/bicycle")
path_name = path.name     # Similar to os.path.basename(), returns the last element of the path
path_empty = path.isEmpty # Property to check if path is empty
# Path validation (E.g. for user created paths)
Sdf.Path.IsValidPathString("/some/_wrong!_/path") # Returns: (False, 'Error Message')
# Join paths (Similar to os.path.join())
path = Sdf.Path("/set/bicycle")
path.AppendPath(Sdf.Path("frame/screws")) # Returns: Sdf.Path("/set/bicycle/frame/screws")
# Manually join individual path elements
path = Sdf.Path(Sdf.Path.childDelimiter.join(["set", "bicycle"])) 
# Get the parent path
parent_path = path.GetParentPath() # Returns Sdf.Path("/set")
parent_path.IsRootPrimPath()       # Returns: True (Root prims are prims that only
                                   #                have a single '/')        
ancestor_range = path.GetAncestorsRange() # Returns an iterator for the parent paths, the same as recursively calling GetParentPath()
# Add child path
child_path = path.AppendChild("wheel") # Returns: Sdf.Path("/set/bicycle/wheel")
# Check if path is a prim path (and not a attribute/relationship path)
path.IsPrimPath() # Returns: True
# Check if path starts with another path
# Important: It actually compares individual path elements (So it is not a str.startswith())
Sdf.Path("/set/cityA/bicycle").HasPrefix(Sdf.Path("/set"))      # Returns: True
Sdf.Path("/set/cityA/bicycle").HasPrefix(Sdf.Path("/set/city")) # Returns: False
Sdf.Path("/set/bicycle").GetCommonPrefix(Sdf.Path("/set"))      # Returns: Sdf.Path("/set")
# Relative/Absolute paths
path = Sdf.Path("/set/cityA/bicycle")
rel_path = path.MakeRelativePath("/set")     # Returns: Sdf.Path('cityA/bicycle')
abs_path = rel_path.MakeAbsolutePath("/set") # Returns: Sdf.Path('/set/cityA/bicycle')
abs_path.IsAbsolutePath()                    # Returns: True -> Checks path[0] == "/"
# Do not use this is performance critical loops
# See for more info: https://openusd.org/release/api/_usd__page__best_practices.html
# This gives you a standard python string
path_str = path.pathString
#// ANCHOR_END: pathBasics

#// ANCHOR: pathSpecialPaths
from pxr import Sdf
# Shortcut for Sdf.Path("/")
root_path = Sdf.Path.absoluteRootPath
root_path == Sdf.Path("/") # Returns: True
# We'll cover in a later section how to rename/remove things in Usd,
# so don't worry about the details how this works yet. Just remember that
# an emptyPath exists and that its usage is to remove something.
src_path = Sdf.Path("/set/bicycle")
dst_path = Sdf.Path.emptyPath
edit = Sdf.BatchNamespaceEdit()
edit.Add(src_path, dst_path)
#// ANCHOR_END: pathSpecialPaths

#// ANCHOR: pathProperties
# Properties (see the next section) are also encoded
# in the path via the "." (Sdf.Path.propertyDelimiter) token
from pxr import Sdf
path = Sdf.Path("/set/bicycle.size")
property_name = path.name # Be aware, this will return 'size' (last element)
# Append property to prim path
Sdf.Path("/set/bicycle").AppendProperty("size") # Returns: Sdf.Path("/set/bicycle.size")
# Properties can also be namespaced with ":" (Sdf.Path.namespaceDelimiter)
path = Sdf.Path("/set/bicycle.tire:size") 
property_name = path.name                 # Returns: 'tire:size'
property_name = path.ReplaceName("color") # Returns: Sdf.Path("/set/bicycle.color")
# Check if path is a property path (and not a prim path)
path.IsPropertyPath() # Returns: True
# Check if path is a property path (and not a prim path)
Sdf.Path("/set/bicycle.tire:size").IsPrimPropertyPath()  # Returns: True
Sdf.Path("/set/bicycle").IsPrimPropertyPath()            # Returns: False
# Convenience methods
path = Sdf.Path("/set/bicycle").AppendProperty(Sdf.Path.JoinIdentifier(["tire", "size"]))
namespaced_elements = Sdf.Path.TokenizeIdentifier("tire:size")   # Returns: ["tire", "size"]
last_element = Sdf.Path.StripNamespace("/set/bicycle.tire:size") # Returns: 'size'
# With GetPrimPath we can strip away all property encodings
path = Sdf.Path("/set/bicycle.tire:size")
prim_path = path.GetPrimPath() # Returns: Sdf.Path('/set/bicycle')

# We can't actually differentiate between a attribute and relationship based on the property path.
# Hence the "Property" terminology.
# In practice we rarely use/see this as this is a pretty low level API use case.
# The only 'common' case, where you will see this is when calling the Sdf.Layer.Traverse function.
# To encode prim relation targets, we can use:
prim_rel_target_path = Sdf.Path("/set.bikes[/set/bicycle]")
prim_rel_target_path.IsTargetPath() # Returns: True
prim_rel_target_path = Sdf.Path("/set.bikes").AppendTarget("/set/bicycle")
# We can also encode check if a path is a relational attribute.
# ToDo: I've not seen this encoding being used anywhere so far.
# "Normal" attr_spec.connectionsPathList connections as used in shaders
# are encoded via Sdf.Path("/set.bikes[/set/bicycle.someOtherAttr]")
attribute_rel_target_path = Sdf.Path("/set.bikes[/set/bicycles].size")
attribute_rel_target_path.IsRelationalAttributePath()  # Returns: True
#// ANCHOR_END: pathProperties

#// ANCHOR: pathVariants
# Variants (see the next sections) are also encoded
# in the path via the "{variantSetName=variantName}" syntax.
from pxr import Sdf
path = Sdf.Path("/set/bicycle")
variant_path = path.AppendVariantSelection("style", "blue") # Returns: Sdf.Path('/set/bicycle{style=blue}')
variant_path = Sdf.Path('/set/bicycle{style=blue}frame/screws')
# Property path to prim path with variants
property_path = Sdf.Path('/set/bicycle{style=blue}frame/screws.size')
variant_path = property_path.GetPrimOrPrimVariantSelectionPath() # Returns: Sdf.Path('/set/bicycle{style=blue}frame/screws')
# Typical iteration example:
variant_path = Sdf.Path('/set/bicycle{style=blue}frame/screws')
if variant_path.ContainsPrimVariantSelection():          # Returns: True # For any variant selection in the whole path
    for parent_path in variant_path.GetAncestorsRange():
        if parent_path.IsPrimVariantSelectionPath():
            print(parent_path.GetVariantSelection())     # Returns: ('style', 'blue')

# When authoring relationships, we usually want to remove all variant encodings in the path:
variant_path = Sdf.Path('/set/bicycle{style=blue}frame/screws')
prim_rel_target_path = variant_path.StripAllVariantSelections() # Returns: Sdf.Path('/set/bicycle/frame/screws')
#// ANCHOR_END: pathVariants

## Data Containers ##

#// ANCHOR: dataContainerPrimOverview
### High Level ###
from pxr import Sdf, Usd
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Xform")
attr = prim.CreateAttribute("tire:size", Sdf.ValueTypeNames.Float)
attr.Set(10)

### Low Level ###
from pxr import Sdf
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/bicycle")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.specifier = Sdf.SpecifierDef
prim_spec.typeName = "Xform"
attr_spec = Sdf.AttributeSpec(prim_spec, "tire:size", Sdf.ValueTypeNames.Float)
attr_spec.default = 10
#// ANCHOR_END: dataContainerPrimOverview


#// ANCHOR: dataContainerPrimCoreHighLevel
from pxr import Kind, Sdf, Usd
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/cube")
prim = stage.DefinePrim(prim_path, "Xform") # Here defining the prim uses a `Sdf.SpecifierDef` define op by default.
# The specifier and type name is something you'll usually always set.
prim.SetSpecifier(Sdf.SpecifierOver)
prim.SetTypeName("Cube")
# The other core specs are set via schema APIs, for example:
model_API = Usd.ModelAPI(prim)
if not model_API.GetKind():
    model_API.SetKind(Kind.Tokens.group)
#// ANCHOR_END: dataContainerPrimCoreHighLevel


#// ANCHOR: dataContainerPrimCoreLowLevel
from pxr import Sdf
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/cube")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path) # Here defining the prim uses a `Sdf.SpecifierOver` define op by default.
# The specifier and type name is something you'll usually always set.
prim_spec.specifier = Sdf.SpecifierDef # Or Sdf.SpecifierOver/Sdf.SpecifierClass
prim_spec.typeName = "Cube"
prim_spec.active = True # There is also a prim_spec.ClearActive() shortcut for removing active metadata
prim_spec.kind = "group"    # There is also a prim_spec.ClearKind() shortcut for removing kind metadata
prim_spec.instanceable = False # There is also a prim_spec.ClearInstanceable() shortcut for removing instanceable metadata.
prim_spec.hidden = False # A hint for UI apps to hide the spec for viewers

# You can also set them via the standard metadata commands:
from pxr import Sdf
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/cube")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
# The specifier and type name is something you'll usually always set.
prim_spec.SetInfo(prim_spec.SpecifierKey, Sdf.SpecifierDef) # Or Sdf.SpecifierOver/Sdf.SpecifierClass
prim_spec.SetInfo(prim_spec.TypeNameKey, "Cube")
# These are some other common specs:
prim_spec.SetInfo(prim_spec.ActiveKey, True)
prim_spec.SetInfo(prim_spec.KindKey, "group")
prim_spec.SetInfo("instanceable", False) 
prim_spec.SetInfo(prim_spec.HiddenKey, False)
#// ANCHOR_END: dataContainerPrimCoreLowLevel


#// ANCHOR: dataContainerPrimBasicsSpecifierTraversal
### High Level ###
from pxr import Sdf, Usd
stage = Usd.Stage.CreateInMemory()
# Replicate the Usd file example above:
stage.DefinePrim("/definedCube", "Cube").SetSpecifier(Sdf.SpecifierDef)
stage.DefinePrim("/overCube", "Cube").SetSpecifier(Sdf.SpecifierOver)
stage.DefinePrim("/classCube", "Cube").SetSpecifier(Sdf.SpecifierClass)
## Traverse with default filter (USD calls filter 'predicate')
# UsdPrimIsActive & UsdPrimIsDefined & UsdPrimIsLoaded & ~UsdPrimIsAbstract
for prim in stage.Traverse():
    print(prim)
# Returns:
# Usd.Prim(</definedCube>)
## Traverse with 'all' filter (USD calls filter 'predicate')
for prim in stage.TraverseAll():
    print(prim)
# Returns:
# Usd.Prim(</definedCube>)
# Usd.Prim(</overCube>)
# Usd.Prim(</classCube>)
## Traverse with IsAbstract (== IsClass) filter (USD calls filter 'predicate')
predicate = Usd.PrimIsAbstract
for prim in stage.Traverse(predicate):
    print(prim)
# Returns:
# Usd.Prim(</classCube>)
## Traverse with ~PrimIsDefined filter (==IsNotDefined) (USD calls filter 'predicate')
predicate = ~Usd.PrimIsDefined
for prim in stage.Traverse(predicate):
    print(prim)
# Returns:
# Usd.Prim(</overCube>)
#// ANCHOR_END: dataContainerPrimBasicsSpecifierTraversal


#// ANCHOR: dataContainerPrimBasicsSpecifierDef
### High Level ###
from pxr import Sdf, Usd
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
# The .DefinePrim method uses a Sdf.SpecifierDef specifier by default
prim = stage.DefinePrim(prim_path, "Xform")
prim.SetSpecifier(Sdf.SpecifierDef)

### Low Level ###
from pxr import Sdf
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/bicycle")
# The .CreatePrimInLayer method uses a Sdf.SpecifierOver specifier by default
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.specifier = Sdf.SpecifierDef
#// ANCHOR_END: dataContainerPrimBasicsSpecifierDef

#// ANCHOR: dataContainerPrimBasicsSpecifierOver
### High Level ###
from pxr import Sdf, Usd
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
# The .DefinePrim method uses a Sdf.SpecifierDef specifier by default
prim = stage.DefinePrim(prim_path, "Xform")
prim.SetSpecifier(Sdf.SpecifierOver)
# or 
prim = stage.OverridePrim(prim_path)
# The prim class' IsDefined method checks if a prim (and all its parents) have the "def" specifier.
print(prim.GetSpecifier() == Sdf.SpecifierOver, not prim.IsDefined() and not prim.IsAbstract())

### Low Level ###
from pxr import Sdf
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/bicycle")
# The .CreatePrimInLayer method uses a Sdf.SpecifierOver specifier by default
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.specifier = Sdf.SpecifierOver
#// ANCHOR_END: dataContainerPrimBasicsSpecifierOver

#// ANCHOR: dataContainerPrimBasicsSpecifierClass
### High Level ###
from pxr import Sdf, Usd
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
# The .DefinePrim method uses a Sdf.SpecifierDef specifier by default
prim = stage.DefinePrim(prim_path, "Xform")
prim.SetSpecifier(Sdf.SpecifierClass)
# or 
prim = stage.CreateClassPrim(prim_path)
# The prim class' IsAbstract method checks if a prim (and all its parents) have the "Class" specifier.
print(prim.GetSpecifier() == Sdf.SpecifierClass, prim.IsAbstract())

### Low Level ###
from pxr import Sdf
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/bicycle")
# The .CreatePrimInLayer method uses a Sdf.SpecifierOver specifier by default
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.specifier = Sdf.SpecifierClass
#// ANCHOR_END: dataContainerPrimBasicsSpecifierClass

#// ANCHOR: dataContainerPrimBasicsTypeName
### High Level ###
from pxr import Sdf, Usd
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Xform")
prim.SetTypeName("Xform")

### Low Level ###
from pxr import Sdf
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/bicycle")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.typeName = "Xform"

# Default type without any fancy bells and whistles:
prim.SetTypeName("Scope")
prim_spec.typeName = "Scope"
#// ANCHOR_END: dataContainerPrimBasicsTypeName


#// ANCHOR: dataContainerPrimBasicsKinds
### High Level ###
from pxr import Kind, Sdf, Usd
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Xform")
model_API = Usd.ModelAPI(prim)
model_API.SetKind(Kind.Tokens.component)
# The prim class' IsModel/IsGroup method checks if a prim (and all its parents) are (sub-) kinds of model/group.
model_API.SetKind(Kind.Tokens.model)
kind = model_API.GetKind()
print(kind, (Kind.Registry.GetBaseKind(kind) or kind) == Kind.Tokens.model, prim.IsModel())
model_API.SetKind(Kind.Tokens.group)
kind = model_API.GetKind()
print(kind, (Kind.Registry.GetBaseKind(kind) or kind) == Kind.Tokens.group, prim.IsGroup())

### Low Level ###
from pxr import Kind, Sdf
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/bicycle")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.SetInfo("kind", Kind.Tokens.component)
#// ANCHOR_END: dataContainerPrimBasicsKinds

#// ANCHOR: dataContainerPrimBasicsTokens
from pxr import Sdf
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/cube")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.SetInfo(prim_spec.KindKey, "group")
#// ANCHOR_END: dataContainerPrimBasicsTokens


#// ANCHOR: dataContainerPrimBasicsDebugging
from pxr import Sdf
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/cube")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.specifier = Sdf.SpecifierDef
prim_spec.SetInfo(prim_spec.KindKey, "group")
attr_spec = Sdf.AttributeSpec(prim_spec, "size", Sdf.ValueTypeNames.Float)
# Running this
print(prim_spec.GetAsText())
# Returns:
"""
def "cube" (
    kind = "group"
)
{
    float size
}
"""
#// ANCHOR_END: dataContainerPrimBasicsDebugging


#// ANCHOR: dataContainerPrimHierarchy
### High Level ###
# Has: 'IsPseudoRoot' 
# Get: 'GetParent', 'GetPath', 'GetName', 'GetStage',
#      'GetChild', 'GetChildren', 'GetAllChildren',   
#      'GetChildrenNames', 'GetAllChildrenNames',
#      'GetFilteredChildren', 'GetFilteredChildrenNames', 
# The GetAll<MethodNames> return children that have specifiers other than Sdf.SpecifierDef
from pxr import Sdf, Usd
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/set/bicycle")
prim = stage.DefinePrim(prim_path, "Xform")
parent_prim = prim.GetParent()
print(prim.GetPath()) # Returns: Sdf.Path("/set/bicycle")
print(prim.GetParent()) # Returns: Usd.Prim("/set")
print(parent_prim.GetChildren()) # Returns: [Usd.Prim(</set/bicycle>)]
print(parent_prim.GetChildrenNames()) # Returns: ['bicycle']

### Low Level ###
from pxr import Sdf
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/set/bicycle")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
print(prim_spec.path) # Returns: Sdf.Path("/set/bicycle")
print(prim_spec.name) # Returns: "bicycle"
# To rename a prim, you can simply set the name attribute to something else.
# If you want to batch-rename, you should use the Sdf.BatchNamespaceEdit class, see our explanation [here]()
prim_spec.name = "coolBicycle"
print(prim_spec.nameParent) # Returns: Sdf.PrimSpec("/set")
print(prim_spec.nameParent.nameChildren) # Returns: {'coolBicycle': Sdf.Find('anon:0x7f6e5a0e3c00:LOP:/stage/pythonscript3', '/set/coolBicycle')}
print(prim_spec.layer) # Returns: The active layer object the spec is on.
#// ANCHOR_END: dataContainerPrimHierarchy


#// ANCHOR: dataContainerPrimSchemas
### High Level ###
# Has: 'IsA', 'HasAPI', 'CanApplyAPI'
# Get: 'GetTypeName', 'GetAppliedSchemas'
# Set: 'SetTypeName', 'AddAppliedSchema', 'ApplyAPI'
# Clear: 'ClearTypeName', 'RemoveAppliedSchema', 'RemoveAPI'
from pxr import Sdf, Usd
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Xform")
# Typed Schemas
prim.SetTypeName("Xform")
# Applied schemas
prim.AddAppliedSchema("SkelBindingAPI")
# AddAppliedSchema does not check if the schema actually exists, 
# you have to use this for codeless schemas.
# prim.RemoveAppliedSchema("SkelBindingAPI")
# Single-Apply API Schemas
prim.ApplyAPI("GeomModelAPI") # Older USD versions: prim.ApplyAPI("UsdGeomModelAPI")

### Low Level ###
# To set applied API schemas via the low level API, we just 
# need to set the `apiSchemas` key to a Token Listeditable Op.
from pxr import Sdf
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/bicycle")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
# Typed Schemas
prim_spec.typeName = "Xform"
# Applied Schemas
schemas = Sdf.TokenListOp.Create(
    prependedItems=["SkelBindingAPI", "GeomModelAPI"]
)
prim_spec.SetInfo("apiSchemas", schemas)
#// ANCHOR_END: dataContainerPrimSchemas

#// ANCHOR: dataContainerPrimTypeDefinition
from pxr import Sdf, Tf, Usd, UsdGeom
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Xform")
prim.ApplyAPI("GeomModelAPI") # Older USD versions: prim.ApplyAPI("UsdGeomModelAPI")
prim_def = prim.GetPrimDefinition()
print(prim_def.GetAppliedAPISchemas()) # Returns: ['GeomModelAPI']
print(prim_def.GetPropertyNames()) 
# Returns: All properties that come from the type name schema and applied schemas
"""
['model:drawModeColor', 'model:cardTextureZPos', 'model:drawMode', 'model:cardTextureZNeg', 
'model:cardTextureYPos', 'model:cardTextureYNeg', 'model:cardTextureXPos', 'model:cardTextur
eXNeg', 'model:cardGeometry', 'model:applyDrawMode', 'proxyPrim', 'visibility', 'xformOpOrde
r', 'purpose']
"""
# You can also bake down the prim definition, this won't flatten custom properties though.
dst_prim = stage.DefinePrim("/flattenedExample")
dst_prim = prim_def.FlattenTo(dst_prim)
# This will also flatten all metadata (docs etc.), this should only be used, if you need to export
# a custom schema to an external vendor. (Not sure if this the "official" way to do it, I'm sure
# there are better ones.)
#// ANCHOR_END: dataContainerPrimTypeDefinition

#// ANCHOR: dataContainerPrimTypeInfo
from pxr import Sdf, Tf, Usd, UsdGeom
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Xform")
prim.ApplyAPI("GeomModelAPI")
print(prim.IsA(UsdGeom.Xform)) # Returns: True
print(prim.IsA(Tf.Type.FindByName('UsdGeomXform'))) # Returns: True
prim_type_info = prim.GetPrimTypeInfo()
print(prim_type_info.GetAppliedAPISchemas()) # Returns: ['GeomModelAPI']
print(prim_type_info.GetSchemaType()) # Returns: Tf.Type.FindByName('UsdGeomXform')
print(prim_type_info.GetSchemaTypeName()) # Returns: Xform
#// ANCHOR_END: dataContainerPrimTypeInfo

#// ANCHOR: dataContainerPrimLoading
### High Level ###
from pxr import Sdf, Tf, Usd, UsdGeom
# Has: 'HasAuthoredActive', 'HasAuthoredHidden'
# Get: 'IsActive', 'IsLoaded', 'IsHidden'
# Set: 'SetActive', 'SetHidden' 
# Clear: 'ClearActive', 'ClearHidden'
# Loading: 'Load', 'Unload'
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Xform")
## Activation: Controls subhierarchy loading of prim.
prim.SetActive(False) # 
# prim.ClearActive()
## Visibility: Controls the visiblity for render delegates (subhierarchy will still be loaded)
imageable_API = UsdGeom.Imageable(prim)
visibility_attr = imageable_API.CreateVisibilityAttr()
visibility_attr.Set(UsdGeom.Tokens.invisible)
## Purpose: Controls if the prim is visible for what the renderer requested.
imageable_API = UsdGeom.Imageable(prim)
purpose_attr = imageable_API.CreatePurposeAttr()
purpose_attr.Set(UsdGeom.Tokens.render)
## Payload loading: Control payload loading (High Level only as it redirects the request to the stage).
# In our example stage here, we have no payloads, so we don't see a difference.
prim.Load()
prim.Unload()
# Calling this on the prim is the same thing.
prim = stage.GetPrimAtPath(prim_path)
prim.GetStage().Load(prim_path)
prim.GetStage().Unload(prim_path)
## Hidden: # Hint to hide for UIs
prim.SetHidden(False)
# prim.ClearHidden()

### Low Level ###
from pxr import Sdf, UsdGeom
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/set/bicycle")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
## Activation: Controls subhierarchy loading of prim.
prim_spec.active = False
# prim_spec.ClearActive()
## Visibility: Controls the visiblity for render delegates (subhierarchy will still be loaded)
visibility_attr_spec = Sdf.AttributeSpec(prim_spec, UsdGeom.Tokens.visibility, Sdf.ValueTypeNames.Token)
visibility_attr_spec.default = UsdGeom.Tokens.invisible
## Purpose: Controls if the prim is visible for what the renderer requested.
purpose_attr_spec = Sdf.AttributeSpec(prim_spec, UsdGeom.Tokens.purpose, Sdf.ValueTypeNames.Token)
purpose_attr_spec.default = UsdGeom.Tokens.render
## Hidden: # Hint to hide for UIs
prim_spec.hidden = True 
# prim_spec.ClearHidden()
#// ANCHOR_END: dataContainerPrimLoading


#// ANCHOR: dataContainerPrimPropertiesHighLevel
from pxr import Usd, Sdf
# Has: 'HasProperty', 'HasAttribute', 'HasRelationship'
# Get: 'GetProperties', 'GetAuthoredProperties', 'GetPropertyNames', 'GetPropertiesInNamespace', 'GetAuthoredPropertiesInNamespace'
#      'GetAttribute', 'GetAttributes', 'GetAuthoredAttributes'
#      'GetRelationship', 'GetRelationships', 'GetAuthoredRelationships'
#      'FindAllAttributeConnectionPaths', 'FindAllRelationshipTargetPaths'
# Set: 'CreateAttribute', 'CreateRelationship'
# Clear: 'RemoveProperty', 
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Cube")
# As the cube schema ships with a "size" attribute, we don't have to create it first
# Usd is smart enough to check the schema for the type and creates it for us.
size_attr = prim.GetAttribute("size")
size_attr.Set(10)
## Looking up attributes
print(prim.GetAttributes())
# Returns: All the attributes that are provided by the schema
"""
[Usd.Prim(</bicycle>).GetAttribute('doubleSided'), Usd.Prim(</bicycle>).GetAttribute('extent'), Usd.
Prim(</bicycle>).GetAttribute('orientation'), Usd.Prim(</bicycle>).GetAttribute('primvars:displayCol
or'), Usd.Prim(</bicycle>).GetAttribute('primvars:displayOpacity'), Usd.Prim(</bicycle>).GetAttribut
e('purpose'), Usd.Prim(</bicycle>).GetAttribute('size'), Usd.Prim(</bicycle>).GetAttribute('visibili
ty'), Usd.Prim(</bicycle>).GetAttribute('xformOpOrder')]
"""
print(prim.GetAuthoredAttributes())
# Returns: Only the attributes we have written to in the active stage.
# [Usd.Prim(</bicycle>).GetAttribute('size')]
## Looking up relationships:
print(prim.GetRelationships())
# Returns:
# [Usd.Prim(</bicycle>).GetRelationship('proxyPrim')]
box_prim = stage.DefinePrim("/box")
prim.GetRelationship("proxyPrim").SetTargets([box_prim.GetPath()])
# If we now check our properties, you can see both the size attribute
# and proxyPrim relationship show up.
print(prim.GetAuthoredProperties())
# Returns:
# [Usd.Prim(</bicycle>).GetRelationship('proxyPrim'),
#  Usd.Prim(</bicycle>).GetAttribute('size')]
## Creating attributes:
# If we want to create non-schema attributes (or even schema attributes without using
# the schema getter/setters), we can run:
tire_size_attr = prim.CreateAttribute("tire:size", Sdf.ValueTypeNames.Float)
tire_size_attr.Set(5)
#// ANCHOR_END: dataContainerPrimPropertiesHighLevel

#// ANCHOR: dataContainerPrimPropertiesLowLevel
from pxr import Sdf
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/cube")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.specifier = Sdf.SpecifierDef
attr_spec = Sdf.AttributeSpec(prim_spec, "size", Sdf.ValueTypeNames.Float)
print(prim_spec.attributes) # Returns: {'size': Sdf.Find('anon:0x7f6efe199480:LOP:/stage/python', '/cube.size')}
attr_spec.default = 10
# To remove a property you can run:
# prim_spec.RemoveProperty(attr_spec)
# Let's re-create what we did in the high level API example.
box_prim_path = Sdf.Path("/box")
box_prim_spec = Sdf.CreatePrimInLayer(layer, box_prim_path)
box_prim_spec.specifier = Sdf.SpecifierDef
rel_spec = Sdf.RelationshipSpec(prim_spec, "proxyPrim")
rel_spec.targetPathList.explicitItems = [box_prim_path]
# Get all authored properties (in the active layer only)
print(prim_spec.properties)
# Returns:
"""
{'size': Sdf.Find('anon:0x7ff87c9c2000', '/cube.size'),
 'proxyPrim': Sdf.Find('anon:0x7ff87c9c2000', '/cube.proxyPrim')}
"""
#// ANCHOR_END: dataContainerPrimPropertiesLowLevel

#// ANCHOR: metadataSummary
from pxr import Sdf, Usd
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Xform")
prim.SetMetadata("assetInfo", {"version": "1"})
prim.SetAssetInfoByKey("identifier", Sdf.AssetPath("bicycler.usd"))
prim.SetMetadata("customData", {"sizeUnit": "meter"})
prim.SetCustomDataByKey("nested:shape", "round")
#// ANCHOR_END: metadataSummary


#// ANCHOR: metadataBasics
"""
### General
# Has:   'HasAuthoredMetadata'/'HasAuthoredMetadataDictKey'/'HasMetadata'/'HasMetadataDictKey'
# Get:   'GetAllAuthoredMetadata'/'GetAllMetadata'/'GetMetadata'/'GetMetadataByDictKey'
# Set:   'SetMetadata'/'SetMetadataByDictKey', 
# Clear: 'ClearMetadata'/'ClearMetadataByDictKey'
### Asset Info (Prims only)
# Has: 'HasAssetInfo'/'HasAssetInfoKey'/'HasAuthoredAssetInfo'/'HasAuthoredAssetInfoKey'
# Get: 'GetAssetInfo'/'GetAssetInfoByKey'
# Set: 'SetAssetInfo'/'SetAssetInfoByKey', 
# Clear: 'ClearAssetInfo'/'ClearAssetInfoByKey'
### Custom Data (Prims, Properties(Attributes/Relationships), Layers)
# Has: 'HasCustomData'/'HasCustomDataKey'/'HasAuthoredCustomData'/'HasAuthoredCustomDataKey'
# Get: 'GetCustomData'/'GetCustomDataByKey'
# Set: 'SetCustomData'/'SetCustomDataByKey', 
# Clear: 'ClearCustomData'/'ClearCustomDataByKey'
"""
from pxr import Usd, Sdf

stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Xform")
prim.SetAssetInfoByKey("identifier", Sdf.AssetPath("bicycler.usd"))
prim.SetAssetInfoByKey("nested", {"assetPath": Sdf.AssetPath("bicycler.usd"), "version": "1"})
prim.SetMetadataByDictKey("assetInfo", "nested:color", "blue")
attr = prim.CreateAttribute("tire:size", Sdf.ValueTypeNames.Float)
attr.SetMetadata("customData", {"sizeUnit": "meter"})
attr.SetCustomDataByKey("nested:shape", "round")

print(prim.HasAuthoredMetadata("assetInfo")) # Returns: True
print(prim.HasAuthoredMetadataDictKey("assetInfo", "identifier")) # Returns: True
print(prim.HasMetadata("assetInfo")) # Returns: True
print(prim.HasMetadataDictKey("assetInfo", "nested:color")) # Returns: True
# prim.ClearMetadata("assetInfo") # Remove all assetInfo in the current layer.
#// ANCHOR_END: metadataBasics


#// ANCHOR: metadataValidateDict
data = {"myCustomKey": 1}
success_state, metadata, error_message = Sdf.ConvertToValidMetadataDictionary(data)
#// ANCHOR_END: metadataValidateDict


#// ANCHOR: metadataNestedKeyPath
from pxr import Usd, Sdf
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Xform")
prim.SetAssetInfoByKey("nested:color", "blue")
print(prim.GetAssetInfo()) # Returns: {'nested': {'color': 'blue'}}
print(prim.GetAssetInfoByKey("nested:color")) # Returns: "blue"
#// ANCHOR_END: metadataNestedKeyPath


#// ANCHOR: metadataAuthored
from pxr import Usd, Sdf
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Xform")
prim.SetAssetInfoByKey("identifier", "bicycle.usd")
# The difference between "authored" and non "authored" methods is
# that "authored" methods don't return fallback values that come from schemas.
print(prim.GetAllAuthoredMetadata()) 
# Returns:
# {'assetInfo': {'identifier': 'bicycle.usd'}, 
#  'specifier': Sdf.SpecifierDef, 
#  'typeName': 'Xform'}
print(prim.GetAllMetadata()) 
# Returns:
#{'assetInfo': {'identifier': 'bicycle.usd'}, 
# 'documentation': 'Concrete prim schema for a transform, which implements Xformable ',
# 'specifier': Sdf.SpecifierDef,
# 'typeName': 'Xform'}
#// ANCHOR_END: metadataAuthored


#// ANCHOR: metadataStage
from pxr import Usd, Sdf
stage = Usd.Stage.CreateInMemory()
stage.SetMetadata("customLayerData", {"myCustomStageData": 1})
# Is the same as:
layer = stage.GetRootLayer()
metadata = layer.customLayerData
metadata["myCustomRootData"] = 1
layer.customLayerData = metadata
# Or:
layer = stage.GetSessionLayer()
metadata = layer.customLayerData
metadata["myCustomSessionData"] = 1
layer.customLayerData = metadata
# To get the value from the session/root layer depending on the edit target:
stage.GetMetadata("customLayerData")
#// ANCHOR_END: metadataStage


#// ANCHOR: metadataLayer
from pxr import Usd, Sdf
layer = Sdf.Layer.CreateAnonymous()
layer.customLayerData = {"myCustomPipelineKey": "myCoolValue"}
#// ANCHOR_END: metadataLayer


#// ANCHOR: metadataPrimPropertySpec
from pxr import Sdf
layer = Sdf.Layer.CreateAnonymous()
### Prims ###
prim_spec = Sdf.CreatePrimInLayer(layer, "/bicycle")
prim_spec.specifier = Sdf.SpecifierDef
# Asset Info and Custom Data
prim_spec.assetInfo = {"identifier": Sdf.AssetPath("bicycle.usd")}
prim_spec.customData = {"myCoolData": "myCoolValue"}
# General metadata
# Has: 'HasInfo'
# Get: 'ListInfoKeys', 'GetMetaDataInfoKeys', 'GetInfo', 'GetFallbackForInfo', 'GetMetaDataDisplayGroup'
# Set: 'SetInfo', 'SetInfoDictionaryValue'
# Clear: 'ClearInfo'
print(prim_spec.ListInfoKeys()) # Returns: ['assetInfo', 'customData', 'specifier']
# To get all registered schema keys run:
print(prim_spec.GetMetaDataInfoKeys())
"""Returns: ['payloadAssetDependencies', 'payload', 'kind', 'suffix', 'inactiveIds', 'clipSets',
'HDAKeepEngineOpen', 'permission', 'displayGroupOrder', 'assetInfo', 'HDAParms', 'instanceable', 
'symmetryFunction', 'HDATimeCacheMode', 'clips', 'HDAAssetName', 'active', 'HDATimeCacheEnd', 
'customData', 'HDAOptions', 'prefix', 'apiSchemas', 'suffixSubstitutions', 'symmetryArguments',
'hidden', 'HDATimeCacheStart', 'sdrMetadata', 'typeName', 'HDATimeCacheInterval', 'documentation',
'prefixSubstitutions', 'symmetricPeer']"""
# For the fallback values and UI grouping hint you can use
# 'GetFallbackForInfo' and 'GetMetaDataDisplayGroup'.
# Prim spec core data is actually also just metadata info
prim_spec.SetInfo("specifier", Sdf.SpecifierDef)
prim_spec.SetInfo("typeName", "Xform")
# Is the same as:
prim_spec.specifier = Sdf.SpecifierDef
prim_spec.typeName = "Xform"

### Properties ###
attr_spec = Sdf.AttributeSpec(prim_spec, "tire:size", Sdf.ValueTypeNames.Float)
# Custom Data
attr_spec.customData = {"myCoolData": "myCoolValue"}
# We can actually use the attr_spec.customData assignment here too,
# doesn't make that much sense though
# General metadata
# Has: 'HasInfo'
# Get: 'ListInfoKeys', 'GetMetaDataInfoKeys', 'GetInfo', 'GetFallbackForInfo', 'GetMetaDataDisplayGroup'
# Set: 'SetInfo', 'SetInfoDictionaryValue'
# Clear: 'ClearInfo'
# The API here is the same as for the prim_spec, as it all inherits from Sdf.Spec
# To get all registered schema keys run:
print(attr_spec.GetMetaDataInfoKeys())
"""Returns: ['unauthoredValuesIndex', 'interpolation', 'displayGroup', 'faceIndexPrimvar', 
'suffix', 'constraintTargetIdentifier', 'permission', 'assetInfo', 'symmetryFunction', 'uvPrimvar',
'elementSize', 'allowedTokens', 'customData', 'prefix', 'renderType', 'symmetryArguments', 
'hidden', 'displayName', 'sdrMetadata', 'faceOffsetPrimvar', 'weight', 'documentation', 
'colorSpace', 'symmetricPeer', 'connectability']
"""
#// ANCHOR_END: metadataPrimPropertySpec

#// ANCHOR: metadataDocs
from pxr import Usd, Sdf
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Cube")
# Shortcut to get the docs metadata
# Has: 'HasAuthoredDocumentation'
# Get: 'GetDocumentation'
# Set: 'SetDocumentation'
# Clear: 'ClearDocumentation'
print(prim.GetDocumentation())
for attr in prim.GetAttributes():
    print(attr.GetName(), attr.GetDocumentation())
    # Or
    # print(attr.GetMetadata("documentation"))
#// ANCHOR_END: metadataDocs

#// ANCHOR: metadataDocsResult
"""
Defines a primitive rectilinear cube centered at the origin.
    The fallback values for Cube, Sphere, Cone, and Cylinder are set so that
    they all pack into the same volume/bounds.
doubleSided Although some renderers treat all parametric or polygonal
        surfaces as if they were effectively laminae with outward-facing
        normals on both sides, some renderers derive significant optimizations
        by considering these surfaces to have only a single outward side,
        typically determined by control-point winding order and/or 
        orientation.  By doing so they can perform "backface culling" to
        avoid drawing the many polygons of most closed surfaces that face away
        from the viewer.
        
        However, it is often advantageous to model thin objects such as paper
        and cloth as single, open surfaces that must be viewable from both
        sides, always.  Setting a gprim's doubleSided attribute to 
        \c true instructs all renderers to disable optimizations such as
        backface culling for the gprim, and attempt (not all renderers are able
        to do so, but the USD reference GL renderer always will) to provide
        forward-facing normals on each side of the surface for lighting
        calculations.
extent Extent is re-defined on Cube only to provide a fallback value.
        \sa UsdGeomGprim::GetExtentAttr().
orientation Orientation specifies whether the gprim's surface normal 
        should be computed using the right hand rule, or the left hand rule.
        Please see for a deeper explanation and
        generalization of orientation to composed scenes with transformation
        hierarchies.
primvars:displayColor It is useful to have an "official" colorSet that can be used
        as a display or modeling color, even in the absence of any specified
        shader for a gprim.  DisplayColor serves this role; because it is a
        UsdGeomPrimvar, it can also be used as a gprim override for any shader
        that consumes a displayColor parameter.
primvars:displayOpacity Companion to displayColor that specifies opacity, broken
        out as an independent attribute rather than an rgba color, both so that
        each can be independently overridden, and because shaders rarely consume
        rgba parameters.
purpose Purpose is a classification of geometry into categories that 
        can each be independently included or excluded from traversals of prims 
        on a stage, such as rendering or bounding-box computation traversals.

        See for more detail about how 
        purpose is computed and used.
size Indicates the length of each edge of the cube.  If you
        author size you must also author extent.

visibility Visibility is meant to be the simplest form of "pruning" 
        visibility that is supported by most DCC apps.  Visibility is 
        animatable, allowing a sub-tree of geometry to be present for some 
        segment of a shot, and absent from others; unlike the action of 
        deactivating geometry prims, invisible geometry is still 
        available for inspection, for positioning, for defining volumes, etc.
xformOpOrder Encodes the sequence of transformation operations in the
        order in which they should be pushed onto a transform stack while
        visiting a UsdStage's prims in a graph traversal that will effect
        the desired positioning for this prim and its descendant prims.
        
        You should rarely, if ever, need to manipulate this attribute directly.
        It is managed by the AddXformOp(), SetResetXformStack(), and
        SetXformOpOrder(), and consulted by GetOrderedXformOps() and
        GetLocalTransformation().
"""
#// ANCHOR_END: metadataDocsResult

#// ANCHOR: metadataActive
from pxr import Sdf, Usd
### High Level ###
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Xform")
prim.SetActive(False)

### Low Level ###
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/cube")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.active = False
# Or
prim_spec.SetInfo(prim_spec.ActiveKey, True)
#// ANCHOR_END: metadataActive


#// ANCHOR: metadataAssetInfo
from pxr import Sdf, Usd
### High Level ###
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Xform")
prim.SetMetadata("assetInfo", {"identifier": Sdf.AssetPath("bicycler.usd")})
prim.SetAssetInfoByKey("name", "bicycle")
prim.SetAssetInfoByKey("version", "v001")
prim.SetAssetInfoByKey("payloadAssetDependencies", Sdf.AssetPathArray(["assetIndentifierA", "assetIndentifierA"]))
# Sdf.AssetPathArray([]) auto-casts all elements to Sdf.AssetPath objects.

### Low Level ###
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/cube")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.assetInfo = {"identifier": Sdf.AssetPath("bicycle.usd")}
prim_spec.assetInfo["name"] = "bicycle"
prim_spec.assetInfo["version"] = "v001"
prim_spec.assetInfo["payloadAssetDependencies"] = Sdf.AssetPathArray(["assetIndentifierA", "assetIndentifierA"])
# Sdf.AssetPathArray([]) auto-casts all elements to Sdf.AssetPath objects.
#// ANCHOR_END: metadataAssetInfo

#// ANCHOR: metadataCustomData
from pxr import Sdf, Usd
### High Level ###
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Xform")
prim.SetMetadata("customData", {"sizeUnit": "meter"})
prim.SetCustomDataByKey("nested:shape", "round")

### Low Level ###
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/cube")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.customData = {"myCoolData": "myCoolValue"}
#// ANCHOR_END: metadataCustomData


#// ANCHOR: metadataComment
from pxr import Sdf, Usd
### High Level ###
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Xform")
prim.SetMetadata("comment", "This is a cool prim!")

### Low Level ###
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/cube")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.SetInfo("comment", "This is a cool prim spec!")
#// ANCHOR_END: metadataComment

#// ANCHOR: metadataIcon
from pxr import Sdf, Usd
### High Level ###
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Xform")
prim.SetMetadata("customData", {"icon": "/path/to/icon.png"})
prim.SetCustomDataByKey("icon", "/path/to/icon.png")

### Low Level ###
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/cube")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.customData = {"icon": "/path/to/icon.png"}
#// ANCHOR_END: metadataIcon

#// ANCHOR: metadataHidden
from pxr import Sdf, Usd
### High Level ###
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Xform")
prim.SetHidden(True)

### Low Level ###
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/cube")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.SetInfo("hidden", True)
#// ANCHOR_END: metadataHidden

#// ANCHOR: metadataVariability
from pxr import Sdf, Usd
### High Level ###
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/box")
prim = stage.DefinePrim(prim_path, "Cube")
attr = prim.CreateAttribute("height", Sdf.ValueTypeNames.Double)
attr.SetMetadata("variability", Sdf.VariabilityUniform)
### Low Level ###
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/box")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.typeName = "Cube"
attr_spec = Sdf.AttributeSpec(prim_spec, "height", Sdf.ValueTypeNames.Double)
attr_spec.SetInfo("variability", Sdf.VariabilityVarying)
#// ANCHOR_END: metadataVariability

#// ANCHOR: metadataCustom
from pxr import Sdf, Usd
### High Level ###
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/box")
prim = stage.DefinePrim(prim_path, "Cube")
attr = prim.CreateAttribute("height", Sdf.ValueTypeNames.Double)
# This is not necessary to do explicitly as
# the high level API does this for us.
attr.SetMetadata("custom", True)
# Or
print(attr.IsCustom())
attr.SetCustom(True)
### Low Level ###
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/box")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.typeName = "Cube"
attr_spec = Sdf.AttributeSpec(prim_spec, "height", Sdf.ValueTypeNames.Double)
attr_spec.SetInfo("custom", True)
#// ANCHOR_END: metadataCustom

# // ANCHOR: metadataRenderSettingsPrimPath
### High Level ###
from pxr import Usd

stage = Usd.Stage.CreateInMemory()
stage.GetRootLayer().pseudoRoot.SetInfo(
    "renderSettingsPrimPath", "/Render/rendersettings"
)
### Low Level ###
from pxr import Sdf

layer = Sdf.Layer.CreateAnonymous()
layer.pseudoRoot.SetInfo("renderSettingsPrimPath", "/Render/rendersettings")
# // ANCHOR_END: metadataRenderSettingsPrimPath


# // ANCHOR: metadataLayerMetrics
from pxr import Sdf, Usd, UsdGeom

### High Level ###
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Cone")
size_attr = prim.GetAttribute("radius")
for frame in range(1001, 1006):
    time_code = Usd.TimeCode(frame)
    size_attr.Set(frame - 1000, time_code)
# FPS Metadata
time_samples = Sdf.Layer.ListAllTimeSamples(layer)
stage.SetTimeCodesPerSecond(25)
stage.SetFramesPerSecond(25)
stage.SetStartTimeCode(time_samples[0])
stage.SetEndTimeCode(time_samples[-1])
# Scene Unit Scale
UsdGeom.SetStageMetersPerUnit(stage, UsdGeom.LinearUnits.centimeters)
# To map 24 fps (default) to 25 fps we have scale by 24/25 when loading the layer in the Sdf.LayerOffset
# Scene Up Axis
UsdGeom.SetStageUpAxis(stage, UsdGeom.Tokens.y)  # Or  UsdGeom.Tokens.z

### Low Level ###
from pxr import Sdf

layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/bicycle")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.specifier = Sdf.SpecifierDef
prim_spec.typeName = "Cube"
attr_spec = Sdf.AttributeSpec(prim_spec, "size", Sdf.ValueTypeNames.Double)
for frame in range(1001, 1006):
    value = float(frame - 1000)
    layer.SetTimeSample(attr_spec.path, frame, value)
# FPS Metadata
layer.timeCodesPerSecond = 25
layer.framesPerSecond = 25
layer.startTimeCode = time_samples[0]
layer.endTimeCode = time_samples[-1]
# Scene Unit Scale
layer.pseudoRoot.SetInfo(UsdGeom.Tokens.metersPerUnit, UsdGeom.LinearUnits.centimeters)
# Scene Up Axis
layer.pseudoRoot.SetInfo(
    UsdGeom.Tokens.upAxis, UsdGeom.Tokens.y
)  # Or  UsdGeom.Tokens.z
# // ANCHOR_END: metadataLayerMetrics

#// ANCHOR: debuggingTokens
from pxr import Tf
# To check if a symbol is active:
Tf.Debug.IsDebugSymbolNameEnabled("MY_SYMBOL_NAME")
# To print all symbols
docs = Tf.Debug.GetDebugSymbolDescriptions()
for name in Tf.Debug.GetDebugSymbolNames():
    desc = Tf.Debug.GetDebugSymbolDescription(name)
    print("{:<50} | {}".format(name, desc))
#// ANCHOR_END: debuggingTokens

#// ANCHOR: debuggingTokensMarkdown
from pxr import Tf
docs = Tf.Debug.GetDebugSymbolDescriptions()
print("| Variable Name | Description |")
print("|-|-|")
for name in Tf.Debug.GetDebugSymbolNames():
    desc = Tf.Debug.GetDebugSymbolDescription(name)
    print("| {} | {} |".format(name, desc))
#// ANCHOR_END: debuggingTokensMarkdown

#// ANCHOR: profilingTraceAttach
import os
from pxr import Trace, Usd
# Code with trace attached
class Bar():
    @Trace.TraceMethod
    def foo(self):
        print("Bar.foo")

@Trace.TraceFunction
def foo(stage):
    with Trace.TraceScope("InnerScope"):
        bar = Bar()
        for prim in stage.Traverse():
            prim.HasAttribute("size")
#// ANCHOR_END: profilingTraceAttach

#// ANCHOR: profilingTraceCollect
import os
from pxr import Trace, Usd
# The Trace.Collector() and Trace.Reporter.globalReporter return a singletons
# The default traces all go to TraceCategory::Default, this is not configurable via python
global_reporter = Trace.Reporter.globalReporter
global_reporter.ClearTree()
collector = Trace.Collector()
collector.Clear()
# Start recording events.
collector.enabled = True
# Enable the Usd Python API tracing (No the manually attached tracers)
collector.pythonTracingEnabled = False
# Run code
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Xform")
foo(stage)
# Stop recording events.
collector.enabled = False
# Print the ASCII report
trace_dir_path = os.path.dirname(os.path.expanduser("~/Desktop/UsdTracing"))
global_reporter.Report(os.path.join(trace_dir_path, "report.trace"))
global_reporter.ReportChromeTracingToFile(os.path.join(trace_dir_path,"report.json"))
#// ANCHOR_END: profilingTraceCollect

#// ANCHOR: profilingStopWatch
from pxr import Tf
sw = Tf.Stopwatch()
sw.Start()
sw.Stop()
sw.Start()
sw.Stop()
print(sw.milliseconds, sw.sampleCount)
sw.Reset()
# Add sampleCount + accumulated time from other stop watch
other_sw = Tf.StopWatch()
other_sw.Start()
other_sw.Stop()
sw.AddFrom(other_sw) 
print(sw.milliseconds, sw.sampleCount)
#// ANCHOR_END: profilingStopWatch

#// ANCHOR: pluginsRegistry
from pxr import Plug
registry = Plug.Registry()
for plugin in registry.GetAllPlugins():
    print(plugin.name, plugin.path, plugin.isLoaded)
    # To print the plugInfo.json content run:
    # print(plugin.metadata)
#// ANCHOR_END: pluginsRegistry

#// ANCHOR: assetResolverBound
from pxr import Ar
from usdAssetResolver import FileResolver
print(Ar.GetResolver())
print(Ar.GetUnderlyingResolver()) # Returns: <usdAssetResolver.FileResolver.Resolver object at <address>>
#// ANCHOR_END: assetResolverBound

#// ANCHOR: assetResolverScopedCache
from pxr import Ar
with Ar.ResolverScopedCache() as scope:
    resolver = Ar.GetResolver()
    path = resolver.Resolve("box.usda")
#// ANCHOR_END: assetResolverScopedCache

#// ANCHOR: assetResolverContextAccess
context_collection = stage.GetPathResolverContext()
activeResolver_context = context_collection.Get()[0]
#// ANCHOR_END: assetResolverContextAccess 

#// ANCHOR: assetResolverContextCreation
from pxr import Ar, Usd
from usdAssetResolver import FileResolver
resolver = Ar.GetUnderlyingResolver()
context_collection = resolver.CreateDefaultContext() # Returns: Ar.ResolverContext(FileResolver.ResolverContext())
context = context_collection.Get()[0]
context.ModifySomething() # Call specific functions of your resolver.
# Create a stage that uses the context
stage = Usd.Stage.CreateInMemory("/output/stage/filePath.usd", pathResolverContext=context)
# Or
stage = Usd.Stage.Open("/Existing/filePath/to/UsdFile.usd", pathResolverContext=context)
#// ANCHOR_END: assetResolverContextCreation

#// ANCHOR: assetResolverContextRefresh
from pxr import Ar
...
resolver = Ar.GetResolver()
# The resolver context is actually a list, as there can be multiple resolvers 
# running at the same time. In this example we only have a single non-URI resolver
# running, therefore we only have a single element in the list.
context_collection = stage.GetPathResolverContext()
activeResolver_context = context_collection.Get()[0]
# Your asset resolver has to Python expose methods to modify the context.
activeResolver_context.ModifySomething()
# Trigger Refresh (Some DCCs, like Houdini, additionally require node re-cooks.)
resolver.RefreshContext(context_collection)
...
#// ANCHOR_END: assetResolverContextRefresh

#// ANCHOR: assetResolverStageContextResolve
resolved_path = stage.ResolveIdentifierToEditTarget("someAssetIdentifier")
# Get the Python string
resolved_path_str = resolved_path.GetPathString() # Or str(resolved_path)
#// ANCHOR_END: assetResolverStageContextResolve

#// ANCHOR: assetResolverResolve
from pxr import Ar
resolver = Ar.GetResolver()
resolved_path = resolver.Resolve("someAssetIdentifier")
# Get the Python string
resolved_path_str = resolved_path.GetPathString() # Or str(resolved_path)
#// ANCHOR_END: assetResolverResolve

#// ANCHOR: assetResolverAssetPath
from pxr import Sdf
asset_path = Sdf.AssetPath("someAssetIdentifier", "/some/Resolved/Path.usd")
print(asset_path.path)         # Returns: "someAssetIdentifier"
print(asset_path.resolvedPath) # Returns: "/some/Resolved/Path.usd"
#// ANCHOR_END: assetResolverAssetPath


#// ANCHOR: noticeRegisterRevoke
from pxr import Tf, Usd
def callback(notice, sender):
    print(notice, sender)
# Add
# Global
listener = Tf.Notice.RegisterGlobally(Usd.Notice.StageContentsChanged, callback)
# Per Stage
listener = Tf.Notice.Register(Usd.Notice.StageContentsChanged, callback, stage)
# Remove
listener.Revoke()
#// ANCHOR_END: noticeRegisterRevoke


#// ANCHOR: noticeCommon
from pxr import Usd, Plug
# Generic (Do not send what stage they are from)
notice = Usd.Notice.StageContentsChanged
notice = Usd.Notice.StageEditTargetChanged
# Layer Muting
notice = Usd.Notice.LayerMutingChanged
# In the callback you can get the changed layers by calling:
# notice.GetMutedLayers()
# notice.GetUnmutedLayers()
# Object Changed
notice = Usd.Notice.ObjectsChanged
# In the callback you can get the following info by calling:
# notice.GetResyncedPaths()          # Changed Paths (Composition or Creation/Rename/Removal)
# notice.GetChangedInfoOnlyPaths()   # Attribute/Metadata value changes
# With these methods you can test if a Usd object 
# (UsdObject==BaseClass for Prims/Properties/Metadata) has been affected.
# notice.AffectedObject(UsdObject) (Generic)
# notice.ResyncedObject(UsdObject) (Composition Change)
# notice.ChangedInfoOnly(UsdObject) (Value Change)
# notice.HasChangedFields(UsdObject/SdfPath) 
# notice.GetChangedFields(UsdObject/SdfPath)
# Plugin registered
notice = Plug.Notice.DidRegisterPlugins
# notice.GetNewPlugins() # Get new plugins
#// ANCHOR_END: noticeCommon


#// ANCHOR: noticePlugins
from pxr import Tf, Usd, Plug

def DidRegisterPlugins_callback(notice):
    print(notice, notice.GetNewPlugins())

listener = Tf.Notice.RegisterGlobally(Plug.Notice.DidRegisterPlugins, DidRegisterPlugins_callback)
listener.Revoke()
#// ANCHOR_END: noticePlugins


#// ANCHOR: noticeCommonApplied
from pxr import Tf, Usd, Sdf

def ObjectsChanged_callback(notice, sender):
    stage = notice.GetStage()
    print("---")
    print(">", notice, sender)
    print(">> (notice.GetResyncedPaths) - Updated paths", notice.GetResyncedPaths())
    print(">> (notice.GetChangedInfoOnlyPaths) - Attribute/Metadata value changes", notice.GetChangedInfoOnlyPaths())
    
    prim = stage.GetPrimAtPath("/bicycle")
    if prim:
        # Check if a specific UsdObject was affected
        print(">> (notice.AffectedObject) - Something changed for", prim.GetPath(), notice.AffectedObject(prim))
        print(">> (notice.ResyncedObject) - Updated path for", prim.GetPath(), notice.ResyncedObject(prim))
        print(">> (notice.ChangedInfoOnly) - Attribute/Metadata ChangedInfoOnly", prim.GetPath(), notice.ChangedInfoOnly(prim))
        print(">> (notice.HasChangedFields) - Attribute/Metadata HasChanges", prim.GetPath(), notice.HasChangedFields(prim))
        print(">> (notice.GetChangedFields) - Attribute/Metadata ChangedFields", prim.GetPath(), notice.GetChangedFields(prim))

    attr = stage.GetAttributeAtPath("/bicycle.tire:size")
    if attr:
        # Check if a specific UsdObject was affected
        print(">> (notice.AffectedObject) - Something changed for", attr.GetPath(), notice.AffectedObject(attr))
        print(">> (notice.ResyncedObject) - Updated path for", attr.GetPath(), notice.ResyncedObject(attr))
        print(">> (notice.ChangedInfoOnly) - Attribute/Metadata ChangedInfoOnly", attr.GetPath(), notice.ChangedInfoOnly(attr))
        print(">> (notice.HasChangedFields) - Attribute/Metadata HasChanges", attr.GetPath(), notice.HasChangedFields(attr))
        print(">> (notice.GetChangedFields) - Attribute/Metadata ChangedFields", attr.GetPath(), notice.GetChangedFields(attr))

# Add
listener = Tf.Notice.RegisterGlobally(Usd.Notice.ObjectsChanged, ObjectsChanged_callback)
# Edit
stage = Usd.Stage.CreateInMemory()
# Create Prim
prim = stage.DefinePrim("/bicycle")
# Results:
# >> <pxr.Usd.ObjectsChanged object at 0x7f071d58e820> Usd.Stage.Open(rootLayer=Sdf.Find('anon:0x7f06927ccc00:tmp.usda'), sessionLayer=Sdf.Find('anon:0x7f06927cdb00:tmp-session.usda'))
# >> (notice.GetResyncedPaths) - Updated paths [Sdf.Path('/bicycle')]
# >> (notice.GetChangedInfoOnlyPaths) - Attribute/Metadata value changes []
# >> (notice.AffectedObject) - Something changed for /bicycle True
# >> (notice.ResyncedObject) - Updated path for /bicycle True
# >> (notice.ChangedInfoOnly) - Attribute/Metadata ChangedFieldsOnly /bicycle False
# >> (notice.HasChangedFields) - Attribute/Metadata HasChanges /bicycle True
# >> (notice.GetChangedFields) - Attribute/Metadata ChangedFields /bicycle ['specifier']
# Create Attribute
attr = prim.CreateAttribute("tire:size", Sdf.ValueTypeNames.Float)
# Results:
# >> <pxr.Usd.ObjectsChanged object at 0x7f071d58e820> Usd.Stage.Open(rootLayer=Sdf.Find('anon:0x7f06927ccc00:tmp.usda'), sessionLayer=Sdf.Find('anon:0x7f06927cdb00:tmp-session.usda'))
# >> (notice.GetResyncedPaths) - Updated paths [Sdf.Path('/bicycle.tire:size')]
# >> (notice.GetChangedInfoOnlyPaths) - Attribute/Metadata value changes []
# >> (notice.AffectedObject) - Something changed for /bicycle False
# >> (notice.ResyncedObject) - Updated path for /bicycle False
# >> (notice.ChangedInfoOnly) - Attribute/Metadata ChangedInfoOnly /bicycle False
# >> (notice.HasChangedFields) - Attribute/Metadata HasChanges /bicycle False
# >> (notice.GetChangedFields) - Attribute/Metadata ChangedFields /bicycle []
# >> (notice.AffectedObject) - Something changed for /bicycle.tire:size True
# >> (notice.ResyncedObject) - Updated path for /bicycle.tire:size True
# >> (notice.ChangedInfoOnly) - Attribute/Metadata ChangedInfoOnly /bicycle.tire:size False
# >> (notice.HasChangedFields) - Attribute/Metadata HasChanges /bicycle.tire:size True
# >> (notice.GetChangedFields) - Attribute/Metadata ChangedFields /bicycle.tire:size ['custom']
# Remove
listener.Revoke()
#// ANCHOR_END: noticeCommonApplied


#// ANCHOR: noticeCustom
from pxr import Tf, Usd
# Create notice callback
def callback(notice, sender):
    print(notice, sender)
# Create a new notice type
class CustomNotice(Tf.Notice):
    '''My custom notice'''
# Get fully qualified domain name
CustomNotice_FQN = "{}.{}".format(CustomNotice.__module__, CustomNotice.__name__)
# Register notice
# Important: If you overwrite the CustomNotice Class in the same Python session
# (for example when running this snippet twice in a DCC Python session), you
# cannot send anymore notifications as the defined type will have lost the pointer
# to the class, but you can't re-define it because of how the type definition works.
if not Tf.Type.FindByName(CustomNotice_FQN):
    Tf.Type.Define(CustomNotice)
# Register notice listeners
# Globally
listener = Tf.Notice.RegisterGlobally(CustomNotice, callback)
# For a specific stage
sender = Usd.Stage.CreateInMemory()
listener = Tf.Notice.Register(CustomNotice, callback, sender)
# Send notice
CustomNotice().SendGlobally()
CustomNotice().Send(sender)
# Remove listener
listener.Revoke()
#// ANCHOR_END: noticeCustom


#// ANCHOR: kindRegistry
from pxr import Kind
registry = Kind.Registry()
for kind in registry.GetAllKinds():
    base_kind = Kind.Registry.GetBaseKind(kind)
    print(f"{kind:<15} - Base Kind - {base_kind}")
# Returns:
"""
set             - Base Kind - assembly
assembly        - Base Kind - group
fx              - Base Kind - component
environment     - Base Kind - assembly
character       - Base Kind - component
group           - Base Kind - model
component       - Base Kind - model
model           - Base Kind 
subcomponent    - Base Kind 
"""    
print(registry.HasKind("fx")) # Returns: True
print(registry.IsA("fx", "model")) # Returns: True
#// ANCHOR_END: kindRegistry

#// ANCHOR: kindTraversal
from pxr import Kind, Sdf, Usd
stage = Usd.Stage.CreateInMemory()
prim = stage.DefinePrim(Sdf.Path("/set"), "Xform")
Usd.ModelAPI(prim).SetKind("set")
prim = stage.DefinePrim(Sdf.Path("/set/garage"), "Xform")
Usd.ModelAPI(prim).SetKind("group")
prim = stage.DefinePrim(Sdf.Path("/set/garage/bicycle"), "Xform")
Usd.ModelAPI(prim).SetKind("prop")
prim = stage.DefinePrim(Sdf.Path("/set/yard"), "Xform")
Usd.ModelAPI(prim).SetKind("group")
prim = stage.DefinePrim(Sdf.Path("/set/yard/explosion"), "Xform")
Usd.ModelAPI(prim).SetKind("fx")
# Result:
print(stage.ExportToString())
"""
def Xform "set" (
    kind = "set"
)
{
    def Xform "garage" (
        kind = "group"
    )
    {
        def Xform "bicycle" (
            kind = "prop"
        )
        {
        }
    }

    def Xform "yard" (
        kind = "group"
    )
    {
        def Xform "explosion" (
            kind = "fx"
        )
        {
        }
    }
}
"""
for prim in stage.Traverse():
    print("{:<20} - IsModel: {} - IsGroup: {}".format(prim.GetPath().pathString, prim.IsModel(), prim.IsGroup()))
# Returns:
"""
/set                 - IsModel: True - IsGroup: True
/set/garage          - IsModel: True - IsGroup: True
/set/garage/bicycle  - IsModel: True - IsGroup: False
/set/yard            - IsModel: True - IsGroup: True
/set/yard/explosion  - IsModel: True - IsGroup: False
"""
registry = Kind.Registry()
for prim in stage.Traverse():
    kind = Usd.ModelAPI(prim).GetKind()
    print("{:<25} - {:<5} - {}".format(prim.GetPath().pathString, kind, registry.IsA("fx", "component")))

# Failed traversal because of missing kinds
stage = Usd.Stage.CreateInMemory()
prim = stage.DefinePrim(Sdf.Path("/set"), "Xform")
Usd.ModelAPI(prim).SetKind("set")
prim = stage.DefinePrim(Sdf.Path("/set/garage"), "Xform")
prim = stage.DefinePrim(Sdf.Path("/set/garage/bicycle"), "Xform")
Usd.ModelAPI(prim).SetKind("prop")
prim = stage.DefinePrim(Sdf.Path("/set/yard"), "Xform")
prim = stage.DefinePrim(Sdf.Path("/set/yard/explosion"), "Xform")
Usd.ModelAPI(prim).SetKind("fx")
registry = Kind.Registry()
for prim in stage.Traverse():
    kind = Usd.ModelAPI(prim).GetKind()
    print("{:<20} - Kind: {:10} - IsA('component') {}".format(prim.GetPath().pathString, kind, registry.IsA(kind, "component")))
    print("{:<20} - IsModel: {} - IsGroup: {}".format(prim.GetPath().pathString, prim.IsModel(), prim.IsGroup()))
"""
/set                 - Kind: set        - IsA('component') False
/set                 - IsModel: True - IsGroup: True
/set/garage          - Kind:            - IsA('component') False
/set/garage          - IsModel: False - IsGroup: False
/set/garage/bicycle  - Kind: prop       - IsA('component') True
/set/garage/bicycle  - IsModel: False - IsGroup: False
/set/yard            - Kind:            - IsA('component') False
/set/yard            - IsModel: False - IsGroup: False
/set/yard/explosion  - Kind: fx         - IsA('component') True
/set/yard/explosion  - IsModel: False - IsGroup: False
"""
#// ANCHOR_END: kindTraversal



#// ANCHOR: animationOverview
from pxr import Sdf, Usd
### High Level ###
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Cube")
size_attr = prim.GetAttribute("size")
for frame in range(1001, 1005):
    time_code = Usd.TimeCode(float(frame - 1001))
    # .Set() takes args in the .Set(<value>, <frame>) format
    size_attr.Set(frame, time_code)
print(size_attr.Get(1005)) # Returns: 4

### Low Level ###
from pxr import Sdf
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/bicycle")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.specifier = Sdf.SpecifierDef
prim_spec.typeName = "Cube"
attr_spec = Sdf.AttributeSpec(prim_spec, "size", Sdf.ValueTypeNames.Double)
for frame in range(1001, 1005):
    value = float(frame - 1001)
    # .SetTimeSample() takes args in the .SetTimeSample(<path>, <frame>, <value>) format
    layer.SetTimeSample(attr_spec.path, frame, value)
print(layer.QueryTimeSample(attr_spec.path, 1005)) # Returns: 4
#// ANCHOR_END: animationOverview

#// ANCHOR: animationTimeCode
from pxr import Sdf, Usd
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Cube")
size_attr = prim.GetAttribute("size")
## Set default value
time_code = Usd.TimeCode.Default()
size_attr.Set(10, time_code)
# Or:
size_attr.Set(10) # The default is to set `default` (non-per-frame) data.
## Set per frame value
for frame in range(1001, 1005):
    time_code = Usd.TimeCode(frame)
    size_attr.Set(frame, time_code)
# Or
# As with Sdf.Path implicit casting from strings in a lot of places in the USD API,
# the time code is implicitly casted from a Python float. 
# It is recommended to do the above, to be more future proof of 
# potentially encoding time unit based samples.
for frame in range(1001, 1005):
    size_attr.Set(frame, frame)
## Other than that the TimeCode class only has a via Is/Get methods of interest:
size_attr.IsDefault() # Returns: True if no time value was given
size_attr.IsNumeric() # Returns: True if not IsDefault()
size_attr.GetValue() # Returns: The time value (if not IsDefault()
#// ANCHOR_END: animationTimeCode

#// ANCHOR: animationLayerOffset
from pxr import Sdf, Usd
# The Sdf.LayerOffset(<offset>, <scale>) class has 
# no attributes/methods other than LayerOffset.offset & LayerOffset.scale.
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/animal")
root_layer = stage.GetRootLayer()
## For sublayering via Python, we first need to sublayer, then edit offset.
# In Houdini we can't due this directly due to Houdini's stage handling system.
file_path = "/opt/hfs19.5/houdini/usd/assets/pig/pig.usd"
root_layer.subLayerPaths.append(file_path)
print(root_layer.subLayerPaths)
print(root_layer.subLayerOffsets)
# Since layer offsets are read only, we need to assign it to a new one in-place.
# !DANGER! Due to how it is exposed to Python, we can't assign a whole array with the
# new offsets, instead we can only swap individual elements in the array, so that the
# array pointer is kept intact.
root_layer.subLayerOffsets[0] = Sdf.LayerOffset(25, 1) 
## For references
ref = Sdf.Reference(file_path, "/pig", Sdf.LayerOffset(25, 1))
prim = stage.DefinePrim(prim_path)
ref_API = prim.GetReferences()
ref_API.AddReference(ref)
ref = Sdf.Reference("", "/animal", Sdf.LayerOffset(50, 1))
internal_prim = stage.DefinePrim(prim_path.ReplaceName("internal"))
ref_API = internal_prim.GetReferences()
ref_API.AddReference(ref)
## For payloads
payload = Sdf.Payload(file_path, "/pig", Sdf.LayerOffset(25, 1))
prim = stage.DefinePrim(prim_path)
payload_API = prim.GetPayloads()
payload_API.AddPayload(payload)
#// ANCHOR_END: animationLayerOffset


#// ANCHOR: animationWrite
from pxr import Sdf, Usd
### High Level ###
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Cube")
size_attr = prim.GetAttribute("size")
## Set default value
time_code = Usd.TimeCode.Default()
size_attr.Set(10, time_code)
# Or:
size_attr.Set(10) # The default is to set `default` (non-per-frame) data.
## Set per frame value
for frame in range(1001, 1005):
    value = float(frame - 1001)
    time_code = Usd.TimeCode(frame)
    size_attr.Set(value, time_code)
# Clear default value
size_attr.ClearDefault(1001)
# Remove a time sample
size_attr.ClearAtTime(1001)

### Low Level ###
from pxr import Sdf
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/bicycle")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.specifier = Sdf.SpecifierDef
prim_spec.typeName = "Cube"
attr_spec = Sdf.AttributeSpec(prim_spec, "size", Sdf.ValueTypeNames.Double)
## Set default value
attr_spec.default = 10
## Set per frame value
for frame in range(1001, 1005):
    value = float(frame - 1001)
    layer.SetTimeSample(attr_spec.path, frame, value)
# Clear default value
attr_spec.ClearDefaultValue()
# Remove a time sample
layer.EraseTimeSample(attr_spec.path, 1001)
#// ANCHOR_END: animationWrite

#// ANCHOR: animationRead
from pxr import Gf, Sdf, Usd
### High Level ###
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Cube")
size_attr = prim.GetAttribute("size")
size_attr.Set(10) 
for frame in range(1001, 1005):
    time_code = Usd.TimeCode(frame)
    size_attr.Set(frame-1001, time_code)
# Query the default value (must be same value source aka layer as the time samples).
print(size_attr.Get()) # Returns: 10
# Query the animation time samples
for time_sample in size_attr.GetTimeSamples():
    print(size_attr.Get(time_sample))
# Returns:
"""
0.0, 1.0, 2.0, 3.0
"""
# Other important time sample methods:
# !Danger! For value clipped (per frame loaded layers),
# this will look into all layers, which is quite expensive.
print(size_attr.GetNumTimeSamples()) # Returns: 4
# You should rather use:
# This does a check for time sample found > 2.
# So it stops looking for more samples after the second sample.
print(size_attr.ValueMightBeTimeVarying()) # Returns: True
## We can also query what the closest time sample to a frame:
print(size_attr.GetBracketingTimeSamples(1003.3)) 
# Returns: (<Found sample>, <lower closest sample>, <upper closest sample>)
(True, 1003.0, 1004.0)
## We can also query time samples in a range. This is useful if we only want to lookup and copy
# a certain range, for example in a pre-render script.
print(size_attr.GetTimeSamplesInInterval(Gf.Interval(1001, 1003))) 
# Returns: [1001.0, 1002.0, 1003.0]


### Low Level ###
from pxr import Sdf
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/bicycle")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.specifier = Sdf.SpecifierDef
prim_spec.typeName = "Cube"
attr_spec = Sdf.AttributeSpec(prim_spec, "size", Sdf.ValueTypeNames.Double)
attr_spec.default = 10
for frame in range(1001, 1005):
    value = float(frame - 1001)
    layer.SetTimeSample(attr_spec.path, frame, value)
# Query the default value
print(attr_spec.default) # Returns: 10
# Query the animation time samples
time_sample_count = layer.GetNumTimeSamplesForPath(attr_spec.path)
for time_sample in layer.ListTimeSamplesForPath(attr_spec.path):
    print(layer.QueryTimeSample(attr_spec.path, time_sample))
# Returns:
"""
0.0, 1.0, 2.0, 3.0
"""
## We can also query what the closest time sample is to a frame:
print(layer.GetBracketingTimeSamplesForPath(attr_spec.path, 1003.3)) 
# Returns: (<Found sample>, <lower closest sample>, <upper closest sample>)
(True, 1003.0, 1004.0)
#// ANCHOR_END: animationRead

#// ANCHOR: animationTimeVarying
# !Danger! For value clipped (per frame loaded layers),
# this will look into all layers, which is quite expensive.
print(size_attr.GetNumTimeSamples())
# You should rather use:
# This does a check for time sample found > 2.
# So it stops looking for more samples after the second sample.
print(size_attr.ValueMightBeTimeVarying())
#// ANCHOR_END: animationTimeVarying

#// ANCHOR: animationSpecialValues
from pxr import Sdf, Usd
### High Level ###
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Cube")
size_attr = prim.GetAttribute("size")
for frame in range(1001, 1005):
    time_code = Usd.TimeCode(frame)
    size_attr.Set(frame - 1001, time_code)
## Value Blocking
size_attr.Set(1001, Sdf.ValueBlock())

### Low Level ###
from pxr import Sdf
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/bicycle")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.specifier = Sdf.SpecifierDef
prim_spec.typeName = "Cube"
attr_spec = Sdf.AttributeSpec(prim_spec, "size", Sdf.ValueTypeNames.Double)
for frame in range(1001, 1005):
    value = float(frame - 1001)
    layer.SetTimeSample(attr_spec.path, frame, value)

## Value Blocking
layer.SetTimeSample(attr_spec.path, 1001, Sdf.ValueBlock())
#// ANCHOR_END: animationSpecialValues

#// ANCHOR: animationFPS
from pxr import Sdf, Usd
### High Level ###
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Cube")
size_attr = prim.GetAttribute("size")
for frame in range(1001, 1005):
    time_code = Usd.TimeCode(frame)
    size_attr.Set(frame - 1001, time_code)
# FPS Metadata
stage.SetTimeCodesPerSecond(25)
stage.SetFramesPerSecond(25)
stage.SetStartTimeCode(1001)
stage.SetEndTimeCode(1005)

### Low Level ###
from pxr import Sdf
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/bicycle")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.specifier = Sdf.SpecifierDef
prim_spec.typeName = "Cube"
attr_spec = Sdf.AttributeSpec(prim_spec, "size", Sdf.ValueTypeNames.Double)
for frame in range(1001, 1005):
    value = float(frame - 1001)
    layer.SetTimeSample(attr_spec.path, frame, value)
# FPS Metadata
time_samples = Sdf.Layer.ListAllTimeSamples(layer)
layer.timeCodesPerSecond = 25
layer.framesPerSecond = 25
layer.startTimeCode = time_samples[0]
layer.endTimeCode = time_samples[-1]

###### Stage vs Layer TimeSample Scaling ######
from pxr import Sdf, Usd

layer_fps = 25
layer_identifier = "ref_layer.usd"
stage_fps = 24
stage_identifier = "root_layer.usd"
frame_start = 1001
frame_end = 1025

# Create layer
reference_layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/bicycle")
prim_spec = Sdf.CreatePrimInLayer(reference_layer, prim_path)
prim_spec.specifier = Sdf.SpecifierDef
prim_spec.typeName = "Cube"
attr_spec = Sdf.AttributeSpec(prim_spec, "size", Sdf.ValueTypeNames.Double)
for frame in range(frame_start, frame_end + 1):
    value = float(frame - frame_start) + 1
    # If we work correctly in seconds everything works as expected.
    reference_layer.SetTimeSample(attr_spec.path, frame * (layer_fps/stage_fps), value)
    # In VFX we often work frame based starting of at 1001 regardless of the FPS.
    # If we then load the 25 FPS in 24 FPS, USD applies the correct scaling, but we have
    # to apply the correct offset to our "custom" start frame.
    # reference_layer.SetTimeSample(attr_spec.path, frame, value)
# FPS Metadata
time_samples = Sdf.Layer.ListAllTimeSamples(reference_layer)
reference_layer.timeCodesPerSecond = layer_fps
reference_layer.framesPerSecond = layer_fps
reference_layer.startTimeCode = time_samples[0]
reference_layer.endTimeCode = time_samples[-1]
# reference_layer.Export(layer_identifier)

# Create stage
stage = Usd.Stage.CreateInMemory()
# If we work correctly in seconds everything works as expected.
reference_layer_offset = Sdf.LayerOffset(0, 1)
# In VFX we often work frame based starting of at 1001.
# If we then load the 25 FPS in 24 FPS, USD applies the correct scaling, but we have
# to apply the correct offset to our "custom" start frame.
# reference_layer_offset = Sdf.LayerOffset(frame_start * (stage_fps/layer_fps) - frame_start, 1)
reference = Sdf.Reference(reference_layer.identifier, "/bicycle", reference_layer_offset)
bicycle_prim_path = Sdf.Path("/bicycle")
bicycle_prim = stage.DefinePrim(bicycle_prim_path)
references_api = bicycle_prim.GetReferences()
references_api.AddReference(reference, position=Usd.ListPositionFrontOfAppendList)
# FPS Metadata (In Houdini we can't set this via python, use a 'configure layer' node instead.)
stage.SetTimeCodesPerSecond(stage_fps)
stage.SetFramesPerSecond(stage_fps)
stage.SetStartTimeCode(1001)
stage.SetEndTimeCode(1005)
# stage.Export(stage_identifier)
#// ANCHOR_END: animationFPS

#// ANCHOR: animationMotionVelocityAcceleration
import numpy as np

from pxr import Sdf, Usd, UsdGeom


MOTION_ATTRIBUTE_NAMES_BY_TYPE_NAME = {
    UsdGeom.Tokens.Mesh: (UsdGeom.Tokens.points, UsdGeom.Tokens.velocities, UsdGeom.Tokens.accelerations),
    UsdGeom.Tokens.Points: (UsdGeom.Tokens.points, UsdGeom.Tokens.velocities, UsdGeom.Tokens.accelerations),
    UsdGeom.Tokens.BasisCurves: (UsdGeom.Tokens.points, UsdGeom.Tokens.velocities, UsdGeom.Tokens.accelerations),
    UsdGeom.Tokens.PointInstancer: (UsdGeom.Tokens.positions, UsdGeom.Tokens.velocities, UsdGeom.Tokens.accelerations)
}
# To lookup schema specific names
# schema_registry = Usd.SchemaRegistry()
# schema = schema_registry.FindConcretePrimDefinition("Mesh")
# print(schema.GetPropertyNames())

def compute_time_derivative(layer, prim_spec, attr_name, ref_attr_name, time_code_inc, multiplier=1.0):
    ref_attr_spec = prim_spec.attributes.get(ref_attr_name)
    if not ref_attr_spec:
        return
    attr_spec = prim_spec.attributes.get(attr_name)
    if attr_spec:
        return
    time_codes = layer.ListTimeSamplesForPath(ref_attr_spec.path)
    if len(time_codes) == 1:
        return
    center_time_codes = {idx: t for idx, t in enumerate(time_codes) if int(t) == t}
    if not center_time_codes:
        return
    attr_spec = Sdf.AttributeSpec(prim_spec, attr_name, Sdf.ValueTypeNames.Vector3fArray)
    time_code_count = len(time_codes)
    for time_code_idx, time_code in center_time_codes.items():
        if time_code_idx == 0:
            time_code_prev = time_code
            time_code_next = time_codes[time_code_idx+1]
        elif time_code_idx == time_code_count - 1:
            time_code_prev = time_codes[time_code_idx-1]
            time_code_next = time_code
        else:
            time_code_prev = time_codes[time_code_idx-1]
            time_code_next = time_codes[time_code_idx+1]
        time_interval_scale = 1.0/(time_code_next - time_code_prev)
        ref_prev = layer.QueryTimeSample(ref_attr_spec.path, time_code_prev)
        ref_next = layer.QueryTimeSample(ref_attr_spec.path, time_code_next)
        if not ref_prev or not ref_next:
            continue
        if len(ref_prev) != len(ref_next):
            continue
        ref_prev = np.array(ref_prev)
        ref_next = np.array(ref_next)
        value = ((ref_next - ref_prev) * time_interval_scale) / (time_code_inc * 2.0)
        layer.SetTimeSample(attr_spec.path, time_code, value * multiplier)

def compute_velocities(layer, prim_spec, time_code_fps, multiplier=1.0):
    # Time Code
    time_code_inc = 1.0/time_code_fps
    prim_type_name = prim_spec.typeName
    if prim_type_name:
        # Defined prim type name
        attr_type_names = MOTION_ATTRIBUTE_NAMES_BY_TYPE_NAME.get(prim_type_name)
        if not attr_type_names:
            return
        pos_attr_name, vel_attr_name, _ = attr_type_names
    else:
        # Fallback
        pos_attr_name, vel_attr_name, _ = MOTION_ATTRIBUTE_NAMES_BY_TYPE_NAME[UsdGeom.Tokens.Mesh]
    pos_attr_spec = prim_spec.attributes.get(pos_attr_name)
    if not pos_attr_spec:
        return
    # Velocities
    compute_time_derivative(layer,
                            prim_spec,
                            vel_attr_name,
                            pos_attr_name,
                            time_code_inc, 
                            multiplier)
    
def compute_accelerations(layer, prim_spec, time_code_fps, multiplier=1.0):
    # Time Code
    time_code_inc = 1.0/time_code_fps
    prim_type_name = prim_spec.typeName
    if prim_type_name:
        # Defined prim type name
        attr_type_names = MOTION_ATTRIBUTE_NAMES_BY_TYPE_NAME.get(prim_type_name)
        if not attr_type_names:
            return
        _, vel_attr_name, accel_attr_name = attr_type_names
    else:
        # Fallback
        _, vel_attr_name, accel_attr_name = MOTION_ATTRIBUTE_NAMES_BY_TYPE_NAME[UsdGeom.Tokens.Mesh]
    vel_attr_spec = prim_spec.attributes.get(vel_attr_name)
    if not vel_attr_spec:
        return
    # Acceleration
    compute_time_derivative(layer,
                            prim_spec,
                            accel_attr_name,
                            vel_attr_name,
                            time_code_inc, 
                            multiplier)

### Run this on a layer with time samples ###
layer = Sdf.Layer.CreateAnonymous()
time_code_fps = layer.timeCodesPerSecond or 24.0
multiplier = 5

def traversal_kernel(path):
    if not path.IsPrimPath():
        return
    prim_spec = layer.GetPrimAtPath(path)
    compute_velocities(layer, prim_spec, time_code_fps, multiplier)
    compute_accelerations(layer, prim_spec, time_code_fps, multiplier)

with Sdf.ChangeBlock(): 
    layer.Traverse(layer.pseudoRoot.path, traversal_kernel)
#// ANCHOR_END: animationMotionVelocityAcceleration


#// ANCHOR: animationStitchCmdlineTool
...
openedFiles = [Sdf.Layer.FindOrOpen(fname) for fname in results.usdFiles]
... 
# the extra computation and fail more gracefully
try:
    for usdFile in openedFiles:
        UsdUtils.StitchLayers(outLayer, usdFile)
        outLayer.Save()
# if something in the authoring fails, remove the output file
except Exception as e:
    print('Failed to complete stitching, removing output file %s' % results.out)
    print(e)
    os.remove(results.out) 
...
#// ANCHOR_END: animationStitchCmdlineTool

#// ANCHOR: animationStitchClipsUtils
from pxr import Sdf, UsdUtils

clip_time_code_start = 1001
clip_time_code_end = 1003
clip_set_name = "cacheClip"
clip_prim_path = "/prim"
clip_interpolate_missing = False
time_sample_files = ["/cache/value_clips/time_sample.1001.usd",
                     "/cache/value_clips/time_sample.1002.usd",
                     "/cache/value_clips/time_sample.1003.usd"]
topology_file_path = "/cache/value_clips/topology.usd"
manifest_file_path = "/cache/value_clips/manifest.usd"
cache_file_path = "/cache/cache.usd"

# We can also use:
# topology_file_path = UsdUtils.GenerateClipTopologyName(cache_file_path)
# Returns: "/cache/cache.topology.usd"
# manifest_file_path = UsdUtils.GenerateClipManifestName(cache_file_path)
# Returns: "/cache/cache.manifest.usd"

topology_layer = Sdf.Layer.CreateNew(topology_file_path)
manifest_layer = Sdf.Layer.CreateNew(manifest_file_path)
cache_layer = Sdf.Layer.CreateNew(cache_file_path)

UsdUtils.StitchClipsTopology(topology_layer, time_sample_files)
UsdUtils.StitchClipsManifest(manifest_layer, topology_layer, 
                             time_sample_files, clip_prim_path)

UsdUtils.StitchClips(cache_layer,
                     time_sample_files,
                     clip_prim_path, 
                     clip_time_code_start,
                     clip_time_code_end,
                     clip_interpolate_missing,
                     clip_set_name)
cache_layer.Save()

# Result in "/cache/cache.usd"
"""
(
    framesPerSecond = 24
    metersPerUnit = 1
    subLayers = [
        @./value_clips/topology.usd@
    ]
    timeCodesPerSecond = 24
)

def "prim" (
    clips = {
        dictionary cacheClip = {
            double2[] active = [(1001, 0), (1002, 1), (1003, 2)] 
            asset[] assetPaths = [@./value_clips/time_sample.1001.usd@, @./value_clips/time_sample.1002.usd@, @./value_clips/time_sample.1003.usd@]
            asset manifestAssetPath = @./value_clips/manifest.usd@
            string primPath = "/prim"
            double2[] times = [(1001, 1001), (1002, 1002), (1003, 1003)]
        }
    }
    clipSets = ["cacheClip"]
)
{
}
"""

## API Overview
UsdUtils
# Generate topology and manifest files based USD preferred naming convention.
UsdUtils.GenerateClipTopologyName("/cache_file.usd") # Returns: "/cache_file.topology.usd"
UsdUtils.GenerateClipManifestName("/cache_file.usd") # Returns: "/cache_file.manifest.usd"
# Open layers
topology_layer = Sdf.Layer.CreateNew(topology_file_path)
manifest_layer = Sdf.Layer.CreateNew(manifest_file_path)
cache_layer = Sdf.Layer.CreateNew(cache_file_path)
## Create topology and manifest. This is the heavy part of creating value clips
## as it has to open all layers.
# Generate topology layer, this opens all the time sample layers and copies all
# attributes that don't have time samples and relationships into the topology_layer.
UsdUtils.StitchClipsTopology(topology_layer, time_sample_files)
# Generate manifest layer, this opens all the time sample layers and creates a 
# hierarchy without values of all attributes that have time samples. This is the inverse
# of the topology layer except it doesn't create values. The hierarchy is then used to
# determine what a clip should load as animation. 
UsdUtils.StitchClipsManifest(manifest_layer, topology_layer, 
                             time_sample_files, clip_prim_path)
# Generate cache layer, this creates the metadata that links to the above created files.
UsdUtils.StitchClips(cache_layer,
                     time_sample_files,
                     clip_prim_path, 
                     clip_time_code_start,
                     clip_time_code_end,
                     clip_interpolate_missing,
                     clip_set_name)
#// ANCHOR_END: animationStitchClipsUtils


#// ANCHOR: animationStitchClipsAPI
from pxr import Sdf, Usd, UsdUtils

time_sample_files = ["/cache/value_clips/time_sample.1001.usd",
                     "/cache/value_clips/time_sample.1002.usd",
                     "/cache/value_clips/time_sample.1003.usd"]
time_sample_asset_paths = Sdf.AssetPathArray(time_sample_files)
topology_file_path = "/cache/value_clips/topology.usd"
manifest_file_path = "/cache/value_clips/manifest.usd"
cache_file_path = "/cache/cache.usd"

topology_layer = Sdf.Layer.CreateNew(topology_file_path)
manifest_layer = Sdf.Layer.CreateNew(manifest_file_path)
cache_layer = Sdf.Layer.CreateNew(cache_file_path)

UsdUtils.StitchClipsTopology(topology_layer, time_sample_files)
UsdUtils.StitchClipsManifest(manifest_layer, topology_layer, 
                             time_sample_files, clip_prim_path)

clip_set_name = "cacheClip"
clip_prim_path = "/prim"
clip_interpolate_missing = False

# For simplicity in this example we already know where the asset roots are.
# If you need to check where they are, you can traverse the topology layer,
# as it contains the full hierarchy of the per frame files.
prim = stage.DefinePrim("/valueClippedPrim", "Xform")
# The clips API is a small wrapper around setting metadata fields. 
clips_API = Usd.ClipsAPI(prim)
# Most function signatures work via the following args:
# clips_API.<method>(<methodArg>, <clipSetName>)
# We'll only be looking at non-template value clips related methods here.
## We have Get<MethodName>/Set<MethodName> for all metadata keys:
# clips_API.Get/SetClipPrimPath 
# clips_API.Get/SetClipAssetPaths
# clips_API.Get/SetClipManifestAssetPath
# clips_API.Get/SetClipActive
# clips_API.Get/SetClipTimes 
# clips_API.Get/SetInterpolateMissingClipValues
## To get/set the whole clips metadata dict, we can run:
# clips_API.Get/SetClips()
## To get/set what clips are active:
# clips_API.Get/SetClipSets

## Convenience methods for generating a manifest based on the
# clips set by clips_API.SetClipAssetPaths
# clips_API.GenerateClipManifest
## Or from a user specified list. This is similar to UsdUtils.StitchClipsManifest()
# clips_API.GenerateClipManifestFromLayers

## Get the resolved asset paths in 'assetPaths' metadata.
# clips_API.ComputeClipAssetPaths

prim = stage.DefinePrim("/valueClippedPrim", "Xform")
clips_API = Usd.ClipsAPI(prim)
clips_API.SetClipPrimPath(clip_prim_path, clip_set_name)
clips_API.SetClipAssetPaths(time_sample_asset_paths, clip_set_name)
clips_API.SetClipActive([(1001, 0), (1002, 1), (1003, 2)], clip_set_name)
clips_API.SetClipTimes([(1001, 1001), (1002, 1001), (1003, 1001)], clip_set_name)
clips_API.SetInterpolateMissingClipValues(clip_interpolate_missing, clip_set_name)
# We can also print all clip metadata
print(clips_API.GetClips())
# Enable the clip
clip_sets_active = Sdf.StringListOp.CreateExplicit([clip_set_name])
clips_API.SetClipSets(clip_sets_active)
#Returns:
"""
{'cacheClip': 
    {
        'primPath': '/prim',
        'interpolateMissingClipValues': False, 
        'active': Vt.Vec2dArray(3, (Gf.Vec2d(1001.0, 0.0), Gf.Vec2d(1002.0, 1.0), Gf.Vec2d(1003.0, 2.0))),
        'assetPaths': Sdf.AssetPathArray(3, (Sdf.AssetPath('/cache/value_clips/time_sample.1001.usd'),
                                            Sdf.AssetPath('/cache/value_clips/time_sample.1002.usd'),
                                            Sdf.AssetPath('/cache/value_clips/time_sample.1003.usd'))),
        'times': Vt.Vec2dArray(3, (Gf.Vec2d(1001.0, 1001.0), Gf.Vec2d(1002.0, 1001.0), Gf.Vec2d(1003.0, 1001.0)))
    }
}
"""
#// ANCHOR_END: animationStitchClipsAPI


#// ANCHOR: schemasOverview
### Typed Schemas ###
# From type name
prim_type_name = prim.GetTypeName()
prim_typed_schema = Usd.SchemaRegistry.GetTypeFromName(prim_type_name).pythonClass(prim)
# From prim type info
prim_typed_schema = prim.GetPrimTypeInfo().GetSchemaType().pythonClass(prim)

### API Schemas ###
# Non-Applied API Schemas
non_applied_api_schema = Usd.ModelAPI(prim)
# Applied API Schemas
applied_api_schema = UsdGeom.MotionAPI.Apply(prim)
#// ANCHOR_END: schemasOverview

#// ANCHOR: schemasTyped
###### Typed Schemas ######
### High Level ###
# Has: 'IsA',
# Get: 'GetTypeName'
# Set: 'SetTypeName'
# Clear: 'ClearTypeName'
from pxr import Sdf, Usd, UsdGeom
stage = Usd.Stage.CreateInMemory()

# Define prim via stage
prim_path = Sdf.Path("/bicycleA")
prim = stage.DefinePrim(prim_path, "Cube")
# Define prim via typed schema
prim_path = Sdf.Path("/bicycleB")
prim_typed_schema = UsdGeom.Cube.Define(stage, prim_path)
# Returns the schema class object, so we have to get the prim
prim = prim_typed_schema.GetPrim()
# Since the "Cube" schema is a subclass of the
# non.concrete typed UsdGeom.Boundable schema, we can check:
print(prim.IsA(UsdGeom.Cube)) # Returns: True
print(prim.IsA(UsdGeom.Boundable)) # Returns: True
# To remove the type, we can call:
# prim.ClearTypeName()
# To access the schema class methods, we give our prim to the 
# class constructor:
prim_typed_schema = UsdGeom.Cube(prim)
# The typed Cube schema for example has a Get/Set method for the schema's size attribute.
prim_typed_schema.GetSizeAttr().Set(5)
# Or we let Usd gives us the Python class
prim_typed_schema = prim.GetPrimTypeInfo().GetSchemaType().pythonClass(prim)
prim_typed_schema.GetSizeAttr().Set(10)
# Or we get it from the type name
prim_typed_schema = Usd.SchemaRegistry.GetTypeFromName(prim.GetTypeName()).pythonClass(prim)

### Low Level ###
# To set typed schemas via the low level API, we just 
# need to set the PrimSpec.typeName = "<SchemaName>"
from pxr import Sdf
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/bicycle")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.typeName = "Cube"
#// ANCHOR_END: schemasTyped


#// ANCHOR: schemasAPI
###### API Schemas ######
### High Level ###
# Has: 'HasAPI', 'CanApplyAPI'
# Get: 'GetAppliedSchemas'
# Set: 'AddAppliedSchema', 'ApplyAPI'
# Clear: 'RemoveAppliedSchema', 'RemoveAPI'
from pxr import Sdf, Usd, UsdGeom
stage = Usd.Stage.CreateInMemory()

### Applied Schemas ###
# Define prim via stage
prim_path = Sdf.Path("/bicycleA")
prim = stage.DefinePrim(prim_path, "Cube")
# Check if it can be applied
print(UsdGeom.MotionAPI.CanApply(prim)) # Returns True
# Apply API schema (in active layer),
prim.ApplyAPI("GeomModelAPI") # Returns: True, older USD versions: prim.ApplyAPI("UsdGeomModelAPI")
# Add applied schema
# This does not check if the schema actually exists, 
# you have to use this for codeless schemas.
prim.AddAppliedSchema("SkelBindingAPI") # Returns: True #
# Apply and get the schema class (preferred usage)
applied_api_schema = UsdGeom.MotionAPI.Apply(prim)
# Remove applied schema (in active layer)
# prim.RemoveAppliedSchema("SkelBindingAPI")
# prim.RemoveAPI("GeomModelAPI")
# For multi-apply schemas, we can feed in our custom name,
# for example for collections it drives the collection name.
prim.ApplyAPI("UsdCollectionAPI", "myCoolCollectionName")
applied_multi_api_schema = Usd.CollectionAPI.Apply(prim, "myCoolCollectionName")
### Non-Applied Schemas ###
# Non-Applied schemas do not have an `Apply` method
# (who would have guessed that?)
non_applied_api_schema = Usd.ModelAPI(prim)

### Low Level ###
# To set applied API schemas via the low level API, we just 
# need to set the `apiSchemas` key to a Token Listeditable Op.
from pxr import Sdf
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/bicycle")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
schemas = Sdf.TokenListOp.Create(
    prependedItems=["SkelBindingAPI", "UsdGeomModelAPI"]
)
prim_spec.SetInfo("apiSchemas", schemas)
# We don't have nice access the the schema class as in the high level API
#// ANCHOR_END: schemasAPI


#// ANCHOR: schemasPluginRegistry
from pxr import Plug, Tf, Usd
registry = Plug.Registry()
print(">>>>>", "Typed Schemas")
for type_name in registry.GetAllDerivedTypes(Usd.Typed):
    print(type_name)
print(">>>>>", "API Schemas")
for type_name in registry.GetAllDerivedTypes(Usd.APISchemaBase):
    print(type_name)

# For example to lookup where the "Cube" type is registered from,
# we can run:
print(">>>>>", "Cube Schema Plugin Source")
plugin = registry.GetPluginForType(Tf.Type.FindByName("UsdGeomCube"))
print(plugin.name)
print(plugin.path)
print(plugin.resourcePath)
print(plugin.metadata)
#// ANCHOR_END: schemasPluginRegistry

#// ANCHOR: schemasRegistry
from pxr import Plug, Sdf, Tf, Usd
registry = Usd.SchemaRegistry()

## Get Tf.Type registry entry (which allows us to get the Python class)
## The result can also be used to run IsA checks for typed schemas.
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycleA")
prim = stage.DefinePrim(prim_path, "Cube")
print(prim.IsA(registry.GetTypeFromName("UsdGeomImageable"))) # Returns: True
print(prim.IsA(registry.GetTypeFromName("UsdGeomImageable").pythonClass)) # Returns: True


# GetTypeFromName allows prim type names and the Tf.Type.typeName.
print(registry.GetTypeFromName("UsdGeomCube"))      # Returns: Tf.Type("UsdGeomCube")
print(registry.GetTypeFromName("Cube"))             # Returns: Tf.Type("UsdGeomCube")
# For typed schemas we can also use:
print(registry.GetTypeFromSchemaTypeName("Imageable")) # Returns: Tf.Type('UsdGeomImageable') -> Tf.Type.typeName gives us 'UsdGeomImageable'
print(registry.GetTypeFromSchemaTypeName("Cube"))      # Returns: Tf.Type("UsdGeomCube") -> Tf.Type.typeName gives us 'UsdGeomCube'
print(registry.GetSchemaTypeName("UsdGeomImageable"))  # Returns: "Imageable"
print(registry.GetSchemaTypeName("UsdGeomCube"))       # Returns: "Cube"
# For concrete typed schemas:
print(registry.GetConcreteSchemaTypeName("UsdGeomCube"))  # Returns: "Cube"
print(registry.GetConcreteTypeFromSchemaTypeName("Cube")) # Returns: Tf.Type("UsdGeomCube")
# For API schemas:
print(registry.GetAPISchemaTypeName("UsdSkelBindingAPI"))  # Returns: "SkelBindingAPI"
print(registry.GetAPITypeFromSchemaTypeName("SkelBindingAPI")) # Returns: Tf.Type("UsdSkelBindingAPI")
#// ANCHOR_END: schemasRegistry


#// ANCHOR: schemasRegistryToPrimDefinition
from pxr import Usd
registry = Usd.SchemaRegistry()
## Useful inspection lookups ##
# Find API schemas. This uses the `Schema Type Name` syntax:
cube_def = registry.FindConcretePrimDefinition("Cube")
print(cube_def.GetPropertyNames())
# Returns:
"""
['doubleSided', 'extent', 'orientation', 'primvars:displayColor', 
 'primvars:displayOpacity', 'purpose', 'size', 'visibility',
 'xformOpOrder', 'proxyPrim']
"""
skel_bind_def = registry.FindAppliedAPIPrimDefinition("SkelBindingAPI")
print(skel_bind_def.GetPropertyNames())
# Returns:
"""
['primvars:skel:geomBindTransform', 'primvars:skel:jointIndices',
 'primvars:skel:jointWeights', 'skel:blendShapes', 'skel:joints', 
 'skel:animationSource', 'skel:blendShapeTargets', 'skel:skeleton']
"""
#// ANCHOR_END: schemasRegistryToPrimDefinition

#// ANCHOR: schemasKind
from pxr import Plug, Sdf, Tf, Usd
### Check schema types ###
registry = Usd.SchemaRegistry()
## Typed Schemas ##
print(registry.IsTyped(UsdGeom.Cube))         # Returns: True
print(registry.IsTyped(UsdGeom.Imageable))    # Returns: True
print(registry.IsAbstract(UsdGeom.Imageable)) # Returns: True
print(registry.IsAbstract(UsdGeom.Cube))      # Returns: False
print(registry.IsConcrete(UsdGeom.Imageable)) # Returns: False
print(registry.IsConcrete(UsdGeom.Cube))      # Returns: True
# Also works with type name strings
print(registry.IsTyped("UsdGeomImageable"))   # Returns: True
print(registry.IsTyped("UsdGeomCube"))        # Returns: True
## API Schemas ##
print(registry.IsAppliedAPISchema("SkelBindingAPI"))      # Returns: True
print(registry.IsMultipleApplyAPISchema("CollectionAPI")) # Returns: True
## We can also ask by schema type name
print(registry.GetSchemaKind("Cube")) # Returns: pxr.Usd.SchemaKind.ConcreteTyped
print(registry.GetSchemaKind("Imageable")) # Returns: pxr.Usd.SchemaKind.AbstractTyped
#// ANCHOR_END: schemasKind


#// ANCHOR: schemasPluginCodelessTest
from pxr import Usd, Sdf
### High Level ###
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/myCoolCustomPrim")
prim = stage.DefinePrim(prim_path, "ComplexPrim")
prim.AddAppliedSchema("ParamsAPI") # Returns: True
# AddAppliedSchema does not check if the schema actually exists, 
# you have to use this for codeless schemas.
### Low Level ###
from pxr import Sdf
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/myCoolCustomPrim")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.typeName = "ComplexPrim"
schemas = Sdf.TokenListOp.Create(
    prependedItems=["ParamsAPI"]
)
prim_spec.SetInfo("apiSchemas", schemas)
#// ANCHOR_END: schemasPluginCodelessTest


#// ANCHOR: schemasPluginCompiledTest
from pxr import Usd, Sdf
### High Level ###
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/myCoolCustomPrim")
prim = stage.DefinePrim(prim_path, "ComplexPrim")
prim.AddAppliedSchema("ParamsAPI") # Returns: True
# AddAppliedSchema does not check if the schema actually exists, 
# you have to use this for codeless schemas.
### Low Level ###
from pxr import Sdf
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/myCoolCustomPrim")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.typeName = "ComplexPrim"
schemas = Sdf.TokenListOp.Create(
    prependedItems=["ParamsAPI"]
)
prim_spec.SetInfo("apiSchemas", schemas)

### Python Classes ###
stage = Usd.Stage.CreateInMemory()
prim = stage.GetPrimAtPath("/prim")
print(prim.GetTypeName())
print(prim.GetPrimTypeInfo().GetSchemaType().pythonClass)

# Schema Classes
import UsdExampleSchemas as schemas
print(schemas.Complex)
print(schemas.ParamsAPI)
print(schemas.Simple)
print(schemas.Tokens)
# Schema Get/Set/Create methods
schemas.Complex.CreateIntAttrAttr()
#// ANCHOR_END: schemasPluginCompiledTest


#// ANCHOR: metadataPlugin
from pxr import Usd, Sdf

# Here we test it in an example stage:
stage = Usd.Stage.CreateInMemory()
layer = stage.GetEditTarget().GetLayer()
prim = stage.DefinePrim("/prim")
prim_spec = layer.GetPrimAtPath(prim.GetPath())

# To see all the globally registered fields for the metadata on prim specs:
print(Sdf.PrimSpec.GetMetaDataInfoKeys(prim_spec))

# Float field
metadata_name = "usdSurvivalGuideFloat"
print(prim.GetMetadata(metadata_name)) # Returns: None
print(prim_spec.GetFallbackForInfo(metadata_name)) # Returns: 5
prim.SetMetadata(metadata_name, 10)
print(prim.GetMetadata(metadata_name)) # Returns: 10
# String List Editable Op
metadata_name = "usdSurvivalGuideAssetDependencies"
string_list_op = Sdf.StringListOp.Create(appendedItems=["motor.usd", "tire.usd"])
print(prim.GetMetadata(metadata_name))
prim.SetMetadata(metadata_name, string_list_op)
print(prim.GetMetadata(metadata_name))
#// ANCHOR_END: metadataPlugin


#// ANCHOR: propertyOverview
# Methods & Attributes of interest:
# 'IsDefined', 'IsAuthored'
# 'FlattenTo'
# 'GetPropertyStack'
from pxr import Usd, Sdf
### High Level ###
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Cube")
# Check if the attribute defined
attr = prim.CreateAttribute("height", Sdf.ValueTypeNames.Double)
print(attr.IsDefined()) # Returns: True
attr = prim.GetAttribute("someRandomName")
print(attr.IsDefined())
if not attr:
    prim.CreateAttribute("someRandomName", Sdf.ValueTypeNames.String)
# Check if the attribute has any written values in any layer
print(attr.IsAuthored()) # Returns: True
attr.Set("debugString")
# Flatten the attribute to another prim (with optionally a different name)
# This is quite usefull when you need to copy a specific attribute only instead
# of a certain prim.
prim_path = Sdf.Path("/box")
prim = stage.DefinePrim(prim_path, "Cube")
attr.FlattenTo(prim, "someNewName")
# Inspect the property value source layer stack.
# Note the method signature takes a time code as an input. If you supply a default time code
# value clips will be stripped from the result.
time_code = Usd.TimeCode(1001)
print(attr.GetPropertyStack(time_code))
### Low Level ###
# The low level API does not offer any "extras" worthy of noting.
#// ANCHOR_END: propertyOverview

#// ANCHOR: attributeInterpolation
from pxr import Sdf, Usd, UsdGeom
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Xform")
attr = prim.CreateAttribute("tire:size", Sdf.ValueTypeNames.Float)
attr.Set(10)
attr.SetMetadata("interpolation", UsdGeom.Tokens.constant)

### Low Level ###
from pxr import Sdf, UsdGeom
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/bicycle")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.specifier = Sdf.SpecifierDef
prim_spec.typeName = "Xform"
attr_spec = Sdf.AttributeSpec(prim_spec, "tire:size", Sdf.ValueTypeNames.Double)
attr_spec.default = 10
attr_spec.interpolation = UsdGeom.Tokens.constant
# Or
attr_spec.SetInfo("interpolation", UsdGeom.Tokens.constant)
#// ANCHOR_END: attributeInterpolation

#// ANCHOR: attributeDataTypeRole
from pxr import Gf, Sdf, Usd
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Xform")
# When we create attributes, we have to specify the data type/role via a Sdf.ValueTypeName
attr = prim.CreateAttribute("tire:size", Sdf.ValueTypeNames.Float)
# We can then set the attribute to a value of that type.
# Python handles the casting to the correct precision automatically for base data types.
attr.Set(10)
# For attributes the `typeName` metadata specifies the data type/role.
print(attr.GetTypeName()) # Returns: Sdf.ValueTypeNames.Float
# Non-base data types
attr = prim.CreateAttribute("someArray", Sdf.ValueTypeNames.Half3Array)
attr.Set([Gf.Vec3h()] * 3)
attr = prim.CreateAttribute("someAssetPathArray", Sdf.ValueTypeNames.AssetArray)
attr.Set(Sdf.AssetPathArray(["testA.usd", "testB.usd"]))

### Low Level ###
from pxr import Gf, Sdf
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/bicycle")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.specifier = Sdf.SpecifierDef
prim_spec.typeName = "Xform"
attr_spec = Sdf.AttributeSpec(prim_spec, "tire:size", Sdf.ValueTypeNames.Double)
# We can then set the attribute to a value of that type.
# Python handles the casting to the correct precision automatically for base data types.
attr_spec.default = 10
# For attributes the `typeName` metadata specifies the data type/role.
print(attr_spec.typeName) # Returns: Sdf.ValueTypeNames.Float
# Non-base data types
attr_spec = Sdf.AttributeSpec(prim_spec, "someArray", Sdf.ValueTypeNames.Half3Array)
attr_spec.default = ([Gf.Vec3h()] * 3)
attr_spec = Sdf.AttributeSpec(prim_spec, "someAssetPathArray", Sdf.ValueTypeNames.AssetArray)
attr_spec.default = Sdf.AssetPathArray(["testA.usd", "testB.usd"])
# Creating an attribute spec with the same data type as an existing attribute (spec)
# is as easy as passing in the type name from the existing attribute (spec)
same_type_attr_spec = Sdf.AttributeSpec(prim_spec, "tire:radius", attr.GetTypeName())
# Or
same_type_attr_spec = Sdf.AttributeSpec(prim_spec, "tire:radius", attr_spec.typeName)
#// ANCHOR_END: attributeDataTypeRole


#// ANCHOR: animationDefaultTimeSampleBlock
from pxr import Sdf, Usd
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Cube")
size_attr = prim.GetAttribute("size")
## Set default value
time_code = Usd.TimeCode.Default()
size_attr.Set(10, time_code)
# Or:
size_attr.Set(10) # The default is to set `default` (non-per-frame) data.
## Set per frame value
for frame in range(1001, 1005):
    time_code = Usd.TimeCode(frame)
    size_attr.Set(frame, time_code)
# Or
# As with Sdf.Path implicit casting from strings in a lot of places in the USD API,
# the time code is implicitly casted from a Python float. 
# It is recommended to do the above, to be more future proof of 
# potentially encoding time unit based samples.
for frame in range(1001, 1005):
    size_attr.Set(frame, frame)
## Block the value. This makes the attribute look to USD as if no value was written.
# For attributes from schemas with default values, this will make it fallback to the default value.
height_attr = prim.CreateAttribute("height", Sdf.ValueTypeNames.Float)
height_attr.Set(Sdf.ValueBlock())
#// ANCHOR_END: animationDefaultTimeSampleBlock


#// ANCHOR: attributeReauthor
from pxr import Sdf, Usd
# Spawn reference data
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/bicycle")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.specifier = Sdf.SpecifierDef
prim_spec.typeName = "Cube"
attr_spec = Sdf.AttributeSpec(prim_spec, "size", Sdf.ValueTypeNames.Double)
for frame in range(1001, 1010):
    value = float(frame - 1001)
    layer.SetTimeSample(attr_spec.path, frame, value)
# Reference data
stage = Usd.Stage.CreateInMemory()
ref = Sdf.Reference(layer.identifier, "/bicycle")
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path)
ref_api = prim.GetReferences()
ref_api.AddReference(ref)

# Now if we try to read and write the data at the same time,
# we overwrite the (layer composition) value source. In non USD speak:
# We change the layer the data is coming from. Therefore we won't see
# the original data after setting the first time sample.
size_attr = prim.GetAttribute("size")
for time_sample in size_attr.GetTimeSamples():
    size_attr_value = size_attr.Get(time_sample)
    print(time_sample, size_attr_value)
    size_attr.Set(size_attr_value, time_sample)
# Prints:
"""
1001.0 0.0
1002.0 0.0
1003.0 0.0
1004.0 0.0
1005.0 0.0
1006.0 0.0
1007.0 0.0
1008.0 0.0
1009.0 0.0
"""

# Let's undo the previous edit.
prim.RemoveProperty("size") # Removes the local layer attribute spec
# Collect data first ()
data = {}
size_attr = prim.GetAttribute("size")
for time_sample in size_attr.GetTimeSamples():
    size_attr_value = size_attr.Get(time_sample)
    print(time_sample, size_attr_value)
    data[time_sample] = size_attr_value
# Prints:
"""
1001.0 0.0
1002.0 1.0
1003.0 2.0
1004.0 3.0
1005.0 4.0
1006.0 5.0
1007.0 6.0
1008.0 7.0
1009.0 8.0
"""
# Then write it
for time_sample, value in data.items():
    size_attr_value = size_attr.Get(time_sample)
    size_attr.Set(value + 10, time_sample)
#// ANCHOR_END: attributeReauthor


#// ANCHOR: attributeReauthorPerLayer
from pxr import Sdf, Usd
# Spawn example data, this would be a file on disk
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/bicycle")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.specifier = Sdf.SpecifierDef
prim_spec.typeName = "Cube"
attr_spec = Sdf.AttributeSpec(prim_spec, "size", Sdf.ValueTypeNames.Double)
for frame in range(1001, 1010):
    value = float(frame - 1001)
    layer.SetTimeSample(attr_spec.path, frame, value)

# Edit content
layer_identifiers = [layer.identifier]
for layer_identifier in layer_identifiers:
    prim_path = Sdf.Path("/bicycle")
    ### High Level ###
    stage = Usd.Stage.Open(layer_identifier)
    prim = stage.GetPrimAtPath(prim_path)
    size_attr = prim.GetAttribute("size")
    for frame in size_attr.GetTimeSamples():
        size_attr_value = size_attr.Get(frame)
        # .Set() takes args in the .Set(<value>, <frame>) format
        size_attr.Set(size_attr_value + 125, frame)
    ### Low Level ###
    # Note that this edits the same layer as the stage above.
    layer = Sdf.Layer.FindOrOpen(layer_identifier)
    prim_spec = layer.GetPrimAtPath(prim_path)
    attr_spec = prim_spec.attributes["size"]
    for frame in layer.ListTimeSamplesForPath(attr_spec.path):
        value = layer.QueryTimeSample(attr_spec.path, frame)
        layer.SetTimeSample(attr_spec.path, frame, value + 125)
#// ANCHOR_END: attributeReauthorPerLayer


#// ANCHOR: attributeReauthorTimeSampleToStatic
from pxr import Sdf, Usd
# Spawn example data, this would be a file on disk
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/bicycle")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.specifier = Sdf.SpecifierDef
prim_spec.typeName = "Cube"
attr_spec = Sdf.AttributeSpec(prim_spec, "size", Sdf.ValueTypeNames.Double)
for frame in range(1001, 1010):
    value = float(frame - 1001)
    layer.SetTimeSample(attr_spec.path, frame, value)
# Reference data
stage = Usd.Stage.CreateInMemory()
ref = Sdf.Reference(layer.identifier, "/bicycle")
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path)
ref_api = prim.GetReferences()
ref_api.AddReference(ref)

# Freeze content
freeze_frame = 1001
attrs = []
for prim in stage.Traverse():
    ### High Level ###
    for attr in prim.GetAuthoredAttributes():      
        # attr.Set(attr.Get(freeze_frame))
        ### Low Level ###
        attrs.append(attr)

### Low Level ###
active_layer = stage.GetEditTarget().GetLayer()
with Sdf.ChangeBlock():
    for attr in attrs:
        attr_spec =  active_layer.GetAttributeAtPath(attr.GetPath())
        if not attr_spec:
            prim_path = attr.GetPrim().GetPath()
            prim_spec = active_layer.GetPrimAtPath(prim_path)
            if not prim_spec:
                prim_spec = Sdf.CreatePrimInLayer(active_layer, prim_path)
            attr_spec = Sdf.AttributeSpec(prim_spec, attr.GetName(),attr.GetTypeName())
        attr_spec.default = attr.Get(freeze_frame)
#// ANCHOR_END: attributeReauthorTimeSampleToStatic


#// ANCHOR: attributePrimvarAPI
## UsdGeom.PrimvarsAPI(prim)
# Has: 'HasPrimvar',
# Get: 'GetAuthoredPrimvars', 'GetPrimvar',
#      'GetPrimvars', 'GetPrimvarsWithAuthoredValues', 'GetPrimvarsWithValues', 
# Set: 'CreatePrimvar', 'CreateIndexedPrimvar', 'CreateNonIndexedPrimvar', 
# Clear: 'RemovePrimvar', 'BlockPrimvar',
## UsdGeom.Primvar(attribute)
# This is the same as Usd.Attribute, but exposes extra
# primvar related methods, mainly:
# Has/Is: 'IsIndexed', 'IsPrimvar'
# Get: 'GetPrimvarName', 'GetIndicesAttr', 'GetIndices'
# Set: 'CreateIndicesAttr', 'ComputeFlattened'
# Remove: 'BlockIndices'
from pxr import Sdf, Usd, UsdGeom, Vt
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Cube")
size_attr = prim.GetAttribute("size")
# Manually define primvar
attr = prim.CreateAttribute("width", Sdf.ValueTypeNames.Float)
print(UsdGeom.Primvar.IsPrimvar(attr)) # Returns: False
attr = prim.CreateAttribute("primvars:depth", Sdf.ValueTypeNames.Float)
print(UsdGeom.Primvar.IsPrimvar(attr)) # Returns: True
# Use primvar API
# This returns an instance of UsdGeom.Primvar
primvar_api = UsdGeom.PrimvarsAPI(prim)
primvar = primvar_api.CreatePrimvar("height", Sdf.ValueTypeNames.StringArray)
print(UsdGeom.Primvar.IsPrimvar(primvar))  # Returns: True
print(primvar.GetPrimvarName()) # Returns: "height"
primvar.Set(["testA", "testB"])
print(primvar.ComputeFlattened()) # Returns: ["testA", "testB"]
# In this case flattening does nothing, because it is not indexed.
# This will fail as it is expected to create indices on primvar creation.
primvar_indices = primvar.CreateIndicesAttr()
# So let's do that
values = ["testA", "testB"]
primvar = primvar_api.CreateIndexedPrimvar("height",
                                           Sdf.ValueTypeNames.StringArray,
                                           Vt.StringArray(values),
                                           Vt.IntArray([0,0,0, 1,1, 0]),
                                           UsdGeom.Tokens.constant, 
                                           time=1001)
print(primvar.GetName(), primvar.GetIndicesAttr().GetName(), primvar.IsIndexed())
# Returns: primvars:height primvars:height:indices True
print(primvar.ComputeFlattened())
# Returns:
# ["testA", "testA", "testA", "testB", "testB", "testA"]
#// ANCHOR_END: attributePrimvarAPI


#// ANCHOR: attributePrimvarInherited
## UsdGeom.PrimvarsAPI(prim)
# To detect inherited primvars, the primvars API offers helper methods:
# 'HasPossiblyInheritedPrimvar', 
# 'FindIncrementallyInheritablePrimvars', 
# 'FindInheritablePrimvars', 
# 'FindPrimvarWithInheritance', 
# 'FindPrimvarsWithInheritance',

from pxr import Sdf, Usd, UsdGeom
stage = Usd.Stage.CreateInMemory()
bicycle_prim = stage.DefinePrim(Sdf.Path("/set/garage/bicycle"), "Cube")
car_prim = stage.DefinePrim(Sdf.Path("/set/garage/car"), "Cube")
set_prim = stage.GetPrimAtPath("/set")
garage_prim = stage.GetPrimAtPath("/set/garage")
tractor_prim = stage.DefinePrim(Sdf.Path("/set/yard/tractor"), "Cube")
"""Hierarchy
/set
/set/garage
/set/garage/bicycle
/set/garage/car
/set/yard
/set/yard/tractor
"""

# Setup hierarchy primvars
primvar_api = UsdGeom.PrimvarsAPI(set_prim)
size_primvar = primvar_api.CreatePrimvar("size", Sdf.ValueTypeNames.Float)
size_primvar.Set(10)
primvar_api = UsdGeom.PrimvarsAPI(garage_prim)
size_primvar = primvar_api.CreatePrimvar("size", Sdf.ValueTypeNames.Float)
size_primvar.Set(5)
size_primvar = primvar_api.CreatePrimvar("point_scale", Sdf.ValueTypeNames.Float)
size_primvar.Set(9000)
primvar_api = UsdGeom.PrimvarsAPI(bicycle_prim)
size_primvar = primvar_api.CreatePrimvar("size", Sdf.ValueTypeNames.Float)
size_primvar.Set(2.5)

# Get (non-inherited) primvars on prim
primvar_api = UsdGeom.PrimvarsAPI(bicycle_prim)
print([p.GetAttr().GetPath() for p in primvar_api.GetPrimvars()])
# Returns:
# [Sdf.Path('/set/garage/bicycle.primvars:displayColor'),
#  Sdf.Path('/set/garage/bicycle.primvars:displayOpacity'),
#  Sdf.Path('/set/garage/bicycle.primvars:size')]
# Check for inherited primvar on prim
primvar_api = UsdGeom.PrimvarsAPI(bicycle_prim)
print(primvar_api.FindPrimvarWithInheritance("test").IsDefined())
# Returns: False

# Get inherited primvar
# This is expensive to compute, as prim prim where you call this,
# the ancestors have to be checked.
primvar_api = UsdGeom.PrimvarsAPI(bicycle_prim)
print([p.GetAttr().GetPath() for p in primvar_api.FindInheritablePrimvars()])
# Returns: [Sdf.Path('/set/garage/bicycle.primvars:size'), Sdf.Path('/set/garage.primvars:point_scale')]

# Instead we should populate our own stack:
# This is fast to compute!
print("----")
primvars_current = []
for prim in stage.Traverse():
    primvar_api = UsdGeom.PrimvarsAPI(prim)
    primvars_current = primvar_api.FindIncrementallyInheritablePrimvars(primvars_current)
    print(prim.GetPath(), [p.GetAttr().GetPath().pathString for p in primvars_current])
# Returns:
"""
/set ['/set.primvars:size']
/set/garage ['/set/garage.primvars:size', '/set/garage.primvars:point_scale']
/set/garage/bicycle ['/set/garage/bicycle.primvars:size', '/set/garage.primvars:point_scale']
/set/garage/car []
/set/yard []
/set/yard/traktor []
"""
print("----")
# This is wrong if you might have noticed!
# We should be seeing our '/set.primvars:size' primvar on the yard prims to!
# If we look at the docs, we see the intended use: 
# FindIncrementallyInheritablePrimvars returns a new list if it gets re-populated.
# So the solution is to track the lists with pre/post visits.
primvar_stack = [[]]
iterator = iter(Usd.PrimRange.PreAndPostVisit(stage.GetPseudoRoot()))
for prim in iterator:
    primvar_api = UsdGeom.PrimvarsAPI(prim)
    if not iterator.IsPostVisit():
        before = hex(id(primvar_stack[-1]))
        primvars_iter = primvar_api.FindIncrementallyInheritablePrimvars(primvar_stack[-1])
        primvar_stack.append(primvars_iter)
        print(before, hex(id(primvars_iter)), prim.GetPath(), [p.GetAttr().GetPath().pathString for p in primvars_iter], len(primvar_stack))
    else:
        primvar_stack.pop(-1)
# This also doesn't work as it seems to clear the memory address for some reason (Or do I have a logic error?)
# Let's write it ourselves:
primvar_stack = [{}]
iterator = iter(Usd.PrimRange.PreAndPostVisit(stage.GetPseudoRoot()))
for prim in iterator:
    primvar_api = UsdGeom.PrimvarsAPI(prim)
    if not iterator.IsPostVisit():
        before_hash = hex(id(primvar_stack[-1]))
        parent_primvars = primvar_stack[-1]
        authored_primvars = {p.GetPrimvarName(): p for p in primvar_api.GetPrimvarsWithAuthoredValues()} 
        if authored_primvars and parent_primvars:
            combined_primvars = {name: p for name, p in parent_primvars.items()}
            combined_primvars.update(authored_primvars)
            primvar_stack.append(combined_primvars)
        elif authored_primvars:
            primvar_stack.append(authored_primvars)
        else:
            primvar_stack.append(parent_primvars)
        after_hash = hex(id(primvar_stack[-1]))
        print(before_hash, after_hash, prim.GetPath(), [p.GetAttr().GetPath().pathString for p in primvar_stack[-1].values()], len(primvar_stack))
    else:
        primvar_stack.pop(-1)
# Returns:
""" This works :)
0x7fea12b349c0 0x7fea12b349c0 / [] 2
0x7fea12b349c0 0x7fea12b349c0 /HoudiniLayerInfo [] 3
0x7fea12b349c0 0x7fea12bfe980 /set ['/set.primvars:size'] 3
0x7fea12bfe980 0x7fea12a89600 /set/garage ['/set/garage.primvars:size', '/set/garage.primvars:point_scale'] 4
0x7fea12a89600 0x7fea367b87c0 /set/garage/bicycle ['/set/garage/bicycle.primvars:size', '/set/garage.primvars:point_scale'] 5
0x7fea12a89600 0x7fea12a89600 /set/garage/car ['/set/garage.primvars:size', '/set/garage.primvars:point_scale'] 5
0x7fea12bfe980 0x7fea12bfe980 /set/yard ['/set.primvars:size'] 4
0x7fea12bfe980 0x7fea12bfe980 /set/yard/tractor ['/set.primvars:size'] 5
"""
#// ANCHOR_END: attributePrimvarInherited


#// ANCHOR: attributePrimvarIndexed
from pxr import Sdf, Usd, UsdGeom, Vt
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/bicycle")
prim = stage.DefinePrim(prim_path, "Cube")
# So let's do that
value_set = ["testA", "testB"]
value_indices = [0,0,0, 1,1, 0]
primvar = primvar_api.CreateIndexedPrimvar("height",
                                           Sdf.ValueTypeNames.StringArray,
                                           Vt.StringArray(value_set),
                                           Vt.IntArray(value_indices),
                                           UsdGeom.Tokens.constant, 
                                           time=1001)
print(primvar.ComputeFlattened())
# Returns:
# ["testA", "testA", "testA", "testB", "testB", "testA"]
#// ANCHOR_END: attributePrimvarIndexed


#// ANCHOR: attributeConnections
from pxr import Sdf, Usd
### High Level ###
# Has: 'HasAuthoredConnections', 
# Get: 'GetConnections',
# Set: 'AddConnection', 'SetConnections'
# Clear:  'RemoveConnection', 'ClearConnections'
stage = Usd.Stage.CreateInMemory()
prim_path = Sdf.Path("/box")
prim = stage.DefinePrim(prim_path, "Cube")
width_attr = prim.CreateAttribute("width", Sdf.ValueTypeNames.Double)
height_attr = prim.CreateAttribute("height", Sdf.ValueTypeNames.Double)
depth_attr = prim.CreateAttribute("depth", Sdf.ValueTypeNames.Double)
width_attr.AddConnection(height_attr.GetPath(), Usd.ListPositionBackOfAppendList)
width_attr.AddConnection(depth_attr.GetPath(), Usd.ListPositionFrontOfAppendList)
print(width_attr.GetConnections())
# Returns: [Sdf.Path('/box.depth'), Sdf.Path('/box.height')]
width_attr.RemoveConnection(depth_attr.GetPath())
print(width_attr.GetConnections())
# Returns: [Sdf.Path('/box.height')]
### Low Level ###
# Connections are managed via the `connectionPathList` AttributeSpec attribute.
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/box")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.typeName = "Cube"
width_attr_spec = Sdf.AttributeSpec(prim_spec, "width", Sdf.ValueTypeNames.Double)
height_attr_spec = Sdf.AttributeSpec(prim_spec, "height", Sdf.ValueTypeNames.Double)
depth_attr_spec = Sdf.AttributeSpec(prim_spec, "depth", Sdf.ValueTypeNames.Double)
width_attr_spec.connectionPathList.Append(height_attr_spec.path)
width_attr_spec.connectionPathList.Append(depth_attr_spec.path)
print(width_attr_spec.connectionPathList.GetAddedOrExplicitItems())
# Returns: (Sdf.Path('/box.height'), Sdf.Path('/box.depth'))
width_attr_spec.connectionPathList.Erase(depth_attr_spec.path)
print(width_attr_spec.connectionPathList.GetAddedOrExplicitItems())
# Returns: (Sdf.Path('/box.height'),)
## This won't work as the connectionPathList attribute can only be edited in place
path_list = Sdf.PathListOp.Create(appendedItems=[height_attr_spec.path])
# width_attr_spec.connectionPathList = path_list
#// ANCHOR_END: attributeConnections


#// ANCHOR: attributePurpose
### High Level ###
from pxr import Sdf, Usd, UsdGeom
stage = Usd.Stage.CreateInMemory()
cube_prim = stage.DefinePrim(Sdf.Path("/bicycle/RENDER/cube"), "Cube")
render_prim = cube_prim.GetParent()
render_prim.SetTypeName("Xform")
UsdGeom.Imageable(render_prim).GetPurposeAttr().Set(UsdGeom.Tokens.render)
sphere_prim = stage.DefinePrim(Sdf.Path("/bicycle/PROXY/sphere"), "Sphere")
proxy_prim = sphere_prim.GetParent()
proxy_prim.SetTypeName("Xform")
UsdGeom.Imageable(proxy_prim).GetPurposeAttr().Set(UsdGeom.Tokens.proxy)
# We can also query the inherited purpose:
imageable_api = UsdGeom.Imageable(cube_prim)
print(imageable_api.ComputePurpose()) # Returns: 'render'

### Low Level ###
from pxr import Sdf, UsdGeom
layer = Sdf.Layer.CreateAnonymous()
prim_path = Sdf.Path("/bicycle")
prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
prim_spec.specifier = Sdf.SpecifierDef
prim_spec.typeName = "Cube"
attr_spec = Sdf.AttributeSpec(prim_spec, "purpose", Sdf.ValueTypeNames.Token)
attr_spec.default = UsdGeom.Tokens.render
#// ANCHOR_END: attributePurpose

#// ANCHOR: attributeVisibility
### High Level ###
# UsdGeom.Imageable()
# Get: 'ComputeVisibility'
# Set: 'MakeVisible', 'MakeInvisible'
from pxr import Sdf, Usd, UsdGeom
stage = Usd.Stage.CreateInMemory()
cube_prim = stage.DefinePrim(Sdf.Path("/set/yard/bicycle"), "Cube")
sphere_prim = stage.DefinePrim(Sdf.Path("/set/garage/bicycle"), "Sphere")
set_prim = cube_prim.GetParent().GetParent()
set_prim.SetTypeName("Xform")
cube_prim.GetParent().SetTypeName("Xform")
sphere_prim.GetParent().SetTypeName("Xform")
UsdGeom.Imageable(set_prim).GetVisibilityAttr().Set(UsdGeom.Tokens.invisible)
# We can also query the inherited visibility:
# ComputeEffectiveVisibility -> This handles per purpose visibility
imageable_api = UsdGeom.Imageable(cube_prim)
print(imageable_api.ComputeVisibility()) # Returns: 'invisible'
# Make only the cube visible. Notice how this automatically sparsely
# selects only the needed parent prims (garage) and makes them invisible.
# How cool is that!
imageable_api.MakeVisible()

### Low Level ###
from pxr import Sdf, UsdGeom
layer = Sdf.Layer.CreateAnonymous()
bicycle_prim_path = Sdf.Path("/set/bicycle")
bicycle_prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)
bicycle_prim_spec.specifier = Sdf.SpecifierDef
bicycle_prim_spec.typeName = "Cube"
bicycle_vis_attr_spec = Sdf.AttributeSpec(prim_spec, "visibility", Sdf.ValueTypeNames.Token)
bicycle_vis_attr_spec.default = UsdGeom.Tokens.inherited
#// ANCHOR_END: attributeVisibility


#// ANCHOR: attributeExtent
### High Level ###
# UsdGeom.Boundable()
# Get: 'GetExtentAttr', 'CreateExtentAttr'
# Set: 'ComputeExtent '
from pxr import Sdf, Usd, UsdGeom
stage = Usd.Stage.CreateInMemory()
cube_prim = stage.DefinePrim(Sdf.Path("/bicycle/cube"), "Cube")
bicycle_prim = cube_prim.GetParent()
bicycle_prim.SetTypeName("Xform")
# If we change the size, we have to re-compute the bounds
cube_prim.GetAttribute("size").Set(10)
boundable_api = UsdGeom.Boundable(cube_prim)
print(boundable_api.GetExtentAttr().Get()) # Returns:  [(-1, -1, -1), (1, 1, 1)]
extent = boundable_api.ComputeExtent(Usd.TimeCode.Default())
boundable_api.GetExtentAttr().Set(extent)
print(boundable_api.GetExtentAttr().Get()) # Returns: [(-5, -5, -5), (5, 5, 5)]
# Author extentsHint
# The bbox cache has to be specified with what frame and purpose to query
bbox_cache = UsdGeom.BBoxCache(1001, [UsdGeom.Tokens.default_, UsdGeom.Tokens.render])
model_api = UsdGeom.ModelAPI(bicycle_prim)
extentsHint = model_api.ComputeExtentsHint(bbox_cache)
model_api.SetExtentsHint(extentsHint)
# Or model_api.SetExtentsHint(extentsHint, <frame>)
### Low Level ###
from pxr import Sdf, UsdGeom, Vt
layer = Sdf.Layer.CreateAnonymous()
cube_prim_path = Sdf.Path("/bicycle/cube")
cube_prim_spec = Sdf.CreatePrimInLayer(layer, cube_prim_path)
cube_prim_spec.specifier = Sdf.SpecifierDef
cube_prim_spec.typeName = "Cube"
bicycle_prim_path = Sdf.Path("/bicycle")
bicycle_prim_spec = Sdf.CreatePrimInLayer(layer, cube_prim_path)
bicycle_prim_spec.specifier = Sdf.SpecifierDef
bicycle_prim_spec.typeName = "Xform"
# The querying should be done via the high level API.
extent_attr_spec = Sdf.AttributeSpec(cube_prim_spec, "extent", Sdf.ValueTypeNames.Vector3fArray)
extent_attr_spec.default = Vt.Vec3fArray([(-1, -1, -1), (1, 1, 1)])
site_attr_spec = Sdf.AttributeSpec(cube_prim_spec, "size", Sdf.ValueTypeNames.Float)
site_attr_spec.default = 10
extent_attr_spec.default = Vt.Vec3fArray([(-5, -5, -5), (5, 5, 5)])
# Author extentsHint
extents_hint_attr_spec = Sdf.AttributeSpec(bicycle_prim_spec, "extentsHint", Sdf.ValueTypeNames.Vector3fArray)
extents_hint_attr_spec.default = Vt.Vec3fArray([(-5, -5, -5), (5, 5, 5)])
#// ANCHOR_END: attributeExtent


#// ANCHOR: relationshipMaterialBinding
## UsdShade.MaterialBindingAPI(<boundable prim>)
# This handles all the binding get and setting
## These classes can inspect an existing binding
# UsdShade.MaterialBindingAPI.DirectBinding()
# UsdShade.MaterialBindingAPI.CollectionBinding()
### High Level ###
from pxr import Sdf, Usd, UsdGeom, UsdShade
stage = Usd.Stage.CreateInMemory()
render_prim = stage.DefinePrim(Sdf.Path("/bicycle/RENDER/render"), "Cube")
material_prim = stage.DefinePrim(Sdf.Path("/bicycle/MATERIALS/example_material"), "Material")
bicycle_prim = render_prim.GetParent().GetParent()
bicycle_prim.SetTypeName("Xform")
render_prim.GetParent().SetTypeName("Xform")
material_prim.GetParent().SetTypeName("Xform")
# Bind materials via direct binding
material = UsdShade.Material(material_prim)
mat_bind_api = UsdShade.MaterialBindingAPI.Apply(render_prim)
mat_bind_api.Bind(material)
# Unbind all
mat_bind_api.UnbindAllBindings()
# Bind via collection
collection_name = "material_example"
collection_api = Usd.CollectionAPI.Apply(bicycle_prim, collection_name)
collection_api.GetIncludesRel().AddTarget(material_prim.GetPath())
collection_api.GetExpansionRuleAttr().Set(Usd.Tokens.expandPrims)
mat_bind_api.Bind(collection_api, material, "material_example")

### Low Level ###
from pxr import Sdf, UsdGeom
layer = Sdf.Layer.CreateAnonymous()
render_prim_spec = Sdf.CreatePrimInLayer(layer, Sdf.Path("/render"))
render_prim_spec.specifier = Sdf.SpecifierDef
render_prim_spec.typeName = "Cube"
material_prim_spec = Sdf.CreatePrimInLayer(layer, Sdf.Path("/material"))
material_prim_spec.specifier = Sdf.SpecifierDef
material_prim_spec.typeName = "Material"
## Direct binding
material_bind_rel_spec = Sdf.RelationshipSpec(render_prim_spec, "material:binding")
material_bind_rel_spec.targetPathList.Append(Sdf.Path("/render"))
# Applied Schemas
schemas = Sdf.TokenListOp.Create(
    prependedItems=["MaterialBindingAPI"]
)
render_prim_spec.SetInfo("apiSchemas", schemas)
#// ANCHOR_END: relationshipMaterialBinding

#// ANCHOR: collectionOverview
# Usd.CollectionAPI.Apply(prim, collection_name)
# collection_api = Usd.CollectionAPI(prim, collection_nam)
# collection_query = collection_api.ComputeMembershipQuery()
### High Level ###
from pxr import Sdf, Usd, UsdUtils
stage = Usd.Stage.CreateInMemory()
bicycle_prim = stage.DefinePrim(Sdf.Path("/set/yard/biycle"), "Cube")
car_prim = stage.DefinePrim(Sdf.Path("/set/garage/car"), "Sphere")
tractor_prim = stage.DefinePrim(Sdf.Path("/set/garage/tractor"), "Cylinder")
helicopter_prim = stage.DefinePrim(Sdf.Path("/set/garage/helicopter"), "Cube")
boat_prim = stage.DefinePrim(Sdf.Path("/set/garage/boat"), "Cube")
set_prim = bicycle_prim.GetParent().GetParent()
set_prim.SetTypeName("Xform")
bicycle_prim.GetParent().SetTypeName("Xform")
car_prim.GetParent().SetTypeName("Xform")
# Create collection
collection_name = "vehicles"
collection_api = Usd.CollectionAPI.Apply(set_prim, collection_name)
collection_api.GetIncludesRel().AddTarget(set_prim.GetPath())
collection_api.GetExcludesRel().AddTarget(bicycle_prim.GetPath())
collection_api.GetExpansionRuleAttr().Set(Usd.Tokens.expandPrims)
print(Usd.CollectionAPI.GetAllCollections(set_prim)) # Returns: [Usd.CollectionAPI(Usd.Prim(</set>), 'vehicles')]
print(Usd.CollectionAPI.GetCollection(set_prim, "vehicles")) # Returns: Usd.CollectionAPI(Usd.Prim(</set>), 'vehicles')
collection_query = collection_api.ComputeMembershipQuery()
print(collection_api.ComputeIncludedPaths(collection_query, stage))
# Returns: 
# [Sdf.Path('/set'), Sdf.Path('/set/garage'), Sdf.Path('/set/garage/boat'),
#  Sdf.Path('/set/garage/car'), Sdf.Path('/set/garage/helicopter'),
#  Sdf.Path('/set/garage/tractor'), Sdf.Path('/set/yard')]
# Set it to explicit only
collection_api.GetExpansionRuleAttr().Set(Usd.Tokens.explicitOnly)
collection_query = collection_api.ComputeMembershipQuery()
print(collection_api.ComputeIncludedPaths(collection_query, stage))
# Returns: [Sdf.Path('/set')]

# To help speed up collection creation, USD also ships with util functions:
# UsdUtils.AuthorCollection(<collectionName>, prim, [<includePathList>], [<excludePathList>])
collection_api = UsdUtils.AuthorCollection("two_wheels", set_prim, [set_prim.GetPath()], [car_prim.GetPath()])
collection_query = collection_api.ComputeMembershipQuery()
print(collection_api.ComputeIncludedPaths(collection_query, stage))
# Returns:
# [Sdf.Path('/set'), Sdf.Path('/set/garage'), Sdf.Path('/set/yard'), Sdf.Path('/set/yard/biycle')]
# UsdUtils.ComputeCollectionIncludesAndExcludes() gives us the possibility to author 
# collections more sparse, that the include to exclude ratio is kept at an optimal size.
# The Python signature differs from the C++ signature:
"""
include_paths, exclude_paths = UsdUtils.ComputeCollectionIncludesAndExcludes(
    target_paths,
    stage,
    minInclusionRatio = 0.75,
    maxNumExcludesBelowInclude = 5,
	minIncludeExcludeCollectionSize = 3,
    pathsToIgnore = [] # This ignores paths from computation (this is not the exclude list)
)		
"""
target_paths = [tractor_prim.GetPath(), car_prim.GetPath(), helicopter_prim.GetPrimPath()]
include_paths, exclude_paths = UsdUtils.ComputeCollectionIncludesAndExcludes(target_paths,stage, minInclusionRatio=.9)
print(include_paths, exclude_paths)
# Returns:
# [Sdf.Path('/set/garage/car'), Sdf.Path('/set/garage/tractor'), Sdf.Path('/set/garage/helicopter')] []
include_paths, exclude_paths = UsdUtils.ComputeCollectionIncludesAndExcludes(target_paths,stage, minInclusionRatio=.1)
print(include_paths, exclude_paths)
# Returns: [Sdf.Path('/set/garage')] [Sdf.Path('/set/garage/boat')]
# Create a collection from the result
collection_api = UsdUtils.AuthorCollection("optimized", set_prim, include_paths, exclude_paths)
#// ANCHOR_END: collectionOverview

#// ANCHOR: relationshipOverview
### High Level ###
# Get: 'GetForwardedTargets', 'GetTargets',
# Set: 'AddTarget', 'SetTargets'
# Clear: 'RemoveTarget', 'ClearTargets'
from pxr import Sdf, Usd, UsdGeom
stage = Usd.Stage.CreateInMemory()
cube_prim = stage.DefinePrim(Sdf.Path("/cube_prim"), "Cube")
sphere_prim = stage.DefinePrim(Sdf.Path("/sphere_prim"), "Sphere")
myFavoriteSphere_rel = cube_prim.CreateRelationship("myFavoriteSphere")
myFavoriteSphere_rel.AddTarget(sphere_prim.GetPath())
print(myFavoriteSphere_rel.GetForwardedTargets()) # Returns:[Sdf.Path('/sphere_prim')]
# myFavoriteSphere_rel.ClearTargets()
# We can also forward relationships to other relationships.
cylinder_prim = stage.DefinePrim(Sdf.Path("/sphere_prim"), "Cylinder")
myFavoriteSphereForward_rel = cylinder_prim.CreateRelationship("myFavoriteSphereForward")
myFavoriteSphereForward_rel.AddTarget(myFavoriteSphere_rel.GetPath())
# GetForwardedTargets: This gives us the final fowarded paths. We'll use this most of the time.
# GetTargets: Gives us the paths set on the relationship, forwarded paths are not baked down.
print(myFavoriteSphereForward_rel.GetForwardedTargets()) # Returns:[Sdf.Path('/sphere_prim')]
print(myFavoriteSphereForward_rel.GetTargets()) # Returns: [Sdf.Path('/cube_prim.myFavoriteSphere')]

### Low Level ###
from pxr import Sdf, UsdGeom
layer = Sdf.Layer.CreateAnonymous()
cube_prim_spec = Sdf.CreatePrimInLayer(layer, Sdf.Path("/cube_prim"))
cube_prim_spec.specifier = Sdf.SpecifierDef
cube_prim_spec.typeName = "Cube"
sphere_prim_spec = Sdf.CreatePrimInLayer(layer, Sdf.Path("/sphere_prim"))
sphere_prim_spec.specifier = Sdf.SpecifierDef
sphere_prim_spec.typeName = "Cube"
rel_spec = Sdf.RelationshipSpec(cube_prim_spec, "proxyPrim")
rel_spec.targetPathList.Append(sphere_prim_spec.path)
# The targetPathList is a list editable Sdf.PathListOp.
# Forwarded rels can only be calculated via the high level API.
#// ANCHOR_END: relationshipOverview


#// ANCHOR: relationshipProxyPrim
### High Level ###
from pxr import Sdf, Usd, UsdGeom
stage = Usd.Stage.CreateInMemory()
render_prim = stage.DefinePrim(Sdf.Path("/bicycle/RENDER/render"), "Cube")
proxy_prim = stage.DefinePrim(Sdf.Path("/bicycle/PROXY/proxy"), "Sphere")
bicycle_prim = render_prim.GetParent().GetParent()
bicycle_prim.SetTypeName("Xform")
render_prim.GetParent().SetTypeName("Xform")
proxy_prim.GetParent().SetTypeName("Xform")
imageable_api = UsdGeom.Imageable(render_prim)
imageable_api.SetProxyPrim(proxy_prim)
# Query the proxy prim
print(imageable_api.ComputeProxyPrim()) # Returns: None
# Why does this not work? We have to set the purpose!
UsdGeom.Imageable(render_prim).GetPurposeAttr().Set(UsdGeom.Tokens.render)
UsdGeom.Imageable(proxy_prim).GetPurposeAttr().Set(UsdGeom.Tokens.proxy)
print(imageable_api.ComputeProxyPrim()) # Returns: (Usd.Prim(</bicycle/PROXY/proxy>), Usd.Prim(</bicycle/RENDER/render>))

### Low Level ###
from pxr import Sdf, UsdGeom
layer = Sdf.Layer.CreateAnonymous()
render_prim_spec = Sdf.CreatePrimInLayer(layer, Sdf.Path("/render"))
render_prim_spec.specifier = Sdf.SpecifierDef
render_prim_spec.typeName = "Cube"
proxy_prim_spec = Sdf.CreatePrimInLayer(layer, Sdf.Path("/proxy"))
proxy_prim_spec.specifier = Sdf.SpecifierDef
proxy_prim_spec.typeName = "Cube"
proxyPrim_rel_spec = Sdf.RelationshipSpec(render_prim_spec, "proxyPrim")
proxyPrim_rel_spec.targetPathList.Append(Sdf.Path("/proxy"))
#// ANCHOR_END: relationshipProxyPrim


#// ANCHOR: collectionInvert
from pxr import Sdf, Usd, UsdUtils
stage = Usd.Stage.CreateInMemory()
# Create hierarchy
prim_paths = [
    "/set/yard/biycle",
    "/set/yard/shed/shovel",
    "/set/yard/shed/flower_pot",
    "/set/yard/shed/lawnmower",
    "/set/yard/shed/soil",
    "/set/yard/shed/wood",
    "/set/garage/car",
    "/set/garage/tractor",
    "/set/garage/helicopter",
    "/set/garage/boat",
    "/set/garage/key_box",
    "/set/garage/key_box/red",
    "/set/garage/key_box/blue",
    "/set/garage/key_box/green",
    "/set/people/mike",
    "/set/people/charolotte"
]
for prim_path in prim_paths:
    prim = stage.DefinePrim(prim_path, "Cube")
print("<< hierarchy >>")
for prim in stage.Traverse():
    print(prim.GetPath())
    parent_prim = prim.GetParent()
    while True:
        if parent_prim.IsPseudoRoot():
            break
        parent_prim.SetTypeName("Xform")
        parent_prim = parent_prim.GetParent()
# Returns:
"""
<< hierarchy >>
/HoudiniLayerInfo
Download .txt
gitextract_fg3igdvu/

├── .github/
│   └── workflows/
│       └── mdbook.yml
├── .gitignore
├── LICENSE
├── README.md
├── code/
│   ├── core/
│   │   ├── composition.py
│   │   └── elements.py
│   ├── dcc/
│   │   └── houdini.py
│   ├── production/
│   │   ├── caches.py
│   │   └── production.py
│   └── test.py
├── docs/
│   ├── book.toml
│   ├── src/
│   │   ├── SUMMARY.md
│   │   ├── google12b063a902eb5a11.html
│   │   ├── index.md
│   │   ├── media/
│   │   │   ├── UsdSurvivalGuide.psd
│   │   │   └── core/
│   │   │       └── composition/
│   │   │           ├── compositionLIVRPS.excalidraw
│   │   │           └── houdiniCompositionReferenceEncapsulate.webm
│   │   ├── not-found.md
│   │   ├── pages/
│   │   │   ├── contributors.md
│   │   │   ├── core/
│   │   │   │   ├── api.md
│   │   │   │   ├── composition/
│   │   │   │   │   ├── arcs.md
│   │   │   │   │   ├── fundamentals.md
│   │   │   │   │   ├── listeditableops.md
│   │   │   │   │   ├── livrps.md
│   │   │   │   │   ├── overview.md
│   │   │   │   │   ├── pcp.md
│   │   │   │   │   ├── pcpPrimIndex.txt
│   │   │   │   │   └── pcpPrimIndexPig.txt
│   │   │   │   ├── elements/
│   │   │   │   │   ├── animation.md
│   │   │   │   │   ├── collection.md
│   │   │   │   │   ├── data_container.md
│   │   │   │   │   ├── data_type.md
│   │   │   │   │   ├── layer.md
│   │   │   │   │   ├── loading_mechanisms.md
│   │   │   │   │   ├── materials.md
│   │   │   │   │   ├── metadata.md
│   │   │   │   │   ├── notice.md
│   │   │   │   │   ├── overview.md
│   │   │   │   │   ├── path.md
│   │   │   │   │   ├── prim.md
│   │   │   │   │   ├── property.md
│   │   │   │   │   ├── schemas.md
│   │   │   │   │   ├── standalone_utilities.md
│   │   │   │   │   └── transform.md
│   │   │   │   ├── glossary.md
│   │   │   │   ├── overview.md
│   │   │   │   ├── plugins/
│   │   │   │   │   ├── assetresolver.md
│   │   │   │   │   ├── kind.md
│   │   │   │   │   ├── metadata.md
│   │   │   │   │   ├── overview.md
│   │   │   │   │   └── schemas.md
│   │   │   │   ├── profiling/
│   │   │   │   │   ├── debug.md
│   │   │   │   │   ├── overview.md
│   │   │   │   │   └── profiling.md
│   │   │   │   └── resources.md
│   │   │   ├── dcc/
│   │   │   │   ├── houdini/
│   │   │   │   │   ├── approach.md
│   │   │   │   │   ├── faq/
│   │   │   │   │   │   └── overview.md
│   │   │   │   │   ├── fx/
│   │   │   │   │   │   ├── deformingMeshes.md
│   │   │   │   │   │   ├── frustumCulling.md
│   │   │   │   │   │   ├── motionblur.md
│   │   │   │   │   │   ├── overview.md
│   │   │   │   │   │   ├── particles.md
│   │   │   │   │   │   ├── pointinstancers.md
│   │   │   │   │   │   ├── rbd.md
│   │   │   │   │   │   ├── transformspace.md
│   │   │   │   │   │   └── volumes.md
│   │   │   │   │   ├── hda/
│   │   │   │   │   │   └── overview.md
│   │   │   │   │   ├── overview.md
│   │   │   │   │   └── performance/
│   │   │   │   │       └── overview.md
│   │   │   │   └── overview.md
│   │   │   ├── introduction/
│   │   │   │   ├── docs.md
│   │   │   │   ├── future.md
│   │   │   │   ├── motivation.md
│   │   │   │   └── structure.md
│   │   │   └── production/
│   │   │       ├── caches/
│   │   │       │   ├── attribute.md
│   │   │       │   ├── boundingbox.md
│   │   │       │   ├── collection.md
│   │   │       │   ├── composition.md
│   │   │       │   ├── materialbinding.md
│   │   │       │   ├── overview.md
│   │   │       │   └── xform.md
│   │   │       ├── composition.md
│   │   │       ├── concepts.md
│   │   │       ├── faq.md
│   │   │       ├── overview.md
│   │   │       ├── prerequisites.md
│   │   │       └── schemas.md
│   │   └── template.md
│   └── theme/
│       ├── ext/
│       │   ├── css/
│       │   │   ├── custom.css
│       │   │   └── mdbook-admonish.css
│       │   └── js/
│       │       ├── custom.js
│       │       └── mermaid-init.js
│       ├── head.hbs.bkp
│       └── header.hbs
├── docs.bat
├── docs.sh
├── files/
│   ├── composition/
│   │   ├── composition.hipnc
│   │   ├── pixar/
│   │   │   ├── faq/
│   │   │   │   └── WhenCanYouDeleteAReference/
│   │   │   │       ├── assembly.usda
│   │   │   │       ├── assembly_with_all_variants.usda
│   │   │   │       ├── assets.usda
│   │   │   │       ├── shot.usda
│   │   │   │       └── shot_variant_switch.usda
│   │   │   └── glossary/
│   │   │       ├── inherits/
│   │   │       │   ├── Forest.usd
│   │   │       │   └── Trees.usd
│   │   │       ├── references/
│   │   │       │   ├── FlattenedMarbleCollection.usd
│   │   │       │   ├── Marble.usd
│   │   │       │   └── MarbleCollection.usd
│   │   │       └── specializes/
│   │   │           ├── Robot.usd
│   │   │           └── RobotScene.usd
│   │   └── usdSurvivalGuide/
│   │       ├── .gitignore
│   │       └── livrps/
│   │           └── sublayer_valueclip_cache_workflow/
│   │               ├── set_anim_valueclip_stitch_clips.manifest.usd
│   │               ├── set_anim_valueclip_stitch_clips.topology.usd
│   │               ├── set_anim_valueclip_stitch_clips.usd
│   │               ├── valueclip_stitch_clips.manifest.usd
│   │               ├── valueclip_stitch_clips.topology.usd
│   │               └── valueclip_stitch_clips.usd
│   ├── dcc/
│   │   └── houdini/
│   │       ├── RBD/
│   │       │   └── RBD.hipnc
│   │       ├── frustumCulling/
│   │       │   └── frustumCulling.hipnc
│   │       ├── hda/
│   │       │   └── hda.hipnc
│   │       ├── motionblur/
│   │       │   └── MotionBlur.hipnc
│   │       ├── overview.hipnc
│   │       ├── pointInstancer/
│   │       │   └── pointInstancer.hipnc
│   │       ├── points/
│   │       │   ├── points_native.hipnc
│   │       │   ├── pythonWrangle.py
│   │       │   ├── renderPreFrame.py
│   │       │   └── render_attribute_modification.hipnc
│   │       ├── profiling/
│   │       │   ├── report.json
│   │       │   ├── report.trace
│   │       │   └── tracing.hipnc
│   │       ├── timeSamples/
│   │       │   └── GetValueMightBeTimeVarying.hipnc
│   │       ├── transforms/
│   │       │   └── xforms.hipnc
│   │       └── variants/
│   │           └── variants.hipnc
│   └── plugins/
│       ├── kinds/
│       │   └── plugInfo.json
│       ├── metadata/
│       │   └── plugInfo.json
│       └── schemas/
│           ├── codelessSchema/
│           │   ├── build.sh
│           │   ├── dist/
│           │   │   ├── generatedSchema.usda
│           │   │   └── plugInfo.json
│           │   └── schema.usda
│           ├── compiledSchema/
│           │   ├── .gitignore
│           │   ├── CMakeLists.txt
│           │   ├── auxiliary/
│           │   │   ├── __init__.py
│           │   │   ├── module.cpp
│           │   │   └── moduleDeps.cpp
│           │   ├── build.sh
│           │   ├── schema.usda
│           │   └── src/
│           │       ├── __init__.py
│           │       ├── api.h
│           │       ├── complex.cpp
│           │       ├── complex.h
│           │       ├── generatedSchema.usda
│           │       ├── module.cpp
│           │       ├── moduleDeps.cpp
│           │       ├── paramsAPI.cpp
│           │       ├── paramsAPI.h
│           │       ├── plugInfo.json
│           │       ├── simple.cpp
│           │       ├── simple.h
│           │       ├── tokens.cpp
│           │       ├── tokens.h
│           │       ├── wrapComplex.cpp
│           │       ├── wrapParamsAPI.cpp
│           │       ├── wrapSimple.cpp
│           │       └── wrapTokens.cpp
│           └── exampleSchema.usda
└── setup.sh
Download .txt
SYMBOL INDEX (98 symbols across 21 files)

FILE: code/core/composition.py
  function variant_nested_edit_context (line 481) | def variant_nested_edit_context(prim, variant_selections, position=Usd.L...
  function variant_nested_prim_path (line 543) | def variant_nested_prim_path(prim_path, variant_selections):
  function define_prim_spec (line 549) | def define_prim_spec(layer, prim_path, type_name):
  function iterator_child_nodes (line 960) | def iterator_child_nodes(root_node):
  function iterator_parent_nodes (line 966) | def iterator_parent_nodes(root_node):
  function _repr (line 994) | def _repr(arc):

FILE: code/core/elements.py
  class Bar (line 1122) | class Bar():
    method foo (line 1124) | def foo(self):
  function foo (line 1128) | def foo(stage):
  function callback (line 1259) | def callback(notice, sender):
  function DidRegisterPlugins_callback (line 1302) | def DidRegisterPlugins_callback(notice):
  function ObjectsChanged_callback (line 1313) | def ObjectsChanged_callback(notice, sender):
  function callback (line 1377) | def callback(notice, sender):
  class CustomNotice (line 1380) | class CustomNotice(Tf.Notice):
  function compute_time_derivative (line 1859) | def compute_time_derivative(layer, prim_spec, attr_name, ref_attr_name, ...
  function compute_velocities (line 1896) | def compute_velocities(layer, prim_spec, time_code_fps, multiplier=1.0):
  function compute_accelerations (line 1920) | def compute_accelerations(layer, prim_spec, time_code_fps, multiplier=1.0):
  function traversal_kernel (line 1949) | def traversal_kernel(path):
  function traversal_kernel (line 3661) | def traversal_kernel(path):
  function traversal_kernel (line 3679) | def traversal_kernel(path):
  function traversal_kernel (line 3691) | def traversal_kernel(path):
  function traversal_kernel (line 3703) | def traversal_kernel(path):
  function create_hierarchy (line 4203) | def create_hierarchy(layer, root_prim_path, max_levels):
  function profile (line 4273) | def profile(func, label, root_prim):
  function profile_boundable (line 4293) | def profile_boundable(prim):
  function profile_GetTypeName (line 4298) | def profile_GetTypeName(prim):
  function profile_kind (line 4303) | def profile_kind(prim):
  function profile_assetInfo_is_leaf (line 4309) | def profile_assetInfo_is_leaf(prim):
  function profile_attribute_has_is_leaf (line 4315) | def profile_attribute_has_is_leaf(prim):
  function profile_attribute_is_leaf (line 4322) | def profile_attribute_is_leaf(prim):
  function profile_attribute_extra_validation_is_leaf (line 4331) | def profile_attribute_extra_validation_is_leaf(prim):
  function traversal_kernel (line 4374) | def traversal_kernel(path):

FILE: code/dcc/houdini.py
  function GetValueMightBeTimeVarying (line 25) | def GetValueMightBeTimeVarying(attribute, checkVariability=False):
  function pointinstancer_prototypes_reorder (line 240) | def pointinstancer_prototypes_reorder(layers):

FILE: code/production/production.py
  function callback (line 219) | def callback(notice, sender):

FILE: code/test.py
  function example (line 2) | def example():

FILE: files/dcc/houdini/points/pythonWrangle.py
  class Tokens (line 4) | class Tokens():
  class Binding (line 10) | class Binding():
    method __init__ (line 12) | def __init__(self):
  class Point (line 17) | class Point():
    method __init__ (line 18) | def __init__(self, bindings):
  class Points (line 24) | class Points():
    method __init__ (line 25) | def __init__(self):
  function run_kernel (line 30) | def run_kernel(stage, frame):

FILE: files/plugins/schemas/compiledSchema/auxiliary/module.cpp
  function PXR_NAMESPACE_USING_DIRECTIVE (line 28) | PXR_NAMESPACE_USING_DIRECTIVE

FILE: files/plugins/schemas/compiledSchema/auxiliary/moduleDeps.cpp
  function PXR_NAMESPACE_OPEN_SCOPE (line 33) | PXR_NAMESPACE_OPEN_SCOPE

FILE: files/plugins/schemas/compiledSchema/src/complex.cpp
  function PXR_NAMESPACE_OPEN_SCOPE (line 31) | PXR_NAMESPACE_OPEN_SCOPE
  function UsdSchemaExamplesComplex (line 53) | UsdSchemaExamplesComplex
  function UsdSchemaExamplesComplex (line 64) | UsdSchemaExamplesComplex
  function UsdSchemaKind (line 78) | UsdSchemaKind UsdSchemaExamplesComplex::_GetSchemaKind() const
  function TfType (line 84) | const TfType &
  function TfType (line 100) | const TfType &
  function UsdAttribute (line 106) | UsdAttribute
  function UsdAttribute (line 112) | UsdAttribute
  function TfTokenVector (line 124) | static inline TfTokenVector
  function TfTokenVector (line 136) | const TfTokenVector&

FILE: files/plugins/schemas/compiledSchema/src/complex.h
  function UsdSchemaExamplesSimple (line 70) | UsdSchemaExamplesSimple(prim)
  function explicit (line 77) | explicit UsdSchemaExamplesComplex(const UsdSchemaBase& schemaObj)

FILE: files/plugins/schemas/compiledSchema/src/module.cpp
  function PXR_NAMESPACE_USING_DIRECTIVE (line 28) | PXR_NAMESPACE_USING_DIRECTIVE

FILE: files/plugins/schemas/compiledSchema/src/moduleDeps.cpp
  function PXR_NAMESPACE_OPEN_SCOPE (line 33) | PXR_NAMESPACE_OPEN_SCOPE

FILE: files/plugins/schemas/compiledSchema/src/paramsAPI.cpp
  function PXR_NAMESPACE_OPEN_SCOPE (line 32) | PXR_NAMESPACE_OPEN_SCOPE
  function UsdSchemaExamplesParamsAPI (line 53) | UsdSchemaExamplesParamsAPI
  function UsdSchemaKind (line 65) | UsdSchemaKind UsdSchemaExamplesParamsAPI::_GetSchemaKind() const
  function UsdSchemaExamplesParamsAPI (line 79) | UsdSchemaExamplesParamsAPI
  function TfType (line 89) | const TfType &
  function TfType (line 105) | const TfType &
  function UsdAttribute (line 111) | UsdAttribute
  function UsdAttribute (line 117) | UsdAttribute
  function UsdAttribute (line 128) | UsdAttribute
  function UsdAttribute (line 134) | UsdAttribute
  function UsdAttribute (line 145) | UsdAttribute
  function UsdAttribute (line 151) | UsdAttribute
  function TfTokenVector (line 163) | static inline TfTokenVector
  function TfTokenVector (line 175) | const TfTokenVector&

FILE: files/plugins/schemas/compiledSchema/src/paramsAPI.h
  function UsdAPISchemaBase (line 69) | UsdAPISchemaBase(prim)
  function explicit (line 76) | explicit UsdSchemaExamplesParamsAPI(const UsdSchemaBase& schemaObj)

FILE: files/plugins/schemas/compiledSchema/src/simple.cpp
  function PXR_NAMESPACE_OPEN_SCOPE (line 31) | PXR_NAMESPACE_OPEN_SCOPE
  function UsdSchemaExamplesSimple (line 47) | UsdSchemaExamplesSimple
  function UsdSchemaKind (line 59) | UsdSchemaKind UsdSchemaExamplesSimple::_GetSchemaKind() const
  function TfType (line 65) | const TfType &
  function TfType (line 81) | const TfType &
  function UsdAttribute (line 87) | UsdAttribute
  function UsdAttribute (line 93) | UsdAttribute
  function UsdRelationship (line 104) | UsdRelationship
  function UsdRelationship (line 110) | UsdRelationship
  function TfTokenVector (line 118) | static inline TfTokenVector
  function TfTokenVector (line 130) | const TfTokenVector&

FILE: files/plugins/schemas/compiledSchema/src/simple.h
  function UsdTyped (line 71) | UsdTyped(prim)
  function explicit (line 78) | explicit UsdSchemaExamplesSimple(const UsdSchemaBase& schemaObj)

FILE: files/plugins/schemas/compiledSchema/src/tokens.h
  function PXR_NAMESPACE_OPEN_SCOPE (line 42) | PXR_NAMESPACE_OPEN_SCOPE

FILE: files/plugins/schemas/compiledSchema/src/wrapComplex.cpp
  function PXR_NAMESPACE_USING_DIRECTIVE (line 41) | PXR_NAMESPACE_USING_DIRECTIVE
  function wrapUsdSchemaExamplesComplex (line 70) | void wrapUsdSchemaExamplesComplex()

FILE: files/plugins/schemas/compiledSchema/src/wrapParamsAPI.cpp
  function PXR_NAMESPACE_USING_DIRECTIVE (line 42) | PXR_NAMESPACE_USING_DIRECTIVE
  function wrapUsdSchemaExamplesParamsAPI (line 100) | void wrapUsdSchemaExamplesParamsAPI()

FILE: files/plugins/schemas/compiledSchema/src/wrapSimple.cpp
  function PXR_NAMESPACE_USING_DIRECTIVE (line 41) | PXR_NAMESPACE_USING_DIRECTIVE
  function wrapUsdSchemaExamplesSimple (line 70) | void wrapUsdSchemaExamplesSimple()

FILE: files/plugins/schemas/compiledSchema/src/wrapTokens.cpp
  function PXR_NAMESPACE_USING_DIRECTIVE (line 28) | PXR_NAMESPACE_USING_DIRECTIVE
  function wrapUsdSchemaExamplesTokens (line 63) | void wrapUsdSchemaExamplesTokens()
Condensed preview — 165 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,029K chars).
[
  {
    "path": ".github/workflows/mdbook.yml",
    "chars": 2014,
    "preview": "name: Deploy Documentation to GitHub Pages\n\non:\n  push:\n    branches: [\"main\"]\n  workflow_dispatch:\n\npermissions:\n  cont"
  },
  {
    "path": ".gitignore",
    "chars": 105,
    "preview": "workspace\nplayground\nbackup\nbuild\ntools\ndocs/book\nexamples\ngeo\n*.code-workspace\n*.vscode\n*.so\n__pycache__"
  },
  {
    "path": "LICENSE",
    "chars": 11357,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "README.md",
    "chars": 1429,
    "preview": "![Usd Survival Guide](https://raw.githubusercontent.com/LucaScheller/VFX-UsdSurvivalGuide/main/docs/src/media/UsdSurviva"
  },
  {
    "path": "code/core/composition.py",
    "chars": 49925,
    "preview": "#// ANCHOR: compositionEditTarget\nfrom pxr import Sdf, Usd\n## Standard way of using edit targets\nstage = Usd.Stage.Creat"
  },
  {
    "path": "code/core/elements.py",
    "chars": 189070,
    "preview": "\"\"\"This file contains all code examples for the 'Core Elements' section.\nThe following mdBook syntax allows us to sparse"
  },
  {
    "path": "code/dcc/houdini.py",
    "chars": 19307,
    "preview": "#// ANCHOR: houdiniCompositionInheritInstanceable\nfrom pxr import Gf, Sdf, Usd\nnode = hou.pwd()\nstage = node.editableSta"
  },
  {
    "path": "code/production/caches.py",
    "chars": 8996,
    "preview": "#// ANCHOR: stageQueryAttribute\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nprim = stage.DefinePrim(Sdf."
  },
  {
    "path": "code/production/production.py",
    "chars": 7713,
    "preview": "#// ANCHOR: productionConceptsSdfBatchNamespaceMoveRenameDelete\n### High Level / Low Level ###\n# The Sdf.BatchNamespaceE"
  },
  {
    "path": "code/test.py",
    "chars": 562,
    "preview": "#// ANCHOR: example\ndef example():\n    print(\"example\")\n#// ANCHOR_END: example\n\n\"\"\"\nNotes:\nAn abstract explanation of U"
  },
  {
    "path": "docs/book.toml",
    "chars": 5820,
    "preview": "[book]\nauthors = [\"Luca Scheller\"]\nlanguage = \"en\"\nmultilingual = false\nsrc = \"src\"\ntitle = \"Usd Survival Guide\"\ndescrip"
  },
  {
    "path": "docs/src/SUMMARY.md",
    "chars": 4660,
    "preview": "# SUMMARY\n[USD Survival Guide]()\n\n----------------------\n\n- [Introduction](./index.md)\n    - [Motivation](./pages/introd"
  },
  {
    "path": "docs/src/google12b063a902eb5a11.html",
    "chars": 53,
    "preview": "google-site-verification: google12b063a902eb5a11.html"
  },
  {
    "path": "docs/src/index.md",
    "chars": 2377,
    "preview": "![](../UsdSurvivalGuide.png#center)\n\n# Usd Survival Guide\n[![Deploy Documentation to GitHub Pages](https://github.com/Lu"
  },
  {
    "path": "docs/src/media/core/composition/compositionLIVRPS.excalidraw",
    "chars": 45353,
    "preview": "{\n  \"type\": \"excalidraw\",\n  \"version\": 2,\n  \"source\": \"https://excalidraw.com\",\n  \"elements\": [\n    {\n      \"type\": \"rec"
  },
  {
    "path": "docs/src/not-found.md",
    "chars": 105,
    "preview": "<center><h3>The requested page was not found, please browse to a valid page in the sidebar!</h3></center>"
  },
  {
    "path": "docs/src/pages/contributors.md",
    "chars": 228,
    "preview": "### Contributors\n- [Luca Scheller (Main Author)](https://github.com/LucaScheller)\n- [Jonas Sorgenfrei](https://github.co"
  },
  {
    "path": "docs/src/pages/core/api.md",
    "chars": 5204,
    "preview": "# API Overview\nBefore we dive into the nitty gritty details, let's first have a look at how the USD API is structured.\n\n"
  },
  {
    "path": "docs/src/pages/core/composition/arcs.md",
    "chars": 10514,
    "preview": "# Composition Arcs\nIn this section we'll cover how to create composition arcs via code. To check our how composition arc"
  },
  {
    "path": "docs/src/pages/core/composition/fundamentals.md",
    "chars": 18317,
    "preview": "# Composition Fundamentals\n\nIn this section will talk about fundamental concepts that we need to know before we look at "
  },
  {
    "path": "docs/src/pages/core/composition/listeditableops.md",
    "chars": 8451,
    "preview": "# List Editable Ops (Operations)\nOn this page we will have a look at list editable ops when not being used in compositio"
  },
  {
    "path": "docs/src/pages/core/composition/livrps.md",
    "chars": 59948,
    "preview": "# Composition Strength Ordering (LIVRPS)\nIn this section we'll cover how composition arcs work and interact with each ot"
  },
  {
    "path": "docs/src/pages/core/composition/overview.md",
    "chars": 1260,
    "preview": "# Composition (Combining layers)\nComposition is the \"art\" of combining layers in USD. (Yes \"art\" as everyone does it a b"
  },
  {
    "path": "docs/src/pages/core/composition/pcp.md",
    "chars": 13546,
    "preview": "# Prim Cache Population (PCP) - Composition Cache\nThe **Prim Cache Population** module is the backend of what makes USD "
  },
  {
    "path": "docs/src/pages/core/composition/pcpPrimIndex.txt",
    "chars": 370,
    "preview": "digraph PcpPrimIndex {\n\t140321959801344 [label=\"@anon:0x7f9ec906e400:tmp.usda@,@anon:0x7f9ec8f85a00:tmp-session.usda@</r"
  },
  {
    "path": "docs/src/pages/core/composition/pcpPrimIndexPig.txt",
    "chars": 3353,
    "preview": "digraph PcpPrimIndex {\n\t140319730187168 [label=\"@anon:0x7f9ec9290900:LOP:rootlayer@,@anon:0x7f9ec906e680:LOP:rootlayer-s"
  },
  {
    "path": "docs/src/pages/core/elements/animation.md",
    "chars": 25229,
    "preview": "# Animation/Time Varying Data\nUsd encodes time related data in a very simple format:\n```json\n{\n    <frame>: <value>\n}\n``"
  },
  {
    "path": "docs/src/pages/core/elements/collection.md",
    "chars": 5626,
    "preview": "# Collections\nCollections are USD's mechanism of storing a set of prim paths. We can nest/forward collections to other c"
  },
  {
    "path": "docs/src/pages/core/elements/data_container.md",
    "chars": 5124,
    "preview": "# Data Containers (Prims & Properties)\nFor Usd to store data at the paths, we need a data container.\nTo fill this need, "
  },
  {
    "path": "docs/src/pages/core/elements/data_type.md",
    "chars": 8184,
    "preview": "# Data Types/Roles\n\n# Table of Contents\n1. [Data Types/Roles In-A-Nutshell](#summary)\n1. [What should I use it for?](#us"
  },
  {
    "path": "docs/src/pages/core/elements/layer.md",
    "chars": 27903,
    "preview": "# Layers & Stages\nLayers and stages are the main entry point to accessing our data stored in USD.\n\n# Table of Contents\n1"
  },
  {
    "path": "docs/src/pages/core/elements/loading_mechanisms.md",
    "chars": 18307,
    "preview": "# Loading & Traversing Data\n\n# Table of Contents\n1. [Traversing & Loading Data In-A-Nutshell](#summary)\n1. [What should "
  },
  {
    "path": "docs/src/pages/core/elements/materials.md",
    "chars": 6885,
    "preview": "# Materials\nMaterials in USD are exposed via the [UsdShade](https://openusd.org/dev/api/usd_shade_page_front.html) modul"
  },
  {
    "path": "docs/src/pages/core/elements/metadata.md",
    "chars": 16484,
    "preview": "# Metadata\nMetadata is the smallest building block in Usd. It is part of the base class from which prims and properties "
  },
  {
    "path": "docs/src/pages/core/elements/notice.md",
    "chars": 2148,
    "preview": "# Notices/Event Listeners\nUsd's event system is exposed via the [Notice](https://openusd.org/dev/api/group__group__tf___"
  },
  {
    "path": "docs/src/pages/core/elements/overview.md",
    "chars": 1691,
    "preview": "# Elements\nIn this sub-section we have a look at the basic building blocks of Usd.\n\nOur approach is incrementally going "
  },
  {
    "path": "docs/src/pages/core/elements/path.md",
    "chars": 3280,
    "preview": "# Paths\nAs Usd is a hierarchy based format, one of its core functions is handling paths.\nIn order to do this, Usd provid"
  },
  {
    "path": "docs/src/pages/core/elements/prim.md",
    "chars": 12477,
    "preview": "\n# Prims\nFor an overview and summary please see the parent [Data Containers](./data_container.md) section.\n\n# Table of C"
  },
  {
    "path": "docs/src/pages/core/elements/property.md",
    "chars": 27391,
    "preview": "# Properties\nFor an overview and summary please see the parent [Data Containers](./data_container.md) section.\n\nHere is "
  },
  {
    "path": "docs/src/pages/core/elements/schemas.md",
    "chars": 13619,
    "preview": "# Schemas\nSchemas are to USD what classes are to object orient programming. Let's explain schemas with that analogy in m"
  },
  {
    "path": "docs/src/pages/core/elements/standalone_utilities.md",
    "chars": 3513,
    "preview": "# Standalone Utilities\nUsd ships with a small set of commandline utilities. Below you find a short summary of the most i"
  },
  {
    "path": "docs/src/pages/core/elements/transform.md",
    "chars": 7800,
    "preview": "# Transforms\n~~~admonish question title=\"Still under construction!\"\nThis section still needs some more love, we'll likel"
  },
  {
    "path": "docs/src/pages/core/glossary.md",
    "chars": 919,
    "preview": "# Vocabulary Cheatsheet\n\n| USD Terminology                       | Meaning                                  |\n|---------"
  },
  {
    "path": "docs/src/pages/core/overview.md",
    "chars": 858,
    "preview": "# USD Essentials\nIn our essentials section, we cover the basics of USD from a software developer perspective.\n\nThat mean"
  },
  {
    "path": "docs/src/pages/core/plugins/assetresolver.md",
    "chars": 16220,
    "preview": "# Asset Resolver\nThe [Asset Resolver](https://openusd.org/dev/api/ar_page_front.html) is one of those core Usd topics yo"
  },
  {
    "path": "docs/src/pages/core/plugins/kind.md",
    "chars": 6401,
    "preview": "# Kinds\nThe [kind](https://openusd.org/release/glossary.html#usdglossary-kind) metadata is a special metadata entry on p"
  },
  {
    "path": "docs/src/pages/core/plugins/metadata.md",
    "chars": 4875,
    "preview": "# Metadata\nUSD allows us to extend the base metadata that is attached to every layer, prim and property (Supported are `"
  },
  {
    "path": "docs/src/pages/core/plugins/overview.md",
    "chars": 4269,
    "preview": "# Plugin System\nUsd has a plugin system over which individual components are loaded.\n\n~~~admonish Abstract title=\"Usd Pi"
  },
  {
    "path": "docs/src/pages/core/plugins/schemas.md",
    "chars": 15955,
    "preview": "# Schemas\n~~~admonish important\nThis page only covers how to compile/install custom schemas, as we cover what schemas ar"
  },
  {
    "path": "docs/src/pages/core/profiling/debug.md",
    "chars": 11118,
    "preview": "# Debugging\nThe Usd API ships with a [debug class](https://openusd.org/dev/api/class_tf_debug.html), which allows you to"
  },
  {
    "path": "docs/src/pages/core/profiling/overview.md",
    "chars": 593,
    "preview": "# Debugging & Performance Profiling\nUsd ships with extensive debugging and profiling tools. You can inspect the code exe"
  },
  {
    "path": "docs/src/pages/core/profiling/profiling.md",
    "chars": 4119,
    "preview": "# Performance Profiling\nFor low level profiling Usd ships with the `trace` profiling module.\n\nThis is also what a few DC"
  },
  {
    "path": "docs/src/pages/core/resources.md",
    "chars": 3945,
    "preview": "# Resources\nIf you are interested in diving into topics yourself, here is a rough categorization:\n\n### General\n- [C++ Cl"
  },
  {
    "path": "docs/src/pages/dcc/houdini/approach.md",
    "chars": 23060,
    "preview": "# General Approach\n~~~admonish question title=\"Still under construction!\"\nWe'll expand our Houdini section in the future"
  },
  {
    "path": "docs/src/pages/dcc/houdini/faq/overview.md",
    "chars": 10068,
    "preview": "# Tips & Tricks\nYou can find all the .hip files of our shown examples in our [USD Survival Guide - GitHub Repo](https://"
  },
  {
    "path": "docs/src/pages/dcc/houdini/fx/deformingMeshes.md",
    "chars": 19,
    "preview": "# Deforming Meshes\n"
  },
  {
    "path": "docs/src/pages/dcc/houdini/fx/frustumCulling.md",
    "chars": 1339,
    "preview": "# Frustum Culling\nUSD also ships with 3d related classes in the `Gf` module. These allow us to also do bounding box inte"
  },
  {
    "path": "docs/src/pages/dcc/houdini/fx/motionblur.md",
    "chars": 1222,
    "preview": "# Motion Blur\nMotion blur is computed by the hydra delegate of your choice using either the interpolated position data(d"
  },
  {
    "path": "docs/src/pages/dcc/houdini/fx/overview.md",
    "chars": 420,
    "preview": "# Handeling Geometry Input/Output and FX\n~~~admonish question title=\"Still under construction!\"\nWe'll expand this sectio"
  },
  {
    "path": "docs/src/pages/dcc/houdini/fx/particles.md",
    "chars": 7255,
    "preview": "# Particles\nImporting particles (points) is the simplest form of geometry import.\n\nLet's see how we can make it complica"
  },
  {
    "path": "docs/src/pages/dcc/houdini/fx/pointinstancers.md",
    "chars": 8466,
    "preview": "# Point Instancers ('Copy To Points')\nWe have four options for mapping Houdini's packed prims to USD:\n- As transforms\n- "
  },
  {
    "path": "docs/src/pages/dcc/houdini/fx/rbd.md",
    "chars": 6853,
    "preview": "# RBD (Rigid Body Dynamics)\nAs mentioned in our [Point Instancer](./pointinstancers.md) section, we have four options fo"
  },
  {
    "path": "docs/src/pages/dcc/houdini/fx/transformspace.md",
    "chars": 98,
    "preview": "# Transform Space (Local/World Space)\nLarge Scale Scenes - Precision Issues\n- local space velocity"
  },
  {
    "path": "docs/src/pages/dcc/houdini/fx/volumes.md",
    "chars": 10,
    "preview": "# Volumes\n"
  },
  {
    "path": "docs/src/pages/dcc/houdini/hda/overview.md",
    "chars": 11822,
    "preview": "# Creating efficient LOPs HDAs\nAs with any other network in Houdini, we can also create HDAs in LOPs.\n\nThis page will fo"
  },
  {
    "path": "docs/src/pages/dcc/houdini/overview.md",
    "chars": 844,
    "preview": "# Houdini\nHoudini's USD implementation, codenamed Solaris, is one of the most easy to use and \"getting started to USD\" e"
  },
  {
    "path": "docs/src/pages/dcc/houdini/performance/overview.md",
    "chars": 14736,
    "preview": "# Performance Optimizations\nYou can find all the .hip files of our shown examples in our [USD Survival Guide - GitHub Re"
  },
  {
    "path": "docs/src/pages/dcc/overview.md",
    "chars": 24,
    "preview": "# Software Integrations\n"
  },
  {
    "path": "docs/src/pages/introduction/docs.md",
    "chars": 1324,
    "preview": "# Documentation\n\nIf you want to locally build this documentation, you'll have to download [mdBook](https://github.com/ru"
  },
  {
    "path": "docs/src/pages/introduction/future.md",
    "chars": 136,
    "preview": "# Future Development\n\nWe do not cover the following topics yet:\n- Cameras\n- Render related schemas\n- USD C++\n- OCIO\n- Re"
  },
  {
    "path": "docs/src/pages/introduction/motivation.md",
    "chars": 3143,
    "preview": "\n# Motivation\nAs [USD](https://openusd.org/release/index.html) has been consistently increasing its market share in the "
  },
  {
    "path": "docs/src/pages/introduction/structure.md",
    "chars": 4440,
    "preview": "\n# Structure\nOn this page will talk about how this guide is structured and what the best approach to reading it is.\n\n# T"
  },
  {
    "path": "docs/src/pages/production/caches/attribute.md",
    "chars": 1523,
    "preview": "# Attribute Queries <a name=\"attribute\"></a>\nWhen we query attribute via `Usd.Attribute.Get()`, the value source resolut"
  },
  {
    "path": "docs/src/pages/production/caches/boundingbox.md",
    "chars": 1274,
    "preview": "# Bounding Box Queries <a name=\"boundingbox\"></a>\nWhenever we change our geometry data, we have to update our \"extents\" "
  },
  {
    "path": "docs/src/pages/production/caches/collection.md",
    "chars": 1697,
    "preview": "# Collection Membership\nLet's have a look at how we can query if a prim path is in a collection. For more info about how"
  },
  {
    "path": "docs/src/pages/production/caches/composition.md",
    "chars": 1573,
    "preview": "# Composition Query\nNext let's look at prim composition queries. Instead of having to filter the prim index ourselves, w"
  },
  {
    "path": "docs/src/pages/production/caches/materialbinding.md",
    "chars": 705,
    "preview": "# Material Binding <a name=\"materialBinding\"></a>\n~~~admonish question title=\"Still under construction!\"\nThis sub-sectio"
  },
  {
    "path": "docs/src/pages/production/caches/overview.md",
    "chars": 634,
    "preview": "# Stage API Query Caches\nWhen inspecting stages, we often want to query a lot of data.\n\nSome types of data, like transfo"
  },
  {
    "path": "docs/src/pages/production/caches/xform.md",
    "chars": 735,
    "preview": "# Xform Queries <a name=\"xform\"></a>\nAs mentioned in our [transforms section](../../core/elements/transform.md), we can "
  },
  {
    "path": "docs/src/pages/production/composition.md",
    "chars": 6482,
    "preview": "# A practical guide to composition\n~~~admonish question title=\"Still under construction!\"\nAs composition is USD's most c"
  },
  {
    "path": "docs/src/pages/production/concepts.md",
    "chars": 8946,
    "preview": "# Advanced Concepts\n\n# Table of Contents\n1. [Edit Targets](#editTargets)\n1. [Utility functions in the Usd.Utils module]("
  },
  {
    "path": "docs/src/pages/production/faq.md",
    "chars": 2617,
    "preview": "# FAQ (Frequently Asked Questions)\n\n# Table of Contents\n1. [Should I prefer assets with a lot of prims or prefer combine"
  },
  {
    "path": "docs/src/pages/production/overview.md",
    "chars": 203,
    "preview": "# USD in Production\nIn this section we'll take a look at USD from a production perspective.\n\nIt aims to cover more highe"
  },
  {
    "path": "docs/src/pages/production/prerequisites.md",
    "chars": 3025,
    "preview": "# 'Are we ready for production'? Here is a preflight checklist for your USD pipeline\nNow that you know the basics (if yo"
  },
  {
    "path": "docs/src/pages/production/schemas.md",
    "chars": 2770,
    "preview": "# Commonly used schemas ('Classes' in OOP terminology) for production\n\nHere is a list of the most used production schema"
  },
  {
    "path": "docs/src/template.md",
    "chars": 1696,
    "preview": "# Section Name\nEnter example intro.\n\n~~~admonish question title=\"Still under construction!\"\nThis sub-section is still un"
  },
  {
    "path": "docs/theme/ext/css/custom.css",
    "chars": 567,
    "preview": "table {\n    width:100%;\n}\n\n:root {\n    --sidebar-width: 485px;\n    --content-max-width: 1300px;\n}\n\n.chapter li {\n    col"
  },
  {
    "path": "docs/theme/ext/css/mdbook-admonish.css",
    "chars": 13192,
    "preview": "@charset \"UTF-8\";\n:root {\n  --md-admonition-icon--note:\n    url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www"
  },
  {
    "path": "docs/theme/ext/js/custom.js",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "docs/theme/ext/js/mermaid-init.js",
    "chars": 40,
    "preview": "mermaid.initialize({startOnLoad:true});\n"
  },
  {
    "path": "docs/theme/head.hbs.bkp",
    "chars": 278,
    "preview": "<!-- SEO \n<meta name=\"robots\" content=\"index, follow\">\n<meta name=\"googlebot\" content=\"index, follow, max-snippet:-1, ma"
  },
  {
    "path": "docs/theme/header.hbs",
    "chars": 541,
    "preview": "\n<div  class=\"\" style=\"display: none; width:100%; position: relative; top: 25.0px; margin-bottom: -45.0px; z-index: 1000"
  },
  {
    "path": "docs.bat",
    "chars": 145,
    "preview": "REM Source setup\nset REPO_ROOT=%~dp0\nREM Clean existing build\nrmdir %REPO_ROOT%docs\\book /S /Q\nREM Build book\nmdbook ser"
  },
  {
    "path": "docs.sh",
    "chars": 220,
    "preview": "# Source setup\nexport REPO_ROOT=$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" &> /dev/null && (pwd -W 2> /dev/null || pwd))\n# Cl"
  },
  {
    "path": "files/composition/pixar/faq/WhenCanYouDeleteAReference/assembly.usda",
    "chars": 512,
    "preview": "#usda 1.0\n(\n    defaultPrim = \"FlexibleSet\"\n)\n\ndef Xform \"FlexibleSet\"\n{\n    def \"Model_1\" (\n        prepend variantSets"
  },
  {
    "path": "files/composition/pixar/faq/WhenCanYouDeleteAReference/assembly_with_all_variants.usda",
    "chars": 604,
    "preview": "#usda 1.0\n(\n    defaultPrim = \"FlexibleSet\"\n)\n\ndef Xform \"FlexibleSet\"\n{\n    def \"Model_1\" (\n        prepend variantSets"
  },
  {
    "path": "files/composition/pixar/faq/WhenCanYouDeleteAReference/assets.usda",
    "chars": 204,
    "preview": "#usda 1.0\n\ndef Xform \"CubeModel\"\n{\n    custom int levelOfNesting = 0\n\n    def Cube \"Gprim\"\n    {\n    }\n}\n\ndef Xform \"Sph"
  },
  {
    "path": "files/composition/pixar/faq/WhenCanYouDeleteAReference/shot.usda",
    "chars": 556,
    "preview": "#usda 1.0\n(\n    defaultPrim = \"World\"\n)\n\ndef Xform \"World\"\n{\n    def \"ShapeFactory\" (\n        references = @assembly.usd"
  },
  {
    "path": "files/composition/pixar/faq/WhenCanYouDeleteAReference/shot_variant_switch.usda",
    "chars": 314,
    "preview": "#usda 1.0\n(\n    defaultPrim = \"World\"\n)\n\ndef Xform \"World\"\n{\n    def \"ShapeFactory\" (\n        references = @assembly_wit"
  },
  {
    "path": "files/composition/pixar/glossary/inherits/Forest.usd",
    "chars": 399,
    "preview": "#usda 1.0\n\n# A new prim, of the same name as the original inherits target, providing new overrides\nclass \"_class_Tree\"\n{"
  },
  {
    "path": "files/composition/pixar/glossary/inherits/Trees.usd",
    "chars": 408,
    "preview": "#usda 1.0\n\nclass Xform \"_class_Tree\"\n{\n    def Mesh \"Trunk\"\n    {\n        color3f[] primvars:displayColor = [(.8, .8, .2"
  },
  {
    "path": "files/composition/pixar/glossary/references/FlattenedMarbleCollection.usd",
    "chars": 671,
    "preview": "#usda 1.0\n\ndef Xform \"MarbleCollection\" (\n    kind = \"assembly\"\n)\n{\n    def Xform \"Marble_Green\" (\n        kind = \"compo"
  },
  {
    "path": "files/composition/pixar/glossary/references/Marble.usd",
    "chars": 189,
    "preview": "#usda 1.0\n(\n    defaultPrim = \"Marble\"\n)\n\ndef Xform \"Marble\" (\n    kind = \"component\"\n)\n{\n    def Sphere \"marble_geom\"\n "
  },
  {
    "path": "files/composition/pixar/glossary/references/MarbleCollection.usd",
    "chars": 559,
    "preview": "#usda 1.0\n\ndef Xform \"MarbleCollection\" (\n    kind = \"assembly\"\n)\n{\n    def \"Marble_Green\" (\n            references = @M"
  },
  {
    "path": "files/composition/pixar/glossary/specializes/Robot.usd",
    "chars": 1152,
    "preview": "#usda 1.0\n\ndef Xform \"Robot\"\n{\n    def Scope \"Materials\"\n    {\n        def Material \"Metal\"\n        {\n            # Inte"
  },
  {
    "path": "files/composition/pixar/glossary/specializes/RobotScene.usd",
    "chars": 403,
    "preview": "#usda 1.0\n\ndef Xform \"World\"\n{\n    def Xform \"Characters\"\n    {\n        def \"Rosie\" (\n            references = @./Robot."
  },
  {
    "path": "files/composition/usdSurvivalGuide/.gitignore",
    "chars": 7,
    "preview": "*.usdnc"
  },
  {
    "path": "files/dcc/houdini/points/pythonWrangle.py",
    "chars": 6845,
    "preview": "import pxr\nimport numpy as np\n\nclass Tokens():\n    mode = \"vfxSurvivalGuide:attributeKernel:mode\"\n    module_code = \"vfx"
  },
  {
    "path": "files/dcc/houdini/points/renderPreFrame.py",
    "chars": 303,
    "preview": "import os\nimport sys\nfrom imp import reload\n# Python Wrangle Module\ndir_path = os.path.dirname(hou.hipFile.path())\nif di"
  },
  {
    "path": "files/dcc/houdini/profiling/report.json",
    "chars": 7167,
    "preview": "{\"traceEvents\":[{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__:"
  },
  {
    "path": "files/dcc/houdini/profiling/report.trace",
    "chars": 3229,
    "preview": "\nTree view  ==============\n   inclusive    exclusive        \n    0.519 ms     0.246 ms       1 samples    Main Thread\n  "
  },
  {
    "path": "files/plugins/kinds/plugInfo.json",
    "chars": 980,
    "preview": "{\n    \"Plugins\":[\n       {\n           \"Type\": \"python\",\n           \"Name\": \"usdSurvivalGuideKinds\", \n         \"Info\":{\n "
  },
  {
    "path": "files/plugins/metadata/plugInfo.json",
    "chars": 776,
    "preview": "{\n   \"Plugins\": [\n       {\n           \"Name\": \"usdSurvivalGuideMetadata\",\n           \"Type\": \"resource\",\n           \"Inf"
  },
  {
    "path": "files/plugins/schemas/codelessSchema/build.sh",
    "chars": 672,
    "preview": "# Source setup\nif [ ! $REPO_SOURCED ]\nthen\n    source ../../../setup.sh\nfi\n# Clear existing build data\nrm -R dist\n# Invo"
  },
  {
    "path": "files/plugins/schemas/codelessSchema/dist/generatedSchema.usda",
    "chars": 1044,
    "preview": "#usda 1.0\n(\n    \"WARNING: THIS FILE IS GENERATED BY usdGenSchema.  DO NOT EDIT.\"\n)\n\nclass \"SimplePrim\" (\n    doc = \"\"\"An"
  },
  {
    "path": "files/plugins/schemas/codelessSchema/dist/plugInfo.json",
    "chars": 1674,
    "preview": "# Portions of this file auto-generated by usdGenSchema.\n# Edits will survive regeneration except for comments and\n# chan"
  },
  {
    "path": "files/plugins/schemas/codelessSchema/schema.usda",
    "chars": 2121,
    "preview": "#usda 1.0\n(\n    \"\"\" This file contains an example schemata for code generation using\n        usdGenSchema.\n    \"\"\"\n    s"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/.gitignore",
    "chars": 5,
    "preview": "dist\n"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/CMakeLists.txt",
    "chars": 5436,
    "preview": "### Configuration ###\n# Here we declare some custom variables that configure namings\nset(USDSG_PROJECT_NAME UsdExamplesS"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/auxiliary/__init__.py",
    "chars": 1109,
    "preview": "#\n# Copyright 2016 Pixar\n#\n# Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n# with the following "
  },
  {
    "path": "files/plugins/schemas/compiledSchema/auxiliary/module.cpp",
    "chars": 1381,
    "preview": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the follo"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/auxiliary/moduleDeps.cpp",
    "chars": 1739,
    "preview": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the follo"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/build.sh",
    "chars": 745,
    "preview": "# Source setup\nif [ ! $REPO_SOURCED ]\nthen\n    source ../../../setup.sh\nfi\n# Clear existing build data\nrm -R src\n# Invok"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/schema.usda",
    "chars": 2082,
    "preview": "#usda 1.0\n(\n    \"\"\" This file contains an example schemata for code generation using\n        usdGenSchema.\n    \"\"\"\n    s"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/__init__.py",
    "chars": 1109,
    "preview": "#\n# Copyright 2016 Pixar\n#\n# Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n# with the following "
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/api.h",
    "chars": 2004,
    "preview": "//\n// Copyright 2017 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the follo"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/complex.cpp",
    "chars": 4891,
    "preview": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the follo"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/complex.h",
    "chars": 7169,
    "preview": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the follo"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/generatedSchema.usda",
    "chars": 1044,
    "preview": "#usda 1.0\n(\n    \"WARNING: THIS FILE IS GENERATED BY usdGenSchema.  DO NOT EDIT.\"\n)\n\nclass \"SimplePrim\" (\n    doc = \"\"\"An"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/module.cpp",
    "chars": 1381,
    "preview": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the follo"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/moduleDeps.cpp",
    "chars": 1739,
    "preview": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the follo"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/paramsAPI.cpp",
    "chars": 5895,
    "preview": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the follo"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/paramsAPI.h",
    "chars": 9243,
    "preview": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the follo"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/plugInfo.json",
    "chars": 1735,
    "preview": "# Portions of this file auto-generated by usdGenSchema.\n# Edits will survive regeneration except for comments and\n# chan"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/simple.cpp",
    "chars": 4417,
    "preview": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the follo"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/simple.h",
    "chars": 6352,
    "preview": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the follo"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/tokens.cpp",
    "chars": 1736,
    "preview": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the follo"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/tokens.h",
    "chars": 3478,
    "preview": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the follo"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/wrapComplex.cpp",
    "chars": 4094,
    "preview": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the follo"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/wrapParamsAPI.cpp",
    "chars": 5827,
    "preview": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the follo"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/wrapSimple.cpp",
    "chars": 4074,
    "preview": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the follo"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/wrapTokens.cpp",
    "chars": 2797,
    "preview": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the follo"
  },
  {
    "path": "files/plugins/schemas/exampleSchema.usda",
    "chars": 2082,
    "preview": "#usda 1.0\n(\n    \"\"\" This file contains an example schemata for code generation using\n        usdGenSchema.\n    \"\"\"\n    s"
  },
  {
    "path": "setup.sh",
    "chars": 394,
    "preview": "# Source repo\nif [ ! $REPO_SOURCED ]\nthen\n    # Define repo root\n    export REPO_SOURCED=1\n    export REPO_ROOT=$(cd \"$("
  }
]

// ... and 21 more files (download for full content)

About this extraction

This page contains the full source code of the LucaScheller/VFX-UsdSurvivalGuide GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 165 files (960.8 KB), approximately 253.6k tokens, and a symbol index with 98 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!