[
  {
    "path": ".github/workflows/mdbook.yml",
    "content": "name: Deploy Documentation to GitHub Pages\n\non:\n  push:\n    branches: [\"main\"]\n  workflow_dispatch:\n\npermissions:\n  contents: read\n  pages: write\n  id-token: write\n\nconcurrency:\n  group: \"pages\"\n  cancel-in-progress: false\n\njobs:\n\n  build:\n    runs-on: ubuntu-latest\n    env:\n      MDBOOK_VERSION: 0.4.28         # MDBOOK_ADMONISH is depends on this exact build.\n      MDBOOK_ADMONISH_VERSION: 1.9.0\n      MDBOOK_MERMAID_VERSION: 0.12.6\n      MDBOOK_SITEMAP_VERSION: 0.1.0\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v4\n      - name: Install mdBook\n        run: |\n          mkdir ~/tools\n          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\n          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\n          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\n          echo ~/tools >> $GITHUB_PATH\n      - name: Install static-sitemap-cli\n        run: npm install static-sitemap-cli\n      - name: Setup Pages\n        id: pages\n        uses: actions/configure-pages@v5\n      - name: Build with mdBook\n        run: mdbook build -d book docs\n      - name: Generate sitemap\n        run: |\n          cd docs/book\n          npx sscli --no-clean --base https://lucascheller.github.io/VFX-UsdSurvivalGuide\n          cd ../..\n      - name: Upload artifact\n        uses: actions/upload-pages-artifact@v3\n        with:\n          path: docs/book\n\n  deploy:\n    environment:\n      name: github-pages\n      url: ${{ steps.deployment.outputs.page_url }}\n    runs-on: ubuntu-latest\n    needs: build\n    steps:\n      - name: Deploy to GitHub Pages\n        id: deployment\n        uses: actions/deploy-pages@v4"
  },
  {
    "path": ".gitignore",
    "content": "workspace\nplayground\nbackup\nbuild\ntools\ndocs/book\nexamples\ngeo\n*.code-workspace\n*.vscode\n*.so\n__pycache__"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "README.md",
    "content": "![Usd Survival Guide](https://raw.githubusercontent.com/LucaScheller/VFX-UsdSurvivalGuide/main/docs/src/media/UsdSurvivalGuide.png)\n\n## USD Survival Guide\n[![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)\n\nThis repository aims to be a practical onboarding guide to [USD](https://openusd.org/release/index.html) for software developers and pipeline TDs.\nFor more information what makes this guide unique, see the [motivation](https://lucascheller.github.io/VFX-UsdSurvivalGuide/pages/introduction/motivation.html) section.\n\nCheck out the guide's website: [Usd Survival Guide GitHub Pages Website](https://lucascheller.github.io/VFX-UsdSurvivalGuide/)\n\n## Contributing and Acknowledgements\n\nPlease 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).\n\nFeel free to fork this repository and share improvements.\nIf you run into issues, please flag them by [submitting a ticket](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/issues/new).\n\n## Contributors:\nFor a full list of who contributed to this guide visit:\n[Usd Survival Guide - Introduction](https://lucascheller.github.io/VFX-UsdSurvivalGuide/)"
  },
  {
    "path": "code/core/composition.py",
    "content": "#// ANCHOR: compositionEditTarget\nfrom pxr import Sdf, Usd\n## Standard way of using edit targets\nstage = Usd.Stage.CreateInMemory()\nroot_layer = stage.GetRootLayer()\na_layer = Sdf.Layer.CreateAnonymous(\"LayerA\")\nb_layer = Sdf.Layer.CreateAnonymous(\"LayerB\")\nroot_layer.subLayerPaths.append(a_layer.identifier)\nroot_layer.subLayerPaths.append(b_layer.identifier)\n# Direct edits to different layers\nstage.SetEditTarget(Usd.EditTarget(a_layer))\nbicycle_prim = stage.DefinePrim(Sdf.Path(\"/bicycle\"), \"Xform\")\nstage.SetEditTarget(Usd.EditTarget(b_layer))\ncar_prim = stage.DefinePrim(Sdf.Path(\"/car\"), \"Xform\")\nprint(b_layer.ExportToString())\n\"\"\"Returns:\n#sdf 1.4.32\ndef Xform \"car\"\n{\n}\n\"\"\"\n## Reference/Payload Edit Targets\nasset_stage = Usd.Stage.CreateInMemory()\ncube_prim = asset_stage.DefinePrim(Sdf.Path(\"/root/RENDER/cube\"), \"Xform\")\nasset_layer = asset_stage.GetRootLayer()\nshot_stage = Usd.Stage.CreateInMemory()\ncar_prim = shot_stage.DefinePrim(Sdf.Path(\"/set/garage/car\"), \"Xform\")\ncar_prim.GetReferences().AddReference(asset_layer.identifier, Sdf.Path(\"/root\"), Sdf.LayerOffset(10))\n# We can't construct edit targets to layers that are not sublayers in the active layer stack.\n# Is this a bug? According to the docs https://openusd.org/dev/api/class_usd_edit_target.html it should work.\n# shot_stage.SetEditTarget(Usd.EditTarget(asset_layer))\n## Variant Edit Targets\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nbicycle_prim_path = Sdf.Path(\"/bicycle\")\nbicycle_prim = stage.DefinePrim(bicycle_prim_path, \"Xform\")\nvariant_sets_api = bicycle_prim.GetVariantSets()\nvariant_set_api = variant_sets_api.AddVariantSet(\"color\", position=Usd.ListPositionBackOfPrependList)\nvariant_set_api.AddVariant(\"colorA\")\nvariant_set_api.SetVariantSelection(\"colorA\")\nwith variant_set_api.GetVariantEditContext():\n    # Anything we write in this edit target context, goes into the variant.\n    cube_prim_path = bicycle_prim_path.AppendChild(\"cube\")\n    cube_prim = stage.DefinePrim(cube_prim_path, \"Cube\")\nprint(stage.GetEditTarget().GetLayer().ExportToString())\n\"\"\"Returns:\n#usda 1.0\n\ndef Xform \"bicycle\" (\n    variants = {\n        string color = \"colorA\"\n    }\n    prepend variantSets = \"color\"\n)\n{\n    variantSet \"color\" = {\n        \"colorA\" {\n            def Cube \"cube\"\n            {\n            }\n\n        }\n    }\n}\n\"\"\"\n#// ANCHOR_END: compositionEditTarget\n\n\n#// ANCHOR: compositionEditTargetContext\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nroot_layer = stage.GetRootLayer()\na_layer = Sdf.Layer.CreateAnonymous(\"LayerA\")\nb_layer = Sdf.Layer.CreateAnonymous(\"LayerB\")\nroot_layer.subLayerPaths.append(a_layer.identifier)\nroot_layer.subLayerPaths.append(b_layer.identifier)\n# Set edit target to a_layer\nstage.SetEditTarget(a_layer)\nbicycle_prim_path = Sdf.Path(\"/bicycle\")\nbicycle_prim = stage.DefinePrim(bicycle_prim_path, \"Xform\")\nedit_target = Usd.EditTarget(b_layer)\nwith Usd.EditContext(stage, edit_target):\n    print(\"Edit Target Layer:\", stage.GetEditTarget().GetLayer()) # Edit Target Layer: Sdf.Find('anon:0x7ff9f4391580:LayerB')\n    car_prim_path = Sdf.Path(\"/car\")\n    car_prim = stage.DefinePrim(car_prim_path, \"Xform\")\nprint(\"Edit Target Layer:\", stage.GetEditTarget().GetLayer()) # Edit Target Layer: Sdf.Find('anon:0x7ff9f4391580:LayerA')\n# Verify result\nprint(a_layer.ExportToString())\n\"\"\"Returns:\n#sdf 1.4.32\ndef Xform \"bicycle\"\n{\n}\n\"\"\"\nprint(b_layer.ExportToString())\n\"\"\"Returns:\n#sdf 1.4.32\ndef Xform \"car\"\n{\n}\n\"\"\"\n#// ANCHOR_END: compositionEditTargetContext\n\n#// ANCHOR: compositionListEditableOpsBasics\nfrom pxr import Sdf\n# Sdf.ReferenceListOp, Sdf.PayloadListOp, Sdf.PathListOp,\npath_list_op = Sdf.PathListOp()\n# There are multiple sub-lists, which are just normal Python lists.\n# 'prependedItems', 'appendedItems', 'deletedItems', 'explicitItems',\n# Legacy sub-lists (do not use these anymore): 'addedItems', 'orderedItems'\n# Currently the way these are exposed to Python, you have to re-assign the list, instead of editing it in place.\n# So this won't work:\npath_list_op.prependedItems.append(Sdf.Path(\"/cube\"))\npath_list_op.appendedItems.append(Sdf.Path(\"/sphere\"))\n# Instead do this:\npath_list_op.prependedItems = [Sdf.Path(\"/cube\")]\npath_list_op.appendedItems = [Sdf.Path(\"/sphere\")]\n# To clear the list op:\nprint(path_list_op) # Returns: SdfPathListOp(Prepended Items: [/cube], Appended Items: [/sphere])\npath_list_op.Clear()\nprint(path_list_op) # Returns: SdfPathListOp()\n# Repopulate via constructor\npath_list_op = Sdf.PathListOp.Create(prependedItems = [Sdf.Path(\"/cube\")], appendedItems = [Sdf.Path(\"/sphere\")])\nprint(path_list_op) # Returns: SdfPathListOp(Prepended Items: [/cube], Appended Items: [/sphere])\n# Add remove items\npath_list_op.deletedItems = [Sdf.Path(\"/sphere\")]\nprint(path_list_op) # Returns: SdfPathListOp(Deleted Items: [/sphere], Prepended Items: [/cube], Appended Items: [/sphere])\n# Notice how it just stores lists, it doesn't actually apply them. We'll have a look at that next.\n\n# In the high level API, all the function signatures that work on list-editable ops\n# usually take a position kwarg which corresponds to what list to edit and the position (front/back)\nUsd.ListPositionFrontOfAppendList\nUsd.ListPositionBackOfAppendList\nUsd.ListPositionFrontOfPrependList\nUsd.ListPositionBackOfPrependList\n# We cover how to use this is our 'Composition Arcs' section.\n#// ANCHOR_END: compositionListEditableOpsBasics\n\n#// ANCHOR: compositionListEditableOpsMerging\nfrom pxr import Sdf\n### Merging basics ###\npath_list_op_layer_top = Sdf.PathListOp.Create(deletedItems = [Sdf.Path(\"/cube\")])\npath_list_op_layer_middle = Sdf.PathListOp.Create(prependedItems = [Sdf.Path(\"/disc\"), Sdf.Path(\"/cone\")])\npath_list_op_layer_bottom = Sdf.PathListOp.Create(prependedItems = [Sdf.Path(\"/cube\")], appendedItems = [Sdf.Path(\"/cone\"),Sdf.Path(\"/sphere\")])\n\nresult = Sdf.PathListOp()\nresult = result.ApplyOperations(path_list_op_layer_top)\nresult = result.ApplyOperations(path_list_op_layer_middle)\nresult = result.ApplyOperations(path_list_op_layer_bottom)\n# Notice how on merge it makes sure that each sublist does not have the values of the other sublists, just like a Python set()\nprint(result) # Returns: SdfPathListOp(Deleted Items: [/cube], Prepended Items: [/disc, /cone], Appended Items: [/sphere])\n# Get the flattened result. This does not apply the deleteItems, only ApplyOperations does that. \nprint(result.GetAddedOrExplicitItems()) # Returns: [Sdf.Path('/disc'), Sdf.Path('/cone'), Sdf.Path('/sphere')]\n\n### Deleted and added items ###\npath_list_op_layer_top = Sdf.PathListOp.Create(appendedItems=[Sdf.Path(\"/disc\"), Sdf.Path(\"/cube\")])\npath_list_op_layer_middle = Sdf.PathListOp.Create(deletedItems = [Sdf.Path(\"/cube\")])\npath_list_op_layer_bottom = Sdf.PathListOp.Create(prependedItems = [Sdf.Path(\"/cube\")], appendedItems = [Sdf.Path(\"/sphere\")])\n\nresult = Sdf.PathListOp()\nresult = result.ApplyOperations(path_list_op_layer_top)\nresult = result.ApplyOperations(path_list_op_layer_middle)\nresult = result.ApplyOperations(path_list_op_layer_bottom)\nprint(result) # Returns: SdfPathListOp(Appended Items: [/sphere, /disc, /cube])\n# Since it now was in the explicit list, it got removed.\n\n### Explicit mode ###\n# There is also an \"explicit\" mode. This clears all previous values on merge and marks the list as explicit.\n# Once explicit and can't be un-explicited. An explicit list is like a reset, it \n# doesn't know anything about the previous values anymore. All lists that are merged\n# after combine the result to be explicit.\npath_list_op_layer_top = Sdf.PathListOp.Create(deletedItems = [Sdf.Path(\"/cube\")])\npath_list_op_layer_middle = Sdf.PathListOp.CreateExplicit([Sdf.Path(\"/disc\")])\npath_list_op_layer_bottom = Sdf.PathListOp.Create(prependedItems = [Sdf.Path(\"/cube\")], appendedItems = [Sdf.Path(\"/sphere\")])\n\nresult = Sdf.PathListOp()\nresult = result.ApplyOperations(path_list_op_layer_top)\nresult = result.ApplyOperations(path_list_op_layer_middle)\nresult = result.ApplyOperations(path_list_op_layer_bottom)\nprint(result, result.isExplicit) # Returns: SdfPathListOp(Explicit Items: [/disc]), True\n# Notice how the deletedItems had no effect, as \"/cube\" is not in the explicit list.\n\npath_list_op_layer_top = Sdf.PathListOp.Create(deletedItems = [Sdf.Path(\"/cube\")])\npath_list_op_layer_middle = Sdf.PathListOp.CreateExplicit([Sdf.Path(\"/disc\"), Sdf.Path(\"/cube\")])\npath_list_op_layer_bottom = Sdf.PathListOp.Create(prependedItems = [Sdf.Path(\"/cube\")], appendedItems = [Sdf.Path(\"/sphere\")])\n\nresult = Sdf.PathListOp()\nresult = result.ApplyOperations(path_list_op_layer_top)\nresult = result.ApplyOperations(path_list_op_layer_middle)\nresult = result.ApplyOperations(path_list_op_layer_bottom)\nprint(result, result.isExplicit) # Returns: SdfPathListOp(Explicit Items: [/disc]), True\n# Since it now was in the explicit list, it got removed.\n#// ANCHOR_END: compositionListEditableOpsMerging\n\n\n#// ANCHOR: compositionArcSublayer\n# For sublayering we modify the .subLayerPaths attribute on a layer.\n# This is the same for both the high and low level API.\n### High Level & Low Level ###\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\n# Layer onto root layer\nlayer_a = Sdf.Layer.CreateAnonymous()\nlayer_b = Sdf.Layer.CreateAnonymous()\nroot_layer = stage.GetRootLayer()\n# Here we pass in the file paths (=layer identifiers).\nroot_layer.subLayerPaths.append(layer_a.identifier)\nroot_layer.subLayerPaths.append(layer_b.identifier)\n# Once we have added the sublayers, we can also access their layer offsets:\nprint(root_layer.subLayerOffsets) # Returns: [Sdf.LayerOffset(), Sdf.LayerOffset()]\n# Since layer offsets are read only copies, we need to assign a newly created \n# layer offset if we want to modify them. We also can't replace the whole list, as\n# it needs to keep a pointer to the array.\nlayer_offset_a = root_layer.subLayerOffsets[0]\nroot_layer.subLayerOffsets[0] = Sdf.LayerOffset(offset=layer_offset_a.offset + 10, \n                                                scale=layer_offset_a.scale * 2)\nlayer_offset_b = root_layer.subLayerOffsets[1]\nroot_layer.subLayerOffsets[1] = Sdf.LayerOffset(offset=layer_offset_b.offset - 10, \n                                                scale=layer_offset_b.scale * 0.5)\nprint(root_layer.subLayerOffsets) # Returns: [Sdf.LayerOffset(10, 2), Sdf.LayerOffset(-10, 0.5)]\n\n# If we want to sublayer on the active layer, we just add it there.\nlayer_c = Sdf.Layer.CreateAnonymous()\nactive_layer = stage.GetEditTarget().GetLayer()\nactive_layer.subLayerPaths.append(layer_c.identifier)\n#// ANCHOR_END: compositionArcSublayer\n\n\n#// ANCHOR: compositionArcSublayerHoudini\n### High Level & Low Level ###\nimport loputils\nfrom pxr import Sdf\n# Hou LOP Node https://www.sidefx.com/docs/houdini/hom/hou/LopNode.html\n# See $HFS/houdini/python3.9libs/loputils.py\n\"\"\"\ndef createPythonLayer(node, savepath=None):\n    # Tag the layer as \"LOP\" so we know it was created by LOPs.\n    layer = Sdf.Layer.CreateAnonymous('LOP')\n    # Add a Houdini Layer Info prim where we can put the save path.\n    p = Sdf.CreatePrimInLayer(layer, '/HoudiniLayerInfo')\n    p.specifier = Sdf.SpecifierDef\n    p.typeName = 'HoudiniLayerInfo'/stage/list_editable_ops/pythonscript6\n    if savepath:\n        p.customData['HoudiniSavePath'] = hou.text.expandString(savepath)\n        p.customData['HoudiniSaveControl'] = 'Explicit'\n    # Let everyone know what node created this layer.\n    p.customData['HoudiniCreatorNode'] = node.sessionId()\n    p.customData['HoudiniEditorNodes'] = Vt.IntArray([node.sessionId()])\n    node.addHeldLayer(layer.identifier)\n    return layer\n\"\"\"\n# Sublayer onto root layer via Python LOP node\nnode = hou.pwd()\nstage = node.editableStage()\nlayer = loputils.createPythonLayer(node, '$HIP/myfile.usda')\nnode.addSubLayer(layer.identifier)\n# This doesn't seem to work at the moment, as Houdini does some custom root layer handeling\n# print(root_layer.subLayerPaths) # Our added layer does not show up. So we have to use the `sublayer` node.\n# root_layer = stage.GetRootLayer()\n# root_layer.subLayerOffsets[0] = Sdf.LayerOffset(offset=10, scale=1)\n\n# Sublayer onto active layer via Python LOP node, here we can do the usual.\nnode = hou.pwd()\nlayer = node.editableLayer()\nlayer_a = loputils.createPythonLayer(node, '$HIP/myfile.usda')\nlayer.subLayerPaths.append(layer_a.identifier)\nlayer.subLayerOffsets[0] = Sdf.LayerOffset(offset=10, scale=1)\n\n# Since layers are automatically garbage collected once they go out of scope,\n# we can tag them to keep them persistently in memory for the active session.\nlayer_b = Sdf.Layer.CreateAnonymous()\nnode.addHeldLayer(layer_b.identifier)\n# This can then be re-used via the standard anywhere in Houdini.\nlayer_b = Sdf.Layer.FindOrOpen(layer_b.identifier)\n#// ANCHOR_END: compositionArcSublayerHoudini\n\n\n#// ANCHOR: compositionArcInherit\n### High Level ###\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nbicycle_prim_path = Sdf.Path(\"/bicycle\")\nbicycle_prim = stage.DefinePrim(bicycle_prim_path)\ncube_prim_path = Sdf.Path(\"/cube\")\ncube_prim = stage.DefinePrim(cube_prim_path, \"Cube\")\ninherits_api = bicycle_prim.GetInherits()\ninherits_api.AddInherit(cube_prim_path, position=Usd.ListPositionFrontOfAppendList)\n# inherits_api.SetInherits() # Clears the list editable ops and authors an Sdf.PathListOp.CreateExplicit([])\n# inherits_api.RemoveInherit(cube_prim_path)\n# inherits_api.ClearInherits() # Sdf.PathListOp.Clear()\n# inherits_api.GetAllDirectInherits() # Returns all inherits generated in the active layer stack\n### Low Level ###\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nbicycle_prim_path = Sdf.Path(\"/bicycle\")\nbicycle_prim_spec = Sdf.CreatePrimInLayer(layer, bicycle_prim_path)\nbicycle_prim_spec.specifier = Sdf.SpecifierDef\ncube_prim_path = Sdf.Path(\"/cube\")\ncube_prim_spec = Sdf.CreatePrimInLayer(layer, cube_prim_path)\ncube_prim_spec.specifier = Sdf.SpecifierDef\ncube_prim_spec.typeName = \"Cube\"\nbicycle_prim_spec.inheritPathList.appendedItems = [cube_prim_path]\n#// ANCHOR_END: compositionArcInherit\n\n#// ANCHOR: compositionArcVariant\n### High Level ###\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\n\nbicycle_prim_path = Sdf.Path(\"/bicycle\")\nbicycle_prim = stage.DefinePrim(bicycle_prim_path, \"Xform\")\n## Methods of Usd.VariantSets\n# Has: 'HasVariantSet'\n# Get: 'GetNames', 'GetVariantSet', 'GetVariantSelection', 'GetAllVariantSelections'\n# Set: 'AddVariantSet', 'SetSelection'\nvariant_sets_api = bicycle_prim.GetVariantSets()\n## Methods of Usd.VariantSet\n# Has: 'HasAuthoredVariant', 'HasAuthoredVariantSelection'\n# Get: 'GetName', 'GetVariantNames', 'GetVariantSelection', 'GetVariantEditContext', 'GetVariantEditTarget'\n# Set: 'AddVariant', 'SetVariantSelection'\n# Clear: 'BlockVariantSelection', 'ClearVariantSelection'\nvariant_set_api = variant_sets_api.AddVariantSet(\"color\", position=Usd.ListPositionBackOfPrependList)\nvariant_set_api.AddVariant(\"colorA\")\n# If we want to author on the selected variant, we have to select it first\nvariant_set_api.SetVariantSelection(\"colorA\")\nwith variant_set_api.GetVariantEditContext():\n    # Anything we write in the context, goes into the variant (prims and properties)\n    cube_prim_path = bicycle_prim_path.AppendChild(\"cube\")\n    cube_prim = stage.DefinePrim(cube_prim_path, \"Cube\")\n# We can also generate the edit target ourselves, but we still need to set the\n# variant selection, seems like a bug. Changing variants is a heavy op ...\nvariant_set_api.AddVariant(\"colorB\")\nvariant_set_api.SetVariantSelection(\"colorB\")\nvariant_prim_path = bicycle_prim_path.AppendVariantSelection(\"color\", \"colorB\") \nlayer = stage.GetEditTarget().GetLayer()\nedit_target = Usd.EditTarget.ForLocalDirectVariant(layer, variant_prim_path)\n# Or\nedit_target = variant_set_api.GetVariantEditTarget()\nedit_context = Usd.EditContext(stage, edit_target) \nwith edit_context as ctx:\n    sphere_prim_path = bicycle_prim_path.AppendChild(\"sphere\")\n    sphere_prim = stage.DefinePrim(\"/bicycle/sphere\", \"Sphere\")\n### Low Level ###\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nbicycle_prim_path = Sdf.Path(\"/bicycle\")\nbicycle_prim_spec = Sdf.CreatePrimInLayer(layer, bicycle_prim_path)\nbicycle_prim_spec.specifier = Sdf.SpecifierDef\nbicycle_prim_spec.typeName = \"Xform\"\n# Variants\ncube_prim_path = bicycle_prim_path.AppendVariantSelection(\"color\", \"colorA\").AppendChild(\"cube\")\ncube_prim_spec = Sdf.CreatePrimInLayer(layer, cube_prim_path)\ncube_prim_spec.specifier = Sdf.SpecifierDef\ncube_prim_spec.typeName = \"Cube\"\nsphere_prim_path = bicycle_prim_path.AppendVariantSelection(\"color\", \"colorB\").AppendChild(\"sphere\")\nsphere_prim_spec = Sdf.CreatePrimInLayer(layer, sphere_prim_path)\nsphere_prim_spec.specifier = Sdf.SpecifierDef\nsphere_prim_spec.typeName = \"Sphere\"\n# Variant Selection\nbicycle_prim_spec.variantSelections[\"color\"] = \"colorA\"\n\n# We can also author the variants via variant specs\nlayer = Sdf.Layer.CreateAnonymous()\ncar_prim_path = Sdf.Path(\"/car\")\ncar_prim_spec = Sdf.CreatePrimInLayer(layer, car_prim_path)\ncar_prim_spec.specifier = Sdf.SpecifierDef\ncar_prim_spec.typeName = \"Xform\"\n# Variants\nvariant_set_spec = Sdf.VariantSetSpec(car_prim_spec, \"color\")\nvariant_spec = Sdf.VariantSpec(variant_set_spec, \"colorA\")\ncube_prim_spec = Sdf.PrimSpec(variant_spec.primSpec, \"cube\", Sdf.SpecifierDef)\ncube_prim_spec.typeName = \"Cube\"\nvariant_spec = Sdf.VariantSpec(variant_set_spec, \"colorB\")\ncube_prim_spec = Sdf.PrimSpec(variant_spec.primSpec, \"sphere\", Sdf.SpecifierDef)\ncube_prim_spec.typeName = \"Sphere\"\n# Ironically this does not setup the variant set names metadata, so we have to author it ourselves.\ncar_prim_spec.SetInfo(\"variantSetNames\", Sdf.StringListOp.Create(prependedItems=[\"color\"]))\n# Variant Selection\ncar_prim_spec.variantSelections[\"color\"] = \"colorA\"\n#// ANCHOR_END: compositionArcVariant\n\n#// ANCHOR: compositionArcVariantCopySpec\nfrom pxr import Sdf\n# Spawn other layer, this usually comes from other stages, that your DCC creates/owns.\nsome_other_layer = Sdf.Layer.CreateAnonymous()\nroot_prim_path = Sdf.Path(\"/root\")\ncube_prim_path = Sdf.Path(\"/root/cube\")\ncube_prim_spec = Sdf.CreatePrimInLayer(some_other_layer, cube_prim_path)\ncube_prim_spec.specifier = Sdf.SpecifierDef\ncube_prim_spec.typeName = \"Cube\"\n# Create demo layer\nbicycle_prim_path = Sdf.Path(\"/bicycle\")\nbicycle_prim_spec = Sdf.CreatePrimInLayer(layer, bicycle_prim_path)\nbicycle_prim_spec.specifier = Sdf.SpecifierDef\nbicycle_prim_spec.typeName = \"Xform\"\n# Copy content into variant\nvariant_set_spec = Sdf.VariantSetSpec(bicycle_prim_spec, \"color\")\nvariant_spec = Sdf.VariantSpec(variant_set_spec, \"colorA\")\nvariant_prim_path = bicycle_prim_path.AppendVariantSelection(\"color\", \"colorA\")\nSdf.CopySpec(some_other_layer, root_prim_path, layer, variant_prim_path)\n# Variant selection\nbicycle_prim_spec.SetInfo(\"variantSetNames\", Sdf.StringListOp.Create(prependedItems=[\"color\"]))\nbicycle_prim_spec.variantSelections[\"color\"] = \"colorA\"\n#// ANCHOR_END: compositionArcVariantCopySpec\n\n#// ANCHOR: compositionArcVariantCopyHoudini\nfrom pxr import Sdf, Usd\n\nnode = hou.pwd()\nlayer = node.editableLayer()\n\nsource_node = node.parm(\"spare_input0\").evalAsNode()\nsource_stage = source_node.stage()\nsource_layer = source_node.activeLayer()\n\nwith Sdf.ChangeBlock():\n    iterator = iter(Usd.PrimRange(source_stage.GetPseudoRoot()))\n    for prim in iterator:\n        if \"GEO\" not in prim.GetChildrenNames():\n            continue\n        iterator.PruneChildren()\n        prim_path = prim.GetPath()\n        prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\n        prim_spec.specifier = Sdf.SpecifierDef\n        prim_spec.typeName = \"Xform\"\n        parent_prim_spec = prim_spec.nameParent\n        while parent_prim_spec:\n            parent_prim_spec.specifier = Sdf.SpecifierDef\n            parent_prim_spec.typeName = \"Xform\"\n            parent_prim_spec = parent_prim_spec.nameParent\n                    \n        # Copy content into variant\n        variant_set_spec = Sdf.VariantSetSpec(prim_spec, \"model\")\n        variant_spec = Sdf.VariantSpec(variant_set_spec, \"myCoolVariant\")\n        variant_prim_path = prim_path.AppendVariantSelection(\"model\", \"myCoolVariant\")\n        Sdf.CopySpec(source_layer, prim_path, layer, variant_prim_path)\n        # Variant selection\n        prim_spec.SetInfo(\"variantSetNames\", Sdf.StringListOp.Create(prependedItems=[\"model\"]))\n        prim_spec.variantSelections[\"model\"] = \"myCoolVariant\"\n#// ANCHOR_END: compositionArcVariantCopyHoudini\n\n#// ANCHOR: compositionArcVariantMoveHoudini\nfrom pxr import Sdf, Usd\n\nnode = hou.pwd()\nlayer = node.editableLayer()\n\nsource_node = node.parm(\"spare_input0\").evalAsNode()\nsource_stage = source_node.stage()\nsource_layer = source_node.activeLayer()\n\nwith Sdf.ChangeBlock():\n    edit = Sdf.BatchNamespaceEdit()\n\n    iterator = iter(Usd.PrimRange(source_stage.GetPseudoRoot()))\n    for prim in iterator:\n        if \"GEO\" not in prim.GetChildrenNames():\n            continue\n        iterator.PruneChildren()\n        prim_path = prim.GetPath()\n        prim_spec = layer.GetPrimAtPath(prim_path)\n        # Move content into variant\n        variant_set_spec = Sdf.VariantSetSpec(prim_spec, \"model\")\n        variant_spec = Sdf.VariantSpec(variant_set_spec, \"myCoolVariant\")\n        variant_prim_path = prim_path.AppendVariantSelection(\"model\", \"myCoolVariant\")\n        edit.Add(prim_path.AppendChild(\"GEO\"), variant_prim_path.AppendChild(\"GEO\"))\n        # Variant selection\n        prim_spec.SetInfo(\"variantSetNames\", Sdf.StringListOp.Create(prependedItems=[\"model\"]))\n        prim_spec.variantSelections[\"model\"] = \"myCoolVariant\"\n        \n    if not layer.Apply(edit):\n        raise Exception(\"Failed to apply layer edit!\")\n#// ANCHOR_END: compositionArcVariantMoveHoudini\n\n\n#// ANCHOR: compositionArcVariantNested\n### High Level ###\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\n\ndef variant_nested_edit_context(prim, variant_selections, position=Usd.ListPositionBackOfPrependList):\n    \"\"\"Author nested variants\n    Args:\n        prim (Usd.Prim): The prim to author on.\n        variant_selections (list): A list of tuples with [('variant_set_name', 'variant_name')] data.\n        position (Usd.ListPosition): The list position of the variant set.\n    Returns:\n        Usd.EditContext: An edit context manager.\n    \"\"\"\n    \n    if not variant_selections:\n        raise Exception(\"No valid variant selections defined!\")\n        \n    def _recursive_variant_context(prim, variant_selections, position):\n        variant_sets_api = bicycle_prim.GetVariantSets()\n        \n        variant_selection = variant_selections.pop(-1)\n        variant_set_name, variant_name = variant_selection\n        \n        variant_set_api = variant_sets_api.AddVariantSet(variant_set_name, position=position)\n        variant_set_api.AddVariant(variant_name)\n        # Be aware, this authors the selection in the variant\n        # ToDo make this a context manager that cleans up the selection authoring.\n        variant_set_api.SetVariantSelection(variant_name)\n        \n        if not variant_selections:\n            return variant_set_api.GetVariantEditContext()\n        else:\n            with variant_set_api.GetVariantEditContext():\n                return _recursive_variant_context(prim, variant_selections, position)\n    \n    variant_selections = variant_selections[::-1]\n    return _recursive_variant_context(prim, variant_selections, position)\n\nbicycle_prim_path = Sdf.Path(\"/bicycle\")\nbicycle_prim = stage.DefinePrim(bicycle_prim_path, \"Xform\")\n# Variants\nvariant_selections = [(\"model\", \"old\"), (\"LOD\", \"lowRes\")]\nedit_context = variant_nested_edit_context(bicycle_prim, variant_selections)\nwith edit_context as ctx:\n    sphere_prim_path = bicycle_prim_path.AppendChild(\"sphere\")\n    sphere_prim = stage.DefinePrim(\"/bicycle/sphere\", \"Sphere\")\nvariant_selections = [(\"model\", \"old\"), (\"LOD\", \"highRes\")]\nedit_context = variant_nested_edit_context(bicycle_prim, variant_selections)\nwith edit_context as ctx:\n    sphere_prim_path = bicycle_prim_path.AppendChild(\"cube\")\n    sphere_prim = stage.DefinePrim(\"/bicycle/cube\", \"Cube\")\nvariant_selections = [(\"model\", \"new\"), (\"LOD\", \"lowRes\")]\nedit_context = variant_nested_edit_context(bicycle_prim, variant_selections)\nwith edit_context as ctx:\n    sphere_prim_path = bicycle_prim_path.AppendChild(\"cylinder\")\n    sphere_prim = stage.DefinePrim(\"/bicycle/cube\", \"Cylinder\")\n# Variant selections\n# Be sure to explicitly set the overall selection, otherwise if will derive from,\n# the nested variant selections.\nvariant_sets_api = bicycle_prim.GetVariantSets()\nvariant_sets_api.SetSelection(\"model\", \"old\")\nvariant_sets_api.SetSelection(\"LOD\", \"lowRes\")\n\n### Low Level ###\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\ndef variant_nested_prim_path(prim_path, variant_selections):\n    variant_prim_path = prim_path\n    for variant_set_name, variant_name in variant_selections:\n        variant_prim_path = variant_prim_path.AppendVariantSelection(variant_set_name, variant_name)\n    return variant_prim_path\n    \ndef define_prim_spec(layer, prim_path, type_name):\n    prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\n    prim_spec.specifier = Sdf.SpecifierDef\n    prim_spec.typeName = type_name\n\nbicycle_prim_path = Sdf.Path(\"/bicycle\")\nbicycle_prim_spec = Sdf.CreatePrimInLayer(layer, bicycle_prim_path)\nbicycle_prim_spec.specifier = Sdf.SpecifierDef\nbicycle_prim_spec.typeName = \"Xform\"\n# Variants\nvariant_selections = [(\"model\", \"old\"), (\"LOD\", \"lowRes\")]\nvariant_prim_path = variant_nested_prim_path(bicycle_prim_path, variant_selections)\ndefine_prim_spec(layer, variant_prim_path.AppendChild(\"sphere\"), \"Sphere\")\nvariant_selections = [(\"model\", \"old\"), (\"LOD\", \"highRes\")]\nvariant_prim_path = variant_nested_prim_path(bicycle_prim_path, variant_selections)\ndefine_prim_spec(layer, variant_prim_path.AppendChild(\"cube\"), \"Cube\")\nvariant_selections = [(\"model\", \"new\"), (\"LOD\", \"lowRes\")]\nvariant_prim_path = variant_nested_prim_path(bicycle_prim_path, variant_selections)\ndefine_prim_spec(layer, variant_prim_path.AppendChild(\"cylinder\"), \"Cylinder\")\n# Variant selections\n# The low level API has the benefit of not setting variant selections\n# in the nested variants.\nbicycle_prim_spec.variantSelections[\"model\"] = \"old\"\nbicycle_prim_spec.variantSelections[\"LOD\"] = \"highRes\"\n#// ANCHOR_END: compositionArcVariantNested\n\n\n#// ANCHOR: compositionArcReferenceExternal\n### High Level ###\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\n# Spawn temp layer\nreference_layer = Sdf.Layer.CreateAnonymous(\"ReferenceExample\")\nreference_bicycle_prim_path = Sdf.Path(\"/bicycle\")\nreference_bicycle_prim_spec = Sdf.CreatePrimInLayer(reference_layer, reference_bicycle_prim_path)\nreference_bicycle_prim_spec.specifier = Sdf.SpecifierDef\nreference_bicycle_prim_spec.typeName = \"Cube\"\n# Set the default prim to use when we specify no primpath. It can't be a prim path, it must be a root prim.\nreference_layer.defaultPrim = reference_bicycle_prim_path.name\n# Reference\nreference_layer_offset = Sdf.LayerOffset(offset=10, scale=1)\nreference = Sdf.Reference(reference_layer.identifier, reference_bicycle_prim_path, reference_layer_offset)\n# Or: If we don't specify a prim, the default prim will get used, as set above\nreference = Sdf.Reference(reference_layer.identifier, layerOffset=reference_layer_offset)\nbicycle_prim_path = Sdf.Path(\"/bicycle\")\nbicycle_prim = stage.DefinePrim(bicycle_prim_path)\nreferences_api = bicycle_prim.GetReferences()\nreferences_api.AddReference(reference, position=Usd.ListPositionFrontOfAppendList)\n# references_api.SetReferences() # Clears the list editable ops and authors an Sdf.ReferenceListOp.CreateExplicit([])\n# references_api.RemoveReference(cube_prim_path)\n# references_api.ClearReferences() # Sdf.ReferenceListOp.Clear()\n### Low Level ###\nfrom pxr import Sdf\n# Spawn temp layer\nreference_layer = Sdf.Layer.CreateAnonymous(\"ReferenceExample\")\nreference_bicycle_prim_path = Sdf.Path(\"/bicycle\")\nreference_bicycle_prim_spec = Sdf.CreatePrimInLayer(reference_layer, reference_bicycle_prim_path)\nreference_bicycle_prim_spec.specifier = Sdf.SpecifierDef\nreference_bicycle_prim_spec.typeName = \"Cube\"\nreference_layer.defaultPrim = reference_bicycle_prim_path.name\n# In Houdini add, otherwise the layer will be garbage collected.\n# node.addHeldLayer(reference_layer.identifier)\n# Reference\nlayer = Sdf.Layer.CreateAnonymous()\nbicycle_prim_path = Sdf.Path(\"/bicycle\")\nbicycle_prim_spec = Sdf.CreatePrimInLayer(layer, bicycle_prim_path)\nbicycle_prim_spec.specifier = Sdf.SpecifierDef\nreference_layer_offset = Sdf.LayerOffset(offset=10, scale=1)\nreference = Sdf.Reference(reference_layer.identifier, reference_bicycle_prim_path, reference_layer_offset)\n# Or: If we don't specify a prim, the default prim will get used, as set above\nreference = Sdf.Reference(reference_layer.identifier, layerOffset=reference_layer_offset)\nbicycle_prim_spec.referenceList.appendedItems = [reference]\n#// ANCHOR_END: compositionArcReferenceExternal\n\n#// ANCHOR: compositionArcReferenceClass\nfrom pxr import Sdf\nref = Sdf.Reference(\"/file/path.usd\", \"/prim/path\", Sdf.LayerOffset(offset=10, scale=1))\n# The reference object is a read only instance.\nprint(ref.assetPath) # Returns: \"/file/path.usd\"\nprint(ref.primPath) # Returns: \"/prim/path\"\nprint(ref.layerOffset) # Returns: Sdf.LayerOffset(offset=10, scale=1)\ntry: \n    ref.assetPath = \"/some/other/file/path.usd\"\nexcept Exception:\n    print(\"Read only Sdf.Reference!\")\n#// ANCHOR_END: compositionArcReferenceClass\n\n#// ANCHOR: compositionArcReferenceInternal\n### High Level ###\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\n# Spawn hierarchy\ncube_prim_path = Sdf.Path(\"/cube\")\ncube_prim = stage.DefinePrim(cube_prim_path, \"Cube\")\nbicycle_prim_path = Sdf.Path(\"/bicycle\")\nbicycle_prim = stage.DefinePrim(bicycle_prim_path)\n# Reference\nreference_layer_offset = Sdf.LayerOffset(offset=10, scale=1)\nreference = Sdf.Reference(\"\", cube_prim_path, reference_layer_offset)\nreferences_api = bicycle_prim.GetReferences()\nreferences_api.AddReference(reference, position=Usd.ListPositionFrontOfAppendList)\n# Or:\nreferences_api.AddInternalReference(cube_prim_path, reference_layer_offset, position=Usd.ListPositionFrontOfAppendList)\n### Low Level ###\nfrom pxr import Sdf\n# Spawn hierarchy\nlayer = Sdf.Layer.CreateAnonymous()\ncube_prim_path = Sdf.Path(\"/cube\")\ncube_prim_spec = Sdf.CreatePrimInLayer(layer, cube_prim_path)\ncube_prim_spec.specifier = Sdf.SpecifierDef\ncube_prim_spec.typeName = \"Cube\"\nbicycle_prim_path = Sdf.Path(\"/bicycle\")\nbicycle_prim_spec = Sdf.CreatePrimInLayer(layer, bicycle_prim_path)\nbicycle_prim_spec.specifier = Sdf.SpecifierDef\n# Reference\nreference_layer_offset = Sdf.LayerOffset(offset=10, scale=1)\nreference = Sdf.Reference(\"\", cube_prim_path, reference_layer_offset)\nbicycle_prim_spec.referenceList.appendedItems = [reference]\n#// ANCHOR_END: compositionArcReferenceInternal\n\n#// ANCHOR: compositionArcPayloadClass\nfrom pxr import Sdf\npayload = Sdf.Payload(\"/file/path.usd\", \"/prim/path\", Sdf.LayerOffset(offset=10, scale=1))\n# The reference object is a read only instance.\nprint(payload.assetPath) # Returns: \"/file/path.usd\"\nprint(payload.primPath) # Returns: \"/prim/path\"\nprint(payload.layerOffset) # Returns: Sdf.LayerOffset(offset=10, scale=1)\ntry: \n    payload.assetPath = \"/some/other/file/path.usd\"\nexcept Exception:\n    print(\"Read only Sdf.Payload!\")\n#// ANCHOR_END: compositionArcPayloadClass\n\n\n#// ANCHOR: compositionArcPayload\n### High Level ###\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\n# Spawn temp layer\npayload_layer = Sdf.Layer.CreateAnonymous(\"PayloadExample\")\npayload_bicycle_prim_path = Sdf.Path(\"/bicycle\")\npayload_bicycle_prim_spec = Sdf.CreatePrimInLayer(payload_layer, payload_bicycle_prim_path)\npayload_bicycle_prim_spec.specifier = Sdf.SpecifierDef\npayload_bicycle_prim_spec.typeName = \"Cube\"\n# Set the default prim to use when we specify no primpath. It can't be a prim path, it must be a root prim.\npayload_layer.defaultPrim = payload_bicycle_prim_path.name\n# Payload\npayload_layer_offset = Sdf.LayerOffset(offset=10, scale=1)\npayload = Sdf.Payload(payload_layer.identifier, payload_bicycle_prim_path, payload_layer_offset)\n# Or: If we don't specify a prim, the default prim will get used, as set above\npayload = Sdf.Payload(payload_layer.identifier, layerOffset=payload_layer_offset)\nbicycle_prim_path = Sdf.Path(\"/bicycle\")\nbicycle_prim = stage.DefinePrim(bicycle_prim_path)\npayloads_api = bicycle_prim.GetPayloads()\npayloads_api.AddPayload(payload, position=Usd.ListPositionFrontOfAppendList)\n# payloads_api.SetPayloads() # Clears the list editable ops and authors an Sdf.PayloadListOp.CreateExplicit([])\n# payloads_api.RemovePayload(cube_prim_path)\n# payloads_api.ClearPayloads() # Sdf.PayloadListOp.Clear()\n### Low Level ###\nfrom pxr import Sdf\n# Spawn temp layer\npayload_layer = Sdf.Layer.CreateAnonymous(\"PayLoadExample\")\npayload_bicycle_prim_path = Sdf.Path(\"/bicycle\")\npayload_bicycle_prim_spec = Sdf.CreatePrimInLayer(payload_layer, payload_bicycle_prim_path)\npayload_bicycle_prim_spec.specifier = Sdf.SpecifierDef\npayload_bicycle_prim_spec.typeName = \"Cube\"\npayload_layer.defaultPrim = payload_bicycle_prim_path.name\n# In Houdini add, otherwise the layer will be garbage collected.\n# node.addHeldLayer(payload_layer.identifier)\n# Payload\nlayer = Sdf.Layer.CreateAnonymous()\nbicycle_prim_path = Sdf.Path(\"/bicycle\")\nbicycle_prim_spec = Sdf.CreatePrimInLayer(layer, bicycle_prim_path)\nbicycle_prim_spec.specifier = Sdf.SpecifierDef\npayload_layer_offset = Sdf.LayerOffset(offset=10, scale=1)\npayload = Sdf.Payload(payload_layer.identifier, payload_bicycle_prim_path, payload_layer_offset)\n# Or: If we don't specify a prim, the default prim will get used, as set above\npayload = Sdf.Payload(payload_layer.identifier, layerOffset=payload_layer_offset)\nbicycle_prim_spec.payloadList.appendedItems = [payload]\n#// ANCHOR_END: compositionArcPayload\n\n\n#// ANCHOR: compositionArcSpecialize\n### High Level ###\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nbicycle_prim_path = Sdf.Path(\"/bicycle\")\nbicycle_prim = stage.DefinePrim(bicycle_prim_path)\ncube_prim_path = Sdf.Path(\"/cube\")\ncube_prim = stage.DefinePrim(cube_prim_path, \"Cube\")\nspecializes_api = bicycle_prim.GetSpecializes()\nspecializes_api.AddSpecialize(cube_prim_path, position=Usd.ListPositionFrontOfAppendList)\n# inherits_api.SetSpecializes() # Clears the list editable ops and authors an Sdf.PathListOp.CreateExplicit([])\n# inherits_api.RemoveSpecialize(cube_prim_path)\n# inherits_api.ClearSpecializes() # Sdf.PathListOp.Clear()\n### Low Level ###\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nbicycle_prim_path = Sdf.Path(\"/bicycle\")\nbicycle_prim_spec = Sdf.CreatePrimInLayer(layer, bicycle_prim_path)\nbicycle_prim_spec.specifier = Sdf.SpecifierDef\ncube_prim_path = Sdf.Path(\"/cube\")\ncube_prim_spec = Sdf.CreatePrimInLayer(layer, cube_prim_path)\ncube_prim_spec.specifier = Sdf.SpecifierDef\ncube_prim_spec.typeName = \"Cube\"\nbicycle_prim_spec.specializesList.appendedItems = [cube_prim_path]\n#// ANCHOR_END: compositionArcSpecialize\n\n\n#// ANCHOR: compositionInstanceable\n# Check if the active prim is marked as instanceable:\n# The prim.IsInstance() checks if it is actually instanced, this\n# just checks if the 'instanceable' metadata is set.\nprim.IsInstanceable()\n# Check if the active prim is an instanced prim:\nprim.IsInstance()\n# Check if we are inside an instanceable prim:\nprim.IsInstanceProxy()\n# Check if the active prim is a prototype root prim with the following format /__Prototype_<idx>\nprim.IsPrototype()\n# For these type of prototype root prims, we can get the instances via:\nprim.GetInstances()\n# From each instance we can get back to the prototype via\nprim.GetPrototype()\n# Check if we are in the /__Prototype_<idx> prim:\nprim.IsInPrototype()\n\n# When we are within an instance, we can get the prototype via:\nif prim.IsInstanceProxy():\n    for ancestor_prim_path in prim.GetAncestorsRange():\n        ancestor_prim = stage.GetPrimAtPath(ancestor_prim_path)\n        if ancestor_prim.IsInstance():\n            prototype = ancestor_prim.GetPrototype()\n            print(list(prototype.GetInstances()))\n            break\n#// ANCHOR_END: compositionInstanceable\n\n#// ANCHOR: listEditableOpsLowLevelAPI\nfrom pxr import Sdf\npath_list_op = Sdf.PathListOp()\n# There are multiple sub-lists, which are just normal Python lists.\n# 'prependedItems', 'appendedItems', 'deletedItems', 'explicitItems',\n# Legacy sub-lists (do not use these anymore): 'addedItems', 'orderedItems'\n# Currently the way these are exposed to Python, you have to re-assign the list, instead of editing it in place.\n# So this won't work:\npath_list_op.prependedItems.append(Sdf.Path(\"/cube\"))\npath_list_op.appendedItems.append(Sdf.Path(\"/sphere\"))\n# Instead do this:\npath_list_op.prependedItems = [Sdf.Path(\"/cube\")]\npath_list_op.appendedItems = [Sdf.Path(\"/sphere\")]\n# To clear the list op:\nprint(path_list_op) # Returns: SdfPathListOp(Prepended Items: [/cube], Appended Items: [/sphere])\npath_list_op.Clear()\nprint(path_list_op) # Returns: SdfPathListOp()\n# Repopulate via constructor\npath_list_op = Sdf.PathListOp.Create(prependedItems = [Sdf.Path(\"/cube\")], appendedItems = [Sdf.Path(\"/sphere\")])\nprint(path_list_op) # Returns: SdfPathListOp(Prepended Items: [/cube], Appended Items: [/sphere])\n# Add remove items\npath_list_op.deletedItems = [Sdf.Path(\"/sphere\")]\nprint(path_list_op) # Returns: SdfPathListOp(Deleted Items: [/sphere], Prepended Items: [/cube], Appended Items: [/sphere])\n# Notice how it just stores lists, it doesn't actually apply them. We'll have a look at that next.\n#// ANCHOR_END: listEditableOpsLowLevelAPI\n\n#// ANCHOR: listEditableOpsHighLevelAPI\n# For example when editing a relationship:\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nyard_prim = stage.DefinePrim(\"/yard\")\ncar_prim = stage.DefinePrim(\"/car\")\nrel = car_prim.CreateRelationship(\"locationsOfInterest\")\nrel.AddTarget(yard_prim.GetPath(), position=Usd.ListPositionFrontOfAppendList)\n# Result:\n\"\"\"\ndef \"car\"\n{\n    custom rel locationsOfInterest\n    append rel locationsOfInterest = </yard>\n}\n\"\"\"\n# The \"Set<Function>\" signatures write an explicit list:\nrel.SetTargets([yard_prim.GetPath()])\n# Result:\n\"\"\"\ndef \"car\"\n{\n    custom rel locationsOfInterest = </yard>\n}\n\"\"\"\n#// ANCHOR_END: listEditableOpsHighLevelAPI\n\n#// ANCHOR: listEditableOpsMerging\nfrom pxr import Sdf\n### Merging basics ###\npath_list_op_layer_top = Sdf.PathListOp.Create(deletedItems = [Sdf.Path(\"/cube\")])\npath_list_op_layer_middle = Sdf.PathListOp.Create(prependedItems = [Sdf.Path(\"/disc\"), Sdf.Path(\"/cone\")])\npath_list_op_layer_bottom = Sdf.PathListOp.Create(prependedItems = [Sdf.Path(\"/cube\")], appendedItems = [Sdf.Path(\"/cone\"),Sdf.Path(\"/sphere\")])\n\nresult = Sdf.PathListOp()\nresult = result.ApplyOperations(path_list_op_layer_top)\nresult = result.ApplyOperations(path_list_op_layer_middle)\nresult = result.ApplyOperations(path_list_op_layer_bottom)\n# Notice how on merge it makes sure that each sublist does not have the values of the other sublists, just like a Python set()\nprint(result) # Returns: SdfPathListOp(Deleted Items: [/cube], Prepended Items: [/disc, /cone], Appended Items: [/sphere])\n# Get the flattened result. This does not apply the deleteItems, only ApplyOperations does that. \nprint(result.GetAddedOrExplicitItems()) # Returns: [Sdf.Path('/disc'), Sdf.Path('/cone'), Sdf.Path('/sphere')]\n\n### Deleted and added items ###\npath_list_op_layer_top = Sdf.PathListOp.Create(appendedItems=[Sdf.Path(\"/disc\"), Sdf.Path(\"/cube\")])\npath_list_op_layer_middle = Sdf.PathListOp.Create(deletedItems = [Sdf.Path(\"/cube\")])\npath_list_op_layer_bottom = Sdf.PathListOp.Create(prependedItems = [Sdf.Path(\"/cube\")], appendedItems = [Sdf.Path(\"/sphere\")])\n\nresult = Sdf.PathListOp()\nresult = result.ApplyOperations(path_list_op_layer_top)\nresult = result.ApplyOperations(path_list_op_layer_middle)\nresult = result.ApplyOperations(path_list_op_layer_bottom)\nprint(result) # Returns: SdfPathListOp(Appended Items: [/sphere, /disc, /cube])\n# Since it now was in the explicit list, it got removed.\n\n### Explicit mode ###\n# There is also an \"explicit\" mode. This clears all previous values on merge and marks the list as explicit.\n# Once explicit and can't be un-explicited. An explicit list is like a reset, it \n# doesn't know anything about the previous values anymore. All lists that are merged\n# after combine the result to be explicit.\npath_list_op_layer_top = Sdf.PathListOp.Create(deletedItems = [Sdf.Path(\"/cube\")])\npath_list_op_layer_middle = Sdf.PathListOp.CreateExplicit([Sdf.Path(\"/disc\")])\npath_list_op_layer_bottom = Sdf.PathListOp.Create(prependedItems = [Sdf.Path(\"/cube\")], appendedItems = [Sdf.Path(\"/sphere\")])\n\nresult = Sdf.PathListOp()\nresult = result.ApplyOperations(path_list_op_layer_top)\nresult = result.ApplyOperations(path_list_op_layer_middle)\nresult = result.ApplyOperations(path_list_op_layer_bottom)\nprint(result, result.isExplicit) # Returns: SdfPathListOp(Explicit Items: [/disc]), True\n# Notice how the deletedItems had no effect, as \"/cube\" is not in the explicit list.\n\npath_list_op_layer_top = Sdf.PathListOp.Create(deletedItems = [Sdf.Path(\"/cube\")])\npath_list_op_layer_middle = Sdf.PathListOp.CreateExplicit([Sdf.Path(\"/disc\"), Sdf.Path(\"/cube\")])\npath_list_op_layer_bottom = Sdf.PathListOp.Create(prependedItems = [Sdf.Path(\"/cube\")], appendedItems = [Sdf.Path(\"/sphere\")])\n\nresult = Sdf.PathListOp()\nresult = result.ApplyOperations(path_list_op_layer_top)\nresult = result.ApplyOperations(path_list_op_layer_middle)\nresult = result.ApplyOperations(path_list_op_layer_bottom)\nprint(result, result.isExplicit) # Returns: SdfPathListOp(Explicit Items: [/disc]), True\n# Since it now was in the explicit list, it got removed.\n#// ANCHOR_END: listEditableOpsMerging\n\n#// ANCHOR: pcpPrimPropertyStack\nfrom pxr import Sdf, Usd\n# Create stage with two different layers\nstage = Usd.Stage.CreateInMemory()\nroot_layer = stage.GetRootLayer()\nlayer_top = Sdf.Layer.CreateAnonymous(\"exampleTopLayer\")\nlayer_bottom = Sdf.Layer.CreateAnonymous(\"exampleBottomLayer\")\nroot_layer.subLayerPaths.append(layer_top.identifier)\nroot_layer.subLayerPaths.append(layer_bottom.identifier)\n# Define specs in two different layers\nprim_path = Sdf.Path(\"/cube\")\nstage.SetEditTarget(layer_top)\nprim = stage.DefinePrim(prim_path, \"Xform\")\nprim.SetTypeName(\"Cube\")\nstage.SetEditTarget(layer_bottom)\nprim = stage.DefinePrim(prim_path, \"Xform\")\nprim.SetTypeName(\"Cube\")\nattr = prim.CreateAttribute(\"debug\", Sdf.ValueTypeNames.Float)\nattr.Set(5, 10)\n# Print the stack (set of layers that contribute data to this prim)\n# For prims this returns all the Sdf.PrimSpec objects that contribute to the prim.\nprint(prim.GetPrimStack()) # Returns: [Sdf.Find('anon:0x7f6e590dc300:exampleTopLayer', '/cube'), \n                           #           Sdf.Find('anon:0x7f6e590dc580:exampleBottomLayer', '/cube')]\n# For attributes this returns all the Sdf.AttributeSpec objects that contribute to the attribute.\n# If we pass a non default time code value clips will be included in the result.\n# This type of function signature is very unique and can't be found anywhere else in USD.\ntime_code = Usd.TimeCode.Default()\nprint(attr.GetPropertyStack(1001)) # Returns: [Sdf.Find('anon:0x7f9eade0ae00:exampleBottomLayer', '/cube.debug')]\nprint(attr.GetPropertyStack(time_code)) # Returns: [Sdf.Find('anon:0x7f9eade0ae00:exampleBottomLayer', '/cube.debug')]\n#// ANCHOR_END: pcpPrimPropertyStack\n\n\n#// ANCHOR: pcpPrimIndex\nimport os\nfrom subprocess import call\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\n# Spawn temp layer\nreference_layer = Sdf.Layer.CreateAnonymous(\"ReferenceExample\")\nreference_bicycle_prim_path = Sdf.Path(\"/bicycle\")\nreference_bicycle_prim_spec = Sdf.CreatePrimInLayer(reference_layer, reference_bicycle_prim_path)\nreference_bicycle_prim_spec.specifier = Sdf.SpecifierDef\nreference_bicycle_prim_spec.typeName = \"Cube\"\nreference_layer_offset = Sdf.LayerOffset(offset=10, scale=1)\nreference = Sdf.Reference(reference_layer.identifier, reference_bicycle_prim_path, reference_layer_offset)\nbicycle_prim_path = Sdf.Path(\"/red_bicycle\")\nbicycle_prim = stage.DefinePrim(bicycle_prim_path)\nreferences_api = bicycle_prim.GetReferences()\nreferences_api.AddReference(reference, position=Usd.ListPositionFrontOfAppendList)\n# You'll always want to use the expanded method,\n# otherwise you might miss some data sources!\n# This is also what the UIs use.\nprim = bicycle_prim\nprint(prim.GetPrimIndex()) \nprint(prim.ComputeExpandedPrimIndex())\n# Dump the index representation to the dot format and render it to a .svg/.png image.\nprim_index = prim.ComputeExpandedPrimIndex()\nprint(prim_index.DumpToString())\ngraph_file_path = os.path.expanduser(\"~/Desktop/usdSurvivalGuide_prim_index.txt\")\ngraph_viz_png_file_path = graph_file_path.replace(\".txt\", \".png\")\ngraph_viz_svg_file_path = graph_file_path.replace(\".txt\", \".svg\")\nprim_index.DumpToDotGraph(graph_file_path, includeMaps=False)\ncall([\"dot\", \"-Tpng\", graph_file_path, \"-o\", graph_viz_png_file_path])\ncall([\"dot\", \"-Tsvg\", graph_file_path, \"-o\", graph_viz_svg_file_path])\n\ndef iterator_child_nodes(root_node):\n    yield root_node\n    for child_node in root_node.children:\n        for child_child_node in iterator_child_nodes(child_node):\n            yield child_child_node\n\ndef iterator_parent_nodes(root_node):\n    iter_node = root_node\n    while iter_node:\n        yield iter_node\n        iter_node = iter_node.parent\n            \nprint(\"Pcp Node Refs\", dir(prim_index.rootNode))\nfor child in list(iterator_child_nodes(prim_index.rootNode))[::1]:\n    print(child, child.arcType, child.path, child.mapToRoot.MapSourceToTarget(child.path))\n\"\"\" The arc type will one one of:\nPcp.ArcTypeRoot\nPcp.ArcTypeInherit\nPcp.ArcTypeVariant\nPcp.ArcTypeReference\nPcp.ArcTypeRelocate\nPcp.ArcTypePayload\nPcp.ArcTypeSpecialize\n\"\"\"\n#// ANCHOR_END: pcpPrimIndex\n\n\n#// ANCHOR: pcpPrimCompositionQuery\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nprim = stage.DefinePrim(\"/pig\")\nrefs_API = prim.GetReferences()\nrefs_API.AddReference(\"/opt/hfs19.5/houdini/usd/assets/pig/pig.usd\")\nprint(\"----\")\ndef _repr(arc):\n    print(arc.GetArcType(), \n          \"| Introducing Prim Path\", arc.GetIntroducingPrimPath() or \"-\",\n          \"| Introducing Layer\", arc.GetIntroducingLayer() or \"-\",\n          \"| Is ancestral\", arc.IsAncestral(),\n          \"| In Root Layer Stack\", arc.IsIntroducedInRootLayerStack())\nprint(\">-> Direct Root Layer Arcs\")\nquery = Usd.PrimCompositionQuery.GetDirectRootLayerArcs(prim)\nfor arc in query.GetCompositionArcs():\n    _repr(arc)\nprint(\">-> Direct Inherits\")\nquery = Usd.PrimCompositionQuery.GetDirectInherits(prim)\nfor arc in query.GetCompositionArcs():\n    _repr(arc)\nprint(\">-> Direct References\")\nquery = Usd.PrimCompositionQuery.GetDirectReferences(prim)\nfor arc in query.GetCompositionArcs():\n    _repr(arc)\n\"\"\"Returns:\n>-> Direct Root Layer Arcs\nPcp.ArcTypeRoot | Introducing Prim Path - | Introducing Layer - | Is ancestral False | In Root Layer Stack True\nPcp.ArcTypeReference | Introducing Prim Path /pig | Introducing Layer Sdf.Find('anon:0x7f9b60d56b00:tmp.usda') | Is ancestral False | In Root Layer Stack True\n>-> Direct Inherits\nPcp.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\nPcp.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\n>-> Direct References\nPcp.ArcTypeReference | Introducing Prim Path /pig | Introducing Layer Sdf.Find('anon:0x7f9b60d56b00:tmp.usda') | Is ancestral False | In Root Layer Stack True\nPcp.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\nPcp.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\nPcp.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\nPcp.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\nPcp.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\nPcp.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\nPcp.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\n\"\"\"\n# Custom filter\n# For example let's get all direct payloads, that were not introduced in the active root layer stack.\nquery_filter = Usd.PrimCompositionQuery.Filter()\nquery_filter.arcTypeFilter = Usd.PrimCompositionQuery.ArcTypeFilter.Payload\nquery_filter.dependencyTypeFilter = Usd.PrimCompositionQuery.DependencyTypeFilter.Direct\nquery_filter.arcIntroducedFilter = Usd.PrimCompositionQuery.ArcIntroducedFilter.All\nquery_filter.hasSpecsFilter = Usd.PrimCompositionQuery.HasSpecsFilter.HasSpecs\nprint(\">-> Custom Query (Direct payloads not in root layer that have specs)\")\nquery = Usd.PrimCompositionQuery(prim)\nquery.filter = query_filter\nfor arc in query.GetCompositionArcs():\n    _repr(arc)\n\"\"\"Returns:\n>-> Custom Query (Direct payloads not in root layer that have specs)\nPcp.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\n\"\"\"\n#// ANCHOR_END: pcpPrimCompositionQuery\n\n\n"
  },
  {
    "path": "code/core/elements.py",
    "content": "\"\"\"This file contains all code examples for the 'Core Elements' section.\nThe following mdBook syntax allows us to sparsely import content:\n#// ANCHOR: contentId\ndef example():\n    print(\"here\")\n#// ANCHOR_END: contentId\n\"\"\"\n\n\"\"\"api.md\"\"\"\n\n#// ANCHOR: apiHighVsLowLevel\n### High Level ### (Notice how we still use elements of the low level API)\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Xform\")\nattr = prim.CreateAttribute(\"tire:size\", Sdf.ValueTypeNames.Float)\nattr.Set(10)\n\n### Low Level ###\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/bicycle\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.specifier = Sdf.SpecifierDef\nprim_spec.typeName = \"Xform\"\nattr_spec = Sdf.AttributeSpec(prim_spec, \"tire:size\", Sdf.ValueTypeNames.Float)\nattr_spec.default = 10\n#// ANCHOR_END: apiHighVsLowLevel\n\n\"\"\"path.md\"\"\"\n\n#// ANCHOR: pathSummary\nfrom pxr import Sdf\n# Prims\nprim_path = Sdf.Path(\"/set/bicycle\")\nprim_path_str = Sdf.Path(\"/set/bicycle\").pathString # Returns the Python str \"/set/bicycle\"\n# Properties (Attribute/Relationship)\nproperty_path = Sdf.Path(\"/set/bicycle.size\")\nproperty_with_namespace_path = Sdf.Path(\"/set/bicycle.tire:size\")\n# Relationship targets\nprim_rel_target_path = Sdf.Path(\"/set.bikes[/set/bicycles]\")           # Prim to prim linking (E.g. path collections)\n# Variants\nvariant_path = prim_path.AppendVariantSelection(\"style\", \"blue\") # Returns: Sdf.Path('/set/bicycle{style=blue}')\nvariant_path = Sdf.Path('/set/bicycle{style=blue}frame/screws')\n#// ANCHOR_END: pathSummary\n\n#// ANCHOR: pathBasics\nfrom pxr import Sdf\npath = Sdf.Path(\"/set/bicycle\")\npath_name = path.name     # Similar to os.path.basename(), returns the last element of the path\npath_empty = path.isEmpty # Property to check if path is empty\n# Path validation (E.g. for user created paths)\nSdf.Path.IsValidPathString(\"/some/_wrong!_/path\") # Returns: (False, 'Error Message')\n# Join paths (Similar to os.path.join())\npath = Sdf.Path(\"/set/bicycle\")\npath.AppendPath(Sdf.Path(\"frame/screws\")) # Returns: Sdf.Path(\"/set/bicycle/frame/screws\")\n# Manually join individual path elements\npath = Sdf.Path(Sdf.Path.childDelimiter.join([\"set\", \"bicycle\"])) \n# Get the parent path\nparent_path = path.GetParentPath() # Returns Sdf.Path(\"/set\")\nparent_path.IsRootPrimPath()       # Returns: True (Root prims are prims that only\n                                   #                have a single '/')        \nancestor_range = path.GetAncestorsRange() # Returns an iterator for the parent paths, the same as recursively calling GetParentPath()\n# Add child path\nchild_path = path.AppendChild(\"wheel\") # Returns: Sdf.Path(\"/set/bicycle/wheel\")\n# Check if path is a prim path (and not a attribute/relationship path)\npath.IsPrimPath() # Returns: True\n# Check if path starts with another path\n# Important: It actually compares individual path elements (So it is not a str.startswith())\nSdf.Path(\"/set/cityA/bicycle\").HasPrefix(Sdf.Path(\"/set\"))      # Returns: True\nSdf.Path(\"/set/cityA/bicycle\").HasPrefix(Sdf.Path(\"/set/city\")) # Returns: False\nSdf.Path(\"/set/bicycle\").GetCommonPrefix(Sdf.Path(\"/set\"))      # Returns: Sdf.Path(\"/set\")\n# Relative/Absolute paths\npath = Sdf.Path(\"/set/cityA/bicycle\")\nrel_path = path.MakeRelativePath(\"/set\")     # Returns: Sdf.Path('cityA/bicycle')\nabs_path = rel_path.MakeAbsolutePath(\"/set\") # Returns: Sdf.Path('/set/cityA/bicycle')\nabs_path.IsAbsolutePath()                    # Returns: True -> Checks path[0] == \"/\"\n# Do not use this is performance critical loops\n# See for more info: https://openusd.org/release/api/_usd__page__best_practices.html\n# This gives you a standard python string\npath_str = path.pathString\n#// ANCHOR_END: pathBasics\n\n#// ANCHOR: pathSpecialPaths\nfrom pxr import Sdf\n# Shortcut for Sdf.Path(\"/\")\nroot_path = Sdf.Path.absoluteRootPath\nroot_path == Sdf.Path(\"/\") # Returns: True\n# We'll cover in a later section how to rename/remove things in Usd,\n# so don't worry about the details how this works yet. Just remember that\n# an emptyPath exists and that its usage is to remove something.\nsrc_path = Sdf.Path(\"/set/bicycle\")\ndst_path = Sdf.Path.emptyPath\nedit = Sdf.BatchNamespaceEdit()\nedit.Add(src_path, dst_path)\n#// ANCHOR_END: pathSpecialPaths\n\n#// ANCHOR: pathProperties\n# Properties (see the next section) are also encoded\n# in the path via the \".\" (Sdf.Path.propertyDelimiter) token\nfrom pxr import Sdf\npath = Sdf.Path(\"/set/bicycle.size\")\nproperty_name = path.name # Be aware, this will return 'size' (last element)\n# Append property to prim path\nSdf.Path(\"/set/bicycle\").AppendProperty(\"size\") # Returns: Sdf.Path(\"/set/bicycle.size\")\n# Properties can also be namespaced with \":\" (Sdf.Path.namespaceDelimiter)\npath = Sdf.Path(\"/set/bicycle.tire:size\") \nproperty_name = path.name                 # Returns: 'tire:size'\nproperty_name = path.ReplaceName(\"color\") # Returns: Sdf.Path(\"/set/bicycle.color\")\n# Check if path is a property path (and not a prim path)\npath.IsPropertyPath() # Returns: True\n# Check if path is a property path (and not a prim path)\nSdf.Path(\"/set/bicycle.tire:size\").IsPrimPropertyPath()  # Returns: True\nSdf.Path(\"/set/bicycle\").IsPrimPropertyPath()            # Returns: False\n# Convenience methods\npath = Sdf.Path(\"/set/bicycle\").AppendProperty(Sdf.Path.JoinIdentifier([\"tire\", \"size\"]))\nnamespaced_elements = Sdf.Path.TokenizeIdentifier(\"tire:size\")   # Returns: [\"tire\", \"size\"]\nlast_element = Sdf.Path.StripNamespace(\"/set/bicycle.tire:size\") # Returns: 'size'\n# With GetPrimPath we can strip away all property encodings\npath = Sdf.Path(\"/set/bicycle.tire:size\")\nprim_path = path.GetPrimPath() # Returns: Sdf.Path('/set/bicycle')\n\n# We can't actually differentiate between a attribute and relationship based on the property path.\n# Hence the \"Property\" terminology.\n# In practice we rarely use/see this as this is a pretty low level API use case.\n# The only 'common' case, where you will see this is when calling the Sdf.Layer.Traverse function.\n# To encode prim relation targets, we can use:\nprim_rel_target_path = Sdf.Path(\"/set.bikes[/set/bicycle]\")\nprim_rel_target_path.IsTargetPath() # Returns: True\nprim_rel_target_path = Sdf.Path(\"/set.bikes\").AppendTarget(\"/set/bicycle\")\n# We can also encode check if a path is a relational attribute.\n# ToDo: I've not seen this encoding being used anywhere so far.\n# \"Normal\" attr_spec.connectionsPathList connections as used in shaders\n# are encoded via Sdf.Path(\"/set.bikes[/set/bicycle.someOtherAttr]\")\nattribute_rel_target_path = Sdf.Path(\"/set.bikes[/set/bicycles].size\")\nattribute_rel_target_path.IsRelationalAttributePath()  # Returns: True\n#// ANCHOR_END: pathProperties\n\n#// ANCHOR: pathVariants\n# Variants (see the next sections) are also encoded\n# in the path via the \"{variantSetName=variantName}\" syntax.\nfrom pxr import Sdf\npath = Sdf.Path(\"/set/bicycle\")\nvariant_path = path.AppendVariantSelection(\"style\", \"blue\") # Returns: Sdf.Path('/set/bicycle{style=blue}')\nvariant_path = Sdf.Path('/set/bicycle{style=blue}frame/screws')\n# Property path to prim path with variants\nproperty_path = Sdf.Path('/set/bicycle{style=blue}frame/screws.size')\nvariant_path = property_path.GetPrimOrPrimVariantSelectionPath() # Returns: Sdf.Path('/set/bicycle{style=blue}frame/screws')\n# Typical iteration example:\nvariant_path = Sdf.Path('/set/bicycle{style=blue}frame/screws')\nif variant_path.ContainsPrimVariantSelection():          # Returns: True # For any variant selection in the whole path\n    for parent_path in variant_path.GetAncestorsRange():\n        if parent_path.IsPrimVariantSelectionPath():\n            print(parent_path.GetVariantSelection())     # Returns: ('style', 'blue')\n\n# When authoring relationships, we usually want to remove all variant encodings in the path:\nvariant_path = Sdf.Path('/set/bicycle{style=blue}frame/screws')\nprim_rel_target_path = variant_path.StripAllVariantSelections() # Returns: Sdf.Path('/set/bicycle/frame/screws')\n#// ANCHOR_END: pathVariants\n\n## Data Containers ##\n\n#// ANCHOR: dataContainerPrimOverview\n### High Level ###\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Xform\")\nattr = prim.CreateAttribute(\"tire:size\", Sdf.ValueTypeNames.Float)\nattr.Set(10)\n\n### Low Level ###\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/bicycle\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.specifier = Sdf.SpecifierDef\nprim_spec.typeName = \"Xform\"\nattr_spec = Sdf.AttributeSpec(prim_spec, \"tire:size\", Sdf.ValueTypeNames.Float)\nattr_spec.default = 10\n#// ANCHOR_END: dataContainerPrimOverview\n\n\n#// ANCHOR: dataContainerPrimCoreHighLevel\nfrom pxr import Kind, Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/cube\")\nprim = stage.DefinePrim(prim_path, \"Xform\") # Here defining the prim uses a `Sdf.SpecifierDef` define op by default.\n# The specifier and type name is something you'll usually always set.\nprim.SetSpecifier(Sdf.SpecifierOver)\nprim.SetTypeName(\"Cube\")\n# The other core specs are set via schema APIs, for example:\nmodel_API = Usd.ModelAPI(prim)\nif not model_API.GetKind():\n    model_API.SetKind(Kind.Tokens.group)\n#// ANCHOR_END: dataContainerPrimCoreHighLevel\n\n\n#// ANCHOR: dataContainerPrimCoreLowLevel\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/cube\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path) # Here defining the prim uses a `Sdf.SpecifierOver` define op by default.\n# The specifier and type name is something you'll usually always set.\nprim_spec.specifier = Sdf.SpecifierDef # Or Sdf.SpecifierOver/Sdf.SpecifierClass\nprim_spec.typeName = \"Cube\"\nprim_spec.active = True # There is also a prim_spec.ClearActive() shortcut for removing active metadata\nprim_spec.kind = \"group\"    # There is also a prim_spec.ClearKind() shortcut for removing kind metadata\nprim_spec.instanceable = False # There is also a prim_spec.ClearInstanceable() shortcut for removing instanceable metadata.\nprim_spec.hidden = False # A hint for UI apps to hide the spec for viewers\n\n# You can also set them via the standard metadata commands:\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/cube\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\n# The specifier and type name is something you'll usually always set.\nprim_spec.SetInfo(prim_spec.SpecifierKey, Sdf.SpecifierDef) # Or Sdf.SpecifierOver/Sdf.SpecifierClass\nprim_spec.SetInfo(prim_spec.TypeNameKey, \"Cube\")\n# These are some other common specs:\nprim_spec.SetInfo(prim_spec.ActiveKey, True)\nprim_spec.SetInfo(prim_spec.KindKey, \"group\")\nprim_spec.SetInfo(\"instanceable\", False) \nprim_spec.SetInfo(prim_spec.HiddenKey, False)\n#// ANCHOR_END: dataContainerPrimCoreLowLevel\n\n\n#// ANCHOR: dataContainerPrimBasicsSpecifierTraversal\n### High Level ###\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\n# Replicate the Usd file example above:\nstage.DefinePrim(\"/definedCube\", \"Cube\").SetSpecifier(Sdf.SpecifierDef)\nstage.DefinePrim(\"/overCube\", \"Cube\").SetSpecifier(Sdf.SpecifierOver)\nstage.DefinePrim(\"/classCube\", \"Cube\").SetSpecifier(Sdf.SpecifierClass)\n## Traverse with default filter (USD calls filter 'predicate')\n# UsdPrimIsActive & UsdPrimIsDefined & UsdPrimIsLoaded & ~UsdPrimIsAbstract\nfor prim in stage.Traverse():\n    print(prim)\n# Returns:\n# Usd.Prim(</definedCube>)\n## Traverse with 'all' filter (USD calls filter 'predicate')\nfor prim in stage.TraverseAll():\n    print(prim)\n# Returns:\n# Usd.Prim(</definedCube>)\n# Usd.Prim(</overCube>)\n# Usd.Prim(</classCube>)\n## Traverse with IsAbstract (== IsClass) filter (USD calls filter 'predicate')\npredicate = Usd.PrimIsAbstract\nfor prim in stage.Traverse(predicate):\n    print(prim)\n# Returns:\n# Usd.Prim(</classCube>)\n## Traverse with ~PrimIsDefined filter (==IsNotDefined) (USD calls filter 'predicate')\npredicate = ~Usd.PrimIsDefined\nfor prim in stage.Traverse(predicate):\n    print(prim)\n# Returns:\n# Usd.Prim(</overCube>)\n#// ANCHOR_END: dataContainerPrimBasicsSpecifierTraversal\n\n\n#// ANCHOR: dataContainerPrimBasicsSpecifierDef\n### High Level ###\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\n# The .DefinePrim method uses a Sdf.SpecifierDef specifier by default\nprim = stage.DefinePrim(prim_path, \"Xform\")\nprim.SetSpecifier(Sdf.SpecifierDef)\n\n### Low Level ###\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/bicycle\")\n# The .CreatePrimInLayer method uses a Sdf.SpecifierOver specifier by default\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.specifier = Sdf.SpecifierDef\n#// ANCHOR_END: dataContainerPrimBasicsSpecifierDef\n\n#// ANCHOR: dataContainerPrimBasicsSpecifierOver\n### High Level ###\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\n# The .DefinePrim method uses a Sdf.SpecifierDef specifier by default\nprim = stage.DefinePrim(prim_path, \"Xform\")\nprim.SetSpecifier(Sdf.SpecifierOver)\n# or \nprim = stage.OverridePrim(prim_path)\n# The prim class' IsDefined method checks if a prim (and all its parents) have the \"def\" specifier.\nprint(prim.GetSpecifier() == Sdf.SpecifierOver, not prim.IsDefined() and not prim.IsAbstract())\n\n### Low Level ###\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/bicycle\")\n# The .CreatePrimInLayer method uses a Sdf.SpecifierOver specifier by default\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.specifier = Sdf.SpecifierOver\n#// ANCHOR_END: dataContainerPrimBasicsSpecifierOver\n\n#// ANCHOR: dataContainerPrimBasicsSpecifierClass\n### High Level ###\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\n# The .DefinePrim method uses a Sdf.SpecifierDef specifier by default\nprim = stage.DefinePrim(prim_path, \"Xform\")\nprim.SetSpecifier(Sdf.SpecifierClass)\n# or \nprim = stage.CreateClassPrim(prim_path)\n# The prim class' IsAbstract method checks if a prim (and all its parents) have the \"Class\" specifier.\nprint(prim.GetSpecifier() == Sdf.SpecifierClass, prim.IsAbstract())\n\n### Low Level ###\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/bicycle\")\n# The .CreatePrimInLayer method uses a Sdf.SpecifierOver specifier by default\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.specifier = Sdf.SpecifierClass\n#// ANCHOR_END: dataContainerPrimBasicsSpecifierClass\n\n#// ANCHOR: dataContainerPrimBasicsTypeName\n### High Level ###\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Xform\")\nprim.SetTypeName(\"Xform\")\n\n### Low Level ###\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/bicycle\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.typeName = \"Xform\"\n\n# Default type without any fancy bells and whistles:\nprim.SetTypeName(\"Scope\")\nprim_spec.typeName = \"Scope\"\n#// ANCHOR_END: dataContainerPrimBasicsTypeName\n\n\n#// ANCHOR: dataContainerPrimBasicsKinds\n### High Level ###\nfrom pxr import Kind, Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Xform\")\nmodel_API = Usd.ModelAPI(prim)\nmodel_API.SetKind(Kind.Tokens.component)\n# The prim class' IsModel/IsGroup method checks if a prim (and all its parents) are (sub-) kinds of model/group.\nmodel_API.SetKind(Kind.Tokens.model)\nkind = model_API.GetKind()\nprint(kind, (Kind.Registry.GetBaseKind(kind) or kind) == Kind.Tokens.model, prim.IsModel())\nmodel_API.SetKind(Kind.Tokens.group)\nkind = model_API.GetKind()\nprint(kind, (Kind.Registry.GetBaseKind(kind) or kind) == Kind.Tokens.group, prim.IsGroup())\n\n### Low Level ###\nfrom pxr import Kind, Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/bicycle\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.SetInfo(\"kind\", Kind.Tokens.component)\n#// ANCHOR_END: dataContainerPrimBasicsKinds\n\n#// ANCHOR: dataContainerPrimBasicsTokens\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/cube\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.SetInfo(prim_spec.KindKey, \"group\")\n#// ANCHOR_END: dataContainerPrimBasicsTokens\n\n\n#// ANCHOR: dataContainerPrimBasicsDebugging\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/cube\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.specifier = Sdf.SpecifierDef\nprim_spec.SetInfo(prim_spec.KindKey, \"group\")\nattr_spec = Sdf.AttributeSpec(prim_spec, \"size\", Sdf.ValueTypeNames.Float)\n# Running this\nprint(prim_spec.GetAsText())\n# Returns:\n\"\"\"\ndef \"cube\" (\n    kind = \"group\"\n)\n{\n    float size\n}\n\"\"\"\n#// ANCHOR_END: dataContainerPrimBasicsDebugging\n\n\n#// ANCHOR: dataContainerPrimHierarchy\n### High Level ###\n# Has: 'IsPseudoRoot' \n# Get: 'GetParent', 'GetPath', 'GetName', 'GetStage',\n#      'GetChild', 'GetChildren', 'GetAllChildren',   \n#      'GetChildrenNames', 'GetAllChildrenNames',\n#      'GetFilteredChildren', 'GetFilteredChildrenNames', \n# The GetAll<MethodNames> return children that have specifiers other than Sdf.SpecifierDef\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/set/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Xform\")\nparent_prim = prim.GetParent()\nprint(prim.GetPath()) # Returns: Sdf.Path(\"/set/bicycle\")\nprint(prim.GetParent()) # Returns: Usd.Prim(\"/set\")\nprint(parent_prim.GetChildren()) # Returns: [Usd.Prim(</set/bicycle>)]\nprint(parent_prim.GetChildrenNames()) # Returns: ['bicycle']\n\n### Low Level ###\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/set/bicycle\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprint(prim_spec.path) # Returns: Sdf.Path(\"/set/bicycle\")\nprint(prim_spec.name) # Returns: \"bicycle\"\n# To rename a prim, you can simply set the name attribute to something else.\n# If you want to batch-rename, you should use the Sdf.BatchNamespaceEdit class, see our explanation [here]()\nprim_spec.name = \"coolBicycle\"\nprint(prim_spec.nameParent) # Returns: Sdf.PrimSpec(\"/set\")\nprint(prim_spec.nameParent.nameChildren) # Returns: {'coolBicycle': Sdf.Find('anon:0x7f6e5a0e3c00:LOP:/stage/pythonscript3', '/set/coolBicycle')}\nprint(prim_spec.layer) # Returns: The active layer object the spec is on.\n#// ANCHOR_END: dataContainerPrimHierarchy\n\n\n#// ANCHOR: dataContainerPrimSchemas\n### High Level ###\n# Has: 'IsA', 'HasAPI', 'CanApplyAPI'\n# Get: 'GetTypeName', 'GetAppliedSchemas'\n# Set: 'SetTypeName', 'AddAppliedSchema', 'ApplyAPI'\n# Clear: 'ClearTypeName', 'RemoveAppliedSchema', 'RemoveAPI'\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Xform\")\n# Typed Schemas\nprim.SetTypeName(\"Xform\")\n# Applied schemas\nprim.AddAppliedSchema(\"SkelBindingAPI\")\n# AddAppliedSchema does not check if the schema actually exists, \n# you have to use this for codeless schemas.\n# prim.RemoveAppliedSchema(\"SkelBindingAPI\")\n# Single-Apply API Schemas\nprim.ApplyAPI(\"GeomModelAPI\") # Older USD versions: prim.ApplyAPI(\"UsdGeomModelAPI\")\n\n### Low Level ###\n# To set applied API schemas via the low level API, we just \n# need to set the `apiSchemas` key to a Token Listeditable Op.\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/bicycle\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\n# Typed Schemas\nprim_spec.typeName = \"Xform\"\n# Applied Schemas\nschemas = Sdf.TokenListOp.Create(\n    prependedItems=[\"SkelBindingAPI\", \"GeomModelAPI\"]\n)\nprim_spec.SetInfo(\"apiSchemas\", schemas)\n#// ANCHOR_END: dataContainerPrimSchemas\n\n#// ANCHOR: dataContainerPrimTypeDefinition\nfrom pxr import Sdf, Tf, Usd, UsdGeom\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Xform\")\nprim.ApplyAPI(\"GeomModelAPI\") # Older USD versions: prim.ApplyAPI(\"UsdGeomModelAPI\")\nprim_def = prim.GetPrimDefinition()\nprint(prim_def.GetAppliedAPISchemas()) # Returns: ['GeomModelAPI']\nprint(prim_def.GetPropertyNames()) \n# Returns: All properties that come from the type name schema and applied schemas\n\"\"\"\n['model:drawModeColor', 'model:cardTextureZPos', 'model:drawMode', 'model:cardTextureZNeg', \n'model:cardTextureYPos', 'model:cardTextureYNeg', 'model:cardTextureXPos', 'model:cardTextur\neXNeg', 'model:cardGeometry', 'model:applyDrawMode', 'proxyPrim', 'visibility', 'xformOpOrde\nr', 'purpose']\n\"\"\"\n# You can also bake down the prim definition, this won't flatten custom properties though.\ndst_prim = stage.DefinePrim(\"/flattenedExample\")\ndst_prim = prim_def.FlattenTo(dst_prim)\n# This will also flatten all metadata (docs etc.), this should only be used, if you need to export\n# a custom schema to an external vendor. (Not sure if this the \"official\" way to do it, I'm sure\n# there are better ones.)\n#// ANCHOR_END: dataContainerPrimTypeDefinition\n\n#// ANCHOR: dataContainerPrimTypeInfo\nfrom pxr import Sdf, Tf, Usd, UsdGeom\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Xform\")\nprim.ApplyAPI(\"GeomModelAPI\")\nprint(prim.IsA(UsdGeom.Xform)) # Returns: True\nprint(prim.IsA(Tf.Type.FindByName('UsdGeomXform'))) # Returns: True\nprim_type_info = prim.GetPrimTypeInfo()\nprint(prim_type_info.GetAppliedAPISchemas()) # Returns: ['GeomModelAPI']\nprint(prim_type_info.GetSchemaType()) # Returns: Tf.Type.FindByName('UsdGeomXform')\nprint(prim_type_info.GetSchemaTypeName()) # Returns: Xform\n#// ANCHOR_END: dataContainerPrimTypeInfo\n\n#// ANCHOR: dataContainerPrimLoading\n### High Level ###\nfrom pxr import Sdf, Tf, Usd, UsdGeom\n# Has: 'HasAuthoredActive', 'HasAuthoredHidden'\n# Get: 'IsActive', 'IsLoaded', 'IsHidden'\n# Set: 'SetActive', 'SetHidden' \n# Clear: 'ClearActive', 'ClearHidden'\n# Loading: 'Load', 'Unload'\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Xform\")\n## Activation: Controls subhierarchy loading of prim.\nprim.SetActive(False) # \n# prim.ClearActive()\n## Visibility: Controls the visiblity for render delegates (subhierarchy will still be loaded)\nimageable_API = UsdGeom.Imageable(prim)\nvisibility_attr = imageable_API.CreateVisibilityAttr()\nvisibility_attr.Set(UsdGeom.Tokens.invisible)\n## Purpose: Controls if the prim is visible for what the renderer requested.\nimageable_API = UsdGeom.Imageable(prim)\npurpose_attr = imageable_API.CreatePurposeAttr()\npurpose_attr.Set(UsdGeom.Tokens.render)\n## Payload loading: Control payload loading (High Level only as it redirects the request to the stage).\n# In our example stage here, we have no payloads, so we don't see a difference.\nprim.Load()\nprim.Unload()\n# Calling this on the prim is the same thing.\nprim = stage.GetPrimAtPath(prim_path)\nprim.GetStage().Load(prim_path)\nprim.GetStage().Unload(prim_path)\n## Hidden: # Hint to hide for UIs\nprim.SetHidden(False)\n# prim.ClearHidden()\n\n### Low Level ###\nfrom pxr import Sdf, UsdGeom\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/set/bicycle\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\n## Activation: Controls subhierarchy loading of prim.\nprim_spec.active = False\n# prim_spec.ClearActive()\n## Visibility: Controls the visiblity for render delegates (subhierarchy will still be loaded)\nvisibility_attr_spec = Sdf.AttributeSpec(prim_spec, UsdGeom.Tokens.visibility, Sdf.ValueTypeNames.Token)\nvisibility_attr_spec.default = UsdGeom.Tokens.invisible\n## Purpose: Controls if the prim is visible for what the renderer requested.\npurpose_attr_spec = Sdf.AttributeSpec(prim_spec, UsdGeom.Tokens.purpose, Sdf.ValueTypeNames.Token)\npurpose_attr_spec.default = UsdGeom.Tokens.render\n## Hidden: # Hint to hide for UIs\nprim_spec.hidden = True \n# prim_spec.ClearHidden()\n#// ANCHOR_END: dataContainerPrimLoading\n\n\n#// ANCHOR: dataContainerPrimPropertiesHighLevel\nfrom pxr import Usd, Sdf\n# Has: 'HasProperty', 'HasAttribute', 'HasRelationship'\n# Get: 'GetProperties', 'GetAuthoredProperties', 'GetPropertyNames', 'GetPropertiesInNamespace', 'GetAuthoredPropertiesInNamespace'\n#      'GetAttribute', 'GetAttributes', 'GetAuthoredAttributes'\n#      'GetRelationship', 'GetRelationships', 'GetAuthoredRelationships'\n#      'FindAllAttributeConnectionPaths', 'FindAllRelationshipTargetPaths'\n# Set: 'CreateAttribute', 'CreateRelationship'\n# Clear: 'RemoveProperty', \nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Cube\")\n# As the cube schema ships with a \"size\" attribute, we don't have to create it first\n# Usd is smart enough to check the schema for the type and creates it for us.\nsize_attr = prim.GetAttribute(\"size\")\nsize_attr.Set(10)\n## Looking up attributes\nprint(prim.GetAttributes())\n# Returns: All the attributes that are provided by the schema\n\"\"\"\n[Usd.Prim(</bicycle>).GetAttribute('doubleSided'), Usd.Prim(</bicycle>).GetAttribute('extent'), Usd.\nPrim(</bicycle>).GetAttribute('orientation'), Usd.Prim(</bicycle>).GetAttribute('primvars:displayCol\nor'), Usd.Prim(</bicycle>).GetAttribute('primvars:displayOpacity'), Usd.Prim(</bicycle>).GetAttribut\ne('purpose'), Usd.Prim(</bicycle>).GetAttribute('size'), Usd.Prim(</bicycle>).GetAttribute('visibili\nty'), Usd.Prim(</bicycle>).GetAttribute('xformOpOrder')]\n\"\"\"\nprint(prim.GetAuthoredAttributes())\n# Returns: Only the attributes we have written to in the active stage.\n# [Usd.Prim(</bicycle>).GetAttribute('size')]\n## Looking up relationships:\nprint(prim.GetRelationships())\n# Returns:\n# [Usd.Prim(</bicycle>).GetRelationship('proxyPrim')]\nbox_prim = stage.DefinePrim(\"/box\")\nprim.GetRelationship(\"proxyPrim\").SetTargets([box_prim.GetPath()])\n# If we now check our properties, you can see both the size attribute\n# and proxyPrim relationship show up.\nprint(prim.GetAuthoredProperties())\n# Returns:\n# [Usd.Prim(</bicycle>).GetRelationship('proxyPrim'),\n#  Usd.Prim(</bicycle>).GetAttribute('size')]\n## Creating attributes:\n# If we want to create non-schema attributes (or even schema attributes without using\n# the schema getter/setters), we can run:\ntire_size_attr = prim.CreateAttribute(\"tire:size\", Sdf.ValueTypeNames.Float)\ntire_size_attr.Set(5)\n#// ANCHOR_END: dataContainerPrimPropertiesHighLevel\n\n#// ANCHOR: dataContainerPrimPropertiesLowLevel\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/cube\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.specifier = Sdf.SpecifierDef\nattr_spec = Sdf.AttributeSpec(prim_spec, \"size\", Sdf.ValueTypeNames.Float)\nprint(prim_spec.attributes) # Returns: {'size': Sdf.Find('anon:0x7f6efe199480:LOP:/stage/python', '/cube.size')}\nattr_spec.default = 10\n# To remove a property you can run:\n# prim_spec.RemoveProperty(attr_spec)\n# Let's re-create what we did in the high level API example.\nbox_prim_path = Sdf.Path(\"/box\")\nbox_prim_spec = Sdf.CreatePrimInLayer(layer, box_prim_path)\nbox_prim_spec.specifier = Sdf.SpecifierDef\nrel_spec = Sdf.RelationshipSpec(prim_spec, \"proxyPrim\")\nrel_spec.targetPathList.explicitItems = [box_prim_path]\n# Get all authored properties (in the active layer only)\nprint(prim_spec.properties)\n# Returns:\n\"\"\"\n{'size': Sdf.Find('anon:0x7ff87c9c2000', '/cube.size'),\n 'proxyPrim': Sdf.Find('anon:0x7ff87c9c2000', '/cube.proxyPrim')}\n\"\"\"\n#// ANCHOR_END: dataContainerPrimPropertiesLowLevel\n\n#// ANCHOR: metadataSummary\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Xform\")\nprim.SetMetadata(\"assetInfo\", {\"version\": \"1\"})\nprim.SetAssetInfoByKey(\"identifier\", Sdf.AssetPath(\"bicycler.usd\"))\nprim.SetMetadata(\"customData\", {\"sizeUnit\": \"meter\"})\nprim.SetCustomDataByKey(\"nested:shape\", \"round\")\n#// ANCHOR_END: metadataSummary\n\n\n#// ANCHOR: metadataBasics\n\"\"\"\n### General\n# Has:   'HasAuthoredMetadata'/'HasAuthoredMetadataDictKey'/'HasMetadata'/'HasMetadataDictKey'\n# Get:   'GetAllAuthoredMetadata'/'GetAllMetadata'/'GetMetadata'/'GetMetadataByDictKey'\n# Set:   'SetMetadata'/'SetMetadataByDictKey', \n# Clear: 'ClearMetadata'/'ClearMetadataByDictKey'\n### Asset Info (Prims only)\n# Has: 'HasAssetInfo'/'HasAssetInfoKey'/'HasAuthoredAssetInfo'/'HasAuthoredAssetInfoKey'\n# Get: 'GetAssetInfo'/'GetAssetInfoByKey'\n# Set: 'SetAssetInfo'/'SetAssetInfoByKey', \n# Clear: 'ClearAssetInfo'/'ClearAssetInfoByKey'\n### Custom Data (Prims, Properties(Attributes/Relationships), Layers)\n# Has: 'HasCustomData'/'HasCustomDataKey'/'HasAuthoredCustomData'/'HasAuthoredCustomDataKey'\n# Get: 'GetCustomData'/'GetCustomDataByKey'\n# Set: 'SetCustomData'/'SetCustomDataByKey', \n# Clear: 'ClearCustomData'/'ClearCustomDataByKey'\n\"\"\"\nfrom pxr import Usd, Sdf\n\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Xform\")\nprim.SetAssetInfoByKey(\"identifier\", Sdf.AssetPath(\"bicycler.usd\"))\nprim.SetAssetInfoByKey(\"nested\", {\"assetPath\": Sdf.AssetPath(\"bicycler.usd\"), \"version\": \"1\"})\nprim.SetMetadataByDictKey(\"assetInfo\", \"nested:color\", \"blue\")\nattr = prim.CreateAttribute(\"tire:size\", Sdf.ValueTypeNames.Float)\nattr.SetMetadata(\"customData\", {\"sizeUnit\": \"meter\"})\nattr.SetCustomDataByKey(\"nested:shape\", \"round\")\n\nprint(prim.HasAuthoredMetadata(\"assetInfo\")) # Returns: True\nprint(prim.HasAuthoredMetadataDictKey(\"assetInfo\", \"identifier\")) # Returns: True\nprint(prim.HasMetadata(\"assetInfo\")) # Returns: True\nprint(prim.HasMetadataDictKey(\"assetInfo\", \"nested:color\")) # Returns: True\n# prim.ClearMetadata(\"assetInfo\") # Remove all assetInfo in the current layer.\n#// ANCHOR_END: metadataBasics\n\n\n#// ANCHOR: metadataValidateDict\ndata = {\"myCustomKey\": 1}\nsuccess_state, metadata, error_message = Sdf.ConvertToValidMetadataDictionary(data)\n#// ANCHOR_END: metadataValidateDict\n\n\n#// ANCHOR: metadataNestedKeyPath\nfrom pxr import Usd, Sdf\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Xform\")\nprim.SetAssetInfoByKey(\"nested:color\", \"blue\")\nprint(prim.GetAssetInfo()) # Returns: {'nested': {'color': 'blue'}}\nprint(prim.GetAssetInfoByKey(\"nested:color\")) # Returns: \"blue\"\n#// ANCHOR_END: metadataNestedKeyPath\n\n\n#// ANCHOR: metadataAuthored\nfrom pxr import Usd, Sdf\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Xform\")\nprim.SetAssetInfoByKey(\"identifier\", \"bicycle.usd\")\n# The difference between \"authored\" and non \"authored\" methods is\n# that \"authored\" methods don't return fallback values that come from schemas.\nprint(prim.GetAllAuthoredMetadata()) \n# Returns:\n# {'assetInfo': {'identifier': 'bicycle.usd'}, \n#  'specifier': Sdf.SpecifierDef, \n#  'typeName': 'Xform'}\nprint(prim.GetAllMetadata()) \n# Returns:\n#{'assetInfo': {'identifier': 'bicycle.usd'}, \n# 'documentation': 'Concrete prim schema for a transform, which implements Xformable ',\n# 'specifier': Sdf.SpecifierDef,\n# 'typeName': 'Xform'}\n#// ANCHOR_END: metadataAuthored\n\n\n#// ANCHOR: metadataStage\nfrom pxr import Usd, Sdf\nstage = Usd.Stage.CreateInMemory()\nstage.SetMetadata(\"customLayerData\", {\"myCustomStageData\": 1})\n# Is the same as:\nlayer = stage.GetRootLayer()\nmetadata = layer.customLayerData\nmetadata[\"myCustomRootData\"] = 1\nlayer.customLayerData = metadata\n# Or:\nlayer = stage.GetSessionLayer()\nmetadata = layer.customLayerData\nmetadata[\"myCustomSessionData\"] = 1\nlayer.customLayerData = metadata\n# To get the value from the session/root layer depending on the edit target:\nstage.GetMetadata(\"customLayerData\")\n#// ANCHOR_END: metadataStage\n\n\n#// ANCHOR: metadataLayer\nfrom pxr import Usd, Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nlayer.customLayerData = {\"myCustomPipelineKey\": \"myCoolValue\"}\n#// ANCHOR_END: metadataLayer\n\n\n#// ANCHOR: metadataPrimPropertySpec\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\n### Prims ###\nprim_spec = Sdf.CreatePrimInLayer(layer, \"/bicycle\")\nprim_spec.specifier = Sdf.SpecifierDef\n# Asset Info and Custom Data\nprim_spec.assetInfo = {\"identifier\": Sdf.AssetPath(\"bicycle.usd\")}\nprim_spec.customData = {\"myCoolData\": \"myCoolValue\"}\n# General metadata\n# Has: 'HasInfo'\n# Get: 'ListInfoKeys', 'GetMetaDataInfoKeys', 'GetInfo', 'GetFallbackForInfo', 'GetMetaDataDisplayGroup'\n# Set: 'SetInfo', 'SetInfoDictionaryValue'\n# Clear: 'ClearInfo'\nprint(prim_spec.ListInfoKeys()) # Returns: ['assetInfo', 'customData', 'specifier']\n# To get all registered schema keys run:\nprint(prim_spec.GetMetaDataInfoKeys())\n\"\"\"Returns: ['payloadAssetDependencies', 'payload', 'kind', 'suffix', 'inactiveIds', 'clipSets',\n'HDAKeepEngineOpen', 'permission', 'displayGroupOrder', 'assetInfo', 'HDAParms', 'instanceable', \n'symmetryFunction', 'HDATimeCacheMode', 'clips', 'HDAAssetName', 'active', 'HDATimeCacheEnd', \n'customData', 'HDAOptions', 'prefix', 'apiSchemas', 'suffixSubstitutions', 'symmetryArguments',\n'hidden', 'HDATimeCacheStart', 'sdrMetadata', 'typeName', 'HDATimeCacheInterval', 'documentation',\n'prefixSubstitutions', 'symmetricPeer']\"\"\"\n# For the fallback values and UI grouping hint you can use\n# 'GetFallbackForInfo' and 'GetMetaDataDisplayGroup'.\n# Prim spec core data is actually also just metadata info\nprim_spec.SetInfo(\"specifier\", Sdf.SpecifierDef)\nprim_spec.SetInfo(\"typeName\", \"Xform\")\n# Is the same as:\nprim_spec.specifier = Sdf.SpecifierDef\nprim_spec.typeName = \"Xform\"\n\n### Properties ###\nattr_spec = Sdf.AttributeSpec(prim_spec, \"tire:size\", Sdf.ValueTypeNames.Float)\n# Custom Data\nattr_spec.customData = {\"myCoolData\": \"myCoolValue\"}\n# We can actually use the attr_spec.customData assignment here too,\n# doesn't make that much sense though\n# General metadata\n# Has: 'HasInfo'\n# Get: 'ListInfoKeys', 'GetMetaDataInfoKeys', 'GetInfo', 'GetFallbackForInfo', 'GetMetaDataDisplayGroup'\n# Set: 'SetInfo', 'SetInfoDictionaryValue'\n# Clear: 'ClearInfo'\n# The API here is the same as for the prim_spec, as it all inherits from Sdf.Spec\n# To get all registered schema keys run:\nprint(attr_spec.GetMetaDataInfoKeys())\n\"\"\"Returns: ['unauthoredValuesIndex', 'interpolation', 'displayGroup', 'faceIndexPrimvar', \n'suffix', 'constraintTargetIdentifier', 'permission', 'assetInfo', 'symmetryFunction', 'uvPrimvar',\n'elementSize', 'allowedTokens', 'customData', 'prefix', 'renderType', 'symmetryArguments', \n'hidden', 'displayName', 'sdrMetadata', 'faceOffsetPrimvar', 'weight', 'documentation', \n'colorSpace', 'symmetricPeer', 'connectability']\n\"\"\"\n#// ANCHOR_END: metadataPrimPropertySpec\n\n#// ANCHOR: metadataDocs\nfrom pxr import Usd, Sdf\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Cube\")\n# Shortcut to get the docs metadata\n# Has: 'HasAuthoredDocumentation'\n# Get: 'GetDocumentation'\n# Set: 'SetDocumentation'\n# Clear: 'ClearDocumentation'\nprint(prim.GetDocumentation())\nfor attr in prim.GetAttributes():\n    print(attr.GetName(), attr.GetDocumentation())\n    # Or\n    # print(attr.GetMetadata(\"documentation\"))\n#// ANCHOR_END: metadataDocs\n\n#// ANCHOR: metadataDocsResult\n\"\"\"\nDefines a primitive rectilinear cube centered at the origin.\n    The fallback values for Cube, Sphere, Cone, and Cylinder are set so that\n    they all pack into the same volume/bounds.\ndoubleSided Although some renderers treat all parametric or polygonal\n        surfaces as if they were effectively laminae with outward-facing\n        normals on both sides, some renderers derive significant optimizations\n        by considering these surfaces to have only a single outward side,\n        typically determined by control-point winding order and/or \n        orientation.  By doing so they can perform \"backface culling\" to\n        avoid drawing the many polygons of most closed surfaces that face away\n        from the viewer.\n        \n        However, it is often advantageous to model thin objects such as paper\n        and cloth as single, open surfaces that must be viewable from both\n        sides, always.  Setting a gprim's doubleSided attribute to \n        \\c true instructs all renderers to disable optimizations such as\n        backface culling for the gprim, and attempt (not all renderers are able\n        to do so, but the USD reference GL renderer always will) to provide\n        forward-facing normals on each side of the surface for lighting\n        calculations.\nextent Extent is re-defined on Cube only to provide a fallback value.\n        \\sa UsdGeomGprim::GetExtentAttr().\norientation Orientation specifies whether the gprim's surface normal \n        should be computed using the right hand rule, or the left hand rule.\n        Please see for a deeper explanation and\n        generalization of orientation to composed scenes with transformation\n        hierarchies.\nprimvars:displayColor It is useful to have an \"official\" colorSet that can be used\n        as a display or modeling color, even in the absence of any specified\n        shader for a gprim.  DisplayColor serves this role; because it is a\n        UsdGeomPrimvar, it can also be used as a gprim override for any shader\n        that consumes a displayColor parameter.\nprimvars:displayOpacity Companion to displayColor that specifies opacity, broken\n        out as an independent attribute rather than an rgba color, both so that\n        each can be independently overridden, and because shaders rarely consume\n        rgba parameters.\npurpose Purpose is a classification of geometry into categories that \n        can each be independently included or excluded from traversals of prims \n        on a stage, such as rendering or bounding-box computation traversals.\n\n        See for more detail about how \n        purpose is computed and used.\nsize Indicates the length of each edge of the cube.  If you\n        author size you must also author extent.\n\nvisibility Visibility is meant to be the simplest form of \"pruning\" \n        visibility that is supported by most DCC apps.  Visibility is \n        animatable, allowing a sub-tree of geometry to be present for some \n        segment of a shot, and absent from others; unlike the action of \n        deactivating geometry prims, invisible geometry is still \n        available for inspection, for positioning, for defining volumes, etc.\nxformOpOrder Encodes the sequence of transformation operations in the\n        order in which they should be pushed onto a transform stack while\n        visiting a UsdStage's prims in a graph traversal that will effect\n        the desired positioning for this prim and its descendant prims.\n        \n        You should rarely, if ever, need to manipulate this attribute directly.\n        It is managed by the AddXformOp(), SetResetXformStack(), and\n        SetXformOpOrder(), and consulted by GetOrderedXformOps() and\n        GetLocalTransformation().\n\"\"\"\n#// ANCHOR_END: metadataDocsResult\n\n#// ANCHOR: metadataActive\nfrom pxr import Sdf, Usd\n### High Level ###\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Xform\")\nprim.SetActive(False)\n\n### Low Level ###\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/cube\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.active = False\n# Or\nprim_spec.SetInfo(prim_spec.ActiveKey, True)\n#// ANCHOR_END: metadataActive\n\n\n#// ANCHOR: metadataAssetInfo\nfrom pxr import Sdf, Usd\n### High Level ###\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Xform\")\nprim.SetMetadata(\"assetInfo\", {\"identifier\": Sdf.AssetPath(\"bicycler.usd\")})\nprim.SetAssetInfoByKey(\"name\", \"bicycle\")\nprim.SetAssetInfoByKey(\"version\", \"v001\")\nprim.SetAssetInfoByKey(\"payloadAssetDependencies\", Sdf.AssetPathArray([\"assetIndentifierA\", \"assetIndentifierA\"]))\n# Sdf.AssetPathArray([]) auto-casts all elements to Sdf.AssetPath objects.\n\n### Low Level ###\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/cube\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.assetInfo = {\"identifier\": Sdf.AssetPath(\"bicycle.usd\")}\nprim_spec.assetInfo[\"name\"] = \"bicycle\"\nprim_spec.assetInfo[\"version\"] = \"v001\"\nprim_spec.assetInfo[\"payloadAssetDependencies\"] = Sdf.AssetPathArray([\"assetIndentifierA\", \"assetIndentifierA\"])\n# Sdf.AssetPathArray([]) auto-casts all elements to Sdf.AssetPath objects.\n#// ANCHOR_END: metadataAssetInfo\n\n#// ANCHOR: metadataCustomData\nfrom pxr import Sdf, Usd\n### High Level ###\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Xform\")\nprim.SetMetadata(\"customData\", {\"sizeUnit\": \"meter\"})\nprim.SetCustomDataByKey(\"nested:shape\", \"round\")\n\n### Low Level ###\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/cube\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.customData = {\"myCoolData\": \"myCoolValue\"}\n#// ANCHOR_END: metadataCustomData\n\n\n#// ANCHOR: metadataComment\nfrom pxr import Sdf, Usd\n### High Level ###\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Xform\")\nprim.SetMetadata(\"comment\", \"This is a cool prim!\")\n\n### Low Level ###\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/cube\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.SetInfo(\"comment\", \"This is a cool prim spec!\")\n#// ANCHOR_END: metadataComment\n\n#// ANCHOR: metadataIcon\nfrom pxr import Sdf, Usd\n### High Level ###\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Xform\")\nprim.SetMetadata(\"customData\", {\"icon\": \"/path/to/icon.png\"})\nprim.SetCustomDataByKey(\"icon\", \"/path/to/icon.png\")\n\n### Low Level ###\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/cube\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.customData = {\"icon\": \"/path/to/icon.png\"}\n#// ANCHOR_END: metadataIcon\n\n#// ANCHOR: metadataHidden\nfrom pxr import Sdf, Usd\n### High Level ###\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Xform\")\nprim.SetHidden(True)\n\n### Low Level ###\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/cube\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.SetInfo(\"hidden\", True)\n#// ANCHOR_END: metadataHidden\n\n#// ANCHOR: metadataVariability\nfrom pxr import Sdf, Usd\n### High Level ###\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/box\")\nprim = stage.DefinePrim(prim_path, \"Cube\")\nattr = prim.CreateAttribute(\"height\", Sdf.ValueTypeNames.Double)\nattr.SetMetadata(\"variability\", Sdf.VariabilityUniform)\n### Low Level ###\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/box\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.typeName = \"Cube\"\nattr_spec = Sdf.AttributeSpec(prim_spec, \"height\", Sdf.ValueTypeNames.Double)\nattr_spec.SetInfo(\"variability\", Sdf.VariabilityVarying)\n#// ANCHOR_END: metadataVariability\n\n#// ANCHOR: metadataCustom\nfrom pxr import Sdf, Usd\n### High Level ###\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/box\")\nprim = stage.DefinePrim(prim_path, \"Cube\")\nattr = prim.CreateAttribute(\"height\", Sdf.ValueTypeNames.Double)\n# This is not necessary to do explicitly as\n# the high level API does this for us.\nattr.SetMetadata(\"custom\", True)\n# Or\nprint(attr.IsCustom())\nattr.SetCustom(True)\n### Low Level ###\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/box\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.typeName = \"Cube\"\nattr_spec = Sdf.AttributeSpec(prim_spec, \"height\", Sdf.ValueTypeNames.Double)\nattr_spec.SetInfo(\"custom\", True)\n#// ANCHOR_END: metadataCustom\n\n# // ANCHOR: metadataRenderSettingsPrimPath\n### High Level ###\nfrom pxr import Usd\n\nstage = Usd.Stage.CreateInMemory()\nstage.GetRootLayer().pseudoRoot.SetInfo(\n    \"renderSettingsPrimPath\", \"/Render/rendersettings\"\n)\n### Low Level ###\nfrom pxr import Sdf\n\nlayer = Sdf.Layer.CreateAnonymous()\nlayer.pseudoRoot.SetInfo(\"renderSettingsPrimPath\", \"/Render/rendersettings\")\n# // ANCHOR_END: metadataRenderSettingsPrimPath\n\n\n# // ANCHOR: metadataLayerMetrics\nfrom pxr import Sdf, Usd, UsdGeom\n\n### High Level ###\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Cone\")\nsize_attr = prim.GetAttribute(\"radius\")\nfor frame in range(1001, 1006):\n    time_code = Usd.TimeCode(frame)\n    size_attr.Set(frame - 1000, time_code)\n# FPS Metadata\ntime_samples = Sdf.Layer.ListAllTimeSamples(layer)\nstage.SetTimeCodesPerSecond(25)\nstage.SetFramesPerSecond(25)\nstage.SetStartTimeCode(time_samples[0])\nstage.SetEndTimeCode(time_samples[-1])\n# Scene Unit Scale\nUsdGeom.SetStageMetersPerUnit(stage, UsdGeom.LinearUnits.centimeters)\n# To map 24 fps (default) to 25 fps we have scale by 24/25 when loading the layer in the Sdf.LayerOffset\n# Scene Up Axis\nUsdGeom.SetStageUpAxis(stage, UsdGeom.Tokens.y)  # Or  UsdGeom.Tokens.z\n\n### Low Level ###\nfrom pxr import Sdf\n\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/bicycle\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.specifier = Sdf.SpecifierDef\nprim_spec.typeName = \"Cube\"\nattr_spec = Sdf.AttributeSpec(prim_spec, \"size\", Sdf.ValueTypeNames.Double)\nfor frame in range(1001, 1006):\n    value = float(frame - 1000)\n    layer.SetTimeSample(attr_spec.path, frame, value)\n# FPS Metadata\nlayer.timeCodesPerSecond = 25\nlayer.framesPerSecond = 25\nlayer.startTimeCode = time_samples[0]\nlayer.endTimeCode = time_samples[-1]\n# Scene Unit Scale\nlayer.pseudoRoot.SetInfo(UsdGeom.Tokens.metersPerUnit, UsdGeom.LinearUnits.centimeters)\n# Scene Up Axis\nlayer.pseudoRoot.SetInfo(\n    UsdGeom.Tokens.upAxis, UsdGeom.Tokens.y\n)  # Or  UsdGeom.Tokens.z\n# // ANCHOR_END: metadataLayerMetrics\n\n#// ANCHOR: debuggingTokens\nfrom pxr import Tf\n# To check if a symbol is active:\nTf.Debug.IsDebugSymbolNameEnabled(\"MY_SYMBOL_NAME\")\n# To print all symbols\ndocs = Tf.Debug.GetDebugSymbolDescriptions()\nfor name in Tf.Debug.GetDebugSymbolNames():\n    desc = Tf.Debug.GetDebugSymbolDescription(name)\n    print(\"{:<50} | {}\".format(name, desc))\n#// ANCHOR_END: debuggingTokens\n\n#// ANCHOR: debuggingTokensMarkdown\nfrom pxr import Tf\ndocs = Tf.Debug.GetDebugSymbolDescriptions()\nprint(\"| Variable Name | Description |\")\nprint(\"|-|-|\")\nfor name in Tf.Debug.GetDebugSymbolNames():\n    desc = Tf.Debug.GetDebugSymbolDescription(name)\n    print(\"| {} | {} |\".format(name, desc))\n#// ANCHOR_END: debuggingTokensMarkdown\n\n#// ANCHOR: profilingTraceAttach\nimport os\nfrom pxr import Trace, Usd\n# Code with trace attached\nclass Bar():\n    @Trace.TraceMethod\n    def foo(self):\n        print(\"Bar.foo\")\n\n@Trace.TraceFunction\ndef foo(stage):\n    with Trace.TraceScope(\"InnerScope\"):\n        bar = Bar()\n        for prim in stage.Traverse():\n            prim.HasAttribute(\"size\")\n#// ANCHOR_END: profilingTraceAttach\n\n#// ANCHOR: profilingTraceCollect\nimport os\nfrom pxr import Trace, Usd\n# The Trace.Collector() and Trace.Reporter.globalReporter return a singletons\n# The default traces all go to TraceCategory::Default, this is not configurable via python\nglobal_reporter = Trace.Reporter.globalReporter\nglobal_reporter.ClearTree()\ncollector = Trace.Collector()\ncollector.Clear()\n# Start recording events.\ncollector.enabled = True\n# Enable the Usd Python API tracing (No the manually attached tracers)\ncollector.pythonTracingEnabled = False\n# Run code\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Xform\")\nfoo(stage)\n# Stop recording events.\ncollector.enabled = False\n# Print the ASCII report\ntrace_dir_path = os.path.dirname(os.path.expanduser(\"~/Desktop/UsdTracing\"))\nglobal_reporter.Report(os.path.join(trace_dir_path, \"report.trace\"))\nglobal_reporter.ReportChromeTracingToFile(os.path.join(trace_dir_path,\"report.json\"))\n#// ANCHOR_END: profilingTraceCollect\n\n#// ANCHOR: profilingStopWatch\nfrom pxr import Tf\nsw = Tf.Stopwatch()\nsw.Start()\nsw.Stop()\nsw.Start()\nsw.Stop()\nprint(sw.milliseconds, sw.sampleCount)\nsw.Reset()\n# Add sampleCount + accumulated time from other stop watch\nother_sw = Tf.StopWatch()\nother_sw.Start()\nother_sw.Stop()\nsw.AddFrom(other_sw) \nprint(sw.milliseconds, sw.sampleCount)\n#// ANCHOR_END: profilingStopWatch\n\n#// ANCHOR: pluginsRegistry\nfrom pxr import Plug\nregistry = Plug.Registry()\nfor plugin in registry.GetAllPlugins():\n    print(plugin.name, plugin.path, plugin.isLoaded)\n    # To print the plugInfo.json content run:\n    # print(plugin.metadata)\n#// ANCHOR_END: pluginsRegistry\n\n#// ANCHOR: assetResolverBound\nfrom pxr import Ar\nfrom usdAssetResolver import FileResolver\nprint(Ar.GetResolver())\nprint(Ar.GetUnderlyingResolver()) # Returns: <usdAssetResolver.FileResolver.Resolver object at <address>>\n#// ANCHOR_END: assetResolverBound\n\n#// ANCHOR: assetResolverScopedCache\nfrom pxr import Ar\nwith Ar.ResolverScopedCache() as scope:\n    resolver = Ar.GetResolver()\n    path = resolver.Resolve(\"box.usda\")\n#// ANCHOR_END: assetResolverScopedCache\n\n#// ANCHOR: assetResolverContextAccess\ncontext_collection = stage.GetPathResolverContext()\nactiveResolver_context = context_collection.Get()[0]\n#// ANCHOR_END: assetResolverContextAccess \n\n#// ANCHOR: assetResolverContextCreation\nfrom pxr import Ar, Usd\nfrom usdAssetResolver import FileResolver\nresolver = Ar.GetUnderlyingResolver()\ncontext_collection = resolver.CreateDefaultContext() # Returns: Ar.ResolverContext(FileResolver.ResolverContext())\ncontext = context_collection.Get()[0]\ncontext.ModifySomething() # Call specific functions of your resolver.\n# Create a stage that uses the context\nstage = Usd.Stage.CreateInMemory(\"/output/stage/filePath.usd\", pathResolverContext=context)\n# Or\nstage = Usd.Stage.Open(\"/Existing/filePath/to/UsdFile.usd\", pathResolverContext=context)\n#// ANCHOR_END: assetResolverContextCreation\n\n#// ANCHOR: assetResolverContextRefresh\nfrom pxr import Ar\n...\nresolver = Ar.GetResolver()\n# The resolver context is actually a list, as there can be multiple resolvers \n# running at the same time. In this example we only have a single non-URI resolver\n# running, therefore we only have a single element in the list.\ncontext_collection = stage.GetPathResolverContext()\nactiveResolver_context = context_collection.Get()[0]\n# Your asset resolver has to Python expose methods to modify the context.\nactiveResolver_context.ModifySomething()\n# Trigger Refresh (Some DCCs, like Houdini, additionally require node re-cooks.)\nresolver.RefreshContext(context_collection)\n...\n#// ANCHOR_END: assetResolverContextRefresh\n\n#// ANCHOR: assetResolverStageContextResolve\nresolved_path = stage.ResolveIdentifierToEditTarget(\"someAssetIdentifier\")\n# Get the Python string\nresolved_path_str = resolved_path.GetPathString() # Or str(resolved_path)\n#// ANCHOR_END: assetResolverStageContextResolve\n\n#// ANCHOR: assetResolverResolve\nfrom pxr import Ar\nresolver = Ar.GetResolver()\nresolved_path = resolver.Resolve(\"someAssetIdentifier\")\n# Get the Python string\nresolved_path_str = resolved_path.GetPathString() # Or str(resolved_path)\n#// ANCHOR_END: assetResolverResolve\n\n#// ANCHOR: assetResolverAssetPath\nfrom pxr import Sdf\nasset_path = Sdf.AssetPath(\"someAssetIdentifier\", \"/some/Resolved/Path.usd\")\nprint(asset_path.path)         # Returns: \"someAssetIdentifier\"\nprint(asset_path.resolvedPath) # Returns: \"/some/Resolved/Path.usd\"\n#// ANCHOR_END: assetResolverAssetPath\n\n\n#// ANCHOR: noticeRegisterRevoke\nfrom pxr import Tf, Usd\ndef callback(notice, sender):\n    print(notice, sender)\n# Add\n# Global\nlistener = Tf.Notice.RegisterGlobally(Usd.Notice.StageContentsChanged, callback)\n# Per Stage\nlistener = Tf.Notice.Register(Usd.Notice.StageContentsChanged, callback, stage)\n# Remove\nlistener.Revoke()\n#// ANCHOR_END: noticeRegisterRevoke\n\n\n#// ANCHOR: noticeCommon\nfrom pxr import Usd, Plug\n# Generic (Do not send what stage they are from)\nnotice = Usd.Notice.StageContentsChanged\nnotice = Usd.Notice.StageEditTargetChanged\n# Layer Muting\nnotice = Usd.Notice.LayerMutingChanged\n# In the callback you can get the changed layers by calling:\n# notice.GetMutedLayers()\n# notice.GetUnmutedLayers()\n# Object Changed\nnotice = Usd.Notice.ObjectsChanged\n# In the callback you can get the following info by calling:\n# notice.GetResyncedPaths()          # Changed Paths (Composition or Creation/Rename/Removal)\n# notice.GetChangedInfoOnlyPaths()   # Attribute/Metadata value changes\n# With these methods you can test if a Usd object \n# (UsdObject==BaseClass for Prims/Properties/Metadata) has been affected.\n# notice.AffectedObject(UsdObject) (Generic)\n# notice.ResyncedObject(UsdObject) (Composition Change)\n# notice.ChangedInfoOnly(UsdObject) (Value Change)\n# notice.HasChangedFields(UsdObject/SdfPath) \n# notice.GetChangedFields(UsdObject/SdfPath)\n# Plugin registered\nnotice = Plug.Notice.DidRegisterPlugins\n# notice.GetNewPlugins() # Get new plugins\n#// ANCHOR_END: noticeCommon\n\n\n#// ANCHOR: noticePlugins\nfrom pxr import Tf, Usd, Plug\n\ndef DidRegisterPlugins_callback(notice):\n    print(notice, notice.GetNewPlugins())\n\nlistener = Tf.Notice.RegisterGlobally(Plug.Notice.DidRegisterPlugins, DidRegisterPlugins_callback)\nlistener.Revoke()\n#// ANCHOR_END: noticePlugins\n\n\n#// ANCHOR: noticeCommonApplied\nfrom pxr import Tf, Usd, Sdf\n\ndef ObjectsChanged_callback(notice, sender):\n    stage = notice.GetStage()\n    print(\"---\")\n    print(\">\", notice, sender)\n    print(\">> (notice.GetResyncedPaths) - Updated paths\", notice.GetResyncedPaths())\n    print(\">> (notice.GetChangedInfoOnlyPaths) - Attribute/Metadata value changes\", notice.GetChangedInfoOnlyPaths())\n    \n    prim = stage.GetPrimAtPath(\"/bicycle\")\n    if prim:\n        # Check if a specific UsdObject was affected\n        print(\">> (notice.AffectedObject) - Something changed for\", prim.GetPath(), notice.AffectedObject(prim))\n        print(\">> (notice.ResyncedObject) - Updated path for\", prim.GetPath(), notice.ResyncedObject(prim))\n        print(\">> (notice.ChangedInfoOnly) - Attribute/Metadata ChangedInfoOnly\", prim.GetPath(), notice.ChangedInfoOnly(prim))\n        print(\">> (notice.HasChangedFields) - Attribute/Metadata HasChanges\", prim.GetPath(), notice.HasChangedFields(prim))\n        print(\">> (notice.GetChangedFields) - Attribute/Metadata ChangedFields\", prim.GetPath(), notice.GetChangedFields(prim))\n\n    attr = stage.GetAttributeAtPath(\"/bicycle.tire:size\")\n    if attr:\n        # Check if a specific UsdObject was affected\n        print(\">> (notice.AffectedObject) - Something changed for\", attr.GetPath(), notice.AffectedObject(attr))\n        print(\">> (notice.ResyncedObject) - Updated path for\", attr.GetPath(), notice.ResyncedObject(attr))\n        print(\">> (notice.ChangedInfoOnly) - Attribute/Metadata ChangedInfoOnly\", attr.GetPath(), notice.ChangedInfoOnly(attr))\n        print(\">> (notice.HasChangedFields) - Attribute/Metadata HasChanges\", attr.GetPath(), notice.HasChangedFields(attr))\n        print(\">> (notice.GetChangedFields) - Attribute/Metadata ChangedFields\", attr.GetPath(), notice.GetChangedFields(attr))\n\n# Add\nlistener = Tf.Notice.RegisterGlobally(Usd.Notice.ObjectsChanged, ObjectsChanged_callback)\n# Edit\nstage = Usd.Stage.CreateInMemory()\n# Create Prim\nprim = stage.DefinePrim(\"/bicycle\")\n# Results:\n# >> <pxr.Usd.ObjectsChanged object at 0x7f071d58e820> Usd.Stage.Open(rootLayer=Sdf.Find('anon:0x7f06927ccc00:tmp.usda'), sessionLayer=Sdf.Find('anon:0x7f06927cdb00:tmp-session.usda'))\n# >> (notice.GetResyncedPaths) - Updated paths [Sdf.Path('/bicycle')]\n# >> (notice.GetChangedInfoOnlyPaths) - Attribute/Metadata value changes []\n# >> (notice.AffectedObject) - Something changed for /bicycle True\n# >> (notice.ResyncedObject) - Updated path for /bicycle True\n# >> (notice.ChangedInfoOnly) - Attribute/Metadata ChangedFieldsOnly /bicycle False\n# >> (notice.HasChangedFields) - Attribute/Metadata HasChanges /bicycle True\n# >> (notice.GetChangedFields) - Attribute/Metadata ChangedFields /bicycle ['specifier']\n# Create Attribute\nattr = prim.CreateAttribute(\"tire:size\", Sdf.ValueTypeNames.Float)\n# Results:\n# >> <pxr.Usd.ObjectsChanged object at 0x7f071d58e820> Usd.Stage.Open(rootLayer=Sdf.Find('anon:0x7f06927ccc00:tmp.usda'), sessionLayer=Sdf.Find('anon:0x7f06927cdb00:tmp-session.usda'))\n# >> (notice.GetResyncedPaths) - Updated paths [Sdf.Path('/bicycle.tire:size')]\n# >> (notice.GetChangedInfoOnlyPaths) - Attribute/Metadata value changes []\n# >> (notice.AffectedObject) - Something changed for /bicycle False\n# >> (notice.ResyncedObject) - Updated path for /bicycle False\n# >> (notice.ChangedInfoOnly) - Attribute/Metadata ChangedInfoOnly /bicycle False\n# >> (notice.HasChangedFields) - Attribute/Metadata HasChanges /bicycle False\n# >> (notice.GetChangedFields) - Attribute/Metadata ChangedFields /bicycle []\n# >> (notice.AffectedObject) - Something changed for /bicycle.tire:size True\n# >> (notice.ResyncedObject) - Updated path for /bicycle.tire:size True\n# >> (notice.ChangedInfoOnly) - Attribute/Metadata ChangedInfoOnly /bicycle.tire:size False\n# >> (notice.HasChangedFields) - Attribute/Metadata HasChanges /bicycle.tire:size True\n# >> (notice.GetChangedFields) - Attribute/Metadata ChangedFields /bicycle.tire:size ['custom']\n# Remove\nlistener.Revoke()\n#// ANCHOR_END: noticeCommonApplied\n\n\n#// ANCHOR: noticeCustom\nfrom pxr import Tf, Usd\n# Create notice callback\ndef callback(notice, sender):\n    print(notice, sender)\n# Create a new notice type\nclass CustomNotice(Tf.Notice):\n    '''My custom notice'''\n# Get fully qualified domain name\nCustomNotice_FQN = \"{}.{}\".format(CustomNotice.__module__, CustomNotice.__name__)\n# Register notice\n# Important: If you overwrite the CustomNotice Class in the same Python session\n# (for example when running this snippet twice in a DCC Python session), you\n# cannot send anymore notifications as the defined type will have lost the pointer\n# to the class, but you can't re-define it because of how the type definition works.\nif not Tf.Type.FindByName(CustomNotice_FQN):\n    Tf.Type.Define(CustomNotice)\n# Register notice listeners\n# Globally\nlistener = Tf.Notice.RegisterGlobally(CustomNotice, callback)\n# For a specific stage\nsender = Usd.Stage.CreateInMemory()\nlistener = Tf.Notice.Register(CustomNotice, callback, sender)\n# Send notice\nCustomNotice().SendGlobally()\nCustomNotice().Send(sender)\n# Remove listener\nlistener.Revoke()\n#// ANCHOR_END: noticeCustom\n\n\n#// ANCHOR: kindRegistry\nfrom pxr import Kind\nregistry = Kind.Registry()\nfor kind in registry.GetAllKinds():\n    base_kind = Kind.Registry.GetBaseKind(kind)\n    print(f\"{kind:<15} - Base Kind - {base_kind}\")\n# Returns:\n\"\"\"\nset             - Base Kind - assembly\nassembly        - Base Kind - group\nfx              - Base Kind - component\nenvironment     - Base Kind - assembly\ncharacter       - Base Kind - component\ngroup           - Base Kind - model\ncomponent       - Base Kind - model\nmodel           - Base Kind \nsubcomponent    - Base Kind \n\"\"\"    \nprint(registry.HasKind(\"fx\")) # Returns: True\nprint(registry.IsA(\"fx\", \"model\")) # Returns: True\n#// ANCHOR_END: kindRegistry\n\n#// ANCHOR: kindTraversal\nfrom pxr import Kind, Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nprim = stage.DefinePrim(Sdf.Path(\"/set\"), \"Xform\")\nUsd.ModelAPI(prim).SetKind(\"set\")\nprim = stage.DefinePrim(Sdf.Path(\"/set/garage\"), \"Xform\")\nUsd.ModelAPI(prim).SetKind(\"group\")\nprim = stage.DefinePrim(Sdf.Path(\"/set/garage/bicycle\"), \"Xform\")\nUsd.ModelAPI(prim).SetKind(\"prop\")\nprim = stage.DefinePrim(Sdf.Path(\"/set/yard\"), \"Xform\")\nUsd.ModelAPI(prim).SetKind(\"group\")\nprim = stage.DefinePrim(Sdf.Path(\"/set/yard/explosion\"), \"Xform\")\nUsd.ModelAPI(prim).SetKind(\"fx\")\n# Result:\nprint(stage.ExportToString())\n\"\"\"\ndef Xform \"set\" (\n    kind = \"set\"\n)\n{\n    def Xform \"garage\" (\n        kind = \"group\"\n    )\n    {\n        def Xform \"bicycle\" (\n            kind = \"prop\"\n        )\n        {\n        }\n    }\n\n    def Xform \"yard\" (\n        kind = \"group\"\n    )\n    {\n        def Xform \"explosion\" (\n            kind = \"fx\"\n        )\n        {\n        }\n    }\n}\n\"\"\"\nfor prim in stage.Traverse():\n    print(\"{:<20} - IsModel: {} - IsGroup: {}\".format(prim.GetPath().pathString, prim.IsModel(), prim.IsGroup()))\n# Returns:\n\"\"\"\n/set                 - IsModel: True - IsGroup: True\n/set/garage          - IsModel: True - IsGroup: True\n/set/garage/bicycle  - IsModel: True - IsGroup: False\n/set/yard            - IsModel: True - IsGroup: True\n/set/yard/explosion  - IsModel: True - IsGroup: False\n\"\"\"\nregistry = Kind.Registry()\nfor prim in stage.Traverse():\n    kind = Usd.ModelAPI(prim).GetKind()\n    print(\"{:<25} - {:<5} - {}\".format(prim.GetPath().pathString, kind, registry.IsA(\"fx\", \"component\")))\n\n# Failed traversal because of missing kinds\nstage = Usd.Stage.CreateInMemory()\nprim = stage.DefinePrim(Sdf.Path(\"/set\"), \"Xform\")\nUsd.ModelAPI(prim).SetKind(\"set\")\nprim = stage.DefinePrim(Sdf.Path(\"/set/garage\"), \"Xform\")\nprim = stage.DefinePrim(Sdf.Path(\"/set/garage/bicycle\"), \"Xform\")\nUsd.ModelAPI(prim).SetKind(\"prop\")\nprim = stage.DefinePrim(Sdf.Path(\"/set/yard\"), \"Xform\")\nprim = stage.DefinePrim(Sdf.Path(\"/set/yard/explosion\"), \"Xform\")\nUsd.ModelAPI(prim).SetKind(\"fx\")\nregistry = Kind.Registry()\nfor prim in stage.Traverse():\n    kind = Usd.ModelAPI(prim).GetKind()\n    print(\"{:<20} - Kind: {:10} - IsA('component') {}\".format(prim.GetPath().pathString, kind, registry.IsA(kind, \"component\")))\n    print(\"{:<20} - IsModel: {} - IsGroup: {}\".format(prim.GetPath().pathString, prim.IsModel(), prim.IsGroup()))\n\"\"\"\n/set                 - Kind: set        - IsA('component') False\n/set                 - IsModel: True - IsGroup: True\n/set/garage          - Kind:            - IsA('component') False\n/set/garage          - IsModel: False - IsGroup: False\n/set/garage/bicycle  - Kind: prop       - IsA('component') True\n/set/garage/bicycle  - IsModel: False - IsGroup: False\n/set/yard            - Kind:            - IsA('component') False\n/set/yard            - IsModel: False - IsGroup: False\n/set/yard/explosion  - Kind: fx         - IsA('component') True\n/set/yard/explosion  - IsModel: False - IsGroup: False\n\"\"\"\n#// ANCHOR_END: kindTraversal\n\n\n\n#// ANCHOR: animationOverview\nfrom pxr import Sdf, Usd\n### High Level ###\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Cube\")\nsize_attr = prim.GetAttribute(\"size\")\nfor frame in range(1001, 1005):\n    time_code = Usd.TimeCode(float(frame - 1001))\n    # .Set() takes args in the .Set(<value>, <frame>) format\n    size_attr.Set(frame, time_code)\nprint(size_attr.Get(1005)) # Returns: 4\n\n### Low Level ###\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/bicycle\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.specifier = Sdf.SpecifierDef\nprim_spec.typeName = \"Cube\"\nattr_spec = Sdf.AttributeSpec(prim_spec, \"size\", Sdf.ValueTypeNames.Double)\nfor frame in range(1001, 1005):\n    value = float(frame - 1001)\n    # .SetTimeSample() takes args in the .SetTimeSample(<path>, <frame>, <value>) format\n    layer.SetTimeSample(attr_spec.path, frame, value)\nprint(layer.QueryTimeSample(attr_spec.path, 1005)) # Returns: 4\n#// ANCHOR_END: animationOverview\n\n#// ANCHOR: animationTimeCode\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Cube\")\nsize_attr = prim.GetAttribute(\"size\")\n## Set default value\ntime_code = Usd.TimeCode.Default()\nsize_attr.Set(10, time_code)\n# Or:\nsize_attr.Set(10) # The default is to set `default` (non-per-frame) data.\n## Set per frame value\nfor frame in range(1001, 1005):\n    time_code = Usd.TimeCode(frame)\n    size_attr.Set(frame, time_code)\n# Or\n# As with Sdf.Path implicit casting from strings in a lot of places in the USD API,\n# the time code is implicitly casted from a Python float. \n# It is recommended to do the above, to be more future proof of \n# potentially encoding time unit based samples.\nfor frame in range(1001, 1005):\n    size_attr.Set(frame, frame)\n## Other than that the TimeCode class only has a via Is/Get methods of interest:\nsize_attr.IsDefault() # Returns: True if no time value was given\nsize_attr.IsNumeric() # Returns: True if not IsDefault()\nsize_attr.GetValue() # Returns: The time value (if not IsDefault()\n#// ANCHOR_END: animationTimeCode\n\n#// ANCHOR: animationLayerOffset\nfrom pxr import Sdf, Usd\n# The Sdf.LayerOffset(<offset>, <scale>) class has \n# no attributes/methods other than LayerOffset.offset & LayerOffset.scale.\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/animal\")\nroot_layer = stage.GetRootLayer()\n## For sublayering via Python, we first need to sublayer, then edit offset.\n# In Houdini we can't due this directly due to Houdini's stage handling system.\nfile_path = \"/opt/hfs19.5/houdini/usd/assets/pig/pig.usd\"\nroot_layer.subLayerPaths.append(file_path)\nprint(root_layer.subLayerPaths)\nprint(root_layer.subLayerOffsets)\n# Since layer offsets are read only, we need to assign it to a new one in-place.\n# !DANGER! Due to how it is exposed to Python, we can't assign a whole array with the\n# new offsets, instead we can only swap individual elements in the array, so that the\n# array pointer is kept intact.\nroot_layer.subLayerOffsets[0] = Sdf.LayerOffset(25, 1) \n## For references\nref = Sdf.Reference(file_path, \"/pig\", Sdf.LayerOffset(25, 1))\nprim = stage.DefinePrim(prim_path)\nref_API = prim.GetReferences()\nref_API.AddReference(ref)\nref = Sdf.Reference(\"\", \"/animal\", Sdf.LayerOffset(50, 1))\ninternal_prim = stage.DefinePrim(prim_path.ReplaceName(\"internal\"))\nref_API = internal_prim.GetReferences()\nref_API.AddReference(ref)\n## For payloads\npayload = Sdf.Payload(file_path, \"/pig\", Sdf.LayerOffset(25, 1))\nprim = stage.DefinePrim(prim_path)\npayload_API = prim.GetPayloads()\npayload_API.AddPayload(payload)\n#// ANCHOR_END: animationLayerOffset\n\n\n#// ANCHOR: animationWrite\nfrom pxr import Sdf, Usd\n### High Level ###\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Cube\")\nsize_attr = prim.GetAttribute(\"size\")\n## Set default value\ntime_code = Usd.TimeCode.Default()\nsize_attr.Set(10, time_code)\n# Or:\nsize_attr.Set(10) # The default is to set `default` (non-per-frame) data.\n## Set per frame value\nfor frame in range(1001, 1005):\n    value = float(frame - 1001)\n    time_code = Usd.TimeCode(frame)\n    size_attr.Set(value, time_code)\n# Clear default value\nsize_attr.ClearDefault(1001)\n# Remove a time sample\nsize_attr.ClearAtTime(1001)\n\n### Low Level ###\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/bicycle\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.specifier = Sdf.SpecifierDef\nprim_spec.typeName = \"Cube\"\nattr_spec = Sdf.AttributeSpec(prim_spec, \"size\", Sdf.ValueTypeNames.Double)\n## Set default value\nattr_spec.default = 10\n## Set per frame value\nfor frame in range(1001, 1005):\n    value = float(frame - 1001)\n    layer.SetTimeSample(attr_spec.path, frame, value)\n# Clear default value\nattr_spec.ClearDefaultValue()\n# Remove a time sample\nlayer.EraseTimeSample(attr_spec.path, 1001)\n#// ANCHOR_END: animationWrite\n\n#// ANCHOR: animationRead\nfrom pxr import Gf, Sdf, Usd\n### High Level ###\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Cube\")\nsize_attr = prim.GetAttribute(\"size\")\nsize_attr.Set(10) \nfor frame in range(1001, 1005):\n    time_code = Usd.TimeCode(frame)\n    size_attr.Set(frame-1001, time_code)\n# Query the default value (must be same value source aka layer as the time samples).\nprint(size_attr.Get()) # Returns: 10\n# Query the animation time samples\nfor time_sample in size_attr.GetTimeSamples():\n    print(size_attr.Get(time_sample))\n# Returns:\n\"\"\"\n0.0, 1.0, 2.0, 3.0\n\"\"\"\n# Other important time sample methods:\n# !Danger! For value clipped (per frame loaded layers),\n# this will look into all layers, which is quite expensive.\nprint(size_attr.GetNumTimeSamples()) # Returns: 4\n# You should rather use:\n# This does a check for time sample found > 2.\n# So it stops looking for more samples after the second sample.\nprint(size_attr.ValueMightBeTimeVarying()) # Returns: True\n## We can also query what the closest time sample to a frame:\nprint(size_attr.GetBracketingTimeSamples(1003.3)) \n# Returns: (<Found sample>, <lower closest sample>, <upper closest sample>)\n(True, 1003.0, 1004.0)\n## We can also query time samples in a range. This is useful if we only want to lookup and copy\n# a certain range, for example in a pre-render script.\nprint(size_attr.GetTimeSamplesInInterval(Gf.Interval(1001, 1003))) \n# Returns: [1001.0, 1002.0, 1003.0]\n\n\n### Low Level ###\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/bicycle\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.specifier = Sdf.SpecifierDef\nprim_spec.typeName = \"Cube\"\nattr_spec = Sdf.AttributeSpec(prim_spec, \"size\", Sdf.ValueTypeNames.Double)\nattr_spec.default = 10\nfor frame in range(1001, 1005):\n    value = float(frame - 1001)\n    layer.SetTimeSample(attr_spec.path, frame, value)\n# Query the default value\nprint(attr_spec.default) # Returns: 10\n# Query the animation time samples\ntime_sample_count = layer.GetNumTimeSamplesForPath(attr_spec.path)\nfor time_sample in layer.ListTimeSamplesForPath(attr_spec.path):\n    print(layer.QueryTimeSample(attr_spec.path, time_sample))\n# Returns:\n\"\"\"\n0.0, 1.0, 2.0, 3.0\n\"\"\"\n## We can also query what the closest time sample is to a frame:\nprint(layer.GetBracketingTimeSamplesForPath(attr_spec.path, 1003.3)) \n# Returns: (<Found sample>, <lower closest sample>, <upper closest sample>)\n(True, 1003.0, 1004.0)\n#// ANCHOR_END: animationRead\n\n#// ANCHOR: animationTimeVarying\n# !Danger! For value clipped (per frame loaded layers),\n# this will look into all layers, which is quite expensive.\nprint(size_attr.GetNumTimeSamples())\n# You should rather use:\n# This does a check for time sample found > 2.\n# So it stops looking for more samples after the second sample.\nprint(size_attr.ValueMightBeTimeVarying())\n#// ANCHOR_END: animationTimeVarying\n\n#// ANCHOR: animationSpecialValues\nfrom pxr import Sdf, Usd\n### High Level ###\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Cube\")\nsize_attr = prim.GetAttribute(\"size\")\nfor frame in range(1001, 1005):\n    time_code = Usd.TimeCode(frame)\n    size_attr.Set(frame - 1001, time_code)\n## Value Blocking\nsize_attr.Set(1001, Sdf.ValueBlock())\n\n### Low Level ###\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/bicycle\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.specifier = Sdf.SpecifierDef\nprim_spec.typeName = \"Cube\"\nattr_spec = Sdf.AttributeSpec(prim_spec, \"size\", Sdf.ValueTypeNames.Double)\nfor frame in range(1001, 1005):\n    value = float(frame - 1001)\n    layer.SetTimeSample(attr_spec.path, frame, value)\n\n## Value Blocking\nlayer.SetTimeSample(attr_spec.path, 1001, Sdf.ValueBlock())\n#// ANCHOR_END: animationSpecialValues\n\n#// ANCHOR: animationFPS\nfrom pxr import Sdf, Usd\n### High Level ###\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Cube\")\nsize_attr = prim.GetAttribute(\"size\")\nfor frame in range(1001, 1005):\n    time_code = Usd.TimeCode(frame)\n    size_attr.Set(frame - 1001, time_code)\n# FPS Metadata\nstage.SetTimeCodesPerSecond(25)\nstage.SetFramesPerSecond(25)\nstage.SetStartTimeCode(1001)\nstage.SetEndTimeCode(1005)\n\n### Low Level ###\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/bicycle\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.specifier = Sdf.SpecifierDef\nprim_spec.typeName = \"Cube\"\nattr_spec = Sdf.AttributeSpec(prim_spec, \"size\", Sdf.ValueTypeNames.Double)\nfor frame in range(1001, 1005):\n    value = float(frame - 1001)\n    layer.SetTimeSample(attr_spec.path, frame, value)\n# FPS Metadata\ntime_samples = Sdf.Layer.ListAllTimeSamples(layer)\nlayer.timeCodesPerSecond = 25\nlayer.framesPerSecond = 25\nlayer.startTimeCode = time_samples[0]\nlayer.endTimeCode = time_samples[-1]\n\n###### Stage vs Layer TimeSample Scaling ######\nfrom pxr import Sdf, Usd\n\nlayer_fps = 25\nlayer_identifier = \"ref_layer.usd\"\nstage_fps = 24\nstage_identifier = \"root_layer.usd\"\nframe_start = 1001\nframe_end = 1025\n\n# Create layer\nreference_layer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/bicycle\")\nprim_spec = Sdf.CreatePrimInLayer(reference_layer, prim_path)\nprim_spec.specifier = Sdf.SpecifierDef\nprim_spec.typeName = \"Cube\"\nattr_spec = Sdf.AttributeSpec(prim_spec, \"size\", Sdf.ValueTypeNames.Double)\nfor frame in range(frame_start, frame_end + 1):\n    value = float(frame - frame_start) + 1\n    # If we work correctly in seconds everything works as expected.\n    reference_layer.SetTimeSample(attr_spec.path, frame * (layer_fps/stage_fps), value)\n    # In VFX we often work frame based starting of at 1001 regardless of the FPS.\n    # If we then load the 25 FPS in 24 FPS, USD applies the correct scaling, but we have\n    # to apply the correct offset to our \"custom\" start frame.\n    # reference_layer.SetTimeSample(attr_spec.path, frame, value)\n# FPS Metadata\ntime_samples = Sdf.Layer.ListAllTimeSamples(reference_layer)\nreference_layer.timeCodesPerSecond = layer_fps\nreference_layer.framesPerSecond = layer_fps\nreference_layer.startTimeCode = time_samples[0]\nreference_layer.endTimeCode = time_samples[-1]\n# reference_layer.Export(layer_identifier)\n\n# Create stage\nstage = Usd.Stage.CreateInMemory()\n# If we work correctly in seconds everything works as expected.\nreference_layer_offset = Sdf.LayerOffset(0, 1)\n# In VFX we often work frame based starting of at 1001.\n# If we then load the 25 FPS in 24 FPS, USD applies the correct scaling, but we have\n# to apply the correct offset to our \"custom\" start frame.\n# reference_layer_offset = Sdf.LayerOffset(frame_start * (stage_fps/layer_fps) - frame_start, 1)\nreference = Sdf.Reference(reference_layer.identifier, \"/bicycle\", reference_layer_offset)\nbicycle_prim_path = Sdf.Path(\"/bicycle\")\nbicycle_prim = stage.DefinePrim(bicycle_prim_path)\nreferences_api = bicycle_prim.GetReferences()\nreferences_api.AddReference(reference, position=Usd.ListPositionFrontOfAppendList)\n# FPS Metadata (In Houdini we can't set this via python, use a 'configure layer' node instead.)\nstage.SetTimeCodesPerSecond(stage_fps)\nstage.SetFramesPerSecond(stage_fps)\nstage.SetStartTimeCode(1001)\nstage.SetEndTimeCode(1005)\n# stage.Export(stage_identifier)\n#// ANCHOR_END: animationFPS\n\n#// ANCHOR: animationMotionVelocityAcceleration\nimport numpy as np\n\nfrom pxr import Sdf, Usd, UsdGeom\n\n\nMOTION_ATTRIBUTE_NAMES_BY_TYPE_NAME = {\n    UsdGeom.Tokens.Mesh: (UsdGeom.Tokens.points, UsdGeom.Tokens.velocities, UsdGeom.Tokens.accelerations),\n    UsdGeom.Tokens.Points: (UsdGeom.Tokens.points, UsdGeom.Tokens.velocities, UsdGeom.Tokens.accelerations),\n    UsdGeom.Tokens.BasisCurves: (UsdGeom.Tokens.points, UsdGeom.Tokens.velocities, UsdGeom.Tokens.accelerations),\n    UsdGeom.Tokens.PointInstancer: (UsdGeom.Tokens.positions, UsdGeom.Tokens.velocities, UsdGeom.Tokens.accelerations)\n}\n# To lookup schema specific names\n# schema_registry = Usd.SchemaRegistry()\n# schema = schema_registry.FindConcretePrimDefinition(\"Mesh\")\n# print(schema.GetPropertyNames())\n\ndef compute_time_derivative(layer, prim_spec, attr_name, ref_attr_name, time_code_inc, multiplier=1.0):\n    ref_attr_spec = prim_spec.attributes.get(ref_attr_name)\n    if not ref_attr_spec:\n        return\n    attr_spec = prim_spec.attributes.get(attr_name)\n    if attr_spec:\n        return\n    time_codes = layer.ListTimeSamplesForPath(ref_attr_spec.path)\n    if len(time_codes) == 1:\n        return\n    center_time_codes = {idx: t for idx, t in enumerate(time_codes) if int(t) == t}\n    if not center_time_codes:\n        return\n    attr_spec = Sdf.AttributeSpec(prim_spec, attr_name, Sdf.ValueTypeNames.Vector3fArray)\n    time_code_count = len(time_codes)\n    for time_code_idx, time_code in center_time_codes.items():\n        if time_code_idx == 0:\n            time_code_prev = time_code\n            time_code_next = time_codes[time_code_idx+1]\n        elif time_code_idx == time_code_count - 1:\n            time_code_prev = time_codes[time_code_idx-1]\n            time_code_next = time_code\n        else:\n            time_code_prev = time_codes[time_code_idx-1]\n            time_code_next = time_codes[time_code_idx+1]\n        time_interval_scale = 1.0/(time_code_next - time_code_prev)\n        ref_prev = layer.QueryTimeSample(ref_attr_spec.path, time_code_prev)\n        ref_next = layer.QueryTimeSample(ref_attr_spec.path, time_code_next)\n        if not ref_prev or not ref_next:\n            continue\n        if len(ref_prev) != len(ref_next):\n            continue\n        ref_prev = np.array(ref_prev)\n        ref_next = np.array(ref_next)\n        value = ((ref_next - ref_prev) * time_interval_scale) / (time_code_inc * 2.0)\n        layer.SetTimeSample(attr_spec.path, time_code, value * multiplier)\n\ndef compute_velocities(layer, prim_spec, time_code_fps, multiplier=1.0):\n    # Time Code\n    time_code_inc = 1.0/time_code_fps\n    prim_type_name = prim_spec.typeName\n    if prim_type_name:\n        # Defined prim type name\n        attr_type_names = MOTION_ATTRIBUTE_NAMES_BY_TYPE_NAME.get(prim_type_name)\n        if not attr_type_names:\n            return\n        pos_attr_name, vel_attr_name, _ = attr_type_names\n    else:\n        # Fallback\n        pos_attr_name, vel_attr_name, _ = MOTION_ATTRIBUTE_NAMES_BY_TYPE_NAME[UsdGeom.Tokens.Mesh]\n    pos_attr_spec = prim_spec.attributes.get(pos_attr_name)\n    if not pos_attr_spec:\n        return\n    # Velocities\n    compute_time_derivative(layer,\n                            prim_spec,\n                            vel_attr_name,\n                            pos_attr_name,\n                            time_code_inc, \n                            multiplier)\n    \ndef compute_accelerations(layer, prim_spec, time_code_fps, multiplier=1.0):\n    # Time Code\n    time_code_inc = 1.0/time_code_fps\n    prim_type_name = prim_spec.typeName\n    if prim_type_name:\n        # Defined prim type name\n        attr_type_names = MOTION_ATTRIBUTE_NAMES_BY_TYPE_NAME.get(prim_type_name)\n        if not attr_type_names:\n            return\n        _, vel_attr_name, accel_attr_name = attr_type_names\n    else:\n        # Fallback\n        _, vel_attr_name, accel_attr_name = MOTION_ATTRIBUTE_NAMES_BY_TYPE_NAME[UsdGeom.Tokens.Mesh]\n    vel_attr_spec = prim_spec.attributes.get(vel_attr_name)\n    if not vel_attr_spec:\n        return\n    # Acceleration\n    compute_time_derivative(layer,\n                            prim_spec,\n                            accel_attr_name,\n                            vel_attr_name,\n                            time_code_inc, \n                            multiplier)\n\n### Run this on a layer with time samples ###\nlayer = Sdf.Layer.CreateAnonymous()\ntime_code_fps = layer.timeCodesPerSecond or 24.0\nmultiplier = 5\n\ndef traversal_kernel(path):\n    if not path.IsPrimPath():\n        return\n    prim_spec = layer.GetPrimAtPath(path)\n    compute_velocities(layer, prim_spec, time_code_fps, multiplier)\n    compute_accelerations(layer, prim_spec, time_code_fps, multiplier)\n\nwith Sdf.ChangeBlock(): \n    layer.Traverse(layer.pseudoRoot.path, traversal_kernel)\n#// ANCHOR_END: animationMotionVelocityAcceleration\n\n\n#// ANCHOR: animationStitchCmdlineTool\n...\nopenedFiles = [Sdf.Layer.FindOrOpen(fname) for fname in results.usdFiles]\n... \n# the extra computation and fail more gracefully\ntry:\n    for usdFile in openedFiles:\n        UsdUtils.StitchLayers(outLayer, usdFile)\n        outLayer.Save()\n# if something in the authoring fails, remove the output file\nexcept Exception as e:\n    print('Failed to complete stitching, removing output file %s' % results.out)\n    print(e)\n    os.remove(results.out) \n...\n#// ANCHOR_END: animationStitchCmdlineTool\n\n#// ANCHOR: animationStitchClipsUtils\nfrom pxr import Sdf, UsdUtils\n\nclip_time_code_start = 1001\nclip_time_code_end = 1003\nclip_set_name = \"cacheClip\"\nclip_prim_path = \"/prim\"\nclip_interpolate_missing = False\ntime_sample_files = [\"/cache/value_clips/time_sample.1001.usd\",\n                     \"/cache/value_clips/time_sample.1002.usd\",\n                     \"/cache/value_clips/time_sample.1003.usd\"]\ntopology_file_path = \"/cache/value_clips/topology.usd\"\nmanifest_file_path = \"/cache/value_clips/manifest.usd\"\ncache_file_path = \"/cache/cache.usd\"\n\n# We can also use:\n# topology_file_path = UsdUtils.GenerateClipTopologyName(cache_file_path)\n# Returns: \"/cache/cache.topology.usd\"\n# manifest_file_path = UsdUtils.GenerateClipManifestName(cache_file_path)\n# Returns: \"/cache/cache.manifest.usd\"\n\ntopology_layer = Sdf.Layer.CreateNew(topology_file_path)\nmanifest_layer = Sdf.Layer.CreateNew(manifest_file_path)\ncache_layer = Sdf.Layer.CreateNew(cache_file_path)\n\nUsdUtils.StitchClipsTopology(topology_layer, time_sample_files)\nUsdUtils.StitchClipsManifest(manifest_layer, topology_layer, \n                             time_sample_files, clip_prim_path)\n\nUsdUtils.StitchClips(cache_layer,\n                     time_sample_files,\n                     clip_prim_path, \n                     clip_time_code_start,\n                     clip_time_code_end,\n                     clip_interpolate_missing,\n                     clip_set_name)\ncache_layer.Save()\n\n# Result in \"/cache/cache.usd\"\n\"\"\"\n(\n    framesPerSecond = 24\n    metersPerUnit = 1\n    subLayers = [\n        @./value_clips/topology.usd@\n    ]\n    timeCodesPerSecond = 24\n)\n\ndef \"prim\" (\n    clips = {\n        dictionary cacheClip = {\n            double2[] active = [(1001, 0), (1002, 1), (1003, 2)] \n            asset[] assetPaths = [@./value_clips/time_sample.1001.usd@, @./value_clips/time_sample.1002.usd@, @./value_clips/time_sample.1003.usd@]\n            asset manifestAssetPath = @./value_clips/manifest.usd@\n            string primPath = \"/prim\"\n            double2[] times = [(1001, 1001), (1002, 1002), (1003, 1003)]\n        }\n    }\n    clipSets = [\"cacheClip\"]\n)\n{\n}\n\"\"\"\n\n## API Overview\nUsdUtils\n# Generate topology and manifest files based USD preferred naming convention.\nUsdUtils.GenerateClipTopologyName(\"/cache_file.usd\") # Returns: \"/cache_file.topology.usd\"\nUsdUtils.GenerateClipManifestName(\"/cache_file.usd\") # Returns: \"/cache_file.manifest.usd\"\n# Open layers\ntopology_layer = Sdf.Layer.CreateNew(topology_file_path)\nmanifest_layer = Sdf.Layer.CreateNew(manifest_file_path)\ncache_layer = Sdf.Layer.CreateNew(cache_file_path)\n## Create topology and manifest. This is the heavy part of creating value clips\n## as it has to open all layers.\n# Generate topology layer, this opens all the time sample layers and copies all\n# attributes that don't have time samples and relationships into the topology_layer.\nUsdUtils.StitchClipsTopology(topology_layer, time_sample_files)\n# Generate manifest layer, this opens all the time sample layers and creates a \n# hierarchy without values of all attributes that have time samples. This is the inverse\n# of the topology layer except it doesn't create values. The hierarchy is then used to\n# determine what a clip should load as animation. \nUsdUtils.StitchClipsManifest(manifest_layer, topology_layer, \n                             time_sample_files, clip_prim_path)\n# Generate cache layer, this creates the metadata that links to the above created files.\nUsdUtils.StitchClips(cache_layer,\n                     time_sample_files,\n                     clip_prim_path, \n                     clip_time_code_start,\n                     clip_time_code_end,\n                     clip_interpolate_missing,\n                     clip_set_name)\n#// ANCHOR_END: animationStitchClipsUtils\n\n\n#// ANCHOR: animationStitchClipsAPI\nfrom pxr import Sdf, Usd, UsdUtils\n\ntime_sample_files = [\"/cache/value_clips/time_sample.1001.usd\",\n                     \"/cache/value_clips/time_sample.1002.usd\",\n                     \"/cache/value_clips/time_sample.1003.usd\"]\ntime_sample_asset_paths = Sdf.AssetPathArray(time_sample_files)\ntopology_file_path = \"/cache/value_clips/topology.usd\"\nmanifest_file_path = \"/cache/value_clips/manifest.usd\"\ncache_file_path = \"/cache/cache.usd\"\n\ntopology_layer = Sdf.Layer.CreateNew(topology_file_path)\nmanifest_layer = Sdf.Layer.CreateNew(manifest_file_path)\ncache_layer = Sdf.Layer.CreateNew(cache_file_path)\n\nUsdUtils.StitchClipsTopology(topology_layer, time_sample_files)\nUsdUtils.StitchClipsManifest(manifest_layer, topology_layer, \n                             time_sample_files, clip_prim_path)\n\nclip_set_name = \"cacheClip\"\nclip_prim_path = \"/prim\"\nclip_interpolate_missing = False\n\n# For simplicity in this example we already know where the asset roots are.\n# If you need to check where they are, you can traverse the topology layer,\n# as it contains the full hierarchy of the per frame files.\nprim = stage.DefinePrim(\"/valueClippedPrim\", \"Xform\")\n# The clips API is a small wrapper around setting metadata fields. \nclips_API = Usd.ClipsAPI(prim)\n# Most function signatures work via the following args:\n# clips_API.<method>(<methodArg>, <clipSetName>)\n# We'll only be looking at non-template value clips related methods here.\n## We have Get<MethodName>/Set<MethodName> for all metadata keys:\n# clips_API.Get/SetClipPrimPath \n# clips_API.Get/SetClipAssetPaths\n# clips_API.Get/SetClipManifestAssetPath\n# clips_API.Get/SetClipActive\n# clips_API.Get/SetClipTimes \n# clips_API.Get/SetInterpolateMissingClipValues\n## To get/set the whole clips metadata dict, we can run:\n# clips_API.Get/SetClips()\n## To get/set what clips are active:\n# clips_API.Get/SetClipSets\n\n## Convenience methods for generating a manifest based on the\n# clips set by clips_API.SetClipAssetPaths\n# clips_API.GenerateClipManifest\n## Or from a user specified list. This is similar to UsdUtils.StitchClipsManifest()\n# clips_API.GenerateClipManifestFromLayers\n\n## Get the resolved asset paths in 'assetPaths' metadata.\n# clips_API.ComputeClipAssetPaths\n\nprim = stage.DefinePrim(\"/valueClippedPrim\", \"Xform\")\nclips_API = Usd.ClipsAPI(prim)\nclips_API.SetClipPrimPath(clip_prim_path, clip_set_name)\nclips_API.SetClipAssetPaths(time_sample_asset_paths, clip_set_name)\nclips_API.SetClipActive([(1001, 0), (1002, 1), (1003, 2)], clip_set_name)\nclips_API.SetClipTimes([(1001, 1001), (1002, 1001), (1003, 1001)], clip_set_name)\nclips_API.SetInterpolateMissingClipValues(clip_interpolate_missing, clip_set_name)\n# We can also print all clip metadata\nprint(clips_API.GetClips())\n# Enable the clip\nclip_sets_active = Sdf.StringListOp.CreateExplicit([clip_set_name])\nclips_API.SetClipSets(clip_sets_active)\n#Returns:\n\"\"\"\n{'cacheClip': \n    {\n        'primPath': '/prim',\n        'interpolateMissingClipValues': False, \n        'active': Vt.Vec2dArray(3, (Gf.Vec2d(1001.0, 0.0), Gf.Vec2d(1002.0, 1.0), Gf.Vec2d(1003.0, 2.0))),\n        'assetPaths': Sdf.AssetPathArray(3, (Sdf.AssetPath('/cache/value_clips/time_sample.1001.usd'),\n                                            Sdf.AssetPath('/cache/value_clips/time_sample.1002.usd'),\n                                            Sdf.AssetPath('/cache/value_clips/time_sample.1003.usd'))),\n        'times': Vt.Vec2dArray(3, (Gf.Vec2d(1001.0, 1001.0), Gf.Vec2d(1002.0, 1001.0), Gf.Vec2d(1003.0, 1001.0)))\n    }\n}\n\"\"\"\n#// ANCHOR_END: animationStitchClipsAPI\n\n\n#// ANCHOR: schemasOverview\n### Typed Schemas ###\n# From type name\nprim_type_name = prim.GetTypeName()\nprim_typed_schema = Usd.SchemaRegistry.GetTypeFromName(prim_type_name).pythonClass(prim)\n# From prim type info\nprim_typed_schema = prim.GetPrimTypeInfo().GetSchemaType().pythonClass(prim)\n\n### API Schemas ###\n# Non-Applied API Schemas\nnon_applied_api_schema = Usd.ModelAPI(prim)\n# Applied API Schemas\napplied_api_schema = UsdGeom.MotionAPI.Apply(prim)\n#// ANCHOR_END: schemasOverview\n\n#// ANCHOR: schemasTyped\n###### Typed Schemas ######\n### High Level ###\n# Has: 'IsA',\n# Get: 'GetTypeName'\n# Set: 'SetTypeName'\n# Clear: 'ClearTypeName'\nfrom pxr import Sdf, Usd, UsdGeom\nstage = Usd.Stage.CreateInMemory()\n\n# Define prim via stage\nprim_path = Sdf.Path(\"/bicycleA\")\nprim = stage.DefinePrim(prim_path, \"Cube\")\n# Define prim via typed schema\nprim_path = Sdf.Path(\"/bicycleB\")\nprim_typed_schema = UsdGeom.Cube.Define(stage, prim_path)\n# Returns the schema class object, so we have to get the prim\nprim = prim_typed_schema.GetPrim()\n# Since the \"Cube\" schema is a subclass of the\n# non.concrete typed UsdGeom.Boundable schema, we can check:\nprint(prim.IsA(UsdGeom.Cube)) # Returns: True\nprint(prim.IsA(UsdGeom.Boundable)) # Returns: True\n# To remove the type, we can call:\n# prim.ClearTypeName()\n# To access the schema class methods, we give our prim to the \n# class constructor:\nprim_typed_schema = UsdGeom.Cube(prim)\n# The typed Cube schema for example has a Get/Set method for the schema's size attribute.\nprim_typed_schema.GetSizeAttr().Set(5)\n# Or we let Usd gives us the Python class\nprim_typed_schema = prim.GetPrimTypeInfo().GetSchemaType().pythonClass(prim)\nprim_typed_schema.GetSizeAttr().Set(10)\n# Or we get it from the type name\nprim_typed_schema = Usd.SchemaRegistry.GetTypeFromName(prim.GetTypeName()).pythonClass(prim)\n\n### Low Level ###\n# To set typed schemas via the low level API, we just \n# need to set the PrimSpec.typeName = \"<SchemaName>\"\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/bicycle\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.typeName = \"Cube\"\n#// ANCHOR_END: schemasTyped\n\n\n#// ANCHOR: schemasAPI\n###### API Schemas ######\n### High Level ###\n# Has: 'HasAPI', 'CanApplyAPI'\n# Get: 'GetAppliedSchemas'\n# Set: 'AddAppliedSchema', 'ApplyAPI'\n# Clear: 'RemoveAppliedSchema', 'RemoveAPI'\nfrom pxr import Sdf, Usd, UsdGeom\nstage = Usd.Stage.CreateInMemory()\n\n### Applied Schemas ###\n# Define prim via stage\nprim_path = Sdf.Path(\"/bicycleA\")\nprim = stage.DefinePrim(prim_path, \"Cube\")\n# Check if it can be applied\nprint(UsdGeom.MotionAPI.CanApply(prim)) # Returns True\n# Apply API schema (in active layer),\nprim.ApplyAPI(\"GeomModelAPI\") # Returns: True, older USD versions: prim.ApplyAPI(\"UsdGeomModelAPI\")\n# Add applied schema\n# This does not check if the schema actually exists, \n# you have to use this for codeless schemas.\nprim.AddAppliedSchema(\"SkelBindingAPI\") # Returns: True #\n# Apply and get the schema class (preferred usage)\napplied_api_schema = UsdGeom.MotionAPI.Apply(prim)\n# Remove applied schema (in active layer)\n# prim.RemoveAppliedSchema(\"SkelBindingAPI\")\n# prim.RemoveAPI(\"GeomModelAPI\")\n# For multi-apply schemas, we can feed in our custom name,\n# for example for collections it drives the collection name.\nprim.ApplyAPI(\"UsdCollectionAPI\", \"myCoolCollectionName\")\napplied_multi_api_schema = Usd.CollectionAPI.Apply(prim, \"myCoolCollectionName\")\n### Non-Applied Schemas ###\n# Non-Applied schemas do not have an `Apply` method\n# (who would have guessed that?)\nnon_applied_api_schema = Usd.ModelAPI(prim)\n\n### Low Level ###\n# To set applied API schemas via the low level API, we just \n# need to set the `apiSchemas` key to a Token Listeditable Op.\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/bicycle\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nschemas = Sdf.TokenListOp.Create(\n    prependedItems=[\"SkelBindingAPI\", \"UsdGeomModelAPI\"]\n)\nprim_spec.SetInfo(\"apiSchemas\", schemas)\n# We don't have nice access the the schema class as in the high level API\n#// ANCHOR_END: schemasAPI\n\n\n#// ANCHOR: schemasPluginRegistry\nfrom pxr import Plug, Tf, Usd\nregistry = Plug.Registry()\nprint(\">>>>>\", \"Typed Schemas\")\nfor type_name in registry.GetAllDerivedTypes(Usd.Typed):\n    print(type_name)\nprint(\">>>>>\", \"API Schemas\")\nfor type_name in registry.GetAllDerivedTypes(Usd.APISchemaBase):\n    print(type_name)\n\n# For example to lookup where the \"Cube\" type is registered from,\n# we can run:\nprint(\">>>>>\", \"Cube Schema Plugin Source\")\nplugin = registry.GetPluginForType(Tf.Type.FindByName(\"UsdGeomCube\"))\nprint(plugin.name)\nprint(plugin.path)\nprint(plugin.resourcePath)\nprint(plugin.metadata)\n#// ANCHOR_END: schemasPluginRegistry\n\n#// ANCHOR: schemasRegistry\nfrom pxr import Plug, Sdf, Tf, Usd\nregistry = Usd.SchemaRegistry()\n\n## Get Tf.Type registry entry (which allows us to get the Python class)\n## The result can also be used to run IsA checks for typed schemas.\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycleA\")\nprim = stage.DefinePrim(prim_path, \"Cube\")\nprint(prim.IsA(registry.GetTypeFromName(\"UsdGeomImageable\"))) # Returns: True\nprint(prim.IsA(registry.GetTypeFromName(\"UsdGeomImageable\").pythonClass)) # Returns: True\n\n\n# GetTypeFromName allows prim type names and the Tf.Type.typeName.\nprint(registry.GetTypeFromName(\"UsdGeomCube\"))      # Returns: Tf.Type(\"UsdGeomCube\")\nprint(registry.GetTypeFromName(\"Cube\"))             # Returns: Tf.Type(\"UsdGeomCube\")\n# For typed schemas we can also use:\nprint(registry.GetTypeFromSchemaTypeName(\"Imageable\")) # Returns: Tf.Type('UsdGeomImageable') -> Tf.Type.typeName gives us 'UsdGeomImageable'\nprint(registry.GetTypeFromSchemaTypeName(\"Cube\"))      # Returns: Tf.Type(\"UsdGeomCube\") -> Tf.Type.typeName gives us 'UsdGeomCube'\nprint(registry.GetSchemaTypeName(\"UsdGeomImageable\"))  # Returns: \"Imageable\"\nprint(registry.GetSchemaTypeName(\"UsdGeomCube\"))       # Returns: \"Cube\"\n# For concrete typed schemas:\nprint(registry.GetConcreteSchemaTypeName(\"UsdGeomCube\"))  # Returns: \"Cube\"\nprint(registry.GetConcreteTypeFromSchemaTypeName(\"Cube\")) # Returns: Tf.Type(\"UsdGeomCube\")\n# For API schemas:\nprint(registry.GetAPISchemaTypeName(\"UsdSkelBindingAPI\"))  # Returns: \"SkelBindingAPI\"\nprint(registry.GetAPITypeFromSchemaTypeName(\"SkelBindingAPI\")) # Returns: Tf.Type(\"UsdSkelBindingAPI\")\n#// ANCHOR_END: schemasRegistry\n\n\n#// ANCHOR: schemasRegistryToPrimDefinition\nfrom pxr import Usd\nregistry = Usd.SchemaRegistry()\n## Useful inspection lookups ##\n# Find API schemas. This uses the `Schema Type Name` syntax:\ncube_def = registry.FindConcretePrimDefinition(\"Cube\")\nprint(cube_def.GetPropertyNames())\n# Returns:\n\"\"\"\n['doubleSided', 'extent', 'orientation', 'primvars:displayColor', \n 'primvars:displayOpacity', 'purpose', 'size', 'visibility',\n 'xformOpOrder', 'proxyPrim']\n\"\"\"\nskel_bind_def = registry.FindAppliedAPIPrimDefinition(\"SkelBindingAPI\")\nprint(skel_bind_def.GetPropertyNames())\n# Returns:\n\"\"\"\n['primvars:skel:geomBindTransform', 'primvars:skel:jointIndices',\n 'primvars:skel:jointWeights', 'skel:blendShapes', 'skel:joints', \n 'skel:animationSource', 'skel:blendShapeTargets', 'skel:skeleton']\n\"\"\"\n#// ANCHOR_END: schemasRegistryToPrimDefinition\n\n#// ANCHOR: schemasKind\nfrom pxr import Plug, Sdf, Tf, Usd\n### Check schema types ###\nregistry = Usd.SchemaRegistry()\n## Typed Schemas ##\nprint(registry.IsTyped(UsdGeom.Cube))         # Returns: True\nprint(registry.IsTyped(UsdGeom.Imageable))    # Returns: True\nprint(registry.IsAbstract(UsdGeom.Imageable)) # Returns: True\nprint(registry.IsAbstract(UsdGeom.Cube))      # Returns: False\nprint(registry.IsConcrete(UsdGeom.Imageable)) # Returns: False\nprint(registry.IsConcrete(UsdGeom.Cube))      # Returns: True\n# Also works with type name strings\nprint(registry.IsTyped(\"UsdGeomImageable\"))   # Returns: True\nprint(registry.IsTyped(\"UsdGeomCube\"))        # Returns: True\n## API Schemas ##\nprint(registry.IsAppliedAPISchema(\"SkelBindingAPI\"))      # Returns: True\nprint(registry.IsMultipleApplyAPISchema(\"CollectionAPI\")) # Returns: True\n## We can also ask by schema type name\nprint(registry.GetSchemaKind(\"Cube\")) # Returns: pxr.Usd.SchemaKind.ConcreteTyped\nprint(registry.GetSchemaKind(\"Imageable\")) # Returns: pxr.Usd.SchemaKind.AbstractTyped\n#// ANCHOR_END: schemasKind\n\n\n#// ANCHOR: schemasPluginCodelessTest\nfrom pxr import Usd, Sdf\n### High Level ###\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/myCoolCustomPrim\")\nprim = stage.DefinePrim(prim_path, \"ComplexPrim\")\nprim.AddAppliedSchema(\"ParamsAPI\") # Returns: True\n# AddAppliedSchema does not check if the schema actually exists, \n# you have to use this for codeless schemas.\n### Low Level ###\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/myCoolCustomPrim\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.typeName = \"ComplexPrim\"\nschemas = Sdf.TokenListOp.Create(\n    prependedItems=[\"ParamsAPI\"]\n)\nprim_spec.SetInfo(\"apiSchemas\", schemas)\n#// ANCHOR_END: schemasPluginCodelessTest\n\n\n#// ANCHOR: schemasPluginCompiledTest\nfrom pxr import Usd, Sdf\n### High Level ###\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/myCoolCustomPrim\")\nprim = stage.DefinePrim(prim_path, \"ComplexPrim\")\nprim.AddAppliedSchema(\"ParamsAPI\") # Returns: True\n# AddAppliedSchema does not check if the schema actually exists, \n# you have to use this for codeless schemas.\n### Low Level ###\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/myCoolCustomPrim\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.typeName = \"ComplexPrim\"\nschemas = Sdf.TokenListOp.Create(\n    prependedItems=[\"ParamsAPI\"]\n)\nprim_spec.SetInfo(\"apiSchemas\", schemas)\n\n### Python Classes ###\nstage = Usd.Stage.CreateInMemory()\nprim = stage.GetPrimAtPath(\"/prim\")\nprint(prim.GetTypeName())\nprint(prim.GetPrimTypeInfo().GetSchemaType().pythonClass)\n\n# Schema Classes\nimport UsdExampleSchemas as schemas\nprint(schemas.Complex)\nprint(schemas.ParamsAPI)\nprint(schemas.Simple)\nprint(schemas.Tokens)\n# Schema Get/Set/Create methods\nschemas.Complex.CreateIntAttrAttr()\n#// ANCHOR_END: schemasPluginCompiledTest\n\n\n#// ANCHOR: metadataPlugin\nfrom pxr import Usd, Sdf\n\n# Here we test it in an example stage:\nstage = Usd.Stage.CreateInMemory()\nlayer = stage.GetEditTarget().GetLayer()\nprim = stage.DefinePrim(\"/prim\")\nprim_spec = layer.GetPrimAtPath(prim.GetPath())\n\n# To see all the globally registered fields for the metadata on prim specs:\nprint(Sdf.PrimSpec.GetMetaDataInfoKeys(prim_spec))\n\n# Float field\nmetadata_name = \"usdSurvivalGuideFloat\"\nprint(prim.GetMetadata(metadata_name)) # Returns: None\nprint(prim_spec.GetFallbackForInfo(metadata_name)) # Returns: 5\nprim.SetMetadata(metadata_name, 10)\nprint(prim.GetMetadata(metadata_name)) # Returns: 10\n# String List Editable Op\nmetadata_name = \"usdSurvivalGuideAssetDependencies\"\nstring_list_op = Sdf.StringListOp.Create(appendedItems=[\"motor.usd\", \"tire.usd\"])\nprint(prim.GetMetadata(metadata_name))\nprim.SetMetadata(metadata_name, string_list_op)\nprint(prim.GetMetadata(metadata_name))\n#// ANCHOR_END: metadataPlugin\n\n\n#// ANCHOR: propertyOverview\n# Methods & Attributes of interest:\n# 'IsDefined', 'IsAuthored'\n# 'FlattenTo'\n# 'GetPropertyStack'\nfrom pxr import Usd, Sdf\n### High Level ###\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Cube\")\n# Check if the attribute defined\nattr = prim.CreateAttribute(\"height\", Sdf.ValueTypeNames.Double)\nprint(attr.IsDefined()) # Returns: True\nattr = prim.GetAttribute(\"someRandomName\")\nprint(attr.IsDefined())\nif not attr:\n    prim.CreateAttribute(\"someRandomName\", Sdf.ValueTypeNames.String)\n# Check if the attribute has any written values in any layer\nprint(attr.IsAuthored()) # Returns: True\nattr.Set(\"debugString\")\n# Flatten the attribute to another prim (with optionally a different name)\n# This is quite usefull when you need to copy a specific attribute only instead\n# of a certain prim.\nprim_path = Sdf.Path(\"/box\")\nprim = stage.DefinePrim(prim_path, \"Cube\")\nattr.FlattenTo(prim, \"someNewName\")\n# Inspect the property value source layer stack.\n# Note the method signature takes a time code as an input. If you supply a default time code\n# value clips will be stripped from the result.\ntime_code = Usd.TimeCode(1001)\nprint(attr.GetPropertyStack(time_code))\n### Low Level ###\n# The low level API does not offer any \"extras\" worthy of noting.\n#// ANCHOR_END: propertyOverview\n\n#// ANCHOR: attributeInterpolation\nfrom pxr import Sdf, Usd, UsdGeom\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Xform\")\nattr = prim.CreateAttribute(\"tire:size\", Sdf.ValueTypeNames.Float)\nattr.Set(10)\nattr.SetMetadata(\"interpolation\", UsdGeom.Tokens.constant)\n\n### Low Level ###\nfrom pxr import Sdf, UsdGeom\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/bicycle\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.specifier = Sdf.SpecifierDef\nprim_spec.typeName = \"Xform\"\nattr_spec = Sdf.AttributeSpec(prim_spec, \"tire:size\", Sdf.ValueTypeNames.Double)\nattr_spec.default = 10\nattr_spec.interpolation = UsdGeom.Tokens.constant\n# Or\nattr_spec.SetInfo(\"interpolation\", UsdGeom.Tokens.constant)\n#// ANCHOR_END: attributeInterpolation\n\n#// ANCHOR: attributeDataTypeRole\nfrom pxr import Gf, Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Xform\")\n# When we create attributes, we have to specify the data type/role via a Sdf.ValueTypeName\nattr = prim.CreateAttribute(\"tire:size\", Sdf.ValueTypeNames.Float)\n# We can then set the attribute to a value of that type.\n# Python handles the casting to the correct precision automatically for base data types.\nattr.Set(10)\n# For attributes the `typeName` metadata specifies the data type/role.\nprint(attr.GetTypeName()) # Returns: Sdf.ValueTypeNames.Float\n# Non-base data types\nattr = prim.CreateAttribute(\"someArray\", Sdf.ValueTypeNames.Half3Array)\nattr.Set([Gf.Vec3h()] * 3)\nattr = prim.CreateAttribute(\"someAssetPathArray\", Sdf.ValueTypeNames.AssetArray)\nattr.Set(Sdf.AssetPathArray([\"testA.usd\", \"testB.usd\"]))\n\n### Low Level ###\nfrom pxr import Gf, Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/bicycle\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.specifier = Sdf.SpecifierDef\nprim_spec.typeName = \"Xform\"\nattr_spec = Sdf.AttributeSpec(prim_spec, \"tire:size\", Sdf.ValueTypeNames.Double)\n# We can then set the attribute to a value of that type.\n# Python handles the casting to the correct precision automatically for base data types.\nattr_spec.default = 10\n# For attributes the `typeName` metadata specifies the data type/role.\nprint(attr_spec.typeName) # Returns: Sdf.ValueTypeNames.Float\n# Non-base data types\nattr_spec = Sdf.AttributeSpec(prim_spec, \"someArray\", Sdf.ValueTypeNames.Half3Array)\nattr_spec.default = ([Gf.Vec3h()] * 3)\nattr_spec = Sdf.AttributeSpec(prim_spec, \"someAssetPathArray\", Sdf.ValueTypeNames.AssetArray)\nattr_spec.default = Sdf.AssetPathArray([\"testA.usd\", \"testB.usd\"])\n# Creating an attribute spec with the same data type as an existing attribute (spec)\n# is as easy as passing in the type name from the existing attribute (spec)\nsame_type_attr_spec = Sdf.AttributeSpec(prim_spec, \"tire:radius\", attr.GetTypeName())\n# Or\nsame_type_attr_spec = Sdf.AttributeSpec(prim_spec, \"tire:radius\", attr_spec.typeName)\n#// ANCHOR_END: attributeDataTypeRole\n\n\n#// ANCHOR: animationDefaultTimeSampleBlock\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Cube\")\nsize_attr = prim.GetAttribute(\"size\")\n## Set default value\ntime_code = Usd.TimeCode.Default()\nsize_attr.Set(10, time_code)\n# Or:\nsize_attr.Set(10) # The default is to set `default` (non-per-frame) data.\n## Set per frame value\nfor frame in range(1001, 1005):\n    time_code = Usd.TimeCode(frame)\n    size_attr.Set(frame, time_code)\n# Or\n# As with Sdf.Path implicit casting from strings in a lot of places in the USD API,\n# the time code is implicitly casted from a Python float. \n# It is recommended to do the above, to be more future proof of \n# potentially encoding time unit based samples.\nfor frame in range(1001, 1005):\n    size_attr.Set(frame, frame)\n## Block the value. This makes the attribute look to USD as if no value was written.\n# For attributes from schemas with default values, this will make it fallback to the default value.\nheight_attr = prim.CreateAttribute(\"height\", Sdf.ValueTypeNames.Float)\nheight_attr.Set(Sdf.ValueBlock())\n#// ANCHOR_END: animationDefaultTimeSampleBlock\n\n\n#// ANCHOR: attributeReauthor\nfrom pxr import Sdf, Usd\n# Spawn reference data\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/bicycle\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.specifier = Sdf.SpecifierDef\nprim_spec.typeName = \"Cube\"\nattr_spec = Sdf.AttributeSpec(prim_spec, \"size\", Sdf.ValueTypeNames.Double)\nfor frame in range(1001, 1010):\n    value = float(frame - 1001)\n    layer.SetTimeSample(attr_spec.path, frame, value)\n# Reference data\nstage = Usd.Stage.CreateInMemory()\nref = Sdf.Reference(layer.identifier, \"/bicycle\")\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path)\nref_api = prim.GetReferences()\nref_api.AddReference(ref)\n\n# Now if we try to read and write the data at the same time,\n# we overwrite the (layer composition) value source. In non USD speak:\n# We change the layer the data is coming from. Therefore we won't see\n# the original data after setting the first time sample.\nsize_attr = prim.GetAttribute(\"size\")\nfor time_sample in size_attr.GetTimeSamples():\n    size_attr_value = size_attr.Get(time_sample)\n    print(time_sample, size_attr_value)\n    size_attr.Set(size_attr_value, time_sample)\n# Prints:\n\"\"\"\n1001.0 0.0\n1002.0 0.0\n1003.0 0.0\n1004.0 0.0\n1005.0 0.0\n1006.0 0.0\n1007.0 0.0\n1008.0 0.0\n1009.0 0.0\n\"\"\"\n\n# Let's undo the previous edit.\nprim.RemoveProperty(\"size\") # Removes the local layer attribute spec\n# Collect data first ()\ndata = {}\nsize_attr = prim.GetAttribute(\"size\")\nfor time_sample in size_attr.GetTimeSamples():\n    size_attr_value = size_attr.Get(time_sample)\n    print(time_sample, size_attr_value)\n    data[time_sample] = size_attr_value\n# Prints:\n\"\"\"\n1001.0 0.0\n1002.0 1.0\n1003.0 2.0\n1004.0 3.0\n1005.0 4.0\n1006.0 5.0\n1007.0 6.0\n1008.0 7.0\n1009.0 8.0\n\"\"\"\n# Then write it\nfor time_sample, value in data.items():\n    size_attr_value = size_attr.Get(time_sample)\n    size_attr.Set(value + 10, time_sample)\n#// ANCHOR_END: attributeReauthor\n\n\n#// ANCHOR: attributeReauthorPerLayer\nfrom pxr import Sdf, Usd\n# Spawn example data, this would be a file on disk\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/bicycle\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.specifier = Sdf.SpecifierDef\nprim_spec.typeName = \"Cube\"\nattr_spec = Sdf.AttributeSpec(prim_spec, \"size\", Sdf.ValueTypeNames.Double)\nfor frame in range(1001, 1010):\n    value = float(frame - 1001)\n    layer.SetTimeSample(attr_spec.path, frame, value)\n\n# Edit content\nlayer_identifiers = [layer.identifier]\nfor layer_identifier in layer_identifiers:\n    prim_path = Sdf.Path(\"/bicycle\")\n    ### High Level ###\n    stage = Usd.Stage.Open(layer_identifier)\n    prim = stage.GetPrimAtPath(prim_path)\n    size_attr = prim.GetAttribute(\"size\")\n    for frame in size_attr.GetTimeSamples():\n        size_attr_value = size_attr.Get(frame)\n        # .Set() takes args in the .Set(<value>, <frame>) format\n        size_attr.Set(size_attr_value + 125, frame)\n    ### Low Level ###\n    # Note that this edits the same layer as the stage above.\n    layer = Sdf.Layer.FindOrOpen(layer_identifier)\n    prim_spec = layer.GetPrimAtPath(prim_path)\n    attr_spec = prim_spec.attributes[\"size\"]\n    for frame in layer.ListTimeSamplesForPath(attr_spec.path):\n        value = layer.QueryTimeSample(attr_spec.path, frame)\n        layer.SetTimeSample(attr_spec.path, frame, value + 125)\n#// ANCHOR_END: attributeReauthorPerLayer\n\n\n#// ANCHOR: attributeReauthorTimeSampleToStatic\nfrom pxr import Sdf, Usd\n# Spawn example data, this would be a file on disk\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/bicycle\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.specifier = Sdf.SpecifierDef\nprim_spec.typeName = \"Cube\"\nattr_spec = Sdf.AttributeSpec(prim_spec, \"size\", Sdf.ValueTypeNames.Double)\nfor frame in range(1001, 1010):\n    value = float(frame - 1001)\n    layer.SetTimeSample(attr_spec.path, frame, value)\n# Reference data\nstage = Usd.Stage.CreateInMemory()\nref = Sdf.Reference(layer.identifier, \"/bicycle\")\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path)\nref_api = prim.GetReferences()\nref_api.AddReference(ref)\n\n# Freeze content\nfreeze_frame = 1001\nattrs = []\nfor prim in stage.Traverse():\n    ### High Level ###\n    for attr in prim.GetAuthoredAttributes():      \n        # attr.Set(attr.Get(freeze_frame))\n        ### Low Level ###\n        attrs.append(attr)\n\n### Low Level ###\nactive_layer = stage.GetEditTarget().GetLayer()\nwith Sdf.ChangeBlock():\n    for attr in attrs:\n        attr_spec =  active_layer.GetAttributeAtPath(attr.GetPath())\n        if not attr_spec:\n            prim_path = attr.GetPrim().GetPath()\n            prim_spec = active_layer.GetPrimAtPath(prim_path)\n            if not prim_spec:\n                prim_spec = Sdf.CreatePrimInLayer(active_layer, prim_path)\n            attr_spec = Sdf.AttributeSpec(prim_spec, attr.GetName(),attr.GetTypeName())\n        attr_spec.default = attr.Get(freeze_frame)\n#// ANCHOR_END: attributeReauthorTimeSampleToStatic\n\n\n#// ANCHOR: attributePrimvarAPI\n## UsdGeom.PrimvarsAPI(prim)\n# Has: 'HasPrimvar',\n# Get: 'GetAuthoredPrimvars', 'GetPrimvar',\n#      'GetPrimvars', 'GetPrimvarsWithAuthoredValues', 'GetPrimvarsWithValues', \n# Set: 'CreatePrimvar', 'CreateIndexedPrimvar', 'CreateNonIndexedPrimvar', \n# Clear: 'RemovePrimvar', 'BlockPrimvar',\n## UsdGeom.Primvar(attribute)\n# This is the same as Usd.Attribute, but exposes extra\n# primvar related methods, mainly:\n# Has/Is: 'IsIndexed', 'IsPrimvar'\n# Get: 'GetPrimvarName', 'GetIndicesAttr', 'GetIndices'\n# Set: 'CreateIndicesAttr', 'ComputeFlattened'\n# Remove: 'BlockIndices'\nfrom pxr import Sdf, Usd, UsdGeom, Vt\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Cube\")\nsize_attr = prim.GetAttribute(\"size\")\n# Manually define primvar\nattr = prim.CreateAttribute(\"width\", Sdf.ValueTypeNames.Float)\nprint(UsdGeom.Primvar.IsPrimvar(attr)) # Returns: False\nattr = prim.CreateAttribute(\"primvars:depth\", Sdf.ValueTypeNames.Float)\nprint(UsdGeom.Primvar.IsPrimvar(attr)) # Returns: True\n# Use primvar API\n# This returns an instance of UsdGeom.Primvar\nprimvar_api = UsdGeom.PrimvarsAPI(prim)\nprimvar = primvar_api.CreatePrimvar(\"height\", Sdf.ValueTypeNames.StringArray)\nprint(UsdGeom.Primvar.IsPrimvar(primvar))  # Returns: True\nprint(primvar.GetPrimvarName()) # Returns: \"height\"\nprimvar.Set([\"testA\", \"testB\"])\nprint(primvar.ComputeFlattened()) # Returns: [\"testA\", \"testB\"]\n# In this case flattening does nothing, because it is not indexed.\n# This will fail as it is expected to create indices on primvar creation.\nprimvar_indices = primvar.CreateIndicesAttr()\n# So let's do that\nvalues = [\"testA\", \"testB\"]\nprimvar = primvar_api.CreateIndexedPrimvar(\"height\",\n                                           Sdf.ValueTypeNames.StringArray,\n                                           Vt.StringArray(values),\n                                           Vt.IntArray([0,0,0, 1,1, 0]),\n                                           UsdGeom.Tokens.constant, \n                                           time=1001)\nprint(primvar.GetName(), primvar.GetIndicesAttr().GetName(), primvar.IsIndexed())\n# Returns: primvars:height primvars:height:indices True\nprint(primvar.ComputeFlattened())\n# Returns:\n# [\"testA\", \"testA\", \"testA\", \"testB\", \"testB\", \"testA\"]\n#// ANCHOR_END: attributePrimvarAPI\n\n\n#// ANCHOR: attributePrimvarInherited\n## UsdGeom.PrimvarsAPI(prim)\n# To detect inherited primvars, the primvars API offers helper methods:\n# 'HasPossiblyInheritedPrimvar', \n# 'FindIncrementallyInheritablePrimvars', \n# 'FindInheritablePrimvars', \n# 'FindPrimvarWithInheritance', \n# 'FindPrimvarsWithInheritance',\n\nfrom pxr import Sdf, Usd, UsdGeom\nstage = Usd.Stage.CreateInMemory()\nbicycle_prim = stage.DefinePrim(Sdf.Path(\"/set/garage/bicycle\"), \"Cube\")\ncar_prim = stage.DefinePrim(Sdf.Path(\"/set/garage/car\"), \"Cube\")\nset_prim = stage.GetPrimAtPath(\"/set\")\ngarage_prim = stage.GetPrimAtPath(\"/set/garage\")\ntractor_prim = stage.DefinePrim(Sdf.Path(\"/set/yard/tractor\"), \"Cube\")\n\"\"\"Hierarchy\n/set\n/set/garage\n/set/garage/bicycle\n/set/garage/car\n/set/yard\n/set/yard/tractor\n\"\"\"\n\n# Setup hierarchy primvars\nprimvar_api = UsdGeom.PrimvarsAPI(set_prim)\nsize_primvar = primvar_api.CreatePrimvar(\"size\", Sdf.ValueTypeNames.Float)\nsize_primvar.Set(10)\nprimvar_api = UsdGeom.PrimvarsAPI(garage_prim)\nsize_primvar = primvar_api.CreatePrimvar(\"size\", Sdf.ValueTypeNames.Float)\nsize_primvar.Set(5)\nsize_primvar = primvar_api.CreatePrimvar(\"point_scale\", Sdf.ValueTypeNames.Float)\nsize_primvar.Set(9000)\nprimvar_api = UsdGeom.PrimvarsAPI(bicycle_prim)\nsize_primvar = primvar_api.CreatePrimvar(\"size\", Sdf.ValueTypeNames.Float)\nsize_primvar.Set(2.5)\n\n# Get (non-inherited) primvars on prim\nprimvar_api = UsdGeom.PrimvarsAPI(bicycle_prim)\nprint([p.GetAttr().GetPath() for p in primvar_api.GetPrimvars()])\n# Returns:\n# [Sdf.Path('/set/garage/bicycle.primvars:displayColor'),\n#  Sdf.Path('/set/garage/bicycle.primvars:displayOpacity'),\n#  Sdf.Path('/set/garage/bicycle.primvars:size')]\n# Check for inherited primvar on prim\nprimvar_api = UsdGeom.PrimvarsAPI(bicycle_prim)\nprint(primvar_api.FindPrimvarWithInheritance(\"test\").IsDefined())\n# Returns: False\n\n# Get inherited primvar\n# This is expensive to compute, as prim prim where you call this,\n# the ancestors have to be checked.\nprimvar_api = UsdGeom.PrimvarsAPI(bicycle_prim)\nprint([p.GetAttr().GetPath() for p in primvar_api.FindInheritablePrimvars()])\n# Returns: [Sdf.Path('/set/garage/bicycle.primvars:size'), Sdf.Path('/set/garage.primvars:point_scale')]\n\n# Instead we should populate our own stack:\n# This is fast to compute!\nprint(\"----\")\nprimvars_current = []\nfor prim in stage.Traverse():\n    primvar_api = UsdGeom.PrimvarsAPI(prim)\n    primvars_current = primvar_api.FindIncrementallyInheritablePrimvars(primvars_current)\n    print(prim.GetPath(), [p.GetAttr().GetPath().pathString for p in primvars_current])\n# Returns:\n\"\"\"\n/set ['/set.primvars:size']\n/set/garage ['/set/garage.primvars:size', '/set/garage.primvars:point_scale']\n/set/garage/bicycle ['/set/garage/bicycle.primvars:size', '/set/garage.primvars:point_scale']\n/set/garage/car []\n/set/yard []\n/set/yard/traktor []\n\"\"\"\nprint(\"----\")\n# This is wrong if you might have noticed!\n# We should be seeing our '/set.primvars:size' primvar on the yard prims to!\n# If we look at the docs, we see the intended use: \n# FindIncrementallyInheritablePrimvars returns a new list if it gets re-populated.\n# So the solution is to track the lists with pre/post visits.\nprimvar_stack = [[]]\niterator = iter(Usd.PrimRange.PreAndPostVisit(stage.GetPseudoRoot()))\nfor prim in iterator:\n    primvar_api = UsdGeom.PrimvarsAPI(prim)\n    if not iterator.IsPostVisit():\n        before = hex(id(primvar_stack[-1]))\n        primvars_iter = primvar_api.FindIncrementallyInheritablePrimvars(primvar_stack[-1])\n        primvar_stack.append(primvars_iter)\n        print(before, hex(id(primvars_iter)), prim.GetPath(), [p.GetAttr().GetPath().pathString for p in primvars_iter], len(primvar_stack))\n    else:\n        primvar_stack.pop(-1)\n# This also doesn't work as it seems to clear the memory address for some reason (Or do I have a logic error?)\n# Let's write it ourselves:\nprimvar_stack = [{}]\niterator = iter(Usd.PrimRange.PreAndPostVisit(stage.GetPseudoRoot()))\nfor prim in iterator:\n    primvar_api = UsdGeom.PrimvarsAPI(prim)\n    if not iterator.IsPostVisit():\n        before_hash = hex(id(primvar_stack[-1]))\n        parent_primvars = primvar_stack[-1]\n        authored_primvars = {p.GetPrimvarName(): p for p in primvar_api.GetPrimvarsWithAuthoredValues()} \n        if authored_primvars and parent_primvars:\n            combined_primvars = {name: p for name, p in parent_primvars.items()}\n            combined_primvars.update(authored_primvars)\n            primvar_stack.append(combined_primvars)\n        elif authored_primvars:\n            primvar_stack.append(authored_primvars)\n        else:\n            primvar_stack.append(parent_primvars)\n        after_hash = hex(id(primvar_stack[-1]))\n        print(before_hash, after_hash, prim.GetPath(), [p.GetAttr().GetPath().pathString for p in primvar_stack[-1].values()], len(primvar_stack))\n    else:\n        primvar_stack.pop(-1)\n# Returns:\n\"\"\" This works :)\n0x7fea12b349c0 0x7fea12b349c0 / [] 2\n0x7fea12b349c0 0x7fea12b349c0 /HoudiniLayerInfo [] 3\n0x7fea12b349c0 0x7fea12bfe980 /set ['/set.primvars:size'] 3\n0x7fea12bfe980 0x7fea12a89600 /set/garage ['/set/garage.primvars:size', '/set/garage.primvars:point_scale'] 4\n0x7fea12a89600 0x7fea367b87c0 /set/garage/bicycle ['/set/garage/bicycle.primvars:size', '/set/garage.primvars:point_scale'] 5\n0x7fea12a89600 0x7fea12a89600 /set/garage/car ['/set/garage.primvars:size', '/set/garage.primvars:point_scale'] 5\n0x7fea12bfe980 0x7fea12bfe980 /set/yard ['/set.primvars:size'] 4\n0x7fea12bfe980 0x7fea12bfe980 /set/yard/tractor ['/set.primvars:size'] 5\n\"\"\"\n#// ANCHOR_END: attributePrimvarInherited\n\n\n#// ANCHOR: attributePrimvarIndexed\nfrom pxr import Sdf, Usd, UsdGeom, Vt\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Cube\")\n# So let's do that\nvalue_set = [\"testA\", \"testB\"]\nvalue_indices = [0,0,0, 1,1, 0]\nprimvar = primvar_api.CreateIndexedPrimvar(\"height\",\n                                           Sdf.ValueTypeNames.StringArray,\n                                           Vt.StringArray(value_set),\n                                           Vt.IntArray(value_indices),\n                                           UsdGeom.Tokens.constant, \n                                           time=1001)\nprint(primvar.ComputeFlattened())\n# Returns:\n# [\"testA\", \"testA\", \"testA\", \"testB\", \"testB\", \"testA\"]\n#// ANCHOR_END: attributePrimvarIndexed\n\n\n#// ANCHOR: attributeConnections\nfrom pxr import Sdf, Usd\n### High Level ###\n# Has: 'HasAuthoredConnections', \n# Get: 'GetConnections',\n# Set: 'AddConnection', 'SetConnections'\n# Clear:  'RemoveConnection', 'ClearConnections'\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/box\")\nprim = stage.DefinePrim(prim_path, \"Cube\")\nwidth_attr = prim.CreateAttribute(\"width\", Sdf.ValueTypeNames.Double)\nheight_attr = prim.CreateAttribute(\"height\", Sdf.ValueTypeNames.Double)\ndepth_attr = prim.CreateAttribute(\"depth\", Sdf.ValueTypeNames.Double)\nwidth_attr.AddConnection(height_attr.GetPath(), Usd.ListPositionBackOfAppendList)\nwidth_attr.AddConnection(depth_attr.GetPath(), Usd.ListPositionFrontOfAppendList)\nprint(width_attr.GetConnections())\n# Returns: [Sdf.Path('/box.depth'), Sdf.Path('/box.height')]\nwidth_attr.RemoveConnection(depth_attr.GetPath())\nprint(width_attr.GetConnections())\n# Returns: [Sdf.Path('/box.height')]\n### Low Level ###\n# Connections are managed via the `connectionPathList` AttributeSpec attribute.\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/box\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.typeName = \"Cube\"\nwidth_attr_spec = Sdf.AttributeSpec(prim_spec, \"width\", Sdf.ValueTypeNames.Double)\nheight_attr_spec = Sdf.AttributeSpec(prim_spec, \"height\", Sdf.ValueTypeNames.Double)\ndepth_attr_spec = Sdf.AttributeSpec(prim_spec, \"depth\", Sdf.ValueTypeNames.Double)\nwidth_attr_spec.connectionPathList.Append(height_attr_spec.path)\nwidth_attr_spec.connectionPathList.Append(depth_attr_spec.path)\nprint(width_attr_spec.connectionPathList.GetAddedOrExplicitItems())\n# Returns: (Sdf.Path('/box.height'), Sdf.Path('/box.depth'))\nwidth_attr_spec.connectionPathList.Erase(depth_attr_spec.path)\nprint(width_attr_spec.connectionPathList.GetAddedOrExplicitItems())\n# Returns: (Sdf.Path('/box.height'),)\n## This won't work as the connectionPathList attribute can only be edited in place\npath_list = Sdf.PathListOp.Create(appendedItems=[height_attr_spec.path])\n# width_attr_spec.connectionPathList = path_list\n#// ANCHOR_END: attributeConnections\n\n\n#// ANCHOR: attributePurpose\n### High Level ###\nfrom pxr import Sdf, Usd, UsdGeom\nstage = Usd.Stage.CreateInMemory()\ncube_prim = stage.DefinePrim(Sdf.Path(\"/bicycle/RENDER/cube\"), \"Cube\")\nrender_prim = cube_prim.GetParent()\nrender_prim.SetTypeName(\"Xform\")\nUsdGeom.Imageable(render_prim).GetPurposeAttr().Set(UsdGeom.Tokens.render)\nsphere_prim = stage.DefinePrim(Sdf.Path(\"/bicycle/PROXY/sphere\"), \"Sphere\")\nproxy_prim = sphere_prim.GetParent()\nproxy_prim.SetTypeName(\"Xform\")\nUsdGeom.Imageable(proxy_prim).GetPurposeAttr().Set(UsdGeom.Tokens.proxy)\n# We can also query the inherited purpose:\nimageable_api = UsdGeom.Imageable(cube_prim)\nprint(imageable_api.ComputePurpose()) # Returns: 'render'\n\n### Low Level ###\nfrom pxr import Sdf, UsdGeom\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/bicycle\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.specifier = Sdf.SpecifierDef\nprim_spec.typeName = \"Cube\"\nattr_spec = Sdf.AttributeSpec(prim_spec, \"purpose\", Sdf.ValueTypeNames.Token)\nattr_spec.default = UsdGeom.Tokens.render\n#// ANCHOR_END: attributePurpose\n\n#// ANCHOR: attributeVisibility\n### High Level ###\n# UsdGeom.Imageable()\n# Get: 'ComputeVisibility'\n# Set: 'MakeVisible', 'MakeInvisible'\nfrom pxr import Sdf, Usd, UsdGeom\nstage = Usd.Stage.CreateInMemory()\ncube_prim = stage.DefinePrim(Sdf.Path(\"/set/yard/bicycle\"), \"Cube\")\nsphere_prim = stage.DefinePrim(Sdf.Path(\"/set/garage/bicycle\"), \"Sphere\")\nset_prim = cube_prim.GetParent().GetParent()\nset_prim.SetTypeName(\"Xform\")\ncube_prim.GetParent().SetTypeName(\"Xform\")\nsphere_prim.GetParent().SetTypeName(\"Xform\")\nUsdGeom.Imageable(set_prim).GetVisibilityAttr().Set(UsdGeom.Tokens.invisible)\n# We can also query the inherited visibility:\n# ComputeEffectiveVisibility -> This handles per purpose visibility\nimageable_api = UsdGeom.Imageable(cube_prim)\nprint(imageable_api.ComputeVisibility()) # Returns: 'invisible'\n# Make only the cube visible. Notice how this automatically sparsely\n# selects only the needed parent prims (garage) and makes them invisible.\n# How cool is that!\nimageable_api.MakeVisible()\n\n### Low Level ###\nfrom pxr import Sdf, UsdGeom\nlayer = Sdf.Layer.CreateAnonymous()\nbicycle_prim_path = Sdf.Path(\"/set/bicycle\")\nbicycle_prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nbicycle_prim_spec.specifier = Sdf.SpecifierDef\nbicycle_prim_spec.typeName = \"Cube\"\nbicycle_vis_attr_spec = Sdf.AttributeSpec(prim_spec, \"visibility\", Sdf.ValueTypeNames.Token)\nbicycle_vis_attr_spec.default = UsdGeom.Tokens.inherited\n#// ANCHOR_END: attributeVisibility\n\n\n#// ANCHOR: attributeExtent\n### High Level ###\n# UsdGeom.Boundable()\n# Get: 'GetExtentAttr', 'CreateExtentAttr'\n# Set: 'ComputeExtent '\nfrom pxr import Sdf, Usd, UsdGeom\nstage = Usd.Stage.CreateInMemory()\ncube_prim = stage.DefinePrim(Sdf.Path(\"/bicycle/cube\"), \"Cube\")\nbicycle_prim = cube_prim.GetParent()\nbicycle_prim.SetTypeName(\"Xform\")\n# If we change the size, we have to re-compute the bounds\ncube_prim.GetAttribute(\"size\").Set(10)\nboundable_api = UsdGeom.Boundable(cube_prim)\nprint(boundable_api.GetExtentAttr().Get()) # Returns:  [(-1, -1, -1), (1, 1, 1)]\nextent = boundable_api.ComputeExtent(Usd.TimeCode.Default())\nboundable_api.GetExtentAttr().Set(extent)\nprint(boundable_api.GetExtentAttr().Get()) # Returns: [(-5, -5, -5), (5, 5, 5)]\n# Author extentsHint\n# The bbox cache has to be specified with what frame and purpose to query\nbbox_cache = UsdGeom.BBoxCache(1001, [UsdGeom.Tokens.default_, UsdGeom.Tokens.render])\nmodel_api = UsdGeom.ModelAPI(bicycle_prim)\nextentsHint = model_api.ComputeExtentsHint(bbox_cache)\nmodel_api.SetExtentsHint(extentsHint)\n# Or model_api.SetExtentsHint(extentsHint, <frame>)\n### Low Level ###\nfrom pxr import Sdf, UsdGeom, Vt\nlayer = Sdf.Layer.CreateAnonymous()\ncube_prim_path = Sdf.Path(\"/bicycle/cube\")\ncube_prim_spec = Sdf.CreatePrimInLayer(layer, cube_prim_path)\ncube_prim_spec.specifier = Sdf.SpecifierDef\ncube_prim_spec.typeName = \"Cube\"\nbicycle_prim_path = Sdf.Path(\"/bicycle\")\nbicycle_prim_spec = Sdf.CreatePrimInLayer(layer, cube_prim_path)\nbicycle_prim_spec.specifier = Sdf.SpecifierDef\nbicycle_prim_spec.typeName = \"Xform\"\n# The querying should be done via the high level API.\nextent_attr_spec = Sdf.AttributeSpec(cube_prim_spec, \"extent\", Sdf.ValueTypeNames.Vector3fArray)\nextent_attr_spec.default = Vt.Vec3fArray([(-1, -1, -1), (1, 1, 1)])\nsite_attr_spec = Sdf.AttributeSpec(cube_prim_spec, \"size\", Sdf.ValueTypeNames.Float)\nsite_attr_spec.default = 10\nextent_attr_spec.default = Vt.Vec3fArray([(-5, -5, -5), (5, 5, 5)])\n# Author extentsHint\nextents_hint_attr_spec = Sdf.AttributeSpec(bicycle_prim_spec, \"extentsHint\", Sdf.ValueTypeNames.Vector3fArray)\nextents_hint_attr_spec.default = Vt.Vec3fArray([(-5, -5, -5), (5, 5, 5)])\n#// ANCHOR_END: attributeExtent\n\n\n#// ANCHOR: relationshipMaterialBinding\n## UsdShade.MaterialBindingAPI(<boundable prim>)\n# This handles all the binding get and setting\n## These classes can inspect an existing binding\n# UsdShade.MaterialBindingAPI.DirectBinding()\n# UsdShade.MaterialBindingAPI.CollectionBinding()\n### High Level ###\nfrom pxr import Sdf, Usd, UsdGeom, UsdShade\nstage = Usd.Stage.CreateInMemory()\nrender_prim = stage.DefinePrim(Sdf.Path(\"/bicycle/RENDER/render\"), \"Cube\")\nmaterial_prim = stage.DefinePrim(Sdf.Path(\"/bicycle/MATERIALS/example_material\"), \"Material\")\nbicycle_prim = render_prim.GetParent().GetParent()\nbicycle_prim.SetTypeName(\"Xform\")\nrender_prim.GetParent().SetTypeName(\"Xform\")\nmaterial_prim.GetParent().SetTypeName(\"Xform\")\n# Bind materials via direct binding\nmaterial = UsdShade.Material(material_prim)\nmat_bind_api = UsdShade.MaterialBindingAPI.Apply(render_prim)\nmat_bind_api.Bind(material)\n# Unbind all\nmat_bind_api.UnbindAllBindings()\n# Bind via collection\ncollection_name = \"material_example\"\ncollection_api = Usd.CollectionAPI.Apply(bicycle_prim, collection_name)\ncollection_api.GetIncludesRel().AddTarget(material_prim.GetPath())\ncollection_api.GetExpansionRuleAttr().Set(Usd.Tokens.expandPrims)\nmat_bind_api.Bind(collection_api, material, \"material_example\")\n\n### Low Level ###\nfrom pxr import Sdf, UsdGeom\nlayer = Sdf.Layer.CreateAnonymous()\nrender_prim_spec = Sdf.CreatePrimInLayer(layer, Sdf.Path(\"/render\"))\nrender_prim_spec.specifier = Sdf.SpecifierDef\nrender_prim_spec.typeName = \"Cube\"\nmaterial_prim_spec = Sdf.CreatePrimInLayer(layer, Sdf.Path(\"/material\"))\nmaterial_prim_spec.specifier = Sdf.SpecifierDef\nmaterial_prim_spec.typeName = \"Material\"\n## Direct binding\nmaterial_bind_rel_spec = Sdf.RelationshipSpec(render_prim_spec, \"material:binding\")\nmaterial_bind_rel_spec.targetPathList.Append(Sdf.Path(\"/render\"))\n# Applied Schemas\nschemas = Sdf.TokenListOp.Create(\n    prependedItems=[\"MaterialBindingAPI\"]\n)\nrender_prim_spec.SetInfo(\"apiSchemas\", schemas)\n#// ANCHOR_END: relationshipMaterialBinding\n\n#// ANCHOR: collectionOverview\n# Usd.CollectionAPI.Apply(prim, collection_name)\n# collection_api = Usd.CollectionAPI(prim, collection_nam)\n# collection_query = collection_api.ComputeMembershipQuery()\n### High Level ###\nfrom pxr import Sdf, Usd, UsdUtils\nstage = Usd.Stage.CreateInMemory()\nbicycle_prim = stage.DefinePrim(Sdf.Path(\"/set/yard/biycle\"), \"Cube\")\ncar_prim = stage.DefinePrim(Sdf.Path(\"/set/garage/car\"), \"Sphere\")\ntractor_prim = stage.DefinePrim(Sdf.Path(\"/set/garage/tractor\"), \"Cylinder\")\nhelicopter_prim = stage.DefinePrim(Sdf.Path(\"/set/garage/helicopter\"), \"Cube\")\nboat_prim = stage.DefinePrim(Sdf.Path(\"/set/garage/boat\"), \"Cube\")\nset_prim = bicycle_prim.GetParent().GetParent()\nset_prim.SetTypeName(\"Xform\")\nbicycle_prim.GetParent().SetTypeName(\"Xform\")\ncar_prim.GetParent().SetTypeName(\"Xform\")\n# Create collection\ncollection_name = \"vehicles\"\ncollection_api = Usd.CollectionAPI.Apply(set_prim, collection_name)\ncollection_api.GetIncludesRel().AddTarget(set_prim.GetPath())\ncollection_api.GetExcludesRel().AddTarget(bicycle_prim.GetPath())\ncollection_api.GetExpansionRuleAttr().Set(Usd.Tokens.expandPrims)\nprint(Usd.CollectionAPI.GetAllCollections(set_prim)) # Returns: [Usd.CollectionAPI(Usd.Prim(</set>), 'vehicles')]\nprint(Usd.CollectionAPI.GetCollection(set_prim, \"vehicles\")) # Returns: Usd.CollectionAPI(Usd.Prim(</set>), 'vehicles')\ncollection_query = collection_api.ComputeMembershipQuery()\nprint(collection_api.ComputeIncludedPaths(collection_query, stage))\n# Returns: \n# [Sdf.Path('/set'), Sdf.Path('/set/garage'), Sdf.Path('/set/garage/boat'),\n#  Sdf.Path('/set/garage/car'), Sdf.Path('/set/garage/helicopter'),\n#  Sdf.Path('/set/garage/tractor'), Sdf.Path('/set/yard')]\n# Set it to explicit only\ncollection_api.GetExpansionRuleAttr().Set(Usd.Tokens.explicitOnly)\ncollection_query = collection_api.ComputeMembershipQuery()\nprint(collection_api.ComputeIncludedPaths(collection_query, stage))\n# Returns: [Sdf.Path('/set')]\n\n# To help speed up collection creation, USD also ships with util functions:\n# UsdUtils.AuthorCollection(<collectionName>, prim, [<includePathList>], [<excludePathList>])\ncollection_api = UsdUtils.AuthorCollection(\"two_wheels\", set_prim, [set_prim.GetPath()], [car_prim.GetPath()])\ncollection_query = collection_api.ComputeMembershipQuery()\nprint(collection_api.ComputeIncludedPaths(collection_query, stage))\n# Returns:\n# [Sdf.Path('/set'), Sdf.Path('/set/garage'), Sdf.Path('/set/yard'), Sdf.Path('/set/yard/biycle')]\n# UsdUtils.ComputeCollectionIncludesAndExcludes() gives us the possibility to author \n# collections more sparse, that the include to exclude ratio is kept at an optimal size.\n# The Python signature differs from the C++ signature:\n\"\"\"\ninclude_paths, exclude_paths = UsdUtils.ComputeCollectionIncludesAndExcludes(\n    target_paths,\n    stage,\n    minInclusionRatio = 0.75,\n    maxNumExcludesBelowInclude = 5,\n\tminIncludeExcludeCollectionSize = 3,\n    pathsToIgnore = [] # This ignores paths from computation (this is not the exclude list)\n)\t\t\n\"\"\"\ntarget_paths = [tractor_prim.GetPath(), car_prim.GetPath(), helicopter_prim.GetPrimPath()]\ninclude_paths, exclude_paths = UsdUtils.ComputeCollectionIncludesAndExcludes(target_paths,stage, minInclusionRatio=.9)\nprint(include_paths, exclude_paths)\n# Returns:\n# [Sdf.Path('/set/garage/car'), Sdf.Path('/set/garage/tractor'), Sdf.Path('/set/garage/helicopter')] []\ninclude_paths, exclude_paths = UsdUtils.ComputeCollectionIncludesAndExcludes(target_paths,stage, minInclusionRatio=.1)\nprint(include_paths, exclude_paths)\n# Returns: [Sdf.Path('/set/garage')] [Sdf.Path('/set/garage/boat')]\n# Create a collection from the result\ncollection_api = UsdUtils.AuthorCollection(\"optimized\", set_prim, include_paths, exclude_paths)\n#// ANCHOR_END: collectionOverview\n\n#// ANCHOR: relationshipOverview\n### High Level ###\n# Get: 'GetForwardedTargets', 'GetTargets',\n# Set: 'AddTarget', 'SetTargets'\n# Clear: 'RemoveTarget', 'ClearTargets'\nfrom pxr import Sdf, Usd, UsdGeom\nstage = Usd.Stage.CreateInMemory()\ncube_prim = stage.DefinePrim(Sdf.Path(\"/cube_prim\"), \"Cube\")\nsphere_prim = stage.DefinePrim(Sdf.Path(\"/sphere_prim\"), \"Sphere\")\nmyFavoriteSphere_rel = cube_prim.CreateRelationship(\"myFavoriteSphere\")\nmyFavoriteSphere_rel.AddTarget(sphere_prim.GetPath())\nprint(myFavoriteSphere_rel.GetForwardedTargets()) # Returns:[Sdf.Path('/sphere_prim')]\n# myFavoriteSphere_rel.ClearTargets()\n# We can also forward relationships to other relationships.\ncylinder_prim = stage.DefinePrim(Sdf.Path(\"/sphere_prim\"), \"Cylinder\")\nmyFavoriteSphereForward_rel = cylinder_prim.CreateRelationship(\"myFavoriteSphereForward\")\nmyFavoriteSphereForward_rel.AddTarget(myFavoriteSphere_rel.GetPath())\n# GetForwardedTargets: This gives us the final fowarded paths. We'll use this most of the time.\n# GetTargets: Gives us the paths set on the relationship, forwarded paths are not baked down.\nprint(myFavoriteSphereForward_rel.GetForwardedTargets()) # Returns:[Sdf.Path('/sphere_prim')]\nprint(myFavoriteSphereForward_rel.GetTargets()) # Returns: [Sdf.Path('/cube_prim.myFavoriteSphere')]\n\n### Low Level ###\nfrom pxr import Sdf, UsdGeom\nlayer = Sdf.Layer.CreateAnonymous()\ncube_prim_spec = Sdf.CreatePrimInLayer(layer, Sdf.Path(\"/cube_prim\"))\ncube_prim_spec.specifier = Sdf.SpecifierDef\ncube_prim_spec.typeName = \"Cube\"\nsphere_prim_spec = Sdf.CreatePrimInLayer(layer, Sdf.Path(\"/sphere_prim\"))\nsphere_prim_spec.specifier = Sdf.SpecifierDef\nsphere_prim_spec.typeName = \"Cube\"\nrel_spec = Sdf.RelationshipSpec(cube_prim_spec, \"proxyPrim\")\nrel_spec.targetPathList.Append(sphere_prim_spec.path)\n# The targetPathList is a list editable Sdf.PathListOp.\n# Forwarded rels can only be calculated via the high level API.\n#// ANCHOR_END: relationshipOverview\n\n\n#// ANCHOR: relationshipProxyPrim\n### High Level ###\nfrom pxr import Sdf, Usd, UsdGeom\nstage = Usd.Stage.CreateInMemory()\nrender_prim = stage.DefinePrim(Sdf.Path(\"/bicycle/RENDER/render\"), \"Cube\")\nproxy_prim = stage.DefinePrim(Sdf.Path(\"/bicycle/PROXY/proxy\"), \"Sphere\")\nbicycle_prim = render_prim.GetParent().GetParent()\nbicycle_prim.SetTypeName(\"Xform\")\nrender_prim.GetParent().SetTypeName(\"Xform\")\nproxy_prim.GetParent().SetTypeName(\"Xform\")\nimageable_api = UsdGeom.Imageable(render_prim)\nimageable_api.SetProxyPrim(proxy_prim)\n# Query the proxy prim\nprint(imageable_api.ComputeProxyPrim()) # Returns: None\n# Why does this not work? We have to set the purpose!\nUsdGeom.Imageable(render_prim).GetPurposeAttr().Set(UsdGeom.Tokens.render)\nUsdGeom.Imageable(proxy_prim).GetPurposeAttr().Set(UsdGeom.Tokens.proxy)\nprint(imageable_api.ComputeProxyPrim()) # Returns: (Usd.Prim(</bicycle/PROXY/proxy>), Usd.Prim(</bicycle/RENDER/render>))\n\n### Low Level ###\nfrom pxr import Sdf, UsdGeom\nlayer = Sdf.Layer.CreateAnonymous()\nrender_prim_spec = Sdf.CreatePrimInLayer(layer, Sdf.Path(\"/render\"))\nrender_prim_spec.specifier = Sdf.SpecifierDef\nrender_prim_spec.typeName = \"Cube\"\nproxy_prim_spec = Sdf.CreatePrimInLayer(layer, Sdf.Path(\"/proxy\"))\nproxy_prim_spec.specifier = Sdf.SpecifierDef\nproxy_prim_spec.typeName = \"Cube\"\nproxyPrim_rel_spec = Sdf.RelationshipSpec(render_prim_spec, \"proxyPrim\")\nproxyPrim_rel_spec.targetPathList.Append(Sdf.Path(\"/proxy\"))\n#// ANCHOR_END: relationshipProxyPrim\n\n\n#// ANCHOR: collectionInvert\nfrom pxr import Sdf, Usd, UsdUtils\nstage = Usd.Stage.CreateInMemory()\n# Create hierarchy\nprim_paths = [\n    \"/set/yard/biycle\",\n    \"/set/yard/shed/shovel\",\n    \"/set/yard/shed/flower_pot\",\n    \"/set/yard/shed/lawnmower\",\n    \"/set/yard/shed/soil\",\n    \"/set/yard/shed/wood\",\n    \"/set/garage/car\",\n    \"/set/garage/tractor\",\n    \"/set/garage/helicopter\",\n    \"/set/garage/boat\",\n    \"/set/garage/key_box\",\n    \"/set/garage/key_box/red\",\n    \"/set/garage/key_box/blue\",\n    \"/set/garage/key_box/green\",\n    \"/set/people/mike\",\n    \"/set/people/charolotte\"\n]\nfor prim_path in prim_paths:\n    prim = stage.DefinePrim(prim_path, \"Cube\")\nprint(\"<< hierarchy >>\")\nfor prim in stage.Traverse():\n    print(prim.GetPath())\n    parent_prim = prim.GetParent()\n    while True:\n        if parent_prim.IsPseudoRoot():\n            break\n        parent_prim.SetTypeName(\"Xform\")\n        parent_prim = parent_prim.GetParent()\n# Returns:\n\"\"\"\n<< hierarchy >>\n/HoudiniLayerInfo\n/set\n/set/yard\n/set/yard/biycle\n/set/yard/shed\n/set/yard/shed/shovel\n/set/yard/shed/flower_pot\n/set/yard/shed/lawnmower\n/set/yard/shed/soil\n/set/yard/shed/wood\n/set/garage\n/set/garage/car\n/set/garage/tractor\n/set/garage/helicopter\n/set/garage/boat\n/set/garage/key_box\n/set/garage/key_box/red\n/set/garage/key_box/blue\n/set/garage/key_box/green\n/set/people\n/set/people/mike\n/set/people/charolotte\n\"\"\"\n# Collections\ncollection_prim = stage.DefinePrim(\"/collections\")\nstorage_include_prim_paths = [\"/set/garage/key_box\", \"/set/yard/shed\"]\nstorage_exclude_prim_paths = [\"/set/yard/shed/flower_pot\"]\ncollection_api = UsdUtils.AuthorCollection(\"storage\", collection_prim, storage_include_prim_paths, storage_exclude_prim_paths)\ncollection_query = collection_api.ComputeMembershipQuery()\nincluded_paths = collection_api.ComputeIncludedPaths(collection_query, stage)\n# print(included_paths)\n# Prune inverse:\nprint(\"<< hierarchy pruned >>\")\niterator = iter(Usd.PrimRange(stage.GetPseudoRoot()))\nfor prim in iterator:\n    if prim.IsPseudoRoot():\n        continue\n    if prim.GetPath() not in included_paths and not len(prim.GetAllChildrenNames()):\n        iterator.PruneChildren()\n        prim.SetActive(False)\n    else:    \n        print(prim.GetPath())\n# Returns:\n\"\"\"\n<< hierarchy pruned >>\n/set\n/set/yard\n/set/yard/shed\n/set/yard/shed/shovel\n/set/yard/shed/lawnmower\n/set/yard/shed/soil\n/set/yard/shed/wood\n/set/garage\n/set/garage/key_box\n/set/garage/key_box/red\n/set/garage/key_box/blue\n/set/garage/key_box/green\n/set/people\n\"\"\"\n#// ANCHOR_END: collectionInvert\n\n\n#// ANCHOR: dataTypeRoleOverview\nfrom pxr import Sdf, Vt\n##### Value Type Names - pxr.Sdf.ValueTypeNames #####\n### Looking at TexCoord2fArray as an example\nvalue_type_name = Sdf.ValueTypeNames.TexCoord2fArray\nprint(\"Value Type Name\", value_type_name) # Returns: Sdf.ValueTypeName(\"texCoord2f[]\")\n## Aliases and cpp names\nprint(\"Value Type Name Alias\", value_type_name.aliasesAsStrings)    # ['texCoord2f[]']\nprint(\"Value Type Name Cpp Type Name\", value_type_name.cppTypeName) # 'VtArray<GfVec2f>'\nprint(\"Value Type Name Role\", value_type_name.role)                 # Returns: 'TextureCoordinate'\n## Array vs Scalar (Single Value)\nprint(\"Value Type Name IsArray\", value_type_name.isArray)          # Returns: True\nprint(\"Value Type Name IsScalar\", value_type_name.isScalar)         # Returns: False\n## Convert type between Scalar <-> Array\nprint(\"Value Type Name -> Get Array Type\", value_type_name.arrayType)   # Returns: Sdf.ValueTypeName(\"texCoord2f[]\") (Same as type_name in this case)\nprint(\"Value Type Name -> Get Scalar Type\", value_type_name.scalarType) # Returns: Sdf.ValueTypeName(\"texCoord2f\")\n### Type (Actual type definiton, holds data about container format\n### like C++ type name and the Python class\nvalue_type = value_type_name.type\nprint(value_type) # Returns: Tf.Type.FindByName('VtArray<GfVec2f>')\n### Get the Python Class\ncls = value_type.pythonClass\n# Or (for base types like float, int)\ndefault_value = value_type_name.defaultValue\ncls = default_value.__class__\ninstance = cls()\n\n##### Types - pxr.Vt.Type Registry #####\nfrom pxr import Vt\n# For Python usage, the only thing of interest for data types in the Vt.Type module are the `*Array`ending classes.\n# You will only use these array types to handle the auto conversion\n# form buffer protocol arrays like numpy arrays, the rest is auto converted and you don't need\n# to worry about it. Normal Python lists do not support the buffer protocol.\nfrom array import array\nVt.Vec3hArray.FromBuffer(array(\"f\", [1,2,3]))\n# Returns:\n# Vt.Vec3hArray(1, (Gf.Vec3h(1.0, 2.0, 3.0),))\n# From Numpy\nimport numpy as np\nvt_array = Vt.Vec3hArray.FromNumpy(np.ones((10, 3)))\nVt.Vec3hArray.FromBuffer(np.ones((10, 3))) # Numpy also supports the buffer protocol.\n# Returns:\n\"\"\"\nVt.Vec3hArray(10, (Gf.Vec3h(1.0, 1.0, 1.0), Gf.Vec3h(1.0, 1.0, 1.0), Gf.Vec3h(1.0, 1.0, 1.0), Gf.Vec3h(1.0, 1.\n0, 1.0), Gf.Vec3h(1.0, 1.0, 1.0), Gf.Vec3h(1.0, 1.0, 1.0), Gf.Vec3h(1.0, 1.0, 1.0), Gf.Vec3h(1.0, 1.0, 1.0), G\nf.Vec3h(1.0, 1.0, 1.0), Gf.Vec3h(1.0, 1.0, 1.0)))\n\"\"\"\n# We can also go the other way:\nnp.array(vt_array)\n#// ANCHOR_END: dataTypeRoleOverview\n\n#// ANCHOR: tfTypeRegistry\n##### Types - pxr.Vt.Type Registry #####\n# All registered types (including other plugin types, so not limited to data types)\n# for type_def in Tf.Type.GetRoot().derivedTypes:\n#    print(type_def)\ntype_def = Tf.Type.FindByName(Sdf.ValueTypeNames.TexCoord2fArray.cppTypeName)\nprint(type_def.typeName) # Returns: VtArray<GfVec2f> # The same as value_type_name.cppTypeName\n# Root/Base/Derived Types\ntype_def.GetRoot(), type_def.baseTypes, type_def.derivedTypes\n#// ANCHOR_END: tfTypeRegistry\n\n#// ANCHOR: layerIdentifier\n# Add code to modify the stage.\n# Use drop down menu to select examples.\n#### Low Level ####\n# Get: 'identifier', 'resolvedPath', 'realPath', 'fileExtension' \n# Set: 'identifier'\n## Helper functions:\n# Get: 'GetFileFormat', 'GetFileFormatArguments', 'ComputeAbsolutePath'\n# Create: 'CreateIdentifier', 'SplitIdentifier'\n### Anoymous identifiers\n# Get: 'anonymous'\n## Helper functions:\n# Get: 'IsAnonymousLayerIdentifier'\nimport os\nfrom pxr import Sdf\n## Anonymous layers\nlayer = Sdf.Layer.CreateAnonymous() \nprint(layer.identifier) # Returns: anon:0x7f8a1040ba80\nlayer = Sdf.Layer.CreateAnonymous(\"myCustomAnonLayer\")\nprint(layer.identifier) # Returns: anon:0x7f8a10498500:myCustomAnonLayer\nprint(layer.anonymous, layer.resolvedPath or \"-\", layer.realPath or \"-\", layer.fileExtension) # Returns: True, \"-\", \"-\", \"sdf\"\nprint(Sdf.Layer.IsAnonymousLayerIdentifier(layer.identifier)) # Returns True\n## Standard layers\nlayer.identifier = \"/my/cool/file/path/example.usd\"\nprint(layer.anonymous, layer.resolvedPath or \"-\", layer.realPath or \"-\", layer.fileExtension)\n# Returns: False, \"/my/cool/file/path/example.usd\", \"/my/cool/file/path/example.usd\", \"usd\"\n# When accesing an identifier string, we should always split it for args to get the URI\nlayer_uri, layer_args = layer.SplitIdentifier(layer.identifier)\nprint(layer_uri, layer_args) # Returns: \"/my/cool/file/path/example.usd\", {}\nlayer_identifier = layer.CreateIdentifier(\"/dir/file.usd\", {\"argA\": \"1\", \"argB\": \"test\"})\nprint(layer_identifier) # Returns: \"/dir/file.usd:SDF_FORMAT_ARGS:argA=1&argB=test\"\nlayer_uri, layer_args = layer.SplitIdentifier(layer_identifier)\nprint(layer_uri, layer_args) # Returns: \"/dir/file.usd\", {'argA': '1', 'argB': 'test'}\n# CreateNew requires the file path to be writable\nlayer_file_path = os.path.expanduser(\"~/Desktop/layer_identifier_example.usd\")\nlayer = Sdf.Layer.CreateNew(layer_file_path, {\"myCoolArg\": \"test\"})\nprint(layer.GetFileFormat()) # Returns: Instance of Sdf.FileFormat\nprint(layer.GetFileFormatArguments()) # Returns: {'myCoolArg': 'test'}\n# Get the actuall resolved path (from our asset resolver):\nprint(layer.identifier, layer.realPath, layer.fileExtension) # Returns: \"~/Desktop/layer_identifier_example.usd\" \"~/Desktop/layer_identifier_example.usd\" \"usd\"\n# This is the same as:\nprint(layer.identifier, layer.resolvedPath.GetPathString())\n# Compute a file relative to the directory of the layer identifier\nprint(layer.ComputeAbsolutePath(\"./some/other/file.usd\")) # Returns: ~/Desktop/some/other/file.usd\n#// ANCHOR_END: layerIdentifier\n\n#// ANCHOR: layerDefaultPrim\n### Low Level ###\n# Has: 'HasDefaultPrim'\n# Get: 'defaultPrim'\n# Set: 'defaultPrim'\n# Clear: 'ClearDefaultPrim'\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprint(layer.defaultPrim) # Returns \"\"\nlayer.defaultPrim = \"example\"\n# While we can set it to \"/example/path\",\n# references and payloads won't use it.\n#// ANCHOR_END: layerDefaultPrim\n\n#// ANCHOR: layerMuting\n### Low Level ###\n# Get: 'IsMuted', 'GetMutedLayers'\n# Set: 'AddToMutedLayers', 'RemoveFromMutedLayers'\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprint(Sdf.Layer.IsMuted(layer)) # Returns: False\nSdf.Layer.AddToMutedLayers(layer.identifier)\nprint(Sdf.Layer.GetMutedLayers()) # Returns: ['anon:0x7f8a1098f100']\nprint(Sdf.Layer.IsMuted(layer)) # Returns: True\nSdf.Layer.RemoveFromMutedLayers(layer.identifier)\nprint(Sdf.Layer.IsMuted(layer)) # Returns: False\n#// ANCHOR_END: layerMuting\n\n\n#// ANCHOR: layerPermissions\n### Low Level ###\n# Get: 'permissionToEdit', 'SetPermissionToEdit'\n# Set: 'permissionToSave', 'SetPermissionToSave'\nimport os\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprint(\"Can edit layer\", layer.permissionToEdit) # Returns: True\nSdf.CreatePrimInLayer(layer, Sdf.Path(\"/bicycle\"))\n# Edit permission\nlayer.SetPermissionToEdit(False)\ntry: \n    # This will now raise an error\n    Sdf.CreatePrimInLayer(layer, Sdf.Path(\"/car\"))\nexcept Exception as e:\n    print(e)\nlayer.SetPermissionToEdit(True)\n# Save permission\nprint(\"Can save layer\", layer.permissionToSave) # Returns: False\ntry:\n    # This fails as we can't save anoymous layers\n    layer.Save()\nexcept Exception as e:\n    print(e)\n# Changing this on anoymous layers doesn't work\nlayer.SetPermissionToSave(True)\nprint(\"Can save layer\", layer.permissionToSave) # Returns: False\n# If we change the identifer to not be an anonymous identifer, we can save it.\nlayer.identifier = os.path.expanduser(\"~/Desktop/layerPermission.usd\")\nprint(\"Can save layer\", layer.permissionToSave) # Returns: True\n#// ANCHOR_END: layerPermissions\n\n#// ANCHOR: layerTimeSamples\n### Low Level ###\n# Get: 'QueryTimeSample', 'ListAllTimeSamples', 'ListTimeSamplesForPath', 'GetNumTimeSamplesForPath', \n#      'GetBracketingTimeSamples', 'GetBracketingTimeSamplesForPath',\n# Set: 'SetTimeSample', \n# Clear: 'EraseTimeSample',\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/bicycle\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nattr_spec = Sdf.AttributeSpec(prim_spec, \"size\", Sdf.ValueTypeNames.Double)\nfor frame in range(1001, 1005):\n    value = float(frame - 1001)\n    # .SetTimeSample() takes args in the .SetTimeSample(<path>, <frame>, <value>) format\n    layer.SetTimeSample(attr_spec.path, frame, value)\nprint(layer.QueryTimeSample(attr_spec.path, 1005)) # Returns: 4\nprint(layer.ListTimeSamplesForPath(attr_spec.path)) # Returns: [1001.0, 1002.0, 1003.0, 1004.0]\nattr_spec = Sdf.AttributeSpec(prim_spec, \"width\", Sdf.ValueTypeNames.Float)\nlayer.SetTimeSample(attr_spec.path, 50, 150)\nprint(layer.ListAllTimeSamples()) # Returns: [50.0, 1001.0, 1002.0, 1003.0, 1004.0]\n# A typicall thing we can do is set the layer time metrics:\ntime_samples = layer.ListAllTimeSamples()\nlayer.startTimeCode = time_samples[0]\nlayer.endTimeCode = time_samples[-1]\n#// ANCHOR_END: layerTimeSamples\n\n\n\n#// ANCHOR: layerImportExport\n### Low Level ###\n# Create: 'New', 'CreateNew', 'CreateAnonymous', \n# Get: 'Find','FindOrOpen', 'OpenAsAnonymous',  'FindOrOpenRelativeToLayer', 'FindRelativeToLayer',\n# Set: 'Save', 'TransferContent', 'Import', 'ImportFromString', 'Export', 'ExportToString'\n# Clear: 'Clear', 'Reload', 'ReloadLayers'\n# See all open layers: 'GetLoadedLayers'\nfrom pxr import Sdf\nimport os\nlayer = Sdf.Layer.CreateAnonymous()\n## The .CreateNew command will check if the layer is saveable at the file location and create an empty file.\nlayer_file_path = os.path.expanduser(\"~/Desktop/layer_identifier_example.usd\")\nlayer = Sdf.Layer.CreateNew(layer_file_path)\nprint(layer.dirty) # Returns: False\n## Our layers are marked as \"dirty\" (edited) as soon as we make an edit.\nprim_spec = Sdf.CreatePrimInLayer(layer, Sdf.Path(\"/pig\"))\nprint(layer.dirty) # Returns: True\nlayer.Save()\n# Only edited (dirty) layers are saved, when layer.Save() is called\n# Only edited (dirty) layers are reloaded, when layer.Reload(force=False) is called.\n# Our layer.Save() and layer.Reload() methods also take an optional \"force\" arg.\n# This forces the layer to be saved. We can also call layer.Save() multiple times,\n# with the USD binary format (.usd/.usdc). This will then dump the content from memory\n# to disk in \"append\" mode. This avoids building up huge memory footprints when\n# creating large layers.\n## We can also transfer layer contents:\nother_layer = Sdf.Layer.CreateAnonymous()\nlayer.TransferContent(other_layer)\n# Or we import the content from another layer\nlayer.Import(layer_file_path)\n# This is the same as:\nlayer.TransferContent(layer.FindOrOpen((layer_file_path)))\n# We can also import/export to USD ascii representations,\n# this is quite usefull for debugging and inspecting the active layer.\n# layer.ImportFromString(other_layer.ExportAsString())\nlayer = Sdf.Layer.CreateAnonymous()\nprim_spec = Sdf.CreatePrimInLayer(layer, Sdf.Path(\"/pig\"))\nprint(layer.ExportToString())\n# Returns:\n\"\"\"\n#sdf 1.4.32\nover \"pig\"\n{\n}\n\"\"\"\n# We can also remove all prims that don't have properties/metadata\n# layer.RemoveInertSceneDescription()\n#// ANCHOR_END: layerImportExport\n\n\n#// ANCHOR: layerDependencies\n### Low Level ###\n# Get: 'GetCompositionAssetDependencies', 'GetAssetInfo', 'GetAssetName', 'GetExternalAssetDependencies',\n# Set: 'UpdateCompositionAssetDependency', 'UpdateExternalReference', 'UpdateAssetInfo'\nimport os\nfrom pxr import Sdf\nHFS_env = os.environ[\"HFS\"]\nlayer = Sdf.Layer.FindOrOpen(os.path.join(HFS_env, \"houdini\",\"usd\",\"assets\",\"pig\",\"payload.usdc\"))\n# Get all sublayer, reference and payload files (These are the only arcs that can load files)\nprint(layer.GetCompositionAssetDependencies()) # Returns: ['./geo.usdc', './mtl.usdc']\n# print(layer.GetExternalReferences(), layer.externalReferences) # The same thing, deprecated method.\n# Get external dependencies for non USD file formats. We don't use this with USD files.\nprint(layer.GetExternalAssetDependencies()) # Returns: [] \n# Get layer asset info. Our asset resolver has to custom implement this.\n# A common use case might be to return database related side car data.\nprint(layer.GetAssetName()) # Returns: None\nprint(layer.GetAssetInfo()) # Returns: None\nlayer.UpdateAssetInfo() # Re-resolve/refresh the asset info. This just force requeries our asset resolver query.\n# The perhaps most powerful method for dependencies is:\nlayer.UpdateCompositionAssetDependency(\"oldIdentifier\", \"newIdentifier\")\n# This allows us to repath any composition arc (sublayer/reference/payload) to a new file in the active layer.\n# Calling layer.UpdateCompositionAssetDependency(\"oldIdentifier\", \"\"), will remove the identifier from the\n# list-editable composition arc ops.\n#// ANCHOR_END: layerDependencies\n\n\n#// ANCHOR: layerTraversal\n### Low Level ###\n# Properties: 'pseudoRoot', 'rootPrims', 'empty'\n# Get: 'GetObjectAtPath', 'GetPrimAtPath', 'GetPropertyAtPath', 'GetAttributeAtPath', 'GetRelationshipAtPath',\n# Traversal: 'Traverse',\nfrom pxr import Sdf\nlayer = Sdf.Layer.CreateAnonymous()\n# Check if a layer actually has any content:\nprint(layer.empty) # Returns: True\nprint(layer.pseudoRoot) # The same as layer.GetPrimAtPath(\"/\")\n# Define prims\nbicycle_prim_spec = Sdf.CreatePrimInLayer(layer, Sdf.Path(\"/set/yard/bicycle\"))\nperson_prim_spec = Sdf.CreatePrimInLayer(layer, Sdf.Path(\"/characters/mike\"))\nprint(layer.rootPrims) # Returns: {'set': Sdf.Find('anon:0x7ff9f8ad7980', '/set'),\n                       #           'characters': Sdf.Find('anon:0x7ff9f8ad7980', '/characters')}\n# The GetObjectAtPath method gives us prim/attribute/relationship specs, based on what is at the path\nattr_spec = Sdf.AttributeSpec(bicycle_prim_spec, \"tire:size\", Sdf.ValueTypeNames.Float)\nattr_spec.default = 10\nrel_sec = Sdf.RelationshipSpec(person_prim_spec, \"vehicle\")\nrel_sec.targetPathList.Append(Sdf.Path(bicycle_prim_spec.path))\nprint(type(layer.GetObjectAtPath(attr_spec.path))) # Returns: <class 'pxr.Sdf.AttributeSpec'>\nprint(type(layer.GetObjectAtPath(rel_sec.path))) # Returns: <class 'pxr.Sdf.RelationshipSpec'>\n# Traversals work differently compared to stages.\ndef traversal_kernel(path):\n    print(path)\nlayer.Traverse(layer.pseudoRoot.path, traversal_kernel)\nprint(\"---\")\n# Returns:\n\"\"\"\n/set/yard/bicycle.tire:size\n/set/yard/bicycle\n/set/yard\n/set\n/characters/mike.vehicle[/set/yard/bicycle]\n/characters/mike.vehicle\n/characters/mike\n/characters\n/\n\"\"\"\n# As we can see, it traverses all path related fields, even relationships, as these map Sdf.Paths.\n# The Sdf.Path object is used as a \"filter\", rather than the Usd.Prim object.\ndef traversal_kernel(path):\n    if path.IsPrimPath():\n        print(path) \nlayer.Traverse(layer.pseudoRoot.path, traversal_kernel)\nprint(\"---\")\n\"\"\" Returns:\n/set/yard/bicycle\n/set/yard\n/set\n/characters/mike\n/characters\n\"\"\"\ndef traversal_kernel(path):\n    if path.IsPrimPropertyPath():\n        print(path) \nlayer.Traverse(layer.pseudoRoot.path, traversal_kernel)\nprint(\"---\")\n\"\"\" Returns:\n/set/yard/bicycle.tire:size\n/characters/mike.vehicle\n\"\"\"\ntire_size_attr_spec = attr_spec\ntire_diameter_attr_spec = Sdf.AttributeSpec(bicycle_prim_spec, \"tire:diameter\", Sdf.ValueTypeNames.Float)\ntire_diameter_attr_spec.connectionPathList.explicitItems = [tire_size_attr_spec.path]\ndef traversal_kernel(path):\n    if path.IsTargetPath():\n        print(\"IsTargetPath\", path) \nlayer.Traverse(layer.pseudoRoot.path, traversal_kernel)\n\"\"\" Returns:\nIsTargetPath /set/yard/bicycle.tire:diameter[/set/yard/bicycle.tire:size]\nIsTargetPath /characters/mike.vehicle[/set/yard/bicycle]\n\"\"\"\n#// ANCHOR_END: layerTraversal\n\n#// ANCHOR: stageMetadata\nfrom pxr import Usd, Sdf\nstage = Usd.Stage.CreateInMemory()\nbicycle_prim = stage.DefinePrim(\"/bicycle\")\nstage.SetMetadata(\"customLayerData\", {\"myCustomStageData\": 1})\n# Is the same as:\nlayer = stage.GetRootLayer()\nmetadata = layer.customLayerData\nmetadata[\"myCustomRootData\"] = 1\nlayer.customLayerData = metadata\n# As with layers, we can also set the default prim\nstage.SetDefaultPrim(bicycle_prim)\n# Is the same as:\nlayer.defaultPrim = \"bicycle\"\n#// ANCHOR_END: stageMetadata\n\n\n#// ANCHOR: stageLayerAccess\n### High Level ###\n# Has: 'HasLocalLayer'\n# Get: 'GetRootLayer', 'GetSessionLayer', 'GetLayerStack', 'GetUsedLayers', \nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nroot_layer = stage.GetRootLayer()\nprim = stage.DefinePrim(Sdf.Path(\"/pig_1\"), \"Xform\")\nprim.GetReferences().AddReference(\"/opt/hfs19.5/houdini/usd/assets/pig/pig.usd\", \"/pig\")\n# Get sublayers of current layer stack\nprint(stage.GetLayerStack()) \n# Get \n\"\"\"Returns:\n[Sdf.Find('anon:0x7ff9f5676280:tmp-session.usda'), Sdf.Find('anon:0x7ff9f5641700:tmp.usda')]\n\"\"\"\n# Get all loaded layers\nprint(stage.GetUsedLayers()) \n\"\"\"Returns:\n[Sdf.Find('/opt/hfs19.5/houdini/usd/assets/pig/pig.usd'), Sdf.Find('/opt/hfs19.5/houdini/usd\n/assets/pig/geo.usdc'), Sdf.Find('/opt/hfs19.5/houdini/usd/assets/pig/payload.usdc'), Sdf.Fi\nnd('/opt/hfs19.5/houdini/usd/assets/pig/mtl.usdc'), Sdf.Find('anon:0x7ff9f5675880:tmp-sessio\nn.usda'), Sdf.Find('anon:0x7ff9f55e7200:tmp.usda')]\n\"\"\"\n#// ANCHOR_END: stageLayerAccess\n\n#// ANCHOR: stageLayerStackUsedLayers\nimport os\nfrom pxr import Sdf, Usd, UsdUtils\nstage = Usd.Stage.CreateInMemory()\nroot_layer = stage.GetRootLayer()\n# Create sublayers with references\nbottom_layer_file_path = os.path.expanduser(\"~/Desktop/layer_bottom.usda\")\nbottom_layer = Sdf.Layer.CreateNew(bottom_layer_file_path)\ntop_layer_file_path = os.path.expanduser(\"~/Desktop/layer_top.usda\")\ntop_layer = Sdf.Layer.CreateNew(top_layer_file_path)\nroot_layer.subLayerPaths.append(top_layer_file_path)\ntop_layer.subLayerPaths.append(bottom_layer_file_path)\nstage.SetEditTarget(top_layer)\nprim = stage.DefinePrim(Sdf.Path(\"/pig_1\"), \"Xform\")\nprim.GetReferences().AddReference(\"/opt/hfs19.5/houdini/usd/assets/pig/pig.usd\", \"/pig\")\nstage.SetEditTarget(bottom_layer)\nprim = stage.DefinePrim(Sdf.Path(\"/pig_1\"), \"Xform\")\nprim.GetReferences().AddReference(\"/opt/hfs19.5/houdini/usd/assets/rubbertoy/rubbertoy.usd\", \"/rubbertoy\")\n# Save\nstage.Save()\n# Layer stack\nprint(stage.GetLayerStack(includeSessionLayers=False)) \n\"\"\" Returns:\n[Sdf.Find('anon:0x7ff9f47b9600:tmp.usda'),\nSdf.Find('/home/lucsch/Desktop/layer_top.usda'),\nSdf.Find('/home/lucsch/Desktop/layer_bottom.usda')]\n\"\"\" \nlayers = set()\nfor layer in stage.GetLayerStack(includeSessionLayers=False):\n    layers.add(layer)\n    layers.update([Sdf.Layer.FindOrOpen(i) for i in layer.GetCompositionAssetDependencies()])\nprint(list(layers))\n\"\"\" Returns:\n[Sdf.Find('/opt/hfs19.5/houdini/usd/assets/rubbertoy/rubbertoy.usd'), \nSdf.Find('/home/lucsch/Desktop/layer_top.usda'),\nSdf.Find('anon:0x7ff9f5677180:tmp.usda'),\nSdf.Find('/opt/hfs19.5/houdini/usd/assets/pig/pig.usd'),\nSdf.Find('/home/lucsch/Desktop/layer_bottom.usda')]\n\"\"\"\n#// ANCHOR_END: stageLayerStackUsedLayers\n\n#// ANCHOR: stageLayerManagement\n### High Level ###\n# Create: 'CreateNew', 'CreateInMemory', 'Open', 'IsSupportedFile', \n# Set: 'Save', 'Export', 'Flatten', 'ExportToString', 'SaveSessionLayers',\n# Clear: 'Reload'\nimport os\nfrom pxr import Sdf, Usd\n# The stage.CreateNew has multiple method signatures, these take:\n# - stage root layer identifier: The stage.GetRootLayer().identifier, this is where your stage get's saved to.\n# - session layer (optional): We can pass in an existing layer to use as an session layer.\n# - asset resolver context (optional): We can pass in a resolver context to aid path resolution. If not given, it will call\n#                                      ArResolver::CreateDefaultContextForAsset() on our registered resolvers.\n# - The initial payload loading mode: Either Usd.Stage.LoadAll or Usd.Stage.LoadNone\nstage_file_path = os.path.expanduser(\"~/Desktop/stage_identifier_example.usda\")\nstage = Usd.Stage.CreateNew(stage_file_path)\n# The stage creation will create an empty USD file at the specified path.\nprint(stage.GetRootLayer().identifier) # Returns: /home/lucsch/Desktop/stage_identifier_example.usd\nprim = stage.DefinePrim(Sdf.Path(\"/bicycle\"), \"Xform\")\n# We can also create a stage in memory, this is the same as Sdf.Layer.CreateAnonymous() and using it as a root layer\n# stage = Usd.Stage.CreateInMemory(\"test\")\n# Or:\nlayer = Sdf.Layer.CreateAnonymous()\nstage.Open(layer.identifier)\n## Saving\n# Calling stage.Save(), calls layer.Save() on all dirty layers that contribute to the stage.\nstage.Save()\n# The same as:\nfor layer in stage.GetLayerStack(includeSessionLayers=False):\n    if not layer.anonymous and layer.dirty:\n        layer.Save()\n# Calling stage.SaveSessionLayers() will also save all session layers, that are not anonymous\n## Flatten\n# We can also flatten our layers of the stage. This merges all the data, so it should be used with care,\n# as it will likely flood your RAM with large scenes. It removes all composition arcs and returns a single layer\n# with the combined result\nstage = Usd.Stage.CreateInMemory()\nroot_layer = stage.GetRootLayer()\nprim = stage.DefinePrim(Sdf.Path(\"/bicycle\"), \"Xform\")\nsublayer = Sdf.Layer.CreateAnonymous()\nroot_layer.subLayerPaths.append(sublayer.identifier)\nstage.SetEditTarget(sublayer)\nprim = stage.DefinePrim(Sdf.Path(\"/car\"), \"Xform\")\nprint(root_layer.ExportToString())\n\"\"\"Returns:\n#usda 1.0\n(\n    subLayers = [\n        @anon:0x7ff9f5fed300@\n    ]\n)\n\ndef Xform \"bicycle\"\n{\n}\n\"\"\"\nflattened_result = stage.Flatten()\nprint(flattened_result.ExportToString())\n\"\"\"Returns:\n#usda 1.0\n(\n)\n\ndef Xform \"car\"\n{\n}\n\ndef Xform \"bicycle\"\n{\n}\n\"\"\"\n## Export:\n# The export command calls the same thing we just did\n# layer = stage.Flatten()\n# layer.Export(\"/myFilePath.usd\")\nprint(stage.ExportToString()) # Returns: The same thing as above\n## Reload:\nstage.Reload()\n# The same as:\nfor layer in stage.GetUsedLayers():\n    # !IMPORTANT! This does not check if the layer is anonymous,\n    # so you will lose all your anon layer content.\n    layer.Reload()\n    # Here is a saver way:\n    if not layer.anonymous:\n        layer.Reload()\n#// ANCHOR_END: stageLayerManagement\n\n\n#// ANCHOR: stageTraversal\n### High Level ###\n# Get: 'GetPseudoRoot', 'GetObjectAtPath',\n#      'GetPrimAtPath', 'GetPropertyAtPath','GetAttributeAtPath', 'GetRelationshipAtPath',\n# Set: 'DefinePrim', 'OverridePrim', 'CreateClassPrim', 'RemovePrim'\n# Traversal: 'Traverse','TraverseAll'\nfrom pxr import Sdf, Usd, UsdUtils\nstage = Usd.Stage.CreateInMemory()\n# Define and change specifier\nstage.DefinePrim(\"/changedSpecifier/definedCube\", \"Cube\").SetSpecifier(Sdf.SpecifierDef)\nstage.DefinePrim(\"/changedSpecifier/overCube\", \"Cube\").SetSpecifier(Sdf.SpecifierOver)\nstage.DefinePrim(\"/changedSpecifier/classCube\", \"Cube\").SetSpecifier(Sdf.SpecifierClass)\n# Or create with specifier\nstage.DefinePrim(\"/createdSpecifier/definedCube\", \"Cube\")\nstage.OverridePrim(\"/createdSpecifier/overCube\")\nstage.CreateClassPrim(\"/createdSpecifier/classCube\")\n# Create attribute\nprim = stage.DefinePrim(\"/bicycle\")\nprim.CreateAttribute(\"tire:size\", Sdf.ValueTypeNames.Float)\n# Get the pseudo root prim at \"/\"\npseudo_root_prim = stage.GetPseudoRoot()\n# Or:\npseudo_root_prim = stage.GetPrimAtPath(\"/\")\n# Traverse:\nfor prim in stage.TraverseAll():\n    print(prim)\n\"\"\" Returns:\nUsd.Prim(</changedSpecifier>)\nUsd.Prim(</changedSpecifier/definedCube>)\nUsd.Prim(</changedSpecifier/overCube>)\nUsd.Prim(</changedSpecifier/classCube>)\nUsd.Prim(</createdSpecifier>)\nUsd.Prim(</createdSpecifier/definedCube>)\nUsd.Prim(</createdSpecifier/overCube>)\nUsd.Prim(</createdSpecifier/classCube>)\n\"\"\"\n# Get Prims/Properties\n# The GetObjectAtPath returns the entity requested by the path (prim/attribute/relationship)\nprim = stage.GetObjectAtPath(Sdf.Path(\"/createdSpecifier\"))\nprim = stage.GetPrimAtPath(Sdf.Path(\"/changedSpecifier\"))\nattr = stage.GetObjectAtPath(Sdf.Path(\"/bicycle.tire:size\"))\nattr = stage.GetAttributeAtPath(Sdf.Path(\"/bicycle.tire:size\"))\n#// ANCHOR_END: stageTraversal\n\n\n#// ANCHOR: loadingMechanismsLayerMuting\n### High Level ###\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nlayer_A = Sdf.Layer.CreateAnonymous(\"Layer_A\")\nlayer_B = Sdf.Layer.CreateAnonymous(\"Layer_B\")\nlayer_C = Sdf.Layer.CreateAnonymous(\"Layer_C\")\nstage.GetRootLayer().subLayerPaths.append(layer_A.identifier)\nstage.GetRootLayer().subLayerPaths.append(layer_B.identifier)\nstage.GetRootLayer().subLayerPaths.append(layer_C.identifier)\n# Mute layer\nstage.MuteLayer(layer_A.identifier)\n# Unmute layer\nstage.UnmuteLayer(layer_A.identifier)\n# Or both MuteAndUnmuteLayers([<layers to mute>], [<layers to unmute>])\nstage.MuteAndUnmuteLayers([layer_A.identifier, layer_B.identifier], [layer_C.identifier])\n# Check what layers are muted\nprint(stage.GetMutedLayers()) # Returns: [layerA.identifier, layerB.identifier]\nprint(stage.IsLayerMuted(layer_C.identifier)) # Returns: False\n#// ANCHOR_END: loadingMechanismsLayerMuting\n\n#// ANCHOR: loadingMechanismsLayerPrimPopulationMask\n## Stage\n# Create: 'OpenMasked',\n# Get: 'GetPopulationMask',\n# Set: 'SetPopulationMask', 'ExpandPopulationMask'\n## Population Mask\n# Usd.StagePopulationMask()\n# Has: 'IsEmpty',  'Includes', 'IncludesSubtree'\n# Get: 'GetIncludedChildNames', 'GetIntersection', 'GetPaths', 'GetUnion'\n# Set:  'Add', 'Intersection',  'Union'\n# Constants: 'All'\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\n# Create hierarchy\nprim_paths = [\n    \"/set/yard/biycle\",\n    \"/set/yard/shed/shovel\",\n    \"/set/yard/shed/flower_pot\",\n    \"/set/yard/shed/lawnmower\",\n    \"/set/yard/shed/soil\",\n    \"/set/yard/shed/wood\",\n    \"/set/garage/car\",\n    \"/set/garage/tractor\",\n    \"/set/garage/helicopter\",\n    \"/set/garage/boat\",\n    \"/set/garage/key_box\",\n    \"/set/garage/key_box/red\",\n    \"/set/garage/key_box/blue\",\n    \"/set/garage/key_box/green\",\n    \"/set/people/mike\",\n    \"/set/people/charolotte\"\n]\nfor prim_path in prim_paths:\n    prim = stage.DefinePrim(prim_path, \"Cube\")\n    \npopulation_mask = Usd.StagePopulationMask()\nprint(population_mask.GetPaths())\nprint(population_mask.All()) # Same as: Usd.StagePopulationMask([Sdf.Path(\"/\")])\n# Or stage.GetPopulationMask()\npopulation_mask.Add(Sdf.Path(\"/set/yard/shed/lawnmower\"))\npopulation_mask.Add(Sdf.Path(\"/set/garage/key_box\"))\nstage.SetPopulationMask(population_mask)\nprint(\"<< hierarchy >>\")\nfor prim in stage.Traverse():\n    print(prim.GetPath())\n\"\"\"Returns:\n/set\n/set/yard\n/set/yard/shed\n/set/yard/shed/lawnmower\n/set/garage\n/set/garage/key_box\n/set/garage/key_box/red\n/set/garage/key_box/blue\n/set/garage/key_box/green\n\"\"\"\n# Intersections tests\nprint(population_mask.Includes(\"/set/yard/shed\")) # Returns: True\nprint(population_mask.IncludesSubtree(\"/set/yard/shed\")) # Returns: False (As not all child prims are included)\nprint(population_mask.IncludesSubtree(\"/set/garage/key_box\")) # Returns: True (As all child prims are included)\n#// ANCHOR_END: loadingMechanismsLayerPrimPopulationMask\n\n\n#// ANCHOR: loadingMechanismsLayerPayloadLoading\n## Stage\n# Has: 'FindLoadable', \n# Get: 'GetLoadRules', 'GetLoadSet'\n# Set: 'Load', 'Unload', 'LoadAndUnload', 'LoadAll', 'LoadNone', 'SetLoadRules'\n# Constants: 'InitialLoadSet.LoadAll', 'InitialLoadSet.LoadNone' \n## Stage Load Rules\n# Has: 'IsLoaded', 'IsLoadedWithAllDescendants', 'IsLoadedWithNoDescendants'\n# Get: 'GetRules', 'GetEffectiveRuleForPath',\n# Set: 'LoadWithDescendants', 'LoadWithoutDescendants'\n#      'LoadAll',  'LoadNone', 'Unload', 'LoadAndUnload', 'AddRule',  'SetRules'\n# Clear: 'Minimize'\n# Constants: StageLoadRules.AllRule, StageLoadRules.OnlyRule, StageLoadRules.NoneRule\nfrom pxr import Sdf, Usd\n# Spawn example data, this would be a file on disk\nlayer = Sdf.Layer.CreateAnonymous()\nprim_path = Sdf.Path(\"/bicycle\")\nprim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\nprim_spec.specifier = Sdf.SpecifierDef\nprim_spec.typeName = \"Cube\"\nattr_spec = Sdf.AttributeSpec(prim_spec, \"size\", Sdf.ValueTypeNames.Double)\nfor frame in range(1001, 1010):\n    value = float(frame - 1001)\n    layer.SetTimeSample(attr_spec.path, frame, value)\n# Payload data\nstage = Usd.Stage.CreateInMemory()\nref = Sdf.Payload(layer.identifier, \"/bicycle\")\nprim_path = Sdf.Path(\"/set/yard/bicycle\")\nprim = stage.DefinePrim(prim_path)\nref_api = prim.GetPayloads()\nref_api.AddPayload(ref)\n# Check for what can be payloaded\nprint(stage.FindLoadable()) # Returns: [Sdf.Path('/set/yard/bicycle')]\n# Check what prim paths are payloaded\nprint(stage.GetLoadSet()) # Returns: [Sdf.Path('/set/yard/bicycle')]\n# Unload payload\nstage.Unload(prim_path)\nprint(stage.GetLoadSet()) # Returns: []\n# Please consult the official docs for how the rule system works.\n# Basically we can flag primpaths to recursively load their nested child payloads or to only load the top most payload.\n#// ANCHOR_END: loadingMechanismsLayerPayloadLoading\n\n\n#// ANCHOR: loadingMechanismsGeomModelAPIDrawMode\nfrom pxr import Gf, Sdf, Usd, UsdGeom, UsdShade\nstage = Usd.Stage.CreateInMemory()\ncone_prim = stage.DefinePrim(Sdf.Path(\"/set/yard/cone\"), \"Cone\")\ncone_prim.GetAttribute(\"radius\").Set(4)\nUsd.ModelAPI(cone_prim).SetKind(\"component\")\nsphere_prim = stage.DefinePrim(Sdf.Path(\"/set/yard/sphere\"), \"Sphere\")\nUsd.ModelAPI(sphere_prim).SetKind(\"component\")\nfor ancestor_prim_path in sphere_prim.GetParent().GetPath().GetAncestorsRange():\n    ancestor_prim = stage.GetPrimAtPath(ancestor_prim_path)\n    ancestor_prim.SetTypeName(\"Xform\")\n    Usd.ModelAPI(ancestor_prim).SetKind(\"group\")\n# Enable on parent\nset_prim = stage.GetPrimAtPath(\"/set\")\nset_geom_model_API = UsdGeom.ModelAPI.Apply(set_prim)\nset_geom_model_API.GetModelDrawModeAttr().Set(UsdGeom.Tokens.bounds)\nset_geom_model_API.GetModelDrawModeColorAttr().Set(Gf.Vec3h([1,0,0]))\n# If we enable \"apply\" on the parent, children will not be drawn anymore,\n# instead just a single combined bbox is drawn for all child prims.\n# set_geom_model_API.GetModelApplyDrawModeAttr().Set(1)\n# Enable on child\nsphere_geom_model_API = UsdGeom.ModelAPI.Apply(sphere_prim)\n# sphere_geom_model_API.GetModelDrawModeAttr().Set(UsdGeom.Tokens.default_)\nsphere_geom_model_API.GetModelDrawModeAttr().Set(UsdGeom.Tokens.cards)\nsphere_geom_model_API.GetModelDrawModeColorAttr().Set(Gf.Vec3h([0,1,0]))\n# For \"component\" (sub-)kinds, this is True by default\n# sphere_geom_model_API.GetModelApplyDrawModeAttr().Set(0)\n#// ANCHOR_END: loadingMechanismsGeomModelAPIDrawMode\n\n\n#// ANCHOR: traverseDataStage\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\n# Create hierarchy\nprim_paths = [\n    \"/set/yard/biycle\",\n    \"/set/yard/shed/shovel\",\n    \"/set/yard/shed/flower_pot\",\n    \"/set/yard/shed/lawnmower\",\n    \"/set/yard/shed/soil\",\n    \"/set/yard/shed/wood\",\n    \"/set/garage/car\",\n    \"/set/garage/tractor\",\n    \"/set/garage/helicopter\",\n    \"/set/garage/boat\",\n    \"/set/garage/key_box\",\n    \"/set/garage/key_box/red\",\n    \"/set/garage/key_box/blue\",\n    \"/set/garage/key_box/green\",\n    \"/set/people/mike\",\n    \"/set/people/charolotte\"\n]\nfor prim_path in prim_paths:\n    prim = stage.DefinePrim(prim_path, \"Cube\")\n\nroot_prim = stage.GetPseudoRoot()\n# Standard Traversal\n# We have to cast it as an iterator to gain access to the .PruneChildren()/.IsPostVisit method.\niterator = iter(Usd.PrimRange(root_prim))\nfor prim in iterator:\n    if prim.GetPath() == Sdf.Path(\"/set/garage/key_box\"):\n        # Skip traversing key_box hierarchy\n        iterator.PruneChildren()\n    print(prim.GetPath().pathString)\n\"\"\"Returns:\n/\n/set\n/set/yard\n/set/yard/biycle\n/set/yard/shed\n/set/yard/shed/shovel\n/set/yard/shed/flower_pot\n/set/yard/shed/lawnmower\n/set/yard/shed/soil\n/set/yard/shed/wood\n/set/garage\n/set/garage/car\n/set/garage/tractor\n/set/garage/helicopter\n/set/garage/boat\n/set/garage/key_box\n/set/people\n/set/people/mike\n/set/people/charolotte\n\"\"\"\n# PreAndPostVisitTraversal\niterator = iter(Usd.PrimRange.PreAndPostVisit(root_prim))\nfor prim in iterator:\n    print(\"Is Post Visit: {:<2} | Path: {}\".format(iterator.IsPostVisit(), prim.GetPath().pathString))\n\"\"\"Returns:\nIs Post Visit: 0  | Path: /\nIs Post Visit: 0  | Path: /set\nIs Post Visit: 0  | Path: /set/yard\nIs Post Visit: 0  | Path: /set/yard/biycle\nIs Post Visit: 1  | Path: /set/yard/biycle\nIs Post Visit: 0  | Path: /set/yard/shed\nIs Post Visit: 0  | Path: /set/yard/shed/shovel\nIs Post Visit: 1  | Path: /set/yard/shed/shovel\nIs Post Visit: 0  | Path: /set/yard/shed/flower_pot\nIs Post Visit: 1  | Path: /set/yard/shed/flower_pot\nIs Post Visit: 0  | Path: /set/yard/shed/lawnmower\nIs Post Visit: 1  | Path: /set/yard/shed/lawnmower\nIs Post Visit: 0  | Path: /set/yard/shed/soil\nIs Post Visit: 1  | Path: /set/yard/shed/soil\nIs Post Visit: 0  | Path: /set/yard/shed/wood\nIs Post Visit: 1  | Path: /set/yard/shed/wood\nIs Post Visit: 1  | Path: /set/yard/shed\nIs Post Visit: 1  | Path: /set/yard\nIs Post Visit: 0  | Path: /set/garage\nIs Post Visit: 0  | Path: /set/garage/car\nIs Post Visit: 1  | Path: /set/garage/car\nIs Post Visit: 0  | Path: /set/garage/tractor\nIs Post Visit: 1  | Path: /set/garage/tractor\nIs Post Visit: 0  | Path: /set/garage/helicopter\nIs Post Visit: 1  | Path: /set/garage/helicopter\nIs Post Visit: 0  | Path: /set/garage/boat\nIs Post Visit: 1  | Path: /set/garage/boat\nIs Post Visit: 0  | Path: /set/garage/key_box\nIs Post Visit: 0  | Path: /set/garage/key_box/red\nIs Post Visit: 1  | Path: /set/garage/key_box/red\nIs Post Visit: 0  | Path: /set/garage/key_box/blue\nIs Post Visit: 1  | Path: /set/garage/key_box/blue\nIs Post Visit: 0  | Path: /set/garage/key_box/green\nIs Post Visit: 1  | Path: /set/garage/key_box/green\nIs Post Visit: 1  | Path: /set/garage/key_box\nIs Post Visit: 1  | Path: /set/garage\nIs Post Visit: 0  | Path: /set/people\nIs Post Visit: 0  | Path: /set/people/mike\nIs Post Visit: 1  | Path: /set/people/mike\nIs Post Visit: 0  | Path: /set/people/charolotte\nIs Post Visit: 1  | Path: /set/people/charolotte\nIs Post Visit: 1  | Path: /set/people\nIs Post Visit: 1  | Path: /set\nIs Post Visit: 1  | Path: /\n\"\"\"\n#// ANCHOR_END: traverseDataStage\n\n\n#// ANCHOR: traverseSampleData\nimport random\nfrom pxr import Sdf, Usd, UsdGeom,UsdShade, Tf\nstage = Usd.Stage.CreateInMemory()\nlayer = stage.GetEditTarget().GetLayer()\n\nleaf_prim_types = (\"Cube\", \"Cylinder\", \"Sphere\", \"Mesh\", \"Points\", \"RectLight\", \"Camera\")\nleaf_prim_types_count = len(leaf_prim_types)\n\ndef create_hierarchy(layer, root_prim_path, max_levels):\n    def generate_hierarchy(layer, root_prim_path, leaf_prim_counter, max_levels):\n        levels = random.randint(1, max_levels)\n        for level in range(levels):\n            level_depth = root_prim_path.pathElementCount + 1\n            prim_path = root_prim_path.AppendChild(f\"level_{level_depth}_child_{level}\")\n            prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\n            prim_spec.specifier = Sdf.SpecifierDef\n            # Type\n            prim_spec.typeName = \"Xform\"\n            # Kind\n            prim_spec.SetInfo(\"kind\", \"group\")\n            # Seed parent prim specs\n            hiearchy_seed_state = random.getstate()\n            # Active\n            random.seed(level_depth)\n            if random.random() < 0.1:\n                prim_spec.SetInfo(\"active\", False)\n            random.setstate(hiearchy_seed_state)\n            if levels == 1:\n                # Parent prim\n                # Kind\n                prim_spec.nameParent.SetInfo(\"kind\", \"component\")\n                # Purpose\n                purpose_attr_spec = Sdf.AttributeSpec(prim_spec.nameParent, \"purpose\", Sdf.ValueTypeNames.Token)\n                if random.random() < .9:\n                    purpose_attr_spec.default = UsdGeom.Tokens.render\n                else:\n                    purpose_attr_spec.default = UsdGeom.Tokens.proxy\n                # Seed leaf prim specs\n                leaf_prim_counter[0] += 1\n                hiearchy_seed_state = random.getstate()\n                random.seed(leaf_prim_counter[0])\n                # Custom Leaf Prim attribute\n                prim_spec.typeName = leaf_prim_types[random.randint(0, leaf_prim_types_count -1)]\n                prim_spec.assetInfo[\"is_leaf\"] = True\n                prim_spec.ClearInfo(\"kind\")\n                is_leaf_attr_spec = Sdf.AttributeSpec(prim_spec, \"is_leaf\", Sdf.ValueTypeNames.Bool)\n                is_leaf_attr_spec.default = True\n                # Active\n                if random.random() < 0.1:\n                    prim_spec.SetInfo(\"active\", False)\n                # Visibility\n                visibility_attr_spec = Sdf.AttributeSpec(prim_spec, \"visibility\", Sdf.ValueTypeNames.Token)\n                if random.random() < .5:\n                    visibility_attr_spec.default = UsdGeom.Tokens.inherited\n                else:\n                    visibility_attr_spec.default = UsdGeom.Tokens.invisible\n                    \n                random.setstate(hiearchy_seed_state)\n            else:\n                generate_hierarchy(layer, prim_path, leaf_prim_counter, max_levels -1)\n    random.seed(0)\n    leaf_prim_counter = [0] # Make sure this is a pointer\n    generate_hierarchy(layer, root_prim_path, leaf_prim_counter, max_levels)\n                \nwith Sdf.ChangeBlock():\n    prim_path = Sdf.Path(\"/profiling_grp\")\n    prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\n    prim_spec.specifier = Sdf.SpecifierDef\n    prim_spec.typeName = \"Xform\"\n    prim_spec.SetInfo(\"kind\", \"group\")\n    create_hierarchy(layer, prim_path, 9)\n#// ANCHOR_END: traverseSampleData\n\n#// ANCHOR: traverseSampleDataProfiling\n# We assume we are running on the stage from the previous example.\nroot_prim = stage.GetPrimAtPath(\"/profiling_grp\")\nleaf_prim_types = (\"Cube\", \"Cylinder\", \"Sphere\", \"Mesh\", \"Points\", \"RectLight\", \"Camera\")\n\ndef profile(func, label, root_prim):\n    # The changeblock doesn't do much here as we are only querying data, but\n    # let's keep it in there anyway.\n    with Sdf.ChangeBlock():\n        runs = 3\n        sw = Tf.Stopwatch()\n        time_delta = 0.0\n        for run in range(runs):\n            sw.Reset()\n            sw.Start()\n            matched_prims = []\n            for prim in iter(Usd.PrimRange(root_prim)):\n                if func(prim):\n                    matched_prims.append(prim)\n            sw.Stop()\n            time_delta += sw.seconds\n        print(\"{:.5f} Seconds | {} | Match {}\".format(time_delta / runs, label, len(matched_prims)))\n\nprint(\"----\")\n\ndef profile_boundable(prim):\n    return prim.IsA(UsdGeom.Boundable)\n\nprofile(profile_boundable, \"IsA(Boundable)\", root_prim)\n    \ndef profile_GetTypeName(prim):\n    return prim.GetTypeName() in leaf_prim_types\n\nprofile(profile_GetTypeName, \"GetTypeName\", root_prim)\n\ndef profile_kind(prim):\n    model_api = Usd.ModelAPI(prim)\n    return model_api.GetKind() != Kind.Tokens.group\n    \nprofile(profile_kind, \"Kind\", root_prim)\n \ndef profile_assetInfo_is_leaf(prim):\n    asset_info = prim.GetAssetInfo()\n    return asset_info.get(\"is_leaf\", False)\n\nprofile(profile_assetInfo_is_leaf, \"IsLeaf AssetInfo \", root_prim)\n\ndef profile_attribute_has_is_leaf(prim):\n    if prim.HasAttribute(\"is_leaf\"):\n        return True\n    return False\n\nprofile(profile_attribute_has_is_leaf, \"IsLeaf Attribute Has\", root_prim)\n\ndef profile_attribute_is_leaf(prim):\n    is_leaf_attr = prim.GetAttribute(\"is_leaf\")\n    if is_leaf_attr:\n        if is_leaf_attr.Get():\n            return True\n    return False\n\nprofile(profile_attribute_is_leaf, \"IsLeaf Attribute \", root_prim)\n\ndef profile_attribute_extra_validation_is_leaf(prim):\n    if prim.HasAttribute(\"is_leaf\"):\n        is_leaf_attr = prim.GetAttribute(\"is_leaf\")\n        if is_leaf_attr.Get():\n            return True\n    return False\n\nprofile(profile_attribute_extra_validation_is_leaf, \"IsLeaf Attribute (Validation)\", root_prim)\n#// ANCHOR_END: traverseSampleDataProfiling\n\n#// ANCHOR: traverseDataStageTemplate\n# Standard\nstart_prim = stage.GetPrimAtPath(\"/\") # Or stage.GetPseudoRoot(), this is the same as stage.Traverse()\niterator = iter(Usd.PrimRange(start_prim))\nfor prim in iterator:\n    if prim.IsA(UsdGeom.Imageable): # Some condition as listed above or custom property/metadata checks\n        # Don't traverse into the child prims\n        iterator.PruneChildren()\n# Pre and post visit:\nstart_prim = stage.GetPrimAtPath(\"/\") # Or stage.GetPseudoRoot(), this is the same as stage.Traverse()\niterator = iter(Usd.PrimRange.PreAndPostVisit(start_prim))\nfor prim in iterator:\n    if not iterator.IsPostVisit():\n        if prim.IsA(UsdGeom.Imageable): # Some condition as listed above or custom property/metadata checks\n            # Don't traverse into the child prims\n            iterator.PruneChildren()\n# Custom Predicate\npredicate = Usd.PrimIsActive & Usd.PrimIsLoaded # All prims, even class and over prims.\nstart_prim = stage.GetPrimAtPath(\"/\") # Or stage.GetPseudoRoot(), this is the same as stage.Traverse()\niterator = iter(Usd.PrimRange.PrimRange(start_prim, predicate=predicate))\nfor prim in iterator:\n    if not iterator.IsPostVisit():\n        if prim.IsA(UsdGeom.Imageable): # Some condition as listed above or custom property/metadata checks\n            # Don't traverse into the child prims\n            iterator.PruneChildren()\n#// ANCHOR_END: traverseDataStageTemplate\n\n\n#// ANCHOR: traverseDataLayerTemplate\nprim_paths = []\nvariant_prim_paths = []\nproperty_paths = [] # The Sdf.Path class doesn't distinguish between attributes and relationships\nproperty_relationship_target_paths = []\ndef traversal_kernel(path):\n    print(path)\n    if path.IsPrimPath():\n        prim_paths.append(path)\n    elif path.IsPrimVariantSelectionPath():\n        variant_prim_paths.append(path)\n    elif path.IsPropertyPath():\n        property_paths.append(path)\n    elif path.IsTargetPath():\n        property_relationship_target_paths.append(path)\nlayer.Traverse(layer.pseudoRoot.path, traversal_kernel)\n#// ANCHOR_END: traverseDataLayerTemplate\n\n\n\n#// ANCHOR: xformXformableOverview\n## Xformable Class\n# This is class is a wrapper around creating attributes that start with \"xformOp\".\n# When we run one of its \"Add<XformOpName>Op\" methods, it automatically adds\n# it to the \"xformOpOrder\" attribute. This attribute controls, what attributes\n# contribute to the xform of a prim. \n# Has: 'TransformMightBeTimeVarying', \n# Get: 'GetOrderedXformOps',  'GetXformOpOrderAttr', 'GetResetXformStack',\n# Add: 'AddTranslateOp', 'AddOrientOp', 'AddRotate<XYZ>op', 'AddScaleOp', 'AddTransformOp', 'AddXformOp',\n# Set: 'CreateXformOpOrderAttr', 'SetXformOpOrder', 'SetResetXformStack', 'MakeMatrixXform',\n# Clear: 'ClearXformOpOrder',\n## For querying we can use the following. For large queries we should resort to UsdGeom.XformCache/UsdGeom.BBoxCache\n# Get Xform: 'GetLocalTransformation', 'ComputeLocalToWorldTransform', 'ComputeParentToWorldTransform',\n# Get Bounds: 'ComputeLocalBound', 'ComputeUntransformedBound', 'ComputeWorldBound',\nimport math\nfrom pxr import Gf,  Sdf, Usd, UsdGeom\nstage = Usd.Stage.CreateInMemory()\nroot_prim_path = Sdf.Path(\"/root\")\nroot_prim = stage.DefinePrim(root_prim_path, \"Xform\")\ncone_prim_path = Sdf.Path(\"/root/cone\")\ncone_prim = stage.DefinePrim(cone_prim_path, \"Cone\")\n\n# Set local transform of leaf prim\ncone_xformable = UsdGeom.Xformable(cone_prim)\ncone_translate_op = cone_xformable.AddTranslateOp(opSuffix=\"upAndDown\")\ncone_rotate_op = cone_xformable.AddRotateXYZOp(opSuffix= \"spinMeRound\")\nfor frame in range(1, 100):\n    cone_translate_op.Set(Gf.Vec3h([5, math.sin(frame * 0.1) * 3, 0]), frame)\n    #cone_rotate_op.Set(Gf.Vec3h([0, frame * 5, 0]), frame)\n# By clearing the xformOpOrder attribute, we keep the transforms, but don't apply it.\ncone_xformOpOrder_attr = cone_xformable.GetXformOpOrderAttr()\ncone_xformOpOrder_value = cone_xformOpOrder_attr.Get()\n#cone_xformable.ClearXformOpOrder()\n# Reverse the transform order\n#cone_xformOpOrder_attr.Set(cone_xformOpOrder_value[::-1])\n\n# A transform is combined with its parent prims' transforms\nroot_xformable = UsdGeom.Xformable(root_prim)\nroot_translate_op = root_xformable.AddTranslateOp(opSuffix=\"upAndDown\")\nroot_rotate_op = root_xformable.AddRotateZOp(opSuffix= \"spinMeRound\")\nfor frame in range(1, 100):\n    # root_translate_op.Set(Gf.Vec3h([5, math.sin(frame * 0.5), 0]), frame)\n    root_rotate_op.Set(frame * 15, frame)\n#// ANCHOR_END: xformXformableOverview\n    \n    \n#// ANCHOR: xformResetXformStack\nimport math\nfrom pxr import Gf,  Sdf, Usd, UsdGeom\nstage = Usd.Stage.CreateInMemory()\nroot_prim_path = Sdf.Path(\"/root\")\nroot_prim = stage.DefinePrim(root_prim_path, \"Xform\")\ncone_prim_path = Sdf.Path(\"/root/cone\")\ncone_prim = stage.DefinePrim(cone_prim_path, \"Cone\")\n# Set local transform of leaf prim\ncone_xformable = UsdGeom.Xformable(cone_prim)\ncone_translate_op = cone_xformable.AddTranslateOp(opSuffix=\"upAndDown\")\nfor frame in range(1, 100):\n    cone_translate_op.Set(Gf.Vec3h([5, math.sin(frame * 0.1) * 3, 0]), frame)\n# A transform is combined with its parent prims' transforms\nroot_xformable = UsdGeom.Xformable(root_prim)\nroot_rotate_op = root_xformable.AddRotateZOp(opSuffix= \"spinMeRound\")\nfor frame in range(1, 100):\n    root_rotate_op.Set(frame * 15, frame)\n# If we only want the local stack transform, we can add the special\n# '!resetXformStack!' attribute to our xformOpOrder attribute.\n# We can add it anywhere in the list, any xformOps before it and on ancestor prims\n# will be ignored.\ncone_xformable.SetResetXformStack(True)\n#// ANCHOR_END: xformResetXformStack\n    \n#// ANCHOR: xformWorldSpaceLocalSpace\nimport math\nfrom pxr import Gf,  Sdf, Usd, UsdGeom, UsdUtils\n\n# Stage A: A car animated in world space\nstage_a = Usd.Stage.CreateInMemory()\n#stage_a = stage\ncar_prim_path = Sdf.Path(\"/set/stret/car\")\ncar_prim = stage_a.DefinePrim(car_prim_path, \"Xform\")\ncar_body_prim_path = Sdf.Path(\"/set/stret/car/body/hull\")\ncar_body_prim = stage_a.DefinePrim(car_body_prim_path, \"Cube\")\ncar_xformable = UsdGeom.Xformable(car_prim)\ncar_translate_op = car_xformable.AddTranslateOp(opSuffix=\"carDrivingDownStreet\")\nfor frame in range(1, 100):\n    car_translate_op.Set(Gf.Vec3h([frame, 0, 0]), frame)\n\n# Stage A: A person animated in world space\nstage_b = Usd.Stage.CreateInMemory()\n#stage_b = stage\nmike_prim_path = Sdf.Path(\"/set/stret/car/person/mike\")\nmike_prim = stage_b.DefinePrim(mike_prim_path, \"Sphere\")\nmike_xformable = UsdGeom.Xformable(mike_prim)\nmike_translate_op = mike_xformable.AddTranslateOp(opSuffix=\"mikeInWorldSpace\")\nmike_xform_op = mike_xformable.AddTransformOp(opSuffix=\"mikeInLocalSpace\")\n# Let's disable the transform op for now\nmike_xformable.GetXformOpOrderAttr().Set([mike_translate_op.GetOpName()])\nfor frame in range(1, 100):\n    mike_translate_op.Set(Gf.Vec3h([frame, 1, 0]), frame)\n\n# How do we merge these?\nstage_a_xform_cache = UsdGeom.XformCache(0)\nstage_b_xform_cache = UsdGeom.XformCache(0)\nfor frame in range(1, 100):\n    stage_a_xform_cache.SetTime(frame)\n    car_xform = stage_a_xform_cache.GetLocalToWorldTransform(car_prim)\n    stage_b_xform_cache.SetTime(frame)\n    mike_xform = stage_b_xform_cache.GetLocalToWorldTransform(mike_prim)\n    mike_xform = mike_xform * car_xform.GetInverse()\n    mike_xform_op.Set(mike_xform, frame)\n# Let's enable the transform op now and disable the translate op\nmike_xformable.GetXformOpOrderAttr().Set([mike_xform_op.GetOpName()])\nstage_c = Usd.Stage.CreateInMemory()\n\n# Combine stages\nstage_c = Usd.Stage.CreateInMemory()\nlayer_a = stage_a.GetRootLayer()\nlayer_b = stage_b.GetRootLayer()\nUsdUtils.StitchLayers(layer_a, layer_b)\nstage_c.GetEditTarget().GetLayer().TransferContent(layer_a)\n#// ANCHOR_END: xformWorldSpaceLocalSpace\n\n#// ANCHOR: xformCache\nimport math\nfrom pxr import Gf,  Sdf, Usd, UsdGeom\nstage = Usd.Stage.CreateInMemory()\nroot_prim_path = Sdf.Path(\"/root\")\nroot_prim = stage.DefinePrim(root_prim_path, \"Xform\")\ncone_prim_path = Sdf.Path(\"/root/cone\")\ncone_prim = stage.DefinePrim(cone_prim_path, \"Cone\")\n# Set local transform of leaf prim\ncone_xformable = UsdGeom.Xformable(cone_prim)\ncone_translate_op = cone_xformable.AddTranslateOp(opSuffix=\"upAndDown\")\nfor frame in range(1, 100):\n    cone_translate_op.Set(Gf.Vec3h([5, math.sin(frame * 0.1) * 3, 0]), frame)\n# A transform is combined with its parent prims' transforms\nroot_xformable = UsdGeom.Xformable(root_prim)\nroot_rotate_op = root_xformable.AddRotateZOp(opSuffix= \"spinMeRound\")\nfor frame in range(1, 100):\n    root_rotate_op.Set(frame * 15, frame)\n# For single queries we can use the xformable API\nprint(cone_xformable.ComputeLocalToWorldTransform(Usd.TimeCode(15)))\n    \n## Xform Cache\n# Get: 'GetTime', 'ComputeRelativeTransform', 'GetLocalToWorldTransform', 'GetLocalTransformation', 'GetParentToWorldTransform'\n# Set: 'SetTime'\n# Clear: 'Clear'\nxform_cache = UsdGeom.XformCache(Usd.TimeCode(1))\nfor prim in stage.Traverse():\n    print(xform_cache.GetLocalToWorldTransform(prim))\n\"\"\"Returns:\n( (0.9659258262890683, 0.25881904510252074, 0, 0), (-0.25881904510252074, 0.9659258262890683, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) )\n( (0.9659258262890683, 0.25881904510252074, 0, 0), (-0.25881904510252074, 0.9659258262890683, 0, 0), (0, 0, 1, 0), (4.7520971567527654, 1.5834484942764433, 0, 1) )\n\"\"\"\nxform_cache = UsdGeom.XformCache(Usd.TimeCode(1))\nfor prim in stage.Traverse():\n    print(xform_cache.GetLocalTransformation(prim))\n\"\"\"Returns:\n(Gf.Matrix4d(0.9659258262890683, 0.25881904510252074, 0.0, 0.0,\n            -0.25881904510252074, 0.9659258262890683, 0.0, 0.0,\n            0.0, 0.0, 1.0, 0.0,\n            0.0, 0.0, 0.0, 1.0), False)\n(Gf.Matrix4d(1.0, 0.0, 0.0, 0.0,\n            0.0, 1.0, 0.0, 0.0,\n            0.0, 0.0, 1.0, 0.0,\n            5.0, 0.299560546875, 0.0, 1.0), False)\n\"\"\"\n#// ANCHOR_END: xformCache\n    \n#// ANCHOR: xformBake\nfrom pxr import Gf,  Sdf, Usd, UsdGeom\nstage = Usd.Stage.CreateInMemory()\n\n# Scene\ncar_prim_path = Sdf.Path(\"/set/stret/car\")\ncar_prim = stage.DefinePrim(car_prim_path, \"Xform\")\ncar_body_prim_path = Sdf.Path(\"/set/stret/car/body/hull\")\ncar_body_prim = stage.DefinePrim(car_body_prim_path, \"Cube\")\ncar_xformable = UsdGeom.Xformable(car_prim)\ncar_translate_op = car_xformable.AddTranslateOp(opSuffix=\"carDrivingDownStreet\")\nfor frame in range(1, 100):\n    car_translate_op.Set(Gf.Vec3h([frame, 0, 0]), frame)\n\n# Constraint Targets\nconstraint_prim_path = Sdf.Path(\"/constraints/car\")\nconstraint_prim = stage.DefinePrim(constraint_prim_path)\nconstraint_xformable = UsdGeom.Xformable(constraint_prim)\nconstraint_xformable.SetResetXformStack(True)\nconstraint_translate_op = constraint_xformable.AddTranslateOp(opSuffix=\"moveUp\")\nconstraint_translate_op.Set(Gf.Vec3h([0,5,0]))\nconstraint_transform_op = constraint_xformable.AddTransformOp(opSuffix=\"constraint\")\nxform_cache = UsdGeom.XformCache(Usd.TimeCode(0))\nfor frame in range(1, 100):\n    xform_cache.SetTime(Usd.TimeCode(frame))\n    xform = xform_cache.GetLocalToWorldTransform(car_body_prim)\n    constraint_transform_op.Set(xform, frame)\n\n# Constrain\nballoon_prim_path = Sdf.Path(\"/objects/balloon\")\nballoon_prim = stage.DefinePrim(balloon_prim_path, \"Sphere\")\nballoon_prim.GetAttribute(\"radius\").Set(2)\nballoon_prim.GetReferences().AddInternalReference(constraint_prim_path)\n#// ANCHOR_END: xformBake\n\n\n#// ANCHOR: xformFull\nimport math\nfrom pxr import Gf,  Sdf, Usd, UsdGeom\n#stage = Usd.Stage.CreateInMemory()\nroot_prim_path = Sdf.Path(\"/root\")\nroot_prim = stage.DefinePrim(root_prim_path, \"Xform\")\ncone_prim_path = Sdf.Path(\"/root/cone\")\ncone_prim = stage.DefinePrim(cone_prim_path, \"Cone\")\n\n# Set local transform of leaf prim\ncone_xformable = UsdGeom.Xformable(cone_prim)\ncone_translate_op = cone_xformable.AddTranslateOp(opSuffix=\"upAndDown\")\ncone_rotate_op = cone_xformable.AddRotateXYZOp(opSuffix= \"spinMeRound\")\nfor frame in range(1, 100):\n    cone_translate_op.Set(Gf.Vec3h([5, math.sin(frame * 0.1) * 3, 0]), frame)\n    #cone_rotate_op.Set(Gf.Vec3h([0, frame * 5, 0]), frame)\n# By clearing the xformOpOrder attribute, we keep the transforms, but don't apply it.\ncone_xformOpOrder_attr = cone_xformable.GetXformOpOrderAttr()\ncone_xformOpOrder_value = cone_xformOpOrder_attr.Get()\n#cone_xformable.ClearXformOpOrder()\n# Reverse the transform order\n#cone_xformOpOrder_attr.Set(cone_xformOpOrder_value[::-1])\n\ntime_code = Usd.TimeCode(1)\nprint(cone_xformable.ComputeLocalToWorldTransform(time_code))\n\"\"\"Returns:\n( (0.9961946980917455, 0, -0.08715574274765818, 0),\n  (0, 1, 0, 0), \n  (0.08715574274765818, 0, 0.9961946980917455, 0), \n  (4.9809734904587275, 0.4794921875, -0.4357787137382909, 1) )\n \"\"\"\n\n# A transform is combined with its parent prims' transforms\nroot_xformable = UsdGeom.Xformable(root_prim)\nroot_translate_op = root_xformable.AddTranslateOp(opSuffix=\"upAndDown\")\nroot_rotate_op = root_xformable.AddRotateZOp(opSuffix= \"spinMeRound\")\nfor frame in range(1, 100):\n    # root_translate_op.Set(Gf.Vec3h([5, math.sin(frame * 0.5), 0]), frame)\n    root_rotate_op.Set(frame * 15, frame)\n\n# We can also force our local transform to be the world transform (ignoring any parent xforms)\n#cone_xformable.SetResetXformStack(1)\n\n# When payloading prims, we want to write an extentsHint attribute to give a bbox hint\n# We can either query it via UsdGeom.BBoxCache or for individual prims via UsdGeom.Xformable.ComputeLocalToWorldTransform\nroot_geom_model_API =  UsdGeom.ModelAPI.Apply(root_prim)\nfor frame in range(1, 100):\n    bbox_cache = UsdGeom.BBoxCache(frame, [UsdGeom.Tokens.default_])\n    extentsHint = root_geom_model_API.ComputeExtentsHint(bbox_cache)\n    root_geom_model_API.SetExtentsHint(extentsHint , frame)\n#// ANCHOR_END: xformFull\n    \n"
  },
  {
    "path": "code/dcc/houdini.py",
    "content": "#// ANCHOR: houdiniCompositionInheritInstanceable\nfrom pxr import Gf, Sdf, Usd\nnode = hou.pwd()\nstage = node.editableStage()\npig_a_prim = stage.GetPrimAtPath(Sdf.Path(\"/pig_A\"))\n# Inspect prototype and collect what to override\nprototype = pig_a_prim.GetPrototype()\n# Create overrides\nclass_prim = stage.CreateClassPrim(Sdf.Path(\"/__CLASS__/pig\"))\nedit_prim = stage.DefinePrim(class_prim.GetPath().AppendPath(\"geo/shape\"))\nxform = Gf.Matrix4d()\nxform.SetTranslate([0, 2, 0])\nedit_prim.CreateAttribute(\"xformOpOrder\", Sdf.ValueTypeNames.TokenArray).Set([\"xformOp:transform:transform\"])\nedit_prim.CreateAttribute(\"xformOp:transform:transform\", Sdf.ValueTypeNames.Matrix4d).Set(xform)\n# Add inherits\ninstance_prims = prototype.GetInstances()\nfor instance_prim in instance_prims:\n    inherits_api = instance_prim.GetInherits()\n    # if instance_prim.GetName() == \"pig_B\":\n    #     continue\n    inherits_api.AddInherit(class_prim.GetPath(), position=Usd.ListPositionFrontOfAppendList)    \n#// ANCHOR_END: houdiniCompositionInheritInstanceable\n\n#// ANCHOR: houdiniTimeDependency\ndef GetValueMightBeTimeVarying(attribute, checkVariability=False):\n    \"\"\"Check if an attribute has time samples.\n    Args:\n        attribute (Usd.Attribute): The attribute to check.\n        checkVariability (bool): Preflight check if the time variability metadata is uniform,\n                                 if yes return False and don't check the value\n    Returns:\n        bool: The state if the attribute has time samples\n    \"\"\"\n    if checkVariability and attribute.GetVariability() == pxr.Sdf.VariabilityUniform:\n        return False\n    # Get the layer stack without value clips\n    property_stack = attribute.GetPropertyStack(pxr.Usd.TimeCode.Default())\n    if property_stack[0].layer.anonymous:\n        # It is fast to lookup data that is in memory\n        return attribute.GetNumTimeSamples() > 0\n    # Otherwise fallback to the default behaviour as this inspects only max two timeSamples\n    return attribute.ValueMightBeTimeVarying()\n#// ANCHOR_END: houdiniTimeDependency\n\n#// ANCHOR: houdiniFrustumCulling\nimport numpy as np\nfrom pxr import Gf, Sdf, Usd, UsdGeom\n\nstage_file_path = \"/path/to/your/stage\"\nstage = Usd.Open(stage_file_path)\n# Or\nimport hou\nstage = hou.pwd().editableStage()\n\ncamera_prim_path = Sdf.Path(\"/cameras/camera\")\ncamera_prim = stage.GetPrimAtPath(camera_prim_path)\nprim_paths = [Sdf.Path(\"/set/toys/instancer\")]\ntime_samples = list(range(1001, 1101))\n\n# Mode\nmode = \"average\" # \"frame\" or \"average\"\ndata = {}\n\nfor time_sample in time_samples:\n    time_code = Usd.TimeCode(time_sample)\n    # Get frustum\n    camera_type_API = UsdGeom.Camera(camera_prim)\n    camera_API = camera_type_API.GetCamera(time_code)\n    frustum = camera_API.frustum\n    # Manually override clipping planes\n    # frustum.SetNearFar(Gf.Range1d(0.01, 100000))\n    # Get bbox cache\n    bbox_cache = UsdGeom.BBoxCache(\n        time_code,\n        [\"default\", \"render\", \"proxy\", \"guide\"],\n        useExtentsHint=False,\n        ignoreVisibility=False\n    )\n    for prim_path in prim_paths:\n        prim = stage.GetPrimAtPath(prim_path)\n        # Skip inactive prims\n        if not prim.IsActive():\n            continue\n        # Skip non boundable prims\n        if not prim.IsA(UsdGeom.Boundable):\n            conitune\n        # Visibility\n        imageable_type_API = UsdGeom.Imageable(prim)\n        visibility_attr = imageable_type_API.GetVisibilityAttr()\n        # Poininstancer Prims\n        if prim.IsA(UsdGeom.PointInstancer):\n            pointinstancer_type_API = UsdGeom.PointInstancer(prim)\n            protoIndices_attr = pointinstancer_type_API.GetProtoIndicesAttr()\n            if not protoIndices_attr.HasValue():\n                continue\n            protoIndices_attr_len = len(protoIndices_attr.Get(time_sample))\n            bboxes = bbox_cache.ComputePointInstanceWorldBounds(\n                pointinstancer_type_API, list(range(protoIndices_attr_len))\n            )\n            # Calculate intersections\n            invisibleIds_attr_value = np.arange(protoIndices_attr_len)\n            for idx, bbox in enumerate(bboxes):\n                if frustum.Intersects(bbox):\n                    invisibleIds_attr_value[idx] = -1\n            # The invisibleIds can be written as a sparse attribute. The array length can differ\n            # from the protoIndices count. If an ids attribute exists, then it will use those \n            # indices, other wise it will use the protoIndices element index. Here we don't work\n            # with the ids attribute to keep the code example simple.\n            invisibleIds_attr_value = invisibleIds_attr_value[invisibleIds_attr_value != -1]\n            if len(invisibleIds_attr_value) == protoIndices_attr_len:\n                visibility_attr_value = UsdGeom.Tokens.invisible\n                invisibleIds_attr_value = []\n            else:\n                visibility_attr_value = UsdGeom.Tokens.inherited\n                invisibleIds_attr_value = invisibleIds_attr_value\n            # Apply averaged frame range value\n            if mode != \"frame\":        \n                data.setdefault(prim_path, {\"visibility\": [], \"invisibleIds\": [], \"invisibleIdsCount\": []})\n                data[prim_path][\"visibility\"].append(visibility_attr_value == UsdGeom.Tokens.inherited)\n                data[prim_path][\"invisibleIds\"].append(invisibleIds_attr_value)\n                data[prim_path][\"invisibleIdsCount\"].append(protoIndices_attr_len)\n                continue\n            # Apply value per frame\n            visibility_attr.Set(UsdGeom.Tokens.inherited, time_code)\n            invisibleIds_attr = pointinstancer_type_API.GetInvisibleIdsAttr()\n            invisibleIds_attr.Set(invisibleIds_attr_value, time_code)\n        else:\n            # Boundable Prims\n            bbox = bbox_cache.ComputeWorldBound(prim)\n            intersects = frustum.Intersects(bbox)\n            # Apply averaged frame range value\n            if mode != \"frame\":        \n                data.setdefault(prim_path, {\"visibility\": [], \"invisibleIds\": []})\n                data[prim_path][\"visibility\"].append(visibility_attr_value == UsdGeom.Tokens.inherited)\n                data[prim_path][\"invisibleIds\"].append(invisibleIds_attr_value)\n                continue\n            # Apply value per frame\n            visibility_attr.Set(UsdGeom.Tokens.inherited\n                                if intersects else UsdGeom.Tokens.invisible, time_code)\n                                \n# Apply averaged result\n# This won't work with changing point counts! If we want to implement this, we\n# have to map the indices to the 'ids' attribute value per frame.\nif mode == \"average\" and data:\n    for prim_path, visibility_data in data.items():\n        prim = stage.GetPrimAtPath(prim_path)\n        imageable_type_API = UsdGeom.Imageable(prim)#\n        visibility_attr = imageable_type_API.GetVisibilityAttr()\n        visibility_attr.Block()\n        # Pointinstancer Prims\n        if visibility_data.get(\"invisibleIds\"):\n            pointinstancer_type_API = UsdGeom.PointInstancer(prim)\n            invisibleIds_average = set(np.arange(max(visibility_data['invisibleIdsCount'])))\n            for invisibleIds in visibility_data.get(\"invisibleIds\"):\n                invisibleIds_average = invisibleIds_average.intersection(invisibleIds)\n            invisibleIds_attr = pointinstancer_type_API.GetInvisibleIdsAttr()\n            invisibleIds_attr.Set(np.array(sorted(invisibleIds_average)), time_code)\n            continue\n        # Boundable Prims\n        prim = stage.GetPrimAtPath(prim_path)\n        imageable_type_API = UsdGeom.Imageable(prim)\n        visibility_attr = imageable_type_API.GetVisibilityAttr()\n        visibility_attr.Block()\n        visibility_attr.Set(UsdGeom.Tokens.inherited if any(visibility_data[\"visibility\"]) else UsdGeom.Tokens.invisible)\n#// ANCHOR_END: houdiniFrustumCulling\n\n#// ANCHOR: houdiniPointsNativeStream\nimport numpy as np\nfrom pxr import UsdGeom\nsop_node = node.parm(\"spare_input0\").evalAsNode()\nsop_geo = sop_node.geometry()\n\nframe = hou.frame()\n\nprim = stage.DefinePrim(\"/points\", \"Points\")\nattribute_mapping = {\n    \"P\": \"points\",\n    \"id\": \"ids\",\n    \"pscale\": \"widths\",\n    \"Cd\": \"primvars:displayColor\",\n}\n# Import attributes\nfor sop_attr in sop_geo.pointAttribs():\n    attr_name = attribute_mapping.get(sop_attr.name())\n    if not attr_name:\n        continue\n    attr = prim.GetAttribute(attr_name)\n    if not attr:\n        continue\n    attr_type_name = attr.GetTypeName()\n    attr_type = attr_type_name.type\n    attr_class = attr_type.pythonClass\n    # The pointFloatAttribValuesAsString always gives us a float array\n    value = np.frombuffer(sop_geo.pointFloatAttribValuesAsString(sop_attr.name()), dtype=np.float32)\n    # This casts it back to its correct type\n    attr.Set(attr_class.FromNumpy(value), frame)\n    # Enforce \"vertex\" (Houdini speak \"Point\") interpolation\n    attr.SetMetadata(\"interpolation\", \"vertex\")\n# Re-Compute extent hints\nboundable_api = UsdGeom.Boundable(prim)\nextent_attr = boundable_api.GetExtentAttr()\nextent_value = UsdGeom.Boundable.ComputeExtentFromPlugins(boundable_api, frame)\nif extent_value:\n    extent_attr.Set(extent_value, frame)\n#// ANCHOR_END: houdiniPointsNativeStream\n\n#// ANCHOR: houdiniPointInstancerReorderTracker\nimport pxr\nnode = hou.pwd()\nlayer = node.editableLayer()\n\nref_node = node.parm(\"spare_input0\").evalAsNode()\nref_stage = ref_node.stage()\n\nwith pxr.Sdf.ChangeBlock():\n    for prim in ref_stage.TraverseAll():\n        prim_path = prim.GetPath()\n        if prim.IsA(pxr.UsdGeom.PointInstancer):\n            prim_spec = layer.GetPrimAtPath(prim_path)\n            # Attrs\n            prototypes = prim.GetRelationship(pxr.UsdGeom.Tokens.prototypes)\n            protoIndices_attr = prim.GetAttribute(pxr.UsdGeom.Tokens.protoIndices)\n            if not protoIndices_attr:\n                continue\n            if not protoIndices_attr.HasValue():\n                continue\n            protoTracker_attr_spec = pxr.Sdf.AttributeSpec(prim_spec, \"protoTracker\", pxr.Sdf.ValueTypeNames.StringArray)\n            layer.SetTimeSample(protoTracker_attr_spec.path, hou.frame(), [p.pathString for p in prototypes.GetForwardedTargets()])\n#// ANCHOR_END: houdiniPointInstancerReorderTracker\n\n#// ANCHOR: houdiniPointInstancerReorderPostProcess\nimport pxr\nimport numpy as np\nnode = hou.pwd()\nlayer = node.editableLayer()\n\n\nlayers = [layer]\n\ndef pointinstancer_prototypes_reorder(layers):\n    \"\"\"Rearrange the prototypes to be the actual value that they were written with\n    based on the 'protoTracker' attribute.\n    We need to do this because relationship attributes can't be animated,\n    which causes instancers with varying prototypes per frame to output wrong\n    prototypes once the scene is cached over the whole frame range.\n    \n    This assumes that the 'protoTracker' attribute has been written with the same\n    time sample count as the 'protoIndices' attribute. They will be matched by time\n    sample index.\n\n    Args:\n        layers (list): A list of pxr.Sdf.Layer objects that should be validated.\n                       It is up to the caller to call the layer.Save() command to\n                       commit the actual results of this function.\n                       \n    \"\"\"\n    \n    # Constants\n    protoTracker_attr_name = \"protoTracker\"\n    \n    # Collect all point instancer prototypes\n    instancer_prototype_mapping = {}\n\n    def collect_data_layer_traverse(path):\n        if not path.IsPrimPropertyPath():\n            return\n        if path.name != protoTracker_attr_name:\n            return\n        instancer_prim_path = path.GetPrimPath()\n        instancer_prototype_mapping.setdefault(instancer_prim_path, set())\n        time_samples = layer.ListTimeSamplesForPath(path)\n        if time_samples:\n            for timeSample in layer.ListTimeSamplesForPath(path):\n                prototype_prim_paths = layer.QueryTimeSample(path, timeSample)\n                instancer_prototype_mapping[instancer_prim_path].update(prototype_prim_paths)\n    \n    for layer in layers:\n        layer.Traverse(layer.pseudoRoot.path, collect_data_layer_traverse)\n    # Exit if not valid instancers were found\n    if not instancer_prototype_mapping:\n        return\n    # Combine prototype mapping data\n    for k, v in instancer_prototype_mapping.items():\n        instancer_prototype_mapping[k] = sorted(v)\n    # Apply combined targets\n    for layer in layers:\n        for instancer_prim_path, prototypes_prim_path_strs in instancer_prototype_mapping.items():\n            instancer_prim_spec = layer.GetPrimAtPath(instancer_prim_path)\n            if not instancer_prim_spec:\n                continue\n            protoTracker_attr_spec = layer.GetPropertyAtPath(\n                instancer_prim_path.AppendProperty(protoTracker_attr_name)\n            )\n            if not protoTracker_attr_spec:\n                continue\n            protoIndices_attr_spec = layer.GetPropertyAtPath(\n                instancer_prim_path.AppendProperty(pxr.UsdGeom.Tokens.protoIndices)\n            )\n            if not protoIndices_attr_spec:\n                continue\n            prototypes_rel_spec = layer.GetRelationshipAtPath(\n                instancer_prim_path.AppendProperty(pxr.UsdGeom.Tokens.prototypes)\n            )\n            if not prototypes_rel_spec:\n                continue\n            # Update prototypes\n            prototypes_prim_paths = [pxr.Sdf.Path(p) for p in prototypes_prim_path_strs]\n            prototypes_rel_spec.targetPathList.ClearEdits()\n            prototypes_rel_spec.targetPathList.explicitItems = prototypes_prim_paths\n            \n            # Here we just match the time sample by index, not by actual values\n            # as some times there are floating precision errors when time sample keys are written.\n            protoIndices_attr_spec_time_samples = layer.ListTimeSamplesForPath(\n                protoIndices_attr_spec.path\n            )\n            # Update protoIndices\n            for protoTracker_time_sample_idx, protoTracker_time_sample in enumerate(\n                layer.ListTimeSamplesForPath(protoTracker_attr_spec.path)\n            ):\n                # Reorder protoIndices\n                protoTracker_prim_paths = list(\n                    layer.QueryTimeSample(\n                        protoTracker_attr_spec.path,\n                        protoTracker_time_sample,\n                    )\n                )\n                # Skip if order already matches\n                if prototypes_prim_paths == protoTracker_prim_paths:\n                    continue\n\n                prototype_order_mapping = {}\n                for protoTracker_idx, protoTracker_prim_path in enumerate(protoTracker_prim_paths):\n                    prototype_order_mapping[protoTracker_idx] = prototypes_prim_paths.index(\n                        protoTracker_prim_path\n                    )\n                # Re-order protoIndices via numpy (Remapping via native Python is slow).\n                source_value = np.array(\n                    layer.QueryTimeSample(\n                        protoIndices_attr_spec.path,\n                        protoIndices_attr_spec_time_samples[protoTracker_time_sample_idx],\n                    ),\n                    dtype=int,\n                )\n                destination_value = np.copy(source_value)\n                for k in sorted(prototype_order_mapping.keys(), reverse=True):\n                    destination_value[source_value == k] = prototype_order_mapping[k]\n                layer.SetTimeSample(\n                    protoIndices_attr_spec.path,\n                    protoIndices_attr_spec_time_samples[protoTracker_time_sample_idx],\n                    destination_value,\n                )\n                # Force deallocate\n                del source_value\n                del destination_value\n                # Update protoTracker attribute to reflect changes, allowing\n                # this function to be run multiple times.\n                layer.SetTimeSample(\n                    protoTracker_attr_spec.path,\n                    protoTracker_time_sample,\n                    pxr.Vt.StringArray(prototypes_prim_path_strs),\n                )\n\npointinstancer_prototypes_reorder(layers)\n#// ANCHOR_END: houdiniPointInstancerReorderPostProcess\n\n#// ANCHOR: houdiniPointInstancerNativeStream\nimport pxr\nnode = hou.pwd()\nlayer = node.editableLayer()\n\nref_node = node.parm(\"spare_input0\").evalAsNode()\nref_stage = ref_node.stage()\n\ntime_code = pxr.Usd.TimeCode.Default() if not ref_node.isTimeDependent() else pxr.Usd.TimeCode(hou.frame())\n\nwith pxr.Sdf.ChangeBlock():\n    edit = pxr.Sdf.BatchNamespaceEdit()\n    for prim in ref_stage.TraverseAll():\n        prim_path = prim.GetPath()\n        if prim.IsA(pxr.UsdGeom.Points):\n            prim_spec = layer.GetPrimAtPath(prim_path)\n            # Prim\n            prim_spec.typeName = \"PointInstancer\"\n            purpose_attr_spec = pxr.Sdf.AttributeSpec(prim_spec, pxr.UsdGeom.Tokens.purpose, pxr.Sdf.ValueTypeNames.Token)\n            # Rels\n            protoTracker_attr = prim.GetAttribute(\"protoTracker\")\n            protoHash_attr = prim.GetAttribute(\"protoHash\")\n            if protoTracker_attr and protoTracker_attr.HasValue():\n                protoTracker_prim_paths = [pxr.Sdf.Path(p) for p in protoTracker_attr.Get(time_code)]\n                prototypes_rel_spec = pxr.Sdf.RelationshipSpec(prim_spec, pxr.UsdGeom.Tokens.prototypes)\n                prototypes_rel_spec.targetPathList.explicitItems = protoTracker_prim_paths\n                # Cleanup\n                edit.Add(prim_path.AppendProperty(\"protoTracker:indices\"), pxr.Sdf.Path.emptyPath)\n                edit.Add(prim_path.AppendProperty(\"protoTracker:lengths\"), pxr.Sdf.Path.emptyPath)\n            elif protoHash_attr and protoHash_attr.HasValue():\n                protoHash_pairs = [i.split(\"|\") for i in protoHash_attr.Get(time_code)]\n                protoTracker_prim_paths = [pxr.Sdf.Path(v) for k, v in protoHash_pairs if k == prim_path]\n                prototypes_rel_spec = pxr.Sdf.RelationshipSpec(prim_spec, pxr.UsdGeom.Tokens.prototypes)\n                prototypes_rel_spec.targetPathList.explicitItems = protoTracker_prim_paths\n                protoTracker_attr_spec = pxr.Sdf.AttributeSpec(prim_spec, \"protoTracker\", pxr.Sdf.ValueTypeNames.StringArray)\n                layer.SetTimeSample(protoTracker_attr_spec.path, hou.frame(), [p.pathString for p in protoTracker_prim_paths])\n                # Cleanup\n                edit.Add(prim_path.AppendProperty(\"protoHash\"), pxr.Sdf.Path.emptyPath)\n                edit.Add(prim_path.AppendProperty(\"protoHash:indices\"), pxr.Sdf.Path.emptyPath)\n                edit.Add(prim_path.AppendProperty(\"protoHash:lengths\"), pxr.Sdf.Path.emptyPath)\n            # Children\n            Prototypes_prim_spec = pxr.Sdf.CreatePrimInLayer(layer, prim_path.AppendChild(\"Prototypes\"))\n            Prototypes_prim_spec.typeName = \"Scope\"\n            Prototypes_prim_spec.specifier = pxr.Sdf.SpecifierDef\n            \n            # Rename\n            edit.Add(prim_path.AppendProperty(pxr.UsdGeom.Tokens.points),\n                     prim_path.AppendProperty(pxr.UsdGeom.Tokens.positions))\n\n    if not layer.Apply(edit):\n        raise Exception(\"Failed to modify layer!\")\n#// ANCHOR: houdiniPointInstancerNativeStream"
  },
  {
    "path": "code/production/caches.py",
    "content": "#// ANCHOR: stageQueryAttribute\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nprim = stage.DefinePrim(Sdf.Path(\"/cube\"), \"Cube\")\n\nsize_attr = prim.GetAttribute(\"size\")\nfor frame in range(10000):\n    size_attr.Set(frame, frame)\n\nattr_query = Usd.AttributeQuery(prim, \"size\")\nprint(attr_query.Get(1001)) # Returns 2.0\n\nfrom pxr import Tf\n# Attribute\nsw = Tf.Stopwatch()\nsw.Start()\nfor frame in range(10000):\n    size_attr.Get(frame)\nsw.Stop()\nprint(sw.milliseconds) # Returns: 14\nsw.Reset()\n# Attribute Query\nsw = Tf.Stopwatch()\nsw.Start()\nfor frame in range(10000):\n    attr_query.Get(frame)\nsw.Stop()\nprint(sw.milliseconds) # Returns: 7\nsw.Reset()\n#// ANCHOR_END: stageQueryAttribute\n\n#// ANCHOR: stageQueryInheritedPrimvars\nfrom pxr import Sdf, Usd, UsdGeom\nstage = Usd.Stage.CreateInMemory()\nbicycle_prim = stage.DefinePrim(Sdf.Path(\"/set/garage/bicycle\"), \"Cube\")\ncar_prim = stage.DefinePrim(Sdf.Path(\"/set/garage/car\"), \"Cube\")\nset_prim = stage.GetPrimAtPath(\"/set\")\ngarage_prim = stage.GetPrimAtPath(\"/set/garage\")\ntractor_prim = stage.DefinePrim(Sdf.Path(\"/set/yard/tractor\"), \"Cube\")\n\"\"\"Hierarchy\n/set\n/set/garage\n/set/garage/bicycle\n/set/garage/car\n/set/yard\n/set/yard/tractor\n\"\"\"\n\n# Setup hierarchy primvars\nprimvar_api = UsdGeom.PrimvarsAPI(set_prim)\nsize_primvar = primvar_api.CreatePrimvar(\"size\", Sdf.ValueTypeNames.Float)\nsize_primvar.Set(10)\nprimvar_api = UsdGeom.PrimvarsAPI(garage_prim)\nsize_primvar = primvar_api.CreatePrimvar(\"size\", Sdf.ValueTypeNames.Float)\nsize_primvar.Set(5)\nsize_primvar = primvar_api.CreatePrimvar(\"point_scale\", Sdf.ValueTypeNames.Float)\nsize_primvar.Set(9000)\nprimvar_api = UsdGeom.PrimvarsAPI(bicycle_prim)\nsize_primvar = primvar_api.CreatePrimvar(\"size\", Sdf.ValueTypeNames.Float)\nsize_primvar.Set(2.5)\n\n# High performance primvar check with our own cache\nprimvar_stack = [{}]\niterator = iter(Usd.PrimRange.PreAndPostVisit(stage.GetPseudoRoot()))\nfor prim in iterator:\n    primvar_api = UsdGeom.PrimvarsAPI(prim)\n    if not iterator.IsPostVisit():\n        before_hash = hex(id(primvar_stack[-1]))\n        parent_primvars = primvar_stack[-1]\n        authored_primvars = {p.GetPrimvarName(): p for p in primvar_api.GetPrimvarsWithAuthoredValues()} \n        if authored_primvars and parent_primvars:\n            combined_primvars = {name: p for name, p in parent_primvars.items()}\n            combined_primvars.update(authored_primvars)\n            primvar_stack.append(combined_primvars)\n        elif authored_primvars:\n            primvar_stack.append(authored_primvars)\n        else:\n            primvar_stack.append(parent_primvars)\n        after_hash = hex(id(primvar_stack[-1]))\n        print(before_hash, after_hash, prim.GetPath(), [p.GetAttr().GetPath().pathString for p in primvar_stack[-1].values()], len(primvar_stack))\n    else:\n        primvar_stack.pop(-1)\n# Returns:\n\"\"\"\n0x7fea12b349c0 0x7fea12b349c0 / [] 2\n0x7fea12b349c0 0x7fea12b349c0 /HoudiniLayerInfo [] 3\n0x7fea12b349c0 0x7fea12bfe980 /set ['/set.primvars:size'] 3\n0x7fea12bfe980 0x7fea12a89600 /set/garage ['/set/garage.primvars:size', '/set/garage.primvars:point_scale'] 4\n0x7fea12a89600 0x7fea367b87c0 /set/garage/bicycle ['/set/garage/bicycle.primvars:size', '/set/garage.primvars:point_scale'] 5\n0x7fea12a89600 0x7fea12a89600 /set/garage/car ['/set/garage.primvars:size', '/set/garage.primvars:point_scale'] 5\n0x7fea12bfe980 0x7fea12bfe980 /set/yard ['/set.primvars:size'] 4\n0x7fea12bfe980 0x7fea12bfe980 /set/yard/tractor ['/set.primvars:size'] 5\n\"\"\"\n#// ANCHOR_END: stageQueryInheritedPrimvars\n\n#// ANCHOR: stageQueryMaterialBinding\nfrom pxr import Sdf, Usd, UsdGeom, UsdShade\nstage = Usd.Stage.CreateInMemory()\n# Leaf prims\ncube_prim = stage.DefinePrim(Sdf.Path(\"/root/RENDER/pointy/cube\"), \"Cube\")\nsphere_prim = stage.DefinePrim(Sdf.Path(\"/root/RENDER/round_grp/sphere\"), \"Sphere\")\ncylinder_prim = stage.DefinePrim(Sdf.Path(\"/root/RENDER/round_grp/cylinder\"), \"Cylinder\")\nround_grp_prim = sphere_prim.GetParent()\nmaterial_prim = stage.DefinePrim(Sdf.Path(\"/root/MATERIALS/example_material\"), \"Material\")\n# Parent prims\nfor prim in stage.Traverse():\n    if prim.GetName() not in (\"cube\", \"sphere\", \"cylinder\", \"example_material\"):\n        prim.SetTypeName(\"Xform\")\n\n# Bind materials via direct binding\nmaterial = UsdShade.Material(material_prim)\n# Bind parent group\nmat_bind_api = UsdShade.MaterialBindingAPI.Apply(round_grp_prim)\nmat_bind_api.Bind(material)\n# Bind leaf prim\nmat_bind_api = UsdShade.MaterialBindingAPI.Apply(cube_prim)\nmat_bind_api.Bind(material)\n\n# Query material bindings\nmaterials, relationships = UsdShade.MaterialBindingAPI.ComputeBoundMaterials([cube_prim, sphere_prim, cylinder_prim])\nfor material, relationship in zip(materials, relationships):\n    print(material.GetPath(), relationship.GetPath())\n\"\"\"Returns\n/root/MATERIALS/example_material /root/RENDER/pointy/cube.material:binding\n/root/MATERIALS/example_material /root/RENDER/round_grp.material:binding\n/root/MATERIALS/example_material /root/RENDER/round_grp.material:binding\n\"\"\"\n#// ANCHOR_END: stageQueryMaterialBinding\n\n\n#// ANCHOR: stageQueryTransform\nimport math\nfrom pxr import Gf,  Sdf, Usd, UsdGeom\nstage = Usd.Stage.CreateInMemory()\nroot_prim_path = Sdf.Path(\"/root\")\nroot_prim = stage.DefinePrim(root_prim_path, \"Xform\")\ncone_prim_path = Sdf.Path(\"/root/cone\")\ncone_prim = stage.DefinePrim(cone_prim_path, \"Cone\")\n# Set local transform of leaf prim\ncone_xformable = UsdGeom.Xformable(cone_prim)\ncone_translate_op = cone_xformable.AddTranslateOp(opSuffix=\"upAndDown\")\nfor frame in range(1, 100):\n    cone_translate_op.Set(Gf.Vec3h([5, math.sin(frame * 0.1) * 3, 0]), frame)\n# A transform is combined with its parent prims' transforms\nroot_xformable = UsdGeom.Xformable(root_prim)\nroot_rotate_op = root_xformable.AddRotateZOp(opSuffix= \"spinMeRound\")\nfor frame in range(1, 100):\n    root_rotate_op.Set(frame * 15, frame)\n# For single queries we can use the xformable API\nprint(cone_xformable.ComputeLocalToWorldTransform(Usd.TimeCode(15)))\n    \n## Xform Cache\n# For batched queries, we should always use the xform cache, to avoid recomputing parent xforms.\n# Get: 'GetTime', 'ComputeRelativeTransform', 'GetLocalToWorldTransform', 'GetLocalTransformation', 'GetParentToWorldTransform'\n# Set: 'SetTime'\n# Clear: 'Clear'\nxform_cache = UsdGeom.XformCache(Usd.TimeCode(1))\nfor prim in stage.Traverse():\n    print(\"Worldspace Transform\", xform_cache.GetLocalToWorldTransform(prim))\n    print(\"Localspace Transform\", xform_cache.GetLocalTransformation(prim))\n#// ANCHOR_END: stageQueryTransform\n\n\n#// ANCHOR: stageQueryBBox\nfrom pxr import Gf,  Sdf, Usd, UsdGeom, Vt\nstage = Usd.Stage.CreateInMemory()\n# Setup scene\nroot_prim_path = Sdf.Path(\"/root\")\nroot_prim = stage.DefinePrim(root_prim_path, \"Xform\")\ncone_prim_path = Sdf.Path(\"/root/cone\")\ncone_prim = stage.DefinePrim(cone_prim_path, \"Cone\")\n\nroot_xformable = UsdGeom.Xformable(root_prim)\nroot_translate_op = root_xformable.AddTranslateOp()\nroot_translate_op.Set(Gf.Vec3h([50, 30, 10]))\nroot_rotate_op = root_xformable.AddRotateZOp()\nroot_rotate_op.Set(45)\n\ncone_xformable = UsdGeom.Xformable(cone_prim)\ncone_translate_op = cone_xformable.AddTranslateOp()\ncone_rotate_op = cone_xformable.AddRotateXYZOp()\n\n## UsdGeom.BBoxCache()\n# Get: 'GetTime', 'GetIncludedPurposes',  'GetUseExtentsHint',\n# Set: 'SetTime', 'SetIncludedPurposes',\n# Clear: 'Clear'\n\n# Compute: 'ComputeWorldBound', 'ComputeLocalBound', 'ComputeRelativeBound', 'ComputeUntransformedBound', \n# Compute Instances: 'ComputePointInstanceWorldBound', 'ComputePointInstanceWorldBounds',\n#                    'ComputePointInstanceLocalBound',  'ComputePointInstanceLocalBounds',\n#                    'ComputePointInstanceRelativeBound', 'ComputePointInstanceRelativeBounds',\n#                    'ComputePointInstanceUntransformedBounds', 'ComputePointInstanceUntransformedBound'\ntime_code = Usd.TimeCode(1) # Determine frame to lookup\nbbox_cache = UsdGeom.BBoxCache(time_code, [UsdGeom.Tokens.default_, UsdGeom.Tokens.render],\n                               useExtentsHint=False, ignoreVisibility=False)\n# Useful for intersection testing:\nbbox = bbox_cache.ComputeWorldBound(cone_prim)\nprint(bbox) # Returns: [([(-1, -1, -1)...(1, 1, 1)]) (( (0.7071067811865475, 0.7071067811865476, 0, 0), (-0.7071067811865476, 0.7071067811865475, 0, 0), (0, 0, 1, 0), (50, 30, 10, 1) )) false]\n# When payloading prims, we want to write an extentsHint attribute to give a bbox hint\n# We can either query it via UsdGeom.BBoxCache or for individual prims via UsdGeom.Xformable.ComputeExtentsHint\nroot_geom_model_API = UsdGeom.ModelAPI.Apply(root_prim)\nextentsHint = root_geom_model_API.ComputeExtentsHint(bbox_cache)\nroot_geom_model_API.SetExtentsHint(extentsHint, time_code)\n# Or\nbbox = bbox_cache.ComputeUntransformedBound(root_prim)\naligned_range = bbox.ComputeAlignedRange()\nextentsHint = Vt.Vec3hArray([Gf.Vec3h(list(aligned_range.GetMin())), Gf.Vec3h(list(aligned_range.GetMax()))])\nroot_geom_model_API.SetExtentsHint(extentsHint, time_code)\n#// ANCHOR_END: stageQueryBBox"
  },
  {
    "path": "code/production/production.py",
    "content": "#// ANCHOR: productionConceptsSdfBatchNamespaceMoveRenameDelete\n### High Level / Low Level ###\n# The Sdf.BatchNamespaceEdit() always runs only on an individual layer.\nfrom pxr import Gf, Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nlayer = stage.GetEditTarget().GetLayer()\nbicycle_prim_path = Sdf.Path(\"/bicycle\")\nbicycle_prim = stage.DefinePrim(bicycle_prim_path, \"Xform\")\nbicycle_color_attr = bicycle_prim.CreateAttribute(\"color\", Sdf.ValueTypeNames.Color3h)\nbicycle_color_attr.Set(Gf.Vec3h([0,1,2]))\ncar_prim_path = Sdf.Path(\"/car\")\ncar_prim = stage.DefinePrim(car_prim_path, \"Xform\")\nsoccer_ball_prim_path = Sdf.Path(\"/soccer_ball\")\nsoccer_ball_prim = stage.DefinePrim(soccer_ball_prim_path, \"Xform\")\nsoccer_ball_player_rel = soccer_ball_prim.CreateRelationship(\"player\")\nsoccer_ball_player_rel.SetTargets([Sdf.Path(\"/players/mike\")])\n\nprint(layer.ExportToString())\n\"\"\"Returns:\n#usda 1.0\n\ndef Xform \"bicycle\"\n{\n    custom color3h color = (0, 1, 2)\n}\n\ndef Xform \"car\"\n{\n}\n\ndef Xform \"soccer_ball\"\n{\n    custom rel player = </players/mike>\n}\n\"\"\"\nwith Sdf.ChangeBlock():\n    edit = Sdf.BatchNamespaceEdit()\n    ## Important: Edits are run in the order they are added.\n    # If we try to move and then remove, it will error.\n    ## Prim Specs\n    # Remove\n    edit.Add(car_prim_path, Sdf.Path.emptyPath)\n    # Move\n    edit.Add(bicycle_prim_path, car_prim_path)\n    # Rename\n    basket_ball_prim_path = soccer_ball_prim_path.ReplaceName(\"basket_ball\")\n    edit.Add(soccer_ball_prim_path, basket_ball_prim_path)\n    ## Property Specs\n    edit.Add(car_prim_path.AppendProperty(\"color\"), car_prim_path.AppendProperty(\"style\"))\n    soccer_ball_player_rel_path = basket_ball_prim_path.AppendProperty(\"player\")\n    edit.Add(soccer_ball_player_rel_path, soccer_ball_player_rel_path.ReplaceName(\"people\"))\n    \n    # We can als \n    if not layer.Apply(edit):\n        raise Exception(\"Failed to apply layer edit!\")\n        \nprint(layer.ExportToString())\n\"\"\"Returns:\n#usda 1.0\ndef Xform \"car\"\n{\n    custom color3h style = (0, 1, 2)\n}\n\ndef Xform \"basket_ball\"\n{\n    custom rel people = </players/mike>\n}\n\"\"\"\n#// ANCHOR_END: productionConceptsSdfBatchNamespaceMoveRenameDelete\n\n\n#// ANCHOR: productionConceptsSdfBatchNamespaceEditVariant\n### High Level / Low Level ###\n# The Sdf.BatchNamespaceEdit() always runs only on an individual layer.\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nprim_path = Sdf.Path(\"/bicycle\")\nprim = stage.DefinePrim(prim_path, \"Xform\")\nstage.DefinePrim(Sdf.Path(\"/bicycle/cube\"), \"Cube\")\n\nlayer = stage.GetEditTarget().GetLayer()\nwith Sdf.ChangeBlock():\n    edit = Sdf.BatchNamespaceEdit()\n    prim_spec = layer.GetPrimAtPath(prim_path)\n    # Move content into variant\n    variant_set_spec = Sdf.VariantSetSpec(prim_spec, \"model\")\n    variant_spec = Sdf.VariantSpec(variant_set_spec, \"myCoolVariant\")\n    variant_prim_path = prim_path.AppendVariantSelection(\"model\", \"myCoolVariant\")\n    edit.Add(prim_path.AppendChild(\"cube\"), variant_prim_path.AppendChild(\"cube\"))\n    # Variant selection\n    prim_spec.SetInfo(\"variantSetNames\", Sdf.StringListOp.Create(prependedItems=[\"model\"]))\n    prim_spec.variantSelections[\"model\"] = \"myCoolVariant\"\n        \n    if not layer.Apply(edit):\n        raise Exception(\"Failed to apply layer edit!\")\n#// ANCHOR_END: productionConceptsSdfBatchNamespaceEditVariant\n\n\n#// ANCHOR: productionConceptsSdfCopySpecStandard\n### High Level / Low Level ###\n# The Sdf.BatchNamespaceEdit() always runs only on an individual layer.\nfrom pxr import Gf, Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nlayer = stage.GetEditTarget().GetLayer()\nbicycle_prim_path = Sdf.Path(\"/bicycle\")\nbicycle_prim = stage.DefinePrim(bicycle_prim_path, \"Xform\")\nbicycle_color_attr = bicycle_prim.CreateAttribute(\"color\", Sdf.ValueTypeNames.Color3h)\nbicycle_color_attr.Set(Gf.Vec3h([0,1,2]))\ncar_prim_path = Sdf.Path(\"/car\")\ncar_prim = stage.DefinePrim(car_prim_path, \"Xform\")\nsoccer_ball_prim_path = Sdf.Path(\"/soccer_ball\")\nsoccer_ball_prim = stage.DefinePrim(soccer_ball_prim_path, \"Xform\")\nsoccer_ball_player_rel = soccer_ball_prim.CreateRelationship(\"player\")\nsoccer_ball_player_rel.SetTargets([Sdf.Path(\"/players/mike\")])\n\nprint(layer.ExportToString())\n\"\"\"Returns:\n#usda 1.0\ndef Xform \"bicycle\"\n{\n    custom color3h color = (0, 1, 2)\n}\n\ndef Xform \"car\"\n{\n}\n\ndef Xform \"soccer_ball\"\n{\n    custom rel player = </players/mike>\n}\n\"\"\"\n# When copying data, the target prim spec will be replaced by the source prim spec.\n# The data will not be averaged\nwith Sdf.ChangeBlock():\n    # Copy Prim Spec\n    Sdf.CopySpec(layer, soccer_ball_prim_path, layer, car_prim_path.AppendChild(\"soccer_ball\"))\n    # Copy Property\n    Sdf.CopySpec(layer, bicycle_color_attr.GetPath(), layer, car_prim_path.AppendChild(\"soccer_ball\").AppendProperty(\"color\"))\nprint(layer.ExportToString())\n\"\"\"Returns:\n#usda 1.0\ndef Xform \"bicycle\"\n{\n    custom color3h color = (0, 1, 2)\n}\n\ndef Xform \"car\"\n{\n    def Xform \"soccer_ball\"\n    {\n        custom color3h color = (0, 1, 2)\n        custom rel player = </players/mike>\n    }\n}\n\ndef Xform \"soccer_ball\"\n{\n    custom rel player = </players/mike>\n}\n\"\"\"\n#// ANCHOR_END: productionConceptsSdfCopySpecStandard\n\n\n#// ANCHOR: productionConceptsSdfCopySpecVariant\n### High Level / Low Level ###\n# The Sdf.CopySpec() always runs on individual layers.\nfrom pxr import Sdf, Usd\nstage = Usd.Stage.CreateInMemory()\nbicycle_prim_path = Sdf.Path(\"/bicycle\")\nbicycle_prim = stage.DefinePrim(bicycle_prim_path, \"Xform\")\ncube_prim_path = Sdf.Path(\"/cube\")\ncube_prim = stage.DefinePrim(cube_prim_path, \"Cube\")\n\nlayer = stage.GetEditTarget().GetLayer()\nwith Sdf.ChangeBlock():\n    edit = Sdf.BatchNamespaceEdit()\n    prim_spec = layer.GetPrimAtPath(bicycle_prim_path)\n    # Copy content into variant\n    variant_set_spec = Sdf.VariantSetSpec(prim_spec, \"model\")\n    variant_spec = Sdf.VariantSpec(variant_set_spec, \"myCoolVariant\")\n    variant_prim_path = bicycle_prim_path.AppendVariantSelection(\"model\", \"myCoolVariant\")\n    Sdf.CopySpec(layer, cube_prim_path, layer, variant_prim_path.AppendChild(\"cube\"))\n    # Variant selection\n    prim_spec.SetInfo(\"variantSetNames\", Sdf.StringListOp.Create(prependedItems=[\"model\"]))\n    prim_spec.variantSelections[\"model\"] = \"myCoolVariant\"\nprint(layer.ExportToString())\n\"\"\"Returns:\n#usda 1.0\n\ndef Xform \"bicycle\" (\n    variants = {\n        string model = \"myCoolVariant\"\n    }\n    prepend variantSets = \"model\"\n)\n{\n    variantSet \"model\" = {\n        \"myCoolVariant\" {\n            def Cube \"cube\"\n            {\n            }\n\n        }\n    }\n}\n\ndef Cube \"cube\"\n{\n}\n\"\"\"\n#// ANCHOR_END: productionConceptsSdfCopySpecVariant\n\n\n\n#// ANCHOR: productionConceptsSdfChangeBlock\nfrom pxr import Sdf, Tf, Usd\ndef callback(notice, sender):\n    print(\"Changed Paths\", notice.GetResyncedPaths())\nstage = Usd.Stage.CreateInMemory()\n# Add\nlistener = Tf.Notice.Register(Usd.Notice.ObjectsChanged, callback, stage)\n# Edit\nlayer = stage.GetEditTarget().GetLayer()\nfor idx in range(5):\n    Sdf.CreatePrimInLayer(layer, Sdf.Path(f\"/test_{idx}\"))\n# Remove\nlistener.Revoke()\n# Returns:\n\"\"\"\nChanged Paths [Sdf.Path('/test_0')]\nChanged Paths [Sdf.Path('/test_1')]\nChanged Paths [Sdf.Path('/test_2')]\nChanged Paths [Sdf.Path('/test_3')]\nChanged Paths [Sdf.Path('/test_4')]\n\"\"\"\nstage = Usd.Stage.CreateInMemory()\n# Add\nlistener = Tf.Notice.Register(Usd.Notice.ObjectsChanged, callback, stage)\nwith Sdf.ChangeBlock():\n    # Edit\n    layer = stage.GetEditTarget().GetLayer()\n    for idx in range(5):\n        Sdf.CreatePrimInLayer(layer, Sdf.Path(f\"/test_{idx}\"))\n# Remove\nlistener.Revoke()\n# Returns:\n# Changed Paths [Sdf.Path('/test_0'), Sdf.Path('/test_1'), Sdf.Path('/test_2'), Sdf.Path('/test_3'), Sdf.Path('/test_4')]\n#// ANCHOR_END: productionConceptsSdfChangeBlock"
  },
  {
    "path": "code/test.py",
    "content": "#// ANCHOR: example\ndef example():\n    print(\"example\")\n#// ANCHOR_END: example\n\n\"\"\"\nNotes:\nAn abstract explanation of Usd could also be:\n- A rule based merging of dictionaries\n- Or if you are coming from IT, it is a like a layer based file system on with a rich features set on top.\n\n- Scene Retimes/Freeze\n    - Currently nternal refernce receive double offest (which makes sense, as they live refer to a layer)\n- Purpose Swapping for preview, bake point color for preview\n\n- time freeze --> How to hack the dependency frame eval Subframe caching in hudini\n\"\"\""
  },
  {
    "path": "docs/book.toml",
    "content": "[book]\nauthors = [\"Luca Scheller\"]\nlanguage = \"en\"\nmultilingual = false\nsrc = \"src\"\ntitle = \"Usd Survival Guide\"\ndescription = \"This repository holds the docs and examples for the Usd Survival Guide.\"\n\n[build]\nbuild-dir = \"book\"\ncreate-missing = false\n\n[preprocessor.admonish]\ncommand = \"mdbook-admonish\"\nassets_version = \"2.0.1\" # do not edit: managed by `mdbook-admonish install`\n\n[preprocessor.mermaid]\ncommand = \"mdbook-mermaid\"\n\n[output.html]\ndefault-theme = \"ayu\"\ninput-404 = \"not-found.md\"\ngit-repository-url = \"https://github.com/LucaScheller/VFX-UsdSurvivalGuide\"\ngit-repository-icon = \"fa-github\"\nedit-url-template = \"https://github.com/LucaScheller/VFX-UsdSurvivalGuide/edit/main/docs/{path}\"\nadditional-css = [\"theme/ext/css/custom.css\", \"theme/ext/css/mdbook-admonish.css\"]\nadditional-js = [\"theme/ext/js/mermaid.min.js\", \"theme/ext/js/mermaid-init.js\", \"theme/ext/js/custom.js\"]\nline-numbers = true\n\n[output.html.fold]\nenable = true\nlevel = 1\n\n[output.html.playground]\neditable = false\ncopyable = true\nline-numbers = true\nshow-line-numbers = true\n\n[output.html.print]\npage-break = true\n\n[output.html.redirect]\n\"introduction/overview.html\" = \"../index.html\"\n\"introduction/motivation.html\" = \"../pages/introduction/motivation.html\"\n\"introduction/structure.html\" = \"../pages/introduction/structure.html\"\n\"introduction/docs.html\" = \"../pages/introduction/docs.html\"\n\"introduction/future.html\" = \"../pages/introduction/future.html\"\n\"core/overview.html\" = \"../pages/core/overview.html\"\n\"core/api.html\" = \"../pages/core/api.html\"\n\"core/elements/overview.html\" = \"../../pages/core/elements/overview.html\"\n\"core/elements/path.html\" = \"../../pages/core/elements/path.html\"\n\"core/elements/data_container.html\" = \"../../pages/core/elements/data_container.html\"\n\"core/elements/prim.html\" = \"../../pages/core/elements/prim.html\"\n\"core/elements/property.html\" = \"../../pages/core/elements/property.html\"\n\"core/elements/data_type.html\" = \"../../pages/core/elements/data_type.html\"\n\"core/elements/schemas.html\" = \"../../pages/core/elements/schemas.html\"\n\"core/elements/metadata.html\"= \"../../pages/core/elements/metadata.html\"\n\"core/elements/layer.html\" = \"../../pages/core/elements/layer.html\"\n\"core/elements/loading_mechanisms.html\" = \"../../pages/core/elements/loading_mechanisms.html\"\n\"core/elements/animation.html\" = \"../../pages/core/elements/animation.html\"\n\"core/elements/materials.html\" = \"../../pages/core/elements/materials.html\"\n\"core/elements/transform.html\" = \"../../pages/core/elements/transform.html\"\n\"core/elements/collection.html\" = \"../../pages/core/elements/collection.html\"\n\"core/elements/notice.html\" = \"../../pages/core/elements/notice.html\"\n\"core/elements/standalone_utilities.html\" = \"../../pages/core/elements/standalone_utilities.html\"\n\"core/composition/overview.html\" = \"../../pages/core/composition/overview.html\"\n\"core/composition/fundamentals.html\" = \"../../pages/core/composition/fundamentals.html\"\n\"core/composition/arcs.html\" = \"../../pages/core/composition/arcs.html\"\n\"core/composition/livrps.html\" = \"../../pages/core/composition/livrps.html\"\n\"core/composition/listeditableops.html\" = \"../../pages/core/composition/listeditableops.html\"\n\"core/composition/pcp.html\" = \"../../pages/core/composition/pcp.html\"\n\"core/plugins/overview.html\" = \"../../pages/core/plugins/overview.html\"\n\"core/plugins/kind.html\" = \"../../pages/core/plugins/kind.html\"\n\"core/plugins/metadata.html\" = \"../../pages/core/plugins/metadata.html\"\n\"core/plugins/schemas.html\" = \"../../pages/core/plugins/schemas.html\"\n\"core/plugins/assetresolver.html\" = \"../../pages/core/plugins/assetresolver.html\"\n\"core/profiling/overview.html\" = \"../../pages/core/profiling/overview.html\"\n\"core/profiling/debug.html\" = \"../../pages/core/profiling/debug.html\"\n\"core/profiling/profiling.html\" = \"../../pages/core/profiling/profiling.html\"\n\"core/glossary.html\" = \"../pages/core/glossary.html\"\n\"core/resources.html\" = \"../pages/core/resources.html\"\n\"production/overview.html\" = \"../pages/production/overview.html\"\n\"production/prerequisites.html\" = \"../pages/production/prerequisites.html\"\n\"production/composition.html\" = \"../pages/production/composition.html\"\n\"production/schemas.html\" = \"../pages/production/schemas.html\"\n\"production/caches/overview.html\" = \"../../pages/production/caches/overview.html\"\n\"production/caches/xform.html\" = \"../../pages/production/caches/xform.html\"\n\"production/caches/boundingbox.html\" = \"../../pages/production/caches/boundingbox.html\"\n\"production/caches/attribute.html\" = \"../../pages/production/caches/attribute.html\"\n\"production/caches/materialbinding.html\" = \"../../pages/production/caches/materialbinding.html\"\n\"production/caches/collection.html\" = \"../../pages/production/caches/collection.html\"\n\"production/caches/composition.html\" = \"../../pages/production/caches/composition.html\"\n\"production/concepts.html\" = \"../pages/production/concepts.html\"\n\"production/faq.html\" = \"../pages/production/faq.html\"\n\"dcc/houdini/overview.html\" = \"../../pages/dcc/houdini/overview.html\"\n\"dcc/houdini/approach.html\" = \"../../pages/dcc/houdini/approach.html\"\n\"dcc/houdini/hda/overview.html\" = \"../../../pages/dcc/houdini/hda/overview.html\"\n\"dcc/houdini/fx/overview.html\" = \"../../../pages/dcc/houdini/fx/overview.html\"\n\"dcc/houdini/fx/particles.html\" = \"../../../pages/dcc/houdini/fx/particles.html\"\n\"dcc/houdini/fx/pointinstancers.html\" = \"../../../pages/dcc/houdini/fx/pointinstancers.html\"\n\"dcc/houdini/fx/rbd.html\" = \"../../../pages/dcc/houdini/fx/rbd.html\"\n\"dcc/houdini/fx/frustumCulling.html\" = \"../../../pages/dcc/houdini/fx/frustumCulling.html\"\n\"dcc/houdini/fx/motionblur.html\" = \"../../../pages/dcc/houdini/fx/motionblur.html\"\n\"dcc/houdini/faq/overview.html\" = \"../../../pages/dcc/houdini/faq/overview.html\"\n\"dcc/houdini/performance/overview.html\" = \"../../../pages/dcc/houdini/performance/overview.html\""
  },
  {
    "path": "docs/src/SUMMARY.md",
    "content": "# SUMMARY\n[USD Survival Guide]()\n\n----------------------\n\n- [Introduction](./index.md)\n    - [Motivation](./pages/introduction/motivation.md) \n    - [Guide Structure](./pages/introduction/structure.md)\n    - [Building the guide locally](./pages/introduction/docs.md)\n    - [Future Development](./pages/introduction/future.md)\n- [USD Essentials](./pages/core/overview.md)\n    - [API Overview](./pages/core/api.md)\n    - [Basic Building Blocks of USD](./pages/core/elements/overview.md)\n        - [Paths](./pages/core/elements/path.md)\n        - [Data Containers (Prims & Properties)](./pages/core/elements/data_container.md)\n            - [Prims](./pages/core/elements/prim.md)\n            - [Properties (Attributes/Relationships)](./pages/core/elements/property.md)\n        - [Data Types/Roles](./pages/core/elements/data_type.md)\n        - [Schemas ('Classes' in OOP terminology)](./pages/core/elements/schemas.md)\n        - [Metadata](./pages/core/elements/metadata.md)\n        - [Layers & Stages (Storage of Data Containers)](./pages/core/elements/layer.md)\n        - [Loading/Traversing Data](./pages/core/elements/loading_mechanisms.md)\n        - [Animation/Time Varying Data](./pages/core/elements/animation.md)\n        - [Materials](./pages/core/elements/materials.md)\n        - [Transforms](./pages/core/elements/transform.md)\n        - [Collections (Storing a group of paths)](./pages/core/elements/collection.md)\n        - [Notices/Event Listeners](./pages/core/elements/notice.md)\n        - [Standalone Utilities](./pages/core/elements/standalone_utilities.md)\n    - [Composition (Combining layers)](./pages/core/composition/overview.md)\n        - [Composition Fundamentals](./pages/core/composition/fundamentals.md)\n        - [Composition Arcs](./pages/core/composition/arcs.md)\n        - [Composition Strength Ordering (LIVRPS)](./pages/core/composition/livrps.md)\n        - [List Editable Ops](./pages/core/composition/listeditableops.md)\n        - [Inspecting Composition (Prim Cache Population (PCP))](./pages/core/composition/pcp.md)\n    - [Plugin System](./pages/core/plugins/overview.md)\n        - [Kinds](./pages/core/plugins/kind.md)\n        - [Metadata](./pages/core/plugins/metadata.md)\n        - [Schemas](./pages/core/plugins/schemas.md)\n        - [Asset Resolver](./pages/core/plugins/assetresolver.md)\n    - [Debugging & Performance Profiling](./pages/core/profiling/overview.md)\n        - [Debugging](./pages/core/profiling/debug.md)\n        - [Performance Profiling](./pages/core/profiling/profiling.md)\n    - [Vocabulary Cheatsheet ⚒️](./pages/core/glossary.md)\n    - [Resources](./pages/core/resources.md)\n- [USD in Production](./pages/production/overview.md)\n    - [Production Checklist before you start a USD pipeline](./pages/production/prerequisites.md)\n    - [A practical guide to composition](./pages/production/composition.md)\n    - [Common schemas ('Classes' in OOP terminology) for production](./pages/production/schemas.md)\n    - [Stage API Query Caches](./pages/production/caches/overview.md)\n        - [Xforms](./pages/production/caches/xform.md)\n        - [Bounding Box](./pages/production/caches/boundingbox.md)\n        - [Attribute/(Inherited) Primvars](./pages/production/caches/attribute.md)\n        - [Material Binding](./pages/production/caches/materialbinding.md)\n        - [Collection Membership](./pages/production/caches/collection.md)\n        - [Composition](./pages/production/caches/composition.md)\n    - [Advanced Concepts](./pages/production/concepts.md)\n    - [FAQ (Frequently Asked Questions)](./pages/production/faq.md)\n[comment]:# - [Software Integrations ⚒️](./pages/dcc/overview.md)\n- [USD in Houdini](./pages/dcc/houdini/overview.md)\n    - [General Approach](./pages/dcc/houdini/approach.md)\n    - [Creating efficient LOPs HDAs](./pages/dcc/houdini/hda/overview.md)\n    - [Geometry IO / FX](./pages/dcc/houdini/fx/overview.md)\n        - [Particles](./pages/dcc/houdini/fx/particles.md)\n[comment]:# - [Deforming Meshes ⚒️](./pages/dcc/houdini/fx/deformingMeshes.md)\n        - [Point Instancers ('Copy To Points')](./pages/dcc/houdini/fx/pointinstancers.md)\n        - [RBD (Rigid Body Dynamics)](./pages/dcc/houdini/fx/rbd.md)\n[comment]:# - [Volumes ⚒️](./pages/dcc/houdini/fx/volumes.md)\n[comment]:# - [Transform Space (Local/World Space) ⚒️](./pages/dcc/houdini/fx/transformspace.md)\n        - [Frustum Culling](./pages/dcc/houdini/fx/frustumCulling.md)\n        - [Motion Blur (Deforming/Xforms/Velocity/Acceleration)](./pages/dcc/houdini/fx/motionblur.md)\n    - [Tips & Tricks](./pages/dcc/houdini/faq/overview.md)\n    - [Performance Optimizations](./pages/dcc/houdini/performance/overview.md)"
  },
  {
    "path": "docs/src/google12b063a902eb5a11.html",
    "content": "google-site-verification: google12b063a902eb5a11.html"
  },
  {
    "path": "docs/src/index.md",
    "content": "![](../UsdSurvivalGuide.png#center)\n\n# Usd Survival Guide\n[![Deploy Documentation to GitHub Pages](https://github.com/LucaScheller/VFX-UsdAssetResolver/actions/workflows/mdbook.yml/badge.svg)](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/actions/workflows/mdbook.yml)\n\nThis repository aims to be a practical onboarding guide to [USD](https://openusd.org/release/index.html) for software developers and pipeline TDs.\nFor more information what makes this guide unique, see the [motivation](./pages/introduction/motivation.md) section.\n\n```admonish success title=\"Siggraph Presentation\"\nThis guide was officially introduced at [Siggraph 2023 - Houdini Hive](https://www.sidefx.com/houdini-hive/siggraph-2023/#usd). Special thanks to SideFX for hosting me and throwing such a cool Houdini lounge and presentation line up!\n```\n\n{{#include pages/contributors.md}}\n\n## License \nThis guide is licensed under the **Apache License 2.0**. For more information as to how this affects copyright and distribution see our [license](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/blob/main/LICENSE) page.\n\n## Prerequisites\nBefore starting our journey, make sure you are all packed:\n- It is expected to have a general notion of what Usd is. If this is your first contact with the topic, check out the links in [motivation](./pages/introduction/motivation.md). The introduction resources there take 1-2 hours to consume for a basic understanding and will help with understanding this guide.\n- A background in VFX industry. Though not strictly necessary, it helps to know the general vocabulary of the industry to understand this guide. This guide aims to stay away from Usd specific vocabulary, where possible, to make it more accessible to the general VFX community.\n- Motivation to learn new stuff. Don't worry to much about all the custom Usd terminology being thrown at you at the beginning, you'll pick it up it no time once you start working with Usd!\n\n## Next Steps\nTo get started, let's head over to the [Core Elements](./pages/core/overview.md) section!\n\n```admonish tip\nThis guide primarily uses [Houdini](https://www.sidefx.com/) to explain concepts, as it is one of the most accessible and easiest ways to learn the ways of Usd with. You can install a non-commercial version for free from their website. It is highly recommended to use it when following this guide.\n```"
  },
  {
    "path": "docs/src/media/core/composition/compositionLIVRPS.excalidraw",
    "content": "{\n  \"type\": \"excalidraw\",\n  \"version\": 2,\n  \"source\": \"https://excalidraw.com\",\n  \"elements\": [\n    {\n      \"type\": \"rectangle\",\n      \"version\": 433,\n      \"versionNonce\": 581071317,\n      \"isDeleted\": false,\n      \"id\": \"tvCKecPpXhCeojSaqctCZ\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 499.0932864977807,\n      \"y\": 110.19266525495414,\n      \"strokeColor\": \"#e8590c\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 410.0605603343787,\n      \"height\": 63.456123274413436,\n      \"seed\": 1307795167,\n      \"groupIds\": [\n        \"yV8nZHmrsj5JBpId34HuL\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 3\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"1K4GBrXuseanF7enpdsvY\",\n          \"type\": \"arrow\"\n        },\n        {\n          \"id\": \"Pdn-OF7tLkp-2fAQtyRik\",\n          \"type\": \"arrow\"\n        },\n        {\n          \"id\": \"bq8J0YMEPbBLRBwFmfaMu\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1690306488999,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 417,\n      \"versionNonce\": 1264815317,\n      \"isDeleted\": false,\n      \"id\": \"4IUZ_8SqWAhj-LpRDE3zj\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 517.4418677244594,\n      \"y\": 128.76611699725908,\n      \"strokeColor\": \"#e8590c\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 376.63958740234375,\n      \"height\": 25,\n      \"seed\": 1568120721,\n      \"groupIds\": [\n        \"yV8nZHmrsj5JBpId34HuL\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1690306494124,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 20,\n      \"fontFamily\": 1,\n      \"text\": \"Direct Opinion on Root Layer/Sublayer\",\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"Direct Opinion on Root Layer/Sublayer\",\n      \"lineHeight\": 1.25,\n      \"baseline\": 17\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 387,\n      \"versionNonce\": 2082986165,\n      \"isDeleted\": false,\n      \"id\": \"oOIprtAcjY2vqFdDqL0Lu\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 554.3502207353968,\n      \"y\": 277.16707243207225,\n      \"strokeColor\": \"#e8590c\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 293.518657112439,\n      \"height\": 64.46080036315615,\n      \"seed\": 148468991,\n      \"groupIds\": [\n        \"MGXhRJRGrbYCbkxpAnW7L\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 3\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"1K4GBrXuseanF7enpdsvY\",\n          \"type\": \"arrow\"\n        },\n        {\n          \"id\": \"fU9Bin0TFQHYVIiQgfVyD\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1690306411008,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 399,\n      \"versionNonce\": 2119099765,\n      \"isDeleted\": false,\n      \"id\": \"90Kgj0RhNWnvAkBgypbpJ\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 657.2318308233216,\n      \"y\": 296.91329340337245,\n      \"strokeColor\": \"#e8590c\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 76.19992065429688,\n      \"height\": 25,\n      \"seed\": 592544063,\n      \"groupIds\": [\n        \"MGXhRJRGrbYCbkxpAnW7L\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1690306413482,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 20,\n      \"fontFamily\": 1,\n      \"text\": \"Inherits\",\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"Inherits\",\n      \"lineHeight\": 1.25,\n      \"baseline\": 17\n    },\n    {\n      \"type\": \"arrow\",\n      \"version\": 784,\n      \"versionNonce\": 620439829,\n      \"isDeleted\": false,\n      \"id\": \"1K4GBrXuseanF7enpdsvY\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 698.0029472363551,\n      \"y\": 180.1004309353094,\n      \"strokeColor\": \"#e8590c\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 1.4127743788499174,\n      \"height\": 86.13890940858792,\n      \"seed\": 281579231,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1690306502486,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": {\n        \"elementId\": \"tvCKecPpXhCeojSaqctCZ\",\n        \"focus\": 0.03282309762147945,\n        \"gap\": 6.451642405941797\n      },\n      \"endBinding\": {\n        \"elementId\": \"oOIprtAcjY2vqFdDqL0Lu\",\n        \"focus\": -0.006694275544913026,\n        \"gap\": 10.927732088174935\n      },\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": \"arrow\",\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          1.4127743788499174,\n          86.13890940858792\n        ]\n      ]\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 412,\n      \"versionNonce\": 1989963477,\n      \"isDeleted\": false,\n      \"id\": \"PH5NAPhBZ09TwYgAs8l4D\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 554.3502207353968,\n      \"y\": 447.99918108160966,\n      \"strokeColor\": \"#e8590c\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 293.518657112439,\n      \"height\": 64.46080036315615,\n      \"seed\": 613831729,\n      \"groupIds\": [\n        \"7aIupSl1TXTLHCdO7PCND\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 3\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"XYL-2dK9xf8LLjxB_1A_l\",\n          \"type\": \"arrow\"\n        },\n        {\n          \"id\": \"fU9Bin0TFQHYVIiQgfVyD\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1690306414466,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 419,\n      \"versionNonce\": 1085995253,\n      \"isDeleted\": false,\n      \"id\": \"E89XJSC2ll90bxos09BC6\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 657.2317621727367,\n      \"y\": 468.986535977732,\n      \"strokeColor\": \"#e8590c\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 81.49990844726562,\n      \"height\": 25,\n      \"seed\": 1245821937,\n      \"groupIds\": [\n        \"7aIupSl1TXTLHCdO7PCND\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1690306416853,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 20,\n      \"fontFamily\": 1,\n      \"text\": \"Variants\",\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"Variants\",\n      \"lineHeight\": 1.25,\n      \"baseline\": 17\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 430,\n      \"versionNonce\": 1798357499,\n      \"isDeleted\": false,\n      \"id\": \"YfFH5FpDLUt_C6c_maJOR\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 554.3502207353968,\n      \"y\": 620.0724236559694,\n      \"strokeColor\": \"#e8590c\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 293.518657112439,\n      \"height\": 64.46080036315615,\n      \"seed\": 293789375,\n      \"groupIds\": [\n        \"-HOOU6dBpdSKZrqtCN_mp\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 3\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"-dQL7N9ePpXkaz1FnscNY\",\n          \"type\": \"arrow\"\n        },\n        {\n          \"id\": \"XYL-2dK9xf8LLjxB_1A_l\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1690306348676,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 430,\n      \"versionNonce\": 1991056405,\n      \"isDeleted\": false,\n      \"id\": \"iYbiHenuDl1mcAym7HcM7\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 648.5439620001524,\n      \"y\": 637.9569094147442,\n      \"strokeColor\": \"#e8590c\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 105.8798828125,\n      \"height\": 25,\n      \"seed\": 1350269695,\n      \"groupIds\": [\n        \"-HOOU6dBpdSKZrqtCN_mp\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [\n        {\n          \"id\": \"-dQL7N9ePpXkaz1FnscNY\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1690306420331,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 20,\n      \"fontFamily\": 1,\n      \"text\": \"References\",\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"References\",\n      \"lineHeight\": 1.25,\n      \"baseline\": 17\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 411,\n      \"versionNonce\": 1432144539,\n      \"isDeleted\": false,\n      \"id\": \"xDZckrktVucN_cf2Fi11t\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 554.3502207353968,\n      \"y\": 791.525099267918,\n      \"strokeColor\": \"#e8590c\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 293.518657112439,\n      \"height\": 64.46080036315615,\n      \"seed\": 679612863,\n      \"groupIds\": [\n        \"mOdsdsUKSmarPTBjD0XPF\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 3\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"-dQL7N9ePpXkaz1FnscNY\",\n          \"type\": \"arrow\"\n        },\n        {\n          \"id\": \"OZoxWG1Vz2ugTsOp4JT-A\",\n          \"type\": \"arrow\"\n        },\n        {\n          \"id\": \"7xZC-ce8EpRhrgkDOXifG\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1690306348676,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 417,\n      \"versionNonce\": 1209637851,\n      \"isDeleted\": false,\n      \"id\": \"jgBPSsEsvF7niEFad0y1R\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 658.4729647481437,\n      \"y\": 811.72540258976,\n      \"strokeColor\": \"#e8590c\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 87.85989379882812,\n      \"height\": 25,\n      \"seed\": 25816575,\n      \"groupIds\": [\n        \"mOdsdsUKSmarPTBjD0XPF\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [\n        {\n          \"id\": \"OZoxWG1Vz2ugTsOp4JT-A\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1690306423281,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 20,\n      \"fontFamily\": 1,\n      \"text\": \"Payloads\",\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"Payloads\",\n      \"lineHeight\": 1.25,\n      \"baseline\": 17\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 429,\n      \"versionNonce\": 2050932539,\n      \"isDeleted\": false,\n      \"id\": \"j4eEiwK_RFYbeKBqvuESP\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 554.3502207353968,\n      \"y\": 962.9777748798666,\n      \"strokeColor\": \"#e8590c\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 293.518657112439,\n      \"height\": 64.46080036315615,\n      \"seed\": 495890129,\n      \"groupIds\": [\n        \"4tiMjOkKwf19wY1owHrpM\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 3\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"OZoxWG1Vz2ugTsOp4JT-A\",\n          \"type\": \"arrow\"\n        },\n        {\n          \"id\": \"srS-xcfL5sMBAu0jQZMB_\",\n          \"type\": \"arrow\"\n        },\n        {\n          \"id\": \"U7iB1kM_AJZWa2Ysr6QVE\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1690306348676,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 421,\n      \"versionNonce\": 629645205,\n      \"isDeleted\": false,\n      \"id\": \"yYGmlDfj6Mdtgim9NoFka\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 642.3382923760422,\n      \"y\": 982.723927200582,\n      \"strokeColor\": \"#e8590c\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 103.59986877441406,\n      \"height\": 25,\n      \"seed\": 1973153425,\n      \"groupIds\": [\n        \"4tiMjOkKwf19wY1owHrpM\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1690306425882,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 20,\n      \"fontFamily\": 1,\n      \"text\": \"Specializes\",\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"Specializes\",\n      \"lineHeight\": 1.25,\n      \"baseline\": 17\n    },\n    {\n      \"type\": \"arrow\",\n      \"version\": 135,\n      \"versionNonce\": 603225493,\n      \"isDeleted\": false,\n      \"id\": \"fU9Bin0TFQHYVIiQgfVyD\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 699.5133823646312,\n      \"y\": 345.71764006730194,\n      \"strokeColor\": \"#e8590c\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 0.6228998488444404,\n      \"height\": 89.46925261390624,\n      \"seed\": 356159295,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1690306414475,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": {\n        \"elementId\": \"oOIprtAcjY2vqFdDqL0Lu\",\n        \"focus\": 0.01257205156544451,\n        \"gap\": 4.089767272073573\n      },\n      \"endBinding\": {\n        \"elementId\": \"PH5NAPhBZ09TwYgAs8l4D\",\n        \"focus\": -0.004488064147194584,\n        \"gap\": 12.812288400401542\n      },\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": \"arrow\",\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          0.6228998488444404,\n          89.46925261390624\n        ]\n      ]\n    },\n    {\n      \"type\": \"arrow\",\n      \"version\": 173,\n      \"versionNonce\": 322030645,\n      \"isDeleted\": false,\n      \"id\": \"XYL-2dK9xf8LLjxB_1A_l\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 700.8441169957204,\n      \"y\": 522.3873193025739,\n      \"strokeColor\": \"#e8590c\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 1.8240977678830177,\n      \"height\": 82.64970631779852,\n      \"seed\": 648541265,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1690306414474,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": {\n        \"elementId\": \"PH5NAPhBZ09TwYgAs8l4D\",\n        \"focus\": 0.008097844596793463,\n        \"gap\": 9.92733785780797\n      },\n      \"endBinding\": {\n        \"elementId\": \"YfFH5FpDLUt_C6c_maJOR\",\n        \"focus\": 0.017643050807413182,\n        \"gap\": 15.035398035596984\n      },\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": \"arrow\",\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          1.8240977678830177,\n          82.64970631779852\n        ]\n      ]\n    },\n    {\n      \"type\": \"arrow\",\n      \"version\": 165,\n      \"versionNonce\": 761162875,\n      \"isDeleted\": false,\n      \"id\": \"-dQL7N9ePpXkaz1FnscNY\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 700.5878564084461,\n      \"y\": 694.031088455791,\n      \"strokeColor\": \"#e8590c\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 0.17586419367330564,\n      \"height\": 85.93621630958057,\n      \"seed\": 295718929,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1690306348677,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": {\n        \"elementId\": \"YfFH5FpDLUt_C6c_maJOR\",\n        \"focus\": 0.0029715458078037843,\n        \"gap\": 9.497864436665338\n      },\n      \"endBinding\": {\n        \"elementId\": \"xDZckrktVucN_cf2Fi11t\",\n        \"focus\": -0.005361252539827391,\n        \"gap\": 11.557794502546415\n      },\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": \"arrow\",\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -0.17586419367330564,\n          85.93621630958057\n        ]\n      ]\n    },\n    {\n      \"type\": \"arrow\",\n      \"version\": 147,\n      \"versionNonce\": 795405493,\n      \"isDeleted\": false,\n      \"id\": \"OZoxWG1Vz2ugTsOp4JT-A\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 703.3887605111134,\n      \"y\": 864.7061066916036,\n      \"strokeColor\": \"#e8590c\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 3.953431791485741,\n      \"height\": 83.87461038210995,\n      \"seed\": 1979473105,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1690306348677,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": {\n        \"elementId\": \"xDZckrktVucN_cf2Fi11t\",\n        \"focus\": -0.028388598623187485,\n        \"gap\": 8.720207060529503\n      },\n      \"endBinding\": {\n        \"elementId\": \"j4eEiwK_RFYbeKBqvuESP\",\n        \"focus\": -0.026113068933483478,\n        \"gap\": 14.3970578061531\n      },\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": \"arrow\",\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -3.953431791485741,\n          83.87461038210995\n        ]\n      ]\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 434,\n      \"versionNonce\": 158410011,\n      \"isDeleted\": false,\n      \"id\": \"5gGThxBq5T2vpa-X2Nldy\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 571.8087054565372,\n      \"y\": 1138.3474050576338,\n      \"strokeColor\": \"#6741d9\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 293.518657112439,\n      \"height\": 64.46080036315615,\n      \"seed\": 704633265,\n      \"groupIds\": [\n        \"rguWGkEmOc9PXR4wvcSyB\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 3\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"srS-xcfL5sMBAu0jQZMB_\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1690306348677,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 490,\n      \"versionNonce\": 1567854101,\n      \"isDeleted\": false,\n      \"id\": \"QcYQu72bILVOJ8XS5SipF\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 584.6423409340443,\n      \"y\": 1158.7363779079903,\n      \"strokeColor\": \"#6741d9\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 271.5997009277344,\n      \"height\": 25,\n      \"seed\": 69722481,\n      \"groupIds\": [\n        \"rguWGkEmOc9PXR4wvcSyB\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1690306348677,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 20,\n      \"fontFamily\": 1,\n      \"text\": \"Default Value From Schema\",\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"Default Value From Schema\",\n      \"lineHeight\": 1.25,\n      \"baseline\": 17\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 440,\n      \"versionNonce\": 266586555,\n      \"isDeleted\": false,\n      \"id\": \"vGQiHsOHt9D0-a0bRW87i\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 550.9096650485852,\n      \"y\": 654.9027574503153,\n      \"strokeColor\": \"#1971c2\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 193.90580487030746,\n      \"height\": 3.3700409723267057,\n      \"seed\": 929509521,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1690306348677,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -94.62796614359513,\n          2.0999310361653443\n        ],\n        [\n          -193.90580487030746,\n          3.3700409723267057\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 390,\n      \"versionNonce\": 677577589,\n      \"isDeleted\": false,\n      \"id\": \"CoD5FvbIAtDyhI0ukk-0F\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 545.7995337491266,\n      \"y\": 480.5440396888997,\n      \"strokeColor\": \"#1971c2\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 185.19772818996904,\n      \"height\": 5.08057213648658,\n      \"seed\": 1588956735,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1690306348677,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -116.31204895193852,\n          -5.08057213648658\n        ],\n        [\n          -185.19772818996904,\n          -3.8104291023648784\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 435,\n      \"versionNonce\": 1171839579,\n      \"isDeleted\": false,\n      \"id\": \"06lzqVPOX0t9nHzUk24H1\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 550.141227088533,\n      \"y\": 317.19112650929867,\n      \"strokeColor\": \"#1971c2\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 191.79051461136922,\n      \"height\": 4.741807349607667,\n      \"seed\": 1638491135,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1690306348677,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -114.77660212676597,\n          -2.428581231368014\n        ],\n        [\n          -191.79051461136922,\n          -4.741807349607667\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 422,\n      \"versionNonce\": 1149029589,\n      \"isDeleted\": false,\n      \"id\": \"ovw-uXzP0xVpgVaZHl3tH\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1059.235044191496,\n      \"y\": 652.5032468577637,\n      \"strokeColor\": \"#6741d9\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 203.22169112174925,\n      \"height\": 5.08057213648658,\n      \"seed\": 1980396671,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1690306348677,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -125.74345782644639,\n          -5.08057213648658\n        ],\n        [\n          -203.22169112174925,\n          -3.8104291023648784\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 469,\n      \"versionNonce\": 1747113723,\n      \"isDeleted\": false,\n      \"id\": \"W1rUi2Zh5kfkRt6GHv0Ie\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1064.1879852603292,\n      \"y\": 487.29881697496353,\n      \"strokeColor\": \"#6741d9\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 216.69379608861743,\n      \"height\": 5.08057213648658,\n      \"seed\": 451251359,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1690306348677,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -145.0268305102488,\n          -5.08057213648658\n        ],\n        [\n          -216.69379608861743,\n          -3.8104291023648784\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 489,\n      \"versionNonce\": 1096182325,\n      \"isDeleted\": false,\n      \"id\": \"2GOr6X78zPcReS_mumjED\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1064.4524297762782,\n      \"y\": 316.16849082653516,\n      \"strokeColor\": \"#6741d9\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 213.0145166163334,\n      \"height\": 5.073935031148037,\n      \"seed\": 15245503,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1690306348677,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -139.89441731559714,\n          -5.073935031148037\n        ],\n        [\n          -213.0145166163334,\n          -3.49333258127872\n        ]\n      ]\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 109,\n      \"versionNonce\": 1967407003,\n      \"isDeleted\": false,\n      \"id\": \"3WuZBdTBsSOX7YA1ssWom\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 515.1340329902335,\n      \"y\": 202.63832546697267,\n      \"strokeColor\": \"#e8590c\",\n      \"backgroundColor\": \"#ffffff\",\n      \"width\": 165.61981201171875,\n      \"height\": 25,\n      \"seed\": 9940543,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1690306348677,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 20,\n      \"fontFamily\": 1,\n      \"text\": \"No opinion found?\",\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"No opinion found?\",\n      \"lineHeight\": 1.25,\n      \"baseline\": 17\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 743,\n      \"versionNonce\": 534076309,\n      \"isDeleted\": false,\n      \"id\": \"cfpswKIiuLnvx7HuYdhGn\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": -29.60853119424837,\n      \"y\": 358.4210157647882,\n      \"strokeColor\": \"#1971c2\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 378.24250264240095,\n      \"height\": 81.05622964369954,\n      \"seed\": 569283121,\n      \"groupIds\": [\n        \"Lta4hhIx87F1ccAdvB5x9\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 3\n      },\n      \"boundElements\": [],\n      \"updated\": 1690306348677,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 764,\n      \"versionNonce\": 2003801147,\n      \"isDeleted\": false,\n      \"id\": \"5nwZR094HSLTOVFUSNH_a\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": -9.426189612297435,\n      \"y\": 375.1560105245046,\n      \"strokeColor\": \"#1971c2\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 344.27960205078125,\n      \"height\": 50,\n      \"seed\": 555907569,\n      \"groupIds\": [\n        \"Lta4hhIx87F1ccAdvB5x9\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1690306348677,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 20,\n      \"fontFamily\": 1,\n      \"text\": \"Recursively apply LIVRP evaluation\\n   (Specialize arcs are ingored)\",\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"Recursively apply LIVRP evaluation\\n   (Specialize arcs are ingored)\",\n      \"lineHeight\": 1.25,\n      \"baseline\": 42\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1204,\n      \"versionNonce\": 674177269,\n      \"isDeleted\": false,\n      \"id\": \"J-MXCoMA7rL9kM1O1tBL7\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 552.1032342882239,\n      \"y\": 998.743854507406,\n      \"strokeColor\": \"#1971c2\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 707.6693442163023,\n      \"height\": 856.9119638060472,\n      \"seed\": 85642097,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1690306348677,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -441.959606835003,\n          -4.641698302675081\n        ],\n        [\n          -643.835724594516,\n          -25.82054495095997\n        ],\n        [\n          -707.0731686381307,\n          -195.56669366947108\n        ],\n        [\n          -707.6693442163023,\n          -856.9119638060472\n        ]\n      ]\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 729,\n      \"versionNonce\": 243750107,\n      \"isDeleted\": false,\n      \"id\": \"PZWHIAxd165rA6hqNJWe8\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": -535.373766478696,\n      \"y\": 142.41962743998255,\n      \"strokeColor\": \"#1971c2\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 378.24250264240095,\n      \"height\": 81.05622964369954,\n      \"seed\": 274534321,\n      \"groupIds\": [\n        \"yQG8a0fXJDY5KgNkKGESe\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 3\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"bq8J0YMEPbBLRBwFmfaMu\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1690306348677,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 808,\n      \"versionNonce\": 2145991253,\n      \"isDeleted\": false,\n      \"id\": \"aqtVcJAwIf6rnaTVuJe-P\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": -518.0761098798115,\n      \"y\": 173.5779673350384,\n      \"strokeColor\": \"#1971c2\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 347.9750671386719,\n      \"height\": 43.74929243585833,\n      \"seed\": 288331633,\n      \"groupIds\": [\n        \"yQG8a0fXJDY5KgNkKGESe\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1690306348677,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 17.499716974343333,\n      \"fontFamily\": 1,\n      \"text\": \"Recursively apply full LIVRPS evaluation\\n  \",\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"Recursively apply full LIVRPS evaluation\\n  \",\n      \"lineHeight\": 1.25,\n      \"baseline\": 36\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 491,\n      \"versionNonce\": 975044987,\n      \"isDeleted\": false,\n      \"id\": \"zsy2fWA2m9S0mGkt9OrKO\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1061.938939829753,\n      \"y\": 824.8023674358803,\n      \"strokeColor\": \"#6741d9\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 210.4926166209035,\n      \"height\": 2.6918204199280353,\n      \"seed\": 547263455,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1690306348677,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -103.37140792445098,\n          -1.7247770258614992\n        ],\n        [\n          -210.4926166209035,\n          -2.6918204199280353\n        ]\n      ]\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 441,\n      \"versionNonce\": 2144937909,\n      \"isDeleted\": false,\n      \"id\": \"mu787P5tu6UloYyYJdKLo\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 914.0405288987565,\n      \"y\": 73.75043021629,\n      \"strokeColor\": \"#6741d9\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 293.518657112439,\n      \"height\": 64.46080036315615,\n      \"seed\": 1482869119,\n      \"groupIds\": [\n        \"fjuwj84XJytlPB8urRnRb\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 3\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"U7iB1kM_AJZWa2Ysr6QVE\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1690306348677,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 438,\n      \"versionNonce\": 1668684315,\n      \"isDeleted\": false,\n      \"id\": \"cTjqPV-i3ek8yA8Km1UnJ\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 988.3761960169447,\n      \"y\": 96.59945167435279,\n      \"strokeColor\": \"#6741d9\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 131.69985961914062,\n      \"height\": 25,\n      \"seed\": 1861203391,\n      \"groupIds\": [\n        \"fjuwj84XJytlPB8urRnRb\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1690306348677,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 20,\n      \"fontFamily\": 1,\n      \"text\": \"Opinion found!\",\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"Opinion found!\",\n      \"lineHeight\": 1.25,\n      \"baseline\": 17\n    },\n    {\n      \"type\": \"arrow\",\n      \"version\": 427,\n      \"versionNonce\": 357938363,\n      \"isDeleted\": false,\n      \"id\": \"Pdn-OF7tLkp-2fAQtyRik\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 918.530756617175,\n      \"y\": 144.7708524802556,\n      \"strokeColor\": \"#6741d9\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 520.4109119949085,\n      \"height\": 8.1172428521636,\n      \"seed\": 1377237855,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1690306488999,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": {\n        \"elementId\": \"tvCKecPpXhCeojSaqctCZ\",\n        \"gap\": 8.874543454895914,\n        \"focus\": 0.17722071097704487\n      },\n      \"endBinding\": {\n        \"elementId\": \"Jeu-yLmbOhzj_6tT1NPPv\",\n        \"gap\": 12.769088332956153,\n        \"focus\": 0.14855234400573966\n      },\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": \"arrow\",\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          520.4109119949085,\n          -8.1172428521636\n        ]\n      ]\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 444,\n      \"versionNonce\": 662838971,\n      \"isDeleted\": false,\n      \"id\": \"Jeu-yLmbOhzj_6tT1NPPv\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1451.7107569450397,\n      \"y\": 107.92478515090068,\n      \"strokeColor\": \"#6741d9\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 163.72010915194087,\n      \"height\": 64.46080036315615,\n      \"seed\": 1839139263,\n      \"groupIds\": [\n        \"S5-pgvZzASo1AS1hN4EJi\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 3\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"Pdn-OF7tLkp-2fAQtyRik\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1690306348677,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 449,\n      \"versionNonce\": 541097589,\n      \"isDeleted\": false,\n      \"id\": \"mNYK6kg1XbLTjFutlYk0R\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1484.8689161132504,\n      \"y\": 129.8786390870756,\n      \"strokeColor\": \"#6741d9\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 105.53987121582031,\n      \"height\": 25,\n      \"seed\": 1841882623,\n      \"groupIds\": [\n        \"S5-pgvZzASo1AS1hN4EJi\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1690306348677,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 20,\n      \"fontFamily\": 1,\n      \"text\": \"Use opinion\",\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"Use opinion\",\n      \"lineHeight\": 1.25,\n      \"baseline\": 17\n    },\n    {\n      \"type\": \"arrow\",\n      \"version\": 667,\n      \"versionNonce\": 1625591643,\n      \"isDeleted\": false,\n      \"id\": \"7xZC-ce8EpRhrgkDOXifG\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 548.1929548860485,\n      \"y\": 826.3981039402985,\n      \"strokeColor\": \"#1971c2\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 190.58146305449736,\n      \"height\": 684.6736614531433,\n      \"seed\": 80879476,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1690306348677,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": {\n        \"elementId\": \"xDZckrktVucN_cf2Fi11t\",\n        \"focus\": -0.44810282641766547,\n        \"gap\": 6.1572658493483345\n      },\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": \"arrow\",\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -160.4630229763186,\n          -21.725531159367847\n        ],\n        [\n          -190.58146305449736,\n          -175.73927894633505\n        ],\n        [\n          -189.80480199241606,\n          -684.6736614531433\n        ]\n      ]\n    },\n    {\n      \"type\": \"arrow\",\n      \"version\": 305,\n      \"versionNonce\": 1003840859,\n      \"isDeleted\": false,\n      \"id\": \"bq8J0YMEPbBLRBwFmfaMu\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": -136.13753475516404,\n      \"y\": 137.92073449804747,\n      \"strokeColor\": \"#1971c2\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 624.0493400870951,\n      \"height\": 0.402767338872593,\n      \"seed\": 2022163532,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1690306488999,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": {\n        \"elementId\": \"PZWHIAxd165rA6hqNJWe8\",\n        \"gap\": 4.4287738208878205,\n        \"focus\": -1.1110067162440436\n      },\n      \"endBinding\": {\n        \"elementId\": \"tvCKecPpXhCeojSaqctCZ\",\n        \"gap\": 11.181481165849725,\n        \"focus\": 0.10852033577110856\n      },\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": \"arrow\",\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          624.0493400870951,\n          0.402767338872593\n        ]\n      ]\n    },\n    {\n      \"type\": \"arrow\",\n      \"version\": 59,\n      \"versionNonce\": 1911548923,\n      \"isDeleted\": false,\n      \"id\": \"srS-xcfL5sMBAu0jQZMB_\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 697.2652291484171,\n      \"y\": 1035.787871870117,\n      \"strokeColor\": \"#6741d9\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 4.530199461717302,\n      \"height\": 92.25125165703753,\n      \"seed\": 124009676,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1690306348677,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": {\n        \"elementId\": \"j4eEiwK_RFYbeKBqvuESP\",\n        \"focus\": 0.039348748395972036,\n        \"gap\": 8.349296627094134\n      },\n      \"endBinding\": {\n        \"elementId\": \"5gGThxBq5T2vpa-X2Nldy\",\n        \"focus\": -0.0989850696138713,\n        \"gap\": 10.308281530479235\n      },\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": \"arrow\",\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          4.530199461717302,\n          92.25125165703753\n        ]\n      ]\n    },\n    {\n      \"type\": \"arrow\",\n      \"version\": 705,\n      \"versionNonce\": 1448158517,\n      \"isDeleted\": false,\n      \"id\": \"U7iB1kM_AJZWa2Ysr6QVE\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 856.3705035811738,\n      \"y\": 993.961704741057,\n      \"strokeColor\": \"#6741d9\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 210.23261441126078,\n      \"height\": 845.2737220951649,\n      \"seed\": 2079302772,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1690306348677,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": {\n        \"elementId\": \"j4eEiwK_RFYbeKBqvuESP\",\n        \"focus\": 0.511245321791829,\n        \"gap\": 8.501625733338017\n      },\n      \"endBinding\": {\n        \"elementId\": \"mu787P5tu6UloYyYJdKLo\",\n        \"focus\": -0.042099547169064944,\n        \"gap\": 10.476752066445982\n      },\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": \"arrow\",\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          182.5347495626129,\n          -40.32442489844425\n        ],\n        [\n          205.6243046943971,\n          -337.4534933774553\n        ],\n        [\n          210.23261441126078,\n          -845.2737220951649\n        ]\n      ]\n    },\n    {\n      \"id\": \"N0iDlKnRmsLSCw-UQHy32\",\n      \"type\": \"line\",\n      \"x\": 868.5220805040946,\n      \"y\": 1172.5583314818282,\n      \"width\": 191.90336658986269,\n      \"height\": 289.310055967366,\n      \"angle\": 0,\n      \"strokeColor\": \"#6741d9\",\n      \"backgroundColor\": \"transparent\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"seed\": 1916747381,\n      \"version\": 484,\n      \"versionNonce\": 608916411,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1690308641343,\n      \"link\": null,\n      \"locked\": false,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          127.5291813575667,\n          -15.25358621894793\n        ],\n        [\n          178.46152166936224,\n          -100.30315237671834\n        ],\n        [\n          191.90336658986269,\n          -289.310055967366\n        ]\n      ],\n      \"lastCommittedPoint\": null,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null\n    }\n  ],\n  \"appState\": {\n    \"gridSize\": null,\n    \"viewBackgroundColor\": \"#ffffff\"\n  },\n  \"files\": {}\n}"
  },
  {
    "path": "docs/src/not-found.md",
    "content": "<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",
    "content": "### Contributors\n- [Luca Scheller (Main Author)](https://github.com/LucaScheller)\n- [Jonas Sorgenfrei](https://github.com/jonassorgenfrei)\n- [Samrat Dutta](https://github.com/DStarRaj)\n- [Roy Nieterau](https://github.com/BigRoy)"
  },
  {
    "path": "docs/src/pages/core/api.md",
    "content": "# API Overview\nBefore we dive into the nitty gritty details, let's first have a look at how the USD API is structured.\n\nOverall there are two different API \"levels\":\n\n```mermaid\nflowchart TD\n    pxr([pxr]) --> highlevel([High Level -> Usd])\n    pxr --> lowlevel([Low Level -> PcP/Sdf])\n```\n\nMost tutorials focus primarily on the high level API, as it is a bit more convenient when starting out. The more you work in Usd though, the more you'll start using the lower level API. Therefore this guide will often have examples for both levels.\n\n~~~admonish tip\nWe'd actually recommend starting out with the lower level API as soon as you can, as it will force you to write performant code from the start.\n~~~\n\nNow there are also a few other base modules that supplement these two API levels, we also have contact with them in this guide:\n- **Gf**: The **G**raphics **F**oundations module provides all math related classes and utility functions (E.g matrix and vector data classes)\n- **Vt** : The **V**alue **T**ypes module provides the value types for what USD can store. Among these is also the `Vt.Array`, which allows us to efficiently map USD arrays (of various data types like int/float/vectors) to numpy arrays for fast data processing.\n- **Plug**: This module manages USD's [plugin framework](../core/plugins/overview.md).\n- **Tf**: The **T**ools **F**oundations module gives us access to profiling, debugging and C++ utilities (Python/Threading). It also houses our type registry (for a variety of USD classes).\n\nFor a full overview, visit the excellently written [USD Architecture Overview - Official API Docs](https://openusd.org/release/api/_usd__overview_and_purpose.html#Usd_ArchitecturalOverview) section.\n\n## TL;DR - API Overview In-A-Nutshell\nHere is the TL;DR version. Usd is made up of two main APIs:\n- High level API:\n    - [Usd Core API](https://openusd.org/release/api/usd_page_front.html)\n- Low level API:\n    - [Sdf - Scene Description Foundations](https://openusd.org/release/api/sdf_page_front.html)\n    - [Pcp - PrimCache Population (Composition)](https://openusd.org/release/api/pcp_page_front.html)\n\nIndividual components of Usd are loaded via a [plugin based system](./plugins/overview.md), for example Hydra, kinds, file plugins (Vdbs, abc) etc.\n\nHere is a simple comparison:\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../code/core/elements.py:apiHighVsLowLevel}}\n```\n~~~\n\n## What should I use it for?\n~~~admonish tip\nYou'll be using these two API levels all the time when working with Usd.\nThe high level API is often used with read ops, the low level with write ops or inspecting the underlying caches of the high level API.\n~~~\n\n## Resources\n- [USD Architecture Overview - Official API Docs](https://openusd.org/release/api/_usd__overview_and_purpose.html#Usd_ArchitecturalOverview)\n- [Common USD API Classes](./resources.md)\n\n## When should I use what?\nAs a rule of thumb, you use the high level API when:\n\n~~~admonish info title=\"\"\n- Reading data of a stage\n- Using Usd Schema Classes (E.g.  [UsdGeomMesh](https://openusd.org/dev/api/class_usd_geom_mesh.html), [UsdClipsAPI](https://openusd.org/release/api/class_usd_clips_a_p_i.html), [UsdGeomPrimvarsAPI](https://openusd.org/release/api/class_usd_geom_primvars_a_p_i.html)) \n~~~\n\nAnd the low level API when:\n\n~~~admonish info title=\"\"\n- Creating/Copying/Moving data of a layer\n- Performance is critical (When is it ever not?)\n~~~\n\n## High Level API\nThe Usd Core API docs page is a great place to get an overview over the high level API:\n\n- [Usd Core API](https://openusd.org/release/api/usd_page_front.html)\n\nBasically everything in the pxr.Usd namespace nicely wraps things in the pxr.Sdf/pxr.Pcp namespace with getters/setters, convenience classes and functions.\n\nTherefore it is a bit more OOP oriented and follows C++ code design patterns.\n\n~~~admonish important\nThis level always operates on the composed state of the stage. This means as soon as you are working stages, you'll be using the higher level API. It also takes care of validation data/setting common data, whereas the lower level API often leaves parts up to the user.\n~~~\n\n\n## Low Level API\nGreat entry points for the lower level API:\n\n- [Sdf - Scene Description Foundations](https://openusd.org/release/api/sdf_page_front.html)\n\n- [Pcp - PrimCache Population (Composition)](https://openusd.org/release/api/pcp_page_front.html)\n\nThis level always operates individual layers. You won't have access to the stage aka composed view of layers.\n\n## Workflows\nThe typical workflow is to do all read/query operations in the high level API by creating/accessing a stage and then to do all the write operations in the low level API.\n\nIn DCCs, the data creation is done by the software, after that it is your job to massage the data to its final form based on what your pipeline needs:\n\nIn the daily business, you'll be doing this 90% of the time:\n\n- Rename/Remove prims\n- Create additional properties/attributes/relationships\n- Add metadata\n\n~~~admonish danger title=\"\"\nSounds simple, right? Ehm right??\n~~~\n\nWell yes and no. This guide tries to give you good pointers of common pitfalls you might run into.\n\nSo let's get started with specifics!\n\n\n\n\n"
  },
  {
    "path": "docs/src/pages/core/composition/arcs.md",
    "content": "# Composition Arcs\nIn this section we'll cover how to create composition arcs via code. To check our how composition arcs interact with each other, check out our [Composition Strength Ordering (LIVRPS)](./livrps.md) section.\n\nPlease read out [fundamentals section](./fundamentals.md) as we often refer to it on this page. \n\n\n# Table of Contents\n1. [Composition Arcs In-A-Nutshell](#summary)\n1. [What should I use it for?](#usage)\n1. [Resources](#resources)\n1. [Overview](#overview)\n1. [Composition Arcs](#compositionArcs)\n    1. [Sublayers / Local Opinions](#compositionArcSublayer)\n        1. [Value Clips](#compositionArcValueClips)\n    1. [Inherits](#compositionArcInherit)\n    1. [Variants](#compositionArcVariant)\n    1. [References](#compositionArcReference)\n        1. [References File](#compositionArcReferenceExternal)\n        1. [References Internal](#compositionArcReferenceInternal)\n    1. [Payloads](#compositionArcPayload)\n    1. [Specializes](#compositionArcSpecialize)\n\n## TL;DR - Composition Arcs In-A-Nutshell <a name=\"summary\"></a>\n- Creating composition arcs is straight forward, the high level API wraps the low level list editable ops with a thin wrappers. We can access the high level API via the `Usd.Prim.Get<ArcName>` syntax.\n- Editing via the low level API is often just as easy, if not easier, especially when [creating (nested) variants](#compositionArcVariantCopySpec). The list editable ops can be set via `Sdf.PrimSpec.SetInfo(<arcType>, <listEditableOp>)` or via the properties e.g. `Sdf.PrimSpec.<arcType>List`.\n\n## What should I use it for? <a name=\"usage\"></a>\n~~~admonish tip\nWe'll be using the below code, whenever we write composition arcs in USD.\n~~~\n\n## Resources <a name=\"resources\"></a>\n- [Sdf.Layer](https://openusd.org/dev/api/class_sdf_layer.html)\n- [Sdf.LayerOffset](https://openusd.org/dev/api/class_sdf_layer_offset.html)\n- [Sdf.\\<Arc\\>ListOp](https://www.sidefx.com/docs/hdk/list_op_8h.html)\n- [Usd.Inherits](https://openusd.org/dev/api/class_usd_inherits.html)\n- [Usd.VariantSets](https://openusd.org/dev/api/class_usd_variant_sets.html)\n- [Usd.VariantSet](https://openusd.org/dev/api/class_usd_variant_set.html)\n- [Usd.References](https://openusd.org/dev/api/class_usd_references.html)\n- [Sdf.VariantSetSpec](https://openusd.org/dev/api/class_sdf_variant_set_spec.html)\n- [Sdf.VariantSpec](https://openusd.org/dev/api/class_sdf_variant_spec.html)\n- [Sdf.Reference](https://openusd.org/dev/api/class_sdf_reference.html)\n- [Usd.Payloads](https://openusd.org/dev/api/class_usd_payloads.html)\n- [Sdf.Reference](https://openusd.org/dev/api/class_sdf_payload.html)\n- [Usd.Specializes](https://openusd.org/dev/api/class_usd_specializes.html)\n\n## Overview <a name=\"overview\"></a>\nThis section will focus on how to create each composition arc via the high and low level API.\n\n## Composition Arcs\nAll arcs that make use of [list-editable ops](./fundamentals.md#list-editable-operations-ops), take of of these tokens as an optional `position` keyword argument via the high level API.\n\n- `Usd.ListPositionFrontOfAppendList`: Prepend to append list, the same as `Sdf.<Type>ListOp`.appendedItems.insert(0, item)\n- `Usd.ListPositionBackOfAppendList`: Append to append list, the same as `Sdf.<Type>ListOp`.appendedItems.append(item)\n- `Usd.ListPositionFrontOfPrependList`: Prepend to prepend list, the same as `Sdf.<Type>ListOp`.appendedItems.insert(0, item)\n- `Usd.ListPositionBackOfPrependList`: Append to prepend list, the same as `Sdf.<Type>ListOp`.appendedItems.append(item)\n\nAs we can see, all arc APIs, except for sublayers, in the high level API, are thin wrappers around the [list editable op](./fundamentals.md#list-editable-operations-ops) of the arc.\n\n\n### Sublayers / Local Opinions <a name=\"compositionArcSublayer\"></a>\n~~~admonish tip title=\"Pro Tip | What do I use sublayer arcs for?\"\nIn our [Composition Strength Ordering (LIVRPS)](./livrps.md#compositionArcSublayer) section we cover in detail, with production related examples, what the sublayer arc is used for.\n~~~\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/composition.py:compositionArcSublayer}}\n```\n~~~\n\nWhen working in Houdini, we can't directly sublayer onto the root layer as with native USD, due to Houdini's layer caching mechanism, that makes node based stage editing possible. Layering on the active layer works as usual though.\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/composition.py:compositionArcSublayerHoudini}}\n```\n~~~\n\nHere is the result:\n\n![Alt text](../../../media/core/composition/houdiniCompositionSublayerPython.jpg)\n\n#### Value Clips <a name=\"compositionArcValueClips\"></a>\n~~~admonish tip title=\"Pro Tip | What do I use value clips for?\"\nIn our [Composition Strength Ordering (LIVRPS)](./livrps.md#compositionArcValueClips) section we cover in detail, with production related examples, what value clips are used for.\n~~~\n\nWe cover value clips in our [animation section](../elements/animation.md). Their opinion strength is lower than direct (sublayer) opinions, but higher than anything else.\n\nThe write them via metadata entries as covered here in our [value clips](../elements/animation.md#value-clips-loading-time-samples-from-multiple-files) section.\n\n### Inherits <a name=\"compositionArcInherit\"></a>\n~~~admonish tip title=\"Pro Tip | What do I use inherit arcs for?\"\nIn our [Composition Strength Ordering (LIVRPS)](./livrps.md#compositionArcInherit) section we cover in detail, with production related examples, what the inherit arc is used for.\n~~~\n\nInherits, like specializes, don't have a object representation, they directly edit the list-editable op list.\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/composition.py:compositionArcInherit}}\n```\n~~~\n\n### Variants <a name=\"compositionArcVariant\"></a>\n~~~admonish tip title=\"Pro Tip | What do I use variant arcs for?\"\nIn our [Composition Strength Ordering (LIVRPS)](./livrps.md#compositionArcVariant) section we cover in detail, with production related examples, what the variant arc is used for.\n~~~\n\nVariant sets (the variant set->variant name mapping) are also managed via list editable ops.\nThe actual variant set data is not though. It is written \"in-line\" into the prim spec via the `Sdf.VariantSetSpec`/`Sdf.VariantSpec` specs, so that's why we have dedicated specs.\n\nThis means we can add variant data, but hide it by not adding the variant set name to the `variantSets`metadata.\n\nFor example here we added it:\n\n~~~admonish tip title=\"\"\n```python\ndef Xform \"car\" (\n    variants = {\n        string color = \"colorA\"\n    }\n    prepend variantSets = \"color\"\n)\n{\n    variantSet \"color\" = {\n        \"colorA\" {\n            def Cube \"cube\"\n            {\n            }\n        }\n        \"colorB\" {\n            def Sphere \"sphere\"\n            {\n            }\n        }\n    }\n}\n```\n~~~\n\nHere we skipped it, by commenting out the:\n`car_prim_spec.SetInfo(\"variantSetNames\", Sdf.StringListOp.Create(prependedItems=[\"color\"]))` line in the below code.\nThis will make it not appear in UIs for variant selections.\n\n~~~admonish tip title=\"\"\n```python\ndef Xform \"car\" (\n    variants = {\n        string color = \"colorA\"\n    }\n)\n{\n    variantSet \"color\" = {\n        \"colorA\" {\n            def Cube \"cube\"\n            {\n            }\n        }\n        \"colorB\" {\n            def Sphere \"sphere\"\n            {\n            }\n        }\n    }\n}\n```\n~~~\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/composition.py:compositionArcVariant}}\n```\n~~~\n\n<a name=\"compositionArcVariantCopySpec\"></a>\n~~~admonish tip title=\"Pro Tip | Copying layer content into a variant\"\nWhen editing variants, we can also move layer content into a (nested) variant very easily via the `Sdf.CopySpec` command. This is a very powerful feature!\n\n```python\n{{#include ../../../../../code/core/composition.py:compositionArcVariantCopySpec}}\n```\n~~~\n\nHere is how we can created nested variant sets via the high level and low level API. As you can see it is quite a bit easier with the low level API.\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/composition.py:compositionArcVariantNested}}\n```\n~~~\n\n\n### References <a name=\"compositionArcReference\"></a>\n~~~admonish tip title=\"Pro Tip | What do I use reference arcs for?\"\nIn our [Composition Strength Ordering (LIVRPS)](./livrps.md#compositionArcReference) section we cover in detail, with production related examples, what the reference arc is used for.\n~~~\n\nThe `Sdf.Reference` class creates a read-only reference description object:\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/composition.py:compositionArcReferenceClass}}\n```\n~~~\n\n#### References File <a name=\"compositionArcReferenceExternal\"></a>\nHere is how we add external references (references that load data from other files):\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/composition.py:compositionArcReferenceExternal}}\n```\n~~~\n\n\n#### References Internal <a name=\"compositionArcReferenceInternal\"></a>\nHere is how we add internal references (references that load data from another part of the hierarchy) :\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/composition.py:compositionArcReferenceInternal}}\n```\n~~~\n\n### Payloads <a name=\"compositionArcPayload\"></a>\n~~~admonish tip title=\"Pro Tip | What do I use payload arcs for?\"\nIn our [Composition Strength Ordering (LIVRPS)](./livrps.md#compositionArcPayload) section we cover in detail, with production related examples, what the payload arc is used for.\n~~~\n\nThe `Sdf.Payload` class creates a read-only payload description object:\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/composition.py:compositionArcPayloadClass}}\n```\n~~~\n\nHere is how we add payloads. Payloads always load data from other files:\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/composition.py:compositionArcPayload}}\n```\n~~~\n\n### Specializes <a name=\"compositionArcSpecialize\"></a>\n~~~admonish tip title=\"Pro Tip | What do I use specialize arcs for?\"\nIn our [Composition Strength Ordering (LIVRPS)](./livrps.md#compositionArcSpecialize) section we cover in detail, with production related examples, what the specialize arc is used for.\n~~~\n\nSpecializes, like inherits, don't have a object representation, they directly edit the list-editable op list.\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/composition.py:compositionArcSpecialize}}\n```\n~~~"
  },
  {
    "path": "docs/src/pages/core/composition/fundamentals.md",
    "content": "# Composition Fundamentals\n\nIn this section will talk about fundamental concepts that we need to know before we look at individual composition arcs.\n\n~~~admonish question title=\"Still under construction!\"\nAs composition is USD's most complicated topic, this section will be enhanced with more examples in the future.\nIf you detect an error or have useful production examples, please [submit a ticket](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/issues/new), so we can improve the guide!\n~~~\n\n# Table of Contents\n1. [Composition Fundamentals In-A-Nutshell](#summary)\n1. [Why should I understand the editing fundamentals?](#usage)\n1. [Resources](#resources)\n1. [Overview](#overview)\n1. [Terminology](#terminology)\n1. [Composition Editing Principles - What do we need to know before we start?](#compositionFundamentals)\n    1. [List-Editable Operations](#compositionFundamentalsListEditableOps)\n    1. [Encapsulation](#compositionFundamentalsEncapsulation)\n    1. [Layer Stack](#compositionFundamentalsLayerStack)\n    1. [Edit Target](#compositionFundamentalsEditTarget)\n\n## TL;DR - Composition Fundamentals In-A-Nutshell <a name=\"summary\"></a>\n- Composition editing works in the active [layer stack](#compositionFundamentalsLayerStack) via [list editable ops](#compositionFundamentalsListEditableOps). \n- When loading a layer (stack) from disk via `Reference` and `Payload` arcs, the contained composition structure is immutable (USD speak [encapsulated](#compositionFundamentalsEncapsulation)). This means you can't remove the arcs within the loaded files. As for what the arcs can use for value resolution: The `Inherit` and `Specialize` arcs still target the \"live\" composed stage and therefore still reflect changes on top of the encapsulated arcs, while the `Reference` arc is limited to seeing the encapsulated layer stack.\n\n## Why should I understand the editing fundamentals? <a name=\"usage\"></a>\n~~~admonish tip\nThis section houses terminology essentials and a detailed explanation of how the underlying mechanism of editing/composing arcs works.\nSome may consider it a deep dive topic, we'd recommend starting out with it first though, as it saves time later on when you don't understand why something might not work.\n~~~\n\n## Resources <a name=\"resources\"></a>\n- [USD Glossary]():\n    - [Layer Stack](https://openusd.org/release/glossary.html#usdglossary-layerstack)\n    - [Root Layer Stack](https://openusd.org/release/glossary.html#usdglossary-rootlayerstack)\n    - [Prim Index](https://openusd.org/release/glossary.html#usdglossary-index)\n    - [List Editing](https://openusd.org/release/glossary.html#list-editing)\n    - [LIVRPS](https://openusd.org/release/glossary.html#livrps-strength-ordering)\n    - [Path Translation](https://openusd.org/release/glossary.html#usdglossary-pathtranslation)\n    - [References](https://openusd.org/release/glossary.html#usdglossary-references)\n- [USD FAQ - When can you delete a reference?](https://openusd.org/release/usdfaq.html#when-can-you-delete-a-reference-or-other-deletable-thing)\n\n## Overview <a name=\"overview\"></a>\nBefore we start looking at the actual composition arcs and their strength ordering rules, let's first look at how composition editing works.\n\n## Terminology <a name=\"terminology\"></a>\nUSD's mechanism of linking different USD files with each other is called `composition`. Let's first clarify some terminology before we start, so that we are all on the same page:\n- **Opinion**: A written value in a layer for a metadata field or property.\n- **Layer**: A layer is an USD file on disk with [prims](../elements/prim.md) & [properties](../elements/property.md). (Technically it can also be in memory, but for simplicity on this page, let's think of it as a file on disk). More info in our [layer section](../elements/layer.md).\n- **Layer Stack**: A stack of layers (Hehe 😉). We'll explain it more in detail below, just remember it is talking about all the loaded layers that use the `sublayer` composition arc.\n- **Composition Arc**: A method of linking (pointing to) another layer or another part of the scene hierarchy. USD has different kinds of composition arcs, each with a specific behavior.\n- **Prim Index**: Once USD has processed all of our composition arcs, it builds a `prim index` that tracks where values can come from. We can think of the `prim index` as something that outputs an ordered list of `[(<layer (stack)>, <hierarchy path>), (<layer (stack)>, <hierarchy path>)]` ordered by the composition rules.\n- **Composed Value**: When looking up a value of a property, USD then checks each location of the `prim index` for a value and moves on to the next one if it can't find one. If no value was found, it uses a schema fallback (if the property came from a schema), other wise it falls back to not having a value (USD speak: not being `authored`).\n\nComposition is \"easy\" to explain in theory, but hard to master in production. It also a topic that keeps on giving and makes you question if you really understand USD. So don't worry if you don't fully understand the concepts of this page, they can take a long time to master. To be honest, it's one of those topics that you have to read yourself back into every time you plan on making larger changes to your pipeline.\n\nWe recommend really playing through as much scenarios as possible before you start using USD in production. Houdini is one of the best tools on the market that let's you easily concept and play around with composition. Therefore we will use it in our examples below.\n\n## Composition Editing Fundamentals - What do we need to know before we start? <a name=\"compositionFundamentals\"></a>\nNow before we talk about individual `composition arcs`, let's first focus on these different base principles composition runs on.\nThese principles build on each other, so make sure you work through them in order they are listed below.\n- [List-Editable Operations](#compositionFundamentalsListEditableOps)\n- [Encapsulation](#compositionFundamentalsEncapsulation)\n- [Layer Stack](#compositionFundamentalsLayerStack)\n- [Edit Target](#compositionFundamentalsEditTarget)\n\n### List-Editable Operations (Ops) <a name=\"compositionFundamentalsListEditableOps\"></a>\nUSD has the concept of list editable operations. Instead of having a \"flat\" array (`[Sdf.Path(\"/cube\"), Sdf.Path(\"/sphere\")]`) that stores what files/hierarchy paths we want to point to, we have wrapper array class that stores multiple sub-arrays. When flattening the list op, USD removes duplicates, so that the end result is like an ordered Python `set()`.\n\nTo make it even more confusing, composition arc list editable ops run on a different logic than \"normal\" list editable ops when looking at the final `composed value`.\n\nWe take a closer look at \"normal\" list editable ops in our [List Editable Ops section](./listeditableops.md), on this page we'll stay focused on the composition ones.\n\nAlright, let's have a quick primer on how these work. There are three sub-classes for composition related list editable ops:\n- `Sdf.ReferenceListOp`: The list op for the `reference` composition arc, stores `Sdf.Reference` objects.\n- `Sdf.PayloadListOp`: The list op for the `payload` composition arc, stores `Sdf.Reference` objects.\n- `Sdf.PathListOp`: The list op for `inherit` and `specialize` composition arcs, as these arcs target another part of the hierarchy (hence `path`) and not a layer. It stores `Sdf.Path` objects.\n\nThese are 100% identical in terms of list ordering functionality, the only difference is what items they can store (as noted above). Let's start of simple with looking at the basics:\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/composition.py:compositionListEditableOpsBasics}}\n```\n~~~\n\nSo far so good? Now let's look at how multiple of these list editable ops are combined. If you remember our [layer](../elements/layer.md) section, each layer stores our prim specs and property specs. The composition list editable ops are stored as metadata on the prim specs. When USD composes the stage, it combines these and then starts building the composition based on the composed result of these metadata fields.\n\nLet's mock how USD does this without layers:\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/composition.py:compositionListEditableOpsMerging}}\n```\n~~~\n\nWhen working with multiple layers, each layer can have list editable ops data in the composition metadata fields. It then gets merged, as mocked above. The result is a single flattened list, without duplicates, that then gets fed to the composition engine.\n\nHere comes the fun part:\n\n~~~admonish danger title=\"List-Editable Ops | Getting the composed (combined) value\"\nWhen looking at the metadata of a prim via UIs (USD View/Houdini) or getting it via the Usd.Prim.GetMetadata() method, you will only see the list editable op of the last layer that edited the metadata, **NOT** the composed result. \n\nThis is probably the most confusing part of USD in my opinion when first starting out. To inspect the full composition result, we actually have to consult the [PCP cache](pcp.md) or run a `Usd.PrimCompositionQuery`. There is another caveat though too, as you'll see in the next section: Composition is **encapsulated**. This means our edits to list editable ops only work in the active `layer stack`. More info below!\n~~~\n\nIn Houdini the list editable ops are exposed on the `reference` node. The \"Reference Operation\" parm sets what sub-array (prepend,append,delete) to use, the \"Pre-Operation\" sets it to `.Clear()` in `Clear Reference Edits in active layer` mode and to `.ClearAndMakeExplicit()` in \"Clear All References\" mode.\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/core/composition/houdiniReferenceComposition.mp4\" type=\"video/mp4\" alt=\"Houdini - Reference Node - List Editable Ops\">\n</video>\n\nHere is how Houdini (but also the USD view) displays the references metadata field with different layers, as this is how the stage sees it.\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/core/composition/houdiniReferenceListEditableOpsLayers.mp4\" type=\"video/mp4\" alt=\"Houdini - List Editable Ops with layers\">\n</video>\n\nYou can see, as soon as we have our reference list editable op on different layers, the metadata only show the top most layer. To inspect all the references that are being loaded, we therefore need to look at the layer stack (the \"Scene Graph Layers\" panel) or perform a [compsition query](../../production/caches/composition.md).\n\nAlso a hint on terminology: In the USD docs/glossary the `Reference` arc often refers to all composition arcs other than `sublayer`, I guess this is a relic, as this was probably the first arc. That's why Houdini uses a similar terminology.\n\n### Encapsulation <a name=\"compositionFundamentalsEncapsulation\"></a>\nWhen you start digging through the API docs, you'll read the word \"encapsulation\" a few times. Here is what it means and why it is crucial to understand.\n\n~~~admonish danger title=\"Encapsulation | Why are layers loaded via references/payloads composition arc locked?\"\nTo make USD composition fast and more understandable, the content of what is loaded from an external file via the **`Reference`** and **`Payload`** composition arcs, is **composition locked** or as USD calls it **encapsulated**. This means that you can't remove any of the composition arcs in the layer stack, that is being loaded, via the list editable ops `deletedItems` list or via the `explicitItems`.\n~~~\n\nThe only way to get rid of a `payload`/`reference` is by putting it behind a `variant` in the first place and then changing the `variant` selection. This can have some unwanted side effects though. You can find a detailed explanation with an example here: [USD FAQ - When can you delete a reference?](https://openusd.org/release/usdfaq.html#when-can-you-delete-a-reference-or-other-deletable-thing)\n\n~~~admonish important title=\"Encapsulation | Are my loaded layers then self contained?\"\nYou might be wondering now, if encapsulation forces the content of `Reference`/`Payload` to be self contained, in the sense that the composition arcs within that file do not \"look\" outside the file. The answer is: It depends on the composition arc.\n\nFor `Inherits` and `Specializes` the arcs still evaluate relative to the composed scene. E.g. that means if you have an inherit somewhere in a referenced in layer stack, that `inherit` will still be live. So if you edit a property in the active stage, that gets inherited somewhere in the file, it will still propagate all the changes from the inherit source to all the inherit targets. The only thing that is \"locked\" is the composition arcs structure, not the way the composition arc evaluates. This extra \"live\" lookup has a performance penalty, so be careful with using `Inherits` and `Specializes` when nesting layers stacks via `References` and `Payloads`.\n\nFor `Internal References` this does not work though. They can only see the encapsulated layer stack and not the \"live\" composed stage. This makes composition faster for internal references.\n\nWe show some interactive examples in Houdini in our [LIVRPS](../composition/livrps.md#compositionArcReferencePayloadEncapsulation) section, as this is hard to describe in words.\n~~~\n\n### Layer Stack <a name=\"compositionFundamentalsLayerStack\"></a>\nWhat is the layer stack, that we keep mentioning, you might ask yourself?\nTo quote from the [USD Glossary](https://openusd.org/release/glossary.html#usdglossary-layerstack)\n\n~~~admonish quote title=\"\"\nThe ordered set of layers resulting from the recursive gathering of all SubLayers of a Layer, plus the layer itself as first and strongest.\n~~~\n\nSo to summarize, all (sub)-layers in the stage that were not loaded by `Reference` and `Payload` arcs.\n\nNow you might be thinking, isn't that the same thing as when we open a Usd file via `Usd.Stage.Open`? Well kind of, yes. When opening a stage, the USD file you open and its sublayers are the layer stack. USD actually calls this the `Root Layer Stack` (it also includes the sessions layers). So one could say, **editing a stage is process of editing a layer stack**. To extend that analogy, we could call a stage, that was written to disk and is being loaded via `Reference` and `Payload` arcs, an encapsulated layer stack.\n\nThese are the important things to understand (as also mentioned in the glossary):\n\n~~~admonish important title=\"Layer Stack | How does it affect composition?\"\n- Composition arcs target the layer stack, not individual layers. They recursively target the composed result (aka the result of all layers combined via the composition arc rules) of each layer they load in.\n- We can only list edit composition arcs via list editable ops in the active layer stack. The active layer stack is usually the active stage (unless when we \"hack\" around it via edit targets, which you 99% of the time don't do).\n~~~\n\nSo to make it clear again (as this is very important when we setup our asset/shot composition structure): **We can only update `Reference` and `Payload` arcs in the active layer stack. Once the active layer stack has been loaded via `Reference` and `Payload` arcs into another layer stack, it is encapsulated and we can't change the composition structure.**\n\nThis means to keep our pipeline flexible, we usually have \"only\" three kind of layer stacks:\n- **Asset Layer Stack**: When building assets, we build a packaged asset element. The end result is a (nested) layer stack that loads in different aspects of the asset (model/materials/fx/etc.). Here the main \"asset.usd\" file, that at the end we reference into our shots, is in control of \"final\" asset layer stack. We usually don't have any encapsulation issue scenarios, as the different assets layers are usually self contained or our asset composition structure is usually developed to sidestep encapsulation problems via variants. \n- **Shot Layer Stack**: The shot layer stack is the one that sublayers in all of your different shot layers that come from different departments. That's right, since we sublayer everything, we still have access to list editable ops on everything that is loaded in via composition arcs that are generated in individual shot layers. This keeps the shot pipeline flexible, as we don't run into the encapsulation problem.\n- **Set/Environment/Assembly Layer Stack** (Optional): We can also reference in multiple assets to an assembly type of asset, that then gets referenced into our shots. This is where you might run into encapsulation problems. For example, if we want to remove a reference from the set from our shot stage, we can't as it is baked into the composition structure. The usual way around it is to: 1. Write the assembly with variants, so we can variant away unwanted assets. 2. Deactivate the asset reference 3. Write the asset reference with variants and then switch to a variant that is empty.\n\n\n### Edit Target <a name=\"compositionFundamentalsEditTarget\"></a>\nTo sum up edit targets in once sentence:\n\n~~~admonish tip title=\"Pro Tip | Edit Targets\"\nA edit target defines, what layer all calls in the high level API should write to.\n~~~\n\nLet's take a look what that means:\n\nAn edit target's job is to map from one namespace to another, we mainly use them for writing to layers in the active layer stack (though we could target any layer) and to write variants, as these are written \"inline\" and therefore need an extra name space injection. \n\nSetting the edit target is done on the stage, as this is our \"controller\" of layers in the high level API: \n\n~~~admonish tip title=\"\"\n```python\nstage.SetEditTarget(layer)\n# We can also explicitly create the edit target:\n# Or\nstage.SetEditTarget(Usd.EditTarget(layer))\n# Or\nstage.SetEditTarget(stage.GetEditTargetForLocalLayer(layer))\n# These all have the same effect.\n```\n~~~\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/composition.py:compositionEditTarget}}\n```\n~~~\n\nFor convenience, USD also offers a context manager for variants, so that we don't have to revert to the previous edit target once we are done:\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/composition.py:compositionEditTargetContext}}\n```\n~~~"
  },
  {
    "path": "docs/src/pages/core/composition/listeditableops.md",
    "content": "# List Editable Ops (Operations)\nOn this page we will have a look at list editable ops when not being used in composition arcs.\n\n~~~admonish danger\nAs mentioned in our [fundamentals](./fundamentals.md#compositionFundamentalsListEditableOps) section, list editable ops play a crucial role to understanding composition. Please read that section before this one, as we build on what was written there.\n~~~\n\n# Table of Contents\n1. [List Editable Ops In-A-Nutshell](#summary)\n1. [What should I use it for?](#usage)\n1. [Resources](#resources)\n1. [Overview](#overview)\n1. [Composition Arcs](#listOpCompositionArc)\n1. [Relationships](#listOpRelationship)\n1. [Metadata](#listOpMetadata)\n\n## TL;DR List Editable Ops - <Topic> In-A-Nutshell <a name=\"summary\"></a>\n- USD has the concept of list editable operations. Instead of having a \"flat\" array (`[Sdf.Path(\"/cube\"), Sdf.Path(\"/sphere\")]`) that stores data, we have wrapper array class that stores multiple sub-arrays (`prependedItems`, `appendedItems`, `deletedItems`, `explicitItems`). When flattening the list op, it merges the prepended and appended items and also removes items in deletedItems as well as duplicates, so that the end result is like an ordered Python `set()`. When in explicit mode, it only keeps the elements in explicitItems and ignores previous layers. This merging is done per layer, so that for example an `appendedItems` op in a higher layer, gets added to an `explicitItems` from a lower layer. This allows us to average the array data over multiple layers.\n- List editable ops behave differently based on the type:\n    - **Composition**: When using list editable ops to define composition arcs, we can only edit them in the [active layer stack](./fundamentals.md#compositionFundamentalsLayerStack). Once referenced or payloaded, they become [encapsulated](./fundamentals.md#compositionFundamentalsEncapsulation).\n    - **Relationships/Metadata**: When making use of list editable ops when defining relationships and metadata, we do not have encapsulation. This means that any layer stack can add/delete/set explicit the list editable type. See the examples below for more info.\n\n## What should I use it for? <a name=\"usage\"></a>\n~~~admonish tip\nUsing list editable ops in non composition arc scenarios is rare, as we often want a more attribute like value resolution behavior. It is good to know though that the mechanism is there. A good production use case is making metadata that tracks asset dependencies list editable, that way all layers can contribute to the sidecar data.\n~~~\n\n## Resources <a name=\"resources\"></a>\n- [USD Glossary - List Editing](https://openusd.org/release/glossary.html#list-editing)\n\n## Overview <a name=\"overview\"></a>\nLet's first go other how list editable ops are edited and applied:\n\nThese are the list editable ops that are available to us:\n- Composition:\n    - `Sdf.PathListOp`\n    - `Sdf.PayloadListOp`\n    - `Sdf.ReferenceListOp`\n- Base Data Types:\n    - `Sdf.PathListOp`\n    - `Sdf.StringListOp`\n    - `Sdf.TokenListOp`\n    - `Sdf.IntListOp`\n    - `Sdf.Int64ListOp`\n    - `Sdf.UIntListOp`\n    - `Sdf.UInt64ListOp`\n\nUSD has the concept of list editable operations. Instead of having a \"flat\" array (`[Sdf.Path(\"/cube\"), Sdf.Path(\"/sphere\")]`) that stores data, we have wrapper array class that stores multiple sub-arrays (`prependedItems`, `appendedItems`, `deletedItems`, `explicitItems`). When flattening the list op, it merges the prepended and appended items and also removes items in deletedItems as well as duplicates, so that the end result is like an ordered Python `set()`. When in explicit mode, it only keeps the elements in explicitItems and ignores previous layers. This merging is done per layer, so that for example an `appendedItems` op in a higher layer, gets added to an `explicitItems` from a lower layer. This allows us to average the array data over multiple layers.\n\nAll list editable ops work the same way, the only difference is what data they can hold.\n\nThese are 100% identical in terms of list ordering functionality, the only difference is what items they can store (as noted above). Let's start of simple with looking at the basics:\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/composition.py:listEditableOpsLowLevelAPI}}\n```\n~~~\n\nWhen working with 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):\n- `Usd.ListPositionFrontOfAppendList`: Prepend to append list, the same as `Sdf.<Type>ListOp`.appendedItems.insert(0, item)\n- `Usd.ListPositionBackOfAppendList`: Append to append list, the same as `Sdf.<Type>ListOp`.appendedItems.append(item)\n- `Usd.ListPositionFrontOfPrependList`: Prepend to prepend list, the same as `Sdf.<Type>ListOp`.appendedItems.insert(0, item)\n- `Usd.ListPositionBackOfPrependList`: Append to prepend list, the same as `Sdf.<Type>ListOp`.appendedItems.append(item)\n\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/composition.py:listEditableOpsHighLevelAPI}}\n```\n~~~\n\nNow let's look at how multiple of these list editable ops are combined. \n\n~~~admonish important title=\"Pro Tip | List Editable OPs in Metadata \"\nAgain it is very important, that composition arc related list editable ops get combined with a different rule set. We cover this extensively in our [fundamentals](./fundamentals.md) section.\n\nNon-composition related list editable ops do not make use of [encapsulation](./fundamentals.md#compositionFundamentalsEncapsulation). This means that any layer can contribute to the result, meaning any layer can add/remove/set explicit. When getting the value of the list op for non-composition arc list ops, we get the absolute result, in the form of an explicit list editable item list.\n\nIn contrast: When looking at composition list editable ops, we only get the value of the last layer that edited the value, and we have to use composition queries to get the actual result.\n\nThis makes non-composition list editable ops a great mechanism to store averaged side car data. Checkout our Houdini example below, to see this in action.\n~~~\n\nLet's mock how USD does this (without using `Sdf.Layer`s to keep it simple):\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/composition.py:listEditableOpsMerging}}\n```\n~~~\n\nWhen working with multiple layers, each layer can have list editable ops data in (composition-) metadata fields and relationship specs. It then gets merged, as mocked above. The result is a single flattened list, without duplicates.\n\n## Composition Arcs <a name=\"listOpCompositionArc\"></a>\nFor a detailed explanation how list editable ops work in conjunction with composition arcs, please check out our [composition fundamentals](./fundamentals.md) section.\n\n## Relationships <a name=\"listOpRelationship\"></a>\nAs with list editable metadata, relationships also show us the combined results from multiple layers. Since it is not a composition arc list editable op, we also don't have the restriction of encapsulation. That means, calling `GetTargets`/`GetForwardedTargets` can combine appended items from multiple layers. Most DCCs go for the `.SetTargets` method though, as layering relationship data can be confusing and often not what we want as an artist using the tools.\n\n~~~admonish important title=\"Pro Tip | List Editable OPs in Collections \"\nSince [collections](../elements/collection.md) are made up of relationships, we can technically list edit them too. Most DCCs set the collection relationships as an explicit item list though, as layering paths can be confusing. \n~~~\n\n## Metadata <a name=\"listOpMetadata\"></a>\nThe default metadata fields that ship with USD, are not of the list editable type. We can easily extend this via a metadata plugin though.\n \nHere is a showcase from our composition example file that edits a custom string list op field which we registered via a [custom meta plugin](../plugins/metadata.md). \n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/core/composition/houdiniListEditableOpsMetadata.mp4\" type=\"video/mp4\" alt=\"Houdini Custom ListEditableOps Metadata\">\n</video>\n\nAs you can see the result is dynamic, even across encapsulated arcs and it always returns an explicit list op with the combined results.\n\nThis can be used to combine metadata non destructively from multiple layers."
  },
  {
    "path": "docs/src/pages/core/composition/livrps.md",
    "content": "# Composition Strength Ordering (LIVRPS)\nIn this section we'll cover how composition arcs work and interact with each other. We cover how to create composition arcs via code in our [composition arcs](./arcs.md) section. This section will also have code examples, but with the focus on practical usage instead of API structure.\n\n~~~admonish tip\nWe have a supplementary Houdini scene, that you can follow along with, available in this [site's repository](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/tree/main/files/composition). All the examples below will walk through this file as it easier to prototype and showcase arcs in Houdini via nodes, than writing it all in code.\n~~~\n\n# Table of Contents\n1. [Composition Strength Ordering In-A-Nutshell](#summary)\n1. [What should I use it for?](#usage)\n1. [Resources](#resources)\n1. [Overview](#overview)\n1. [Composition Strength Ordering](#compositionStrengthOrdering)\n1. [Composition Arc Categories](#compositionArcCategory)\n    1. [Composition Arc By Use Case](#compositionArcCategoryByUseCase)\n    1. [Composition Arc By Time Offset/Scale Capability](#compositionArcCategoryByTimeOffset)\n    1. [Composition Arc By Target Type (File/Hierarchy)](#compositionArcCategoryByTargetType)\n1. [Composition Arcs](#compositionArcs)\n    1. [Sublayers / Local Direct Opinions](#compositionArcSublayer)\n        1. [Value Clips](#compositionArcValueClips)\n    1. [Inherits](#compositionArcInherit)\n    1. [Variants](#compositionArcVariant)\n        1. [Nested Variants](#compositionArcVariantNested)\n        1. [Variant Data Lofting](#compositionArcVariantLofting)\n        1. [Sharing data among variants](#compositionArcVariantSharing)\n        1. [Efficiently re-writing existing data as variants](#compositionArcVariantReauthor)\n    1. [References](#compositionArcReference)\n        1. [Composition encapsulation for references (and payloads)](#compositionArcReferencePayloadEncapsulation)\n        1. [Nested composition and list editable op order](#compositionArcReferenceStrongWeakerListOrder)\n    1. [Payloads](#compositionArcPayload)\n        1. [Workflows for loading payloads over references in shots](#compositionArcPayloadLoadWorkflow)\n    1. [Specializes](#compositionArcSpecialize)\n1. [Instancing in USD](#compositionInstance)\n\n## TL;DR - Composition Arcs In-A-Nutshell <a name=\"summary\"></a>\nHere are the arcs in their composition strength order and their main intent:\n- **L**ocal Opinions/Sublayers**: The sublayer arc is used to build up your stage root layer stack. They can be time offset/scaled via a Sdf.LayerOffset, see our code examples.\n- **I**nherits: The inherit arc is used to add overrides to existing (instanceable) prims. The typical use case is to apply an edit to a bunch of referenced in assets that were loaded as instanceable without losing instance-ability and without increasing the prototype count. It does not support adding a time offset via Sdf.LayerOffset.\n- **V**ariants: The variant arc is used to allow users to switch through different variations of sub-hierarchies. It does not support adding any time offsets via Sdf.LayerOffsets.\n- **R**eferences: The reference arc is one of the most used arcs. Its main purpose is to aggregate scene description data from other files or sub-hierarchies. It is the only arc that has both file loading and internal hierarchy linking/loading possibilities. It does support adding time offsets via Sdf.LayerOffsets.\n- **P**ayloads: The payload arc is also one of the most used arcs. Its main purpose is to load heavy data. This means it is the arc that you'll use when loading any type of renderable geometry. It does support adding time offsets via Sdf.LayerOffsets.\n- **S**pecializes: The specialize arc is used to supply \"template\" like values to your prim hierarchy. Any other arc can then overrides these. If we update the \"template\", all overrides from other arcs are kept. It does not support adding a time offset via Sdf.LayerOffset.\n- **(F)** allback value: If no value is found, [schemas](../elements/schemas.md) can provide fallback values.\n\nThis is a very nuanced topic, therefore we recommend working through this section to fully understand it.\n\n## What should I use it for? <a name=\"usage\"></a>\n~~~admonish tip\nWe'll be using composition arcs to load data from different files and hierarchy locations. This is the core mechanism that makes USD powerful, as we can layer/combine our layers in meaningful ways.\n\nFor USD to be able to scale well, we can also \"lock\" the composition on prims with the same arcs, so that they can use the same data source. This allows us to create instances, which keep our memory footprint low.\n~~~\n\n## Resources <a name=\"resources\"></a>\n- [USD Glossary - LIVRPS Composition Strength Ordering](https://openusd.org/release/glossary.html#livrps-strength-ordering)\n- [USD Glossary - Direct Opinions](https://openusd.org/release/glossary.html#direct-opinion)\n- [USD Glossary - Inherits](https://openusd.org/release/glossary.html#usdglossary-inherits)\n- [USD Glossary - Variants](https://openusd.org/release/glossary.html#usdglossary-variant)\n- [USD Glossary - References](https://openusd.org/release/glossary.html#usdglossary-references)\n- [USD Glossary - Payloads](https://openusd.org/release/glossary.html#usdglossary-payload)\n- [USD Glossary - Specializes](https://openusd.org/release/glossary.html#usdglossary-specializes)\n- [USD Instancing](https://openusd.org/release/api/_usd__page__scenegraph_instancing.html)\n\n## Overview <a name=\"overview\"></a>\nUSD's composition arcs each fulfill a different purpose. As we can attach attach all arcs (except sublayers) to any part of the hierarchy other than the pseudo root prim. When loading our data, we have a pre-defined load order of how arcs prioritize against each other. Each prim (and property) in our hierarchy then gets resolved (see our [Inspecting Compositon](./pcp.md) section) based on this order rule set and the outcome is a (or multiple) value sources, that answer data queries into our hierarchy.\n\nAll arcs, except the `sublayer` arc, target (load) a specific prim of a layer stack (**NOT layer**). This allows us to rename the prim, where the arc is created on, to something different, than what the arc's source hierarchy prim is named. An essential task that USD performs for us, is mapping paths from the target layer to the source layer (stack).\n\n~~~admonish important title=\"Important | Good-To-Knows\"\n- Composition arcs target layer stacks, not individual layers. This just means that they recursively load what is in a layer.\n- When arcs target a non root prim, they do **not** receive parent data that usually \"flows\" down the hierarchy. This means that primvars, material bindings or transforms from ancestor prims do not get \"inherited\" (we don't mean the inherited arc here). They **do** see the composition result though. So for example if your file reference targets a prim inside a variant, it can't change the variant as the variant is not in the stage it was referenced into to.\n- Internal composition arcs (inherit/internal references/specialize) cannot target ancestor or child arcs. We can only target sibling prims or prims that are at/under a different \"/\" stage root prim.\n- Composition arcs only look in the active layer stack and in \"higher\" layer stacks (layer stacks that reference/payload the active layer stack).\n~~~\n\n## Composition Strength Ordering <a name=\"compositionStrengthOrdering\"></a>\nTo prioritize how different arcs evaluate against each other, we have `composition strength ordering`. This is a fancy word for \"what layer (file) provides the actual value for my prim/property/metadata based on all available composition arcs\". (I think we'll stick to using `composition strength ordering` 😉).\n\nAll arcs, except sublayers, make use of list editing, see our [fundamentals](./fundamentals.md#compositionFundamentalsListEditableOps) for a detailed explanation. We highly recommend reading it first before continuing.\n\nLet's look at the order:\n\n![LIVRPS Order Visualized](../../../media/core/composition/compositionLIVRPS.svg)\n~~~admonish quote title=\"Credits\"\nAll credits for this info graphic go to [Remedy-Entertainment - Book Of USD](https://remedy-entertainment.github.io/USDBook/terminology/LIVRPS.html). Check out their site, it is another great value source for USD.\n~~~\n\nUSD refers to this with the acronym `L(V)IVRPS(F)`:\n- **L**ocal: Search for [direct opinions](https://openusd.org/release/glossary.html#direct-opinion) in the active root layer stack. \n    - **V**alue Clips: Search for [direct opinions](https://openusd.org/release/glossary.html#direct-opinion) from value clips. These are weaker than direct opinions on layers.\n- **I**nherits: Search for inherits affecting the path. This searches in the (nested) layer stack by recursively applying *LIVRP* (No specializes) evaluation.\n- **V**ariant Sets: Search for variants affecting the path. This searches in the (nested) layer stack by recursively applying *LIVRP* (No specializes) evaluation.\n- **R**eferences: Search for references affecting the path. This searches in the (nested) layer stack by recursively applying *LIVRP* (No specializes) evaluation.\n- **P**ayloads: Search for payloads affecting the path. This searches in the (nested) layer stack by recursively applying *LIVRP* (No specializes) evaluation.\n- **S**pecializes: Search for payloads affecting the path. This searches in the (nested) layer stack by recursively applying full *LIVRPS* evaluation. This causes the specialize opinions to always be last.\n- **(F)** allback value: Look for [schema](../elements/schemas.md) fallbacks.\n\nNow if you just didn't understand any of that, don't worry! We'll have a look where what arc is typically used in the examples below.\n\n~~~admonish important title=\"Important | Nested Composition Arc Resolve Order\"\nWhen resolving nested composition arcs and value clips, the arc/value clip metadata, that is authored on the closest ancestor parent prim or the prim itself, wins. In short to quote from the USD glossary `“ancestral arcs” are weaker than “direct arcs”`. To make our lives easier, we recommend having predefined locations where you author composition arcs. A typical location is your asset root prim and a set/assembly root prim.\n~~~\n\n## Composition Arc Categories <a name=\"compositionArcCategory\"></a>\nLet's try looking at arcs from a use case perspective. Depending on what we want to achieve, we usually end up with a specific arc designed to fill our needs.\n\n### Composition Arc By Use Case <a name=\"compositionArcCategoryByUseCase\"></a>\nHere is a comparison between arcs by use case. Note that this is only a very \"rough\" overview, there are a few more things to pay attention to when picking the correct arc. It does help to first understand what the different arcs try to achieve though.\n\n~~~admonish tip title=\"\"\n```mermaid\nflowchart LR\n    userRoot([\"I want to load\"])\n    userExternal([\"a file (with a time offset/scale)\"])\n    userExternalWholeLayer([\"with the whole content (that is light weight and links to other files)\"])\n    userExternalHierarchyInLayer([\"with only a specific part of its hierarchy (to a specific path in the stage)\"])\n    userExternalHierarchyInLayerHeavyData([\"thats contains a lot of heavy data\"])\n    userExternalHierarchyInLayerLightData([\"thats contains light weight data\"])\n    userInternal([\"an existing sub-hierarchy in the active layer stack/stage\"])\n    userInternalTimeOffset([\"into a new hierarchy location (with a time offset/scale)\"])\n    userInternalOverride([\"to add overrides to multiple (instanced) prims\"])\n    userInternalBaseValues([\"to act as the base-line values that can be overriden by higher layers and arcs\"])\n    userInternalVariation([\"as a variation of the hierarchy\"])\n\n    compositionArcSublayer([\"Sublayer\"])\n    compositionArcInherit([\"Inherit\"])\n    compositionArcVariant([\"Variant\"])\n    compositionArcReferenceFile([\"Reference\"])\n    compositionArcReferenceInternal([\"Reference\"])\n    compositionArcPayload([\"Payload\"])\n    compositionArcSpecialize([\"Specialize\"])\n    style compositionArcSublayer fill:#63beff\n    style compositionArcInherit fill:#63beff\n    style compositionArcVariant fill:#63beff\n    style compositionArcReferenceFile fill:#63beff\n    style compositionArcReferenceInternal fill:#63beff\n    style compositionArcPayload fill:#63beff\n    style compositionArcSpecialize fill:#63beff\n\n    userRoot --> userExternal\n    userExternal --> userExternalWholeLayer\n    userExternal --> userExternalHierarchyInLayer\n    userExternalWholeLayer --> compositionArcSublayer\n    userExternalHierarchyInLayer --> userExternalHierarchyInLayerHeavyData\n    userExternalHierarchyInLayer --> userExternalHierarchyInLayerLightData\n    userExternalHierarchyInLayerLightData --> compositionArcReferenceFile\n    userExternalHierarchyInLayerHeavyData --> compositionArcPayload\n    userRoot --> userInternal\n    userInternal --> userInternalTimeOffset\n    userInternalTimeOffset --> compositionArcReferenceInternal\n    userInternal --> userInternalOverride\n    userInternalOverride --> compositionArcInherit\n    userInternal --> userInternalBaseValues\n    userInternalBaseValues --> compositionArcSpecialize\n    userInternal --> userInternalVariation\n    userInternalVariation --> compositionArcVariant\n```\n~~~\n\n### Composition Arc By Time Offset/Scale Capability <a name=\"compositionArcCategoryByTimeOffset\"></a>\nSome arcs can specify a time offset/scale via a`Sdf.LayerOffset`.\n~~~admonish tip title=\"\"\n```mermaid\nflowchart LR\n    userRoot([\"I want to\"])\n    userRootTimeOffset([\"time offset/scale my hierarchy (via a `Sdf.LayerOffset`)\"])\n    userRootNoTimeOffset([\"not time offset/scale my hierarchy\"])\n\n    compositionArcSublayer([\"Sublayer\"])\n    compositionArcInherit([\"Inherit\"])\n    compositionArcVariant([\"Variant\"])\n    compositionArcReference([\"Reference (External/Internal)\"])\n    compositionArcPayload([\"Payload\"])\n    compositionArcSpecialize([\"Specialize\"])\n    style compositionArcSublayer fill:#63beff\n    style compositionArcInherit fill:#63beff\n    style compositionArcVariant fill:#63beff\n    style compositionArcReference fill:#63beff\n    style compositionArcPayload fill:#63beff\n    style compositionArcSpecialize fill:#63beff\n\n    userRoot --> userRootTimeOffset\n    userRootTimeOffset --> compositionArcSublayer\n    userRootTimeOffset --> compositionArcReference\n    userRootTimeOffset --> compositionArcPayload\n    userRoot --> userRootNoTimeOffset\n    userRootNoTimeOffset --> compositionArcInherit\n    userRootNoTimeOffset --> compositionArcVariant\n    userRootNoTimeOffset --> compositionArcSpecialize\n```\n~~~\n\n### Composition Arc By Target Type (File/Hierarchy) <a name=\"compositionArcCategoryByTargetType\"></a>\nHere is a comparison between arcs that can target external layers (files) and arcs that target another part of the hierarchy.\n\n~~~admonish tip title=\"\"\n```mermaid\nflowchart TD\n    compositionArcSublayer([\"Sublayers (Direct Opinions)\"])\n    compositionArcValueClip([\"Value Clips (Lower than Direct Opinions)\"])\n    compositionArcInherit([\"Inherits\"])\n    compositionArcVariant([\"Variants\"])\n    compositionArcReferenceFile([\"References\"])\n    compositionArcReferenceInternal([\"References\"])\n    compositionArcPayload([\"Payloads\"])\n    compositionArcSpecialize([\"Specialize\"])\n    compositionArcInternal([\"Internal Arcs (Target Hierarchy)\"])\n    compositionArcExternal([\"File Arcs (Target File (+ Hierarchy))\"])\n    style compositionArcSublayer fill:#63beff\n    style compositionArcInherit fill:#63beff\n    style compositionArcVariant fill:#63beff\n    style compositionArcReferenceFile fill:#63beff\n    style compositionArcReferenceInternal fill:#63beff\n    style compositionArcPayload fill:#63beff\n    style compositionArcSpecialize fill:#63beff    \n\n    compositionArcInternal --> compositionArcInherit\n    compositionArcInternal --> compositionArcVariant\n    compositionArcInternal --> compositionArcReferenceInternal\n    compositionArcInternal --> compositionArcSpecialize\n    compositionArcExternal --> compositionArcSublayer\n    compositionArcExternal --> compositionArcReferenceFile\n    compositionArcExternal --> compositionArcPayload\n    compositionArcSublayer --> compositionArcValueClip\n```\n~~~\n\n\n## Composition Arcs <a name=\"compositionArcs\"></a>\nLet's gets practical! Below will go through every arc individually and highlight what is important.\n\n~~~admonish tip\nWe have a supplementary Houdini scene, that you can follow along with, available in this [site's repository](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/tree/main/files/composition). All the examples below will walk through this file as it easier to prototype and showcase arcs in Houdini via nodes, than writing it all in code.\n~~~\n\n### Sublayers / Local Direct Opinions <a name=\"compositionArcSublayer\"></a>\nThe sublayer arc is used to build up your stage [root layer stack](./fundamentals.md#compositionFundamentalsLayerStack). They can be time offset/scaled via a `Sdf.LayerOffset`, see our [code examples](./arcs.md#compositionArcSublayer).\n\n~~~admonish tip title=\"Pro Tip | What do we use sublayers for?\"\nTypically we'll be using sublayers for mainly these things:\n- As a mechanism to separate data when working in your DCCs. On file write we usually flatten layers to a single flattened output(s)(if you have multiple save paths set). Why not put everything on the same layer? We can use the layer order as a form of control to A. allow/block edits (or rather seeing them have an effect because of weaker opinion strength) B. Sort data from temporary data. \n- To load in references and payloads. That way all the heavy lifting is not done (and should not be done) by the sublayer arc.\n- In shot workflows to load different shot layers. Why don't we do this via references or payloads you might be asking yourself? As covered in our [fundamentals](./fundamentals.md#compositionFundamentalsEncapsulation) section, anything your reference or payload in will be encapsulated. In shot workflows we want to keep having access to list editable ops. For example if we have a layout and a lighting layer, the lighting layer should still be able to remove a reference, that was created in the layout layer.\n~~~\n\n~~~admonish tip title=\"Pro Tip | Editing sublayer arcs via the USD API\"\nIf you want to create/edit sublayer arcs via code, see our [Composition Arc - Code API](./arcs.md#compositionArcSublayer) section.\n~~~\n\nLet's look at how sublayers are used in native USD:\n\nWhen creating a stage we have two layers by default:\n- **Session Layer**: This is a temp layer that doesn't get applied on disk save. Here we usually put things like viewport overrides.\n- **Root Layer**: This is the base layer all edits target by default. We can add sublayers based on what we need to it. When calling `stage.Save()`, all sublayers that are dirty and not anonymous, will be saved. \n\nHow are sublayers setup in Houdini?\n\nIn Houdini every node always edits the top most root layer sublayer (in USD speak the layer to edit is called the **edit target**). This way we don't have to worry about what our layer, we want to write to, is. In the scene graph panel the session layer is displayed under the root layer, it is actually over (higher) than the root layer.\n\nTo summarize how Houdini makes node editing a layer based system possible (at least from what we can gather from reverse engineering): \n\nEvery node stashes a copy of the top most layer (Houdini calls it the **active layer**), that way, when we switch from node to node, it transfers back the content as soon as it needs to be displayed/cooked. This does have a performance hit (as covered in our [Houdini performance](../../dcc/houdini/performance/overview.md)) section. It also spawns a new stage per node when necessary, for example when a python LOP node or python parm expression accesses the previous node's stage. This mechanism gives the user the control to spawn new layers when needed. By default your network is color coded by what the active layer is.\n\n![Houdini Layer Stack](../../../media/core/composition/houdiniCompositionSublayerRootLayerStack.jpg)\n\nHoudini writes all your scene graph panel viewport overrides into session layer sublayers. By default these are not shown in the UI, you can view them by looking at the layer content though.\n\n![Alt text](../../../media/core/composition/houdiniCompositionSublayerSessionLayer.jpg)\n\nInstead of using layers non-anonymous save paths (layer identifiers) directly, all layers created in your session are anonymous layers (with Houdini specific metadata that tracks the save path). We're guessing that this is because all layers without a save path get merged into the next available layer with a save path on file save. If no layer has a save path, all content gets flattened into the layer file path you put on the USD rop.\n\n![Alt text](../../../media/core/composition/houdiniCompositionSublayerSavePath.jpg)\n\n#### Value Clips <a name=\"compositionArcValueClips\"></a>\nWe cover value clips in our [animation section](../elements/animation.md). Value clips are USD's mechanism for loading per frame (or per chunk) files, so that we don't have a single gigantic file for large caches.\n\nTheir opinion strength is lower than direct (sublayer) opinions, but higher than anything else. This of course is only relevant if we author time samples and value clips in the same layer. If we have multiple layers, then it behaves as expected, so the highest layers wins.\n\n~~~admonish tip title=\"Pro Tip | Editing value clips via the USD API\"\nValue clips are written via metadata entries on prims. If you want to create/edit value clips via code, see our [value clips](../elements/animation.md#value-clips-loading-time-samples-from-multiple-files) section.\n~~~\n\nHere is a comparison between a layer with value clip metadata and time samples vs separate layers with each.\nHoudini's \"Load Layer For Editing\", simply does a `active_layer.TransferContent(Sdf.Layer.FindOrOpen(\"/Disk/Layer.usd\"))`, in case you are wondering, so it fakes it as if we created the value clip metadata in the active layer.\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/core/composition/houdiniCompositionSublayerValueClip.mp4\" type=\"video/mp4\" alt=\"Houdini Sublayer Value Clip\">\n</video>\n\n~~~admonish tip title=\"Pro Tip | How do we load value clipped files?\"\nWe cover a production based example of how to load value clips in our [Composition for production](../../production/composition.md) section. Here are some import things to keep in mind:\n- When making prims instanceable, the value clip metadata has to be under the instanceable prim, as the value clip metadata can't be read from outside of the instance (as it would then mean each instance could load different clips, which would defeat the purpose of instanceable prims).\n- Value clip metadata can't be inherited/internally referenced/specialized in. It must reside on the prim as a direct opinion.\n\nSee the production examples for how to best load value clips.\n~~~\n\n### Inherits <a name=\"compositionArcInherit\"></a>\nThe inherit arc is used to add overrides to existing (instanceable) prims. The typical use case is to apply an edit to a bunch of referenced in assets that were loaded as instanceable without losing instance-ability and without increasing the prototype count. It does **not** support adding a time offset via `Sdf.LayerOffset`.\n\n~~~admonish tip title=\"Pro Tip | What do we use inherits for?\"\n- We use inherit arcs as a \"broadcast\" operator for overrides: When we want to apply an edit to our hierarchy in multiple places, we typically create a class prim, whose child prims contain the properties we want to modify. After that we create an inherit arc on all prims that should receive the edit. As it is the second highest arc behind direct opinions, it will always have the highest composition strength, when applied to instanceable prims, as instanceable prims can't have direct opinions.\n- The inherit arc lookup is never [encapsulated](./fundamentals.md#compositionFundamentalsEncapsulation), the inherit arc list-editable op is. This means that any layer stack, that re-creates the prims that that the inherit targets, gets used by the inherit. This does come at a performance cost, as the composition engine needs to check all layer stacks from where the arc was authored and higher for the hierarchy that the inherit targets.\n- The inherit arc commonly gets used together with the [class prim specifier](../elements/prim.md#primSpecifier). The class prim specifier is specifically there to get ignored by default traversals and to provide template hierarchies that can then get inherited (or internally referenced/specialized) to have a \"single source to multiple targets\" effect.  \n- Depending on if we are working on shots or assets are common practices:\n    - **Assets**: When creating assets, we can author a `/__CLASS__/<assetName>` inherit. When we use the asset in shots, we can then easily add overrides to all assets of this type, by creating prims and properties under that specific class prim hierarchy. While this sounds great in theory, artists often want to only selectively apply an override to an asset. Therefore having the additional performance cost of this arc in assets is something might not worth doing. See the next bullet point.\n    - **Shots**: This is where inherits shine! We usually create inherits to:\n        - Batch apply render geometry settings to (instanceable) prims. This is a great way of having a single control point to editing render settings per different areas of interest in your scene.\n        - Batch apply activation/visibility to instanceable prims. This way we don't increase the prototype count.\n~~~\n\n~~~admonish tip title=\"Pro Tip | Editing inherit arcs via the USD API\"\nIf you want to create/edit inherit arcs via code, see our [Composition Arc - Code API](./arcs.md#compositionArcInherit) section.\n~~~\n\nIn the accompanying [Houdini file](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/tree/main/files/composition) you can find the inherit example from the [USD Glossary - Inherit](https://openusd.org/release/glossary.html#usdglossary-inherits) section.\n\n~~~admonish tip title=\"Pro Tip | Add inherits to instanceable prims\"\nHere is a typical code pattern we'll use when creating inherits:\n```python\nfrom pxr import Sdf\n...\n# Inspect prototype and collect what to override\nprototype = prim.GetPrototype()\n...\n# Create overrides\nclass_prim = stage.CreateClassPrim(Sdf.Path(\"/__CLASS__/myCoolIdentifier\"))\nedit_prim = stage.DefinePrim(class_prim.GetPath().AppendChild(\"leaf_prim\"))\nedit_prim.CreateAttribute(\"size\", Sdf.ValueTypeNames.Float).Set(5)\n...\n# Add inherits\ninstance_prims = prototype.GetInstances()\nfor instance_prim in instance_prims:\n    inherits_api = instance_prim.GetInherits()\n    inherits_api.AddInherit(class_prim.GetPath(), position=Usd.ListPositionFrontOfAppendList)    \n```\n~~~\n\nLet's look at some more examples.\n\n~~~admonish danger title=\"Pro Tip | Inherit Performance Cost\"\nAs mentioned above, an inherit \"only\" searches the active layer stack and layer stacks the reference/payload the active layer stack. That means if we create an inherit in a \"final\" stage (A stage that never gets referenced or payloaded), there is little performance cost to using inherits.\n~~~\n\n![Houdini Composition Inherit Styles](../../../media/core/composition/houdiniCompositionInheritStyles.jpg)\n\nHere is the composition result for the left node stream. (For how to log this, see our [Inspecting composition](./pcp.md) section).\n\n![Houdini Composition Inherit - Classical Asset](../../../media/core/composition/houdiniCompositionInheritStyleClassicalAsset.svg)\n\nVs the right node stream:\n\n![Houdini Composition Inherit - Shot Asset](../../../media/core/composition/houdiniCompositionInheritStyleShot.svg)\n\nIf we actually switch to an reference arc for the \"shot style\" inherit stream, we won't see a difference. So why use inherits here? As inherits are higher than variants, you should prefer inherits, for these kind of \"broadcast\" operations. As inherits also don't support time offsetting, they are the \"simplest\" arc in this scenario that does the job 100% of the time.\n\n\n~~~admonish tip title=\"Pro Tip | Advanced Inherits - Making USD simple again!\"\nWhen you've worked a while in USD, you sometimes wonder why we need all these different layering rules. Why can't life be simple for once? \n\nHead over to our [Composition in production](../../production/composition.md) section for a more production related view on composition. There we discuss how to get the best out of each arc, without making it overly complicated.\n~~~\n\n### Variants <a name=\"compositionArcVariant\"></a>\nThe variant arc is used to allow users to switch through different variations of sub-hierarchies. It does **not** support adding any time offsets via `Sdf.LayerOffset`s.\n\n~~~admonish tip title=\"Pro Tip | What do we use variants for?\"\n- We use it as a mechanism to swap between (wait for it ...) variations of a hierarchy. The main applications are:\n    - **Assets**: Instead of having multiple assets with variations based of off a single base asset, we can store one asset and add variants. That way it is cleaner to track throughout the pipeline.\n    - **Shots**: Variants in shots are typically used when a sequence based hierarchy needs to be replaced by a per shot variation. While you could also solve this by just deactivating the prims your need per shot or via sublayer ordering (if you overwrite the same prims), variants offer a cleaner workflow. This way we can keep the hierarchy at the same place and all our lighting department needs to do is target the same hierarchy, when picking what to render. Since variants swap out a whole sub section of a hierarchy, we also ensure that the geometry is not getting any unwanted attributes from other layers.\n- We can have any number of nested variants. A typical example is having multiple model variants, which each in return have different LOD (level of detail) variants.\n- We can also use it as a mechanism to share mesh data. For example if we have a car asset, we can write the car without a variant and then add all car accessories (which don't overlap hierarchy-wise with the car meshes) as variants. That way the artists can swap through what they need on top of the \"base\" model.\n- We don't need to have a variant selection. If we block or unset the selection, no variant will be selected/loaded, which results in an empty hierarchy. Fallbacks for variant set selections can be configured via the USD API or a USD plugin ([API Docs](https://openusd.org/dev/api/class_usd_stage.html), search for 'Variant Management')\n- How are variants structured? Variants are written \"inline\", unlike the inherit/reference/payload/specialize arcs, they do not point to another hierarchy path. Instead they are more similar to child prims (specs). We usually then write other arcs, like payloads, into the variants, that do the actual heavy data loading.\n- We can also use variants as the mechanism to \"variant away\" arcs that have been encapsulated. More info in our [fundamentals section](./fundamentals.md#compositionFundamentalsEncapsulation).\n~~~\n\n~~~admonish tip title=\"Pro Tip | Editing variant arcs via the USD API\"\nIf you want to create/edit variant arcs via code, see our [Composition Arc - Code API](./arcs.md#compositionArcVariant) section.\n~~~\n\nLet's talk about technical details:\nVariant sets (the variant set to variant name mapping) is managed via list editable ops.\nThe actual variant data is not though. It is written \"in-line\" into the prim spec via the `Sdf.VariantSetSpec`/`Sdf.VariantSpec` specs, so that's why we have dedicated specs. This means we can add variant data, but hide it by not adding the variant set name to the `variantSets` metadata.\n\nLet's first look at a simple variant.\n\n~~~admonish tip title=\"\"\n```python\ndef Xform \"car\" (\n    variants = {\n        string color = \"colorA\"\n    }\n    prepend variantSets = \"color\"\n)\n{\n    variantSet \"color\" = {\n        \"colorA\" {\n            def Cube \"cube\"\n            {\n            }\n        }\n        \"colorB\" {\n            def Sphere \"sphere\"\n            {\n            }\n        }\n    }\n}\n```\n~~~\n\nWe can also block a selection, so that nothing gets loaded:\n~~~admonish tip title=\"\"\n```python\ndef Xform \"car\" (\n    variants = {\n        string color = \"\"\n    }\n    prepend variantSets = \"color\"\n)\n{\n    variantSet \"color\" = {\n        \"colorA\" {\n            def Cube \"cube\"\n            {\n            }\n        }\n        \"colorB\" {\n            def Sphere \"sphere\"\n            {\n            }\n        }\n    }\n}\n```\n~~~\n\nSee our [variant composition arc authoring](./arcs.md#compositionArcVariant) section on how to create this via code. \n\n#### Nested Variants <a name=\"compositionArcVariantNested\"></a>\nWhen we write nested variants, we can also write the selections into the nested variants. Here is an example, have a look at the `variants = {string LOD = \"lowRes\"}` dict.\n\n~~~admonish danger title=\"Pro Tip | Nested Variant Selections\"\nWhen we have nested variants the selection is still driven through the highest layer that has a variant selection value (USD speak `opinion`) for each variant selection set. If we don't provide a selection, it will fallback to using the (nested) selection, if one is written. In the example below, if we remove the `string LOD = \"lowRes\"` entry on the bicycle prim, the selection will fallback to \"highRes\" as it will get the selection from the nested variant selection.\n```python\ndef Xform \"bicycle\" (\n    variants = {\n        string LOD = \"lowRes\"\n        string model = \"old\"\n    }\n    prepend variantSets = \"model\"\n)\n{\n    variantSet \"model\" = {\n        \"new\" (\n            variants = {\n                string LOD = \"lowRes\"\n            }\n            prepend variantSets = \"LOD\"\n        ) {\n            variantSet \"LOD\" = {\n                \"lowRes\" {\n                    def Cylinder \"cube\"\n                    {\n                    }\n\n                }\n            }\n\n        }\n        \"old\" (\n            variants = {\n                string LOD = \"highRes\"\n            }\n            prepend variantSets = \"LOD\"\n        ) {\n            variantSet \"LOD\" = {\n                \"highRes\" {\n                    def Cube \"cube\"\n                    {\n                    }\n\n                }\n                \"lowRes\" {\n                    def Sphere \"sphere\"\n                    {\n                    }\n\n                }\n            }\n\n        }\n    }\n}\n```\n~~~\n\n~~~admonish tip title=\"Pro Tip | Nested Variant Naming Conventions\"\nWhen working with nested variants in production, we recommend locking down the naming convention for the variant set names as well as the nested order. We also recommend **not** creating nested variants that only exists for a specific parent variant. This way, variant sets don't \"randomly\" come into existence based on other nested variant selections.\n\nThat way all your code knows where to look when authoring variants and authoring variants can be automated.\n~~~\n\n#### Variant Data Lofting <a name=\"compositionArcVariantLofting\"></a>\nIn production we usually create variants in our asset layer stack. The common practice is to put your whole asset content behind a single payload (or to load individual asset layers behind a payload) that contain the variants. When unloading payloads, we still want to be able to make variant selections (or at least see what is available). In order for us to do this, we can \"loft\" the payload structure to the asset prim. Lofting in this case means, re-creating all variants, but without content. That way UIs can still pick up on the variant composition, but not load any of the data.\n\nOne key problem of lofting the info is, that we have to dive into any nested variant to actually see the nested content. Since this is a one-off operation that can be done on publish, it is fine.\n\n~~~admonish question title=\"Still under construction!\"\nIt is on our to do list to build a code example for this.\n~~~\n\n~~~admonish danger title=\"\"\n```python\ndef Xform \"root_grp\" (\n    prepend payload = @asset_data@</root_grp>\n    variants = {\n        string LOD = \"highRes\"\n        string model = \"old\"\n    }\n    prepend variantSets = \"model\"\n)\n{\n    variantSet \"model\" = {\n        \"new\" (\n            prepend variantSets = \"LOD\"\n        ) {\n            variantSet \"LOD\" = {\n                \"lowRes\" {\n\n                }\n            }\n\n        }\n        \"old\" (\n            prepend variantSets = \"LOD\"\n        ) {\n            variantSet \"LOD\" = {\n                \"highRes\" {\n\n                }\n                \"lowRes\" {\n\n                }\n            }\n\n        }\n    }\n}\n```\n~~~\n\nHere is a comparison in Houdini with unloaded/loaded payloads with lofted variant data.\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/core/composition/houdiniCompositionVariantLoft.mp4\" type=\"video/mp4\" alt=\"Houdini Composition Variant Loft\">\n</video>\n\n#### Sharing data among variants <a name=\"compositionArcVariantSharing\"></a>\nTo share data among variants, we can either payload/reference the same data into each variant. We can also write our data that should be shared outside of the variant and then only add hierarchy overrides/additions via the variants.\n\nHere is how it can be setup in Houdini:\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/core/composition/houdiniCompositionVariantShare.mp4\" type=\"video/mp4\" alt=\"Houdini Composition Variant Share\">\n</video>\n\n#### Efficiently re-writing existing data as variants <a name=\"compositionArcVariantReauthor\"></a>\nVia the low level API we can also copy or move content on a layer into a variant. This is super powerful to easily create variants from caches.\n\nHere is how it can be setup in Houdini:\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/core/composition/houdiniCompositionVariantCopyMove.mp4\" type=\"video/mp4\" alt=\"Houdini Composition Variant Copy/Move\">\n</video>\n\nHere is the code for moving variants:\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/composition.py:compositionArcVariantMoveHoudini}}\n```\n~~~\n\nAnd for copying:\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/composition.py:compositionArcVariantCopyHoudini}}\n```\n~~~\n\n### References <a name=\"compositionArcReference\"></a>\nThe reference arc is one of the most used arcs. Its main purpose is to aggregate scene description data from other files or sub-hierarchies. It is the only arc that has both file loading and internal hierarchy linking/loading possibilities. It does support adding time offsets via `Sdf.LayerOffset`s.\n\n~~~admonish tip title=\"Pro Tip | What do we use references for?\"\n- The reference arc is one of the most used arcs in USD: Its main use case is to combine smaller pieces of scene description into larger aggregates. Its main applications are:\n\t- **Assets**: For assets we mainly stick to payloading in the individual layers (model/fx/materials) or we create a single payload that then references all the individual layers. So depending on how you build your asset structure, you might end up not using references, except for when building assembly type assets. Assemblies are USD files that reference other USD files for a logical grouping of assets, for example a film set or city.\n\t- **Shots**: This is the most common place of usage for references. We use references to bring in our assets or assemblies. We also use it to time offset assets or existing hierarchies, as the reference arc can point to another prim path in the active layer stack. This makes it a powerful tool to drive (time) variations of assets in shots.\n- As written in the previous bullet point, the reference arc should aggregate data. That means the files it is loading should not be heavy, but contain only (lofted) metadata and references/payloads to other files.\n- The reference arc targets a specific prim in the hierarchy. When using references to load a file, we either point to a specific prim we want to load from that file or we don't specify a prim and then the value of the \"defaultPrim\" layer metadata gets used. The default prim has to be a direct child prim of the pseudo root prim \"/\".\n- The reference arc (as the payload arc) uses the principle of encapsulation. This means once a file is referenced in, the composition arcs in the file can't be list-edited any more.\n~~~\n\n~~~admonish tip title=\"Pro Tip | Editing reference arcs via the USD API\"\nIf you want to create/edit reference arcs via code, see our [Composition Arc - Code API](./arcs.md#compositionArcReference) section.\n~~~\n\n#### Composition encapsulation for references (and payloads) <a name=\"compositionArcReferencePayloadEncapsulation\"></a>\nLet's have a look at encapsulation of the list-editable ops of composition arcs:\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/core/composition/houdiniCompositionReferenceEncapsulate.webm\" type=\"video/mp4\" alt=\"Houdini Reference Encapsulation\">\n</video>\n\nAs you can see, once we start loading another written USD file, we can't remove any composition arcs.\n\nLet's compare this to other list-editable ops, like relationships:\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/core/composition/houdiniCompositionListEditableRelationship.mp4\" type=\"video/mp4\" alt=\"Houdini Relationship Encapsulation\">\n</video>\n\nAs you can see they don't have the same restrictions as composition arc list-editable ops.\n\nEncapsulation also affects what referenced (payload) content \"sees\". Inherits and specialized do not have this restriction, only their arc structure is encapsulated/\"locked\", but they remain live in the sense that they still look at the live composed prims that they target.\n\nAs mentioned in our [fundamentals section](./fundamentals.md), encapsulation affects the list-editable op. It also affects what payloads/references \"see\" when they load their content. Inherit and specialize arcs are kept \"live\", they always look at the current layer stack for what to load. Internal references do not, they only look at the active layer stack. As soon as the internally referenced content is loaded via a payload/reference into another layer stack, it only sees the layer stack where it came from. Let's look at an example:\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/core/composition/houdiniCompositionReferenceInheritSpecializeEncapsulate.mp4\" type=\"video/mp4\" alt=\"Houdini Reference/Inherit/Specialize Encapsulation\">\n</video>\n\nAs you can see in the live layer stack, the edit to the radius has the same result on all internal arcs. As soon as we reference it though (same with if we payload it), \"only\" the inherit and specialize arc are kept live.\n\n\n#### Nested composition and list editable op order <a name=\"compositionArcReferenceStrongWeakerListOrder\"></a>\nRemember how with list editable ops we can specify if we want to pre-/append to the list op? Let's take a look how that works, when working with nested references, for example in assemblies:\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/core/composition/houdiniCompositionReferenceStrongWeaker.mp4\" type=\"video/mp4\" alt=\"Houdini Relationship Encapsulation\">\n</video>\n\nAs you can see, as soon as the encapsulated assembly ref is brought it, it doesn't matter if our asset scaled box ref is weaker or stronger. Why? In this case it is actually due to being the closer arc to the \"box\" prim. The closer (ancestor-wise) a composition arc is authored to a prim, the higher its strength will be when we have nested arcs.\n\n\n\n### Payloads <a name=\"compositionArcPayload\"></a>\nThe payload arc is also one of the most used arcs. Its main purpose is to load heavy data. This means it is the arc that you'll use when loading any type of renderable geometry. It does support adding time offsets via `Sdf.LayerOffset`s.\n\n~~~admonish tip title=\"Pro Tip | What do we use payloads for?\"\n- You might be wondering why we should use payloads when we have references? The answer is USD's hierarchy loading mechanisms. Payloads are special, in that we can tell USD to not load any payloads or only specific hierarchies with payloads when working with stages. We cover it in more detail in our [Loading Mechanisms](../elements/loading_mechanisms.md) section. This makes payload's main purpose loading heavy data.\n- The payload arc is therefore also one of the most used arcs in USD, its main applications are:\n\t- **Assets**: Any layer in your asset, that contains geometry/renderable data, should be behind a payload. We can also first aggregate different files via references and then load this aggregated file via a payload. The important thing is that when we load the asset into the shot, we can opt-out of having to load the heavy data directly.\n\t- **Shots**: In shots we use payloads to bring in shot relevant caches, most importantly animation and FX caches. Now you might have noticed that payloads are lower than references. This means if we want to load an fx cache over an asset that was brought in as a reference, we either have to first import the payload somewhere else and then link to it via an inherit or variant, or we don't load it as a payload and bring it in as a reference. More on how this affects performance below.\n- The payload arc targets a specific prim in the hierarchy. When using payloads to load a file, we either point to a specific prim we want to load from that file or we don't specify a prim and then the value of the \"defaultPrim\" layer metadata gets used. The default prim has to be a direct child prim of the pseudo root prim \"/\".\n- The payload arc (as the reference arc) uses the principle of encapsulation. This means once a file is payloaded in, the composition arcs in the file can't be list-edited any more. See the reference section above for more info. Now with payloads this isn't an issue that much, because typically we use payloads to point to a cache file that carries the raw data and not other cache files.\n- Payloads can also be time offset via an `Sdf.LayerOffset`.\n~~~\n\n~~~admonish tip title=\"Pro Tip | Editing payload arcs via the USD API\"\nIf you want to create/edit payload arcs via code, see our [Composition Arc - Code API](./arcs.md#compositionArcPayload) section.\n~~~\n\n#### Workflows for loading payloads over references in shots <a name=\"compositionArcPayloadLoadWorkflow\"></a>\nLet's take a look at how we can bring in payloads in shots:\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/core/composition/houdiniCompositionPayloadOverReference.mp4\" type=\"video/mp4\" alt=\"Houdini Payload over Reference\">\n</video>\n\nAs you can see, we could bring it in as a reference, when it \"collides\" with an existing asset reference, so that the shot data wins (the color and updated position in this case). When we unload the asset payload, you'll notice that we still have reference shot data. Remember when we talked about how composition builds a value source index (prim/property index) in our [fundamentals section](./fundamentals.md)? In theory, USD doesn't load the actual values of attributes until a render delegate queries for it. So as long as we don't access the attributes (via UI panels/code), the hierarchy is still loaded, but the heavy data is not pulled yet. Now there are still downsides: USD still has to build the hierarchy, so there is a file read (USD is smart enough to only read the hierarchy structure and not load the full data). It also depends if your hydra delegate is smart enough to filter out prims, that can't be rendered. So in summary: We don't recommend doing this, but the option is there, and it will not impact performance as much as you think in small to midsize hierarchies.\n\nFor an production view on composition, check out our [Composition in Production](../../production/composition.md) section, where we look at this in detail.\n\n### Specializes <a name=\"compositionArcSpecialize\"></a>\nThe specialize arc is used to supply a base set of values to prims. You might be thinking, isn't that similar to what a schema should be doing? Well yes, but a specialize arc targets a whole hierarchy vs schemas only affect a single prim(type) at a time. The specialize arc is usually something we only want to use in assets (mostly materials) or in shots when we create new hierarchies that have nothing to do with any existing hierarchies. You can think of the specialize arc as the counter part to the inherit arc, as it does the same thing but only with the guaranteed lowest value opinion strength vs highest opinion strength. It does **not** support adding a time offset via `Sdf.LayerOffset`.\n\nTo quote from the USD glossary:\n~~~admonish quote title=\"\"\nThe specializes behavior is desirable in this context of building up many unique refinements of something whose base properties we may want to continue to update as assets travel down the pipeline, but without changing anything that makes the refinements unique.\n~~~\n\nThe specializes behavior is desirable in this context of building up many unique refinements of something whose base properties we may want to continue to update as assets travel down the pipeline, but without changing anything that makes the refinements unique.\n\n~~~admonish tip title=\"Pro Tip | What do we use specializes for?\"\n- We use specialize arcs as a \"broadcast\" operator for supplying a template-like hierarchy: When we want to supply a \"base\" hierarchy to multiple places, we typically create a class prim, whose child prims contain the properties we want to modify. After that we create a specialize arc on all prims that should receive the hierarchy.\n- The specialize arc lookup is never [encapsulated](./fundamentals.md#compositionFundamentalsEncapsulation), the specialize arc list-editable op is. This means that any layer stack, that re-creates the prims that that the specialize targets, gets used by the specialize. This does come at a performance cost, as the composition engine needs to check all layer stacks from where the arc was authored and higher for the hierarchy that the specialize targets.\n- The specialize arc commonly gets used together with the [class prim specifier](../elements/prim.md#primSpecifier). The class prim specifier is specifically there to get ignored by default traversals and to provide template hierarchies that can then get inherited (or internally referenced/specialized) to have a \"single source to multiple targets\" effect.  \n- Depending on if we are working on shots or assets are common practices:\n    - **Assets**: As assets provide the data for our shot content, specializes are more typical here.\n        - When creating assets, we can author a `/__CLASS__/<assetName>` specialize. When we use the asset in shots, we can then easily add \"underrides\" to all assets of this type, by creating prims and properties under that specific class prim hierarchy. Since specializes have the lowest strength, any other composition arc that provides data will win in any higher layer. While this sounds great in theory, artists often want to only selectively apply an override to an asset. Therefore having the additional performance cost of this arc in assets is something might not worth doing.\n        - The other common case is to use them for materials: \n            - We put all of our materials under a `/__CLASS__` and then specialize it to the asset materials. This way asset (material) variants can add overrides to the materials. We could also use an internal reference arc to achieve this, depending on how you structure your composition though it would defeat the purpose of even a non direction opinion style authoring. For example if we payload individual asset layers together (e.g. fx_layer.usd, model_layer.usd), then the internal reference would be encapsulated and not live anymore. Whereas a specialize would be.\n            - We specialize materials with each other. You can find the example from the USD glossary below that shows how this works. \n    - **Shots**: In shots, specializes are more rare, as the shot layer stack is the \"final\" layer stack that gets rendered. Some use cases might be:\n        - Batch apply render geometry settings to (instanceable) prims. This is a great way of having a single control point to editing render settings per different areas of interest in your scene. This has the same intent as inherits, the difference is that existing overrides are kept in place, as with inherits they are not (unless they are direct opinions on sublayers).\n        - Building a template hierarchy for new content hierarchies that don't 'over' over any existing prims.\n~~~\n\n~~~admonish tip title=\"Pro Tip | Editing specialize arcs via the USD API\"\nIf you want to create/edit specialize arcs via code, see our [Composition Arc - Code API](./arcs.md#compositionArcSpecialize) section.\n~~~\n\nIn the accompanying [Houdini file](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/tree/main/files/composition) you can find the specialize example from the [USD Glossary - Specializes](https://openusd.org/release/glossary.html#usdglossary-specializes) section.\n\n\nLet's look at some more examples.\n\n~~~admonish danger title=\"Pro Tip | Specialize Performance Cost\"\nAs with inherits, an specialize \"only\" searches the active layer stack and layer stacks the reference/payload the active layer stack. That means if we create a specialize in a \"final\" stage (A stage that never gets referenced or payloaded), there is little performance cost to using specializes.\n~~~\n\n![Houdini Composition Specialize Styles](../../../media/core/composition/houdiniCompositionSpecializeStyles.jpg)\n\nHere is the composition result (For how to log this, see our [Inspecting composition](./pcp.md) section).\n\n![Houdini Composition Inherit - Classical Asset](../../../media/core/composition/houdiniCompositionSpecializeStyleClassicalAsset.svg)\n\nLet's compare it to the inherit visualization:\n\n![Houdini Composition Specialize - Classical Asset](../../../media/core/composition/houdiniCompositionInheritStyleClassicalAsset.svg)\n\nYou might have expected it to look the exact same way, so why does it not? The answer lies in the composition calculation as described by our diagram in the [Composition Strength Ordering](#compositionStrengthOrdering) section. (At least that's how we read the graph, if this is wrong, please correct us!) Specializes are special (hehe) in that, since they are the lowest arc, they can just directly look at the layer stacks of where they should specialize from as to \"following\" the composition arc structure. (It still follows, but builds a list of flattened sources in full LIVRPS mode (because it always has to follow all arcs because it is the weakest arc) as to recursively following the source by looking into files in LIVRP mode (no \"S\") and stopping on first source hit).\n\nIf we look at the right hand node output graph, this becomes more clear.\n\n![Houdini Composition Specialize - Classical Assembly](../../../media/core/composition/houdiniCompositionSpecializeClassicAssembly.svg)\n\nVs inherits:\n\n![Houdini Composition Inherit - Classical Assembly](../../../media/core/composition/houdiniCompositionInheritClassicAssembly.svg)\n\nLet's have a look at the example from the [USD Glossary - Specializes](https://openusd.org/release/glossary.html#usdglossary-specializes) section:\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/core/composition/houdiniCompositionInheritVsInternalReferenceVsSpecialize.mp4\" type=\"video/mp4\" alt=\"Houdini Inherit vs Internal Reference vs Specialize\">\n</video>\n\nThis shows the individual arcs in action and also again the effect of encapsulation when using internal references.\n\n\n## Instancing in USD <a name=\"compositionInstance\"></a>\nYou might be wondering: \"Huh, why are we talking about instancing in the section about composition?\". The answer is: The two are actually related.\n\nLet's first define what instancing is:\n~~~admonish tip title=\"\"\nInstancing is the multi re-use of a part of the hierarchy, so that we don't have to load it into memory multiple times. In USD speak the term for the \"base\" copy, all instances refer to, is **Prototype**.\n~~~\n\n~~~admonish danger title=\"\"\nInstancing is what keeps things fast as your stage content grows. It should be one of the main factors of how you design your composition setup.\n~~~\n\nUSD has two ways of handling data instancing:\n- **Explicit**: Explicit data instancing via [`UsdGeom.PointInstancer`](https://openusd.org/dev/api/class_usd_geom_point_instancer.html) prims. The idea is simple: Given a set of array attributes made up of positions, orientations, scales (and velocity) data, copy a `Prototype` to each point. In this case prototype refers to any prim (and its sub-hierarchy) in your stage. We usually group them under the point instancer prims for readability. \n- **Implicit**: Implicit instances are instances that are marked with the `instanceable` metadata. Now we can't just mark any hierarchy prim with this data. (Well we can but it would have no effect.) This metadata has to be set on prims that have composition arcs written. Our usual case is an asset that was brought in via a reference. What USD then does is \"lock\" the composition and create on the fly `/__Prototype_<index>` prim as the base copy. Any prim in your hierarchy that has the exact same let's call it **composition hash** (exact same composition arcs), will then re-use this base copy. This also means that we can't edit any prim beneath the `instanceable` marked prim.\n\nSee the official docs [here](https://openusd.org/release/api/_usd__page__scenegraph_instancing.html) for a lengthy explanation.\n\n~~~admonish danger title=\"Pro Tip | Prototype Count\"\nWe should always keep an eye on the prototype count, as it is a good performance indicator of if our composition structure is well setup.\n\nWe can also access the implicit prototypes via Python. They are not editable and on the fly re-spawned every time you edit your stage, so don't count on their naming/path/content to be the same. \n\nWe often do use them though to find the prims they are the prototype of. That way we can add arcs (for example an inherit) and still keep the prototype count the same, as the overall unique compositions structures stay the same.\n```python\nprint(\"Prototype Count\", len(stage.GetPrototypes()))\n```\n~~~\n\nIn Houdini we can show the implicit prototypes by enabling the \"Show Implicit Prototype Primitives\" option in the sunglasses menu in our scene graph tree panel.\n\n![Houdini Instanceable](../../../media/core/composition/houdiniCompositionInstanceable.jpg)\n\nHere is how we can check if a prim is inside an instance or inside a prototype:\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/composition.py:compositionInstanceable}}\n```\n~~~\n\nHere is an example of how we can't edit the content within an instanceable prim. Instead we have to create a hierarchy (in this case a `/__CLASS__` hierarchy) where we inherit from. As you can see the prototype count changes depending on if we apply the inherit to only a single reference or all. (Houdini shows the `/__class__` prim in the righ click menu, this is because the Houdini test assets where setup with an inherit by default that always runs on all assets. Since we only want to selectively broadcast our edit, we have to create a different class hierarchy.)\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/core/composition/houdiniCompositionInstanceableInherit.mp4\" type=\"video/mp4\" alt=\"Houdini Composition Variant Copy/Move\">\n</video>\n\n"
  },
  {
    "path": "docs/src/pages/core/composition/overview.md",
    "content": "# Composition (Combining layers)\nComposition is the \"art\" of combining layers in USD. (Yes \"art\" as everyone does it a bit differently 😉)\n\nComposition requires some base knowledge that we cover in our fundamentals section. You can also skip it, as it is a bit of a deep dive, but we highly recommend it, as the subsequent pages refer to it quite often.\n\n- [Composition Fundamentals](./fundamentals.md): Here we cover the basic terminology and principles behind composition.\n- [Composition Arcs](./arcs.md): Here we look at how to create composition arcs via code.\n- [Composition Strength Ordering (LIVRPS)](./livrps.md): Here we discuss each arc's usage and give tips and tricks on how to best utilize it in production.\n- [List Editable Ops](./listeditableops.md): Here we look at list editable ops. These are used to give every arc a specific load order. We also take a look at other aspects of USD that use these.\n- [Inspecting Composition (Prim Cache Population (PCP))](./pcp.md): Here we take a look at how to debug and inspect composition.\n\nThis is probably USD's most dreaded topic, as it is also the most complex. But don't worry, we'll start slow and explain everything with a lot of examples, so that you'll feel comfortable with the topic in no time!"
  },
  {
    "path": "docs/src/pages/core/composition/pcp.md",
    "content": "# Prim Cache Population (PCP) - Composition Cache\nThe **Prim Cache Population** module is the backend of what makes USD composition work. You could call it the `composition core`, that builds the prim index.\nThe prim index is like an ordered list per prim, that defines where values can be loaded from. For example when we call `Usd.Prim.GetPrimStack`, the `pcp` gives us a list of value sources as an ordered list, with the \"winning\" value source as the first entry.\n\nWhen USD opens a stage, it builds the prim index, so that it knows for each prim/property where to pull data from.\nThis is then cached, and super fast to access.\n\nWhen clients (like hydra delegates or C++/Python attribute queries) request data, only then the data is loaded.\nThis way hierarchies can load blazingly fast, without actually loading the heavy attribute data.\n\n~~~admonish tip\nTo summarize: Composition (the process of calculating the value sources) is cached, value resolution is not, to allow random access data loading.\n~~~\n\nFor a detailed explanation, checkout the [Value Resolution](https://openusd.org/release/glossary.html#usdglossary-valueresolution) docs page.\n\n# Table of Contents\n1. [Prim Cache Population (PCP) In-A-Nutshell](#summary)\n1. [What should I use it for?](#usage)\n1. [Resources](#resources)\n1. [Overview](#overview)\n1. [Inspecting Composition](#pcpInspect)\n    1. [Prim/Property Stack](#pcpPrimPropertyStack)\n    1. [Prim Index](#pcpPrimPropertyIndex)\n    1. [Prim Composition Query](#pcpPrimCompositionQuery)\n\n## TL;DR - <Topic> In-A-Nutshell <a name=\"summary\"></a>\n- The **Prim Cache Population** module in USD computes and caches the composition (how different layers are combined) by building an index of value sources per prim called **prim index**.\n- This process of calculating the value sources is cached, value resolution is not, to allow random access to data. This makes accessing hierarchies super fast, and allows attribute data to be streamed in only when needed. This is also possible due to USD's [binary crate format](https://openusd.org/release/glossary.html#crate-file-format), which allows sparse \"read only what you need\" access from USD files.\n- The **Prim Cache Population (Pcp)** module is exposed via two ways:\n    - **High Level API**: Via the `Usd.PrimCompositionQuery` class.\n    - **Low Level API**: Via the`Usd.Prim.GetPrimIndex`/`Usd.Prim.ComputeExpandedPrimIndex` methods.\n- Notice how both ways are still accessed via the high level API, as the low level `Sdf` API is not aware of composition.\n\n## What should I use it for? <a name=\"usage\"></a>\n~~~admonish tip\nWe'll be using the prim cache population module for inspecting composition.\nThis is more of a deep dive topic, but you may at some point run into this in production.\n\nAn example scenario might be, that when we want to author a new composition arc, we first need to check if there are existing strong arcs, than the arc we intend on authoring.\nFor example if a composition query detects a variant, we must also author at least a variant or a higher composition arc in order for our edits to come through.\n~~~\n\n## Resources <a name=\"resources\"></a>\n- [PrimCache Population (Composition)](https://openusd.org/dev/api/pcp_page_front.html)\n- [Prim Index](https://openusd.org/release/glossary.html#usdglossary-index)\n- [Pcp.PrimIndex](https://openusd.org/release/api/class_pcp_prim_index.html)\n- [Pcp.Cache](https://openusd.org/dev/api/class_pcp_cache.html)\n- [Usd.CompositionArc](https://openusd.org/dev/api/class_usd_prim_composition_query_arc.html)\n- [Usd.CompositionArcQuery](https://openusd.org/dev/api/class_usd_prim_composition_query.html)\n- [Value Resolution](https://openusd.org/release/glossary.html#usdglossary-valueresolution)\n- [USD binary crate file format](https://openusd.org/release/glossary.html#crate-file-format)\n\n## Overview <a name=\"overview\"></a>\nThis page currently focuses on the practical usage of the `Pcp` module, it doesn't aim to explain how the composition engine works under the hood. (As the author(s) of this guide also don't know the details 😉, if you know more in-depth knowledge, please feel free to share!)\n\nThere is a really cool plugin for the [UsdView](../elements/standalone_utilities.md) by [chrizzftd](https://github.com/chrizzFTD) called [The Grill](https://grill.readthedocs.io/en/latest/views.html), that renders out the dot graph representation interactively based on the selected prim.\n\nIn the examples below, we'll look at how to do this ourselves via Python.\n\n## Inspecting Composition <a name=\"pcpInspect\"></a>\nTo query data about composition, we have to go through the high level Usd API first, as the `Sdf` low level API is not aware of composition related data.\nThe high level Usd API then queries into the low level Pcp (Prim cache population) API, which tracks all composition related data and builds a value source index called **prim index**. \n\nThe prim stack in simple terms: A stack of layers per prim (and therefore also properties) that knows about all the value sources (layers) a value can come from. Once a value is requested, the highest layer in the stack wins and returns the value for attributes. For metadata and relationships the value resolution can consult multiple layers, depending on how it was authored (see [list editable ops](../composition/listeditableops.md) as an example for a multiple layer averaged value).\n\n### Prim/Property Stack <a name=\"pcpPrimPropertyStack\"></a>\nLet's first have a look at the prim and property stacks with a simple stage with a cubes that has written values in two different layers.\nThese return us all value sources for a prim or attribute.\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/composition.py:pcpPrimPropertyStack}}\n```\n~~~\n\nIn Houdini/USD view we can also view these stacks in the UI.\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/core/composition/houdiniPrimPropertyStack.mp4\" type=\"video/mp4\" alt=\"Houdini Prim/Property Stack\">\n</video>\n\n\n### Prim Index <a name=\"pcpPrimIndex\"></a>\nNext let's look at the prim index.\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/composition.py:pcpPrimIndex}}\n```\n~~~\n\nThe prim index class can dump our prim index graph to the *dot* file format. The *dot* commandline tool ships with the most operating systems, we can then use it to visualize our graph as a .svg/.png file.\n\n~~~admonish tip title=\"Result of: `print(prim_index.DumpToString())` | Click to view content\" collapsible=true\n```txt\nNode 0:\n    Parent node:              NONE\n    Type:                     root\n    DependencyType:           root\n    Source path:              </bicycle>\n    Source layer stack:       @anon:0x7f9eae9f2400:tmp.usda@,@anon:0x7f9eae9f1000:tmp-session.usda@\n    Target path:              <NONE>\n    Target layer stack:       NONE\n    Map to parent:\n        / -> /\n    Map to root:\n        / -> /\n    Namespace depth:          0\n    Depth below introduction: 0\n    Permission:               Public\n    Is restricted:            FALSE\n    Is inert:                 FALSE\n    Contribute specs:         TRUE\n    Has specs:                TRUE\n    Has symmetry:             FALSE\n    Prim stack:\n      </bicycle> anon:0x7f9eae9f2400:tmp.usda - @anon:0x7f9eae9f2400:tmp.usda@\nNode 1:\n    Parent node:              0\n    Type:                     reference\n    DependencyType:           non-virtual, purely-direct\n    Source path:              </bicycle>\n    Source layer stack:       @anon:0x7f9eae9f2b80:ReferenceExample@\n    Target path:              </bicycle>\n    Target layer stack:       @anon:0x7f9eae9f2400:tmp.usda@,@anon:0x7f9eae9f1000:tmp-session.usda@\n    Map to parent:\n        SdfLayerOffset(10, 1)\n        /bicycle -> /bicycle\n    Map to root:\n        SdfLayerOffset(10, 1)\n        /bicycle -> /bicycle\n    Namespace depth:          1\n    Depth below introduction: 0\n    Permission:               Public\n    Is restricted:            FALSE\n    Is inert:                 FALSE\n    Contribute specs:         TRUE\n    Has specs:                TRUE\n    Has symmetry:             FALSE\n    Prim stack:\n      </bicycle> anon:0x7f9eae9f2b80:ReferenceExample - @anon:0x7f9eae9f2b80:ReferenceExample@\n```\n~~~\n\n\n~~~admonish tip title=\"Result of writing the graph to a dot .txt file | Click to view content\" collapsible=true\n```txt\n{{#include pcpPrimIndex.txt}}\n```\n~~~\n\nFor example if we run it on a more advanced composition, in this case Houdini's pig asset:\n\n~~~admonish tip title=\"Python print output for Houdini's pig asset | Click to view content\" collapsible=true\n```python\nPcp Node Ref\n<pxr.Pcp.NodeRef object at 0x7f9ed3ad19e0> Pcp.ArcTypeRoot /pig /pig\n<pxr.Pcp.NodeRef object at 0x7f9ed3ad17b0> Pcp.ArcTypeInherit /__class__/pig /pig\n<pxr.Pcp.NodeRef object at 0x7f9ed3ad1cf0> Pcp.ArcTypeReference /pig /pig\n<pxr.Pcp.NodeRef object at 0x7f9ed3ad1970> Pcp.ArcTypeInherit /__class__/pig /pig\n<pxr.Pcp.NodeRef object at 0x7f9ed3ad1890> Pcp.ArcTypeVariant /pig{geo=medium} /pig{geo=medium}\n<pxr.Pcp.NodeRef object at 0x7f9ed3ad1270> Pcp.ArcTypePayload /pig /pig\n<pxr.Pcp.NodeRef object at 0x7f9ed3ad1660> Pcp.ArcTypeReference /pig /pig\n<pxr.Pcp.NodeRef object at 0x7f9ed3ad1510> Pcp.ArcTypeVariant /pig{geo=medium} /pig{geo=medium}\n<pxr.Pcp.NodeRef object at 0x7f9ed3ad13c0> Pcp.ArcTypeReference /ASSET_geo_variant_1/ASSET /pig\n<pxr.Pcp.NodeRef object at 0x7f9ed3abbd60> Pcp.ArcTypeVariant /ASSET_geo_variant_1/ASSET{mtl=default} /pig{mtl=default}\n<pxr.Pcp.NodeRef object at 0x7f9ed3abb6d0> Pcp.ArcTypeReference /ASSET_geo_variant_1/ASSET_mtl_default /pig\n<pxr.Pcp.NodeRef object at 0x7f9ed3ad1a50> Pcp.ArcTypeReference /pig /pig\n<pxr.Pcp.NodeRef object at 0x7f9ed3ad15f0> Pcp.ArcTypeReference /ASSET_geo_variant_2/ASSET /pig\n<pxr.Pcp.NodeRef object at 0x7f9ed3abbe40> Pcp.ArcTypeVariant /ASSET_geo_variant_2/ASSET{geo=medium} /pig{geo=medium}\n<pxr.Pcp.NodeRef object at 0x7f9ed3ad1ac0> Pcp.ArcTypeReference /ASSET_geo_variant_1/ASSET /pig\n<pxr.Pcp.NodeRef object at 0x7f9ed3abbf90> Pcp.ArcTypeVariant /ASSET_geo_variant_1/ASSET{geo=medium} /pig{geo=medium}\n<pxr.Pcp.NodeRef object at 0x7f9ed3abb430> Pcp.ArcTypeReference /ASSET_geo_variant_0/ASSET /pig\n<pxr.Pcp.NodeRef object at 0x7f9ed3abb9e0> Pcp.ArcTypeVariant /ASSET_geo_variant_0/ASSET{geo=medium} /pig{geo=medium}\n```\n~~~\n\n~~~admonish tip title=\"Result of writing the graph to a dot .txt file for Houdini's pig asset | Click to view content\" collapsible=true\n```txt\n{{#include pcpPrimIndexPig.txt}}\n```\n~~~\n\n![Alt text](../../../media/core/composition/pcpPrimIndexPig.png)\n\n~~~admonish tip\nWe can also access the `Pcp.Cache` of the stage via: `pcp_cache = stage._GetPcpCache()`\n~~~\n\n### Prim Composition Query <a name=\"pcpPrimCompositionQuery\"></a>\nNext let's look at prim composition queries. Instead of having to filter the prim index ourselves, we can use the `Usd.PrimCompositionQuery` to do it for us. More info in the [USD API docs](https://openusd.org/dev/api/class_usd_prim_composition_query.html).\n\nThe query works by specifying a filter and then calling `GetCompositionArcs`.\n\nUSD provides these convenience filters, it returns a new `Usd.PrimCompositionQuery` instance with the filter applied:\n- `Usd.PrimCompositionQuery.GetDirectInherits(prim)`: Returns all non ancestral inherit arcs\n- `Usd.PrimCompositionQuery.GetDirectReferences(prim)`: Returns all non ancestral reference arcs\n- `Usd.PrimCompositionQuery.GetDirectRootLayerArcs(prim)`: Returns arcs that were defined in the active layer stack.\n\nThese are the sub-filters that can be set. We can only set a single token value per filter:\n- **ArcTypeFilter**: Filter based on different arc(s).\n    - `Usd.PrimCompositionQuery.ArcTypeFilter.All`\n    - `Usd.PrimCompositionQuery.ArcTypeFilter.Inherit`\n    - `Usd.PrimCompositionQuery.ArcTypeFilter.Variant`\n    - `Usd.PrimCompositionQuery.ArcTypeFilter.NotVariant`\n    - `Usd.PrimCompositionQuery.ArcTypeFilter.Reference`\n    - `Usd.PrimCompositionQuery.ArcTypeFilter.Payload`\n    - `Usd.PrimCompositionQuery.ArcTypeFilter.NotReferenceOrPayload`\n    - `Usd.PrimCompositionQuery.ArcTypeFilter.ReferenceOrPayload`\n    - `Usd.PrimCompositionQuery.ArcTypeFilter.InheritOrSpecialize` \n    - `Usd.PrimCompositionQuery.ArcTypeFilter.NotInheritOrSpecialize` \n    - `Usd.PrimCompositionQuery.ArcTypeFilter.Specialize`\n- **DependencyTypeFilter**: Filter based on if the arc was introduced on a parent prim or on the prim itself.\n    - `Usd.PrimCompositionQuery.DependencyTypeFilter.All`\n    - `Usd.PrimCompositionQuery.DependencyTypeFilter.Direct`\n    - `Usd.PrimCompositionQuery.DependencyTypeFilter.Ancestral`\n- **ArcIntroducedFilter**: Filter based on where the arc was introduced.\n    - `Usd.PrimCompositionQuery.ArcIntroducedFilter.All`\n    - `Usd.PrimCompositionQuery.ArcIntroducedFilter.IntroducedInRootLayerStack`\n    - `Usd.PrimCompositionQuery.ArcIntroducedFilter.IntroducedInRootLayerPrimSpec`\n- **HasSpecsFilter**: Filter based if the arc has any specs (For example an inherit might not find any in the active layer stack)\n    - `Usd.PrimCompositionQuery.HasSpecsFilter.All`\n    - `Usd.PrimCompositionQuery.HasSpecsFilter.HasSpecs`\n    - `Usd.PrimCompositionQuery.HasSpecsFilter.HasNoSpecs`\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/composition.py:pcpPrimCompositionQuery}}\n```\n~~~\n\nThe returned filtered `Usd.CompositionArc` objects, allow us to inspect various things about the arc. You can find more info in the [API docs](https://openusd.org/dev/api/class_usd_prim_composition_query_arc.html)\n"
  },
  {
    "path": "docs/src/pages/core/composition/pcpPrimIndex.txt",
    "content": "digraph PcpPrimIndex {\n\t140321959801344 [label=\"@anon:0x7f9ec906e400:tmp.usda@,@anon:0x7f9ec8f85a00:tmp-session.usda@</red_bicycle> (0)\\n\\ndepth: 0\", shape=\"box\", style=\"solid\"];\n\t140321959801448 [label=\"@anon:0x7f9ec906e900:ReferenceExample@</bicycle> (1)\\n\\ndepth: 1\", shape=\"box\", style=\"solid\"];\n\t140321959801344 -> 140321959801448 [color=red, label=\"reference\"];\n}\n"
  },
  {
    "path": "docs/src/pages/core/composition/pcpPrimIndexPig.txt",
    "content": "digraph PcpPrimIndex {\n\t140319730187168 [label=\"@anon:0x7f9ec9290900:LOP:rootlayer@,@anon:0x7f9ec906e680:LOP:rootlayer-session.usda@</pig> (0)\\n\\ndepth: 0\", shape=\"box\", style=\"solid\"];\n\t140319730187272 [label=\"@anon:0x7f9ec9290900:LOP:rootlayer@,@anon:0x7f9ec906e680:LOP:rootlayer-session.usda@</__class__/pig> (1)\\n\\ndepth: 1\", shape=\"box\", style=\"dotted\"];\n\t140319730187168 -> 140319730187272 [color=green, label=\"inherit\", style=dashed];\n\t140319730187272 -> 140319730187480 [style=dotted label=\"origin\" constraint=\"false\"];\n\t140319730187376 [label=\"@pig.usd@</pig> (2)\\n\\ndepth: 1\", shape=\"box\", style=\"solid\"];\n\t140319730187168 -> 140319730187376 [color=red, label=\"reference\"];\n\t140319730187480 [label=\"@pig.usd@</__class__/pig> (3)\\n\\ndepth: 1\", shape=\"box\", style=\"solid\"];\n\t140319730187376 -> 140319730187480 [color=green, label=\"inherit\"];\n\t140319730187584 [label=\"@pig.usd@</pig{geo=medium}> (4)\\n\\ndepth: 1\", shape=\"box\", style=\"solid\"];\n\t140319730187376 -> 140319730187584 [color=orange, label=\"variant\"];\n\t140319730187688 [label=\"@payload.usdc@</pig> (5)\\n\\ndepth: 1\", shape=\"box\", style=\"solid\"];\n\t140319730187376 -> 140319730187688 [color=indigo, label=\"payload\"];\n\t140319730187792 [label=\"@mtl.usdc@</pig> (6)\\n\\ndepth: 1\", shape=\"box\", style=\"solid\"];\n\t140319730187688 -> 140319730187792 [color=red, label=\"reference\"];\n\t140319730187896 [label=\"@mtl.usdc@</pig{geo=medium}> (7)\\n\\ndepth: 1\", shape=\"box\", style=\"solid\"];\n\t140319730187792 -> 140319730187896 [color=orange, label=\"variant\"];\n\t140319730188000 [label=\"@mtl.usdc@</ASSET_geo_variant_1/ASSET> (8)\\n\\ndepth: 1\", shape=\"box\", style=\"solid\"];\n\t140319730187896 -> 140319730188000 [color=red, label=\"reference\"];\n\t140319730188104 [label=\"@mtl.usdc@</ASSET_geo_variant_1/ASSET{mtl=default}> (9)\\n\\ndepth: 2\", shape=\"box\", style=\"solid\"];\n\t140319730188000 -> 140319730188104 [color=orange, label=\"variant\"];\n\t140319730188208 [label=\"@mtl.usdc@</ASSET_geo_variant_1/ASSET_mtl_default> (10)\\n\\ndepth: 2\", shape=\"box\", style=\"solid\"];\n\t140319730188000 -> 140319730188208 [color=red, label=\"reference\"];\n\t140319730188312 [label=\"@geo.usdc@</pig> (11)\\n\\ndepth: 1\", shape=\"box\", style=\"solid\"];\n\t140319730187688 -> 140319730188312 [color=red, label=\"reference\"];\n\t140319730188416 [label=\"@geo.usdc@</ASSET_geo_variant_2/ASSET> (12)\\n\\ndepth: 1\", shape=\"box\", style=\"solid\"];\n\t140319730188312 -> 140319730188416 [color=red, label=\"reference\"];\n\t140319730188520 [label=\"@geo.usdc@</ASSET_geo_variant_2/ASSET{geo=medium}> (13)\\n\\ndepth: 2\", shape=\"box\", style=\"dotted\"];\n\t140319730188416 -> 140319730188520 [color=orange, label=\"variant\"];\n\t140319730188624 [label=\"@geo.usdc@</ASSET_geo_variant_1/ASSET> (14)\\n\\ndepth: 1\", shape=\"box\", style=\"solid\"];\n\t140319730188312 -> 140319730188624 [color=red, label=\"reference\"];\n\t140319730188728 [label=\"@geo.usdc@</ASSET_geo_variant_1/ASSET{geo=medium}> (15)\\n\\ndepth: 2\", shape=\"box\", style=\"solid\"];\n\t140319730188624 -> 140319730188728 [color=orange, label=\"variant\"];\n\t140319730188832 [label=\"@geo.usdc@</ASSET_geo_variant_0/ASSET> (16)\\n\\ndepth: 1\", shape=\"box\", style=\"solid\"];\n\t140319730188312 -> 140319730188832 [color=red, label=\"reference\"];\n\t140319730188936 [label=\"@geo.usdc@</ASSET_geo_variant_0/ASSET{geo=medium}> (17)\\n\\ndepth: 2\", shape=\"box\", style=\"dotted\"];\n\t140319730188832 -> 140319730188936 [color=orange, label=\"variant\"];\n}\n"
  },
  {
    "path": "docs/src/pages/core/elements/animation.md",
    "content": "# Animation/Time Varying Data\nUsd encodes time related data in a very simple format:\n```json\n{\n    <frame>: <value>\n}\n```\n\n# Table of Contents\n1. [Animation/Time Varying Data In-A-Nutshell](#summary)\n2. [What should I use it for?](#usage)\n3. [Resources](#resources)\n4. [Overview](#overview)\n    1. [Time Code](#animationTimeCode)\n    2. [Layer Offset (A Non-Animateable Time Offset/Scale for Composition Arcs)](#animationLayerOffset)\n    3. [Reading & Writing default values, time samples and value blocks](#animationReadWrite)\n    4. [Time Metrics (Frames Per Second & Frame Range)](#animationMetadata)\n    5. [Motionblur - Computing Velocities and Accelerations](#animationMotionVelocityAcceleration)\n    6. [Stitching/Combining time samples](#animationStitch)\n    7. [Value Clips (Loading time samples from multiple files)](#animationValueClips)\n\n## TL;DR - Animation/Time Varying Data In-A-Nutshell <a name=\"summary\"></a>\n~~~admonish tip\n- Terminology: A single time/value pair is called `time sample`, if an attribute doesn't have time samples, it has `default` value (Which just means it has a single static value).\n- Time samples are encoded in a simple {\\<time(frame)\\>: \\<value\\>} dict.\n- If a frame is requested where no time samples exist, it will be interpolated if the data type allows it and non changing array lengths in neighbour time samples exist. Value queries before/after the first/last time sample will be clamped to these time samples.\n- Time samples are encoded unitless/per frame and not in time units. This means they have to be shifted depending on the current frames per second.\n- Only attributes can carry time sample data. (So composition arcs can not be time animated, only offset/scaled (see the LayerOffset section on this page)).\n\nReading and writing is quite straight forward:\n```python\n{{#include ../../../../../code/core/elements.py:animationOverview}}\n```\n~~~\n\n## What should I use it for? <a name=\"usage\"></a>\n~~~admonish tip\nAnything that has time varying data will be written as time samples. Usually DCCs handle the time sample creation for you, but there are situations where we need to write them ourselves. For example if you want to efficiently combine time samples from two different value sources or if we want to turn a time sample into a `default` sampled value (a value without animation).\n~~~\n\n## Resources\n- [USD Time Sample Examples](https://openusd.org/release/tut_xforms.html)\n- [USD Value Clips](https://openusd.org/dev/api/_usd__page__value_clips.html)\n- [USD Value Clips Utils](https://openusd.org/dev/api/stitch_clips_8h.html#details) \n\n## Overview <a name=\"overview\"></a>\n~~~admonish important\n A single frame(time)/value pair is called `time sample`, if an attribute doesn't have time samples, it has `default` value (Which just means it has a single static value). The time value is the active frame where data is being exported on. It is not time/FPS based. This means that depending on `frames per second` set on the stage, different time samples are read. This means if you have a cache that was written in 25 FPS, you'll have to shift/scale the time samples if you want to use the cache in 24 FPS and you want to have the same result. More about this in the examples below.\n~~~\n\n~~~admonish danger\nCurrently USD has no concept of animation curves or multi time value interpolation other than `linear`. This means that in DCCs you'll have to grab the time data around your frame and have the DCCs re-interpolate the data. In Houdini this can be easily done via a `Retime` SOP node.\n~~~\n\nThe possible stage interpolation types are:\n- `Usd.InterpolationTypeLinear` (Interpolate linearly (if array length doesn't change and data type allows it))\n- `Usd.InterpolationTypeHeld` (Hold until the next time sample)\n\nThese can be set via `stage.SetInterpolationType(<Token>)`. Value queries before/after the first/last time sample will be clamped to these time samples.\n\nRender delegates access the time samples within the shutter open close values when motion blur is enabled. When they request a value from Usd and a time sample is not found at the exact time/frame that is requested, it will be linearly interpolated if the array length doesn't change and the data type allows it.\n\n~~~admonish danger\nSince value lookups in USD can only have one value source, you cannot combine time samples from different layers at run time, instead you'll have to re-write the combined values across the whole frame range. This may seem unnecessary, but since USD is a cache based format and to keep USD performant, value source lookup is only done once and then querying the data is fast. This is the mechanism what makes USD able to expand and load large hierarchies with ease.\n~~~\n\n\nFor example:\n\n```python\n# We usually want to write time samples in the shutter open/close range of the camera times the sample count of deform/xform motion blur.\ndouble size.timeSamples = {\n    1001: 2,\n    1002: 2.274348497390747,\n    1003: 3.0096023082733154,\n    1004: 4.0740742683410645,\n    1005: 5.336076736450195,\n    1006: 6.663923263549805,\n    1007: 7.9259257316589355,\n    1008: 8.990397453308105,\n    1009: 9.725651741027832,\n    1010: 10,\n}\n# If we omit time samples, value requests for frames in between will get a linearly interpolated result.\ndouble scale.timeSamples = {\n    1001: 2,\n    1005: 5.336076736450195,\n    1010: 10,\n}\n```\n\n~~~admonish warning\nSince an attribute can only have a single value source, we can't have a `default` value from layer A and time samples from layer B. We can however have default and time samples values from the same value source.\n\nFor example:\n```python\ndef Cube \"Cube\" (\n)\n{\n    double size = 15\n    double size.timeSamples = {\n        1001: 1,\n        1010: 10,\n    }\n}\n```\nIf we now request the value without a frame, it will return `15`, if we request it with a time, then it will linearly interpolate or given the time sample if it exists on the frame.\n```python\n...\nsize_attr.Get() # Returns: 15.0\nsize_attr.Get(1008) # Returns: 8.0\n...\n\n```\nUsually we'll only have one or the other, it is quite common to run into this at some point though. So when you query data, you should always use `.Get(<frame>)` as this also works when you don't have time samples. It will then just return the default value. Or you check for time samples, which in some cases can be quite expensive. We'll look at some more examples on this, especially with Houdini and causing node time dependencies in our [Houdini](../../dcc/houdini/hda/timedependency.md) section.\n~~~\n\n### Time Code <a name=\"animationTimeCode\"></a>\nThe `Usd.TimeCode` class is a small wrapper class for handling time encoding. Currently it does nothing more than storing if it is a `default` time code or a `time/frame` time code with a specific frame. In the future it may get the concept of encoding in `time` instead of `frame`, so to future proof your code, you should always use this class instead of setting a time value directly.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:animationTimeCode}}\n```\n~~~\n\n### Layer Offset (A Non-Animateable Time Offset/Scale for Composition Arcs) <a name=\"animationLayerOffset\"></a>\nThe `Sdf.LayerOffset` is used for encoding a time offset and scale for composition arcs. \n\n~~~admonish warning\nThe offset and scale cannot be animated.\n~~~\n\nFollowing composition arcs can use it:\n- Sublayers\n- Payloads\n- References (Internal & file based)\n\nThe Python exposed LayerOffsets are always read-only copies, so you can't modify them in-place.\nInstead you have to create new ones and re-write the arc/assign the new layer offset.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:animationLayerOffset}}\n```\n~~~\n\nIf you are interested on how to author composition in the low level API, checkout our [composition](../composition/overview.md) section.\n\n### Reading & Writing default values, time samples and value blocks <a name=\"animationReadWrite\"></a>\n\n#### Writing data\n\nHere are the high and low level APIs to write data.\n~~~admonish tip\nWhen writing a large amount of samples, you should use the low level API as it is a lot faster.\n~~~\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:animationWrite}}\n```\n~~~\n\nIf you are not sure if a schema attribute can have time samples, you can get the variability hint.\nThis is only a hint, it is up to you to not write time samples. In some parts of Usd things will fail or not work as exepcted if you write time samples for a non varying attribute.\n~~~admonish info title=\"\"\n```python\nattr.GetMetadata(\"variability\") == Sdf.VariabilityVarying\nattr.GetMetadata(\"variability\") == Sdf.VariabilityUniform \n```\n~~~\n\n#### Reading data\n\nTo read data we recommend using the high level API. That way you can also request data from value clipped (per frame loaded Usd) files. The only case where reading directly in the low level API make sense is when you need to open a on disk layer and need to tweak the time samples. Check out our [FX Houdini](../../dcc/houdini/fx/pointinstancers.md) section for a practical example.\n\n~~~admonish tip\nIf you need to check if an attribute is time sampled, run the following:\n```python\n{{#include ../../../../../code/core/elements.py:animationTimeVarying}}\n```\nIf you know the whole layer is in memory, then running GetNumTimeSamples()\nis fine, as it doesn't have t open any files.\n~~~\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:animationRead}}\n```\n~~~\n\n#### Special Values\nYou can also tell a time sample to block a value. Blocking means that the attribute at that frame will act as if it doesn't have any value written (\"Not authored\" in USD speak) to stage queries and render delegates.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:animationSpecialValues}}\n```\n~~~\n\n### Time Metrics (Frames Per Second & Frame Range) <a name=\"animationMetadata\"></a>\nWith what FPS the samples are interpreted is defined by the `timeCodesPerSecond`/`framesPerSecond` metadata.\n\nWhen working with stages, we have the following [loading order of FPS](https://openusd.org/dev/api/class_usd_stage.html#a85092d7455ae894d50224e761dc6e840):\n1. timeCodesPerSecond from session layer\n1. timeCodesPerSecond from root layer\n1. framesPerSecond from session layer\n1. framesPerSecond from root layer\n1. fallback value of 24\n\nThese should match the FPS settings of your DCC. The 'framesPerSecond' is intended to be a hint for playback engines (e.g. your DCC/Usdview etc.) to set the FPS to when reading your file. The 'timeCodesPerSecond' describes the actual time sample intent. With the fallback behavior we can also only specify the 'framesPerSecond' to keep both metadata entries in sync.\n\nWhen working with layers, we have the following [loading order of FPS](https://openusd.org/dev/api/class_sdf_layer.html#a8c7a1ac2e85efa2aa4831123de576b7c):\n1. timeCodesPerSecond of layer\n1. framesPerSecond of layer\n1. fallback value of 24\n\n~~~admonish info\nWhen loading samples from a sublayered/referenced or payloaded file, USD automatically uses the above mentioned metadata in the layer as a frame of reference of how to bring in the time samples. If the FPS settings mismatch it will automatically scale the time samples to match our stage FPS settings as mentioned above.\n\nTherefore when writing layers, we should always write these layer metrics, so that we know what\nthe original intended FPS were and our caches work FPS independently.\n~~~\n\n~~~admonish warning\nIn VFX we often work starting from 1001 regardless of the FPS as it is easier for certain departments like FX to have pre-cache frames to init their sims as well as it also makes it easier to write frame based expressions. That means that when working with both 25 and 24 FPS caches, we have to adjust the offset of the incoming cache.\n\nLet's say we have an anim in 25 FPS starting off at 1001 that we want to bring into a 24 FPS scene. USD as mentioned above handles the scaling for us based on the metadata, but since we still want to start at 1001, we have to offset based on \"frame_start * (stage_fps/layer_fps) - frame_start\". See the below commented out code for a live example. That way we now have the same 25 FPS cache running in 24 FPS from the same \"starting pivot\" frame. If we work fully time based, we don't have this problem, as animation in the 25 FPS cache would have its time samples written at larger frames than the 24 FPS cache and USD's scaling would auto correct it.\n~~~\n\n```python\n(\n    timeCodesPerSecond = 24\n    framesPerSecond = 24\n    metersPerUnit = 1\n    startTimeCode = 1001\n    endTimeCode = 1010\n)\n```\n\nThe `startTimeCode` and `endTimeCode` entries give intent hints on what the (useful) frame range of the USD file is. Applications can use this to automatically set the frame range of the stage when opening a USD file or use it as the scaling pivot when calculating time offsets or creating loop-able caches via value clips.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:animationFPS}}\n```\n~~~\n\n\n\n\n\n### Motion Blur - Computing Velocities and Accelerations <a name=\"animationMotionVelocityAcceleration\"></a>\nMotion blur is computed by the hydra delegate of your choice using either the interpolated position data or by making use of velocity/acceleration data.\nDepending on the image-able schema, the attribute namings slightly differ, e.g. for meshes the names are 'UsdGeom.Tokens.points', 'UsdGeom.Tokens.velocities', 'UsdGeom.Tokens.accelerations'. Check the specific schema for the property names.\n\n~~~admonish warning\nDepending on the delegate, you will likely have to set specific primvars that control the sample rate of the position/acceleration data.\n~~~\n\nWe can also easily derive velocities/accelerations from position data, if our point count doesn't change:\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:animationMotionVelocityAcceleration}}\n```\n~~~\n\nYou can find a interactive Houdini demo of this in our [Houdini - Motion Blur](../../dcc/houdini/fx/motionblur.md) section.\n\n### Stitching/Combining time samples<a name=\"animationStitch\"></a>\nWhen working with Usd in DCCs, we often have a large amount of data that needs to be exported per frame. To speed this up, a common practice is to have a render farm, where multiple machines render out different frame ranges of scene. The result then needs to be combined into a single file or loaded via value clips for heavy data (as described in the next section below).\n\n~~~admonish tip\nStitching multiple files to a single file is usually used for small per frame USD files. If you have large (1 GB > ) files per frame, then we recommend using values clips. During stitching all data has to be loaded into memory, so your RAM specs have to be high enough to handle all the files combined.\n~~~\n\nA typical production use case we use it for, is rendering out the render USD files per frame and then stitching these, as these are usually a few mb per frame at most.\n\n~~~admonish warning\nWhen working with collections, make sure that they are not too big, by selecting parent prims where possible. Currently USD stitches target path lists a bit inefficiently, which will result in your stitching either not going through at all or taking forever. See our [collections](../composition/relationships.md) section for more details.\n~~~\n\nUSD ships with a standalone `usdstitch` commandline tool, which is a small Python wrapper around the `UsdUtils.StitchLayers()` function. You can read more it in our [standalone tools](./standalone_utilities.md) section.\n\nIn Houdini you can find it in the `$HFS/bin`folder, e.g. `/opt/hfs19.5/bin`.\n\nHere is an excerpt:\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:animationStitchCmdlineTool}}\n```\n~~~\n\nMore about layer stitching/flattening/copying in our [layer](./layer.md) section.\n\n### Value Clips (Loading time samples from multiple files)<a name=\"animationValueClips\"></a>\n~~~admonish note\nWe only cover value clips in a rough overview here, we might extend this a bit more in the future, if there is interest. We recommend checking out the [official docs page](https://openusd.org/dev/api/_usd__page__value_clips.html) as it is well written and worth the read!\n~~~\n\nUSD [value clips](https://openusd.org/dev/api/_usd__page__value_clips.html) are USD's mechanism of loading in data per frame from different files. It has a special rule set, that we'll go over now below.\n\n~~~admonish important\nComposition wise, value clips (or the layer that specifies the value clip metadata) is right under the `local` arc strength and over `inherit` arcs.\n~~~\n\nHere are some examples from USD's official docs:\n\n```python\ndef \"Prim\" (\n    clips = {\n        dictionary clip_set_1 = {\n            double2[] active = [(101, 0), (102, 1), (103, 2)] \n            asset[] assetPaths = [@./clip1.usda@, @./clip2.usda@, @./clip3.usda@]\n            asset manifestAssetPath = @./clipset1.manifest.usda@\n            string primPath = \"/ClipSet1\"\n            double2[] times = [(101, 101), (102, 102), (103, 103)]\n        }\n    }\n    clipSets = [\"clip_set_1\"]\n)\n{\n}\n```\n\nThere is also the possibility to encode the value clip metadata via a file wild card syntax (The metadata keys start with `template`). We recommend sticking to the the above format as it is more flexible and more explicit.\n\n~~~admonish info title=\"Click here to expand contents\" collapsible=true\n```python\ndef \"Prim\" (\n    clips = {\n        dictionary clip_set_2 = {\n            string templateAssetPath = \"clipset2.#.usd\"\n            double templateStartTime = 101\n            double templateEndTime = 103\n            double templateStride = 1\n            asset manifestAssetPath = @./clipset2.manifest.usda@\n            string primPath = \"/ClipSet2\"\n        }\n    }\n    clipSets = [\"clip_set_2\"]\n)\n{\n}\n```\n~~~\n\nAs you can see it is pretty straight forward to implement clips with a few key metadata entries:\n- `primPath`: Will substitute the current prim path with this path, when looking in the clipped files. This is similar to how you can specify a path when creating references (when not using the `defaultPrim` metadata set in the layer metadata).\n- `manifestAssetPath`: A asset path to a file containing a hierarchy of attributes that have time samples without any default or time sample data.\n- `assetPaths`: A list of asset paths that should be used for the clip.\n- `active`: A list of (\\<stage time\\>, \\<asset path list index\\>) pairs, that specify on what frame what clip is active.\n- `times`: A list of (\\<stage time\\>, \\<asset path time\\>) pairs, that map how the current time should be mapped into the time that should be looked up in the active asset path file.\n- `interpolateMissingClipValues` (Optional): Boolean that activates interpolation of time samples from surrounding clip files, should the active file not have any data on the currently requested time.\n\n~~~admonish warning\nThe content of individual clip files must be the raw data, in other words anything that is loaded in via composition arcs is ignored.\n~~~\n\nThe other files that are needed to make clips work are:\n- The `manifest` file: A file containing a hierarchy of attributes that have time samples  without any default or time sample data.\n- The `topology` file: A file containing all the attributes that only have static `default` data.\n\nHere is how you can generate them:\nUSD ships with a `usdstitchclips` commandline tool that auto-converts multiple clip (per frame) files to a value clipped main file for you. This works great if you only have a single root prim you want to load clipped data on. \n\nUnfortunately this is often not the case in production, so this is where the value clip API comes into play. The `usdstitchclips` tool is a small Python wrapper around that API, so you can also check out the Python code there.\n\nHere are the basics, the main modules we will be using are `pxr.Usd.ClipsAPI` and `pxr.UsdUtils`:\n\n~~~admonish tip\nTechnically you can remove all default attributes from the per frame files after running the topology layer generation. This can save a lot of disk space,but you can't partially re-render specific frames of the cache though. So only do this if you know the cache is \"done\".\n~~~\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:animationStitchClipsUtils}}\n```\n~~~\n\nSince in production (see the next section), we usually want to put the metadata at the asset roots, we'll usually only want to run \n- `UsdUtils.StitchClipsTopology(topology_layer, time_sample_files)`\n- `UsdUtils.StitchClipsManifest(manifest_layer, topology_layer, time_sample_files, clip_prim_path)`\n\nAnd then create the clip metadata in the cache_layer ourselves:\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:animationStitchClipsAPI}}\n```\n~~~\n\n\n#### How will I use it in production?\nValue clips are the go-to mechanism when loading heavy data, especially for animation and fx. They are also the only USD mechanism for looping data.\n\nAs discussed in more detail in our [composition](../composition/overview.md) section, caches are usually attached to asset root prim. As you can see above, the metadata must always specify a single root prim to load the clip on, this is usually your asset root prim. You could also load it on a prim higher up in the hierarchy, this makes your scene incredibly hard to debug though and is not recommended.\n\nThis means that if you are writing an fx cache with a hierarchy that has multiple asset roots, you'll be attaching the metadata to each individual asset root. This way you can have a single value clipped cache, that is loaded in multiple parts of you scene. You can then payload/reference in this main file, with the value clip metadata per asset root prim, per asset root prim, which allows you to partially load/unload your hierarchy as usual.\n\nYour file structure will look as follows:\n- Per frame(s) files with time sample data:\n    - /cache/value_clips/time_sample.1001.usd\n    - /cache/value_clips/time_sample.1002.usd\n    - /cache/value_clips/time_sample.1003.usd\n- Manifest file (A lightweight Usd file with attributes without values that specifies that these are attributes are with animation in clip files):    \n    - /cache/value_clips/manifest.usd \n- Topology file (A USD file that has all attributes with default values):    \n    - /cache/value_clips/topology.usd\n- Value clipped file (It sublayers the topology.usd file and writes the value clip metadata (per asset root prim)):\n    - /cache/cache.usd\n\nTypically your shot or asset layer USD files will then payload or reference in the individual asset root prims from the cache.usd file.\n\n~~~admonish important\nSince we attach the value clips to asset root prims, our value clipped caches can't have values above asset root prims.\n~~~\n\nIf this all sounds a bit confusing don't worry about it for now, we have a hands-on example in our \n[composition](../composition/overview.md) section.\n\n~~~admonish tip title=\"Value Clips and Instanceable Prims\"\nFor more info on how value clips affect instancing, check out our [composition](../composition/overview.md) section. There you will also find an example with multiple asset roots re-using the same value clipped cache.\n~~~\n\n\n#### How does it affect attribute time samples and queries?\nWhen working with time samples in value clips there are two important things to keep in mind:\n\n##### Subframes\nThe `active` and `times` metadata entries need to have sub-frames encoded. Let's look at our example:\n\nThree per frame files, with each file having samples around the centered frame:\n- /cache/value_clips/time_sample.1001.usd\": (1000.75, 1001, 1001.25)\n- /cache/value_clips/time_sample.1002.usd\": (1001.75, 1002, 1002.25)\n- /cache/value_clips/time_sample.1003.usd\": (1002.75, 1003, 1003.25)\n\nThey must be written as follows in order for subframe time sample to be read.\n```python\ndouble2[] active = [(1000.5, 0), (1001.75, 1), (1002.75, 2)] \ndouble2[] times = [(1000.5, 1000.5), (1001.75, 1001.75), (1002.75, 1003)]\n```\nAs you may have noticed, we don't need to specify the centred or .25 frame, these will be interpolated linearly to the next entry in the list.\n\n##### Queries\nWhen we call attribute.GetTimeSamples(), we will get the interval that is specified with the `times` metadata.\nFor the example above this would return:\n```python\n(1000.75, 1001, 1001.25, 1001.75, 1002, 1002.25, 1002.75, 1003, 1003.25)\n```\n\nIf we would only write the metadata on the main frames:\n```python\ndouble2[] active = [(1001, 0), (1002, 1), (1003, 2)] \ndouble2[] times = [(1001, 1001), (1002, 1002), (1003, 1003)]\n```\nIt will return:\n```python\n(1001, 1001.25, 1002, 1002.25, 1003, 1003.25)\n```\n~~~admonish important\nWith value clips it can be very expensive to call `attribute.GetTimesamples()` as this will open all layers to get the samples in the interval that is specified in the metadata. It does not only read the value clip metadata. If possible use `attribute.GetTimeSamplesInInterval()` as this only opens the layers in the interested interval range.\n~~~\n\n"
  },
  {
    "path": "docs/src/pages/core/elements/collection.md",
    "content": "# Collections\nCollections are USD's mechanism of storing a set of prim paths. We can nest/forward collections to other collections and relationships, which allows for powerful workflows. For example we can forward multiple collections to a light linking relationship or forwarding material binding relationships to a single collection on the asset root prim, which then in return forwards to the material prim.\n\n# Table of Contents\n1. [Collections In-A-Nutshell](#summary)\n1. [What should I use it for?](#usage)\n1. [Resources](#resources)\n1. [Overview](#overview)\n    1. [Creating & querying collections](#collectionQuery)\n    1. [Inverting a collection](#collectionInvert)\n\n## TL;DR - Metadata In-A-Nutshell <a name=\"summary\"></a>\n- Collections are encoded via a set of properties. A prim can store any number of collections.\n    - `collection:<collectionName>:includes` relationship: A list of target `Sdf.Path`s to include, we can als target other collections.\n    - `collection:<collectionName>:excludes` relationship: A list of target `Sdf.Path`s to exclude. These must be below the include paths.\n    - `collection:<collectionName>:expansionRule`attribute: Controls how collections are computed, either by running `includes` - `excludes` (mode `explicitOnly`) or by expanding all child prims and then doing `includes` - `excludes` (mode `expandPrims`).\n- Collections can link to other collections, which gives us a powerful mechanism of forwarding hierarchy structure information.\n- Collections can easily be accessed and queried via the [Usd.CollectionAPI](https://openusd.org/release/api/class_usd_collection_a_p_i.html). The query can be limited via USD [filter predicates](https://openusd.org/dev/api/prim_flags_8h.html#Usd_PrimFlags), e.g. to defined prims only.\n- To help speed up collection creation, USD also ships with util functions:\n    - Collection creation: `UsdUtils.AuthorCollection(<collectionName>, prim, [<includePathList>], [<excludePathList>])`\n    - Re-writing a collection to be as sparse as possible: `include_paths, exclude_paths = UsdUtils.ComputeCollectionIncludesAndExcludes(target_paths, stage)`\n\n## What should I use it for? <a name=\"usage\"></a>\n~~~admonish tip\nWe use collections for multiple things:\n- Creating a group of target paths, that are of interest to other departments, e.g. mark prims that are useful for FX/layout/lighting selections (for example character vs. background). Another common thing to use them for is storing render layer selections, that then get applied in our final render USD file.\n- Faster navigation of hierarchies by isolating to collections that interest us.\n- As collections can contain other collections, they are a powerful mechanism of forwarding and aggregating selections.\n~~~\n\n## Resources <a name=\"resources\"></a>\n- [Usd.CollectionAPI](https://openusd.org/release/api/class_usd_collection_a_p_i.html)\n- [UsdUtils Collection Convenience Functions](https://openusd.org/dev/api/authoring_8h.html#ad2939a973bd544ff30e4828ff09765db)\n\n\n## Overview <a name=\"overview\"></a>\nCollections are made up of relationships and attributes:\n- `collection:<collectionName>:includes` relationship: A list of target `Sdf.Path`s to include, we can als target other collections.\n- `collection:<collectionName>:excludes` relationship: A list of target `Sdf.Path`s to exclude. These must be below the include paths. Excluding another collection does not work. \n- `collection:<collectionName>:expansionRule`attribute: This controls how collections are expanded:\n    - `explicitOnly`: Do not expand to any child prims, instead just do an explicit diff between include and exclude paths. This is like a Python `set().difference()`.  \n    - `expandPrims`: Expand the include paths to all children and subtract the exclude paths.\n    - `expandPrimsAndProperties`: Same as `expandPrims`, but expand properties too. (Not used by anything at the moment).\n- (Optional) `collection:<collectionName>:includeRoot` attribute: When using `expandPrims`/`expandPrimsAndProperties` this bool attribute enables the includes to target the `/` pseudo root prim.\n\n~~~admonish danger title=\"Collection Size\"\nMake sure that you write your collections as sparsely as possible, as otherwise they can take a long time to combine when stitching multiple files, when writing per frame USD files.\n~~~\n\n### Creating & querying collections <a name=\"collectionQuery\"></a>\nWe interact with them via the `Usd.CollectionAPI` class [API Docs](https://openusd.org/release/api/class_usd_collection_a_p_i.html). The collection api is a multi-apply API schema, so we can add multiple collections to any prim.\n\nHere are the UsdUtils.ComputeCollectionIncludesAndExcludes [API docs](https://openusd.org/dev/api/authoring_8h.html#ad2939a973bd544ff30e4828ff09765db).\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:collectionOverview}}\n```\n~~~\n\n### Inverting a collection <a name=\"collectionInvert\"></a>\nWhen we want to isolate a certain part of the hierarchy (for example to pick what to render), a typical thing to do, is to give users a \"render\" collection which then gets applied by setting all prims not included to be [inactive](./prim.md#active). Here is an example of how to iterate a stage by pruning (skipping the child traversal) and deactivating anything that is not in the specific collection.\n\nThis is very fast and \"sparse\" as we don't edit leaf prims, instead we find the highest parent and deactivate it, if no children are part of the target collection.\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:collectionInvert}}\n```\n~~~\n"
  },
  {
    "path": "docs/src/pages/core/elements/data_container.md",
    "content": "# Data Containers (Prims & Properties)\nFor Usd to store data at the paths, we need a data container.\nTo fill this need, Usd has the concept of `prims`. \nPrims can own properties, which can either be `attributes` or `relationships`. These store all the data that can be consumed by clients. Prims are added to layers which are then written to on disk Usd files.\n\nIn the high level API it looks as follows:\n```mermaid\nflowchart LR\n    prim([Usd.Prim]) --> property([Usd.Property])\n    property --> attribute([Usd.Attribute])\n    property --> relationship([Usd.Relationship])\n```\nIn the low level API:\n```mermaid\nflowchart LR\n    prim([Sdf.PrimSpec]) --> property([Sdf.PropertySpec])\n    property --> attribute([Sdf.AttributeSpec])\n    property --> relationship([Sdf.RelationshipSpec])\n```\n\n### Structure\nLarge parts of the (high level and parts of the low level) API follow this pattern:\n\n- \\<ContainerType\\>.Has\\<Name\\>() or \\<ContainerType\\>.Is\\<Name\\>()\n- \\<ContainerType\\>.Create\\<Name\\>()\n- \\<ContainerType\\>.Get\\<Name\\>()\n- \\<ContainerType\\>.Set\\<Name\\>()\n- \\<ContainerType\\>.Clear\\<Name\\>() or .Remove\\<Name\\>()\n\nThe high level API also has the extra destinction of \\<ContainerType\\>.HasAuthored\\<Name\\>() vs .Has\\<Name\\>().\n`HasAuthored` only returns explicitly defined values, where `Has` is allowed to return schema fallbacks.\n\nThe low level API only has the explicitly defined values, as does not operate on the composed state and is therefore not aware of schemas (at least when it comes to looking up values). \n\nLet's do a little thought experiment:\n- If we were to compare Usd to .json files, each layer would be a .json file, where the nested key hierarchy is the Sdf.Path. Each path would then have standard direct key/value pairs like `typeName`/`specifier` that define metadata as well as the `attributes` and `relationships` keys which carry dicts with data about custom properties.\n- If we would then write an API for the .json files, our low level API would directly edit the keys. This is what the Sdf API does via `Sdf.PrimSpec`/`Sdf.PropertySpec`/`Sdf.AttributeSpec`/`Sdf.RelationshipSpec` classes. These are very small wrappers that set the keys more or less directly. They are still wrappers though.\n- To make our lives easier, we would also create a high level API, that would call into the low level API. The high level API would then be a public API, so that if we decide to change the low-level API, the high level API still works. Usd does this via the `Usd.Prim`/`Usd.Property`/`Usd.Attribute`/`Usd.Relationship` classes. These classes provide OOP patterns like Getter/Setters as well as common methods to manipulate the underlying data.\n\nThis is in very simplified terms how the Usd API works in terms of data storage.\n\n# Table of Contents\n1. [API Overview In-A-Nutshell](#summary)\n2. [What should I use it for?](#usage)\n3. [Resources](#resources)\n4. [Overview](#overview)\n    1. [Prims](./prim.md)\n    2. [Properties](./property.md)\n\n## TL;DR - Data Containers (Prims/Properties/Attributes/Relationships) In-A-Nutshell <a name=\"summary\"></a>\n- In order to store data at our `Sdf.Path`s, we need data containers. Usd therefore has the concept of `Usd.Prim`s/`Sdf.PrimSpec`s, which can hold `Usd.Property`ies/`Sdf.PropertySpec`s\n- To distinguish between data and data relations, `Usd.Property`ies are separated in:\n    - `Usd.Attribute`s/`Sdf.AttributeSpec`s: These store data of different types (float/ints/arrays/etc.)\n        - `UsdGeom.Primvar`s: These are the same as attributes with extra features:\n            - They are created the same way as attributes, except they use the `primvars.<myAttributeName>` namespace.\n            - They get inherited down the hierarchy if they are of constant interpolation (They don't vary per point/vertex/prim).\n            - They are exported to Hydra (Usd's render scene description abstraction API), so you can use them for materials/render settings/etc.\n    - `Usd.Relationship`s/`Sdf.RelationshipSpec`s: These store mapping from prim to prim(s) or attribute to attribute.\n\n## What should I use it for? <a name=\"usage\"></a>\n~~~admonish tip\nIn production, these are the classes you'll have the most contact with. They handle data creation/storage/modification. They are the heart of what makes Usd be Usd.\n~~~\n\n## Resources <a name=\"resources\"></a>\n- [Usd.Prim](https://openusd.org/dev/api/class_usd_prim.html)\n- [Usd.Property](https://openusd.org/dev/api/class_usd_property.html)\n- [Usd.Attribute](https://openusd.org/dev/api/class_usd_attribute.html)\n- [Usd.Relationship](https://openusd.org/dev/api/class_usd_relationship.html)\n- [Sdf.PrimSpec](https://openusd.org/dev/api/class_sdf_prim_spec.html)\n- [Sdf.PropertySpec](https://openusd.org/dev/api/class_sdf_property_spec.html)\n- [Sdf.AttributeSpec](https://openusd.org/dev/api/class_sdf_attribute_spec.html)\n- [Sdf.RelationshipSpec](https://openusd.org/dev/api/class_sdf_relationship_spec.html)\n\n## Overview <a name=\"overview\"></a>\nWe cover the details for prims and properties in their own sections as they are big enough topics on their own:\n- [Prims](./prim.md)\n- [Properties](./property.md)"
  },
  {
    "path": "docs/src/pages/core/elements/data_type.md",
    "content": "# Data Types/Roles\n\n# Table of Contents\n1. [Data Types/Roles In-A-Nutshell](#summary)\n1. [What should I use it for?](#usage)\n1. [Resources](#resources)\n1. [Overview](#overview)\n    1. [Data Types](#dataTypes)\n    1. [Data Roles](#dataRoles)\n\n## TL;DR - Metadata In-A-Nutshell <a name=\"summary\"></a>\nWhen reading and writing data in USD, all data is of a specific data type. USD extends the standard base types (`float`, `int`) with computer graphics related classes (e.g. `Gf.Matrix3d`, `Gf.Vec3h`) that make it easy to perform common 3d math operations and Usd related types (e.g. `Sdf.Asset`). To give a hint about how a data type should be used, we also have the concept of data roles (`Position`, `Normal`, `Color`). All data value type names are stored in the `Sdf.ValueTypeNames` registry, from these we can get the base classes stored in `Gf` (math related classes), `Sdf`(USD related classes) and `Vt` (array classes that carry `Gf` data types).\n\n~~~admonish tip title=\"Pro Tip | Creating arrays\"\nThe constructors for arrays allow us to input tuples/lists instead of the explicit base classes.\n```python\n# Explicit\npxr.Vt.Vec3dArray([Gf.Vec3d(1,2,3)])\n# Implicit\npxr.Vt.Vec3dArray([(1,2,3)])\n```\nInstead of searching for the corresponding `Gf` or `Vt` array class, we can get it from the type name and instantiate it:\n```python\nvec3h_array = Sdf.ValueTypeNames.Point3hArray.type.pythonClass([(0,1,2)])\n# Or: Usd.Attribute.GetTypeName().type.pythonClass([(0,1,2)]) / Sdf.AttributeSpec.typeName.type.pythonClass([(0,1,2)])\nprint(type(vec3h_array)) # Returns: <class 'pxr.Vt.Vec3hArray'>\n```\nAs `Vt.Array` support the buffer protocol, we can map the arrays to numpy without data duplication and perform high performance \nvalue editing.\n```python\nfrom pxr import Vt\nimport numpy as np\nfrom array import array\n# Python Arrays\nvt_array = Vt.Vec3hArray.FromBuffer(array(\"f\", [1,2,3,4,5,6])) # Returns: Vt.Vec3hArray(2, (Gf.Vec3h(1.0, 2.0, 3.0),Gf.Vec3h(4.0, 5.0, 6.0),))\n# From Numpy Arrays \nVt.Vec3hArray.FromNumpy(np.ones((10, 3)))\nVt.Vec3hArray.FromBuffer(np.ones((10, 3)))\n# To Numpy arrays\nnp.array(vt_array)\n```\n~~~\n\n## What should I use it for? <a name=\"usage\"></a>\n~~~admonish tip\nWhen creating attributes we always have to specify a `Sdf.ValueTypeName`, which defines the data type & role.\nUSD ships with great computer graphics related classes in the `Gf` module, which we can use for calculations.\nThe `Vt.Array` wrapper around the `Gf` data base classes implements the buffer protocol, so we can easily map these arrays to Numpy arrays and perform high performance value edits. This is great for adjusting geometry related attributes.\n~~~\n\n## Resources <a name=\"resources\"></a>\n- [USD API Data Type Docs](https://openusd.org/dev/api/_usd__page__datatypes.html)\n- [Nvidia USD Data Types Docs](https://docs.omniverse.nvidia.com/dev-guide/latest/dev_usd/quick-start/usd-types.html)\n\n## Overview <a name=\"overview\"></a>\nWhen reading and writing data in USD, all data is of a specific data type. USD extends the standard base types (`float`, `int`) with computer graphics related classes (`Gf.Matrix3d`, `Gf.Vec3h`) that make it easy to perform common 3d math operations. To give a hint about how a data type should be used, we also have the concept of data roles.\n\n### Data Types <a name=\"dataTypes\"></a>\nLet's first talk about data types. These are the base data classes all data is USD is stored in.\n\nTo access the base data classes there are three modules:\n- `Sdf`(Scene Description Foundations): Here you'll 99% of the time only be using `Sdf.AssetPath`, `Sdf.AssetPathArray` and the [list editable ops](../composition/listeditableops.md) that have the naming convention `<Type>ListOp` e.g. `Sdf.PathListOp`, `Sdf.ReferenceListOp`, `Sdf.ReferenceListOp`, `PayloadListOp`, `StringListOp`, `TokenListOp`\n- `Gf`(Graphics Foundations): The `Gf` module is basically USD's math module. Here we have all the math related data classes that are made up of the base types (base types being `float`, `int`, `double`, etc.). Commonly used classes/types are `Gf.Matrix4d`, `Gf.Quath`(Quaternions), `Gf.Vec2f`, `Gf.Vec3f`, `Gf.Vec4f`. Most classes are available in different precisions, noted by the suffix `h`(half),`f`(float), `d`(double).\n- `Vt` (Value Types): Here we can find all the `Array` (list) classes that capture the base classes from the `Gf` module in arrays. For example `Vt.Matrix4dArray`. The `Vt` arrays implement the [buffer protocol](https://docs.python.org/3/c-api/buffer.html), so we can convert to Numpy/Python without data duplication. This allows for some very efficient array editing via Python. Checkout our [Houdini Particles](../../dcc/houdini/fx/particles.md) section for a practical example. The value types module also houses wrapped base types (`Float`, `Int`, etc.), we don't use these though, as with Python everything is auto converted for us.\n\nThe `Vt.Type` registry also handles all on run-time registered types, so not only data types, but also custom types like `Sdf.Spec`,`SdfReference`, etc. that is registered by plugins.\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:tfTypeRegistry}}\n```\n~~~\n\n\n### Data Roles <a name=\"dataRoles\"></a>\nNext let's explain what data roles are. Data roles extend the base data types by adding an hint about how the data should be interpreted. For example `Color3h`is just `Vec3h` but with the `role` that it should be treated as a color, in other words it should not be transformed by xforms ops, unlike `Point3h`, which is also `Vec3h`. Having roles is not something USD invented, you can find something similar in any 3d application.\n\n### Working with data classes in Python \nYou can find all values roles (and types) in the `Sdf.ValueTypeNames` module, this is where USD keeps the value type name registry.\n\nThe `Sdf.ValueTypeName` class gives us the following properties/methods:\n- `aliasesAsStrings`: Any name aliases e.g. `texCoord2f[]`\n- `role`: The role (intent hint), e.g. \"Color\", \"Normal\", \"Point\"\n- `type`: The actual Tf.Type definition. From the type definition we can retrieve the actual Python data type class e.g. `Gf.Vec3h` and instantiate it.\n- `cppTypeName`: The C++ data type class name, e.g `GfVec2f`. This is the same as `Sdf.ValueTypeNames.TexCoord2f.type.typeName`\n- `defaultUnit`: The default unit. As USD is unitless (at least per when it comes to storing the data), this is `Sdf.DimensionlessUnitDefault` most of the time.\n- `defaultValue`: The default value, e.g. `Gf.Vec2f(0.0, 0.0)`. For arrays this is just an empty Vt.Array. We can use `.scalarType.type.pythonClass` or `.scalarType.defaultValue` to get a valid value for a single element.\n- Check/Convert scalar <-> array value type names:\n    - `isArray`: Check if the type is an array.\n    - `arrayType`: Get the vector type, e.g. `Sdf.ValueTypeNames.AssetArray.arrayType`gives us `Sdf.ValueTypeNames.AssetArray`\n    - `isScalar`: Check if the type is scalar.\n    - `scalarType`: Get the scalar type, e.g. `Sdf.ValueTypeNames.AssetArray.scalarType`gives us `Sdf.ValueTypeNames.Asset`\n\nWe can also search based on the string representation or aliases of the value type name, e.g. `Sdf.ValueTypeNames.Find(\"normal3h\")`.\n\n~~~admonish tip title=\"Pro Tip | Creating arrays\"\nThe constructors for arrays allow us to input tuples/lists instead of the explicit base classes.\n```python\n# Explicit\npxr.Vt.Vec3dArray([Gf.Vec3d(1,2,3)])\n# Implicit\npxr.Vt.Vec3dArray([(1,2,3)])\n```\nInstead of searching for the corresponding `Gf` or `Vt` array class, we can get it from the type name:\n```python\nvec3h_array =  Sdf.ValueTypeNames.Point3hArray.type.pythonClass((0,1,2))\nprint(type(vec3h_array)) # Returns: <class 'pxr.Vt.Vec3hArray'>\n```\n~~~\n\n\nWe won't be looking at specific data classes on this page, instead we'll have a look at how to access the data types from value types and vice versa as usually the data is generated by the DCC we use and our job is to validate the data type/role or e.g. create attributes with the same type when copying values.\n\n\nLet's look at this in practice:\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:dataTypeRoleOverview}}\n```\n~~~\n"
  },
  {
    "path": "docs/src/pages/core/elements/layer.md",
    "content": "# Layers & Stages\nLayers and stages are the main entry point to accessing our data stored in USD.\n\n# Table of Contents\n1. [Layers & Stages In-A-Nutshell](#summary)\n1. [What should I use it for?](#usage)\n1. [Resources](#resources)\n1. [Overview](#overview)\n1. [Layers](#layerOverview)\n    1. [Layer Singleton](#layerSingleton)\n    1. [(Anonymous) Layer Identifiers](#layerIdentifier) \n    1. [Layers Creation/Import/Export](#layerImportExport)\n    1. [Dependencies](#layerDependencies)\n    1. [Layer Metrics](#layerMetrics)\n    1. [Permissions](#layerPermissions)\n    1. [Muting](#layerMuting)\n    1. [Composition](#layerCompositionArcs)\n    1. [Traversal and Prim/Property Access](#layerTraversal)\n    1. [Time Samples](#layerTimeSamples)\n    1. [Metadata](#layerMetadata)\n1. [Stages](#stageOverview)\n    1. [Configuration](#stageConfiguration)\n        1. [Asset Resolver](#stageAssetResolver)\n        1. [Stage Metrics](#stageMetrics)\n        1. [Stage Time Sample Interpolation](#stageTimeSampleInterpolation)\n        1. [Variant/Prim Type Fallbacks](#stageFallbacks)\n        1. [Color Management](#stageColormanagement)\n        1. [Default Render Settings](#stageRenderSettingsDefault)\n        1. [Metadata](#stageMetadata)\n    1. [Composition](#stageComposition)\n    1. [Loading mechanisms ](#stageLoadingMechanisms)\n    1. [Stage Layer Management (Creation/Save/Export)](#stageLayerManagement)\n    1. [Traversal and Prim/Property Access](#stageTraversal)\n\n## TL;DR - Layers & Stages In-A-Nutshell <a name=\"summary\"></a>\n**Layers**\n- Layers are managed via a singleton pattern: Each layer is only opened once in memory and is identified by the layer identifier. When stages load a layer, they point to the same data in memory.\n- Layers identifiers can have two different formats:\n    - Standard identifiers: `Sdf.Layer.CreateNew(\"/file/path/or/URI/identifier.<ext(.usd/.usdc/.usda)>\")`, these layers are backed by a file on disk\n    - Anonymous identifiers: `Sdf.Find('anon:<someHash(MemoryLocation)>:<customName>'`, these are in-memory only layers\n\n**Stages**\n- A stage is a view of a set of composed layers. You can think of it as the viewer in a view--model design. Each layer that the stage opens is a data source to the data model. When \"asking\" the stage for data, we ask the view for the combined (composed) data, which then queries into the layers based on the value source found by our composition rules.\n- When creating a stage we have two layers by default:\n    - **Session Layer**: This is a temp layer that doesn't get applied on disk save. Here we usually put things like viewport overrides.\n    - **Root Layer**: This is the base layer all edits target by default. We can add sublayers based on what we need to it. When calling `stage.Save()`, all sublayers that are dirty and not anonymous, will be saved. \n\n## What should I use it for? <a name=\"usage\"></a>\n~~~admonish tip\nStages and layers are what make USD work, it is our entry point to accessing our hierarchies.\n~~~\n\n## Resources <a name=\"resources\"></a>\n- [Sdf.Layer](https://openusd.org/dev/api/class_sdf_layer.html)\n- [Usd.Stage](https://openusd.org/release/api/class_usd_stage.html)\n- [Usd.EditTarget](https://openusd.org/release/api/class_usd_edit_target.html)\n\n## Overview <a name=\"overview\"></a>\nThis section will focus on what the `Sdf.Layer` and `Usd.Stage` classes have to offer. For an explanation of how layers work together, please see our [compsition section](../composition/overview.md).\n\n~~~admonish tip title=\"Pro Tip | Advanced Concepts and Utility Functions for Layers/Stages\"\nThere are also utility methods available, that are not in the `Sdf.Layer`/`Usd.Stage` namespace.\nWe cover these in our [advanced concepts in production](../../production/concepts.md) section.\n~~~\n\n## Layers <a name=\"layerOverview\"></a>\n```mermaid\nflowchart LR\n    layerSingleton(Layer Singleton/Registry) --> layer1([Layer])\n    layer1([Layer]) --> prim1([Property])\n    prim1([Prim]) --> property([Property])\n    property --> attribute([Attribute])\n    property --> relationship([Relationship])\n    layerSingleton --> layer2([Layer])\n    layer2([Layer]) --> prim2([...])\n```\n\nLayers are the data container for our prim specs and properties, they are the part of USD that actually holds and import/exports the data.\n\n~~~admonish tip title=\"Layers - In-A-Nutshell\"\n- Layers are managed via a singleton pattern: Each layer is only opened once in memory and is identified by the layer identifier.\n- Layers identifiers can have two different formats:\n    - Standard identifiers: `Sdf.Layer.CreateNew(\"/file/path/or/URI/identifier.<ext(.usd/.usdc/.usda)>\")`\n    - Anonymous identifiers: `Sdf.Find('anon:<someHash(MemoryLocation)>:<customName>'` \n- Layers store our prim and property specs, they are the data container for all USD data that gets persistently written to file. When we want to edit layers directly, we have to use the low-level API, the high level API edits the stage, which in return forwards the edits to the layer that is set by the active edit target.\n- The `Sdf.FileFormat` plugin interface allows us to implement plugins that convert the content of (custom) file format's to the USD's prim/property/metadata data model. This is how USD manages the [USD crate (binary)](https://openusd.org/release/glossary.html#crate-file-format), alembic and vdb formats.\n- USD's [crate (binary)](https://openusd.org/release/glossary.html#crate-file-format) format allows layers to be lazily read and written to. Calling `layer.Save()` multiple times, flushes the in-memory content to disk by appending it to the .usd file, which allows us to efficiently write large layer files. This format can also read in hierarchy data without loading property value data. This way we have low IO when opening files, as the property data gets lazy loaded on demand. This is similar to how we can parse image metadata without reading the image content.\n~~~\n\n### Layer Singleton <a name=\"layerSingleton\"></a>\nLayers in USD are managed by a singleton design pattern. This means that each layer, identified by its layer identifier, can only be opened once. Each stage that makes use of a layer, uses the same layer. That means if we make an edit on a layer in one stage, all other stages will get changed notifications and update accordingly.\n\nWe get all opened layers via the `Sdf.Layer.GetLoadedLayers()` method.\n~~~admonish tip title=\"\"\n```python\nfor layer in Sdf.Layer.GetLoadedLayers():\n    print(layer.identifier)\n# Skip anonymous layers\nfor layer in Sdf.Layer.GetLoadedLayers():\n    if layer.anonymous:\n        continue\n    print(layer.identifier)\n```\n~~~\n\nIf a layer is no longer used in a stage and goes out of scope in our code, it will be deleted. If we still have access to the Python object, we can check whether it points to a valid layer using the `layer.expired` property.\n\nAs also mentioned in the next section, the layer identifier is made up of the URI(Unique Resource Identifier) and optional arguments. The layer identifier includes the optional args. This is on purpose, because different args can potentially mean a different file.\n\nTo demonstrate the singleton behavior let's try changing a layers content in Houdini and then view the layer through two different unrelated stages. (In Houdini every LOPs node is a separate stage):\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/core/elements/layerSingleton.mp4\" type=\"video/mp4\" alt=\"Houdini Layer Singleton\">\n</video>\n\nThe snippet from the video:\n\n~~~admonish tip title=\"\"\n```python\nfrom pxr import Sdf\nflippy_layer = Sdf.Layer.FindOrOpen(\"/opt/hfs19.5/houdini/usd/assets/rubbertoy/geo.usdc\")\npig_layer = Sdf.Layer.FindOrOpen(\"/opt/hfs19.5/houdini/usd/assets/pig/geo.usdc\")\nflippy_layer.TransferContent(pig_layer)\n```\n~~~\n\n\"No flippyyyy, where did you go?\" Luckily all of our edits were just in memory, so if we just call layer.Reload() or refresh the layer via the reference node, all is good again. \n\nShould you ever use this in production as a way to broadcast an edit of a nested layer? We wouldn't recommend it, as it breaks the WYSIWYG paradigm. A better approach would be to rebuild the layer stack (this is what Houdini's \"Edit Target Layer\" node does) or we remap it via our asset resolver. In Houdini you should never use this method, as it can cause very strange stage caching issues.\n\n### (Anonymous) Layer Identifiers <a name=\"layerIdentifier\"></a>\nLayer identifiers come in two styles:\n- Standard identifiers: `Sdf.Layer.CreateNew(\"URI.<ext(.usd/.usdc/.usda)>\")`\n- Anonymous identifiers: `Sdf.Find('anon:<someHash(MemoryLocation)>:<customName>'` \n\nWe can optionally add file format args: `Sdf.Layer.CreateNew(\"URI.<ext>:SDF_FORMAT_ARGS:<ArgNameA>=<ArgValueA>&<ArgNameB>=<ArgValueB>\")` \n\nAnonymous layers have these special features:\n- They are in-memory layers that have no real path or asset information fields.\n- We can additionally give a custom name suffix, so that we can identify the layer better visually\n- The identifier is not run through the asset resolver (Edit: I have to verify this again, but I'm fairly certain)\n- They cannot be saved via `layer.Save()`, it will return an error\n- We can convert them to \"normal\" layers, by assigning a non-anonymous identifier (`layer.identifier=\"/file/path/myIdentifier.usd\"`), this also removes the save permission lock.\n\nWhen using standard identifiers, we use the URI not the absolute resolved path. The URI is then resolved by our [asset resolver](../plugins/assetresolver.md). We often need to compare the URI, when doing so be sure to call `layer_uri, layer_args = layer.SplitIdentifier(layer.identifier)` to strip out the optional args or compare using the resolve URI `layer.realPath`. \n\n~~~admonish danger\nThe layer identifier includes the optional args. This is on purpose, because different args can potentially mean a different file.\n~~~\n\nIf we write our own [file format plugin](https://openusd.org/dev/api/_sdf__page__file_format_plugin.html), we can also pass in these args via attributes, but only non animated.\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:layerIdentifier}}\n```\n~~~\n\n### Layers Creation/Import/Export <a name=\"layerImportExport\"></a>\n\nHere is an overview of how we can create layers:\n~~~admonish danger title=\"Pro Tip  | Saving and Reloading\"\n- We can call layer.Save() multiple times with the USD binary format (.usd/.usdc). This will then dump the content from memory to disk in \"append\" mode. This avoids building up huge memory footprints when creating large layers.\n- Calling `layer.Reload()` on anonymous layers clears their content (destructively). So make sure you can really dispose of it as there is no undo method.\n- To reload all (composition) related layers, we can use `stage.Reload()`. This calls `layer.Reload()` on all used stage layers.\n- Calling `layer.Reload()` consults the result of `layer.GetExternalAssetDependencies()`. These return non USD/composition related external files, that influence the layer. This is only relevant when using non USD file formats.\n~~~\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:layerImportExport}}\n```\n~~~\n\n### Dependencies <a name=\"layerDependencies\"></a>\nWe can also query the layer dependencies of a layer. \n\n~~~admonish tip title=\"Pro Tip | Inspecting dependencies\"\nThe most important methods are:\n- `layer.GetCompositionAssetDependencies()`: This gets layer identifiers of sublayer/reference/payload composition arcs. This is only for the active layer, it does not run recursively.\n- `layer.UpdateCompositionAssetDependency(\"oldIdentifier\", \"newIdentifier\")`: The allows us to remap any sublayer/reference/payload identifier in the active layer, without having to edit the list-editable ops ourselves. Calling `layer.UpdateCompositionAssetDependency(\"oldIdentifier\", \"\")` removes a layer.\n~~~\n\nIn our example below, we assume that the code is run in Houdini.\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:layerDependencies}}\n```\n~~~\n\nNow there are also utility functions available in the `UsdUtils` module ([USD Docs](https://openusd.org/dev/api/flatten_layer_stack_8h.html)):\n- **UsdUtils.ExtractExternalReferences**: This is similar to `layer.GetCompositionAssetDependencies()`, except that it returns three lists: `[<sublayers>], [<references>], [<payloads>]`. It also consults the assetInfo metadata, so result might be more \"inclusive\" than `layer.GetCompositionAssetDependencies()`.\n- **UsdUtils.ComputeAllDependencies**: This recursively calls `layer.GetCompositionAssetDependencies()` and gives us the aggregated result.\n- **UsdUtils.ModifyAssetPaths**: This is similar to Houdini's output processors. We provide a function that gets the input path and returns a (modified) output path.\n\n### Layer Metrics <a name=\"layerMetrics\"></a>\nWe can also set animation/time related metrics, these are stored via metadata entries on the layer itself.\n~~~admonish info title=\"\"\n```python\n(\n    timeCodesPerSecond = 24\n    framesPerSecond = 24\n    startTimeCode = 1\n    endTimeCode = 240\n    metersPerUnit = 0.01\n    upAxis = \"Z\"\n)\n```\n~~~\n\nAs this is handled via metadata, we cover it in detail our [Animation (Time related metrics)](./animation.md#animationMetadata), [Scene Unit Scale/UpAxis - FAQ](../../production/faq.md) and [Metadata](./metadata.md#metadataMetricsLayer) sections.\n\nThe `metersPerUnit` and `upAxis` are only intent hints, it is up to the application/end user to correctly interpret the data and change it accordingly.\n\nThe time related metrics should be written into all layers, as we can then use them to quickly inspect time related data in the file without having to fully parse it.\n\n### Permissions <a name=\"layerPermissions\"></a>\nWe can lock a layer to not allow editing or save permissions. Depending on the DCC, this is automatically done for you depending on how you access the stage. However, some applications leave this up to the user.\n\nAnonymous layers can't be saved to disk, therefore for them `layer.permissionToSave` is always `False`.\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:layerPermissions}}\n```\n~~~\n\n### Muting <a name=\"layerMuting\"></a>\nMuting layers can be done globally on the layer itself or per stage via `stage.MuteLayer(layer.identifier)`/`stage.UnmuteLayer(layer.identifier)`.\nWhen doing it globally on the layer, it affects all stages that use the layer. This is also why the mute method is not exposed on a layer instance, instead we call it on the `Sdf.Layer` class, as we modify muting on the singleton.\n\nMore info on this topic in our [loading data](./loading_mechanisms.md) section.\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:layerMuting}}\n```\n~~~\n\n### Composition <a name=\"layerCompositionArcs\"></a>\nAll composition arcs, excepts sublayers, are created on prim(specs). Here is how we edit sublayers (and their `Sdf.LayerOffsets`) on `Sdf.Layer`s:\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/composition.py:compositionArcSublayer}}\n```\n~~~\n\nFor more info on composition arcs (especially the sublayer arc) see our [Composition](../composition/arcs.md#compositionArcSublayer) section.\n\n\n#### Default Prim\nAs discussed in more detail in our [composition](../composition/overview.md) section, the default prim specifies the default root prim to import via reference and payload arcs. If it is not specified, the first prim in the layer is used, that is not [abstract](./prim.md#primSpecifier) (not a prim with a class specifier) and that is [defined](./prim.md#primSpecifier) (has a `Sdf.SpecifierDef` define specifier), unless we specify them explicitly. We cannot specify nested prim paths, the path must be in the root (`Sdf.Path(\"/example\").IsRootPrimPath()` must return `True`). Setting an invalid path will not cause an error, but it will not work when referencing or payloading the file.\n\nWe typically use this in asset layers to specify the root prim that is the asset.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:layerDefaultPrim}}\n```\n~~~\n\n### Traversal and Prim/Property Access <a name=\"layerTraversal\"></a>\nTraversing and accessing prims/properties works a tad different:\n- The `layer.Get<SpecType>AtPath` methods return `Sdf.Spec` objects (`Sdf.PrimSpec`, `Sdf.AttributeSpec`, `Sdf.RelationshipSpec`) and not USD high level objects.\n- The traverse method doesn't return an iterable range, instead it is \"kernel\" like. We pass it a function that each path in the layer gets run through.\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:layerTraversal}}\n```\n~~~\n\n### Time Samples <a name=\"layerTimeSamples\"></a>\nIn the high level API, reading and writing time samples is handled via the `attribute.Get()/Set()` methods. In the lower level API, we use the methods exposed on the layer.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:layerTimeSamples}}\n```\n~~~\n\nSee our [animation section](./animation.md) for more info about how to deal with time samples.\n\n\n\n### Metadata <a name=\"layerMetadata\"></a>\nLayers, like prims and properties, can store metadata. Apart from the above mentioned layer metrics, we can store custom metadata in the `customLayerData` key or create custom metadata root keys as discussed in our [metadata plugin](../plugins/metadata.md) section. This can be used to track important pipeline related data without storing it on a prim.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:metadataLayer}}\n```\n~~~\n\nSee our [Metadata](./metadata.md#metadataLayerStage) section for detailed examples for layer and stage metadata.\n\n\n\n\n\n\n\n\n\n\n\n## Stages\nStages offer a view on a set of composed layers. We cover [composition](../composition/overview.md) in its on section, as it is a complicated topic. \n\n```mermaid\nflowchart LR\n    stage(Stage) --> layerRoot(Root Layer)\n    layerRoot -- Sublayer --> layer1([Layer])\n    layer1 -- Payload --> layer1Layer1([Layer])\n    layer1 -- Sublayer--> layer1Layer2([Layer])\n    layerRoot -- Sublayer --> layer2([Layer])\n    layer2 -- Reference --> layer2Layer1([Layer])\n    layer2Layer1 -- Payload --> layer2Layer1Layer1([Layer])\n    layer2 -- Payload --> layer2Layer2([Layer])\n    layerRoot -- Composition Arc --> layer3([...])\n    layer3 -- Composition Arc --> layer3Layer1([...])\n```\n\nUnlike layers, stages are not managed via a singleton. There is the [Usd.StageCache](https://openusd.org/dev/api/class_usd_stage_cache.html) class though, that would provide a similar mechanism. We usually don't use this though, as our DCCs manage the lifetime cycle of our stages.\n\nIf a stage goes out of scope in our code, it will be deleted. Should we still have access the to Python object, we can check if it actually points to a valid layer via the `stage.expired` property.\n\nWhen creating a stage we have two layers by default:\n- **Session Layer**: This is a temp layer that doesn't get applied on disk save. Here we usually put things like viewport overrides.\n- **Root Layer**: This is the base layer all edits target by default. We can add sublayers based on what we need to it. When calling `stage.Save()`, all sublayers that are dirty and not anonymous, will be saved. \n\n\n### Configuration <a name=\"stageConfiguration\"></a>\nLet's first look at some configuration related options we can set on the stage.\n\n#### Asset Resolver  <a name=\"stageAssetResolver\"></a>\nThe stage can be opened with a [asset resolver context](../plugins/assetresolver.md#assetResolverContext). The context needs to be passed in on stage open, it can be refreshed afterwards (if implemented in the resolver). The resolver context object itself is bound to the runtime of the the stage though. The asset resolver context is just a very simple class, that our custom asset resolver can attach data to to help with path resolution.\n \nIn terms of asset resolution there are only two methods exposed on the stage class:\n- `stage.GetPathResolverContext()`: Get the resolver context object.\n- `stage.ResolveIdentifierToEditTarget()`: Resolve an asset identifier using the stage's resolver context.\n\nWe cover how to use these in our [asset resolver](../plugins/assetresolver.md) section, where we also showcase asset resolver reference implementations that ship with this guide.\n\n#### Stage Metrics  <a name=\"stageMetrics\"></a>\nAs discussed in the above [layer metrics section](#layerMetrics), we can set animation/time related metrics. The stage class also exposes methods to do this, which just set the metadata entries on the root layer of the stage.\n\nThe time related metrics should be written into all layers, as we can then use them to quickly inspect time related data in the file without having to fully parse it.\n\nWe cover it in detail our [Animation (Time related metrics)](./animation.md#animationMetadata), [Scene Unit Scale/UpAxis - FAQ](../../production/faq.md) and [Metadata](./metadata.md#metadataMetricsLayer) sections.\n\n#### Stage Time Sample Interpolation <a name=\"stageTimeSampleInterpolation\"></a>\nWe can set how time samples are interplated per stage.\n\nThe possible stage interpolation types are:\n- Usd.InterpolationTypeLinear: Interpolate linearly (if array length doesn't change and data type allows it))\n- Usd.InterpolationTypeHeld: Hold until the next time sample\n\n~~~admonish tip title=\"\"\n```python\nfrom pxr import Usd\nstage = Usd.Stage.CreateInMemory()\nprint(stage.GetInterpolationType()) # Returns: Usd.InterpolationTypeLinear\nstage.SetInterpolationType(Usd.InterpolationTypeHeld)\n```\n~~~\n\nCheckout our [animation section](./animation.md) for more info on how animation and time samples are treated in USD.\n\n#### Variant/Prim Type Fallbacks <a name=\"stageFallbacks\"></a>\nWe can also provide fallback values for:\n- [Variant selections](https://openusd.org/release/api/class_usd_stage.html#a34d1d78fe8e31f0ba439d2265d694af5): If no explicit variant selection is written, we can define a default fallback.\n- [Concrete typed prims](./schemas.md#summary): If a prim definition is not found, we can provide a fallback to be used instead. See the [official docs](https://openusd.org/release/api/_usd__page__object_model.html#Usd_OM_FallbackPrimTypes) for more info.\n\n#### Color Management <a name=\"stageColormanagement\"></a>\n~~~admonish question title=\"Still under construction!\"\nThis sub-section is still under development, it is subject to change and needs extra validation.\n~~~\n\n~~~admonish tip title=\"\"\n```python\n# Get: 'GetColorConfiguration', 'GetColorManagementSystem', 'GetColorConfigFallbacks'\n# Set: 'SetColorConfiguration', 'SetColorManagementSystem', 'SetColorConfigFallbacks'\n```\n~~~\n\n#### Default Render Settings <a name=\"stageRenderSettingsDefault\"></a>\n\nWe can supply a render settings prim path on our root layer that can be used as a default by applications.\n\nSee our [Metadata](./metadata.md#metadataRenderSettingsPrimPath) section for more information.\n\n\n#### Metadata <a name=\"stageMetadata\"></a>\nSetting metadata on the stage, redirects the edits to the root layer.\nWe discuss this in detail in our [metadata section](./metadata.md).\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:stageMetadata}}\n```\n~~~\n\n### Composition <a name=\"stageComposition\"></a>\nWe cover in detail how to inspect composition in our [composition section](../composition/overview.md).\n\nStages offer access to the [Prim Cache Population](../composition/pcp.md) cache via `stage._GetPcpCache()`. We almost never interact with it this way, instead we use the methods dicussed in our [inspecting composition](../composition/pcp.md) section.\n\nWe also have access to our instanced prototypes, for more info on what these are and how they can be inspected/used see our [composition instanceable prims](../composition/livrps.md#compositionInstance) section. \n\nLastly we control the edit target via the stage. The edit target defines, what layer all calls in the high level API should write to.\n\nWhen starting out with USD, you'll mostly be using it in the form of:\n\n~~~admonish tip title=\"\"\n```python\nstage.SetEditTarget(layer)\n# We can also explicitly create the edit target:\n# Or\nstage.SetEditTarget(Usd.EditTarget(layer))\n# Or\nstage.SetEditTarget(stage.GetEditTargetForLocalLayer(layer))\n# These all have the same effect.\n```\n~~~\n\nIn Houdini we don't have to manage this, it is always the highest layer in the active layer stack. Houdini gives it to us via `hou.node.activeLayer()` or `node.editableLayer`in python LOP nodes.\n\nMore info about edit targets in our [composition fundamentals](../composition/fundamentals.md) section.\n\n### Loading mechanisms <a name=\"stageLoadingMechanisms\"></a>\nStages are the controller of how our [Prim Cache Population (PCP)](../composition/pcp.md) cache loads our composed layers. We cover this in detail in our [Traversing/Loading Data](./loading_mechanisms.md) section. Technically the stage just exposes the PCP cache in a nice API, that forwards its requests to its PCP cache `stage._GetPcpCache()`, similar how all `Usd` ops are wrappers around `Sdf` calls.\n\nStages control:\n- **Layer Muting**: This controls what layers are allowd to contribute to the composition result.\n- **Prim Population Mask**: This controls what prim paths to consider for loading at all.\n- **Payload Loading**: This controls what prim paths, that have payloads, to load.\n\n### Stage Layer Management (Creation/Save/Export) <a name=\"stageLayerManagement\"></a>\nWhen creating a stage we have two layers by default:\n- **Session Layer**: This is a temp layer that doesn't get applied on disk save. Here we usually put things like viewport overrides.\n- **Root Layer**: This is the base layer all edits target by default. We can add sublayers based on what we need to it. When calling `stage.Save()`, all sublayers that are dirty and not anonymous, will be saved. \n\nLet's first look at layer access, there are two methods of special interest to us:\n- `stage.GetLayerStack()`: Get all the layers in the active [layer stack](../composition/fundamentals.md#layerStack)\n- `stage.GetUsedLayers(includeClipLayers=True)`: Get all layers that are currently used by the stage. We can optionally exclude value clip layers. This is only a snapshot, as layers might be \"varianted\" away or in the case of value clips, we only get the active chunk file.\n\nThe following example is run in Houdini:\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:stageLayerStackUsedLayers}}\n```\n~~~\n\nAs you might have noticed, when calling `stage.GetLayerStack()`, we didn't get the pig reference. Let's have a look how we can get all composition arc layers of the active layer stack:\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:stageLayerStackUsedLayers}}\n```\n~~~\n\nIf you are confused what a layer stack, check out our composition [layer stack](../composition/fundamentals.md#layerStack) section for a detailed breakdown.\n\nLet's have a look at stage creation and export:\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:stageLayerManagement}}\n```\n~~~\n\n### Traversal and Prim/Property Access <a name=\"stageTraversal\"></a>\nUSD stage traversing and accessing prims/properties works via the high level API.\n- The `stage.Get<SpecType>AtPath` methods return `Usd.Object` objects (`Usd.Prim`, `Usd.Attribute`, `Usd.Relationship`).\n- The traverse method returns an iterable that goes through the prims in the stage.\n\nWe cover stage traversals in full detail in our [Traversing/Loading Data (Purpose/Visibility/Activation/Population)\n](./loading_mechanims) section.\n\nHere are the basics:\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:stageTraversal}}\n```\n~~~"
  },
  {
    "path": "docs/src/pages/core/elements/loading_mechanisms.md",
    "content": "# Loading & Traversing Data\n\n# Table of Contents\n1. [Traversing & Loading Data In-A-Nutshell](#summary)\n1. [What should I use it for?](#usage)\n1. [Resources](#resources)\n1. [Overview](#overview)\n1. [Loading Mechanisms](#loadingMechanisms)\n    1. [Layer Muting](#loadingMechanismsLayerMuting)\n    1. [Prim Path Loading (USD speak: Prim Population Mask)](#loadingMechanismsLayerPrimPopulationMask)\n    1. [Payload Loading](#loadingMechanismsLayerPayloadLoading)\n    1. [GeomModelAPI->Draw Mode](#loadingMechanismsGeomModelAPIDrawMode)\n1. [Traversing Data](#traverseData)\n    1. [Traversing Stages](#traverseDataStage)\n    1. [Traversing Layers](#traverseDataLayer)\n    1. [Traverse Sample Data/Profiling](#traverseDataProfiling)\n\n## TL;DR - Loading & Traversing Data In-A-Nutshell <a name=\"summary\"></a>\n#### Loading Mechanisms\nWhen loading large scenes, we can selectively disabling loading via the following loading mechanisms:\nThere are three ways to influence the data load, from lowest to highest granularity .\n- **Layer Muting**: This controls what layers are allowed to contribute to the composition result.\n- **Prim Population Mask**: This controls what prim paths to consider for loading at all.\n- **Payload Loading**: This controls what prim paths, that have payloads, to load.\n- **GeomModelAPI->Draw Mode**: This controls per prim how it should be drawn by delegates. It can be one of \"Full Geometry\"/\"Origin Axes\"/\"Bounding Box\"/\"Texture Cards\". It requires the kind to be set on the prim and all its ancestors. Therefore it is \"limited\" to (asset-) root prims and ancestors.\n- **Activation**: Control per prim whether load itself and its child hierarchy. This is more an artist facing mechanism, as we end up writing the data to the stage, which we don't do with the other methods.\n\n#### Traversing/Iterating over our stage/layer\nTo inspect our stage, we can iterate (traverse) over it:\n\nWhen traversing, we try to pre-filter our prims as much as we can, via our prim metadata and USD core features(metadata), before inspecting their properties. This keeps our traversals fast even with hierarchies with millions of prims. We recommend first filtering based on metadata, as this is a lot faster than trying to access attributes and their values.\n\nWe also have a thing called [predicate](https://openusd.org/dev/api/prim_flags_8h.html#Usd_PrimFlags), which just defines what core metadata to consult for pre-filtering the result.\n\nAnother important feature is stopping traversal into child hierarchies. This can be done by calling `ìterator.PruneChildren()\n\n~~~admonish tip title=\"Stage/Prim Traversal\"\n```python\n{{#include ../../../../../code/core/elements.py:traverseDataStageTemplate}}\n```\n~~~\n\nLayer traversal is a bit different. Instead of iterating, we provide a function, that gets called with each `Sdf.Path` representable object in the active layer. So we also see all properties, relationship targets and variants.\n\n~~~admonish tip title=\"Layer Traversal\"\n```python\n{{#include ../../../../../code/core/elements.py:traverseDataLayerTemplate}}\n```\n~~~\n\n## What should I use it for? <a name=\"usage\"></a>\n~~~admonish tip\nWe'll be using loading mechanisms to optimize loading only what is relevant for the current task at hand.\n~~~\n\n## Resources <a name=\"resources\"></a>\n- [Prim Cache Population (Pcp)](https://openusd.org/dev/api/pcp_page_front.html)\n- [Stage Payload Loading](https://openusd.org/dev/api/class_usd_stage.html#Usd_workingSetManagement)\n- [Pcp.Cache](https://openusd.org/dev/api/class_pcp_cache.html)\n- [Usd.StagePopulationMask](https://openusd.org/dev/api/class_usd_stage_population_mask.html)\n- [Usd.StageLoadRules](https://openusd.org/dev/api/class_usd_stage_load_rules.html)\n\n## Loading Mechanisms <a name=\"loadingMechanisms\"></a>\nLet's look at load mechanisms that USD offers to make the loading of our hierarchies faster.\n\nBefore we proceed, it is important to note, that USD is highly performant in loading hierarchies. When USD loads .usd/.usdc binary crate files, it sparsely loads the content: It can read in the hierarchy without loading in the attributes. This allows it to, instead of loading terabytes of data, to only read the important bits in the file and lazy load on demand the heavy data when requested by API queries or a hydra delegate. \n\nWhen loading stages/layers per code only, we often therefore don't need to resort to using these mechanisms.\n\nThere are three ways to influence the data load, from lowest to highest granularity .\n- **Layer Muting**: This controls what layers are allowed to contribute to the composition result.\n- **Prim Population Mask**: This controls what prim paths to consider for loading at all.\n- **Payload Loading**: This controls what prim paths, that have payloads, to load.\n- **GeomModelAPI->Draw Mode**: This controls per prim how it should be drawn by delegates. It can be one of \"Full Geometry\"/\"Origin Axes\"/\"Bounding Box\"/\"Texture Cards\". It requires the kind to be set on the prim and all its ancestors. Therefore it is \"limited\" to (asset-) root prims and ancestors.\n- **Activation**: Control per prim whether load itself and its child hierarchy. This is more an artist facing mechanism, as we end up writing the data to the stage, which we don't do with the other methods.\n\nStages are the controller of how our [Prim Cache Population (PCP)](../composition/pcp.md) cache loads our composed layers. Technically the stage just exposes the PCP cache in a nice API, that forwards its requests to its PCP cache `stage._GetPcpCache()`, similar how all `Usd` ops are wrappers around `Sdf` calls.\n\n\nHoudini exposes all three in two different ways:\n- **Configue Stage** LOP node: This is the same as setting it per code via the stage.\n- **Scene Graph Tree** panel: In Houdini, that stage that gets rendered, is actually not the stage of your node (at least what we gather from reverse engineering). Instead it is a duplicate, that has overrides in the session layer and loading mechanisms listed above.\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/core/elements/houdiniLoadingMechanisms.mp4\" type=\"video/mp4\" alt=\"Houdini Configure Stage Node\">\n</video>\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/core/elements/houdiniSceneGraphTreePanel.mp4\" type=\"video/mp4\" alt=\"Houdini Scene Graph Tree Panel\">\n</video>\n\nMore Houdini specific information can be found in our [Houdini - Performance Optimizations](../../dcc/houdini/performance/overview.md#loadingMechanisms) section.\n\n### Layer Muting <a name=\"loadingMechanismsLayerMuting\"></a>\nWe can \"mute\" (disable) layers either globally or per stage.\n\nGlobally muting layers is done via the singleton, this mutes it on all stages that use the layer.\n~~~admonish tip title=\"\"\n```python\nfrom pxr import Sdf\nlayer = Sdf.Layer.FindOrOpen(\"/my/layer/identifier\")\nSdf.Layer.AddToMutedLayers(layer.identifier)\nSdf.Layer.RemoveFromMutedLayers(layer.identifier)\n```\n~~~\n\nMuting layers per stage is done via the `Usd.Stage` object, all function signatures work with the layer identifier string. If the layer is muted globally, the stage will not override the muting and it stays muted.\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:loadingMechanismsLayerMuting}}\n```\n~~~\n\n~~~admonish tip title=\"Pro Tip | Layer Muting\"\nWe use layer muting in production for two things:\n- Artists can opt-in to load layers that are relevant to them. For example in a shot, a animator doesn't have to load the background set or fx layers.\n- Pipeline-wise we have to ensure that artists add shot layers in a specific order (For example: lighting > fx > animation > layout >). Let's say a layout artist is working in a shot, we only want to display the layout and camera layers. All the other layers can (should) be muted, because A. performance, B. there might be edits in higher layers, that the layout artist is not interested in seeing yet. If we were to display them, some of these edits might block ours, because they are higher in the layer stack.\n~~~\n\nHere is an example of global layer muting:\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/core/elements/layerMutingGlobal.mp4\" type=\"video/mp4\" alt=\"Houdini Layer Muting Global\">\n</video>\n\nWe have to re-cook the node for it to take effect, due to how Houdini caches stages.\n\n### Prim Path Loading Mask (USD speak: Prim Population Mask) <a name=\"loadingMechanismsLayerPrimPopulationMask\"></a>\n\n~~~admonish tip title=\"Pro Tip | Prim Population Mask\"\nSimilar to prim activation, the prim population mask controls what prims (and their child prims) are even considered for being loaded into the stage. Unlike activation, the prim population mask does not get stored in a USD layer. It is therefore a pre-filtering mechanism, rather than an artist facing \"what do I want to hide from my scene\" mechanism.\n~~~\n\nOne difference to activation is that not only the child hierarchy is stripped away for traversing, but also the prim itself, if it is not included in the mask.\n\nThe population mask is managed via the `Usd.StagePopulationMask` class.\n\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:loadingMechanismsLayerPrimPopulationMask}}\n```\n~~~\n\nWhat's also really cool, is that we can populate the mask by relationships/attribute connections.\n\n~~~admonish tip title=\"\"\n```python\nstage.ExpandPopulationMask(relationshipPredicate=lambda r: r.GetName() == 'material:binding',\n                           attributePredicate=lambda a: False)\n```\n~~~\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/core/elements/houdiniPopulationMaskExpand.mp4\" type=\"video/mp4\" alt=\"Houdini Population Mask Expand\">\n</video>\n\n### Payload Loading <a name=\"loadingMechanismsLayerPayloadLoading\"></a>\n~~~admonish tip title=\"Pro Tip | Payload Loading\"\nPayloads are USD's mechanism of disabling the load of heavy data and instead leaving us with a bounding box representation (or texture card representation, if you set it up). We can configure our stages to not load payloads at all or to only load payloads at specific prims.\n~~~\n\nWhat might be confusing here is the naming convention: USD refers to this as \"loading\", which sounds pretty generic. Whenever we are looking at stages and talking about loading, know that we are talking about payloads.\n\nYou can find more details in the [API docs](https://openusd.org/dev/api/class_usd_stage.html#Usd_workingSetManagement).\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:loadingMechanismsLayerPayloadLoading}}\n```\n~~~\n\n### GeomModelAPI->Draw Mode <a name=\"loadingMechanismsGeomModelAPIDrawMode\"></a>\n~~~admonish tip title=\"Pro Tip | Draw Mode\"\nThe draw mode can be used to tell our Hydra render delegates to not render a prim and its child hierarchy. Instead it will only display a preview representation.\n\nThe preview representation can be one of:\n- Full Geometry\n- Origin Axes\n- Bounding Box\n- Texture Cards\n\nLike visibility, the draw mode is inherited downwards to its child prims. We can also set a draw mode color, to better differentiate the non full geometry draw modes, this is not inherited though and must be set per prim.\n~~~\n\n~~~admonish danger title=\"Important | Draw Mode Requires Kind\"\nIn order for the draw mode to work, the prim and all its ancestors, must have a [kind](../plugins/kind.md) defined. Therefore it is \"limited\" to (asset-)root prims and its ancestors.\nSee the [official docs](https://openusd.org/dev/api/class_usd_geom_model_a_p_i.html) for more info.\n~~~\n\nHere is how we can set it via Python, it is part of the `UsdGeomModelAPI`:\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:loadingMechanismsGeomModelAPIDrawMode}}\n```\n~~~\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/core/elements/houdiniLoadingMechanismsDrawMode.mp4\" type=\"video/mp4\" alt=\"Houdini Draw Mode\">\n</video>\n\n\n## Traversing Data <a name=\"traverseData\"></a>\nWhen traversing (iterating) through our hierarchy, we commonly use these metadata and property entries on prims to pre-filter what we want to access:\n- .IsA Typed Schemas (Metadata)\n- Type Name (Metadata)\n- Specifier (Metadata)\n- Activation (Metadata)\n- Kind (Metadata)\n- Purpose (Attribute)\n- Visibility (Attribute)\n\n~~~admonish tip title=\"Pro Tip | High Performance Traversals\"\nWhen traversing, using the above \"filters\" to narrow down your selection well help keep your traversals fast, even with hierarchies with millions of prims. We recommend first filtering based on metadata, as this is a lot faster than trying to access attributes and their values.\n\nAnother important feature is stopping traversal into child hierarchies. This can be done by calling `ìterator.PruneChildren()`:\n```python\nfrom pxr import Sdf, UsdShade\nroot_prim = stage.GetPseudoRoot()\n# We have to cast it as an iterator to gain access to the .PruneChildren() method.\niterator = iter(Usd.PrimRange(root_prim))\nfor prim in iterator:\n    if prim.IsA(UsdShade.Material):\n        # Don't traverse into the shader network prims\n        iterator.PruneChildren()\n```\n~~~\n\n### Traversing Stages <a name=\"traverseDataStage\"></a>\nTraversing stages works via the `Usd.PrimRange` class. The `stage.Traverse`/`stage.TraverseAll`/`prim.GetFilteredChildren` methods all use this as the base class, so let's checkout how it works:\n\nWe have two traversal modes:\n- Default: Iterate over child prims\n- PreAndPostVisit: Iterate over the hierarchy and visit each prim twice, once when first encountering it, and then again when \"exiting\" the child hierarchy. See our [primvars query](../../production/caches/attribute.md#primvars) section for a hands-on example why this can be useful.\n\nWe also have a thing called \"predicate\"([Predicate Overview](https://openusd.org/dev/api/prim_flags_8h.html#Usd_PrimFlags)), which just defines what core metadata to consult for pre-filtering the result:\n- Usd.PrimIsActive: Usd.Prim.IsActive() - If the \"active\" metadata is True\n- Usd.PrimIsLoaded: Usd.Prim.IsLoaded() - If the (ancestor) payload is loaded\n- Usd.PrimIsModel: Usd.Prim.IsModel() - If the kind is a sub kind of `Kind.Tokens.model`\n- Usd.PrimIsGroup: Usd.Prim.IsGroup() - If the kind is `Kind.Tokens.group`\n- Usd.PrimIsAbstract: Usd.Prim.IsAbstract() - If the prim specifier is `Sdf.SpecifierClass`\n- Usd.PrimIsDefined: Usd.Prim.IsDefined() - If the prim specifier is `Sdf.SpecifierDef`\n- Usd.PrimIsInstance: Usd.Prim.IsInstance() - If prim is an instance root (This is false for prims in instances)\n\nPresets:\n- Usd.PrimDefaultPredicate: `Usd.PrimIsActive & Usd.PrimIsDefined & Usd.PrimIsLoaded & ~Usd.PrimIsAbstract`\n- Usd.PrimAllPrimsPredicate: Shortcut for selecting all filters (basically ignoring the prefilter).\n\nBy default the Usd.PrimDefaultPredicate is used, if we don't specify one.\n\n~~~admonish tip title=\"Pro Tip | Usd Prim Range\"\nHere is the most common syntax you'll be using:\n```python\n{{#include ../../../../../code/core/elements.py:traverseDataStageTemplate}}\n```\n~~~\n\nThe default traversal also doesn't go into [instanceable prims](../composition/livrps.md#compositionInstance).\nTo enable it we can either run `pxr.Usd.TraverseInstanceProxies(<existingPredicate>)` or `predicate.TraverseInstanceProxies(True)`\n\nWithin instances we can get the prototype as follows, for more info see our [instanceable section](../composition/livrps.md#compositionInstance):\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/composition.py:compositionInstanceable}}\n```\n~~~\n\nLet's look at some traversal examples:\n\n~~~admonish tip title=\"Stage/Prim Traversal | Click to expand\" collapsible=true\n```python\n{{#include ../../../../../code/core/elements.py:traverseDataStage}}\n```\n~~~\n\n### Traversing Layers <a name=\"traverseDataLayer\"></a>\nLayer traversal is different, it only looks at the active layer and traverses everything that is representable via an `Sdf.Path` object.\nThis means, it ignores activation and it traverses into variants and relationship targets. This can be quite useful, when we need to rename something or check for data in the active layer.\n\nWe cover it in detail with examples over in our [layer and stages](./layer.md#layerTravesal) section.\n\n~~~admonish tip title=\"Pro Tip | Layer Traverse\"\nThe traversal for layers works differently. Instead of an iterator, we have to provide a\n\"kernel\" like function, that gets an `Sdf.Path` as an input.\nHere is the most common syntax you'll be using:\n```python\n{{#include ../../../../../code/core/elements.py:traverseDataLayerTemplate}}\n```\n~~~\n\n### Traverse Sample Data/Profiling <a name=\"traverseDataProfiling\"></a>\nTo test profiling, we can setup a example hierarchy. The below code spawns a nested prim hierarchy.\nYou can adjust the `create_hierarchy(layer, prim_path, <level>)`, be aware this is exponential, so a value of 10 and higher will already generate huge hierarchies.\n\nThe output will be something like this:\n\n![Houdini Traversal Profiling Hierarchy](../../../media/core/composition/traversalProfilingHierarchy.jpg)\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:traverseSampleData}}\n```\n~~~\n\nHere is how we can run profiling (this is kept very simple, check out our [profiling](../profiling/overview.md) section how to properly trace the stats) on the sample data:\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:traverseSampleDataProfiling}}\n```\n~~~\n\nHere is a sample output, we recommend running each traversal multiple times and then averaging the results.\nAs we can see running attribute checks against attributes can be twice as expensive than checking metadata or the type name. (Surprisingly kind checks take a long time, even though it is also a metadata check) \n~~~admonish tip title=\"\"\n```python\n0.17678 Seconds | IsA(Boundable) | Match 38166\n0.17222 Seconds | GetTypeName | Match 44294\n0.42160 Seconds | Kind | Match 93298\n0.38575 Seconds | IsLeaf AssetInfo  | Match 44294\n0.27142 Seconds | IsLeaf Attribute Has | Match 44294\n0.38036 Seconds | IsLeaf Attribute  | Match 44294\n0.37459 Seconds | IsLeaf Attribute (Validation) | Match 44294\n```\n~~~\n\n"
  },
  {
    "path": "docs/src/pages/core/elements/materials.md",
    "content": "# Materials\nMaterials in USD are exposed via the [UsdShade](https://openusd.org/dev/api/usd_shade_page_front.html) module.\n\nShader networks are encoded via the [UsdShade.ConnectableAPI](https://openusd.org/dev/api/class_usd_shade_connectable_a_p_i.html). So we have full access to the node graph as it is fully represented as USD prims. This allows for flexible editing, as it is as simple as editing attributes and connections on your individual material node prims.\n\nUSD has support for encoding [MaterialX](https://materialx.org/) node graphs, which allows for render engine agnostic shader creation.\n\n# Table of Contents\n1. [Materials In-A-Nutshell](#summary)\n1. [What should I use it for?](#usage)\n1. [Resources](#resources)\n1. [Overview](#overview)\n    1. [Material Binding](#materialBinding)\n    1. [Node graph encoding via attribute to attribute connections](#materialNodeGraph)\n\n## TL;DR - Metadata In-A-Nutshell <a name=\"summary\"></a>\n- USD can encode material node graphs as prims. It supports writing [MaterialX](https://materialx.org/) node graphs, which are renderer agnostic material descriptions.\n- We can bind materials either directly or via [collections](./collection.md).\n\n## What should I use it for? <a name=\"usage\"></a>\n~~~admonish tip\nMaterials themselves are usually generated by the DCC you are working in, so we usually don't have to create them ourselves. What we do use the `UsdShade` module for is editing material bindings and overriding individual nodes and their connections in a material node graph.\n~~~\n\n## Resources <a name=\"resources\"></a>\n- [UsdShade](https://openusd.org/dev/api/usd_shade_page_front.html)\n- [UsdShade.Material](https://openusd.org/dev/api/class_usd_shade_material.html)\n- [UsdShade.MaterialBindingAPI](https://openusd.org/dev/api/class_usd_shade_material_binding_a_p_i.html)\n- [UsdShade.ConnectableAPI](https://openusd.org/dev/api/class_usd_shade_connectable_a_p_i.html)\n\n## Overview <a name=\"overview\"></a>\n~~~admonish question title=\"Still under construction!\"\nThis section still needs some more love, we'll likely expand it more in the near future.\n~~~\n\n### Material binding <a name=\"materialBinding\">\nOne of the most common use cases of relationships is encoding the material binding. Here we simply link from any imageable (renderable) prim to a `UsdShade.Material` (`Material`) prim.\n\n~~~admonish important\nMaterial bindings are a special kind of relationship. Here are a few important things to know:\n- When looking up material bindings, USD also looks at parent prims if it can't find a written binding on the prim directly. This means you can create the binding on any parent prim and just as with primvars, it will be inherited downwards to its children.\n- The \"binding strength\" can be adjusted, so that a child prim assignment can also be override from a binding higher up the hierarchy.\n- Material bindings can also be written per purpose, if not then they bind to all purposes. (Technically it is not called purpose, the token names are `UsdShade.MaterialBindingAPI.GetMaterialPurposes() -> ['', 'preview', 'full']`). The 'preview' is usually bound to the 'UsdGeom.Tokens.proxy' purpose, the 'full' to the 'UsdGeom.Tokens.render' purpose.\n- The material binding can be written in two ways:\n    - Direct Binding: A relationship that points directly to a material prim\n    - Collection Based Binding: A relationship that points to another collection, that then stores the actual binding paths) and to a material prim to bind.\n~~~\n\nHere is an example of a direct binding:\n```python\nover \"asset\"\n{\n    over \"GEO\"(\n        prepend apiSchemas = [\"MaterialBindingAPI\"]\n    )\n    {\n        rel material:binding = </materials/metal>\n        over \"plastic_mesh\" (\n            prepend apiSchemas = [\"MaterialBindingAPI\"]\n        )\n        {\n            rel material:binding = </asset/materials/plastic>\n        }\n    }\n}\n```\n\nAnd here is an example of a collection based binding. As you can see it is very easy to exclude a certain prim from a single control point, whereas with the direct binding we have to author it on the prim itself.\n```python\ndef \"asset\" (\n    prepend apiSchemas = [\"MaterialBindingAPI\", \"CollectionAPI:material_metal\"]\n)\n{\n    rel material:binding:collection:material_metal = [\n        </shaderball.collection:material_metal>,\n        </materials/metal>,\n    ]\n\n    uniform token collection:material_metal:expansionRule = \"expandPrims\"\n    rel collection:material_metal:includes = </asset>\n    rel collection:material_metal:excludes = </asset/GEO/plastic_mesh>\n}\n```\n\nFor creating bindings in the high level API, we use the `UsdShade.MaterialBindingAPI` schema.\nHere is the link to the official [API docs](https://openusd.org/dev/api/class_usd_shade_material_binding_a_p_i.html).\n\nFor more info about the load order (how collection based bindings win over direct bindings), you can read the \"Bound Material Resolution\" section on the API docs page.\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:relationshipMaterialBinding}}\n```\n~~~\n\n\n### Node graph encoding via attribute to attribute connections <a name=\"materialNodeGraph\"></a>\nAttributes can also encode relationship-like paths to other attributes. These connections are encoded directly on the attribute. It is up to Usd/Hydra to evaluate these \"attribute graphs\", if you simply connect two attributes, it will not forward attribute value A to connected attribute B (USD does not have a concept for a mechanism like that (yet)).\n\nHere is an example of how a material network is encoded.\n\n~~~admonish important title=\"\"\n```python\ndef Scope \"materials\"\n{\n    def Material \"karmamtlxsubnet\" (\n    )\n    {\n        token outputs:mtlx:surface.connect = </materials/karmamtlxsubnet/mtlxsurface.outputs:out>\n\n        def Shader \"mtlxsurface\" ()\n        {\n            uniform token info:id = \"ND_surface\"\n            string inputs:edf.connect = </materials/karmamtlxsubnet/mtlxuniform_edf.outputs:out>\n            token outputs:out\n        }\n\n        def Shader \"mtlxuniform_edf\"\n        {\n            uniform token info:id = \"ND_uniform_edf\"\n            color3f inputs:color.connect = </materials/karmamtlxsubnet/mtlx_constant.outputs:out>\n            token outputs:out\n        }\n\n        def Shader \"mtlx_constant\"\n        {\n            uniform token info:id = \"ND_constant_float\"\n            float outputs:out\n        }\n    }\n}\n```\n~~~\n\nIn our [property](./property.md#attribute-to-attribute-connections-node-graph-encoding) section we cover the basics how to connect different attributes. For material node graphs USD ships with the [UsdShade.ConnectableAPI](https://openusd.org/dev/api/class_usd_shade_connectable_a_p_i.html). It should be used/preferred instead of using the `Usd.Attribute.AddConnection` method, as it does extra validation as well as offer convenience functions for iterating over connections.\n"
  },
  {
    "path": "docs/src/pages/core/elements/metadata.md",
    "content": "# Metadata\nMetadata is the smallest building block in Usd. It is part of the base class from which prims and properties inherit from and possesses a slightly different feature set than other parts of Usd.\n\n# Table of Contents\n1. [API Overview In-A-Nutshell](#summary)\n1. [What should I use it for?](#usage)\n1. [Resources](#resources)\n1. [Overview](#overview)\n1. [Composition/Value resolution](#composition_value_resolution)\n1. [Working with metadata in your stages](#practicalExamples)\n    1. [Basics (High level API)](#metadataBasics)\n    1. [Validation of dict content](#metadataValidateDict)\n    1. [Nested key path syntax](#metadataNestedKeyPath)\n    1. [Creating custom metadata fields via plugins](#metadataPlugin)\n    1. [Reading metadata documentation strings (High level API)](#metadataDocs)\n    1. [Authored vs fallback metadata values (High level API)](#metadataAuthored)\n    1. [Reading/writing metadata via prim/property specs(Low level API)](#metadataPrimPropertySpec)\n    1. [Special metadata fields for prims](#metadataSpecialPrim)\n        1. [Active/Activation](#metadataActive)\n        1. [Asset Info](#metadataAssetInfo)\n        1. [Custom Data](#metadataCustomData) \n        1. [Comment](#metadataComment)\n        1. [Icon (UI)](#metadataIcon)\n        1. [Hidden (UI)](#metadataHidden)\n    1. [Special metadata fields for properties](#metadataSpecialProperty)\n        1. [Support for animation (USD speak **variability**)](#metadataVariability)\n        1. [Custom vs schema defined properties](#metadataCustom)\n    1. [Special metadata fields for layers and stages](#metadataLayerStage)\n        1. [Stage/Root Layer Default Render Settings (High/Low level API)](#metadataRenderSettingsPrimPath)\n        1. [Stage and layer metrics (FPS/Scene Unit Scale/Up Axis) (High/Low level API)](#metadataMetricsLayer)\n        1. [Stage and layer customData metadata (High/Low level API)](#metadataCustomDataLayer)\n\n\n## TL;DR - Metadata In-A-Nutshell <a name=\"summary\"></a>\n- Metadata attaches additional non-animatable data to prims/properties/layers via a dictionary\n- Composition arcs and core data (specifiers/type names) is added via metadata\n- `assetInfo` and `customData` are predefined keys for prim metadata you can track asset/custom data with\n- To write to other keys, they must be registered via schemas.\n\n## What should I use it for? <a name=\"usage\"></a>\n~~~admonish tip\nIn production, you'll use the `assetInfo`/`customData` prim metadata fields to track any production related data.\nYou can also use metadata to edit composition arcs, though the high level API offers nice class wrappers that wrap this for you.\n```python\n{{#include ../../../../../code/core/elements.py:metadataSummary}}\n```\n~~~\n\n## Resources <a name=\"resources\"></a>\n- [Metadata API Docs](https://openusd.org/release/api/_usd__page__object_model.html#Usd_OM_Metadata)\n- [Usd.Object](https://openusd.org/dev/api/class_usd_object.html)\n- [Sdf.Spec](https://openusd.org/dev/api/class_sdf_spec.html)\n\n## Overview <a name=\"overview\"></a>\n\nHere is the class structure for the different API levels:\n\nHigh Level API\n```mermaid\nflowchart TD\n    usdObject([\"Usd.Object (Includes Metadata API)\"]) --> usdPrim([Usd.Prim])\n    usdObject --> usdProperty([Usd.Property])\n    usdProperty --> usdAttribute([Usd.Attribute])\n    usdProperty --> usdRelationship([Usd.Relationship])\n    usdStage([\"Usd.Stage (Includes Metadata API)\"])\n```\n\nLow Level API\n```mermaid\nflowchart TD\n    sdfSpec([\"Sdf.Spec (Includes Metadata API)\"]) --> sdfPropertySpec([Sdf.Property])\n    sdfSpec --> sdfPrimSpec([Sdf.PrimSpec])\n    sdfSpec --> sdfVariantSetSpec([Sdf.VariantSetSpec])\n    sdfSpec --> sdfVariantSpec([Sdf.VariantSpec])\n    sdfPropertySpec --> sdfAttributeSpec([Sdf.AttributeSpec])\n    sdfPropertySpec --> sdfRelationshipSpec([Sdf.RelationshipSpec])\n    sdfLayer([\"Sdf.Layer (Includes Metadata API)\"])\n\n```\n\nMetadata is different in that it:\n- Is the smallest building block in Usd (There are no subclasses) and its data is stored as a dictionary.\n- Is extremely fast to access\n- Can't be time varying:\n    - Composition arcs are written into metadata fields on prims, so you can't animate composition.\n    - Metadata stored in value clip files is ignored\n- Is strongly typed via schemas, so you need to register a custom schema if you want custom keys. This way we can ensure fallback values/documentation per key/value and avoid random data flying through your pipelines. For example all your mesh attributes have metadata for exactly what type/role they must match.\n- There are two special metadata keys for prims:\n    - `assetInfo`: Here you should dump asset related data. This is just a predefined standardized location all vendors/companies should adhere to when writing asset data that should be tracked.\n    - `customData`: Here you can dump any data you want, a kind of scratch space, so you don't need to add your own schema. If you catch yourself misusing it too much, you should probably generate your own schema.\n\n\n~~~admonish tip\nWe go into more detail over in the [schema](./schemas.md) section on how to create or lookup registered schemas.\n~~~\n\n## Composition/Value resolution <a name=\"composition_value_resolution\"></a>\nMetadata is slightly different when it comes to value resolution. (As a reminder: `value resolution` is just a fancy word for \"what layer has the winning value out of all your layers where the data will be loaded from\"):\n- Nested dictionaries are combined\n- Attribute metadata behaves by the same rules as attribute value resolution\n- Core metadata (Metadata that affects composition/prim definitions):\n    - Composition metadata is composed via Listeditable-Ops. See our section [here](../composition/listeditableops.md) for more details. Be sure to understand these to save your self a lot of head-aches why composition works the way it does.\n    - Specific prim metadata has its own rule set (E.g. prim specifiers).\n\n\n## Working with metadata in your stages <a name=\"practicalExamples\"></a>\nLet's look at some actual code examples on how to modify metadata.\n\n### Basics (High level API) <a name=\"metadataBasics\"></a>\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:metadataBasics}}\n```\n~~~\n\n### Validation of dict content <a name=\"metadataBasics\"></a>\nTo create a valid metadata compatible dict, you can validate it:\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:metadataValidateDict}}\n```\n~~~\nThis is useful if you expose setting metadata to your user facing UIs. This will auto-cast Python arrays to VtArray and other Usd internal types. You can also skip this step, it might error later on when setting the data then though. \n\n### Nested key path syntax <a name=\"metadataBasics\"></a>\nTo access nested dict keys, we use the `:` symbol as the path separator.\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:metadataNestedKeyPath}}\n```\n~~~\n\nThe `Get`/`Set` methods without the `ByKey`/`ByDictKey` allow you to set root dict keys, e.g. `SetMetadata(\"typeName\", \"Xform\")`\nThe `ByKey`/`ByDictKey` take a root key and a key path (with `:` if nested), e.g. `SetMetadataByDictKey('assetInfo', \"data:version\", 1)` which will result in `{\"assetInfo\": {\"data\": \"version\": 1}}`\n\n### Creating custom metadata fields via plugins <a name=\"metadataPlugin\"></a>\nWe can easily extend metadata fields via plugins. We cover this in detail in out [metadata plugin](../plugins/metadata.md) section.\n\n### Reading metadata documentation strings (High level API) <a name=\"metadataDocs\"></a>\nThis is quite useful if you need to expose docs in UIs.\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:metadataDocs}}\n```\n~~~\n\n~~~admonish note title=\"Click here to view the result\" collapsible=true\n```python\n{{#include ../../../../../code/core/elements.py:metadataDocsResult}}\n```\n~~~\n\n### Authored vs fallback metadata values (High level API) <a name=\"metadataAuthored\"></a>\nThe getters offer the distinction between retrieving authored or fallback values provided by the schemas that registered the metadata.\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:metadataAuthored}}\n```\n~~~\n\n### Reading/writing metadata via prim/property specs(Low level API) <a name=\"metadataPrimPropertySpec\"></a>\nSame as with the layer customData, the lower level APIs on prim/property specs expose it to Python via lower camel case syntax in combination with direct assignment, instead of offer getter and setters.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:metadataPrimPropertySpec}}\n```\n~~~\nAs you can see the higher level API gives us fallback info via the Get(authored) methods. In the lower level API we have to process this data logic ourselves.\n\n\n### Special metadata fields for prims <a name=\"metadataSpecialPrim\"></a>\nHere are the most common prim metadata keys we'll be working with.\n\n\n#### Active/Activation <a name=\"metadataActive\"></a>\nThe `active` metadata controls if the prim and its children are loaded or not.\nWe only cover here how to set the metadata, for more info checkout our [Loading mechansims](./loading_mechanisms.md) section. Since it is a metadata entry, it can not be animated. For animated pruning we must use [visibility](./property.md#visibility).\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:metadataActive}}\n```\n~~~\n\n#### Asset Info <a name=\"metadataAssetInfo\"></a>\nThe `assetInfo` metadata carries asset related data. This is just a predefined standardized location all vendors/companies should adhere to when writing asset data that should be tracked.\n\nThere are currently four standardized keys:\n- `identifier` (Sdf.AssetPath): The asset identifier (that the [asset resolver](../plugins/assetresolver.md) can resolve)\n- `name` (str): The name of the asset.\n- `version` (str): The version of the asset.\n- `payloadAssetDependencies` (Sdf.AssetPathArray()): This is typically attached to the prim where you attach payloads to that when you unloaded payloads, you can still see what is in the file without traversing the actual layer content. It is up to you\nto manage the content of this list to be synced with the actual payload(s) content.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:metadataAssetInfo}}\n```\n~~~\n\n#### Custom Data <a name=\"metadataCustomData\"></a>\nThe `customData` field can be for any data you want, a kind of scratch space, so you don't need to add your own schema. If you catch yourself misusing it too much, you should probably generate your own schema.\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:metadataCustomData}}\n```\n~~~\n\n#### Comments <a name=\"metadataComment\"></a>\nThere is also a special key to track user comments:\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:metadataComment}}\n```\n~~~\n\n#### Icon (UI) <a name=\"metadataIcon\"></a>\nYou can also write an `icon` key into the `customData` dict, which UI applications can then optionally use to draw the prim icon with.\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:metadataComment}}\n```\n~~~\n\n#### Hidden (UI) <a name=\"metadataHidden\"></a>\nThere is also a special key `hidden` key that is a UI hint that can be used by applications to hide the prim in views. It is up to the application to implement.\n\nThis also exists for properties, but is not read by most UIs in apps/DCCs.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:metadataHidden}}\n```\n~~~\n\n### Special metadata fields for properties <a name=\"metadataSpecialProperty\"></a>\nSetting metadata works the same for properties, but they do have a different set of default core metadata.\nHere we cover the most important ones.\n \n#### Support for animation (USD speak **variability**) <a name=\"metadataVariability\"></a>\nThe term `variability` in USD just means if a property can have animation ([time samples](./animation.md)) or not. There are two values:\n- `Sdf.VariabilityUniform` (No animation/time samples)\n- `Sdf.VariabilityVarying` (Supports time samples)\n\n~~~admonish important\nThe variability actually only declares the intent of time capabilities of the property. You can still write time samples for uniform variability attributes, there are chances though that something else somewhere in the API/Hydra won't work then though. So as a best practice don't write animated attributes to `Sdf.VariabilityUniform` declared schema attributes. Relationships always have the `Sdf.VariabilityUniform` intent as they can't be animated.  \n~~~\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:metadataVariability}}\n```\n~~~\n\n#### Custom vs schema defined properties <a name=\"metadataCustom\"></a>\nAll properties that are not registered via a [schema](../elements/schemas.md) are marked as `custom`.\n\nThis is one of the examples where we can clearly see the benefit of the high level API:\nIt automatically checks if a property is in the assigned schemas and marks it as `custom` if necessary.\n\nWith the lower level API, we have to mark it ourselves.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:metadataCustom}}\n```\n~~~\n\n### Special metadata fields for layers and stages <a name=\"metadataLayerStage\"></a>\nFor stages (root layer/session layer) and layers, we can also write a few special fields as covered below.\n\n#### Stage/Root Layer Default Render Settings (High/Low level API) <a name=\"metadataRenderSettingsPrimPath\"></a>\n\nWe can supply a default render settings prim path on our root layer. This will be used in DCCs as the default render settings to drive Hydra rendering.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:metadataRenderSettingsPrimPath}}\n```\n~~~\n\nFor example in Houdini we can then see it marked with the \"Default\" prefix in our viewport display options.\n\n![Houdini Viewport Display Options - Default Render Settings](../../../media/core/elements/metadataRenderSettingsPrimPath.jpg)\n\n\n#### Stage and layer metrics (FPS/Scene Unit Scale/Up Axis) (High/Low level API) <a name=\"metadataMetricsLayer\"></a>\n\nFor more info about the FPS, see our [animation](./animation.md#frames-per-second) section.\n\nWe can supply an up axis and scene scale hint in the layer metadata, but this does not seem to be used by most DCCs or in fact Hydra itself when rendering the geo. So if you have a mixed values, you'll have to counter correct via transforms yourself.\n\nThe default scene `metersPerUnit` value is centimeters (0.01) and the default `upAxis` is `Y`.\n\nSee [Scene Up Axis API Docs](https://openusd.org/dev/api/group___usd_geom_up_axis__group.html) and [Scene Unit API Docs](https://openusd.org/dev/api/group___usd_geom_linear_units__group.html) for more info.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:metadataLayerMetrics}}\n```\n~~~\n\n#### Stage and layer customData metadata (High/Low level API) <a name=\"metadataCustomDataLayer\"></a>\n~~~admonish tip\nThis is often used to track pipeline relevant data in DCCs. For node based DCCs, this is a convenient way to pass general data down through the node network. For layer based DCCs, this can be used to tag layers (for example to anonymous layers that carry specific pipeline data).\n~~~\n\nLayer metadata, like some other classes in the low level API, uses the lower camel case syntax in combination with direct assignment, instead of offer getter and setters. Here we can just use the standard Python dict methods. \n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:metadataLayer}}\n```\n~~~\n\n~~~admonish danger\nAs we are operating on the layer (lower level API), we do not see any composed metadata and instead only the data in the layer we are looking at. The `Usd.Stage` class also offers the metadata methods, it follows a different logic though:\nIt writes the metadata to the session or root layer. So you won't see any composed metadata of individual layers, only those of the session/root layer (depending on the edit target according to the [docs](https://openusd.org/release/api/class_usd_stage.html#ad2d76f736733f3ad51aa1ea1df6f4d44)\n~~~\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:metadataStage}}\n```\n~~~\n"
  },
  {
    "path": "docs/src/pages/core/elements/notice.md",
    "content": "# Notices/Event Listeners\nUsd's event system is exposed via the [Notice](https://openusd.org/dev/api/group__group__tf___notification.html) class. It can be used to subscribe to different stage events or custom events to get notified about changes. \n\nA common case for using it with Python is sending update notifications to UIs.\n\n## TL;DR - Notice/Event Listeners In-A-Nutshell\n- The event system is uni-directional: The listeners subscribe to senders, but can't send information back to the senders. The senders are also not aware of the listeners, senders just send the event and the event system distributes it to the senders.\n- The listeners are called synchronously in a random order (per thread where the listener was created), so make sure your listeners action is fast or forwards its execution into a separate thread. \n\n## What should I use it for? <a name=\"usage\"></a>\n~~~admonish tip\nIn production, the mose common use case you'll use the notification system for is changes in the stage. You can use these notifications to track user interaction and to trigger UI refreshes.\n~~~\n\n## Resources\n- [Usd Notice API Docs](https://openusd.org/dev/api/class_usd_notice.html)\n- [Tf Notification API Docs](https://openusd.org/dev/api/group__group__tf___notification.html)\n\n## Notice code examples\n\n#### Register/Revoke notice\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:noticeRegisterRevoke}}\n```\n~~~\n\n#### Overview of built-in standard notices for stage change events\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:noticeCommon}}\n```\n~~~\n\nIf we run this on a simple example stage, we get the following results:\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:noticeCommonApplied}}\n```\n~~~\n\n#### Plugin Register Notice\nThe plugin system sends a notice whenever a new plugin was registered.\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:noticePlugins}}\n```\n~~~\n\n#### Setup a custom notice:\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:noticeCustom}}\n```\n~~~"
  },
  {
    "path": "docs/src/pages/core/elements/overview.md",
    "content": "# Elements\nIn this sub-section we have a look at the basic building blocks of Usd.\n\nOur approach is incrementally going from the smallest building blocks to the larger ones (except for metadata we squeeze that in later as a deep dive), so the recommended order to work through is as follows:\n\n- [Paths](./path.md)\n- [Data Containers (Prims & Properties)](./data_container.md)\n    - [Prims](./prim.md)\n    - [Properties (Attributes/Relationships)](./property.md)\n- [Data Types](./data_type.md)\n- [Schemas ('Classes' in OOP terminology)](./schemas.md)\n- [Metadata](./metadata.md)\n- [Layers & Stages (Containers of actual data)](./layer.md)\n- [Traversing/Loading Data (Purpose/Visibility/Activation/Population)](./loading_mechanisms.md)\n- [Animation/Time Varying Data](./animation.md)\n- [Materials](./materials.md)\n- [Transforms](./transform.md)\n- [Collections](./collection.md)\n- [Notices/Event Listeners](./notice.md)\n- [Standalone Utilities](./standalone_utilities.md)\n\nThis will introduce you to the core classes you'll be using the most and then increasing the complexity step by step to see how they work together with the rest of the API.\n\n~~~admonish tip title=\"Vocabulary/Terminology\"\nWe try to stay terminology agnostic as much as we can, but some vocab you just have to learn to use USd. We compiled a small [cheat sheet](../glossary.md) here, that can assist you with all those weird Usd words.\n~~~\n\nGetting down the basic building blocks down is crucial, so take your time! In the current state the examples are a bit \"dry\", we'll try to make it more entertaining in the future.\n\nGet yourself comfortable and let's get ready to roll! You'll master the principles of Usd in no time!"
  },
  {
    "path": "docs/src/pages/core/elements/path.md",
    "content": "# Paths\nAs Usd is a hierarchy based format, one of its core functions is handling paths.\nIn order to do this, Usd provides the pxr.Sdf.Path class. You'll be using quite a bunch, so that's why we want to familiarize ourselves with it first.\n\n~~~admonish info title=\"\"\n```python\npxr.Sdf.Path(\"/My/Example/Path\")\n```\n~~~\n\n# Table of Contents\n1. [API Overview In-A-Nutshell](#summary)\n2. [What should I use it for?](#usage)\n3. [Resources](#resources)\n4. [Overview](#overview)\n    1. [Creating a path & string representation](#pathBasics)\n    2. [Special Paths: emptyPath & absoluteRootPath](#pathSpecialPaths)\n    3. [Variants ](#pathVariants)\n    4. [Properties](#pathProperties)\n\n## TL;DR - Paths In-A-Nutshell <a name=\"summary\"></a>\nHere is the TL;DR version:\nPaths can encode the following path data:\n- `Prim`: \"/set/bicycle\" - Separator `/`\n- `Property`:\n    - `Attribute`: \"/set/bicycle.size\"  - Separator `.`\n    - `Relationship`: \"/set.bikes[/path/to/target/prim]\"  - Separator `.` / Targets `[]`  (Prim to prim target paths e.g. collections of prim paths)\n- `Variants` (\"/set/bicycle{style=blue}wheel.size\")\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:pathSummary}}\n```\n~~~\n\n## What should I use it for? <a name=\"usage\"></a>\n~~~admonish tip\nAnything that is path related in your hierarchy, use Sdf.Path objects. It will make your life a lot easier than if you were to use strings.\n~~~\n\n## Resources <a name=\"resources\"></a>\n- [Sdf.Path](https://openusd.org/release/api/class_sdf_path.html#sec_SdfPath_Overview)\n\n## Overview <a name=\"overview\"></a>\nEach element in the path between the \"/\" symbol is a [prim](https://openusd.org/release/glossary.html#usdglossary-prim) similar to how on disk file paths mark a folder or a file.\n\nMost Usd API calls that expect Sdf.Path objects implicitly take Python strings as well, we'd recommend using Sdf.Paths from the start though, as it is faster and more convenient.\n\nWe recommend going through these small examples (5-10 min), just to get used to the Path class.\n\n### Creating a path & string representation <a name=\"pathBasics\"></a>\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:pathBasics}}\n```\n~~~\n\n### Special Paths: emptyPath & absoluteRootPath <a name=\"pathSpecialPaths\"></a>\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:pathSpecialPaths}}\n```\n~~~\n\n### Variants <a name=\"pathVariants\"></a>\nWe can also encode variants into the path via the {variantSetName=variantName} syntax.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:pathVariants}}\n```\n~~~\n\n### Properties <a name=\"pathProperties\"></a>\nPaths can also encode properties (more about what these are in the next section).\nNotice that attributes and relationships are both encoded with the \".\" prefix, hence the name `property` is used to describe them both.\n\n~~~admonish tip\nWhen using Usd, we'll rarely run into the relationship `[]` encoded targets paths. Instead we use the `Usd.Relationship`/`Sdf.RelationshipSpec` methods to set the path connections. Therefore it is just good to know they exist.\n~~~\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:pathProperties}}\n```\n~~~\n\n"
  },
  {
    "path": "docs/src/pages/core/elements/prim.md",
    "content": "\n# Prims\nFor an overview and summary please see the parent [Data Containers](./data_container.md) section.\n\n# Table of Contents\n1. [Prim Basics](#primBasics)\n    1. [Specifier](#primSpecifier)\n    2. [Type Name](#primTypeName)\n    3. [Kind](#primKind)\n    4. [Active](#primActive)\n    5. [Metadata](#primMetadata)\n    6. [Tokens (Low Level API)](#primTokens)\n    7. [Debugging](#primDebugging)\n2. [Hierarchy (Parent/Child)](#primHierarchy)\n3. [Schemas](#primSchemas)\n4. [Composition](#primComposition)\n5. [Loading Data (Activation/Visibility)](#primLoading)\n6. [Properties (Attributes/Relationships)](#primProperties)\n\n\n## Overview\nThe main purpose of a prim is to define and store properties. The prim class itself only stores very little data:\n- Path/Name\n- A connection to its properties\n- Metadata related to composition and schemas as well as core metadata(specifier, typeName, kind,activation, assetInfo, customData) \n\nThis page covers the data on the prim itself, for properties check out this [section](./property.md).\n\nThe below examples demonstrate the difference between the higher and lower level API where possible. Some aspects of prims are only available via the high level API, as it acts on composition/stage related aspects. \n\n~~~admonish warning title=\"\"\nThere is a lot of code duplication in the below examples, so that each example works by itself. In practice editing data is very concise and simple to read, so don't get overwhelmed by all the examples.\n~~~\n\n### Prim Basics <a name=\"primBasics\"></a>\nSetting core metadata via the high level is not all exposed on the prim itself via getters/setters, instead\nthe getters/setters come in part from schemas or schema APIs. For example setting the kind is done via the Usd.ModelAPI.\n\n##### High Level\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:dataContainerPrimCoreHighLevel}}\n```\n~~~\n\nWe are also a few \"shortcuts\" that check specifiers/kinds (`.IsAbstract`, `.IsDefined`, `.IsGroup`, `.IsModel`), more about these in the kind section below.\n\n##### Low Level\nThe Python lower level Sdf.PrimSpec offers quick access to setting common core metadata via standard class instance attributes:\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:dataContainerPrimCoreLowLevel}}\n```\n~~~\n\nWe will look at specifics in the below examples, so don't worry if you didn't understand everything just yet :)\n\n\n#### Specifiers <a name=\"primSpecifier\"></a>\nUsd has the concept of [specifiers](https://openusd.org/release/glossary.html#usdglossary-specifier). \n\n~~~admonish important\nThe job of specifiers is mainly to define if a prim should be visible to hierarchy traversals. More info about traversals in our [Layer & Stage](./layer.md) section.\n~~~\n\nHere is an example USD ascii file with all three specifiers.\n~~~admonish info title=\"\"\n```json\ndef Cube \"definedCube\" ()\n{\n    double size = 2\n}\n\nover Cube \"overCube\" ()\n{\n    double size = 2\n}\n\nclass Cube \"classCube\" ()\n{\n    double size = 2\n}\n```\n~~~\n\nThis is how it affects traversal:\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:dataContainerPrimBasicsSpecifierTraversal}}\n```\n~~~\n\n\n##### Sdf.SpecifierDef: `def`(define)\nThis specifier is used to specify a prim in a hierarchy, so that is it always visible to traversals.\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:dataContainerPrimBasicsSpecifierDef}}\n```\n~~~\n\n##### Sdf.SpecifierOver: `over`\nPrims defined with `over` only get loaded if the prim in another layer has been specified with a `def`specified. It gets used when you want to add data to an existing hierarchy, for example layering only position and normals data onto a character model, where the base model has all the static attributes like topology or UVs.\n\n~~~admonish important\nBy default stage traversals will skip over `over` only prims. Prims that only have an `over` also do not get forwarded to Hydra render delegates.\n~~~\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:dataContainerPrimBasicsSpecifierOver}}\n```\n~~~\n\n##### Sdf.SpecifierClass: `class`\nThe `class` specifier gets used to define \"template\" hierarchies that can then get attached to other prims. A typical example would be to create a set of geometry render settings that then get applied to different parts of the scene by creating an inherit composition arc. This way you have a single control point if you want to adjust settings that then instantly get reflected across your whole hierarchy. \n\n~~~admonish important\n- By default stage traversals will skip over `class` prims.\n- Usd refers to class prims as \"abstract\", as they never directly contribute to the hierarchy.\n- We target these class prims via inherits/internal references and specialize [composition arcs](../composition/livrps.md)\n~~~\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:dataContainerPrimBasicsSpecifierClass}}\n```\n~~~\n\n\n#### Type Name <a name=\"primTypeName\"></a>\nThe type name specifies what concrete schema the prim adheres to.\nIn plain english: Usd has the concept of schemas, which are like OOP classes. Each prim can be an instance of a class, so that it receives the default attributes of that class. More about schemas in our [schemas](./schemas.md) section. You can also have prims without a type name, but in practice you shouldn't do this. For that case USD has an \"empty\" class that just has all the base attributes called \"Scope\".\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:dataContainerPrimBasicsTypeName}}\n```\n~~~\n\n#### Kind <a name=\"primKind\"></a>\nThe [kind](https://openusd.org/release/glossary.html#usdglossary-kind) metadata can be attached to prims to mark them what kind hierarchy level it is. This way we can quickly traverse and select parts of the hierarchy that are of interest to us, without traversing into every child prim.\n\nFor a full explanation we have a dedicated section: [Kinds](../plugins/kind.md) \n\nHere is the reference code on how to set kinds. For a practical example with stage traversals, check out the kinds page.\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:dataContainerPrimBasicsKinds}}\n```\n~~~\n\n#### Active <a name=\"primActive\"></a>\nThe `active` metadata controls if the prim and its children are loaded or not.\nWe only cover here how to set the metadata, for more info checkout our [Loading mechansims](./loading_mechanisms.md) section. Since it is a metadata entry, it can not be animated. For animated pruning we must use [visibility](./property.md#visibility).\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:metadataActive}}\n```\n~~~\n\n#### Metadata <a name=\"primMetadata\"></a>\nWe go into more detail about metadata in our [Metadata](./metadata.md) section. \n\n~~~admonish important\nAs you can see on this page, most of the prim functionality is actually done via metadata, except path, composition and property related functions/attributes.\n~~~\n\n#### Tokens (Low Level API) <a name=\"primTokens\"></a>\nPrim (as well as property, attribute and relationship) specs also have the tokens they can set as their metadata as class attributes ending with 'Key'.\nThese 'Key' attributes are the token names that can be set on the spec via `SetInfo`, for example prim_spec.SetInfo(prim_spec.KindKey, \"group\")\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:dataContainerPrimBasicsTokens}}\n```\n~~~\n\n#### Debugging (Low Level API) <a name=\"primDebugging\"></a>\nYou can also print a spec as its ascii representation (as it would be written to .usda files):\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:dataContainerPrimBasicsDebugging}}\n```\n~~~\n\n### Hierarchy (Parent/Child) <a name=\"primHierarchy\"></a>\nFrom any prim you can navigate to its hierarchy neighbors via the path related methods.\nThe lower level API is dict based when accessing children, the high level API returns iterators or lists.\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:dataContainerPrimHierarchy}}\n```\n~~~\n\n### Schemas <a name=\"primSchemas\"></a>\n\nWe explain in more detail what schemas are in our [schemas](./schemas.md) section.\nIn short: They are the \"base classes\" of Usd. Applied schemas are schemas that don't \ndefine the prim type and instead just \"apply\" (provide values) for specific metadata/properties\n\n~~~admonish important\nThe 'IsA' check is a very valueable check to see if something is an instance of a (base) class. It is similar to Python's isinstance method.\n~~~\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:dataContainerPrimSchemas}}\n```\n~~~\n\n#### Prim Type Definition (High Level)\nWith the [prim definition](https://openusd.org/dev/api/class_usd_prim_definition.html) we can inspect what the schemas provide. Basically you are inspecting the class (as to the prim being the instance, if we compare it to OOP paradigms).\nIn production, you won't be using this a lot, it is good to be aware of it though.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:dataContainerPrimTypeDefinition}}\n```\n~~~\n\n#### Prim Type Info (High Level)\nThe [prim type info](https://openusd.org/dev/api/class_usd_prim_type_info.html) holds the composed type info of a prim. You can think of it as as the class that answers Python `type()` like queries for Usd. It caches the results of type name and applied API schema names, so that `prim.IsA(<typeName>)` checks can be used to see if the prim matches a given type.\n\n~~~admonish tip\nThe prim's `prim.IsA(<typeName>)` checks are highly performant, you should use them as often as possible when traversing stages to filter what prims you want to edit. Doing property based queries to determine if a prim is of interest to you, is a lot slower.\n~~~\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:dataContainerPrimTypeInfo}}\n```\n~~~\n\n### Composition <a name=\"primComposition\"></a>\nWe discuss handling composition in our [Composition](../composition/overview.md) section as it follows some different rules and is a bigger topic to tackle.\n\n\n### Loading Data (Purpose/Activation/Visibility) <a name=\"primLoading\"></a>\nWe cover this in detail in our [Loading Data](./loading_mechanisms.md) section.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:dataContainerPrimLoading}}\n```\n~~~\n\n### Properties/Attributes/Relationships <a name=\"primProperties\"></a>\nWe cover properties in more detail in our [properties](./property.md) section.\n\n~~~admonish important title=\"Deep Dive | Properties\"\nTechnically properties are also stored as metadata on the `Sdf.PrimSpec`. So later on when we look at composition, keep in mind that the prim stack therefore also drives the property stack. That's why the prim index is on the `prim` level and not on the `property` level.\n```python\n...\nprint(prim_spec.properties, prim_spec.attributes, prim_spec.relationships)\nprint(prim_spec.GetInfo(\"properties\"))\n...\n```\n~~~\n\nHere are the basics for both API levels:\n\n#### High Level API\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:dataContainerPrimPropertiesHighLevel}}\n```\n~~~\n\n#### Low Level API\nTo access properties on `Sdf.PrimSpec`s we can call the `properties`, `attributes`, `relationships` methods. These return a dict with the {'name': spec} data.\nHere is an example of what is returned when you create cube with a size attribute:\n\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:dataContainerPrimPropertiesLowLevel}}\n```\n~~~\n\n~~~admonish important\nSince the lower level API doesn't see the schema properties, these commands will only return what is actually in the layer, in Usd speak `authored`.\n~~~\n\nWith the high level API you can get the same/similar result by calling prim.GetAuthoredAttributes() as you can see above.\nWhen you have multiple layers, the prim.GetAuthoredAttributes(), will give you the created attributes from all layers, where as the low level API only the ones from the active layer.\n\nAs mentioned in the `properties` section, properties is the base class, so the `properties` method will give you\nthe merged dict of the `attributes` and `relationship` dicts.\n\n\n\n\n\n"
  },
  {
    "path": "docs/src/pages/core/elements/property.md",
    "content": "# Properties\nFor an overview and summary please see the parent [Data Containers](./data_container.md) section.\n\nHere is an overview of the API structure, in the high level API it looks as follows:\n```mermaid\nflowchart TD\n    property([Usd.Property])\n    property --> attribute([Usd.Attribute])\n    property --> relationship([Usd.Relationship])\n```\nIn the low level API:\n```mermaid\nflowchart TD\n    property([Sdf.PropertySpec])\n    property --> attribute([Sdf.AttributeSpec])\n    property --> relationship([Sdf.RelationshipSpec])\n```\n\n# Table of Contents\n1. [Properties](#propertyOverview)\n1. [Attributes](#attributeOverview)\n    1. [Attribute Types (Detail/Prim/Vertex/Point) (USD Speak: **Interpolation**)](#attributeInterpolation)\n    1. [Attribute Data Types & Roles](#attributeDataTypeRole)\n    1. [Static (Default) Values vs Time Samples vs Value Blocking](#attributeAnimation)\n        1. [Re-writing a range of values from a different layer](#attributeReauthor)\n        1. [Time freezing (mesh) data](#attributeReauthorTimeSampleToStatic)\n    1. [Attribute To Attribute Connections (Node Graph Encoding)](#attributeConnections)\n    1. [The **primvars** (primvars:<AttributeName>) namespace](#attributePrimvars)\n        1. [Reading inherited primvars](#attributePrimvarsInherited)\n        1. [Indexed Primvars](#attributePrimvarsIndexed)\n    1. [Common Attributes](#attributeCommon):\n        1. [Purpose](#attributePurpose)\n        1. [Visibility](#attributeVisibility)\n        1. [Extents Hint vs Extent](#attributeExtent)\n        1. [Xform Ops](#attributeXformOps)\n1. [Relationships](#relationshipOverview)\n    1. [Material Binding](#relationshipMaterialBinding)\n    1. [Collections](#relationshipCollections)\n    1. [Relationships Forwarding](#relationshipForwarding)\n    1. [Proxy Prim](#relationshipProxyPrim)\n1. [Schemas](#propertySchemas)\n\n## Resources\n- [Usd.Property](https://openusd.org/dev/api/class_usd_property.html)\n- [Usd.Attribute](https://openusd.org/dev/api/class_usd_attribute.html)\n- [Usd.Relationship](https://openusd.org/dev/api/stitch_clips_8h.html#details)\n- [Usd.GeomPrimvar](https://openusd.org/release/api/class_usd_geom_primvar.html)\n- [Usd.GeomPrimvarsAPI](https://openusd.org/dev/api/class_usd_geom_primvars_a_p_i.html)\n- [Usd.GeomImageable](https://openusd.org/release/api/class_usd_geom_imageable.html)\n- [Usd.GeomBoundable](https://openusd.org/dev/api/class_usd_geom_boundable.html)\n\n## Properties <a name=\"propertyOverview\"></a>\nLet's first have a look at the shared base class `Usd.Property`. This inherits most its functionality from `Usd.Object`, which mainly exposes metadata data editing. We won't cover how metadata editing works for properties here, as it is extensively covered in our [metadata](./metadata.md#metadataSpecialProperty) section.\n\nSo let's inspect what else the class offers:\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:propertyOverview}}\n```\n~~~\n\nAs you can see, the `.GetProperty`/`.GetAttribute`/`.GetRelationship` methods return an object instead of just returning `None`. This way we can still check for `.IsDefined()`. We can also use them  as \"truthy\"/\"falsy\" objects, e.g. `if not attr` which makes it nicely readable.\n\nFor a practical of the `.GetPropertyStack()` method see our [Houdini](../../dcc/houdini/hda/timedependency.md) section, where we use it to debug if time varying data actually exists. We also cover it in more detail in our [composition](../composition/pcp.md) section.\n\n## Attributes <a name=\"attributeOverview\"></a>\nAttributes in USD are the main data containers to hold all of you geometry related data. They are the only element in USD that can be [animateable](./animation.md).\n\n\n### Attribute Types (Detail/Prim/Vertex/Point) (USD Speak: **Interpolation**) <a name=\"attributeInterpolation\"></a>\nTo determine on what geo prim element an attribute applies to, attributes are marked with `interpolation` metadata.\nWe'll use Houdini's naming conventions as a frame of reference here:\n\nYou can read up more info in the [Usd.GeomPrimvar](https://openusd.org/release/api/class_usd_geom_primvar.html#Usd_InterpolationVals) docs page.\n\n- `UsdGeom.Tokens.constant` (Same as Houdini's `detail`attributes): Global attributes (per prim in the hierarchy).\n- `UsdGeom.Tokens.uniform` (Same as Houdini's `prim` attributes): Per prim attributes (e.g. groups of polygons).\n- `UsdGeom.Tokens.faceVarying` (Same as Houdini's `vertex` attributes): Per vertex attributes (e.g. UVs).\n- `UsdGeom.Tokens.varying` (Same as Houdini's `vertex` attributes): This the same as face varying, except for nurbs surfaces.\n- `UsdGeom.Tokens.vertex` (Same as Houdini's `point` attributes): Per point attributes (e.g. point positions).\n\nTo summarize:\n\n| Usd Name                  | Houdini Name |\n|---------------------------|--------------|\n|UsdGeom.Tokens.constant    | detail       |\n|UsdGeom.Tokens.uniform     | prim         |\n|UsdGeom.Tokens.faceVarying | vertex       |\n|UsdGeom.Tokens.vertex      | point        |\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:attributeInterpolation}}\n```\n~~~\n\n~~~admonish tip\nFor attributes that don't need to be accessed by Hydra (USD's render abstraction interface), we don't need to set the interpolation. In order for an attribute, that does not derive from a schema, to be accessible for the Hydra, we need to namespace it with `primvars:`, more info below at [primvars](#attributePrimvars). If the attribute element count for non detail (constant) attributes doesn't match the corresponding prim/vertex/point count, it will be ignored by the renderer (or crash it).\n\nWhen we set schema attributes, we don't need to set the interpolation, as it is provided from the [schema](./schemas.md).\n~~~\n\n### Attribute Data Types & Roles <a name=\"attributeDataTypeRole\"></a>\nWe cover how to work with data classes in detail in our [data types/roles](./data_type.md) section. For array attributes, USD has implemented the buffer protocol, so we can easily convert from numpy arrays to USD Vt arrays and vice versa. This allows us to write high performance attribute modifications directly in Python. See our [Houdini Particles](../../dcc/houdini/fx/particles.md) section for a practical example.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:attributeDataTypeRole}}\n```\n~~~\n\nThe role specifies the intent of the data, e.g. `points`, `normals`, `color` and will affect how renderers/DCCs handle the attribute. This is not a concept only for USD, it is there in all DCCs. For example a color vector doesn't need to be influenced by transform operations where as normals and points do.\n\nHere is a comparison to when we create an attribute a float3 normal attribute in Houdini.\n![](../../../media/core/elements/attributesDataRole.jpg#center)\n\n### Static (Default) Values vs Time Samples vs Value Blocking <a name=\"attributeAnimation\"></a>\nWe talk about how animation works in our [animation](./animation.md) section.\n\n~~~admonish important\nAttributes are the only part of USD that can encode time-varying data.\n~~~\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:animationOverview}}\n```\n~~~\n\nWe can set an attribute with a static value (USD speak `default`) or with time samples (or both, checkout the animation section on how to handle this edge case). We can also block it, so that USD sees it as if no value was written. For attributes from schemas with default values, this will make it fallback to the default value.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:animationDefaultTimeSampleBlock}}\n```\nFor more examples (also for the lower level API) check out the [animation](./animation.md) section.\n~~~\n\n#### Re-writing a range of values from a different layer <a name=\"attributeReauthor\"></a>\n\n~~~admonish danger\nAn important thing to note is that when we want to re-write the data of an attribute from a different layer, we have to get all the existing data first and then write the data, as otherwise we are changing the value source. To understand better why this happens, check out our [composition](../composition/overview.md) section.\n~~~\n\nLet's demonstrate this:\n~~~admonish info title=\"Change existing values | Click to expand code\" collapsible=true\n```python\n{{#include ../../../../../code/core/elements.py:attributeReauthor}}\n```\n~~~\n\nFor heavy data it would be impossible to load everything into memory to offset it. USD's solution for that problem is [Layer Offsets](./animation.md#layer-offset-a-non-animateable-time-offsetscale-for-composition-arcs). \n\nWhat if we don't want to offset the values, but instead edit them like in the example above? \n\nIn a production pipeline you usually do this via a DCC that imports the data, edits it and then re-exports it (often per frame and loads it via value clips). So we mitigate the problem by distributing the write to a new file(s) on multiple machines/app instances. Sometimes though we actually have to edit the samples in an existing file, for example when post processing data. In our [point instancer](../../dcc/houdini/fx/pointinstancers.md) section we showcase a practical example of when this is needed.\n\nTo edit the time samples directly, we can open the layer as a stage or edit the layer directly. To find the layers you can inspect the layer stack or value clips, but most of the time you know the layers, as you just wrote to them:\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:attributeReauthorPerLayer}}\n```\n~~~\n\n#### Time freezing (mesh) data <a name=\"attributeReauthorTimeSampleToStatic\"></a>\nIf we want to time freeze a prim (where the data comes from composed layers), we simply re-write a specific time sample to the default value.\n\n~~~admonish tip title=\"Pro Tip | Time Freeze | Click to expand code\" collapsible=true\n```python\n{{#include ../../../../../code/core/elements.py:attributeReauthorTimeSampleToStatic}}\n```\n~~~\n\n~~~admonish danger\nIf you have to do this for a whole hierarchy/scene, this does mean that you are flattening everything into your memory, so be aware! USD currently offers no other mechanism.\n~~~\n\nWe'll leave \"Time freezing\" data from the active layer to you as an exercise.\n\n~~~admonish tip title=\"Hint | Time Freeze | Active Layer | Click to expand\" collapsible=true\nWe just need to write the time sample of your choice to the `attr_spec.default` attribute and clear the time samples ;\n~~~\n\n### Attribute To Attribute Connections (Node Graph Encoding)<a name=\"attributeConnections\"></a>\nAttributes can also encode relationship-like paths to other attributes. These connections are encoded directly on the attribute. It is up to Usd/Hydra to evaluate these \"attribute graphs\", if you simply connect two attributes, it will not forward attribute value A to connected attribute B (USD does not have a concept for a mechanism like that (yet)).\n\n~~~admonish important\nAttribute connections are encoded from target attribute to source attribute.\nThe USD file syntax is: `<data type> <attribute name>.connect = </path/to/other/prim.<attribute name>`\n~~~\n\nCurrently the main use of connections is encoding node graphs for shaders via the [UsdShade.ConnectableAPI](https://openusd.org/dev/api/class_usd_shade_connectable_a_p_i.html).\n\n\nHere is an example of how a material network is encoded.\n\n~~~admonish important title=\"\"\n```python\ndef Scope \"materials\"\n{\n    def Material \"karmamtlxsubnet\" (\n    )\n    {\n        token outputs:mtlx:surface.connect = </materials/karmamtlxsubnet/mtlxsurface.outputs:out>\n\n        def Shader \"mtlxsurface\" ()\n        {\n            uniform token info:id = \"ND_surface\"\n            string inputs:edf.connect = </materials/karmamtlxsubnet/mtlxuniform_edf.outputs:out>\n            token outputs:out\n        }\n\n        def Shader \"mtlxuniform_edf\"\n        {\n            uniform token info:id = \"ND_uniform_edf\"\n            color3f inputs:color.connect = </materials/karmamtlxsubnet/mtlx_constant.outputs:out>\n            token outputs:out\n        }\n\n        def Shader \"mtlx_constant\"\n        {\n            uniform token info:id = \"ND_constant_float\"\n            float outputs:out\n        }\n    }\n}\n```\n~~~\n\nConnections, like relationships and composition arcs, are encoded via `List Editable Ops`. These are a core USD concept that is crucial to understand (They are like fancy version of a Python list with rules how sub-lists are merged). Checkout our [List Editable Ops](../composition/listeditableops.md) section for more info. \n\nHere is how connections are managed on the high and low API level. Note as mentioned above this doesn't do anything other than make the connection. USD doesn't drive attribute values through connections. So this example is just to demonstrate the API.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:attributeConnections}}\n```\n~~~\n\n### The **primvars** (primvars:<AttributeName>) namespace <a name=\"attributePrimvars\"></a>\nAttributes in the `primvars` namespace `:` are USD's way of marking attributes to be exported for rendering. These can then be used by materials and AOVs. Primvars can be written per attribute type (detail/prim/vertex/point), it is up to the render delegate to correctly access them.\n\nPrimvars that are written as `detail` (UsdGeom.Tokens.constant interpolation) attributes, get inherited down the hierarchy. This makes them ideal transport mechanism of assigning render geometry properties, like dicing settings or render ray visibility.\n\n~~~admonish important\n- An attribute with the `primvars:` can be accessed at render time by your render delegate for things like settings, materials and AOVs\n- `detail` (UsdGeom.Tokens.constant interpolation) primvars are inherited down the hierarchy, ideal to apply a constant value per USD prim, e.g. for render geometry settings or instance variation.\n~~~\n~~~admonish danger\n- The term `inherited` in conjunction with `primvars` refers to a constant interpolation primvar being passed down to its children. It is not to be confused with `inherit` composition arcs.\n~~~\n\nTo deal with primvars, the high level API has the `UsdGeom.PrimvarsAPI` [(API Docs)](https://openusd.org/dev/api/class_usd_geom_primvars_a_p_i.html). In the low level, we need to do everything ourselves. This create `UsdGeom.Primvar` [(API Docs)](https://openusd.org/dev/api/class_usd_geom_primvar.html) objects, that are similar `Usd.Attribute` objects, but with methods to edit primvars. To get the attribute call `primvar.GetAttr()`.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:attributePrimvarAPI}}\n```\n~~~\n\n#### Reading inherited primvars <a name=\"attributePrimvarsInherited\"></a>\nTo speed up the lookup of inherited primvars see this guide [API Docs](https://openusd.org/dev/api/class_usd_geom_primvars_a_p_i.html#usdGeom_PrimvarFetchingAPI). Below is an example how to self implement a high performant lookup, as we couldn't get the `.FindIncrementallyInheritablePrimvars` to work with Python as expected.\n\n~~~admonish danger title=\"High performance primvars inheritance calculation | Click to expand code\" collapsible=true\n```python\n{{#include ../../../../../code/core/elements.py:attributePrimvarInherited}}\n```\n~~~\n\n#### Indexed primvars <a name=\"attributePrimvarsIndexed\"></a>\nPrimvars can optionally be encoded via an index table. Let's explain via an example:\n\nHere we store it without an index table, as you can see we have a lot of duplicates in our string list. \nThis increases the file size when saving the attribute to disk.\n```python\n...\n        string[] primvars:test = [\"test_0\", \"test_0\", \"test_0\", \"test_0\",\n                                  \"test_1\", \"test_1\", \"test_1\", \"test_1\",\n                                  \"test_2\", \"test_2\", \"test_2\", \"test_2\",\n                                  \"test_3\", \"test_3\", \"test_3\", \"test_3\"] (\n            interpolation = \"uniform\"\n        )\n        int[] primvars:test:indices = None\n...\n```\nInstead we can encode it as a indexed primvar:\n```python\n...\n        string[] primvars:test = [\"test_0\", \"test_1\", \"test_2\", \"test_3\"] (interpolation = \"uniform\")\n        int[] primvars:test:indices = [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3] ()\n...\n```\nWe can also flatten the index, when looking up the values. It should be preferred to keep the index, if you intend on updating the primvar.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:attributePrimvarIndexed}}\n```\n~~~\n\nIf you are a Houdini user you might know this method, as this is how Houdini's internals also store string attributes.\nYou can find more info in the [USD Docs](https://openusd.org/release/api/class_usd_geom_primvar.html)\n\n\n### Common Attributes <a name=\"attributeCommon\"></a>\nNow that we got the basics down, let's have a look at some common attributes (and their schemas to access them).\n\n#### Purpose <a name=\"attributePurpose\"></a>\nThe `purpose` is a special USD attribute that:\n- Affects certain scene traversal methods (e.g. [bounding box or xform cache lookups](../../production/caches.md) can be limited to a specific purpose).\n- Is a mechanism for Hydra (USD's render abstraction interface) to only pull in data with a specific purpose. Since any rendering (viewport or final image) is run via Hydra, this allows users to load in only prims tagged with a specific purpose. For example, the `pxr.UsdGeom.Tokens.preview` purpose is used for scene navigation and previewing only, while the `UsdGeom.Tokens.render` purpose is used for final frame rendering.\n- It is inherited (like [primvars](#the-primvars-primvars-namespace)) down the hierarchy. You won't see this in UIs unlike with primvars.\n\n~~~admonish tip title=\"Pro Tip | Where to mark the purpose\"\nAs a best practice you should build your hierarchies in such a way that you don't have to write a purpose value per prim.\nA typical setup is to have a `<asset root>/GEO`, `<asset root>/PROXY`, ... hierarchy, where you can then tag the `GEO`, `PROXY`, ... prims with the purpose. That way all child prims receive the purpose and you have a single point where you can override the purpose.\n\nThis is useful, if you for example want to load a whole scene in `proxy` purpose and a specific asset in `render` purpose. You then just have to edit a single prim to make it work.\n~~~\n\nThe purpose is provided by the `UsdGeom.Imageable` (renderable) typed non-concrete schema, and is therefore on anything that is renderable.\n\n~~~admonish tip title=\"Usd.GeomImageable inheritance graph | Click to expand code\" collapsible=true\n![](../../../media/core/elements/schemasTypedNonConcreteUsdGeomImageable.jpg#center)\n~~~\n\nThere are 4 different purposes:\n- `UsdGeom.Tokens.default_`: The default purpose. This is the fallback purpose, when no purpose is explicitly defined. It means that this prim should be traversed/visible to any purpose.\n- `UsdGeom.Tokens.render`: Tag any (parent) prim with this to mark it suitable for final frame rendering.\n- `UsdGeom.Tokens.proxy`:  Tag any (parent) prim with this to mark it suitable for low resolution previewing. We usually tag prims with this that can be loaded very quickly.\n- `UsdGeom.Tokens.guide`: Tag any (parent) prim with this to mark it suitable for displaying guide indicators like rig controls or other useful scene visualizers.\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:attributePurpose}}\n```\n~~~\n\n#### Visibility <a name=\"attributeVisibility\"></a>\nThe `visibility` attribute controls if the prim and its children are visible to Hydra or not. Unlike the `active` [metadata](./metadata.md#activeactivation), it does not prune the child prims, they are still reachable for inspection and traversal. Since it is an attribute, we can also animate it. Here we only cover  how to set/compute the attribute, for more info checkout our [Loading mechansims](./loading_mechanisms.md) section\n\nThe attribute data type is `Sdf.Token` and can have two values:\n- UsdGeom.Tokens.inherited\n- UsdGeom.Tokens.invisible\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:attributeVisibility}}\n```\n~~~\n\n~~~admonish note\nIn the near future visibility can be set per purpose (It is already possible, just not widely used). Be aware that this might incur further API changes.\n~~~\n\n#### Extents Hint vs Extent <a name=\"attributeExtent\"></a>\nIn order for Hydra delegates but also stage bounding box queries to not have to compute the bounding box of each individual boundable prim, we can write an extent attribute.\n\nThis attribute is mandatory for all boundable prims. The data format is:\n\n`Vt.Vec3fArray(2, (Gf.Vec3f(<min_x>, <min_y>, <min_z>), Gf.Vec3f(<max_x>, <max_y>, <max_z>)))`\n\nE.g.: `Vt.Vec3fArray(2, (Gf.Vec3f(-5.0, 0.0, -5.0), Gf.Vec3f(5.0, 0.0, 5.0)))`\n\nHere are all boundable prims (prims that have a bounding box).\n\n~~~admonish tip title=\"UsdGeom.Boundable inheritance graph | Click to view\" collapsible=true\n![](../../../media/core/elements/schemasTypedNonConcreteUsdBoundable.jpg#center)\n~~~\n\nSince boundable prims are leaf prims (they have (or at least should have) no children), a prim higher in the hierarchy can easily compute an accurate bounding box representation, by iterating over all leaf prims and reading the `extent` attribute. This way, if a single leaf prim changes, the parent prims can reflect the update without having to do expensive per prim point position attribute lookups.\n\n~~~admonish tip title=\"Pro Tip | Bounding Box Cached Queries in Production\"\nWe cover how to use the a bounding box cache in detail in our [stage API query caches](../../production/caches.md) for optimized bounding box calculation and extent writing.\n~~~\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:attributeExtent}}\n```\n~~~\n\nThere is also an `extentsHint` attribute we can create on non-boundable prims. This attribute can be consulted by bounding box lookups too and it is another optimization level on top of the `extent` attribute.\nWe usually write it on asset root prims, so that when we unload payloads, it can be used to give a correct bbox representation.\n\nThe `extentsHint` has a different data format: It can store the extent hint per purpose or just for the default purpose.\n\nFor just the default purpose it looks like:\n`Vt.Vec3fArray(2, (Gf.Vec3f(<min_x>, <min_y>, <min_z>), Gf.Vec3f(<max_x>, <max_y>, <max_z>)))`\n\nFor the default and proxy purpose (without render): \n`Vt.Vec3fArray(6, (Gf.Vec3f(<min_x>, <min_y>, <min_z>), Gf.Vec3f(<max_x>, <max_y>, <max_z>), Gf.Vec3f(0, 0, 0), Gf.Vec3f(0, 0, 0), Gf.Vec3f(<proxy_min_x>, <proxy_min_y>, <proxy_min_z>), Gf.Vec3f(<proxy_max_x>, <proxy_max_y>, <proxy_max_z>)))`\n\nAs you can see the order is `UsdGeom.Tokens.default_`, `UsdGeom.Tokens.render`,`UsdGeom.Tokens.proxy`, `UsdGeom.Tokens.guide`. It a purpose is not authored, it will be sliced off (it it is at the end of the array).\n\n#### Xform (Transform) Ops <a name=\"attributeXformOps\"></a>\nPer prim transforms are also encoded via attributes. As this is a bigger topic, we have a dedicated [Transforms](./transform.md) section for it.\n\n## Relationships <a name=\"relationshipOverview\"></a>\nRelationships in USD are used to encode prim path to prim path connections.\nThey can be in the form of `single` -> `single` prim path or `single` -> `multiple` primpaths.\n\nTechnically relationships can also target properties (because they encode `Sdf.Path` objects), I'm not aware of it being used other than to target other collection properties. The paths must always be absolute (we'll get an error otherwise).\n\nRelationships are [list-editable](../composition/listeditableops.md), this is often not used, as a more explicit behavior is favoured.\n\nWhen we start looking at composition (aka loading nested USD files), you'll notice that relationships that where written in a different file are mapped into the hierarchy where it is being loaded. That way every path still targets the correct destination path.\n(Don't worry, we'll look at some examples in our [Composition](../composition/overview.md) and [Houdini](../../dcc/houdini/overview.md) sections. \n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:relationshipOverview}}\n```\n~~~\n\n### Material Binding <a name=\"relationshipMaterialBinding\">\nOne of the most common use cases of relationships is encoding the material binding. Here we simply link from any imageable (renderable) prim to a `UsdShade.Material` (`Material`) prim.\n\nAs this is a topic in itself, we have a dedicated [materials](./materials.md) section for it.\n\n### Collections <a name=\"relationshipCollections\"></a>\nCollections are USD's concept for storing a set of prim paths. We can nest/forward collections to other collections and relationships, which allows for powerful workflows. For example we can forward multiple collections to a light linking relationship or forwarding material binding relationships to a single collection on the asset root prim, which then in return forwards to the material prim.\n\nAs this is a bigger topic, we have a dedicated [collections](./collection.md) section for it.\n\n### Relationship Forwarding <a name=\"relationshipForwarding\"></a>\nRelationships can also point to other relations ships. This is called `Relationship Forwarding`.\nWe cover this topic in detail in our [Advanced Topics](../../production/concepts.md#relationship-forwarding) section.\n\n### Proxy Prim <a name=\"relationshipProxyPrim\"></a>\nThe `proxyPrim` is a relationship from a prim with the `UsdGeom.Token.render` purpose to a prim with the `UsdGeom.Token.proxy` purpose. It can be used by DCCs/USD consumers to find a preview representation of a render prim. A good use case example is when we need to simulate rigid body dynamics and need to find a low resolution representation of an asset.\n\nThe relation can also be used by clients to redirect edits back from the proxy prim to the render prim, for example transform edits or material assignments. Since the relation is from render to proxy and not the other way around, it can come with a high cost to relay this info, because we first need to find the correct prims. Therefore it is more common to just edit a mutual parent instead of redirecting what UI manipulators do on the preview prim to the render prim.\n\n~~~admonish tip title=\"Pro Tip | Preview Purpose Prim Counts\"\nOne of the biggest bottlenecks in USD is creating enormous hierarchies as you then have a lot of prims that need to be considered as value sources. When creating proxy purpose prims/meshes, we should try to keep it as low-res as possible. Best case we only have a single proxy prim per asset.\n~~~\n\nTo edit and query the `proxyPrim`, we use the `UsdGeom.Imageable` schema class.\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:relationshipProxyPrim}}\n```\n~~~\n\n## Schemas <a name=\"propertySchemas\"></a>\nSchemas are like OOP classes in USD, we cover them in detail [here](./schemas.md). Once applied to a prim, they provide different metadata and properties with fallback values. They also expose convenience methods to edit these.\n\nWe have used a few so far in our examples, for a list of the most usefull ones see our [Common Schemas in Production](../../production/schemas.md) section."
  },
  {
    "path": "docs/src/pages/core/elements/schemas.md",
    "content": "# Schemas\nSchemas are to USD what classes are to object orient programming. Let's explain schemas with that analogy in mind:\n\n- Schemas are templates that define default properties and methods. You can think of each prim in your hierarchy being an instance of a class. \n- Each prim must (or rather should, technically it is not enforced) have a type name set (see our [prim](./prim.md) section). The type name defines the primary class your prim is an instance of. To dynamically subclass your primary classes with additional classes, USD has the concept of API schemas. These then provide extra metadata/properties or methods that can manipulate your prim data.\n\n~~~admonish warning title=\"\"\nThe examples on this page only talk about how to apply/remove schemas and how to inspect them. In our [production](../../production/overview.md) and [Houdini](../../dcc/houdini/overview.md) section we'll look into the most used ones and run through some production examples.\n~~~\n\n# Table of Contents\n1. [API Overview In-A-Nutshell](#summary)\n2. [What should I use it for?](#usage)\n3. [Resources](#resources)\n4. [Overview](#overview)\n6. [Creating/Using schemas in your code](#schemasPracticalGuide)\n7. [Prim Definition](#schemasPrimDefinition)\n8. [Prim Type Info](#schemasPrimDefinition)\n9. [Schema Classes](#schemasClasses)\n    1. [Schema Registry](#schemasRegistry)\n    2. [Schema Kind](#schemasKind) \n\n## TL;DR - Metadata In-A-Nutshell <a name=\"summary\"></a>\n- Schemas are like classes in OOP that each prim in your hierarchy then instances. They provide properties (with fallback values) and metadata as well as methods (`Get<PropertName>`/`Set<PropertName>`/Utility functions) to manipulate your prim data.\n- There are two different base schema types (See the [overview](#overview) section for more info):\n    - **Typed Schemas**:\n        - Define prim type name (OOP: The main class of your prim), like `Cube`/`Mesh`/`Xform`\n        - Provide metadata/properties and methods to edit these\n        - Checkable via `prim.IsA(<SchemaClassName>)`\n    - **API Schemas (Class Naming Convention `<SchemaClassName>API`)**:\n        - Do not define prim type name (OOP: A subclass that inherits to your main class)\n        - Is divided in:\n            - **Non-Applied API schemas**:\n                - Add convenience methods to manipulate common prim data like properties and core metadata (like `kind`/`clips`).\n            - **Applied API schemas**:\n                - Supplement typed schemas by adding additional metadata/properties and methods to edit these\n                - Checkable via `prim.HasAPI(<SchemaClassName>)`\n- A prims composed schema definition can be accessed via `prim.GetPrimDefinition()`. This defines a prim's full type signature, similar to how you can inherit from multiple classes in OOP `class (<TypedSchemaClass>, <AppliedAPISchemaA>, <AppliedAPISchemaA>)`.\n- You can generate your own as described in our [plugin schemas](../plugins/schemas.md) section.\n\n## What should I use it for? <a name=\"usage\"></a>\n~~~admonish tip\nWe'll be using schema classes a lot in production, so we recommend familiarizing yourself with the below examples.\n\nThey are the main interface for your prims in the high level API that gives you getters/setters for all the standard properties that ship with Usd.\n\n```python\n{{#include ../../../../../code/core/elements.py:schemasOverview}}\n```\n\nThe schema classes then give you access to all of the schemas Get/Set methods and utility functions.\n~~~\n\n## Resources <a name=\"resources\"></a>\n- [API Docs](https://openusd.org/release/api/_usd__page__generating_schemas.html)\n- [Schema Registry](https://openusd.org/dev/api/class_usd_schema_registry.html)\n- [Generating a schema](https://openusd.org/release/tut_generating_new_schema.html)\n- [Prim Definition](https://openusd.org/dev/api/class_usd_prim_definition.html)\n- [Prim Type Info](https://openusd.org/dev/api/class_usd_prim_type_info.html)\n\n## Overview <a name=\"overview\"></a>\n\nHere is a flow chart of how the schema inheritance is setup:\n\n```mermaid\nflowchart TD\n    schemaBase([\"Usd.SchemaBase\"])\n    schemaTyped([\"Typed Schemas (Usd.Typed) | Checkable via prim.IsA()\"])\n    schemaTypedNonConcrete([\"Non-Concrete Schemas (Abstract Classes)\"]) \n    schemaTypedConcrete([\"Concrete Schemas (Define Prim Type Name)\"]) \n    schemaAPI([\"API Schemas (Usd.APISchemaBase )\"]) \n    schemaAPINonApplied([Non-Applied])\n    schemaAPIApplied([\"Applied | Checkable via prim.HasAPI()\"])\n    schemaAPIAppliedSingle([Single Applied])\n    schemaAPIAppliedMulti([Multi Applied])\n    style schemaTypedNonConcrete fill:#57ff5f\n    style schemaTypedConcrete fill:#63beff\n    style schemaAPINonApplied fill:#63beff\n    style schemaAPIAppliedSingle fill:#63beff\n    style schemaAPIAppliedMulti fill:#63beff\n\n    schemaBase --> schemaTyped \n    schemaTyped --> schemaTypedNonConcrete\n    schemaTypedNonConcrete --> schemaTypedConcrete\n    schemaBase --> schemaAPI\n    schemaAPI --> schemaAPINonApplied\n    schemaAPI --> schemaAPIApplied\n    schemaAPIApplied --> schemaAPIAppliedSingle\n    schemaAPIApplied --> schemaAPIAppliedMulti\n```\n\nAll the blue colored endpoints are the ones you'll set/apply/use via code, the green one you won't instantiate directly, but you can use it to check for inheritance.\n\n- `Typed Schemas (Usd.Typed)`:\n    - The base class for all schemas that define prim types, hence the name `Typed Schemas`\n    - Defines properties and metadata that is attached to prims that have this type.\n    - We can check if it is applied to a prim via `prim.IsA(<className>)`\n    - Accessible via `SchemaClass(prim)` e.g. `UsdGeom.Imageable(prim)` (Non-concrete), `UsdGeom.Xform(prim)`(concrete), to get access to the methods. To actually apply the schema, we have to set the type name as described below. Accessing a typed schema on a prim with a different type name will result in errors once you try to get/set data. To actually not guess what the typed Python class is we can run `prim.GetPrimTypeInfo().GetSchemaType().pythonClass(prim)`.\n- `Typed Schemas (Usd.Typed)` -> `Non-Concrete Schemas`:\n    - The non-concrete schemas are like abstract classes in OOP. They are schemas that concrete schemas can inherit from. The purpose of these is to define common properties/metadata that a certain type of typed schemas need. (For example lights all share a non-concrete schema for the essential properties.) \n    - Do not define a type name (hence non-concrete).\n- `Typed Schemas (Usd.Typed)` -> `Non-Concrete Schemas` -> `Concrete Schemas`:\n    - Defines a type name\n    - In OOP terms you can think of it as the primary base class that your prim is instancing.\n    - Applied via `Prim.SetTypeName(<typeName>)`/`PrimSpec.typeName=\"<typeName>\"`/`SchemaClass.Define(stage, Sdf.Path(\"/path\"))`\n\nHere is an example of the inheritance graph of the [UsdGeom.Imageable](https://openusd.org/dev/api/class_usd_geom_imageable.html) typed non-concrete schema:\n~~~admonish note title=\"Click to expand content\" collapsible=true\n![](../../../media/core/elements/schemasTypedNonConcreteUsdGeomImageable.jpg#center)\n~~~\n\n- `API Schemas (Usd.APISchemaBase)`\n    - The base class for all API Schemas, subclasses must end with `API`\n    - In OOP terms, API schemas are classes that your primary (typed) class can inherit from to gain access to convenience methods, but also additional metadata/properties.\n- `API Schemas (Usd.APISchemaBase)` -> `Non-Applied API Schemas`:\n    - Provide only methods to manipulate existing prim data like properties and core metadata (like `kind`/`clips`). Their common usage is to add convenience methods to manipulate common prim data.\n    - They do not define any metadata/properties. \n    - The schema name is not written to the `apiSchemas` metadata, it therefore does not contribute to the prim definition.\n    - Code: Applied via `SchemaClassAPI(prim)` e.g. `Usd.ClipsAPI(prim)`\n- `API Schemas (Usd.APISchemaBase)` -> `Applied API Schemas`:\n    - Adds additional metadata/properties to prim and provides methods to manipulate these.\n    - The schema name is added to the `apiSchemas` metadata, it contributes to the prim definition.\n    - We can check if it is applied to a prim via `prim.HasAPI(<APISchemaType>)`\n    - Applied via `SchemaClassAPI.Apply(prim)` e.g. `UsdGeom.ModelAPI.Apply(prim)`/`prim_spec.SetInfo(\"apiSchemas\", Sdf.TokenListOp.Create(prependedItems=[\"GeomModelAPI\"]))`\n- `API Schemas (Usd.APISchemaBase)` -> `Applied API Schemas` -> `Single Apply API Schemas`:\n    - Can only be applied once per prim\n- `API Schemas (Usd.APISchemaBase)` -> `Applied API Schemas` -> `Multi Apply API Schemas`:\n    - Can be applied multiple times with a different instance name, properties are namespaced with the instance name.\n\nIf you want to see a list of off the schema classes that ship with USD by default check out the [Usd.SchemaBase API docs](\nhttps://openusd.org/dev/api/class_usd_schema_base.html) page, it has a full inheritance diagram.\n\n~~~admonish tip\nAs covered in our [prim](./prim.md#schemas) section, Usd has a PrimDefinition/PrimTypeInfo classes we can use to inspect all properties and metadata given through applied and typed schemas on a given prim. This prim definition/type info carry the full type signature of a given prim.\n~~~\n\n\n## Creating/Using schemas in production <a name=\"schemasPracticalGuide\"></a>\n\nLet's first look at typed schemas:\n\n~~~admonish tip title=\"Pro Tip | Find class from type name\"\nTo get the class from the prim, we can run:\n```python\n# From type name\nprim_type_name = prim.GetTypeName()\nprim_typed_schema = Usd.SchemaRegistry.GetTypeFromName(prim_type_name).pythonClass(prim)\n# From prim type info\nprim_typed_schema = prim.GetPrimTypeInfo().GetSchemaType().pythonClass(prim)\n```\nThis way we don't have to find and import the right class ourselves.\n~~~\n\nTo summarize the below code:\n\n~~~admonish tip title=\"Pro Tip | Best practices how to apply schemas\"\n```python\n{{#include ../../../../../code/core/elements.py:schemasOverview}}\n```\n~~~\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:schemasTyped}}\n```\n~~~\n\n~~~admonish important\nThe 'IsA' check is a very valuable check to see if something is an instance of a (base) class. It is similar to Python's isinstance method.\n~~~\n\nAnd the API schemas:\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:schemasAPI}}\n```\n~~~\n\n## Prim Definition <a name=\"schemasPrimDefinition\"></a>\nWith the [prim definition](https://openusd.org/dev/api/class_usd_prim_definition.html) we can inspect what the schemas provide. Basically you are inspecting the class (as to the prim being the instance, if we compare it to OOP paradigms).\nIn production, you won't be using this a lot, it is good to be aware of it though. If you change things here, you are actually on run-time modifying the base class, which might cause some weird issues.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:dataContainerPrimTypeDefinition}}\n```\n~~~\n\n## Prim Type Info <a name=\"schemasPrimTypeInfo\"></a>\nThe [prim type info](https://openusd.org/dev/api/class_usd_prim_type_info.html) holds the composed type info of a prim. You can think of it as as the class that answers Python `type()` like queries for Usd. It caches the results of type name and applied API schema names, so that `prim.IsA(<typeName>)` checks can be used to see if the prim matches a given type.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:dataContainerPrimTypeInfo}}\n```\n~~~\n\n## Schema Classes <a name=\"schemasClasses\"></a>\nWe can lookup all registered schemas via the plugin registry as well as find out what plugin provided a schema.\n\nBefore we do that let's clarify some terminology:\n- `Schema Type Name`: The name of the schema class, e.g. `Cube`, `Imageable`, `SkelBindingAPI`\n- `Tf.Type.typeName` registry name: The full registered type name `UsdGeomCube`, `UsdGeomImageable`, `UsdSkelBindingAPI`\n\nWe can map from `schema type name` to `Tf.Type.typeName` via:\n```python\nregistry = Usd.SchemaRegistry()\nregistry.GetTypeFromName(\"Cube\").typeName # Returns: \"UsdGeomCube\"\n```\nWe can map from `Tf.Type.typeName` to `schema type name` via:\n```python\nregistry = Usd.SchemaRegistry()\nregistry.GetSchemaTypeName(\"UsdGeomCube\") # Returns: \"Cube\"\n```\n\n### Schema Registry <a name=\"schemasRegistry\"></a>\n\nLet's list all the schemas:\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:schemasPluginRegistry}}\n```\n~~~\n\nThis allows us to also look up the Tf.Type from schema (type) names, \nwhich we can then use in `IsA()` checks.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:schemasRegistry}}\n```\n~~~\n\nA practical use case of looking thru the registry, is that we can grab the prim definitions. We can use these to inspect what properties a schema creates. We can use this to for example builds UIs that list all the schema attributes.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:schemasRegistryToPrimDefinition}}\n```\n~~~\n\n### Schema Kind <a name=\"schemasKind\"></a>\n\nWe can also inspect the schema kind. The kind defines (if we look at our inheritance tree in [overview](#overview)) what kind of schema it is.\n\nThe kind can be one of:\n- Usd.SchemaKind.AbstractBase\n- Usd.SchemaKind.AbstractTyped\n- Usd.SchemaKind.ConcreteTyped\n- Usd.SchemaKind.NonAppliedAPI\n- Usd.SchemaKind.SingleApplyAPI\n- Usd.SchemaKind.MultipleApplyAPI\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:schemasKind}}\n```\n~~~\n"
  },
  {
    "path": "docs/src/pages/core/elements/standalone_utilities.md",
    "content": "# Standalone Utilities\nUsd ships with a small set of commandline utilities. Below you find a short summary of the most important ones:\n\n## TL;DR - Commandline Utilites In-A-Nutshell\n~~~admonish tip\nThe following are a must have for anyone using Usd in production:\n- [usdmanager](http://www.usdmanager.org/): Your go-to Usd ascii editing app\n- [usdview](http://www.usdmanager.org/): Your go-to standalone Usd 3d viewing/debugging app\n    - [TheGrill/Grill](https://github.com/thegrill/grill): A Usd View plugin to view composition arcs\n~~~\n\n## Resources\n- [Commandline Utilities](https://openusd.org/release/toolset.html)\n- External Tools:\n    - [usdmanager](http://www.usdmanager.org/): A Usd ascii editing app\n    - [TheGrill/Grill](https://github.com/thegrill/grill): A Usd View plugin to view composition arcs\n\n## Overview\nThe most notable ones are:\n- [usdstitch](https://openusd.org/release/toolset.html#usdstitch): Combine multiple files into a single file. This combines the data, with the first file getting the highest strength and so forth. A typical use case is when you are exporting a layer per frame from a DCC and then need to combine it to a single file.\n- [usdstitchclips](https://openusd.org/release/toolset.html#usdstitchclips): Create a file that links to multiple files for a certain time range (for example per frame). Unlike 'usdstitch' this does not combine the data, instead it creates a file (and few sidecar files to increase data lookup performance) that has a mapping what file to load per frame/a certain time range.\n- [usddiff](https://openusd.org/release/toolset.html#usddiff): Opens the diff editor of your choice with the difference between two .usd files. This is super useful to debug for example render .usd files with huge hierarchies, where a visual 3d diff is to expensive or where looking for a specific attribute would take to long, because you don't know where to start.\n- [usdGenSchema](https://openusd.org/release/api/_usd__page__generating_schemas.html): This commandline tool helps us generate our own schemas (Usd speak for classes) without having to code them ourselves in C++. Head over to our [schema](../plugins/schemas.md) section for a hands on example.\n- [usdrecord](https://openusd.org/release/toolset.html#usdrecord): A simple hydra to OpenGL proof of concept implementation. If you are interested in the the high level render API, this is good starting point to get a simple overview. \n- [usdview](https://openusd.org/release/toolset.html#usdview): A 3d viewer for Usd stages. If you are interested in the high level render API of Usd/Hydra, feel free to dive into the source code, as the Usd View exposes 99% of the functionality of the high level api. It is a great 'example' to learn and a good starting point if you want to integrate it into your apps with a handful of Qt widgets ready to use.\n\nMost of these tools actually are small python scripts, so you can dive in and inspect them!\n\nThere are also a few very useful tools from external vendors:\n- [usdmanager](http://www.usdmanager.org/): A Usd text editor from DreamWorksAnimation that allows you to interactively browse your Usd files. This is a must have of anyone using Usd!\n- [TheGrill/Grill](https://github.com/thegrill/grill): A super useful Usd View plugin that allows you to visualize the layer stack/composition arcs. A must have when trying to debug complicated value resolution issues. For a visual overview check out this [link](https://grill.readthedocs.io/en/latest/views.html).\n\n\n"
  },
  {
    "path": "docs/src/pages/core/elements/transform.md",
    "content": "# Transforms\n~~~admonish question title=\"Still under construction!\"\nThis section still needs some more love, we'll likely expand it more in the near future.\n~~~\n\n# Table of Contents\n1. [Transforms In-A-Nutshell](#summary)\n1. [What should I use it for?](#usage)\n1. [Resources](#resources)\n1. [Overview](#overview)\n    1. [Creating and animating transforms](#xformCreate)\n    2. [Ignoring parent transforms by resetting the xform stack](#xformResetXformStack)\n    1. [Querying transforms](#xformQuery)\n1. [Transforms in production](#xformProduction):\n    1. [Merging hierarchy transforms](#xformWorldSpaceToLocalSpace)\n    1. [Baking transforms for constraint like behaviour](#xformBake)\n    1. [Reading Xforms in Shaders](xformCoordinate)\n\n## TL;DR - Transforms In-A-Nutshell <a name=\"summary\"></a>\nTransforms are encoded via the following naming scheme and attributes:\n- **xformOpOrder**: This (non-animatable) attribute controls what **xformOp:** namespaced attributes affect the prims local space transform.\n- **xfromOp:**: Xform ops are namespaced with this namespace and can be considered by the \"xformOpOrder\" attribute. We can add any number of xform ops for xformable prims, the final world transform is then computed based on a prims local transform and that of all its ancestors.\n\n## What should I use it for? <a name=\"usage\"></a>\n~~~admonish tip\nWe rarely write the initial transforms ourselves, this is something our DCCs excel at. We do query transforms though for different scenarios:\n- We can bake down the transform to a single prim. This can then be referenced or inherited and used as a parent constraint like mechanism.\n- When merging hierarchies, we often want to preserve the world transform of leaf prims. Let's say we have two stages: We can simply get the parent xform of stage A and then apply it in inverse to our leaf prim in stage B. That way the leaf prim in stage B is now in local space and merging the stages returns the expected result. We show an example of this below.\n~~~\n\n## Resources <a name=\"resources\"></a>\n- [UsdGeom Xforms](https://openusd.org/dev/api/usd_geom_page_front.html)\n- [UsdGeom.Xformable](https://openusd.org/dev/api/class_usd_geom_xformable.html)\n- [UsdGeom.XformCommonAPI](https://openusd.org/dev/api/class_usd_geom_xform_common_a_p_i.html)\n\n## Overview <a name=\"overview\"></a>\nCreating xforms is usually handled by our DCCS. Let's go over the basics how USD encodes them to understand what we are working with.\n\nAll shown examples can be found in the [xforms .hip file](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/tree/main/files/dcc/houdini/transforms) in our GitHub repo.\n\n### Creating and animating transforms <a name=\"xformCreate\"></a>\nUSD evaluates xform attributes on all sub types of the xformable schema.\n\n![Usd Xformable](../../../media/core/elements/xformXformableClassInheritance.jpg)\n\nTransforms are encoded via the following naming scheme and attributes:\n- **xformOpOrder**: This (non-animatable) attribute controls what **xformOp:** namespaced attributes affect the prims local space transform.\n- **xfromOp:**: Xform ops are namespaced with this namespace and can be considered by the \"xformOpOrder\" attribute.\n    - We can add any number of xform ops to xformable prims.\n    - Any xform op can be suffixed with a custom name, e.g. xformOp:translate:myCoolTranslate\n    - Available xform Ops are:\n        - xformOp:translate\n        - xformOp:orient\n        - xformOp:rotateXYZ, xformOp:rotateXZY, xformOp:rotateYXZ, xformOp:rotateYZX, xformOp:rotateZXY, xformOp:rotateZYX\n        - xformOp:rotateX, xformOp:rotateY, xformOp:rotateZ\n        - xformOp:scale\n        - xformOp:transform\n\nThe final world transform is computed based on a prims local transform and that of all its ancestors.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:xformXformableOverview}}\n```\n~~~\n\nHere is the snippet in action:\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/core/elements/xformCreation.mp4\" type=\"video/mp4\" alt=\"Houdini Xform Creation\">\n</video>\n\n### Ignoring parent transforms by resetting the xform stack <a name=\"xformResetXformStack\"></a>\nWe can also set the special '!resetXformStack!' value in our \"xformOpOrder\" attribute to reset the transform stack. This means all parent transforms will be ignored, as well as any attribute before the '!resetXformStack!' in the xformOp order list.\n\n~~~admonish danger title=\"\"\nResetting the xform stack is often not the right way to go, as we loose any parent hierarchy updates. We also have to make sure that we write our reset-ed xform with the correct sub-frame time samples, so that motion blur works correctly.\n\nThis should only be used as a last resort to enforce a prim to have a specific transform. We should rather re-write leaf prim xform in local space, see [Merging hierarchy transforms](#xformWorldSpaceToLocalSpace) for more info.\n~~~\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:xformResetXformStack}}\n```\n~~~\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/core/elements/xformResetXformStack.mp4\" type=\"video/mp4\" alt=\"Houdini Xform Stack Reset\">\n</video>\n\n### Querying transforms<a name=\"xformQuery\"></a>\nWe can query xforms via `UsdGeom.Xformable` API or via the `UsdGeom.XformCache` cache.\n\nThe preferred way should always be the xform cache, as it re-uses ancestor xforms in its cache, when querying nested xforms. Only when querying a single leaf transform, we should go with the Xformable API.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:xformCache}}\n```\n~~~\n\n## Transforms in production <a name=\"xformProduction\"></a>\nLet's have a look at some production related xform setups.\n\n### Merging hierarchy transforms <a name=\"xformWorldSpaceLocalSpace\"></a>\nIn production we often need to merge different layers with different transforms at different hierarchy levels. For example when we have a cache in world space and we want to merge it into an existing hierarchy.\n\nHere's how we can achieve that (This example is a bit abstract, we'll add something more visual in the near future).\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:xformWorldSpaceLocalSpace}}\n```\n~~~\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/core/elements/xformWorldSpaceLocalSpace.mp4\" type=\"video/mp4\" alt=\"Houdini Xform Localize Xform\">\n</video>\n\n### Baking transforms for constraint like behavior <a name=\"xformBake\"></a>\nIf we want a parent constraint like behavior, we have to bake down the transform to a single prim. We can then inherit/internal reference/specialize this xform to \"parent constrain\" something.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:xformBake}}\n```\n~~~\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/core/elements/xformBake.mp4\" type=\"video/mp4\" alt=\"Houdini Xform Localize Xform\">\n</video>\n\n\n### Reading Xforms in Shaders <a name=\"xformCoordinate\"></a>\n~~~admonish question title=\"Still under construction!\"\nWe'll add code examples in the future.\n~~~\n\nTo read composed xforms in shaders, USD ships with the [Coordinate Systems](https://openusd.org/release/wp_coordsys.html) mechanism.\n\nIt allows us to add a relationship on prims, that targets to an xform prim. This xform can then be queried in shaders e.g. for projections or other transform related needs. \n\nSee these links for more information:\n[UsdShade.CoordSys](https://openusd.org/dev/api/class_usd_shade_coord_sys_a_p_i.html)\n[Houdini CoordSys in Shaders](https://www.sidefx.com/docs/houdini/nodes/lop/coordsys.html)\n"
  },
  {
    "path": "docs/src/pages/core/glossary.md",
    "content": "# Vocabulary Cheatsheet\n\n| USD Terminology                       | Meaning                                  |\n|---------------------------------------|------------------------------------------|\n| property                              | Parent class of attribute/relationship |\n| prim                                  | Container for your properties |\n| layer                                 | Container for storing your prims and properties |\n| stage                                 | A view of a set of composed layers |\n| compose                               | Load a layer or another part of a hierarchy via a composition arc |\n| author                                | Explicitly written value for a property/metadata entry (rather than it coming from a schema fallback) |\n| Value Resolution Source               | What layer(s) has the winning priority out of all your layers where the data can be loaded from |\n"
  },
  {
    "path": "docs/src/pages/core/overview.md",
    "content": "# USD Essentials\nIn our essentials section, we cover the basics of USD from a software developer perspective.\n\nThat means we go over the most common base classes we'll interacting with in our day-to-day work.\n\nOur approach is to start by looking at the smallest elements in USD and increasing complexity until we talk about how different broader aspects/concepts of USD work together.\n\nThat does mean we do **not** provide a high level overview. As mentioned in our [motivation](../introduction/motivation.md) section, this guide is conceptualized to be an onboarding guide for developers. We therefore take a very code heavy and deep dive approach from the get-go.\n\nDon't be scared though! We try to stay as \"generic\" as possible, avoiding USD's own terminology where possible.\n\nAre you ready to dive into the wonderful world of USD? Then let's get started!"
  },
  {
    "path": "docs/src/pages/core/plugins/assetresolver.md",
    "content": "# Asset Resolver\nThe [Asset Resolver](https://openusd.org/dev/api/ar_page_front.html) is one of those core Usd topics you have to face eventually and can't get around if you plan on using Usd in production. To summarize its functionality in a simple diagram:\n~~~admonish tip title=\"\"\n```mermaid\nflowchart LR\n    assetIdentifier([\"@Asset Identifier@\"]) --> assetResolver([Asset Resolver])\n    assetResolver --> assetResolvedPath([Resolved Asset Path])\n```\n~~~\nYou can kind of think of your asset resolver as a little black box that takes an input path, processes it and spits out a file path/URI that can be opened as a file/streamed data from. It allows you to hook into Usd's file path lookups in order to redirect where the actual file is or to pin an asset identifier to an older version. This is probably the most common use case in VFX pipelines, as when rendering on the farm, you want your Usd stage to be in the exact same state as in your live scene.\n\nIn Usd itself, asset paths are separated from normal strings so that they can be identified as something that has to run through the resolver. In the Usd file, you'll see the `@assset_identifier@` syntax:\n~~~admonish tip title=\"\"\n```python\ndef \"bicycle\" (\n    assetInfo = {\n        dictionary UsdSurvivalGuide = {\n            asset Asset = @assetMetadata@\n            asset[] AssetDependencyPaths = [@dependencyPathA@, @dependencyPathB@]\n        }\n    }\n    prepend references = @/opt/hfs19.5/houdini/usd/assets/pig/pig.usd@\n){\n    custom asset Asset = @someAsset@\n    custom asset[] AssetArray = [@someAssetA@, @someAssetB@]\n}\n\n```\n~~~\n\nAll file based composition arcs use [asset paths](hhttps://openusd.org/dev/api/class_sdf_asset_path.html) as well as any metadata (especially `assetInfo`) and any (custom) attributes of type `Asset`/`AssetArray`. In Usd files the naming convention for asset paths is `Asset`, in the API it is `pxr.Sdf.AssetPath`. So any time you see the `@...@` syntax, just remember it is an asset path.\n\nAn important thing to note is that asset resolvers only go in one direction (at least in the Usd API): From asset identifier to resolved asset path. I assume this is because you can have multiple asset identifiers that point the the same resolved asset path. Depending on your asset resolver implementation, you can also make it bidirectional.\n\n# Table of Contents\n1. [Asset Resolvers In-A-Nutshell](#summary)\n1. [What should I use it for?](#usage)\n1. [Resources](#resources)\n1. [Asset Resolver](#assetResolver)\n1. [Asset Resolver Contexts](#assetResolverContext)\n1. [Common Resolver Code Examples](#assetResolverAPI)\n    1. [Initialization](#assetResolverAPIInitialization)\n    1. [Scoped resolver caches](#assetResolverAPIScopedResolverCaches)\n    1. [Creating/Opening a stage with a resolver context](#assetResolverAPIStageContext)\n    1. [Resolving a path with a given bound context](#assetResolverAPIContextResolve)\n    1. [Asset Paths vs Resolved Paths](#assetResolverAPIAssetPathVsResolvedPaths)\n\n## TL;DR - Asset Resolvers In-A-Nutshell <a name=\"summary\"></a>\nAsset resolvers resolve asset identifiers (encoded in Usd with the `@...@` syntax) to loadable file paths/URIs.\n~~~admonish tip title=\"\"\n```mermaid\nflowchart LR\n    assetIdentifier([\"@Asset Identifier@\"]) --> assetResolver([Asset Resolver])\n    assetResolver --> assetResolvedPath([Resolved Asset Path])\n    assetResolverContext([Asset Resolver Context]) --> assetResolver  \n```\n~~~\nIt is Usd's abstraction of where to pull the actual data from and offers you the possibility to add custom pinning or data source redirection mechanisms. To guide the resolver, Usd adds the option of passing in an `Asset Resolver Context`, which is just a very simple class (with pretty much no methods you need to re-implement), that your resolver can use to aid resolution.\n\nContexts are handled per stage: They are optionally given on stage open and can also be shared between stages. If you do not provide a context, your resolver will provide a default fallback context.\n\nTo resolve an asset identifier you can call:\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:assetResolverStageContextResolve}}\n```\n~~~\nIf you don't want to use any context you can call:\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:assetResolverResolve}}\n```\n~~~\n\nOne important thing to not confuse is the `Ar.ResolvedPath` and the `Sdf.AssetPath` classes.\nThe `Sdf.AssetPath` is the class you instantiate when you set any asset path related field/property/composition arc when writing to your layer/stage. It does not resolve anything, it only has dummy properties which just reflect what you pass to the constructor.\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:assetResolverAssetPath}}\n```\n~~~\n\nTo soften the blow on the steep asset resolver implementation learning curve we provide production ready asset resolvers here in our [GitHub Repository](https://github.com/LucaScheller/VFX-UsdAssetResolver).\nThese include:\n- A fully functional file based resolver with pinning support and on runtime modification.\n- A fully functional python based resolver with feature parity to the file resolver, that you can use to debug/prototype your resolver. This might be enough for very small studios, who don't access thousands of assets.\n- A hybrid pre-cached python resolver is in the works, keep an eye on this repo for updates.\n\nThis should help you get up and running (or at least protoype easily and possibly outsource the C++ implementation if you need a lot of customization).\n\n~~~admonish danger\nCurrently the asset resolvers only ship with instructions for compiling against Houdini on Linux. It is on the roadmap to include Windows instructions as well as to create a build pipeline via GitHub, so that you don't necessarily have to self compile it. We'll keep you posted :)\n~~~\n\nAll the implementation details and examples can be found in the below resources links. We separated it from these docs, as it is a big enough topic on its own.\n\n~~~admonish important title=\"Compiling against USD\"\nMost DCCs ship with a customized USD build, where most vendors adhere to the [VFX Reference Platform](https://vfxplatform.com/) and only change USD with major version software releases. They do backport important production patches though from time to time. That's why we recommend using the USD build from the DCC instead of trying to self compile and link it to the DCC, as this guarantees the most stability. This does mean though, that you have to compile all plugins against each (major version) releases of each individual DCC.\n~~~\n\n## What should I use it for? <a name=\"usage\"></a>\n~~~admonish tip\nWe'll be using the asset resolver to redirect file paths for different reasons, mainly:\n- Pinning: As USD pipelines are often based on \"the latest asset/shot gets automatically refreshed/loaded\" principle, we use the asset resolver to pin a USD stage to a specific version/state, so that it doesn't receive any asset/shot updates anymore.\n- Redirecting the path from a custom identifier to an actual data resource. You'll only be using this aspect, if your resolver is not file based and instead URI (`myCustomURIPrefix:<identifier>`) based.\n~~~\n\n## Resources <a name=\"resources\"></a>\n- [Asset Resolver API Docs](https://openusd.org/dev/api/class_ar_resolver.html)\n- [Asset Resolver Context API Docs](https://openusd.org/dev/api/class_ar_resolver_context.html)\n- [Usd Asset Resolver - Reference Implementations - GitHub Repository](https://github.com/LucaScheller/VFX-UsdAssetResolver)\n- [Usd Asset Resolver - Reference Implementations - Documentation](https://lucascheller.github.io/VFX-UsdAssetResolver/)\n\n## Asset Resolver <a name=\"assetResolver\"></a>\nYou can register multiple asset resolvers via the plugin system:\n- There must be one primary resolver that is not URI based. As a fallback the default resolver will be used\n- Any number of URI based resolvers: These resolvers will be called when they find a path prefixed with the scheme name syntax `\"<scheme>:...\"` for example `http://usdSurvivalGuide/assets/bicycle.usd`)\n\nHere is an example for a primary resolver plugin .json file:\n~~~admonish note title=\"To see the file click here\" collapsible=true\n```json\n{\n    \"Plugins\": [\n        {\n            \"Info\": {\n                \"Types\": {\n                    \"MyPrimaryResolver\": {\n                        \"bases\": [\"ArResolver\"],\n                        \"implementsContexts\" : true\n                    }\n                }\n            },\n            \"LibraryPath\": \"../lib/myPrimaryResolver.so\",\n            \"Name\": \"myPrimaryResolver\",\n            \"Root\": \".\",\n            \"Type\": \"library\"\n        }\n    ]\n}\n```\n~~~\n\nAnd an example for a URI resolver plugin .json file:\n~~~admonish note title=\"To see the file click here\" collapsible=true\n```json\n{\n    \"Plugins\": [\n        {\n            \"Info\": {\n                \"Types\": {\n                    \"HybridResolver\": {\n                        \"bases\": [\"MyUriResolver\"],\n                        \"implementsContexts\" : true\n                    }\n                }\n            },\n            \"LibraryPath\": \"../lib/myUriResolver.so\",\n            \"Name\": \"myUriResolver\",\n            \"Root\": \".\",\n            \"Type\": \"library\"\n        }\n    ]\n}\n```\n~~~\n\nThe Usd files save the asset identifiers with the `@someString@` syntax. Depending on the resolver context, these identifiers might resolve to different \npaths. This allows us to save the pinned state of a Usd file. For example if we have an asset path `@assets/bicycle@` we might resolve it to  `@/server/assets/bicycle/bicycle_latest.usd@` which points to a symlink of the latest bicycle USD file. Once we submit a rendering, we usually want to pin the whole Usd file to the state it is actively being viewed in. To do that we collect all asset paths and then store their current mapping. This way we can then map the bicycle to the active version by storing `@assets/bicycle@` -> `@/server/assets/bicycle/bicycle_v003.usd@` in our resolver context.\n~~~admonish danger\nAn asset identifier can be a string with any characters except `[]` brackets, as these are used for reading .usdz package files.\n~~~\n\n## Asset Resolver Contexts <a name=\"assetResolverContext\"></a>\nTo assist the resolver with processing asset paths, Usd adds the option of passing in an `Asset Resolver Context`. The context is just a very simple class, that your resolver can use to aid path resolution. A simple context only needs to implement:\n```\n- Default and copy constructors\n- < and == operators\n- hash_value\n```\nThe rest is up to you to implement and Python expose. \n\nContexts are handled per stage: They are optionally given on stage open and can also be shared between stages. If you do not provide a context, your resolver will provide a default fallback context. You can not change the context without re-opening the stage, but you can implement methods to modify the active stages and then signal a change notification to the stages. The resolvers listed above implement different methods to modify the mapping pairs. Are refresh can be called as follows:\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:assetResolverContextRefresh}}\n```\n~~~\n\nAs you can see the ```stage.GetPathResolverContext()``` actually returns a list and not a single resolver context. This is because there can be multiple resolvers running at the same time. As stated above a single primary resolver and multiple URI-resolvers, you therefore have a resolver context per resolver.\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:assetResolverContextAccess}}\n```\n~~~\n\n~~~admonish warning title=\"Resolver Contexts Per Resolver in C++\"\nThere can only be a single resolver context object instance of the same class in the resolver context. Usually each resolver ships with its own context class, if the resolver tries to create another instance of the resolver context, it will be ignored when trying to add it the the bound context list.\nThis is nothing you have to worry about in Python, we'd just thought we'd mention it here \nfor completeness, as it can cause some head-scratching when coding a resolver.\n~~~\n\n~~~admonish warning title=\"Refresh Resolver Contexts in Python\"\nWhen implementing the context in C++, make sure that the internal data is accessed via a shared pointer as Usd currently creates resolver context copies when exposed via Python\ninstead of passing thru the pointer. Otherwise calling ```ArNotice::ResolverChanged(*ctx).Send();``` won't work!\nSee for more info: [Usd Interest Forum Thread](https://groups.google.com/g/usd-interest/c/9JrXGGbzBnQ/m/_f3oaqBdAwAJ)\n~~~\n\n\n## Common Resolver Code Examples <a name=\"assetResolverAPI\"></a>\nLet's look at some practical examples that you'll use in the day to day work, we'll discuss Houdini specifics in the Houdini section of this guide:\n\n#### Initialization <a name=\"assetResolverAPIInitialization\"></a>\nTo see if your resolver is being loaded you can set the `TF_DEBUG` environment variable to `AR_RESOLVER_INIT`:\n~~~admonish tip title=\"\"\n```bash\nexport TF_DEBUG=AR_RESOLVER_INIT\n```\n~~~\nThis will log the following to stdout if you use our FileResolver:\n\n~~~admonish tip title=\"\"\n```\nArGetResolver(): Using asset resolver FileResolver from plugin ../dist/fileResolver/lib/fileResolver.so for primary resolver\nArGetResolver(): Found URI resolver ArDefaultResolver\nArGetResolver(): Found URI resolver FS_ArResolver\nArGetResolver(): Using FS_ArResolver for URI scheme(s) [\"op\", \"opdef\", \"oplib\", \"opdatablock\"]\nArGetResolver(): Found URI resolver FileResolver\nArGetResolver(): Found package resolver USD_NcPackageResolver\nArGetResolver(): Using package resolver USD_NcPackageResolver for usdlc from plugin usdNc\nArGetResolver(): Using package resolver USD_NcPackageResolver for usdnc from plugin usdNc\nArGetResolver(): Found package resolver Usd_UsdzResolver\nArGetResolver(): Using package resolver Usd_UsdzResolver for usdz from plugin usd\n```\n~~~\n\nFor more information about debugging, check out our [Debugging & Performance Profiling](../profiling/overview.md) section.\n\nTo check what the active primary resolver is, you can also run:\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:assetResolverBound}}\n```\n~~~\nIt is important that you import the Python module of your resolver first, otherwise you won't get your Python object when calling `Ar.GetUnderlyingResolver()`.\n\n#### Scoped resolver caches <a name=\"assetResolverAPIScopedResolverCaches\"></a>\nTo ensure that we always get the same resolved paths, you can use a scoped resolver cache. When working in DCCs, you don't have to worry about this as the DCC should handle this for you.\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:assetResolverScopedCache}}\n```\n~~~\n\n#### Creating/Opening a stage with a resolver context <a name=\"assetResolverAPIStageContext\"></a>\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:assetResolverContextCreation}}\n```\n~~~\n\n#### Resolving a path with a given bound context <a name=\"assetResolverAPIContextResolve\"></a>\nThis is probably most used resolved method you'll use. It resolves the asset identifier using the active stage's context.\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:assetResolverStageContextResolve}}\n```\n~~~\n\nIf you don't want to use any context you can call:\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:assetResolverResolve}}\n```\n~~~\n\n#### Asset Paths vs Resolved Paths <a name=\"assetResolverAPIAssetPathVsResolvedPaths\"></a>\nOne important thing to not confuse is the `Ar.ResolvedPath` and the `Sdf.AssetPath` classes.\nThe `Sdf.AssetPath` is the class you instantiate when you set any asset path related field/property/composition arc when writing to your layer/stage. It does not resolve anything, it only has dummy properties which just reflect what you pass to the constructor.\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:assetResolverAssetPath}}\n```\n~~~\n\n\n"
  },
  {
    "path": "docs/src/pages/core/plugins/kind.md",
    "content": "# Kinds\nThe [kind](https://openusd.org/release/glossary.html#usdglossary-kind) metadata is a special metadata entry on prims that can be written  to mark prims with data what \"hierarchy level type\" it is. This way we can quickly traverse and select parts of the hierarchy that are of interest to us, without traversing into every child prim. The most common types are `component` and `group`. We use these (or sub-kinds) of these to make our stage more easily browse-able, so that we can visually/programmatically easily detect where assets start.\n\n# Table of Contents\n1. [Kinds In-A-Nutshell](#summary)\n1. [What should I use it for?](#usage)\n1. [Resources](#resources)\n1. [Overview](#overview)\n    1. [Reading and Writing Kinds](#kindAuthoring)\n    1. [Kind Registry](#kindRegistry)\n    1. [Kind IsA Checks/Travesal](#kindTraversal)\n\n## TL;DR - Kinds In-A-Nutshell <a name=\"summary\"></a>\n~~~admonish tip\nThe kind metadata is mainly used to for two things:\n- Traversal: You can quickly detect (and stop traversal to children) where the assets are in your hierarchy by marking them as a a `model` subtype like `component`. A typical use case would be \"find me all `fx` assets\": In your pipeline you would define a 'fx' model kind subtype and then you can traverse for all prims that have the 'fx' kind set.\n- DCCs use this to drive user selection in UIs. This way we can quickly select non-leaf prims that are of interest. For example to transform an asset in the hierarchy, we only want to select the asset root prim and not its children, so we can tell our DCC to select only `model` kind prims. This will limit the selection to all sub-kinds of `model`.\n~~~\n~~~admonish tip title=\"Pro Tip | Houdini Kind Icons\"\nIf you have created custom kinds, you can place icons (png/svg) in your `$HOUDINI_PATH/config/Icons/SCENEGRAPH_kind_<name>.<ext>` folder and they will be shown in your scene graph tree panel.\n~~~\n\n## What should I use it for? <a name=\"usage\"></a>\n~~~admonish tip\nIn production, you'll use kinds as a way to filter prims when looking for data. As kind data is written in prim metadata, it is very fast to access and suited for high performance queries/traversals. For more info on traversals, take a look at the [traversal]() section.\n~~~\n~~~admonish important\nYou should always tag all prims in the hierarchy with kinds at least to the asset level. Some Usd methods as well as DCCs will otherwise not traverse into the child hierarchy of a prim if they come across a prim without a kind being set.\nSo this means you should have at least `group` kind metadata set for all parent prims of `model` sub-kind prims.\n~~~\n\n## Resources\n- [Kind Glossary Definition](https://openusd.org/release/glossary.html#usdglossary-kind)\n- [Extending Kinds](https://openusd.org/dev/api/kind_page_front.html#kind_extensions)\n- [Kind Registry](https://openusd.org/dev/api/class_kind_registry.html) \n\n## Overview <a name=\"overview\"></a>\nUsd ships with these kinds by default, to register your own kinds, see the below examples for more details:\n- `model`: The base kind for all model kinds, don't use it directly.\n    - `group`: A group of model prims.\n        - `assembly`: A collection of model prims, typically used for sets/a assembled collection of models or environments.\n    - `component`: A sub-kind of 'model' that has no other child prims of type 'model'\n- `subcomponent`: An important subhierarchy of an component.\n\n\n~~~admonish important\nYou should always tag all prims with kinds at least to the asset level in the hierarchy. Some DCCs will otherwise not traverse into the hierarchy if they come across a prim without a hierarchy.\nSo this means you should have `group` kinds set for all parent prims of `model` prims.\n~~~\n\n### Reading and Writing Kinds <a name=\"kindAuthoring\"></a>\nKinds can be easily set via the high and low level APIs:\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:dataContainerPrimBasicsKinds}}\n```\n~~~\n\nAn example Usd file could look likes this\n~~~admonish info title=\"\"\n```python\ndef Xform \"set\" (\n    kind = \"set\"\n)\n{\n    def Xform \"garage\" (\n        kind = \"group\"\n    )\n    {\n        def Xform \"bicycle\" (\n            kind = \"prop\"\n        )\n        {\n        }\n    }\n\n    def Xform \"yard\" (\n        kind = \"group\"\n    )\n    {\n        def Xform \"explosion\" (\n            kind = \"fx\"\n        )\n        {\n        }\n    }\n}\n```\n~~~\n\n### Creating own kinds <a name=\"kindPlugin\"></a>\nWe can register kinds via the [plugin system](./overview.md).\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../files/plugins/kinds/plugInfo.json}}\n```\n~~~\n\nTo register the above kinds, copy the contents into a file called `plugInfo.json`. Then set your `PXR_PLUGINPATH_NAME` environment variable to the folder containing the `plugInfo.json` file.\n\nFor Linux this can be done for the active shell as follows:\n```bash\nexport PXR_PLUGINPATH_NAME=/my/cool/plugin/resources:${PXR_PLUGINPATH_NAME}\n```\n\nIf you downloaded this repo, we provide an example kind plugin [here](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/tree/main/files/plugins/kinds). All you need to do is point the environment variable there and launch a USD capable application.\n\n### Kind Registry <a name=\"kindRegistry\"></a>\nWe can also check if a plugin with kind data was registered via Python.\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:kindRegistry}}\n```\n~~~\n\n### Kind IsA Checks & Traversal <a name=\"kindTraversal\"></a>\nWe can then also use our custom kinds for traversal checks.\nUsd offers the `prim.IsModel` and `prim.IsGroup` checks as convenience methods to check if a kind is a sub-kind of the base kinds.\n\n~~~admonish important\nMake sure that your whole hierarchy has kinds defined (to the prim you want to search for), otherwise your `prim.IsModel` and `prim.IsGroup` checks will fail. This also affects how DCCs implement traversal: For example when using Houdini's LOPs selection rules with the `%kind:component` syntax, the selection rule will not traverse into the prim children and will stop at the parent prim without a kind. Manually checking via `registry.IsA(prim.GetKind(), \"component\")` still works though, as this does not include the parents in the check. (See examples below)\n#ToDo Add icon\n~~~\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:kindTraversal}}\n```\n~~~"
  },
  {
    "path": "docs/src/pages/core/plugins/metadata.md",
    "content": "# Metadata\nUSD allows us to extend the base metadata that is attached to every layer, prim and property (Supported are `Sdf.Layer` and subclasses of `Sdf.Spec`). This allows us to write custom fields with a specific type, so that we don't have to rely on writing everything into the `assetInfo` and `customData` entries.\n\nTo get an overview of metadata in USD, check out our dedicated [metadata section](../elements/metadata.md).\n\n# Table of Contents\n1. [Metadata Plugins In-A-Nutshell](#summary)\n1. [What should I use it for?](#usage)\n1. [Resources](#resources)\n1. [Overview](#overview)\n    1. [Installing a metadata plugin](#metadataPluginInstall)\n    1. [Reading/Writing the installed custom metadata](#metadataPluginReadWrite)\n\n## TL;DR - Metadata Plugins In-A-Nutshell <a name=\"summary\"></a>\n- Extending USD with custom metadata fields is as simple as creating a `plugInfo.json` file with entires for what custom fields you want and on what entities (Supported are `Sdf.Layer` and subclasses of `Sdf.Spec`). \n\n## What should I use it for? <a name=\"usage\"></a>\n~~~admonish tip\nIn production, most of the sidecar metadata should be tracked via the `assetInfo` and `customData` metadata entries. It does make sense to extend the functionality with own metadata keys for:\n- Doing high performance lookups. Metadata is fast to read, as it follows simpler composition rules, so we can use it as a `IsA` replacement mechanism we can tag our prims/properties with.\n- We can add [list editable ops](../composition/listeditableops.md) metadata fields, this can be used as a way to layer together different array sidecar data. For an example see our [Reading/Writing the installed custom metadata](#metadataPluginReadWrite) section.\n~~~\n\n## Resources\n- [USD Survival Guide - Metadata](../elements/metadata.md)\n- [USD API - Metadata](https://openusd.org/release/api/sdf_page_front.html#sdf_plugin_metadata)\n- [USD Cookbook - Extending Metadata](https://github.com/ColinKennedy/USD-Cookbook/blob/master/references/working_with_plugins.md#Extend-Metadata) \n\n## Overview <a name=\"overview\"></a>\nHere is the minimal plugin template with all options you can configure for your metadata:\n~~~admonish info title=\"\"\n```json\n{\n   \"Plugins\": [\n       {\n           \"Name\": \"<PluginName>\",\n           \"Type\": \"resource\",\n           \"Info\": {\n               \"SdfMetadata\": {\n                    \"<field_name>\" : {\n                        \"appliesTo\": \"<Optional comma-separated list of spec types this field applies to>\",\n                        \"default\": \"<Optional default value for field>\",\n                        \"displayGroup\": \"<Optional name of associated display group>\",\n                        \"type\": \"<Required name indicating field type>\",\n                    }\n               }\n           }\n       }\n   ]\n}\n```\n~~~\n\n\nWe can limit the metadata entry to the following `Sdf.Layer`/Subclasses of `Sdf.Spec`s with the `type` entry:\n\n| \"appliesTo\" token\t| Spec type                    |\n|-------------------|------------------------------|\n| layers\t        | SdfLayer (SdfPseudoRootSpec) |\n| prims\t            | SdfPrimSpec, SdfVariantSpec  |\n| properties\t    | SdfPropertySpec              |\n| attributes\t    | SdfAttributeSpec             |\n| relationships\t    | SdfRelationshipSpec          |\n| variants          | SdfVariantSpec               |\n\nYou can find all the supported data types on this page in the official docs: [USD Cookbook - Extending Metadata](https://openusd.org/release/api/sdf_page_front.html#sdf_plugin_metadata).\n\n### Installing a metadata plugin <a name=\"metadataPluginInstall\"></a>\n\nHere is an example `plugInfo.json` file for metadata, it also ships with this repo [here](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/tree/main/files/plugins/metadata).\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../files/plugins/metadata/plugInfo.json}}\n```\n~~~\n\nTo register the above metadata plugin, copy the contents into a file called `plugInfo.json`. Then set your `PXR_PLUGINPATH_NAME` environment variable to the folder containing the `plugInfo.json` file.\n\nFor Linux this can be done for the active shell as follows:\n```bash\nexport PXR_PLUGINPATH_NAME=/my/cool/plugin/resources:${PXR_PLUGINPATH_NAME}\n```\n\nIf you downloaded this repo, we provide the above example metadata plugin [here](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/tree/main/files/plugins/metadata). All you need to do is point the environment variable there and launch a USD capable application.\n\n\n### Reading/Writing the installed custom metadata <a name=\"metadataPluginReadWrite\"></a>\nOnce the plugin is loaded, we can now read and write to the custom entry.\n\nCustom metadata fields on the `Sdf.Layer` are not exposed via Python (as far as we could find).\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:metadataPlugin}}\n```\n~~~"
  },
  {
    "path": "docs/src/pages/core/plugins/overview.md",
    "content": "# Plugin System\nUsd has a plugin system over which individual components are loaded.\n\n~~~admonish Abstract title=\"Usd Pipeline Plugins\"\nIn this guide we will cover how to create these minimal set of plugins needed to setup a production ready Usd pipeline:\n- **Kinds Plugin** (No compiling needed): For this plugin all you need is a simple .json file that adds custom kinds. Head over to our [kind](./kind.md) section to get started.\n- **Asset Resolver Plugin** (Compiling needed or use pre-packed resolvers): Head over to our [asset resolver](./assetresolver.md) section to get started. The actual [code](https://github.com/LucaScheller/VFX-UsdAssetResolver) and [guide](https://lucascheller.github.io/VFX-UsdAssetResolver/) is hosted here as it is a big enough topic of its own.\n- **Schema Plugin** (Optional, compiling needed if you want Python C++/Bindings): A schema plugin allows you to create own prim types/API schemas. This is useful when you need to often create a standardized set of attributes on prims that are relevant for your pipeline. Head over to our [schemas](./schemas.md) section to get going or to our [schemas overview](../elements/schemas.md) section to get an overview of what schemas are.\n- **Metadata Plugin** (Optional, No compiling needed): A metadata plugin allows you to create own metadata entries, so that you don't have to use the `assetInfo`/`customData` dict fields for transporting custom metadata. Schema plugins can also specify metadata, it is limited to the prim/applied schema though, so a standalone metadata plugin allows us to make metadata available on all prims/properties regardless of prim type/schema.\n~~~\n\n~~~admonish important title=\"Compiling against USD\"\nAs listed above, some plugins need to be compiled. Most DCCs ship with a customized USD build, where most vendors adhere to the [VFX Reference Platform](https://vfxplatform.com/) and only change USD with major version software releases. They do backport important production patches though from time to time. That's why we recommend using the USD build from the DCC instead of trying to self compile and link it to the DCC, as this guarantees the most stability. This does mean though, that you have to compile all plugins against each (major version) releases of each individual DCC.\n~~~\n\nTypical plugins are:\n- Schemas\n- Metadata\n- Kinds\n- Asset Resolver\n- Hydra Delegates (Render Delegates)\n- File Format Plugins (.abc/.vdb)\n\nYou can inspect if whats plugins were registered by setting the `TF_DEBUG` variable as mentioned in the [debugging](../profiling/debug.md) section:\n```bash\nexport TF_DEBUG=PLUG_REGISTRATION\n```\n\nIf you want to check via Python, you have to know under what registry the plugin is installed. There are several (info shamelessly copied from the below linked USD-CookBook page ;)):\n- KindRegistry\n- PlugRegistry\n- Sdf_FileFormatRegistry\n- ShaderResourceRegistry\n- UsdImagingAdapterRegistry\n\nColin Kennedy's USD-Cookbook has an excellent overview on this topic:\n[USD Cook-Book Plugins](https://github.com/ColinKennedy/USD-Cookbook/blob/33eac067a0a62578934105b19a2b9d8e4ea0646c/references/working_with_plugins.md)\n\nPlugins are detected by looking at the `PXR_PLUGINPATH_NAME` environment variable for folders containing a`plugInfo.json` file.\n\nTo set it temporarily, you can run the following in a shell and then run your Usd application:\n```\n// Linux\nexport PXR_PLUGINPATH_NAME=/my/cool/plugin/resources:${PXR_PLUGINPATH_NAME}\n// Windows\nset PXR_PLUGINPATH_NAME=/my/cool/plugin/resources:${PXR_PLUGINPATH_NAME}\n```\n\nIf you search your Usd installation, you'll find a few of these for different components of Usd. They are usually placed in a <Plugin Root>/resources folder as a common directory convention.\n\nVia Python you can also partially search for plugins (depending on what registry they are in) and also print their plugInfo.json file content via the `.metadata` attribute.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:pluginsRegistry}}\n```\n~~~\n\nWe can also use the plugin registry to lookup from what plugin a specific type/class (in this case a schema) is registered by:\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:schemasPluginRegistry}}\n```\n~~~\n\n"
  },
  {
    "path": "docs/src/pages/core/plugins/schemas.md",
    "content": "# Schemas\n~~~admonish important\nThis page only covers how to compile/install custom schemas, as we cover what schemas are in our [schemas](../elements/schemas.md) basic building blocks of USD section.\n~~~\n\nAs there is a very well written documentation in the [official docs](https://openusd.org/release/api/_usd__page__generating_schemas.html), we only cover compilation(less) schema creation and installation here as a hands-on example and won't go into any customization details. You can also check out Colin's excellent [Usd-Cook-Book](https://github.com/ColinKennedy/USD-Cookbook/tree/master/plugins/custom_schemas_with_python_bindings) example.\n\n# Table of Contents\n1. [API Overview In-A-Nutshell](#summary)\n2. [What should I use it for?](#usage)\n3. [Resources](#resources)\n4. [Overview](#overview)\n5. [Generate Codeless Schema](#usdGenSchemaCodelessSchema)\n    1. [Edit 'GLOBAL' prim 'customData' dict](#usdGenSchemaCodelessSchemaStep1)\n    2. [Run usdGenSchema](#usdGenSchemaCodelessSchemaStep2)\n    3. [Add the generated pluginInfo.json director to 'PXR_PLUGINPATH_NAME' env var.](#usdGenSchemaCodelessSchemaStep3)\n    4. [Run your Usd (capable) application.](#usdGenSchemaCodelessSchemaStep4)\n6. [Generate Compiled Schema](#usdGenSchemaCompiledSchema)\n    1. [Run usdGenSchema](#usdGenSchemaCompiledSchemaStep1)\n    2. [Compile schema](#usdGenSchemaCompiledSchemaStep2)\n    3. [Update environment variables.](#usdGenSchemaCompiledSchemaStep3)\n    4. [Run your Usd (capable) application.](#usdGenSchemaCompiledSchemaStep4)\n\n\n## TL;DR - Schema Creation In-A-Nutshell <a name=\"summary\"></a>\n- Generating schemas in Usd is as easy as supplying a customized `schema.usda` file to the `usdGenSchema` commandline tool that ships with Usd. That's right, you don't need to code!\n- Custom schemas allow us to create custom prim types/properties/metadata (with fallback values) so that we don't have to repeatedly re-create it ourselves.\n- In OOP speak: It allows you to create your own subclasses that nicely fit into Usd and automatically generates all the `Get<PropertyName>`/`Set<PropertyName>` methods, so that it feels like you're using native USD classes.\n- We can also create `codeless` schemas, these don't need to be compiled, but we won't get our nice automatically generated getters and setters and schema C++/Python classes.\n\n~~~admonish tip\nCodeless schemas are ideal for smaller studios or when you need to prototype a schema. The result only consists of a `plugInfo.json` and `generatedSchema.usda` file and is instantly created without any need for compiling.\n~~~\n\n~~~admonish important title=\"Compiling against USD\"\nMost DCCs ship with a customized USD build, where most vendors adhere to the [VFX Reference Platform](https://vfxplatform.com/) and only change USD with major version software releases. They do backport important production patches though from time to time. That's why we recommend using the USD build from the DCC instead of trying to self compile and link it to the DCC, as this guarantees the most stability. This does mean though, that you have to compile all plugins against each (major version) releases of each individual DCC.\n~~~\n\n## What should I use it for? <a name=\"usage\"></a>\n~~~admonish tip\nWe'll usually want to generate custom schemas, when we want to have a set of properties/metadata that should always exist (with a fallback value) on certain prims. A typical use case for creating an own typed/API schema is storing common render farm settings or shot related data.\n~~~\n\n# Resources <a name=\"resources\"></a>\n- [API Docs](https://openusd.org/release/api/_usd__page__generating_schemas.html)\n\n## Overview <a name=\"overview\"></a>\nFor both examples we'll start of with the example schema that USD ships with in its official repo.\n\nYou can copy and paste the [content](https://github.com/PixarAnimationStudios/OpenUSD/blob/release/extras/usd/examples/usdSchemaExamples/schema.usda) into a file and then follow along or take the prepared files from [here](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/tree/main/files/plugins/schemas) that ship with this repo.\n\nOur guide focuses on working with Houdini, therefore we use the `usdGenSchema` that ships with Houdini. You can find it in your Houdini /bin directory.\n~~~admonish tip title=\"\"\n```bash\n$HFS/bin/usdGenSchema\n# For example on Linux:\n/opt/hfs19.5/bin/usdGenSchema\n```\n~~~\n\nIf you download/clone this repo, we ship with .bash scripts that automatically runs all the below steps for you.\n\nYou'll first need to `cd` to the root repo dir and then run `./setup.sh`. Make sure that you edit the `setup.sh` file to point to your Houdini version. By default it will be the latest Houdini major release symlink, currently `/opt/hfs19.5`, that Houdini creates on install.\n\nThen follow along the steps as mentioned below.\n\n## Codeless Schema <a name=\"usdGenSchemaCodelessSchema\"></a>\nCodeless schemas allow us to generate schemas without any C++/Python bindings. This means your won't get fancy `Schema.Get<PropertyName>`/`Schema.Set<PropertyName>` getters and setters. On the upside you don't need to compile anything. \n\n~~~admonish tip\nCodeless schemas are ideal for smaller studios or when you need to prototype a schema. The result only consists of a `plugInfo.json` and `generatedSchema.usda` file.\n~~~\n\nTo enable codeless schema generation, we simply have to add `bool skipCodeGeneration = true` to the customData metadata dict on the global prim in our schema.usda template file.\n~~~admonish tip title=\"\"\n```python\nover \"GLOBAL\" (\n    customData = {\n        bool skipCodeGeneration = true\n    }\n) {\n}\n```\n~~~\n\nLet's do this step by step for our example schema.\n\n#### Step 1: Edit 'GLOBAL' prim 'customData' dict <a name=\"usdGenSchemaCodelessSchemaStep1\"></a>\nUpdate the global prim custom data dict from:\n~~~admonish tip title=\"\"\n```python\nover \"GLOBAL\" (\n    customData = {\n        string libraryName       = \"usdSchemaExamples\"\n        string libraryPath       = \".\"\n        string libraryPrefix     = \"UsdSchemaExamples\"\n    }\n) {\n}\n```\n~~~\nto:\n~~~admonish tip title=\"\"\n```python\nover \"GLOBAL\" (\n    customData = {\n        string libraryName       = \"usdSchemaExamples\"\n        string libraryPath       = \".\"\n        string libraryPrefix     = \"UsdSchemaExamples\"\n        bool skipCodeGeneration = true\n    }\n) {\n}\n```\n~~~\n\n~~~admonish info title=\"Result | Click to expand content\" collapsible=true\n```python\n{{#include ../../../../../files/plugins/schemas/codelessSchema/schema.usda}}\n```\n~~~\n\n#### Step 2: Run usdGenSchema <a name=\"usdGenSchemaCodelessSchemaStep2\"></a>\nNext we need to generate the schema. \n\nMake sure that you first sourced you Houdini environment by running `$HFS/houdini_setup` so that it find all the correct libraries and python interpreter.\n\n~~~admonish tip title=\"usdGenSchema on Windows\"\nOn Windows you can also run `hython usdGenSchema schema.usda dst` to avoid having to source the env yourself.\n~~~\n\nThen run the following\n~~~admonish tip title=\"\"\n```bash\ncd /path/to/your/schema # In our case: .../VFX-UsdSurvivalGuide/files/plugins/schemas/codelessSchema\nusdGenSchema schema.usda dst\n```\n~~~\nOr if you use the helper bash scripts in this repo (after sourcing the `setup.sh` in the repo root):\n~~~admonish tip title=\"\"\n```bash\ncd ./files/plugins/schemas/codelessTypedSchema/\nchmod +x build.sh # Add execute rights\nsource ./build.sh # Run usdGenSchema and source the env vars for the plugin path\n```\n~~~\n\n~~~admonish bug\nNot sure if this is a bug, but the `usdGenSchema` in codeless mode currently outputs a wrong `plugInfo.json` file. (It leaves in the cmake @...@ string replacements).\n\nThe fix is simple, open the `plugInfo.json` file and replace:\n```python\n...\n    \"LibraryPath\": \"@PLUG_INFO_LIBRARY_PATH@\", \n    \"Name\": \"usdSchemaExamples\", \n    \"ResourcePath\": \"@PLUG_INFO_RESOURCE_PATH@\", \n    \"Root\": \"@PLUG_INFO_ROOT@\", \n    \"Type\": \"resource\"\n...\n```\nTo:\n```python\n...\n    \"LibraryPath\": \".\", \n    \"Name\": \"usdSchemaExamples\", \n    \"ResourcePath\": \".\", \n    \"Root\": \".\", \n    \"Type\": \"resource\"\n...\n```\n~~~\n\n~~~admonish info title=\"Result | Click to expand content\" collapsible=true\n```python\n{{#include ../../../../../files/plugins/schemas/codelessSchema/dist/plugInfo.json}}\n```\n~~~\n\n\n#### Step 3: Add the generated pluginInfo.json director to 'PXR_PLUGINPATH_NAME' env var. <a name=\"usdGenSchemaCodelessSchemaStep3\"></a>\nNext we need to add the pluginInfo.json directory to the `PXR_PLUGINPATH_NAME` environment variable.\n~~~admonish tip title=\"\"\n```bash\n// Linux\nexport PXR_PLUGINPATH_NAME=/Enter/Path/To/dist:${PXR_PLUGINPATH_NAME}\n// Windows\nset PXR_PLUGINPATH_NAME=/Enter/Path/To/dist;%PXR_PLUGINPATH_NAME%\n```\n~~~\nIf you used the helper bash script, it is already done for us.\n\n#### Step 4: Run your Usd (capable) application. <a name=\"usdGenSchemaCodelessSchemaStep4\"></a>\nYes, that's right! It was that easy. (Puts on sunglass, ah yeeaah! 😎)\n\nIf you run Houdini and then create a primitive, you can now choose the `ComplexPrim` as well as assign the `ParamAPI` API schema.\n\n![\"test\"](../../../media/core/plugins/schemaCodelessHoudini.jpg#center)\n\nOr if you want to test it in Python:\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:schemasPluginCodelessTest}}\n```\n~~~\n\n## Compiled Schema <a name=\"usdGenSchemaCompiledSchema\"></a>\nCompiled schemas allow us to generate schemas with any C++/Python bindings. This means we'll get `Schema.Get<PropertyName>`/`Schema.Set<PropertyName>` getters and setters automatically which gives our schema a very native Usd feeling. You can then also edit the C++ files to add custom features on top to manipulate the data generated by your schema. This is how many of the schemas that ship with USD do it.\n\n~~~admonish tip title=\"usdGenSchema on Windows\"\nCurrently these instructions are only tested for Linux. We might add Windows support in the near future. (We use CMake, so in theory it should be possible to run the same steps in Windows too.)\n~~~\n\nLet's get started step by step for our example schema. \n\nWe also ship with a `build.sh` for running all the below steps in one go. Make sure you first run the `setup.sh` as described in the [overview](#overview) section and then navigate to the compiledSchema folder.\n~~~admonish tip title=\"\"\n```bash\ncd .../VFX-UsdSurvivalGuide/files/plugins/schemas/compiledSchema\nchmod +x build.sh # Add execute rights\nsource ./build.sh # Run usdGenSchema and source the env vars for the plugin path\n```\n~~~\n\nThis will completely rebuild all directories and set the correct environment variables. You can then go straight to the last step to try it out.\n\n#### Step 1: Run usdGenSchema <a name=\"usdGenSchemaCompiledSchemaStep1\"></a>\nFirst we need to generate the schema. \n\nMake sure that you first sourced you Houdini environment by running `$HFS/houdini_setup` so that it can find all the correct libraries and python interpreter.\n\n~~~admonish tip title=\"usdGenSchema on Windows\"\nOn Windows you can also run `hython usdGenSchema schema.usda dst` to avoid having to source the env yourself.\n~~~\n\nThen run the following\n~~~admonish tip title=\"\"\n```bash\ncd /path/to/your/schema # In our case: ../VFX-UsdSurvivalGuide/files/plugins/schemas/compiledSchema\nrm -R src\nusdGenSchema schema.usda src\n```\n~~~\n\nCurrently `usdGenSchema` fails to generate the following files:\n- `module.cpp`\n- `moduleDeps.cpp`\n- `__init__.py`\n\nWe needs these for the Python bindings to work, so we supplied them in the `VFX-UsdSurvivalGuide/files/plugins/schemas/compiledSchema/auxiliary` folder of this repo. Simply copy them into the `src` folder after running `usdGenSchema`. \n\nIt does automatically detect the boost namespace, so the generated files will automatically work with Houdini's `hboost` namespace.\n\n~~~admonish important\nIf you adjust your own schemas, you will have edit the following in these files:\n- `module.cpp`: Per user define schema you need to add a line consisting of `TF_WRAP(<SchemaClassName>);`\n- `moduleDeps.cpp`: If you add C++ methods, you will need to declare any dependencies what your schemas have. This file also contains the namespace for C++/Python where the class modules will be accessible. We change `RegisterLibrary(TfToken(\"usdSchemaExamples\"), TfToken(\"pxr.UsdSchemaExamples\"), reqs);` to `RegisterLibrary(TfToken(\"usdSchemaExamples\"), TfToken(\"UsdSchemaExamples\"), reqs);` as we don't want to inject into the default pxr namespace for this demo.\n~~~\n\n#### Step 2: Compile schema <a name=\"usdGenSchemaCompiledSchemaStep2\"></a>\nNext up we need to compile the schema. You can check out our asset resolver guide for more info on [system requirements](https://lucascheller.github.io/VFX-UsdAssetResolver/installation/requirements.html). In short you'll need a recent version of:\n- gcc (compiler)\n- cmake (build tool).\n\nTo compile, we first need to adjust our `CMakeLists.txt` file.\n\nUSD actually ships with a `CMakeLists.txt` file in the [examples](https://github.com/PixarAnimationStudios/OpenUSD/blob/release/extras/usd/examples/usdSchemaExamples/CMakeLists.txt) section. It uses some nice USD CMake convenience functions generate the make files.\n\nWe are not going to use that one though. Why? Since we are building against Houdini and to make things more explicit, we prefer showing how to explicitly define all headers/libraries ourselves. For that we provide the `CMakeLists.txt` file [here](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/tree/main/files/plugins/schemas/compiledSchema).\n\nThen run the following\n~~~admonish tip title=\"\"\n```bash\n# Clear build & install dirs\nrm -R build\nrm -R dist\n# Build\ncmake . -B build\ncmake --build build --clean-first # make clean all\ncmake --install build             # make install\n```\n~~~\n\nHere is the content of the CMakeLists.txt file. We might make a CMake intro later, as it is pretty straight forward to setup once you know the basics.\n\n~~~admonish info title=\"CMakeLists.txt | Click to expand content\" collapsible=true\n```python\n{{#include ../../../../../files/plugins/schemas/compiledSchema/CMakeLists.txt}}\n```\n~~~\n\n#### Step 3: Update environment variables. <a name=\"usdGenSchemaCompiledSchemaStep3\"></a>\nNext we need to update our environment variables. The cmake output log actually has a message that shows what to set:\n- `PXR_PLUGINPATH_NAME`: The USD plugin search path variable.\n- `PYTHONPATH`: This is the standard Python search path variable.\n- `LD_LIBRARY_PATH`: This is the search path variable for how `.so` files are found on Linux.\n\n~~~admonish tip title=\"\"\n```bash\n// Linux\nexport PYTHONPATH=..../VFX-UsdSurvivalGuide/files/plugins/schemas/compiledSchema/dist/lib/python:/opt/hfs19.5/python/lib/python3.9/site-packages:$PYTHONPATH\nexport PXR_PLUGINPATH_NAME=.../VFX-UsdSurvivalGuide/files/plugins/schemas/compiledSchema/dist/resources:$PXR_PLUGINPATH_NAME\nexport LD_LIBRARY_PATH=.../VFX-UsdSurvivalGuide/files/plugins/schemas/compiledSchema/dist/lib:/python/lib:/dsolib:$LD_LIBRARY_PATH\n// Windows\nset PYTHONPATH=..../VFX-UsdSurvivalGuide/files/plugins/schemas/compiledSchema/dist/lib/python;/opt/hfs19.5/python/lib/python3.9/site-packages;%PYTHON_PATH%\nset PXR_PLUGINPATH_NAME=.../VFX-UsdSurvivalGuide/files/plugins/schemas/compiledSchema/dist/resources;%PXR_PLUGINPATH_NAME%\n```\nFor Windows, specifying the linked .dll search path is different. We'll add more info in the future.\n~~~\n\n#### Step 4: Run your Usd (capable) application. <a name=\"usdGenSchemaCompiledSchemaStep4\"></a>\nIf we now run Houdini and then create a primitive, you can now choose the `ComplexPrim` as well as assign the `ParamAPI` API schema.\n\n![\"\"](../../../media/core/plugins/schemaCodelessHoudini.jpg#center)\n\nOr if you want to test it in Python:\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:schemasPluginCompiledTest}}\n```\n~~~\n\nAs you can see we now get our nice `Create<PropertyName>`/`Get<PropertyName>`/`Set<PropertyName>` methods as well as full Python exposure to our C++ classes."
  },
  {
    "path": "docs/src/pages/core/profiling/debug.md",
    "content": "# Debugging\nThe Usd API ships with a [debug class](https://openusd.org/dev/api/class_tf_debug.html), which allows you to log different messages by setting the `TF_DEBUG` environment variable to one of the symbols. This is useful to see if plugins are loaded or to see if the asset resolver is correctly hooked in.\n\n## TL;DR - Debug In-A-Nutshell\n- You can set the `TF_DEBUG` environment variable to one the the values listed below or symbol name from a plugin.\n- You can also activate a symbol in the active session via Python: ```pxr.Tf.Debug.SetDebugSymbolsByName(\"AR_RESOLVER_INIT\", True)```\n\n## What should I use it for?\n~~~admonish tip\nEnabling debug symbols, allows you to inspect specific log outputs of Usd. Typical use cases are to check if plugins are loaded correctly or if data is properly being refreshed.\n~~~\n\n## Resources\n- [Debug API Docs](https://openusd.org/dev/api/class_tf_debug.html)\n\n## Overview\nEnvironment Variables:\n\n| Name                  | Value                |\n|-----------------------|----------------------|\n| TF_DEBUG              | 'DEBUG_SYMBOL_NAME'  |\n| TF_DEBUG_OUTPUT_FILE  | 'stdout' or 'stderr' |\n\n~~~admonish tip\nActivating the log output via bash:\n```bash\nexport TF_DEBUG=AR_RESOLVER_INIT\n```\nThen launch your app.\n~~~\nYou can also set them interactively in the active session via Python. Wildcarding is allowd to turn on multiple debug symbols in batch.\n\n~~~admonish tip\n```python\nactivated_symbols = pxr.Tf.Debug.SetDebugSymbolsByName(\"AR_RESOLVER_INIT\", True) # Returns: [\"AR_RESOLVER_INIT\"]\nactivated_symbols = pxr.Tf.Debug.SetDebugSymbolsByName(\"AR_*\", True)\n```\n~~~\n\nExternal plugins (like asset resolvers) often register own debug symbols which you can then use to see exactly what is going on.\n\nTo get a list of value `TF_DEBUG`values you can run:\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:debuggingTokens}}\n```\n~~~\n\nFull list of debug codes:\n\n| Variable Name | Description |\n|----|----|\n| AR_RESOLVER_INIT | Print debug output during asset resolver initialization |\n| GLF_DEBUG_CONTEXT_CAPS | Glf report when context caps are initialized and dump contents |\n| GLF_DEBUG_DUMP_SHADOW_TEXTURES | Glf outputs shadows textures to image files |\n| GLF_DEBUG_ERROR_STACKTRACE | Glf dump stack trace on GL error |\n| GLF_DEBUG_POST_SURFACE_LIGHTING | Glf post surface lighting setup |\n| GLF_DEBUG_SHADOW_TEXTURES | Glf logging for shadow map management |\n| GUSD_STAGECACHE | GusdStageCache details. |\n| HDST_DISABLE_FRUSTUM_CULLING | Disable view frustum culling |\n| HDST_DISABLE_MULTITHREADED_CULLING | Force the use of the single threaded version of frustum culling |\n| HDST_DRAW | Reports diagnostics for drawing |\n| HDST_DRAWITEMS_CACHE | Reports lookups from the draw items cache. |\n| HDST_DRAW_BATCH | Reports diagnostics for draw batches |\n| HDST_DRAW_ITEM_GATHER | Reports when draw items are fetched for a render pass. |\n| HDST_DUMP_FAILING_SHADER_SOURCE | Print generated shader source code for shaders that fail compilation |\n| HDST_DUMP_FAILING_SHADER_SOURCEFILE | Write out generated shader source code to files for shaders that fail compilation |\n| HDST_DUMP_GLSLFX_CONFIG | Print composed GLSLFX configuration |\n| HDST_DUMP_SHADER_SOURCE | Print generated shader source code |\n| HDST_DUMP_SHADER_SOURCEFILE | Write out generated shader source code to files |\n| HDST_FORCE_DRAW_BATCH_REBUILD | Forces rebuild of draw batches. |\n| HDST_MATERIAL_ADDED | Report when a material is added |\n| HDST_MATERIAL_REMOVED | Report when a material is removed |\n| HDX_DISABLE_ALPHA_TO_COVERAGE | Disable alpha to coverage transpancy |\n| HDX_INTERSECT | Output debug info of intersector |\n| HDX_SELECTION_SETUP | Output debug info during creation of selection buffer |\n| HD_BPRIM_ADDED | Report when bprims are added |\n| HD_BPRIM_REMOVED | Report when bprims are removed |\n| HD_BUFFER_ARRAY_INFO | Report detail info of HdBufferArrays |\n| HD_BUFFER_ARRAY_RANGE_CLEANED | Report when bufferArrayRange is cleaned |\n| HD_CACHE_HITS | Report every cache hit |\n| HD_CACHE_MISSES | Report every cache miss |\n| HD_COUNTER_CHANGED | Report values when counters change |\n| HD_DIRTY_ALL_COLLECTIONS | Reports diagnostics when all collections are marked dirty |\n| HD_DIRTY_LIST | Reports dirty list state changes |\n| HD_DISABLE_MULTITHREADED_RPRIM_SYNC | Run RPrim sync on a single thread |\n| HD_DRAWITEMS_CULLED | Report the number of draw items culled in each render pass |\n| HD_ENGINE_PHASE_INFO | Report the execution phase of the Hydra engine |\n| HD_EXT_COMPUTATION_ADDED | Report when ExtComputations are added |\n| HD_EXT_COMPUTATION_EXECUTION | Report when ExtComputations are executed |\n| HD_EXT_COMPUTATION_REMOVED | Report when ExtComputations are removed |\n| HD_EXT_COMPUTATION_UPDATED | Report when ExtComputations are updated |\n| HD_FREEZE_CULL_FRUSTUM | Freeze the frustum used for culling at it's current value |\n| HD_INSTANCER_ADDED | Report when instancers are added |\n| HD_INSTANCER_CLEANED | Report when instancers are fully cleaned |\n| HD_INSTANCER_REMOVED | Report when instancers are removed |\n| HD_INSTANCER_UPDATED | Report when instancers are updated |\n| HD_RENDER_SETTINGS | Report render settings changes |\n| HD_RPRIM_ADDED | Report when rprims are added |\n| HD_RPRIM_CLEANED | Report when rprims are fully cleaned |\n| HD_RPRIM_REMOVED | Report when rprims are removed |\n| HD_RPRIM_UPDATED | Report when rprims are updated |\n| HD_SAFE_MODE | Enable additional security checks |\n| HD_SELECTION_UPDATE | Report when selection is updated |\n| HD_SHARED_EXT_COMPUTATION_DATA | Report info related to deduplication of ext computation data buffers |\n| HD_SPRIM_ADDED | Report when sprims are added |\n| HD_SPRIM_REMOVED | Report when sprims are removed |\n| HD_SYNC_ALL | Report debugging info for the sync all algorithm. |\n| HD_TASK_ADDED | Report when tasks are added |\n| HD_TASK_REMOVED | Report when tasks are removed |\n| HD_VARYING_STATE | Reports state tracking of varying state |\n| HGIGL_DEBUG_ERROR_STACKTRACE | HgiGL dump stack trace on GL error |\n| HGIGL_DEBUG_FRAMEBUFFER_CACHE | Debug framebuffer cache management per context arena. |\n| HGI_DEBUG_DEVICE_CAPABILITIES | Hgi report when device capabilities are initialized and dump contents |\n| HIO_DEBUG_DICTIONARY | glslfx dictionary parsing |\n| HIO_DEBUG_FIELD_TEXTURE_DATA_PLUGINS | Hio field texture data plugin registration and loading |\n| HIO_DEBUG_GLSLFX | Hio GLSLFX info |\n| HIO_DEBUG_TEXTURE_IMAGE_PLUGINS | Hio image texture plugin registration and loading |\n| NDR_DEBUG | Advanced debugging for Node Definition Registry |\n| NDR_DISCOVERY | Diagnostics from discovering nodes for Node Definition Registry |\n| NDR_INFO | Advisory information for Node Definition Registry |\n| NDR_PARSING | Diagnostics from parsing nodes for Node Definition Registry |\n| NDR_STATS | Statistics for registries derived from NdrRegistry |\n| PCP_CHANGES | Pcp change processing |\n| PCP_DEPENDENCIES | Pcp dependencies |\n| PCP_NAMESPACE_EDIT | Pcp namespace edits |\n| PCP_PRIM_INDEX | Print debug output to terminal during prim indexing |\n| PCP_PRIM_INDEX_GRAPHS | Write graphviz 'dot' files during prim indexing (requires PCP_PRIM_INDEX) |\n| PLUG_INFO_SEARCH | Plugin info file search |\n| PLUG_LOAD | Plugin loading |\n| PLUG_LOAD_IN_SECONDARY_THREAD | Plugins loaded from non-main threads |\n| PLUG_REGISTRATION | Plugin registration |\n| SDF_ASSET | Sdf asset resolution |\n| SDF_ASSET_TRACE_INVALID_CONTEXT | Post stack trace when opening an SdfLayer with no path resolver context |\n| SDF_CHANGES | Sdf change notification |\n| SDF_FILE_FORMAT | Sdf file format plugins |\n| SDF_LAYER | SdfLayer loading and lifetime |\n| SDR_TYPE_CONFORMANCE | Diagnostcs from parsing and conforming default values for Sdr and Sdf type conformance |\n| TF_ATTACH_DEBUGGER_ON_ERROR | attach/stop in a debugger for all errors |\n| TF_ATTACH_DEBUGGER_ON_FATAL_ERROR | attach/stop in a debugger for fatal errors |\n| TF_ATTACH_DEBUGGER_ON_WARNING | attach/stop in a debugger for all warnings |\n| TF_DEBUG_REGISTRY | debug the TfDebug registry |\n| TF_DISCOVERY_DETAILED | detailed debugging of TfRegistryManager |\n| TF_DISCOVERY_TERSE | coarse grain debugging of TfRegistryManager |\n| TF_DLCLOSE | show files closed by TfDlclose |\n| TF_DLOPEN | show files opened by TfDlopen |\n| TF_ERROR_MARK_TRACKING | capture stack traces at TfErrorMark ctor/dtor, enable TfReportActiveMarks debugging API. |\n| TF_LOG_STACK_TRACE_ON_ERROR | log stack traces for all errors |\n| TF_LOG_STACK_TRACE_ON_WARNING | log stack traces for all warnings |\n| TF_PRINT_ALL_POSTED_ERRORS_TO_STDERR | print all posted errors immediately, meaning that even errors that are expected and handled will be printed, producing possibly confusing output |\n| TF_SCRIPT_MODULE_LOADER | show script module loading activity |\n| TF_TYPE_REGISTRY | show changes to the TfType registry |\n| USDGEOM_BBOX | UsdGeom bounding box computation |\n| USDGEOM_EXTENT | Reports when Boundable extents are computed dynamically because no cached authored attribute is present in the scene. |\n| USDIMAGING_CHANGES | Report change processing events |\n| USDIMAGING_COLLECTIONS | Report collection queries |\n| USDIMAGING_COMPUTATIONS | Report Hydra computation usage in usdImaging. |\n| USDIMAGING_COORDSYS | Coordinate systems |\n| USDIMAGING_INSTANCER | Report instancer messages |\n| USDIMAGING_PLUGINS | Report plugin status messages |\n| USDIMAGING_POINT_INSTANCER_PROTO_CREATED | Report PI prototype stats as they are created |\n| USDIMAGING_POINT_INSTANCER_PROTO_CULLING | Report PI culling debug info |\n| USDIMAGING_POPULATION | Report population events |\n| USDIMAGING_SELECTION | Report selection messages |\n| USDIMAGING_SHADERS | Report shader status messages |\n| USDIMAGING_TEXTURES | Report texture status messages |\n| USDIMAGING_UPDATES | Report non-authored, time-varying data changes |\n| USDMTLX_READER | UsdMtlx reader details |\n| USDSKEL_BAKESKINNING | UsdSkelBakeSkinningLBS() method. |\n| USDSKEL_CACHE | UsdSkel cache population. |\n| USDUTILS_CREATE_USDZ_PACKAGE | UsdUtils USDZ package creation details |\n| USD_AUTO_APPLY_API_SCHEMAS | USD API schema auto application details |\n| USD_CHANGES | USD change processing |\n| USD_CLIPS | USD clip details |\n| USD_COMPOSITION | USD composition details |\n| USD_DATA_BD | USD BD file format traces |\n| USD_DATA_BD_TRY | USD BD call traces. Prints names, errors and results. |\n| USD_INSTANCING | USD instancing diagnostics |\n| USD_PATH_RESOLUTION | USD path resolution diagnostics |\n| USD_PAYLOADS | USD payload load/unload messages |\n| USD_PRIM_LIFETIMES | USD prim ctor/dtor messages |\n| USD_SCHEMA_REGISTRATION | USD schema registration details. |\n| USD_STAGE_CACHE | USD stage cache details |\n| USD_STAGE_INSTANTIATION_TIME | USD stage instantiation timing |\n| USD_STAGE_LIFETIMES | USD stage ctor/dtor messages |\n| USD_STAGE_OPEN | USD stage opening details |\n| USD_VALIDATE_VARIABILITY | USD attribute variability validation |\n| USD_VALUE_RESOLUTION | USD trace of layers inspected as values are resolved |\n\nYou scrolled all the way to the end 🥳. Congratulations, you have now earned the rank of \"Usd Nerd\"!"
  },
  {
    "path": "docs/src/pages/core/profiling/overview.md",
    "content": "# Debugging & Performance Profiling\nUsd ships with extensive debugging and profiling tools. You can inspect the code execution a various levels, which allows you to really pinpoint where the performance issues are.\n\nWhen starting out these to two interfaces are of interest:\n\n- [Debug Symbols](./debug.md): Enable logging of various API sections to stdout. Especially useful for plugins like asset resolvers or to see how DCCs handle Usd integration.\n- [Performance Profiling](./profiling.md): Usd has a powerful performance profiler, which you can also view with Google Chrome's Trace Viewer."
  },
  {
    "path": "docs/src/pages/core/profiling/profiling.md",
    "content": "# Performance Profiling\nFor low level profiling Usd ships with the `trace` profiling module.\n\nThis is also what a few DCCs (like Houdini) expose to profile Usd writing/rendering.\n\n![](../../../media/core/profiling/GoogleChromeTraceProfiling.jpg#center)\n\n## TL;DR - Profiling In-A-Nutshell\n- The trace module offers easy to attach Python decorators (`@Trace.TraceMethod/TraceFunction`) that you can wrap your functions with to expose them to the profiler.\n- You can dump the profiling result to .txt or the GoogleChrome tracing format you can open under [`chrome://tracing`](chrome://tracing). Even if you don't attach custom traces, you'll get extensive profiling stats of the underlying Usd API execution.\n\n## What should I use it for?\n~~~admonish tip\nIf you want to benchmark you Usd stage operations, the profiling module offers a fast and easy way to visualize performance.\n~~~\n\n## Resources\n- [Trace Overview](https://openusd.org/dev/api/trace_page_front.html)\n- [Trace Details](https://openusd.org/dev/api/trace_page_detail.html)\n\n## Overview\nThe trace module is made up of two parts:\n- `TraceCollector`: A singleton thread-safe recorder of (globale) events.\n- `TraceReporter`: Turn event data to meaning full views.\n\nVia the C++ API, you can customize the behavior further, for Python 'only' the global collector is exposed.\n\n### Marking what to trace\nFirst you mark what to trace. You can also mark nothing, you'll still have access to all the default profiling:\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:profilingTraceAttach}}\n```\n~~~\n\n### Trace collector & reporter\nThen you enable the collector during the runtime of what you want to trace and write the result to the disk.\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:profilingTraceCollect}}\n```\n~~~\n\nHere is an example (from the Usd docs) of a report to a .txt file. If you have ever rendered with Houdini this will be similar to when you increase the log levels.\n~~~admonish info title=\"\"\n```text\nTree view  ==============\n   inclusive    exclusive        \n  358.500 ms                    1 samples    Main Thread\n    0.701 ms     0.701 ms       8 samples    | SdfPath::_InitWithString\n    0.003 ms     0.003 ms       2 samples    | {anonymous}::VtDictionaryToPython::convert\n  275.580 ms   275.580 ms       3 samples    | PlugPlugin::_Load\n    0.014 ms     0.014 ms       3 samples    | UcGetCurrentUnit\n    1.470 ms     0.002 ms       1 samples    | UcIsKnownUnit\n    1.467 ms     0.026 ms       1 samples    |   Uc::_InitUnitData [initialization]\n    1.442 ms     1.442 ms       1 samples    |   | Uc_Engine::GetValue\n    0.750 ms     0.000 ms       1 samples    | UcGetValue\n    0.750 ms     0.750 ms       1 samples    |   Uc_Engine::GetValue\n    9.141 ms     0.053 ms       1 samples    | PrCreatePathResolverForUnit\n    0.002 ms     0.002 ms       6 samples    |   UcIsKnownUnit\n```\n~~~\n\nHere is an example of a report to a Google Chrome trace .json file opened at [`chrome://tracing`](chrome://tracing) in Google Chrome with a custom python trace marked scope.\n\n![](../../../media/core/profiling/GoogleChromePythonScopeTraceProfiling.jpg#center)\n\n\n### Measuring time deltas\nUsd ships with a simpel stop watch class that offers high precision time deltas.\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:profilingStopWatch}}\n```\n~~~\n\n### Stage Stats\nYou can also gather stage stats, this is mainly used to expose statistics for UIs.\n~~~admonish info title=\"\"\n```python\nfrom pxr import UsdUtils\nprint(UsdUtils.ComputeUsdStageStats(stage))\n# Returns (On stage with a single cube):\n{\n 'assetCount': 0, \n 'instancedModelCount': 0,\n 'modelCount': 0,\n 'primary': {'primCounts': {'activePrimCount': 2,\n                            'inactivePrimCount': 0,\n                            'instanceCount': 0, \n                            'pureOverCount': 0,\n                            'totalPrimCount': 2},\n 'primCountsByType': {'Cube': 1}}, \n 'prototypeCount': 0,\n 'totalInstanceCount': 0,\n 'totalPrimCount': 2,\n 'usedLayerCount': 10\n}\n```\n~~~"
  },
  {
    "path": "docs/src/pages/core/resources.md",
    "content": "# Resources\nIf you are interested in diving into topics yourself, here is a rough categorization:\n\n### General\n- [C++ Classes](https://openusd.org/release/api/annotated.html)\n\n### High Level API\n\n- [Usd Core API](https://openusd.org/release/api/usd_page_front.html)\n    - [Asset Resolution (How file paths are evaluated)](https://openusd.org/release/api/ar_page_front.html)\n    - [Cameras](https://openusd.org/release/api/class_gf_camera.html)\n        - [Frustum](https://openusd.org/release/api/class_gf_frustum.html)\n    - [Collections](https://openusd.org/release/api/class_usd_collection_a_p_i.html)\n        - [Utils](https://openusd.org/release/api/authoring_8h.html)\n    - [Event Listeners/Notifications](https://openusd.org/release/api/class_tf_notice.html) / [Notices](https://openusd.org/release/api/page_tf__notification.html)\n    - [Hierarchy Iteration](https://openusd.org/release/api/class_usd_prim_range.html)\n    - [Kinds](https://openusd.org/release/api/kind_page_front.html)\n    - [Layers](https://openusd.org/release/api/class_sdf_layer.html)\n        - [Stitching multiple layers to a single layer](https://openusd.org/release/api/stitch_8h.html)\n        - [Loading different layers per frame (Value Clips)](https://openusd.org/release/api/_usd__page__value_clips.html)\n            - [Utils](https://openusd.org/release/api/stitch_clips_8h.html)\n        - [Flattening a stage to a layer]()\n    - [Plugins](https://openusd.org/release/api/plug_page_front.html)\n    - Schemas (USD speak for classes)\n        - [Collections](https://openusd.org/release/api/class_usd_collection_a_p_i.html)\n        - [Lights](https://openusd.org/release/api/class_usd_lux_light_a_p_i.html)\n        - [Node Graph Shader Connections](https://openusd.org/release/api/class_usd_shade_connectable_a_p_i.html)\n        - [Value Clips](https://openusd.org/release/api/class_usd_clips_a_p_i.html)\n        - [Transforms](https://openusd.org/dev/api/class_usd_geom_xformable.html)\n    - Query/Lookup Caches\n        - [Attributes](https://openusd.org/release/api/class_usd_attribute_query.html)\n        - [Composition](https://openusd.org/release/api/class_usd_prim_composition_query.html)\n        - [Collections](https://openusd.org/release/api/class_usd_collection_membership_query.html)\n        - [Bounding Boxes](https://openusd.org/release/api/class_usd_geom_b_box_cache.html)\n        - [Transforms](https://openusd.org/release/api/class_usd_geom_xform_cache.html)\n    - [Stages]()\n        - [Prims](https://openusd.org/release/api/class_usd_prim.html)\n        - [Property](https://openusd.org/release/api/class_usd_property.html)\n            - [Attribute](https://openusd.org/release/api/class_usd_attribute.html)\n            - [Relationship](https://openusd.org/release/api/class_usd_relationship.html)\n    - Statistics\n        - [Stage Statistics](https://openusd.org/release/api/introspection_8h.html)\n        - [Profiling Performance(Tracing)](https://openusd.org/release/api/trace_page_front.html)\n    - [Utils](https://openusd.org/release/api/usd_utils_page_front.html)\n\n### Low Level API\n\n- [Sdf - Scene Description Foundations](https://openusd.org/release/api/sdf_page_front.html)\n    - [Sdf.Layer]()\n        - [Sdf.PrimSpec]()\n            - [Sdf.PropertySpec](https://openusd.org/release/api/class_sdf_property_spec.html)\n                - [Sdf.AttributeSpec](https://openusd.org/release/api/class_sdf_attribute_spec.html)\n                - [Sdf.RelationshipSpec](https://openusd.org/release/api/class_sdf_relationship_spec.html)\n        - [Sdf.VariantSpec](https://openusd.org/release/api/class_sdf_variant_spec.html)\n    - [Sdf.Path](https://openusd.org/release/api/class_sdf_path.html)\n    - [Sdf.ListOps](https://openusd.org/release/api/class_sdf_list_op.html)\n- [Pcp - PrimCache Population (Composition)](https://openusd.org/release/api/pcp_page_front.html)\n    - [Pcp.PrimIndex](https://openusd.org/release/api/class_pcp_prim_index.html)\n"
  },
  {
    "path": "docs/src/pages/dcc/houdini/approach.md",
    "content": "# General Approach\n~~~admonish question title=\"Still under construction!\"\nWe'll expand our Houdini section in the future with topics such as:\n- lighting\n- rendering (render products/render vars (USD speak for AOVs)/render procedurals)\n- asset/shot templates\n~~~\n\nThis page will focus on the basics of what you need to know before getting started in LOPs.\n\nCurrently this is limited to LOPs basics and SOP geometry importing/exporting, we'll expand this in the future to other topics.\n\n# Table of Contents\n1. [Houdini LOPs In-A-Nutshell](#summary)\n1. [What should I use it for?](#usage)\n1. [Resources](#resources)\n1. [Overview](#overview)\n1. [Artist Vs Pipeline](#artistVsPipeline)\n1. [Path Structure](#path)\n1. [How to convert between LOPs and SOPs](#IO)\n    1. [Importing from LOPs to SOPs](#IOLopsToSops)\n    1. [Exporting from SOPs to LOPs](#IOSopsToLops)\n    1. [Stage/Layer Metrics](#IOLayerMetrics)\n1. [Composition](#composition)\n    1. [Asset Resolver](#compositionAssetResolver)\n    1. [Creating Composition Arcs](#compositionAssetResolver)\n\n## TL;DR - Approach In-A-Nutshell <a name=\"summary\"></a>\nWhen working in Houdini, the basics our pipeline has to handle is USD import/export as well as setting up the correct composition.\n\nAs covered in our composition section, composition arcs are centered around loading a specific prim (and its children) in the hierarchy. We usually design our path structure around \"root\" prims. That way we can load/unload a specific hierarchy selection effectively. With value clips (USD speak for per frame/chunk file loading) we also need to target a specific root prim, so that we can keep the hierarchy reference/payloadable and instanceable.\n\nTo make it convenient for our artists to use USD, we should therefore make handling paths and composition as easy as possible. Our job is to abstract away composition, so that we use its benefits as best as possible without inconveniencing our artists.\n\n~~~admonish tip title=\"Houdini | SOPs to LOPs Path | Evaluation Order\"\nAs for paths, Houdini's SOPs to LOPs mechanism in a nutshell is:\n1. Check what \"path\" attribute names to consult\n1. Check (in order) if the attribute exists and has a non-empty value\n1. If the value is relative (starts with \"./some/Path\", \"some/Path\", \"somePath\", so no `/`), prefix the path with the setting defined in \"Import Path Prefix\" (unless it is a point instance prototype/volume grid path, see exceptions below).\n1. If no value is found, use a fallback value with the `<typeName>_<idx>` syntax.\n\nThere are two special path attributes, that cause a different behavior for the relative path anchoring.\n- **usdvolumesavepath**: This defines the path of your \"Volume\" prim. \n- **usdinstancerpath**: This defines the path of your \"PointInstancer\" prim (when exporting packed prims as point instancers).\n~~~\n\n## What should I use it for? <a name=\"usage\"></a>\n~~~admonish tip\nWe'll be using LOPs to create awesome VFX via USD!\n~~~\n\n## Resources <a name=\"resources\"></a>\n- [Importing SOP geometry into USD](https://www.sidefx.com/docs/houdini/solaris/sop_import.html)\n- [Solaris Performance](https://www.sidefx.com/docs/houdini/solaris/performance.html)\n- [Houdini Configure Layer](https://www.sidefx.com/docs/houdini/nodes/lop/configurelayer.html)\n\n## Overview <a name=\"overview\"></a>\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/dcc/houdini/houdiniNodeCategories.mp4\" type=\"video/mp4\" alt=\"Houdini Node Categories\">\n</video>\n\nYou can find all the examples we take a look at in our [USD Survival Guide - GitHub Repository](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/blob/main/files/dcc/houdini)\n\nWe have a lot of really cool nodes available for us what ship natively with Houdini. Quite a few of them are actually bare-bone wrappers around USD API commands, so that we don't have to master the API to use them.\n\nNow for pipeline developers, these are the nodes you'll primarily be interacting with:\n\n![Houdini Pipeline Nodes](../../../media/dcc/houdini/houdiniNodePipeline.jpg)\n\nYou favorite node will be the Python LOP node, as we have exposure to the full USD API and can modify the stage to our needs.\n\nReady!?! Let's goooooooo!\n\n## Artist Vs Pipeline <a name=\"artistVsPipeline\"></a>\nWhen switching to a USD backed pipeline, an important thing to not gloss over, is how to market USD to artists.\n\nHere are the most important things to keep in mind of what a pipeline should abstract away and what it should directly communicate to artists before getting started:\n- As USD is its own data format, we will not have the native file IO speeds of .bgeo(.sc). The huge benefit is that we can use our caches in any DCC that offers a USD implementation. The downside is, that we have to be more \"explicit\" of what data we are exporting. For example for packed geometry we have to define how to map it to USD, e.g. as \"PointInstancers\", \"Xforms\" or flattened geometry. This means there is now an additional step, that has to be made aware of, before each export. \n- USD exposes other departments work to us directly through its layering mechanism. This a very positive aspect, but it also comes with more communication overhead. Make sure you have setup clear communication structures beforehand of who to contact should questions and issues arise.\n- USD comes with its own terminology. While we do recommend teaching and learning it, when first transitioning to USD, we should try to keep in familiar waters where possible to soften the blow.\n\nHere are a few things pipeline can/should cover to make things as easy going as possible:\n- Provide learning material in the form of documentation, follow along workshops and template scenes. We recommend putting a strong focus on this before going \"live\" as once a show is running, it can cause a high demand in one-on-one artist support. The more you prepare in advance, the more things will flow smoothly. We also recommend tieing artists into your development process, as this keeps you on your toes and also helps ease the transition.\n- A core element pipeline should always handle is data IO. We provide various tips on how to make exporting to LOPs similar to SOP workflows in this guide.\n- We recommend being more restrictive in different workflow aspects rather than allowing to mix'n'match all different styles of geometry import/export and node tree flow \"designs\". What we mean with this is, that we should \"lock\" down specific use cases like \"What geo am I exporting (characters/water/debris/RBD/etc.)\" and build specific HDAs around these. This way there is no ambiguity to how to load in geometry to USD. It also makes pre-flight checks easy to implement, because we know in advance what to expect.\n- In LOPs, we can often stick to building a \"monolithic\" node stream (as to SOPs where we often branch and merge). As order of operation in LOPs is important, there are fewer ways to merge data. This means we can/should pre-define how our node tree should be structured (model before material, material before lighting etc.). A good approach is to segment based on tasks and then merge their generated data into the \"main\" input stream. For example when creating lights, we can create a whole light rig and then merge it in.\n\nThese tips may sound like a lot of work, but the benefits of USD are well worth it!\n\n~~~admonish question title=\"Still under construction!\"\nWe'll likely expand on this sub-section in the future.\n~~~\n\n## Path Structure <a name=\"path\"></a>\nAs covered in our [composition section](../../core/composition/overview.md), composition arcs are centered around loading a specific prim (and its children) in the hierarchy. We usually design our path structure around \"root\" prims. That way we can load/unload a specific hierarchy selection effectively. With value clips (USD speak for per frame/chunk file loading) we also need to target a specific root prim, so that we can keep the hierarchy reference/payloadable and instanceable.\n\nAs pipeline developers, we therefore should make it as convenient as possible for artists to not have to worry about these \"root\" prims.\n\nWe have two options:\n- We give artists the option to not be specific about these \"root\" prims. Everything that doesn't have one in its name, will then be grouped under a generic \"/root\" prim (or whatever we define as a \"Import Path Prefix\" on our import configure nodes). This makes it hard for pipeline to re-target it into a specific (shot) hierarchy. It kind of breaks the USD principle of layering data together.\n- We enforce to always have these root prims in our path. This looses the flexibility a bit, but makes our node network easier to read as we always deal with absolute(s, like the Sith) prim paths.\n\nWhen working in SOPs, we don't have sidecar metadata per path segment (prim) as in LOPs, therefore we need to define a naming convention upfront, where we can detect just based on the path, if a root is defined or not. There is currently no industry standard (yet), but it might be coming sooner than we might think! Say goodbye to vendor specific asset structures, say hello to globally usable assets.\n\nAs also mentioned in our composition section, this means that only prims under the root prims can have data (as the structure above is not payloaded/referenced). Everything we do in SOPs, affects only the leaf prims in world space. So we are all good on that side.\n\n## How to convert between LOPs and SOPs <a name=\"IOLopsToSops\"></a>\nTo handle the SOPs to LOPs conversion we can either configure the import settings on the LOPs sop import node or we can use the SOPs USD configure node, which sets the exact same settings, but as detail attributes. For pipeline tools, we recommend using the SOPs detail attributes, as we can dynamically change them depending on what we need.\n\n| LOPs Sop Import                                  | SOPs USD Configure Name                            |\n|--------------------------------------------------|----------------------------------------------------|\n| ![LOPs SOP Import](../../../media/dcc/houdini/houdiniLOPsSOPImportPath.jpg) | ![SOPs Usd Configure](../../../media/dcc/houdini/houdiniSOPsUsdConfigure.jpg) |\n\nWe strongly recommend reading the official docs [Importing SOP geometry into USD](https://www.sidefx.com/docs/houdini/solaris/sop_import.html) as supplementary reading material.\n\nIn our [Basic Building Blocks of Usd](../../core/elements/overview.md) section, the first thing we covered was how to handle paths.\nBefore we look at our import/export nodes let's do the same for Houdini.\n\nIn Houdini we can define what attributes Houdini consults for defining the `Sdf.Path` for our prims. By default it is the `path` and `name` attribute. When looking up the path, it looks through the path attributes in the order we define on the sop import/USD configure node. If the value is empty it moves onto the next attribute. If it doesn't find a valid value, it will fallback to defaults (`<typeName>_<idx>`, e.g. \"mesh_0\").\n\nWe can also specify relative paths. These are any paths, that don't start with `/`. These will be prefixed with the prefix defined via the \"Import Path Prefix\" parm on either ones of the configure nodes.\n\n~~~admonish tip title=\"Houdini | SOPs to LOPs Path | Evaluation Order\"\n1. Check what \"path\" attribute names to consult\n1. Check (in order) if the attribute exists and has a non-empty value\n1. If the value is relative (starts with \"./some/Path\", \"some/Path\", \"somePath\", so no `/`), prefix the path with the setting defined in \"Import Path Prefix\" (unless it is a point instance prototype/volume grid path, see exceptions below).\n1. If no value is found, use a fallback value with the `<typeName>_<idx>` syntax.\n~~~\n\nWhen working with packed prims (or nested levels of packed prims), the relative paths are anchored to the parent packed level for the nested levels. The top level packed prim is then anchored as usual against the import settings prefix.\n\nFor example:\n1. Packed: \"/level_0\"\n    1. Packed: \"./level_1\"\n        1. Mesh: \"myCoolMesh\"\n\nThe resulting path will be \"/level_0/level_1/myCoolMesh\". Be careful, using \"../../../myPath\" works too, strongly **not** recommended as it breaks out of the path (like a `cd ../../path/to/other/folder``)!\n\n~~~admonish danger title=\"Important | Paths and Packed Prims\"\nWhen working with paths in SOPs and packed prims, we have to set the path before we pack the geometry. We can't adjust it afterwards, without unpacking the geometry. If we define absolute paths within packed geometry, they will not be relative to the parent packed level. This can cause unwanted behaviours (as your hierarchy \"breaks\" out of its packed level). We therefore recommend not having absolute paths inside packed prims.\n\nWe can easily enforce this, by renaming our \"outside\" packed attributes to something else and using these as \"path\" import attributes. That way the inside get's the fallback behavior, unless explicitly set to our \"outer\" path attributes.\n~~~\n\nThere are two special path attributes, that cause a different behavior for the relative path anchoring.\n- **usdvolumesavepath**: This defines the path of your \"Volume\" prim. As for volumes we usually use the \"name\" attribute to drive the volume grid/field name, this gives us \"/my/cool/explosionVolume/density\", \"/my/cool/explosionVolume/heat\", etc, as long as we don't define another path attribute that starts with \"/\". So this gives us a convenient way to define volumes with (VDB) grids.\n- **usdinstancerpath**: This defines the path of your \"PointInstancer\" prim (when exporting packed prims as point instancers). When we define a relative path, it is anchored under \"/my/cool/debrisInstancer/Prototypes/ourRelativePathValue\". Collecting our prototypes under the \"/Prototypes\" prim is a common USD practice, as it visually is clear where the data is coming as well as it make the hierarchy \"transportable\" as we don't point to random other prims, that might be unloaded.\n\nWhen these two attributes are active, our path attributes that are relative, are anchored differently:\n- **usdvolumesavepath**: \"/my/cool/explosionVolume/**relativePathValue**\".\n- **usdinstancerpath**: \"/my/cool/debrisInstancer/Prototypes/**relativePathValue**\"\n\nHere's a video showing all variations, you can find the file, as mentioned above, in our GitHub repo:\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/dcc/houdini/houdiniPathAbsoluteVsRelative.mp4\" type=\"video/mp4\" alt=\"Houdini Node Path\">\n</video>\n\n### Importing from LOPs to SOPs <a name=\"IOLopsToSops\"></a>\nImporting from LOPs is done via two nodes:\n- **LOP Import**: This imports packed USD prims.\n- **USD Unpack**: This unpacks the packed USD prims to polygons.\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/dcc/houdini/houdiniSOPsLOPImportTraversal.mp4\" type=\"video/mp4\" alt=\"Houdini LOP Import Traversal\">\n</video>\n\n~~~admonish danger title=\"Selecting Parent & Child Prims\"\nIf we select a parent and child prim at the same time, we will end up with duplicated geometry on import (and the import will take twice as long).\n\nBy default the \"USD Unpack\" node traverses to \"GPrims\" (Geometry Prims), so it only imports anything that is a geo prim. That means on LOP import, we don't have to select our leaf mesh prims ourselves, when we want the whole model.\n~~~\n\nAs loading data takes time, we recommend being as picky as possible of what you want to import. We should not import our whole stage as a \"USD Packed Prim\" and then traverse/break it down, instead we should pick upfront what to load. This avoids accidentally creating doubled imports and keeps things fast.\n\n~~~admonish tip title=\"Pro Tip | Import Xforms\"\nOur packed USD prims, carry the same transform information as standard packed geo. We can use this to parent something in SOPs by extracting the packed intrinsic transform to the usual point xform attributes.\n~~~\n\nIf we want to import data from a LOPs PointInstancer prim, we can LOP import the packed PointInstancer prim and then unpack it polygons. This will give us a packed USD prim per PoinstInstancer prin (confusing right?). Be careful with displaying this in the viewport, we recommend extracting the xforms and then adding a add node that only keeps the points for better performance.\n\n~~~admonish danger title=\"USD Packed Prims\"\nDisplaying a lot of packed prims in SOPS can lead to Houdini being unstable. We're guessing because it has to draw via Hydra and HoudiniGL and because USD packed prims draw a stage partially, which is a weird intermediate filter level.\n\nWe recommend unpacking to polygons as \"fast\" as possible and/or pre-filtering the LOP import as best as possible.\n~~~\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/dcc/houdini/houdiniSOPsLOPImportPointInstancer.mp4\" type=\"video/mp4\" alt=\"Houdini LOP Import PointInstancer\">\n</video>\n\n### Exporting from SOPs to LOPs <a name=\"IOSopsToLops\"></a>\nExport to LOPs is as simple as creating a SOP Import node and picking the SOP level geo.\n\nAs described above, we can drive the SOP import settings via the \"USD Configure\" SOPs level node or the \"SOP Import\" LOPs node.\n\nWe go into detail on how to handle the different (FX) geometry types in our [Geometry IO/FX section](../houdini/fx/overview.md).\n\nWe recommend building workflows for each geo type (points/deformed meshes/transforms/copy-to-points/RBD/crowds) as this makes it easy to pre-flight check as we know exactly what to export and we can optimize (the heck) out of it.\n\n~~~admonish tip title=\"Pro Tip | Working Against Stages\"\nWhen working LOPs, we like to use the terminology: \"We are working against a stage.\"\n\nWhat do we mean with that? When importing from or editing our stage, we are always making the edits relative to our current stage.\nWhen importing to SOPs, we can go out of sync, if our SOP network intermediate-caches geometry. For example if it writes SOP imported geometry to a .bgeo.sc cache and the hierarchy changes in LOPs, you SOPs network will not get the correct hierarchy until it is re-cached.\n\nThis can start being an issue, when you want to \"over\" the data from SOPs onto an existing hierarchy. Therefore we should always try to write our caches \"against a stage\". Instead of just caching our USD to disk and then composition arc-ing it into our \"main\" node stream.\n\nThis means that we can validate our hierarchy and read stage metrics like shutter sample count or local space transforms on USD export.\nThis ensures that the resulting cache is valid enough to work downstream in our pipeline.  Houdini's \"SOP Import\" node is also constructed to work against the input connected stage and does alot of this for you (e.g. material binding/local space correction (\"Adjust Transforms for Input Hierarchy\")).\n~~~\n\nAnother thing we have to keep in mind is that SOPs only represents the active frame, where as a written USD cache file represents the whole frame range.\n\nTo emulate this we can add a cache LOPs node. If we have geometry \"popping\" in and out across the frame range, it will by default always be visible in the whole frame range cached file. When we write USD files on different machines (for example on a farm), each frame that is being cooked does not know of the other frames. \n\nTo solve this USD has two solutions:\n- If our output file is a single stitched USD file, then we have to manually check the layers before stitching them and author visibility values if we want to hide the prims on frames where they produced no data.\n- With value clips we have to write an \"inherited\" visibility time sample per prim for every time sample. If the hierarchy does not exist, it will fallback to the manifest, where we have to write a value of \"invisible\".\n\nHoudini has the option to track visibility for frame ranges (that are cooked in the same session) to prevent this. For large production scenes, we usually have to resort to the above to have better scalability.\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../media/dcc/houdini/houdiniLOPsSOPImportTimeVisibility.mp4\" type=\"video/mp4\" alt=\"Houdini SOP Import Time Visibility\">\n</video>\n\n### Stage/Layer Metrics <a name=\"IOLayerMetrics\"></a>\nAs mentioned in our [stage/layer](../../core/elements/layer.md#layerMetrics) and [animation](../../core/elements/animation.md#animationMetadata) sections, we can/should setup layer related metrics.\n\nThey work the same way in Houdini, the only difference is we have to use Houdini's [Configure Layer](https://www.sidefx.com/docs/houdini/nodes/lop/configurelayer.html) node to set them, if we want to set them on the root layer/stage (due to how Houdini manages stages).\n\n![Houdini Stage/Layer metrics](../../../media/dcc/houdini/houdiniLayerMetrics.jpg)\n\n## Composition <a name=\"composition\"></a>\n\n### Asset Resolver <a name=\"compositionAssetResolver\"></a>\nIn Houdini our asset resolver is loaded as usual via the plugin system. If we don't provide a context, the default context of the resolver is used.\n\nWe can pass in our [asset resolver context](../../core/plugins/assetresolver.md#assetResolverContext) in two ways:\n- Via the the configure stage node. When set via the stage node, the left most node stream with a context \"wins\", when we start merging node trees.\n- Globally via the scene graph tree panel settings.\n\n| Node Tree                                               | Global Context                                               |\n|---------------------------------------------------------|--------------------------------------------------------------|\n| ![LOPs Configure Stage Node](../../../media/dcc/houdini/houdiniAssetResolverContextNode.jpg) | ![LOPs Stage Settings](../../../media/dcc/houdini/houdiniAssetResolverContextGlobal.jpg) |\n\nIf you are using the scene graph tree panel settings, be sure to turn off \"Set Asset Resolver Context From LOP Node Parameters\" in the preferences.\n\n![Asset Resolver Preferences](../../../media/dcc/houdini/houdiniAssetResolverContextPreferences.jpg)\n\nFor more info about resolvers, check out our [asset resolver](../../core/plugins/assetresolver.md) section.\nWe provide reference resolver implementations that are ready to be used in production.\n\n### Creating Composition Arcs <a name=\"compositionAssetResolver\"></a>\nCreating composition arcs in LOPs can be done via Houdini's sublayer, variant and reference (for inherit/payload/specializes) nodes.\n\nWe recommend using these for prototyping composition. Once we've figured out where we want to go, we should re-write it in Python, as it is easier and a lot faster when working on large hierarchies.\n\nThis guide comes with an extensive [composition fundamentals](../../core/composition/overview.md)/[composition in production](../../production/composition.md) section with a lot of code samples. \n\nWe also cover advanced composition arc creation, specifically for Houdini, in our [Tips & Tricks](../houdini/faq/overview.md#compositionOverview) section."
  },
  {
    "path": "docs/src/pages/dcc/houdini/faq/overview.md",
    "content": "# Tips & Tricks\nYou can find all the .hip files of our shown examples in our [USD Survival Guide - GitHub Repo](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/tree/main/files/dcc/houdini).\n\n# Table of Contents\n1. [Composition](#compositionOverview)\n    1. [Extracting payloads and references from an existing layer stack with anonymous layers](#compositionReferencePayloadLayerStack)\n    1. [Efficiently re-writing existing hierarchies as variants](#compositionArcVariantReauthor)\n    1. [Adding overrides via inherits](#compositionArcInherit)\n1. [How do I check if an attribute has time samples (if there is only a single time sample)?](#timeSampleValueMightBeTimeVarying)\n1. [Where are Houdini's internal lop utils stored?](#houLopUtils)\n1. [How do I get the LOPs node that last edited a prim?](#houLastEditedPrim)\n1. [How do I store side car data from node to node?](#houSidecarData)\n\n## Composition <a name=\"compositionOverview\"></a>\nNow we've kind of covered these topics in our [A practical guide to composition](../../../production/composition.md) and [Composition - LIVRPS](../../../core/composition/livrps.md) sections.\n\nWe strongly recommend reading these pages before this one, as they cover the concepts in a broader perspective. \n\n### Extracting payloads and references from an existing layer stack with anonymous layers <a name=\"compositionReferencePayloadLayerStack\"></a>\nWhen building our composition in USD, we always have to make sure that layers that were generated in-memory are loaded via the same arc as layers loaded from disk.\nIf we don't do this, our composition would be unreliable in live preview vs cache preview mode.\n\nComposition arcs always reference a specific prim in a layer, therefore we usually attach our caches to some sort of predefined root prim (per asset).\nThis means that if we import SOP geometry, with multiple of these root hierarchies, we should also create multiple references/payloads so that each root prim can be unloaded/loaded via the payload mechanism.\n\nInstead of having a single SOP import or multiple SOP imports that are flattened to a single layer, we can put a SOP import within a for loop. Each loop iteration will then carry only the data of the current loop index (in our example box/sphere/tube) its own layer, because we filter the sop level by loop iteration.\n\nThe very cool thing then is that in a Python node, we can then find the layers from the layer stack of the for loop and individually payload them in. \n\nAgain you can also do this with a single layer, this is just to demonstrate that we can pull individual layers from another node.\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/dcc/houdini/faq/houdiniCompositionReferencePayloadForLoop.mp4\" type=\"video/mp4\" alt=\"Houdini Reference/Payload For Loop\">\n</video>\n\nYou can find this example in the composition.hipnc file in our [USD Survival Guide - GitHub Repo](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/tree/main/files/dcc/houdini).\n\n## Efficiently re-writing existing hierarchies as variants <a name=\"compositionArcVariantReauthor\"></a>\nVia the low level API we can also copy or move content on a layer into a variant. This is super powerful to easily create variants from caches.\n\nHere is how it can be setup in Houdini:\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/core/composition/houdiniCompositionVariantCopyMove.mp4\" type=\"video/mp4\" alt=\"Houdini Composition Variant Copy/Move\">\n</video>\n\nHere is the code for moving variants:\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../../code/core/composition.py:compositionArcVariantMoveHoudini}}\n```\n~~~\n\nAnd for copying:\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../../code/core/composition.py:compositionArcVariantCopyHoudini}}\n```\n~~~\n\n## Adding overrides via inherits <a name=\"compositionArcInherit\"></a>\nWe can add inherits as explained in detail in our [composition - LIVRPS](../../../core/composition/livrps.md#inherits) section.\n\nWe typically drive the prim selection through a user defined [prim pattern/lop selection rule](../performance/overview.md#houLopSelectionRule). In the example below, for simplicity, we instead iterate over all instances of the prototype of the first pig prim.\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../../code/dcc/houdini.py:houdiniCompositionInheritInstanceable}}\n```\n~~~\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/dcc/houdini/faq/houdiniCompositionInheritInstanceable.mp4\" type=\"video/mp4\" alt=\"Houdini Composition Inherit\">\n</video>\n\n## How do I check if an attribute has time samples (if there is only a single time sample)? <a name=\"timeSampleValueMightBeTimeVarying\"></a>\nWe often need to check if an attribute has animation or not. Since time samples can come through many files when using value clips, USD ships with the `Usd.Attribute.ValueMightBeTimeVarying()` method. This checks for any time samples and exists as soon as it has found some as to opening every file like `Usd.Attribute.GetTimeSamples` does.\n\nThe issue is that if there is only a single time sample (not default value) it still returns False, as the value is not animated per se. (By the way, this is also how the .abc file did it). Now that kind of makes sense, the problem is when working with live geometry in Houdini, we don't have multiple time samples, as we are just looking at the active frame.\nSo unless we add a \"Cache\" LOP node afterwards that gives us multiple time samples, the `GetTimeSamples` will return a \"wrong\" value.\n\nHere is how we get a correct value:\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../../code/dcc/houdini.py:houdiniTimeDependency}}\n```\n~~~\n\nThe logic is relatively simple: When looking at in-memory layers, use the usual command of `GetNumTimeSamples` as in-memory layers are instant when querying data.\nWhen looking at on disk files, use the `ValueMightBeTimeVarying`, as it is the fastest solution.\n\nYou can find the shown file here: [UsdSurvivalGuide - GitHub](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/tree/main/files/dcc/houdini/timeSamples)\n\n![Houdini Attribute Value Might Be Time Varying](../../../../media/dcc/houdini/faq/houdiniAttributeValueMightBeTimeVarying.jpg)\n\n\n## Where are Houdini's internal lop utils stored? <a name=\"houLopUtils\"></a>\nYou can find Houdini's internal loputils under the following path:\n~~~admonish tip title=\"\"\n$HFS/houdini/python3.9libs/loputils.py\n~~~\nIt is not an official API module, so use it with care, it may be subject to change.\n\nYou can simply import via `import loputils`. It is a good point of reference for UI related functions, for example action buttons on parms use it at lot.\n\nHere you can find the [loputils.py - Sphinx Docs](https://ikrima.github.io/houdini_additional_python_docs/loputils.html) online.\n\n## How do I get the LOPs node that last edited a prim? <a name=\"houLastEditedPrim\"></a>\nWhen creating data on your layers, Houdini attaches some custom data to the `customData` prim metadata. Among the data is the `HoudiniPrimEditorNodes`. This stores the internal [hou.Node.sessionId](https://www.sidefx.com/docs/houdini/hom/hou/nodeBySessionId.html) and allows you to get the last node that edited a prim.\n\nThis value is not necessarily reliable, for example if you do custom Python node edits, this won't tag the prim (unless you do it yourself). Most Houdini nodes track it correctly though, so it can be useful for UI related node selections.\n\n~~~admonish tip title=\"\"\n```Python\n...\ndef Xform \"pig\" (\n    customData = {\n        int[] HoudiniPrimEditorNodes = [227]\n    }\n    kind = \"component\"\n)\n...\n```\n~~~\nHere is how you retrieve it:\n~~~admonish tip title=\"\"\n```Python\nimport hou\nfrom pxr import Sdf\nstage = node.stage()\nprim = stage.GetPrimAtPath(Sdf.Path(\"/pig\"))\nhoudini_prim_editor_nodes = prim.GetCustomDataByKey(\"HoudiniPrimEditorNodes\")\nedit_node = None\nif houdini_prim_editor_nodes:\n    edit_node = hou.nodeBySessionId(houdini_prim_editor_nodes[-1])\n```\n~~~\n\nYou can also set it:\n~~~admonish tip title=\"\"\n```Python\nimport hou\nfrom pxr import Sdf, Vt\nnode = hou.pwd()\nstage = node.editableStage()\nprim = stage.GetPrimAtPath(Sdf.Path(\"/pig\"))\nhoudini_prim_editor_nodes = prim.GetCustomDataByKey(\"HoudiniPrimEditorNodes\") or []\nhoudini_prim_editor_nodes = [i for i in houdini_prim_editor_nodes]\nhoudini_prim_editor_nodes.append(node.sessionId())\nprim.SetCustomDataByKey(\"HoudiniPrimEditorNodes\", Vt.IntArray(houdini_prim_editor_nodes))\n```\n~~~\n\nThe Houdini custom data gets stripped from the file, if you enable it on the USD rop (by default it gets removed).\n![Alt text](../../../../media/dcc/houdini/faq/houdiniNodeBySessionId.jpg)\n\n## How do I store side car data from node to node? <a name=\"houSidecarData\"></a>\nTo have a similar mechanism like SOPs detail attributes to track data through your network, we can write our data to the `/HoudiniLayerInfo` prim. This is a special prim that Houdini creates (and strips before USD file write) to track Houdini internal data. It is hidden by default, you have to enable \"Show Layer Info Primitives\" in your scene graph tree under the sunglasses icon to see it. We can't track data on the root or session layer customData as Houdini handles these different than with bare bone USD to enable efficient node based stage workflows.\n\nYou can either do it via Python:\n~~~admonish tip title=\"\"\n```Python\nimport hou\nimport json\nfrom pxr import Sdf\nnode = hou.pwd()\nstage = node.editableStage()\nprim = stage.GetPrimAtPath(Sdf.Path(\"/HoudiniLayerInfo\"))\ncustom_data_key = \"usdSurvivalGuide:coolDemo\"\nmy_custom_data = json.loads(prim.GetCustomDataByKey(custom_data_key) or \"{}\")\nprint(my_custom_data)\nprim.SetCustomDataByKey(custom_data_key, json.dumps(my_custom_data))\n```\n~~~\n\nOr with Houdini's [Store Parameters Values](https://www.sidefx.com/docs/houdini/nodes/lop/storeparametervalues.html) node. See the docs for more info (It also uses the loputils module to pull the data).\n"
  },
  {
    "path": "docs/src/pages/dcc/houdini/fx/deformingMeshes.md",
    "content": "# Deforming Meshes\n"
  },
  {
    "path": "docs/src/pages/dcc/houdini/fx/frustumCulling.md",
    "content": "# Frustum Culling\nUSD also ships with 3d related classes in the `Gf` module. These allow us to also do bounding box intersection queries.\n\nWe also have a frustum class available to us, which makes implementing frustum culling quite easy! The below code is a great exercise that combines using numpy, the core USD math modules, cameras and time samples. We recommend studying it as it is a great learning resource.\n\nThe code also works on \"normal\" non point instancer boundable prims.\n\nYou can find all the .hip files of our shown examples in our [USD Survival Guide - GitHub Repo](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/tree/main/files/dcc/houdini).\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/dcc/houdini/fx/frustumCullingPointIInstancer.mp4\" type=\"video/mp4\" alt=\"Houdini Frustum Culling\">\n</video>\n\nIf you look closely you'll notice that the python LOP node does not cause any time dependencies. This is where the power of USD really shines, as we can sample the full animation range at once. It also allows us to average the culling data.\n\nFor around 10 000 instances and 100 frames, this takes around 2 seconds.\n\nHere is the code shown in the video.\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../../code/dcc/houdini.py:houdiniFrustumCulling}}\n```\n~~~"
  },
  {
    "path": "docs/src/pages/dcc/houdini/fx/motionblur.md",
    "content": "# Motion Blur\nMotion blur is computed by the hydra delegate of your choice using either the interpolated position data(deformation/xforms) or by making use of velocity/acceleration data.\n\nYou can find all the .hip files of our shown examples in our [USD Survival Guide - GitHub Repo](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/tree/main/files/dcc/houdini).\n\nAs noted in our [Motion Blur - Computing Velocities and Accelerations](../../../core/elements/animation.md#animationMotionVelocityAcceleration),\nwe can also easily derive the velocity and acceleration data from our position data, if the point count doesn't change.\n\n![Houdini Motion Data Compute](../../../../media/dcc/houdini/fx/motionblurDeformingVelocityAcceleration.png)\n\n~~~admonish warning\nDepending on the delegate, you will likely have to set specific primvars that control the sample rate of the position/acceleration data.\n~~~\n\nWe can also easily derive velocities/accelerations from position data, if our point count doesn't change:\n~~~admonish tip title=\"Motionblur | Compute | Velocity/Acceleration | Click to expand\" collapsible=true\n```python\n{{#include ../../../../../../code/core/elements.py:animationMotionVelocityAcceleration}}\n```\n~~~"
  },
  {
    "path": "docs/src/pages/dcc/houdini/fx/overview.md",
    "content": "# Handeling Geometry Input/Output and FX\n~~~admonish question title=\"Still under construction!\"\nWe'll expand this section in the future with topics such as:\n- Deforming Meshes\n- Volumes\n- Local/World Transform Space Handling\n~~~\n\nIn this section, we'll have a look at how to import/export different geometry types to and from USD.\n\nWe'll also explain advanced setups, that can increase your IO performance drastically.\n\n"
  },
  {
    "path": "docs/src/pages/dcc/houdini/fx/particles.md",
    "content": "# Particles\nImporting particles (points) is the simplest form of geometry import.\n\nLet's see how we can make it complicated 🤪. We'll take a look at these two cases:\n- Houdini native point import\n- Render overrides via (Numpy) Python wrangles\n\nYou can find all the .hip files of our shown examples in our [USD Survival Guide - GitHub Repo](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/tree/main/files/dcc/houdini).\n\nFor all options for SOP to LOP importing, check out the official [Houdini docs](https://www.sidefx.com/docs/houdini/solaris/sop_import.html).\n\n## Houdini Native Import\nWhen importing points, all you need to set is a path attribute on your points (rather than on prims as with polygon meshes), because we don't have any prims on sop level. (Thanks captain obvious).\n\nFor an exercise, let's build a simple SOP import ourselves. Should we use this in production: No, Houdini's geo conversion is a lot faster, when it comes to segmenting your input based on the path attribute. Nonetheless it is a fun little demo:\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../../code/dcc/houdini.py:houdiniPointsNativeStream}}\n```\n~~~\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/dcc/houdini/fx/pointsNativeStream.mp4\" type=\"video/mp4\" alt=\"Houdini Python Wrangle\">\n</video>\n\nWhy should we do it ourselves, you might ask? Because there are instances, where we can directly load in the array, because we know we are only editing a single prim. Some of Houdini's nodes actually use this mechanism in a few of the point instancer related nodes.\n\n## Render-Time Overrides via (Numpy) Python Wrangles\nNow you might be thinking, is Python performant enough to actually manipulate geometry?\n\nIn the context of points (also point instancers), we answer is yes. As we do not have to do geometry operations, manipulating points is \"just\" editing arrays. This can be done very efficiently via numpy, if we use it for final tweaking. So don't expect to have the power of vex, the below is a \"cheap\" solution to adding render time overrides, when you don't have the resources to write your own compiled language (looking at your [DNEG (OpenVDB AX)](https://www.openvdb.org/documentation/doxygen/openvdbax.html)).\n\nIn the near future, this can probably also be done by Houdini's render procedurals (it actually already can be). The method we show here, is DCC independent though, so it does have its benefits, because you don't need a Houdini (engine) license. \n\nTo showcase how we manipulate arrays at render time, we've built a \"Python Wrangle\" .hda. Here is the basic .hda structure:\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/dcc/houdini/fx/pointsPythonWrangleOverview.mp4\" type=\"video/mp4\" alt=\"Houdini Python Wrangle\">\n</video>\n\nAs discussed in our [Creating efficient LOPs .Hdas](../hda/overview.md) section, we start and end the Hda with a new layer to ensure that we don't \"suffer\" from the problem of our layer getting to data heavy. Then we have two python nodes: The first one serializes the Hda parms to a json dict and stores it on our point prims, the second one modifies the attributes based on the parm settings. Why do we need to separate the data storage and execution? Because we want to only opt-in into the python code execution at render-time. So that's why we put down a switch node that is driven via a context variable. Context variables are similar to global Houdini variables, the main difference is they are scoped to a section of our node graph or are only set when we trigger a render.\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/dcc/houdini/fx/pointsPythonWrangleHusk.mp4\" type=\"video/mp4\" alt=\"Houdini Python Wrangle Husk\">\n</video>\n\nThis means that when rendering the USD file to disk, all the points will store is our wrangle code (and the original point data, in production this usually comes from another already cached USD file that was payloaded in). In our pre render scripts, we can then iterate over our stage and execute our code.\n\nLet's talk about performance: The more attributes we manipulate, the slower it will get. To stress test this, let's try building a point replicator with a constant seed. To \"upres\" from 1 million to 10 million points, it takes around 30 seconds. For this being a \"cheap\" solution to implement, I'd say that is manageable for interactivity. Now we could also do a similar thing by just using a point instancer prim and upres-ing our prototypes, using this method allows for per point overrides though, which gives us more detail.\n\nHere is a demo of a point replicator:\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/dcc/houdini/fx/pointsPythonWranglePointReplicate.mp4\" type=\"video/mp4\" alt=\"Houdini Python Wrangle Husk\">\n</video>\n\nAnother cool thing is, that this is actually not limited to points prims (We lied in our intro 😱). Since all attributes are is arrays of data, we can run the python wrangle on any prim. For example if we just wan't to increase our pscale width or multiply our velocities, operating on an array via numpy is incredibly fast, we're talking a few 100 milliseconds at most for a few millions points. As mentioned in our [data types](../../../core/elements/data_type.md) section, USD implements the buffer protocol, so we don't actually duplicate any memory until really needed and mapping `Vt.Array`s to numpy is as straight forward as casting the array to a numpy array.\n\n\nNow the below code might look long, but the import bits are:\n- Getting the data: `np.array(attr.Get(frame)`\n- Setting the data: `attr.Set(attr.GetTypeName().type.pythonClass.FromNumpy(output_data[binding.property_name]), frame))`\n- Updating the extent hint: `UsdGeom.Boundable.ComputeExtentFromPlugins(boundable_api, frame)`\n\n~~~admonish tip title=\"Python Wrangle Hda | Summary |  Click to expand!\" collapsible=true\n```python\n    ...\n    # Read data\n    input_data[binding.property_name] = np.array(attr.Get(frame))\n    ...\n    # Write data\n    for binding in bindings:\n        attr = prim.GetAttribute(binding.property_name)\n        if len(output_data[binding.property_name]) != output_point_count:\n            attr.Set(pxr.Sdf.ValueBlock())\n            continue\n        attr_class = attr.GetTypeName().type.pythonClass\n        attr.Set(attr_class.FromNumpy(output_data[binding.property_name]), frame)\n    ...\n    # Re-Compute extent hints\n    boundable_api = pxr.UsdGeom.Boundable(prim)\n    extent_attr = boundable_api.GetExtentAttr()\n    extent_value = pxr.UsdGeom.Boundable.ComputeExtentFromPlugins(boundable_api, frame)\n    if extent_value:\n        extent_attr.Set(extent_value, frame)\n```\n~~~\n\n\nThe code for our \"python kernel\" executor:\n\n~~~admonish tip title=\"Python Wrangle Hda | Python Kernel | Click to expand!\" collapsible=true\n```python\n{{#include ../../../../../../files/dcc/houdini/points/pythonWrangle.py}}\n```\n~~~\n\nThe code for our pre render script:\n\n~~~admonish tip title=\"Python Wrangle Hda | Pre-Render Script | Click to expand!\" collapsible=true\n```python\n{{#include ../../../../../../files/dcc/houdini/points/renderPreFrame.py}}\n```\n~~~\n"
  },
  {
    "path": "docs/src/pages/dcc/houdini/fx/pointinstancers.md",
    "content": "# Point Instancers ('Copy To Points')\nWe have four options for mapping Houdini's packed prims to USD:\n- As transforms\n- As point instancers\n- As deformed geo (baking down the xform to actual geo data)\n- As skeletons, more info in our [RBD section](./rbd.md)\n\n~~~admonish tip title=\"Pro Tip | When to use PointInstancer prims?\"\nWe'll always want to use USD's PointInstancer prims, when representing a \"replicate a few unique meshes to many points\" scenario.\nIn SOPs we usually do this via the \"Copy To Points\" node.\n~~~\n\nYou can find all the .hip files of our shown examples in our [USD Survival Guide - GitHub Repo](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/tree/main/files/dcc/houdini).\n\nFor all options for SOP to LOP importing, check out the official [Houdini docs](https://www.sidefx.com/docs/houdini/solaris/sop_import.html).\n\nIn the below examples, we use the `path`/`name` attributes to define the prim path. You can actually configure yourself what attributes Houdini should use for defining our prim paths on the \"SOP import node\" LOP/\"USD Configure\" SOP node.\n\n## Houdini Native Import (and making it convenient for artists)\nTo import our geometry to \"PointInstancer\" USD prims, we have to have it as packed prims in SOPs. If you have nested packed levels, they will be imported as nested point instancers. We do not recommend doing this, as it can cause some confusing outputs. The best practice is to always have a \"flat\" packed hierarchy, so only one level of packed prims.\n\nHoudini gives us the following options for importing:\n- The `usdinstancerpath` attribute defines the location of our `PointInstancer` prim.\n- The `path`/`name` attribute defines the location of the prototype prims. Prototypes are the unique prims that should get instances, they are similar to the left input on your \"copy to points\" node. \n\nAn important thing to note is, that if your `path`/`name` attribute does not have any `/` slashes or starts with `./`, the prototypes will be imported with the following path: `<usdinstancerpath>/Prototypes/<pathOrName>`. Having the `/Prototypes` prim is just a USD naming convention thing.\n\nTo make it easy to use for artists, we recommend mapping the traditional path attribute value to `usdinstancerpath` and making sure that the `name` attribute is relative. \n\nAnother important thing to know about packed prims is, that the `path`/`name` attributes are also used to define the hierarchy within the packed prim content. So before you pack your geometry, it has to have a valid path value.\n\nGood, now that we know the basics, let's have a look at a not so expectable behavior:\nIf you remember, in our [Basic Building Blocks of Usd](../../../core/elements/overview.md) section, we explained that relationships can't be animated. Here's the fun part:\n\n~~~admonish danger title=\"PointInstancer | Varying Prototypes | Problem\"\nThe mapping of what point maps to what prototype prim is stored via the `protoIndices` attribute. This maps an index to the prim paths targetd by the `prototypes` relationship. Since relationships can't be animated, the `protoIndices`/`prototypes` properties has to be aware of all prototypes, that ever get instanced across the whole cache.\n~~~\n\nThis is the reason, why in our LOPs instancer node, we have to predefine all prototypes. The problem is in SOPs, it kind of goes against the usual artist workflow. For example when we have debris instances, we don't want to have the artist managing to always have at least one copy of all unique prims we are trying to instance.\n\n\n~~~admonish tip title=\"PointInstancer | Varying Prototypes | Solution\"\nThe artist should only have to ensure a unique `name` attribute value per unique instance and a valid `usdinstancerpath` value.\nMaking sure the protoIndices don't jump, as prototypes come in and out of existence, is something we can fix on the pipeline side.\n~~~\n\nLuckily, we can fix this behavior, by tracking the prototypes ourselves per frame and then re-ordering them as a post process of writing our caches.\n\nLet's take a look at the full implementation:\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/dcc/houdini/fx/pointInstancerPrototypeReorder.mp4\" type=\"video/mp4\" alt=\"Houdini Prototype Re-Order\">\n</video>\n\nAs you can see, all looks good, when we only look at the active frame, because the active frame does not know about the other frames. As soon as we cache it to disk though, it \"breaks\", because the protoIndices map to the wrong prototype.\n\nAll we have to do is create an attribute, that per frame stores the relation ship targets as a string list. After the cache is done, we have to map the wrong prototype index to the write one.\n\nHere is the tracker script:\n\n~~~admonish tip title=\"PointInstancer | Re-Order Prototypes | Track Prototypes | Click to expand\" collapsible=true\n```python\n{{#include ../../../../../../code/dcc/houdini.py:houdiniPointInstancerReorderTracker}}\n```\n~~~\n\nAnd here the post processing script. You'll usually want to trigger this after the whole cache is done writing. It also works with value clips, you pass in all the individual clip files into the layers list. This is also another really cool demo, of how numpy can be used to get C++ like performance.\n\n~~~admonish tip title=\"PointInstancer | Re-Order Prototypes | Track Prototypes | Click to expand\" collapsible=true\n```python\n{{#include ../../../../../../code/dcc/houdini.py:houdiniPointInstancerReorderPostProcess}}\n```\n~~~\n\nPhew, now everything looks alright again!\n\n## Performance Optimizations\nYou may have noticed, that we always have to create packed prims on SOP level, to import them as PointInstancer prims. If we really want to go all out on the most high performance import, we can actually replicate a \"Copy To Points\" import. That way we only have to pass in the prototypes and the points, but don't have the overhead of spawning the packed prims in SOPs.\n\nIs this something you need to be doing? No, Houdini's LOPs import as well as the packed prim generation are highly performant, the following solution is really only necessary, if you are really picky about making your export a few hundred milliseconds faster with very large instance counts.\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/dcc/houdini/fx/pointInstancerPerformance.mp4\" type=\"video/mp4\" alt=\"Houdini Prototype Re-Order\">\n</video>\n\nAs you can see we are at a factor 20 (1 seconds : 50 milliseconds). Wow! Now what we don't show is, that we actually have to conform the point instances attributes to what the PointInstancer prim schema expects. So the ratio we just mentioned is the best case scenario, but it can be a bit slower, when we have to map for example `N`/`up` to `orientations`. This is also only this performant because we are importing a single PointInstancer prim, which means we don't have to segment any of the protoIndices.\n\nWe also loose the benefit of being able to work with our packed prims in SOP level, for example for collision detection etc.\n\nLet's look at the details:\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/dcc/houdini/fx/pointInstancerPerformanceDetails.mp4\" type=\"video/mp4\" alt=\"Houdini Prototype Re-Order\">\n</video>\n\nOn SOP level:\n- We create a \"protoIndices\" attribute based on all unique values of the \"name\" attribute\n- We create a \"protoHash\" attribute in the case we have multiple PointInstancer prim paths, so that we can match the prototypes per instancer\n- We conform all instancing related attributes to have the correct precision. This is very important, as USD does not allow other precisions types than what is defined in the PointInstancer schema.\n- We conform the different instancing attributes Houdini has to the attributes the PointInstancer schema expects. (Actually the setup in the video doesn't do this, but you have to/should, in case you want to use this in production)\n\nOn LOP level:\n- We import the points as a \"Points\" prim, so now we have to convert it to a \"PointInstancer\" prim. For the prim itself, this just means changing the prim type to \"PointInstancer\" and renaming \"points\" to \"positions\".\n- We create the \"prototypes\" relationship property.\n\n~~~admonish tip title=\"PointInstancer | Custom Import | Click to expand\" collapsible=true\n```python\n{{#include ../../../../../../code/dcc/houdini.py:houdiniPointInstancerNativeStream}}\n```\n~~~"
  },
  {
    "path": "docs/src/pages/dcc/houdini/fx/rbd.md",
    "content": "# RBD (Rigid Body Dynamics)\nAs mentioned in our [Point Instancer](./pointinstancers.md) section, we have four options for mapping Houdini's packed prims to USD:\n- As transforms\n- As point instancers\n- As deformed geo (baking down the xform to actual geo data)\n- As skeletons\n\nWhich confronts us with the question:\n\n~~~admonish tip title=\"Pro Tip | How should I import my RBD(Rigid Body Dynamics) simulation?\"\nAs mentioned in our [production FAQ](../../../production/faq.md#faqPrimCount), large prim counts cause a significant decrease in performance.\nThat's why we should avoid writing RBD sims as transform hierarchies and instead either go for deformed geo (not memory efficient) or skeletons \n(memory efficient).\n~~~\n\n~~~admonish danger title=\"Skeletons and Custom Normals\"\nCurrently Hydra does not yet read in custom normals, when calculating skinning. This will likely be resolved in the very near future, until then we have to bake the skinning pre-render. This is very fast to do via the skeleton API, more details below.\n~~~\n\nOn this page we'll focus on the skeleton import, as it is the only viable solution for large hierarchy imports. It is also the most efficient one, as skeletons only store the joint xforms, just like the RBD simulation point output.\n\nUsing skeletons does have one disadvantage: We can't select a mesh separately and hide it as skeletons deform subsets of each individual prim based on weighting.\n\nThe solution is to set the scale of the packed piece to 0. For hero simulations, where we need to have a separate hierarchy entry for every piece, we'll have to use the standard packed to xform import. We can also do a hybrid model: Simply change the hierarchy paths to your needs and import them as skeletons. This way, we can still disable meshes based on what we need, but get the benefits of skeletons.\n\nYou can find all the .hip files of our shown examples in our [USD Survival Guide - GitHub Repo](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/tree/main/files/dcc/houdini).\n\n\n## Houdini Native Import via KineFX/Crowd Agents\nLet's first take a look at what Houdini supports out of the box:\n- We can import KineFX characters and crowd agents as skeletons. This does have the overhead of creating KineFX characters/crowd agents in a way that they map to our target output hierarchy we want in LOPs. It is also harder to setup with a lot of different skeletons (Or we couldn't figure, input is always welcome).\n- The \"RBD Destruction\" LOP node has a reference implementation of how to import packed prims as skeletons animations. It relies on Python for the heavy data lifting and doesn't scale well, we'll take a look at a high performance solution in the next section below, that uses Houdini's native import for the data loading and Python to map everything to its correct place.\n\nHere is a video showing both methods:\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/dcc/houdini/fx/rbdKineFXCrowdAgent.mp4\" type=\"video/mp4\" alt=\"Houdini Character Skeleton Import\">\n</video>\n\nThis works great, if we have a character like approach. \n\n## Houdini High Performance RBD Skeleton Import\n\nThe problem is with RBD sims this is not the case: We usually have a large hierarchy consisting of assets, that we fracture, that should then be output to the same hierarchy location as the input hierarchy. As skeletons are only evaluated for child hierarchies, where we have a \"SkelRoot\" prim as an ancestor, our approach should be to make all asset root prims (the ones that reference/payload all the data), be converted to have the \"SkelRoot\" prim type. This way we can nicely attach a skeleton to each asset root, which means we can selectively payload (un)load our hierarchy as before, even though each asset root pulls the skeleton data from the same on disk cache.\n\nLet's take a look how that works:\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/dcc/houdini/fx/rbdSkeleton.mp4\" type=\"video/mp4\" alt=\"Houdini Skeleton Custom Import\">\n</video>\n\nNow we won't breakdown how skelton's themselves work, as this is a topic on its own. You can read up on it in the [official API docs](https://openusd.org/dev/api/_usd_skel__intro.html).\n\nWhat we'll do instead is break down our approach. We have three inputs from LOPs, where we are pulling data from:\n- Geometry data: Here we import our meshes with:\n    - their joint weighting (RBD always means a weight of 1, because we don't want to blend xforms). \n    - their joint index. Skeleton animations in USD can't have time varying joint index to joint name mapping. This is designed on purpose, to speed up skeleton mesh binding calculation.\n    - their target skeleton. By doing our custom import we can custom build our skeleton hierarchy. In our example we choose to group by asset, so one skeleton per asset.\n- Rest data: As with a SOP transform by points workflow, we have to provide:\n    - the rest position\n    - the bind position (We can re-use the rest position)\n    - the joint names. We could also import them via the animation data, there is no benefit though, as joint idx to name mappings can't be animated (even though they are attributes and not relationships).\n- Animation data: This pulls in the actual animation data as:\n    - translations\n    - rotations\n    - scales (Houdini's RBD destruction .hda optionally disables animation import for scales as an performance opt-in)\n\nAfter the initial import, we then \"only\" have to apply a few schemas and property renames. That's it, it's as simple as that!\n\nSo why is this a lot faster, than the other methods?\n\nWe use Houdini's super fast SOP import to our benefit. The whole thing that makes this work are the following two pieces of our node network:\n\nOur joint name to index mapping is driven by a simple \"Enumerate\" node that runs per skeleton target prim path.\n\n <video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/dcc/houdini/fx/rbdSkeletonJointIndexName.mp4\" type=\"video/mp4\" alt=\"Houdini Skeleton Joint Index Name\">\n</video>\n\nOur joint xforms then create the same skeleton target prim path. We don't have to enumerate, because on LOP import our geometry is segmented based on the skeleton prim path. This slices the arrays the exact same way as the enumerate node. \n\n <video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/dcc/houdini/fx/rbdSkeletonJointXforms.mp4\" type=\"video/mp4\" alt=\"Houdini Skeleton Joint Xforms\">\n</video>\n\nThe outcome is that we let Houdini do all the heavy data operations like mesh importing and attribute segmentation by path.\nWe then only have to remap all the data entries to their correct parts. As USD is smart enough to not duplicate data for renames, this is fast and memory efficient.\n"
  },
  {
    "path": "docs/src/pages/dcc/houdini/fx/transformspace.md",
    "content": "# Transform Space (Local/World Space)\nLarge Scale Scenes - Precision Issues\n- local space velocity"
  },
  {
    "path": "docs/src/pages/dcc/houdini/fx/volumes.md",
    "content": "# Volumes\n"
  },
  {
    "path": "docs/src/pages/dcc/houdini/hda/overview.md",
    "content": "# Creating efficient LOPs HDAs\nAs with any other network in Houdini, we can also create HDAs in LOPs.\n\nThis page will focus on the most important performance related aspects of LOP HDAs, we will be referencing some of the points mentioned in the [performance optimizations](./performance/overview.md) section with a more practical view.\n\nYou can find all the .hip files of our shown examples in our [USD Survival Guide - GitHub Repo](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/tree/main/files/dcc/houdini).\n\n# Table of Contents\n1. [Overview](#overview)\n1. [HDA Template Setup](#hdaTemplate)\n    1. [Order of operations](#hdaOrderOfOperations)\n    1. [Dealing with time dependencies](#hdaTimeDependencies)\n    1. [Layer Size/Count](#hdaLayerSizeCount)\n1. [Composition](#hdaComposition)\n\n## Overview <a name=\"overview\"></a>\nWhen building LOP HDAs with USD, the big question is:\n\n~~~admonish question\nWhat should we do in Python and would should we do with HDAs/nodes that Houdini ships with?\n~~~\n\nThe answer depends on your knowledge level of USD and the pipeline resources you have.\n\nIf you want to go the \"expert\" route, this is the minimal working set of nodes you'll be using:\n\n![HDA Minimal Working Set Nodes](../../../../media/dcc/houdini/hda/hdaMinimalNodeWorkingSet.jpg)\n\nTechnically we won't be needing more, because everything else can be done in Python. \n(There are also the standard control flow related nodes, we skipped those in the above image).\nIt is also faster to run operations in Python, because we can batch edits, where as with nodes, Houdini\nhas to evaluate the node tree.\n\nSo does this mean we shouldn't use the Houdini nodes at all? Definitely not! Houdini's LOPs tool set offers a lot of useful nodes, especially when your are prototyping, we definitely recommend using these first. A common workflow for developers is therefore:\n\n~~~admonish tip title=\"\"\nBuild everything with LOP HDAs first, then rebuild it, where possible, with Python LOPs when we notice performance hits.\n~~~\n\nWe'll always use the \"Material Library\" and \"SOP Import\" nodes as these pull data from non LOP networks.\n\nThere are also a lot of UI related nodes, which are simply awesome. We won't be putting these in our HDAs, but they should be used by artists to complement our workflows.\n\n![Houdini UI Custom Panel Nodes](../../../../media/dcc/houdini/hda/houdiniUICustomPanelNodes.jpg)\n\n## HDA Template Setup <a name=\"hdaTemplate\"></a>\nLet's take a look at how we can typically structure HDAs:\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/dcc/houdini/hda/hdaTemplateStructure.mp4\" type=\"video/mp4\" alt=\"Houdini Hda Template Structure\">\n</video>\n\nFor parms we can make use of Houdini's internal loputils under the following path:\n~~~admonish tip title=\"\"\n$HFS/houdini/python3.9libs/loputils.py\n~~~\nIt is not an official API module, so use it with care, it may be subject to change.\n\nYou can simply import via `import loputils`. It is a good point of reference for UI related functions, for example action buttons on parms use it at lot.\n\nHere you can find the [loputils.py - Sphinx Docs](https://ikrima.github.io/houdini_additional_python_docs/loputils.html) online.\n\nIt gives us common lop related helpers, like selectors etc.\n\nFor the structure we recommend:\n1. Create a new layer\n2. Perform your edits (best-case only a single Python node) or merge in content from other inputs.\n3. Create a new layer\n\nWhy should we spawn the new layers? See our [layer size and content](#hdaLayerSizeCount) section below for the answer.\n\nWhen merging other layers via the merge node we recommend first flattening your input layers and then using the \"Separate Layers\" mode. That way we also avoid the layer size problem and keep our network fast.\n\n### Order of Operations <a name=\"hdaOrderOfOperations\"></a>\nThe same as within SOPs, we have to pay attention to how we build our node network to have it perform well.\n\nLet's look at a wrong example and how to fix it:\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/dcc/houdini/hda/hdaOrderOfOperationSlow.mp4\" type=\"video/mp4\" alt=\"Houdini Order of Operations slow\">\n</video>\n\nHere is a more optimized result:\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/dcc/houdini/hda/hdaOrderOfOperationOptimized.mp4\" type=\"video/mp4\" alt=\"Houdini Order of Operations fast\">\n</video>\n\nThe name of the game is isolating your time dependencies. Now the above is often different how a production setup might look, but the important part is that we try to isolate each individual component that can stand by itself to a separate node stream before combining it into the scene via a merge node.\n\nIn our HDAs we can often build a separate network and then merge it into the main node stream, that way not everything has to re-cook, only the merge, if there is an upstream time dependency. \n\nNow you may have noticed that in the first video we also merged a node stream  with itself.\n\nIf Ghostbusters taught us one thing:\n\n~~~admonish danger title=\"Important | Merging node streams\"\nDon't cross the streams!*\n\n*(unless you use a layer break).\n~~~\n\nThe solution is simple, add a layer break (and make sure that your have the \"Strip Layers Above Layer Breaks\" toggle turned on). We have these \"diamond\" shaped networks quite a lot, so make sure you always layer break them correctly. For artists it can be convenient to build a HDA that does this for them.\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/dcc/houdini/hda/hdaOrderOfOperationsLayerBreak.mp4\" type=\"video/mp4\" alt=\"Houdini Merge Order\">\n</video>\n\n~~~admonish danger title=\"Important | Merging a layer stack with itself\"\nUSD is also very \"forgiving\", if we create content in a layer, that is already there from another layer (or layer stack via a reference or payload). The result is the same (due to composition), but the layer stack is \"doubled\". This is particularly risky and can lead to strange crashes, e.g. when we start to duplicate references on the same prim.\n\nNow if we do this in the same layer stack, everything is fine as our [list-editable ops](../../../core/composition/fundamentals.md#compositionFundamentalsListEditableOps) are merged in the active layer stack. So you'll only have the reference being loaded once, even though it occurs twice in the same layer stack.\n\nNow if we load a reference that is itself referenced, it is another story due to [encapsulation](../../../core/composition/fundamentals.md#compositionFundamentalsEncapsulation). We now have the layer twice, which gives us the same output visually/hierarchy wise, but our layers that are used by composition now has really doubled.\n\nCheck out this video for comparison:\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/dcc/houdini/hda/hdaOrderOfOperationsLayerStackDuplication.mp4\" type=\"video/mp4\" alt=\"Houdini Layer Stack Duplication\">\n</video>\n\n~~~\n\n\nWhat also is important, is the merge order. Now in SOPs we can just merge in any order, and our result is still the same (except the point order).\n\nFor LOPs this is different: The merge order is the sublayer order and therefore effects composition. As you can see in the video below, if we have an attribute that is the same in both layers (in this case the transform matrix), the order matters.\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/dcc/houdini/hda/hdaOrderOfOperationsMergeOrder.mp4\" type=\"video/mp4\" alt=\"Houdini Merge Order\">\n</video>\n\n### Dealing with time dependencies <a name=\"hdaTimeDependencies\"></a>\nAs with SOPs, we should also follow the design principle of keeping everything non-time dependent where possible.\n\nWhen we have time dependencies, we should always isolate them, cache them and then merge them into our \"main\" node stream.\n\n~~~admonish important title=\"Pro Tip | Writing Time Samples Via Python\"\nWhen writing Python code, we can write time samples for the full range too. See our [animation section](../../../core/elements/animation.md) for more info. We recommend using the lower level API, as it is a lot faster when writing a large time sample count. A typical example would be to write the per image output file or texture sequences via Python, as this is highly performant.\n~~~\n\nThe very cool thing with USD is that anything that comes from a cached file does not cause a Houdini time dependency, because the time samples are stored in the file/layer itself. This is very different to how SOPs works and can be confusing in the beginning.\n\nEssentially the goal with LOPs is to have no time dependency (at least when not loading live caches).\n\nStarting with H19.5 most LOP nodes can also whole frame range cache their edits. This does mean that a node can cook longer for very long frame ranges, but overall your network will not have a time dependency, which means when writing your node network to disk (for example for rendering), we only have to write a single frame and still have all the animation data. How cool is that! \n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/dcc/houdini/hda/hdaTimeDependencyPerNode.mp4\" type=\"video/mp4\" alt=\"Houdini Time Sample Per Node\">\n</video>\n\nIf a node doesn't have that option, we can almost always isolate that part of the network and pre cache it, that way we have the same effect but for a group of nodes.\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/dcc/houdini/hda/hdaTimeDependencyCache.mp4\" type=\"video/mp4\" alt=\"Houdini Time Sample Per Node\">\n</video>\n\n~~~admonish danger title=\"Important | Previewing Xform/Deformation Motionblur\"\nIf we want to preview xform/deformation motionblur that is not based on the `velocities`/`accelerations` attribute, then we have to pre-cache the time samples in interactive sessions. This is as simple as adding a LOPs cache node as shown above.\n~~~\n\nAlso check out our [Tips & Tricks section](../faq/overview.md#timeSampleValueMightBeTimeVarying) to see how we can query if an attribute is time sampled or only has a default value. This is a bit different in Houdini than bare-bone USD, because we often only have a single time sample for in session generated data.\n\n### Layer Size/Count <a name=\"hdaLayerSizeCount\"></a>\nAs mentioned in the [overview](#overview), layer content size can become an issue.\n\nWe therefore recommend starting of with a new layer and ending with a new layer. That way our HDA starts of fast, can create any amount of data and not affect downstream nodes.\n\nFor a full explanation see our [performance section](../performance/overview.md).\n\n## Composition <a name=\"hdaComposition\"></a>\nWe strongly recommend reading up on our [composition section](../../../core/composition/overview.md) before getting started in LOPs.\n\nWhen setting up composition arcs in Houdini, we can either do it via nodes or code. We recommend first doing everything via nodes and then refactoring it to be code based, as it is faster. Our custom HDAs are usually the ones that bring in data, as this is the core task of every pipeline.\n\nIn our [Tips & Tricks section](../faq/overview.md), we have provided these common examples:\n- [Extracting payloads and references from an existing layer stack with anonymous layers](../faq/overview.md#compositionReferencePayloadLayerStack)\n- [Efficiently re-writing existing hierarchies as variants](../faq/overview.md#compositionArcVariantReauthor)\n- [Adding overrides via inherits](../faq/overview.md#compositionArcInherit)\n\nThese provide entry points of how you can post-process data do you needs, after you have SOP imported it."
  },
  {
    "path": "docs/src/pages/dcc/houdini/overview.md",
    "content": "# Houdini\nHoudini's USD implementation, codenamed Solaris, is one of the most easy to use and \"getting started to USD\" entry points currently on the market.\n\nWe highly recommend grabbing a free-for-private use copy of Houdini via the [SideFX website](https://www.sidefx.com/).\n\nHoudini offers an extensive tool set around USD, often exposing common API calls as easy to use nodes. It therefore is also a great way to get started with the USD API, as the terminology is the same.\n\nIn this guide's Houdini section we focus on the production related side of USD. That means we cover things like:\n- How to best approach USD in Houdini, what to expect from a artist vs pipeline perspective\n- What Houdini handles differently to using native bare-bone USD\n- Typical pitfalls in common production scenarios\n- Optimizing HDAs and geometry import/export"
  },
  {
    "path": "docs/src/pages/dcc/houdini/performance/overview.md",
    "content": "# Performance Optimizations\nYou can find all the .hip files of our shown examples in our [USD Survival Guide - GitHub Repo](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/tree/main/files/dcc/houdini).\n\n# Table of Contents\n1. [Selection Rules](#houLopSelectionRule)\n1. [How to get your stage to load and open fast](#loadingMechanisms)\n1. [Write full time sample ranges (with subsamples)](#timeSample) \n1. [Layer Content Size](#layerContentSize)\n1. [Layer Count](#layerCount)\n1. [AOV Count](#renderAOVCount)\n\n## Selection Rules <a name=\"houLopSelectionRule\"></a>\nHoudini's [LOPs Selection Rule/Prim Pattern Matching](https://www.sidefx.com/docs/houdini/solaris/pattern.html) syntax is a artist friendly wrapper around stage traversals.\n\nPretty much any artist selectable prim pattern parm is/should be run through the selection rules. Now we won't cover how they work here, because Houdini's documentation is really detailed on this topic.\n\nInstead we'll compare it to our own [traversal section](../../../core/elements/loading_mechanisms.md#traverseData).\n~~~admonish tip title=\"\"\n```python\nimport hou\nrule = hou.LopSelectionRule()\n# Set traversal demand, this is similar to USD's traversal predicate\n# https://openusd.org/dev/api/prim_flags_8h.html#Usd_PrimFlags\nhou.lopTraversalDemands.Active\nhou.lopTraversalDemands.AllowInstanceProxies\nhou.lopTraversalDemands.Default\nhou.lopTraversalDemands.Defined\nhou.lopTraversalDemands.Loaded\nhou.lopTraversalDemands.NoDemands\nhou.lopTraversalDemands.NonAbstract\nrule.setTraversalDemands(hou.lopTraversalDemands.Default)\n# Set rule pattern\nrule.setPathPattern(\"%type:Boundable\")\n# Evaluate rule\nprim_paths = rule.expandedPaths(lopnode=None, stage=stage)\nfor prim_path in prim_paths:\n    print(prim_path) # Returns: Sdf.Path\n```\n~~~\n\nAs you can see we have a similar syntax, the predicate is \"replaced\" by hou.lopTraversalDemands.\n\nNow the same rules apply for fast traversals:\n- Fast traversals mean not going into the hierarchies we are not interested in. The equivalent to `iterator.PruneChildren` is the `~` tilde symbol (e.g. `%type:Xform ~ %kind:component`)\n- We should aim to pre-filter by type `%type:<ConcreteTypedSchemaName>` and kind `%kind:component`, before querying other data as this is fast\n- Attributes lookups (via vex in the expression) are heavy to compute\n\n## How to get your stage to load and open fast <a name=\"loadingMechanisms\"></a>\nAs discussed in our [Loading/Traversing section](../../../core/elements/loading_mechanisms.md), we can limit how stages are opened via our three loading mechanisms (ordered from lowest to highest granularity):\n- **Layer Muting**: This controls what layers are allowed to contribute to the composition result.\n- **Prim Population Mask**: This controls what prim paths to consider for loading at all.\n- **Payload Loading**: This controls what prim paths, that have payloads, to load.\n\nBefore we proceed, it is important to note, that USD is highly performant in loading hierarchies. When USD loads .usd/.usdc binary crate files, it sparsely loads the content: It can read in the hierarchy without loading in the attributes. This allows it to, instead of loading terabytes of data, to only read the important bits in the file and lazy load on demand the heavy data when requested by API queries or a hydra delegate.\n\nWhat does this mean for Houdini? It can often be enough to pause the scene viewer when opening the file. It can be done via this snippet:\n~~~admonish tip title=\"\"\n```python\nfor pane in hou.ui.paneTabs():\n    if pane.type == hou.paneTabType.SceneViewer:\n        pane.setSceneGraphStageLocked(False)\n```\n~~~\n\nHoudini exposes these three loading mechanisms in two different ways:\n- **Configure Stage** LOP node: This is the same as setting it per code via the stage.\n- **Scene Graph Tree** panel: In Houdini, that stage that gets rendered, is actually not the stage of your node (at least what we gather from reverse engineering). Instead it is a duplicate, that has overrides in the session layer and loading mechanisms listed above.\n\n~~~admonish danger title=\"Scene Graph Tree vs Configure Stage\"\nEverything you set in your scene graph tree panel is a viewport **only** override to your stage. This can be very confusing when first starting out in Houdini.\nIf we want to apply it to the actual stage, we have to use the configure stage node. This will then also affect our scene graph tree panel.\n\nWhy does Houdini do this? As mentioned hierarchy loading is fast, streaming the data to Hydra is not. This way we can still see the full hierarchy, but separately limit what the viewer sees, which is actually a pretty cool mechanism.\n~~~\n\nLet's have a look at the differences, as you can see anything we do with the configure stage node actually affects our hierarchy, whereas scene graph tree panel edits are only for the viewport:\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/core/elements/houdiniLoadingMechanisms.mp4\" type=\"video/mp4\" alt=\"Scene Graph Tree vs Configure Stage\">\n</video>\n\nAnother great tip is to disable tieing the scene graph panel to the active selected node:\n\n![Scene Graph Tree Panel Node Displayed](../../../../media/dcc/houdini/performance/houdiniSceneGraphTreePanelActiveNode.jpg)\n\nInstead it is then tied to you active display flag, which makes things a lot faster when clicking through your network.\n\n## Write full time sample ranges (with subsamples) <a name=\"timeSample\"></a>\nIn Houdini we always want to avoid time dependencies where possible, because that way the network doesn't have to recook the tree per frame.\n\nWe cover this in more detail for HDAs in our [HDA section](../hda/hda.md) as it is very important when building tools, but here is the short version.\n\nWe have two ways of caching the animation, so that the node itself loses its time dependency.\n\nStarting with H19.5 most LOP nodes can whole frame range cache their edits. This does mean that a node can cook longer for very long frame ranges, but overall your network will not have a time dependency, which means when writing your node network to disk (for example for rendering), we only have to write a single frame and still have all the animation data. How cool is that! \n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/dcc/houdini/hda/hdaTimeDependencyPerNode.mp4\" type=\"video/mp4\" alt=\"Houdini Time Sample Per Node\">\n</video>\n\nIf a node doesn't have that option, we can almost always isolate that part of the network and pre cache it, that way we have the same effect but for a group of nodes.\n\nThe common workflow is to link the shutter samples count to your camera/scene xform sample count and cache out the frames you need.\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/dcc/houdini/performance/timeSample.mp4\" type=\"video/mp4\" alt=\"Houdini Time Sample Subframes\">\n</video>\n\nWe recommend driving the parms through global variables or functions, that you can attach to any node via the node [onLoaded](https://www.sidefx.com/docs/houdini/hom/locations.html#scene_events) scripts.\n\nThis is also how you can write out SOP geometry with deform/xform subsamples, simply put the cache node after a \"SOP Import\" and set the mode to \"Sample Current Frame\".\nWe usually do this in combination with enabling \"Flush Data After Each Frame\" on the USD render rop plus adding \"$F4\" to your file path.\nThis way we stay memory efficient and dump the layer from memory to disk every frame. After that we stitch it via [value clips](../../../core/elements/animation.md#animationValueClips) or the \"UsdStitch\" commandline tool/rop node. \n\n\n## Layer Content Size <a name=\"layerContentSize\"></a>\nIn Houdini the size of the active layer can impact performance.\n\nTo quote from the docs:\n~~~admonish tip\nAs LOP layers have more and more opinions and values added, there can be slow-downs in the viewport. If you notice simple transforms are very slow in the viewport, try using a Configure Layer to start a new layer above where you're working, and see if that improves interactivity.\n~~~\nLet's build a test setup, where we provoke the problem on purpose:\n\n~~~admonish tip title=\"\"\n```python\nfrom pxr import Sdf\nnode = hou.pwd()\nlayer = node.editableLayer()\nwith Sdf.ChangeBlock():\n    root_grp_prim_path = Sdf.Path(f\"/root_grp\")\n    root_grp_prim_spec = Sdf.CreatePrimInLayer(layer, root_grp_prim_path)\n    root_grp_prim_spec.typeName = \"Xform\"\n    root_grp_prim_spec.specifier = Sdf.SpecifierDef\n    \n    prim_count = 1000 * 100\n    for idx in range(prim_count):\n        prim_path = Sdf.Path(f\"/root_grp/prim_{idx}\")\n        prim_spec = Sdf.CreatePrimInLayer(layer, prim_path)\n        prim_spec.typeName = \"Cube\"\n        prim_spec.specifier = Sdf.SpecifierDef\n        attr_spec = Sdf.AttributeSpec(prim_spec, \"debug\", Sdf.ValueTypeNames.Float)\n        attr_spec.default = float(idx)\n        if idx != 0:\n            prim_spec.SetInfo(prim_spec.ActiveKey, False)\n```\n~~~\n\n~~~admonish danger\nNow if we add an edit property node and tweak the \"debug\" attribute on prim \"/root_grp/prim_0\", it will take around 600 milliseconds!\n~~~\n\nThe simple solution as stated above is to simply add a \"Configure Layer\" LOP node and enable \"Start New Layer\". Now all edits are fast again.\n\nSo why is this slow? It is actually due to how Houdini makes node based editing of layers possible. Houdini tries to efficiently cache only the active layer, where all the edits go, per node (if a node did write operations). The active layer in Houdini speak is the same as the stage's edit target layer. This means every node creates a duplicate of the active layer, so that we can jump around the network and display different nodes, without recalculating everything all the time. The down side is the copying of the data, which is causing the performance hit we are seeing.\n\nThe solution is simple: Just start a new layer and then everything is fast again (as it doesn't have to copy all the content). Houdini colors codes its nodes every time they start a new (active) layer, so you'll also see a visual indicator that the nodes after the \"Configure Layer\" LOP are on a new layer.\n\n~~~admonish tip title=\"Pro Tip | Layer size in Hdas\"\nWhat does this mean for our .hda setups? The answer is simple: As there is no downside to having a large layer count (unless we start going into the thousands), each .hda can simply start of and end with creating a new layer. That way all the edits in the .hda are guaranteed to not be impacted by this caching issue.\n~~~\n\nHere is a comparison video:\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/dcc/houdini/performance/layerContentSize.mp4\" type=\"video/mp4\" alt=\"Layer Size\">\n</video>\n\n## Layer Count <a name=\"layerCount\"></a>\nNow as mentioned in the [layer content size](#layerContentSize) section, there is no down side to having thousands of layers. Houdini will merge these to a single (or multiple, depending on how you configured your save paths) layers on USD rop render. Since this is done on write, the described active layer stashing mechanism doesn't kick in and therefore it stays fast.\n\nDoes that mean we should write everything on a new layer? No, the sweet spot is somewhere in between. For example when grafting (moving a certain part of the hierarchy somewhere else) we also have to flatten the layer on purpose (Houdini's \"Scene Restructure\"/\"Graft\" nodes do this for us). At some layer count, you will encounter longer layer merging times, so don't over do it! This can be easily seen with the LOPs for loop.\n\n~~~admonish tip title=\"Pro Tip | Layer count\"\nSo as a rule of thumb: Encapsulate heavy layer edits with newly started layers, that way the next node downstream will run with optimal performance. Everything else is usually fine to be on the active input layer.\n~~~\n\nIn LOPs we also often work with the principle of having a \"main\" node stream (the stream, where your shot layers are loaded from). A good workflow would be to always put anything you merge into the main node stream into a new layer, as often these \"side\" streams create heavy data.\n\n~~~admonish danger title=\"Important | LOP 'For Each Loops'\"\nLOPs \"for each loops\" work a bit different: Each iteration of the loop is either merged with the active layer or kept as a separate layer, depending on the set merge style.\nWhen we want to spawn a large hierarchy, we recommend doing it via Python, as it is a lot faster. We mainly use the \"for each loop\" nodes for stuff we can't do in Python code. For example for each looping a sop import.\n\n![Houdini For Each Loop Merge Style](../../../../media/dcc/houdini/performance/houdiniForEachMergeStyle.jpg)\n~~~\n\n## AOV Count <a name=\"renderAOVCount\"></a>\nNow this tip is kind of obvious, but we'd though we'd mention it anyway:\n\nWhen rendering interactively in the viewport, deactivating render var prims that are connected to the render outputs you are rendering, can speed up interactivity. Why? We are rendering to fewer image buffers, so less memory consumption and less work for the renderer to output your rays to pixels.\n\nOur AOVs are connected via the `orderedVars` relationship to the render product. That means we can just overwrite it to only contain render vars we need during interactive sessions. For farm submissions we can then just switch back to all.\n\nThe same goes for the `products` relationship on your render settings prim. Here you can also just connect the products you need.\n\n~~~admonish tip title=\"\"\n```python\ndef Scope \"Render\"\n{\n    def Scope \"Products\"\n    {\n        def RenderProduct \"beauty\" (\n        )\n        {\n            rel orderedVars = [\n                </Render/Products/Vars/Beauty>,\n                </Render/Products/Vars/CombinedDiffuse>,\n                </Render/Products/Vars/DirectDiffuse>,\n                </Render/Products/Vars/IndirectDiffuse>,\n            ]\n            token productType = \"raster\"\n        }\n    }\n\n    def RenderSettings \"rendersettings\" (\n        prepend apiSchemas = [\"KarmaRendererSettingsAPI\"]\n    )\n    {\n        rel camera = </cameras/render_cam>\n        rel products = </Render/Products/beauty>\n        int2 resolution = (1280, 720)\n    }\n}\n```\n~~~\n\nIn Houdini this is as simple as editing the relationship and putting the edit behind a switch node with a context option switch. On our render USD rop we can then set the context option to 1 and there you go, it is now always on for the USD rop write.\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../../../media/dcc/houdini/performance/houdiniRenderAOVCount.mp4\" type=\"video/mp4\" alt=\"Houdini Render AOV Count\">\n</video>\n\n"
  },
  {
    "path": "docs/src/pages/dcc/overview.md",
    "content": "# Software Integrations\n"
  },
  {
    "path": "docs/src/pages/introduction/docs.md",
    "content": "# Documentation\n\nIf you want to locally build this documentation, you'll have to download [mdBook](https://github.com/rust-lang/mdBook), [mdBook-admonish](https://github.com/tommilligan/mdbook-admonish) and [mdBook-mermaid](https://github.com/badboy/mdbook-mermaid) and add their parent directories to the `PATH`env variable so that the executables are found.\n\nYou can do this via bash (after running `source setup.sh`):\n```bash\nexport MDBOOK_VERSION=\"0.4.28\"\nexport MDBOOK_ADMONISH_VERSION=\"1.9.0\"\nexport MDBOOK_MERMAID_VERSION=\"0.12.6\"\nexport MDBOOK_SITEMAP_VERSION=\"0.1.0\"\ncurl -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 ${REPO_ROOT}/tools\ncurl -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 ${REPO_ROOT}/tools\ncurl -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\nexport PATH=${REPO_ROOT}/tools:$PATH\n```\n\nYou then can just run the following to build the documentation in html format:\n```bash\n./docs.sh\n```\n\nThe documentation will then be built in docs/book."
  },
  {
    "path": "docs/src/pages/introduction/future.md",
    "content": "# Future Development\n\nWe do not cover the following topics yet:\n- Cameras\n- Render related schemas\n- USD C++\n- OCIO\n- Render Procedurals"
  },
  {
    "path": "docs/src/pages/introduction/motivation.md",
    "content": "\n# Motivation\nAs [USD](https://openusd.org/release/index.html) has been consistently increasing its market share in the recent years, it is definitely a technology to be aware of when working in any industry that uses 3d related data. It is becoming the de facto standard format on how different applications and vendors exchange their data.\n\nYou might be thinking:\n```admonish question title=\"\"\nOh no another guide! Do we really need this?\n```\n\nThis guide aims to solve the following 'niche':\n- It aims to be an onboarding guide for software developers & pipeline developers so that you can hit the ground running.\n- It aims to be practical as opposed to offering a high-level overview. This means you'll find a lot of code examples from actual production scenarios as well as a more hands on approach instead of overviews/terminology explanations. We'll often link to resources you can look into before a certain section to have a better understanding should vocabulary issues arise.\n- It aims to soften the steep learning curve that some aspects of USD have by having a look at common production examples so you can have those sweet \"aha, that's how it works\" moments.  \n\nBasically think of it as a balance of links listed in the below resources section.\n```admonish tip\nIf this is your first time working with Usd, we recommend watching this 20 minute video from Apple:\n\n[Understand USD fundamentals (Frm WWDC 2022)](https://developer.apple.com/videos/play/wwdc2022/10129/)\n\nIt covers the basic terminology in a very succinct manner.\n```\n\n## Resources\nWe highly recommend also checking out the following resources:\n\n- [USD - Pixar](https://openusd.org/release/index.html)\n- [USD - Interest Forum](https://groups.google.com/g/usd-interest)\n- [USD - Working Group](https://wiki.aswf.io/display/WGUSD)\n- [USD - SideFX/Houdini](https://www.sidefx.com/docs/houdini/solaris/usd.html)\n- [Book Of USD - Remedy Entertainment](https://remedy-entertainment.github.io/USDBook/index.html)\n- [USD CookBook - Colin Kennedy](https://github.com/ColinKennedy/USD-Cookbook)\n- [USD - Nvidia](https://developer.nvidia.com/usd)\n- [USD - Apple](https://developer.apple.com/videos/play/wwdc2022/10129/)\n\n```admonish info title=\"A big thank you to the VFX community!\"\nAt this point of the guide, we just want to state, that we didn't re-invent the wheel here: A big thank you to all the (open-source) projects/tutorials/guides that cover different aspects of Usd. You have been a big help in designing this guide as well as giving great insights. There is no one-to-rule them all documentation, so please consider contributing back to these projects if possible!\n```\n\n## Contributing and Acknowledgements\nPlease 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).\n\nFeel free to fork this repository and share further examples/improvements.\nIf you run into issues, please flag them by [submitting a ticket](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/issues/new).\n\n{{#include ../contributors.md}}\n"
  },
  {
    "path": "docs/src/pages/introduction/structure.md",
    "content": "\n# Structure\nOn this page will talk about how this guide is structured and what the best approach to reading it is.\n\n# Table of Contents\n1. [Structure](#structure)\n1. [Learning Path](#learningPath)\n1. [How To Run Our Code Examples](#code)\n\n## Structure <a name=\"structure\"></a>\nMost of our sections follow this simple template:\n- **Table of Contents**: Here we show the structure of the individual page, so we can jump to what we are interested in.\n- **TL;DR (Too Long; Didn't Read) - In-A-Nutshell**: Here we give a short summary of the page, the most important stuff without all the details.\n- **What should I use it for?**: Here we explain what relevance the page has in our day to day work with USD.\n- **Resources**: Here we provide external supplementary reading material, often the USD API docs or USD glossary.\n- **Overview**: Here we cover the individual topic in broad strokes, so you get the idea of what it is about.\n\nThis guide uses Houdini as its \"backbone\" for exploring concepts, as it is one of the easiest ways to get started with USD.\n\nYou can grab free-for-private use copy of Houdini via the [SideFX website](https://www.sidefx.com/). SideFX is the software development company behind the Houdini.\n\nAlmost all demos we show are from within Houdini, although you can also save the output of all our code snippets to a .usd file and view it in [USD view](../core/elements/standalone_utilities.md) or [USD manager](http://www.usdmanager.org/) by calling `stage.Export(\"/file/path.usd\")`/`layer.Export(\"/file/path.usd\")`\n\nYou can find all of our example files in our [Usd Survival Guide - GitHub Repository](\nhttps://github.com/LucaScheller/VFX-UsdSurvivalGuide/tree/main/files) as well in our supplementary [Usd Asset Resolver - GitHub Repository](https://lucascheller.github.io/VFX-UsdAssetResolver/). Among these files are Houdini .hip scenes, Python snippets and a bit of C++/CMake code.\n\nWe also indicate important to know tips with stylized blocks, these come in the form of:\n\n~~~admonish info title=\"Info | Useful information!\"\nInformation blocks give you \"good-to-know\" information.\n~~~\n\n~~~admonish info title=\"Pro Tip | Here is an advanced tip!\"\nWe often provide \"Pro Tips\" that give you pointers how to best approach advanced topics.\n~~~\n\n~~~admonish danger title=\"Danger | Here comes trouble!\"\nDanger blocks warn you about common pitfalls or short comings of USD and how to best workaround them.\n~~~\n\n~~~admonish tip title=\"Collapsible Block | Click me to show my content!\" collapsible=true\nFor longer code snippets, we often collapse the code block to maintain site readability.\n```python\nprint(\"Hello world!\")\n```\n~~~\n\n## Learning Path <a name=\"learningPath\"></a>\nWe recommend working through the guide from start to finish in chronological order. While we can do it in a random order, especially our [Basic Building Blocks of Usd](../core/elements/overview.md) and [Composition](../core/composition/overview.md) build on each other and should therefore be done in order.\n\nTo give you are fair warning though, we do deep dive a bit in the beginning, so just make sure you get the gist of it and then come back later when you feel like you need a refresher or deep dive on a specific feature.\n\n## How To Run Our Code Examples <a name=\"code\"></a>\nWe also have code blocks, where if you hover other them, you can copy the content to you clipboard by pressing the copy icon on the right.\nMost of our code examples are \"containered\", meaning they can run by themselves. \n\nThis does come with a bit of the same boiler plate code per example. The big benefit though is that we can just copy and run them and don't have to initialize our environment.\n\nMost snippets create in memory stages or layers. If we want to use the snippets in a Houdini Python LOP, we have to replace the stage/layer access as follows:\n\n~~~admonish danger title=\"Danger | Houdini Python LOP Stage/Layer access\"\nIn Houdini we can't call `hou.pwd().editableStage()` and `hou.pwd().editableLayer()` in the same Python LOP node.\nTherefore, when running our high vs low level API examples, make sure you are using two different Python LOP nodes.\n~~~\n\n~~~admonish tip title=\"\"\n```python\nfrom pxr import Sdf, Usd\n## Stages\n# Native USD\nstage = Usd.Stage.CreateInMemory()\n# Houdini Python LOP\nstage = hou.pwd().editableStage()\n## Layers\n# Native USD\nlayer = Sdf.Layer.CreateAnonymous()\n# Houdini Python LOP\nlayer = hou.pwd().editableLayer()\n```\n~~~\n\n\n"
  },
  {
    "path": "docs/src/pages/production/caches/attribute.md",
    "content": "# Attribute Queries <a name=\"attribute\"></a>\nWhen we query attribute via `Usd.Attribute.Get()`, the value source resolution is re-evaluated on every call.\nThis can be cached by using `Usd.AttributeQuery(<prim>, <attributeName>)`. This small change can already bring a big performance boost, when looking up a large time sample count. In our example below, it doubled the speed.\n\nFor value clips the speed increase is not as high, as the value source can vary between clips.\n\nThe `Usd.AttributeQuery` object has a very similar signature to the `Usd.Attribute`. We can also get the time sample count, bracketing time samples and time samples within an interval.\nFor more information, check out the [official API docs](https://openusd.org/dev/api/class_usd_attribute_query.html).\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/production/caches.py:stageQueryAttribute}}\n```\n~~~\n\n# Primvars Queries <a name=\"primvars\"></a>\nAs mentioned in our [properties](../../core/elements/property.md#reading-inherited-primvars) section, we couldn't get the native `FindIncrementallyInheritablePrimvars` primvars API method to work correctly. That's why we implemented it ourselves here, which should be nearly as fast, as we are not doing any calls into parent prims and tracking the inheritance ourselves.\n\nIt's also a great example of when to use `.PreAndPostVisit()` prim range iterators.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/production/caches.py:stageQueryInheritedPrimvars}}\n```\n~~~"
  },
  {
    "path": "docs/src/pages/production/caches/boundingbox.md",
    "content": "# Bounding Box Queries <a name=\"boundingbox\"></a>\nWhenever we change our geometry data, we have to update our \"extents\" attribute on [boundable prims](https://openusd.org/dev/api/class_usd_geom_boundable.html). The bbox cache allows us to efficiently query bounding boxes. The result is always returned in the form of a `Gf.BBox3d` object.\n\nFor some production related examples, check out our [Frustum Culling](../../dcc/houdini/fx/frustumCulling.md) and [Particles](../../dcc/houdini/fx/particles.md) sections.\n\nCheckout the [official API docs](https://openusd.org/dev/api/class_usd_geom_b_box_cache.html) for more info.\n\nThe \"extents\" attribute is managed via the `UsdGeom.Boundable` schema, you can find the [docs](https://openusd.org/dev/api/class_usd_geom_boundable.html) here. This has to be set per boundable prim.\n\nThe \"extensHint\" attribute is managed via the `UsdGeom.ModeAPI`, you can find the [docs](https://openusd.org/dev/api/class_usd_geom_model_a_p_i.html) here. This can be used to accelerate lookups, by not looking into the child-hierarchy. We typically write it on prims that load payloads, to have extent data when the payload is unloaded.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/production/caches.py:stageQueryBBox}}\n```\n~~~"
  },
  {
    "path": "docs/src/pages/production/caches/collection.md",
    "content": "# 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 collections work, check out our [Collections](../../core/elements/collection.md) section.\n\n### Creating & querying collections <a name=\"collectionQuery\"></a>\nWe interact with collectins via the `Usd.CollectionAPI` class [API Docs](https://openusd.org/release/api/class_usd_collection_a_p_i.html). The collection api is a multi-apply API schema, so we can add multiple collections to any prim. We can them access them via the collection API. The `UsdUtils` module also offers some useful functions to recompute collections so that they don't consume to much disk storage.\n\nHere are the UsdUtils.ComputeCollectionIncludesAndExcludes [API docs](https://openusd.org/dev/api/authoring_8h.html#ad2939a973bd544ff30e4828ff09765db).\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:collectionOverview}}\n```\n~~~\n\n### Inverting a collection <a name=\"collectionInvert\"></a>\nWhen we want to isolate a certain part of the hierarchy (for example to pick what to render), a typical thing to do, is to give users a \"render\" collection which then gets applied by setting all prims not included to be [inactive](./prim.md#active). Here is an example of how to iterate a stage by pruning (skipping the child traversal) and deactivating anything that is not in the specific collection.\n\nThis is very fast and \"sparse\" as we don't edit leaf prims, instead we find the highest parent and deactivate it, if no children are part of the target collection.\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/elements.py:collectionInvert}}\n```\n~~~\n"
  },
  {
    "path": "docs/src/pages/production/caches/composition.md",
    "content": "# Composition Query\nNext let's look at prim composition queries. Instead of having to filter the prim index ourselves, we can use the `Usd.PrimCompositionQuery` to do it for us. For more info check out our [Inspecting Composition](../../core/composition/pcp.md) section.\n\nThe query works by specifying a filter and then calling `GetCompositionArcs`.\n\nUSD provides these convenience filters, it returns a new `Usd.PrimCompositionQuery` instance with the filter applied:\n- `Usd.PrimCompositionQuery.GetDirectInherits(prim)`: Returns all non ancestral inherit arcs\n- `Usd.PrimCompositionQuery.GetDirectReferences(prim)`: Returns all non ancestral reference arcs\n- `Usd.PrimCompositionQuery.GetDirectRootLayerArcs(prim)`: Returns arcs that were defined in the active layer stack.\n\nThese are the sub-filters that can be set. We can only set a single token value per filter:\n- **ArcTypeFilter**: Filter based on different arc(s).\n- **DependencyTypeFilter**: Filter based on if the arc was introduced on a parent prim or on the prim itself.\n- **ArcIntroducedFilter**: Filter based on where the arc was introduced.\n- **HasSpecsFilter**: Filter based if the arc has any specs (For example an inherit might not find any in the active layer stack)\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../../code/core/composition.py:pcpPrimCompositionQuery}}\n```\n~~~\n\nThe returned filtered `Usd.CompositionArc` objects, allow us to inspect various things about the arc. You can find more info in the [API docs](https://openusd.org/dev/api/class_usd_prim_composition_query_arc.html)\n"
  },
  {
    "path": "docs/src/pages/production/caches/materialbinding.md",
    "content": "# Material Binding <a name=\"materialBinding\"></a>\n~~~admonish question title=\"Still under construction!\"\nThis sub-section is still under development, we'll add more advanced binding lookups in the near future!\n~~~\n\nLooking up material bindings is as simple as running `materials, relationships = UsdShade.MaterialBindingAPI.ComputeBoundMaterials([<list of prims>]`.\nThis gives us the bound material as a `UsdShade.Material` object and the relationship that bound it.\nThat means if the binding came from a parent prim, we'll get the `material:binding` relationship from the parent.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/production/caches.py:stageQueryMaterialBinding}}\n```\n~~~"
  },
  {
    "path": "docs/src/pages/production/caches/overview.md",
    "content": "# Stage API Query Caches\nWhen inspecting stages, we often want to query a lot of data.\n\nSome types of data, like transforms/material bindings or primavars, are inherited down the hierarchy. Instead of re-querying the ancestor data for each leaf prim query, USD ships with various query classes that cache their result, so that repeated queries have faster look ups.\n\nFor currently cover these query caches:\n- [Xforms](./xform.md)\n- [BoundingBox](./boundingbox.md)\n- [Attribute/(Inherited) Primvars](./attribute.md)\n- [Material Binding](./materialbinding.md)\n- [Collection Membership](./collection.md)\n- [Composition](./composition.md)"
  },
  {
    "path": "docs/src/pages/production/caches/xform.md",
    "content": "# Xform Queries <a name=\"xform\"></a>\nAs mentioned in our [transforms section](../../core/elements/transform.md), we can batch query transforms via the `UsdGeom.XformCache()`.\n\nIt caches ancestor parent xforms, so that when we query leaf prims under the same parent hierarchy, the lookup retrieves the cached parent xforms. The cache is managed per time code, so if we use `XformCache.SetTime(Usd.TimeCode(<someOtherFrame>))`, it clears the cache and re-populates it on the next query for the new time code.\n\nCheckout the [official API docs](https://openusd.org/dev/api/class_usd_geom_xform_cache.html) for more info.\n\n~~~admonish info title=\"\"\n```python\n{{#include ../../../../../code/production/caches.py:stageQueryTransform}}\n```\n~~~"
  },
  {
    "path": "docs/src/pages/production/composition.md",
    "content": "# A practical guide to composition\n~~~admonish question title=\"Still under construction!\"\nAs composition is USD's most complicated topic, this section will be enhanced with more examples in the future.\nIf you detect an error or have useful production examples, please [submit a ticket](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/issues/new), so we can improve the guide!\n\nIn the near future, we'll add examples for:\n- Best practice asset structures\n- Push Vs Pull / FullPin Opt-In pipelines\n~~~\n\n~~~admonish tip\nWe have a supplementary Houdini scene, that you can follow along with, available in this [site's repository](https://github.com/LucaScheller/VFX-UsdSurvivalGuide/tree/main/files/composition). All the examples below will walk through this file as it easier to prototype and showcase arcs in Houdini via nodes, than writing it all in code.\n~~~\n\n### How to approach shot composition\nWhen prototyping your shot composition, we recommend an API like approach to loading data:\n\nWe create a `/__CLASS__/assets` and a `/__CLASS__/shots/<layer_name>` hierarchy. All shot layers first load assets via references and shot (fx/anim/etc.) caches via payloads into their respective class hierarchy. We then inherit this into the actual \"final\" hierarchy. This has one huge benefit: \n\nThe class hierarchy is a kind of \"API\" to your scene hierarchy. For example if we want to time shift (in USD speak layer offset) an asset that has multiple occurrences in our scene, we have a single point of control where we have to change the offset. Same goes for any other kind of edit. \n\nWe take a look at variations of this pattern in our [Composition Strength Ordering (LIVRPS)](../core/composition/livrps.md) section in context of different arcs, we highly recommend looking through the \"Pro Tip\" sections there.\n\nThis approach solves composition \"problems\": When we want to payload something over an asset reference, we can't because the payload arc is weaker than the reference arc. By \"proxying\" it to a class prim and then inheriting it, we guarantee that it always has the strongest opinion. This makes it easier to think about composition, as it is then just a single list-editable op rather than multiple arcs coming from different sources.\n\nThe downside to this approach is that we (as pipeline devs) need to restructure all imports to always work this way. The cache files themselves can still write the \"final\" hierarchy, we just have to reference/payload it all in to the class hierarchy and then inherit it. This may sound like a lot of work, but it is actually quick to setup and definitely helps us/artists keep organized with larger scenes. \n\nIt also keeps our whole setup [instanceable](../core/composition/livrps.md#compositionInstance), so that we have the best possible performance. \n\n~~~admonish danger title=\"Pro Tip | Instanceable Prims\"\nWhen creating our composition structure concept, we should always try to keep everything instanceable until the very last USD file (the one that usually gets rendered). This way we ensure optimal performance and scalability.\n~~~\n\nWe also show an example for this approach in our [Composition Payloads section](../core/composition/livrps.md#compositionArcPayloadLoadWorkflow) as well as bellow in the next bullet point.\n\n### Loading heavy caches into your shots\nWhen writing heavy caches, we usually write per frame/chunk files and load them via value clips. Let's have a look how to best do this:\nAs a best practice we always want to keep everything [instanceable](../core/composition/livrps.md#compositionInstance), so let's keep that in mind when loading in the data. \n\n~~~admonish tip title=\"Pro Tip | How do we load value clipped files?\"\n- When making prims instanceable, the value clip metadata has to be under the instanceable prim, as the value clip metadata can't be read from outside of the instance (as it would then mean each instance could load different clips, which would defeat the purpose of instanceable prims).\n- Value clip metadata can't be inherited/internally referenced/specialized in. It must reside on the prim as a direct opinion.\n- We can't have data above the prims where we write our metadata. In a typical asset workflow, this means that all animation is below the asset prims (when using value clips).\n~~~\n\nLet's have a look how we can set it up in Houdini while prototyping, in production you should do this via code, see our [animation](../core/elements/animation.md#animationValueClips) section for how to do this.\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../media/production/compositionValueClipAbstraction.mp4\" type=\"video/mp4\" alt=\"Houdini Value Clip Composition\">\n</video>\n\nThe simplest version is to write the value clips, stitch them and load the resulting file as a payload per asset root prim. This doesn't work though, if you have to layer over a hierarchy that already exists, for example an asset.\n\nWe therefore go for the \"API\" like approach as discussed above: We first load the cache via a payload into a class hierarchy and then inherit it onto its final destination. This is a best-practise way of loading it. By \"abstracting\" the payload to class prims, we have a way to load it via any arc we want, for example we could also payload it into variants. By then inherting it to the \"final\" hierarchy location, we ensure that no matter what arc, the cache gets loaded. This way we can load the cache (as it has heavy data) as payloads and then ensure it gets loaded with the highest opinion (via inherits).\n\nLet's also take a look at why this doesn't work when trying to write value clips at non asset root prims:\n\n<video width=\"100%\" height=\"100%\" controls autoplay muted loop>\n  <source src=\"../../media/production/compositionValueClipAbstractionStageRoot.mp4\" type=\"video/mp4\" alt=\"Houdini Value Clip Composition\">\n</video>\n\nLoading a payload for a whole cache file works, the problem you then run into though is, that the inherit arcs don't see the parent prims value clip metadata. So we'd have to load the whole layer as a value clip. While this is possible, we highly don't recommend it, as it is not clear where the data source is coming from and we are making the scene structure messy by not having clear points of data loading. We also can't make it instanceable (unles we intend on making the whole hierarchy instanceable, which in shots doesn't work because we need per prim overrides (on at least asset (parent) prims))."
  },
  {
    "path": "docs/src/pages/production/concepts.md",
    "content": "# Advanced Concepts\n\n# Table of Contents\n1. [Edit Targets](#editTargets)\n1. [Utility functions in the Usd.Utils module](#usdUtils)\n1. [Utility functions in the Sdf module](#sdf)\n    1. [Moving/Renaming/Removing prim/property/variant specs with Sdf.BatchNamespaceEdit()](#sdfBatchNamespaceEdit)\n    1. [Copying data with Sdf.CopySpec](#sdfCopySpec)\n    1. [Delaying change notifications with the Sdf.ChangeBlock](#sdfChangeBlock)\n1. [Relationships](#relationship)\n    1. [Special Relationships](#relationshipSpecial)\n    1. [Relationship Forwarding (Binding post)](#relationshipForwarding)\n    1. [Collections](#relationshipCollection)\n\n## Edit Targets\n~~~admonish tip title=\"Pro Tip | Edit Targets\"\nA edit target defines, what layer all calls in the high level API should write to.\n~~~\n\nAn edit target's job is to map from one namespace to another, we mainly use them for writing to layers in the active layer stack (though we could target any layer) and to write variants, as these are written \"inline\" and therefore need an extra name space injection. \n\nWe cover edit targets in detail in our [composition fundamentals](../core/composition/fundamentals.md#compositionFundamentalsEditTarget) section.\n\n## Utility functions in the Usd.Utils module <a name=\"utilsUsdUtils\"></a>\nUsd provides a bunch of utility functions in the `UsdUtils` module ([USD Docs](https://openusd.org/dev/api/flatten_layer_stack_8h.html)):\n\nFor retrieving/upating dependencies:\n- **UsdUtils.ExtractExternalReferences**: This is similar to `layer.GetCompositionAssetDependencies()`, except that it returns three lists: `[<sublayers>], [<references>], [<payloads>]`. It also consults the assetInfo metadata, so result might be more \"inclusive\" than `layer.GetCompositionAssetDependencies()`.\n- **UsdUtils.ComputeAllDependencies**: This recursively calls `layer.GetCompositionAssetDependencies()` and gives us the aggregated result.\n- **UsdUtils.ModifyAssetPaths**: This is similar to Houdini's output processors. We provide a function that gets the input path and returns a (modified) output path.\n\nFor animation and value clips stitching:\n- Various tools for stitching/creating value clips. We cover these in our [animation section](../core/elements/animation.md#animationValueClips). These are also what the commandline tools that ship with USD use.\n\nFor collection authoring/compression:\n- We cover these in detail in our [collection section](../core/elements/collection.md#collectionQuery).\n\n## Utility functions in the Sdf module <a name=\"sdf\"></a>\n\n### Moving/Renaming/Removing prim/property/variant specs with Sdf.BatchNamespaceEdit() <a name=\"sdfBatchNamespaceEdit\"></a>\nWe've actually used this quite a bit in the guide so far, so in this section we'll summarize its most important uses again:\n\n#### Using Sdf.BatchNamespaceEdit() moving/renaming/removing prim/property (specs)\nWe main usage is to move/rename/delete prims. We can only run the name space edit on a layer, it does not work with stages.\nThats means if we have nested composition, we can't rename prims any more. In production this means we'll only be using this\nwith the \"active\" layer, that we are currently creating/editing. All the edits added are run in the order they are added,\nwe have to be careful what order we add removes/renames if they interfere with each other.\n\n~~~admonish tip title=\"Sdf.BatchNamespaceEdit | Moving/renaming/removing prim/property specs | Click to expand!\" collapsible=true\n```python\n{{#include ../../../../code/production/production.py:productionConceptsSdfBatchNamespaceMoveRenameDelete}}\n```\n~~~\n\n#### Using Sdf.BatchNamespaceEdit() for variant creation\nWe can create variant via the namespace edit, because variants are in-line USD namespaced paths.\n\n~~~admonish tip title=\"Sdf.BatchNamespaceEdit | Moving prim specs into variants | Click to expand!\" collapsible=true\n```python\n{{#include ../../../../code/production/production.py:productionConceptsSdfBatchNamespaceEditVariant}}\n```\n~~~\n\nWe also cover variants in detail in respect to Houdini in our [Houdini - Tips & Tricks](../dcc/houdini/faq/overview.md) section.\n\n### Copying data with Sdf.CopySpec <a name=\"sdfCopySpec\"></a>\nWe use the `Sdf.CopySpec` method to copy/duplicate content from layer to layer (or within the same layer).\n\n#### Copying specs (prim and properties) from layer to layer with Sdf.CopySpec()\nThe `Sdf.CopySpec` can copy anything that is representable via the `Sdf.Path`. This means we can copy prim/property/variant specs.\nWhen copying, the default is to completely replace the target spec. \n\nWe can filter this by passing in filter functions. Another option is to copy the content to a new anonymous layer and then\nmerge it via `UsdUtils.StitchLayers(<StrongLayer>, <WeakerLayer>)`. This is often more \"user friendly\" than implementing\na custom merge logic, as we get the \"high layer wins\" logic for free and this is what we are used to when working with USD.\n\n~~~admonish question title=\"Still under construction!\"\nWe'll add some examples for custom filtering at a later time.\n~~~\n\n~~~admonish tip title=\"Sdf.CopySpec | Copying prim/property specs | Click to expand!\" collapsible=true\n```python\n{{#include ../../../../code/production/production.py:productionConceptsSdfCopySpecStandard}}\n```\n~~~\n\n#### Using Sdf.CopySpec() for variant creation\nWe can also use `Sdf.CopySpec` for copying content into a variant.\n\n~~~admonish tip title=\"Sdf.CopySpec | Copying prim specs into variants | Click to expand!\" collapsible=true\n```python\n{{#include ../../../../code/production/production.py:productionConceptsSdfCopySpecVariant}}\n```\n~~~\n\nWe also cover variants in detail in respect to Houdini in our [Houdini - Tips & Tricks](../dcc/houdini/faq/overview.md) section.\n\n### Delaying change notifications with the Sdf.ChangeBlock <a name=\"sdfChangeBlock\"></a>\nWhenever we edit something in our layers, change notifications get sent to all consumers (stages/hydra delegates) that use the layer. This causes them to recompute and trigger updates.\n\nWhen performing a large edit, for example creating large hierarchies, we can batch the edit, so that the change notification gets the combined result.\n\n~~~admonish danger title=\"Pro Tip | When/How to use Sdf.ChangeBlocks\"\nIn theory it is only safe to use the change block with the lower level Sdf API.\nWe can also use it with the high level API, we just have to make sure that we don't accidentally query an attribute, that we just overwrote or perform ops on deleted properties.\n\nWe therefore recommend work with a read/write code pattern:\n- We first query all the data via the Usd high level API\n- We then write our data via the Sdf low level API\n\nWhen writing data, we can also write it to a temporary anonymous layer, that is not linked to a stage and then merge the result back in via `UsdUtils.StitchLayers(anon_layer, active_layer)`. This is a great solution when it is to heavy to query all data upfront.\n~~~\n\nFor more info see the [Sdf.ChangeBlock](https://openusd.org/dev/api/class_sdf_change_block.html) API docs.\n\n~~~admonish tip title=\"\"\n```python\n{{#include ../../../../code/production/production.py:productionConceptsSdfChangeBlock}}\n```\n~~~\n\n## Relationships <a name=\"relationship\"></a>\n\n### Special Relationships <a name=\"relationshipSpecial\"></a>\n~~~admonish question title=\"Still under construction!\"\nThis sub-section is still under development, it is subject to change and needs extra validation.\n~~~\nUSD has a few \"special\" relationships that infer information on our hierarchy. These are:\n- `proxyPrim`: This is a relationship from a prim with a render purpose to a prim with a proxy purpose. It can be used by clients to get low-resolution proxy representations (for example for simulations/collision detection etc.). Setting it is optional.\n\nThese special relationships have primvar like inheritance from parent to child prims:\n- `material:binding`: This controls the material binding.\n- `coordSys:<customName>`: Next to collections, this is currently the only other multi-apply API schema that ships natively with USD. It allows us to target an xform prim, whose transform we can then read into our shaders at render time.\n- `skel:skeleton`/`skel:animationSource`:\n    - `skel:skeleton`: This defines what skeleton prims with the skelton binding api schema should bind to.\n    - `skel:animationSource`: This relationship can be defined on mesh prims to target the correct animation, but also on the skeletons themselves to select the skeleton animation prim.\n\n### Relationship Forwarding (Binding post) <a name=\"relationshipForwarding\"></a>\n~~~admonish question title=\"Still under construction!\"\nThis sub-section is still under development, it is subject to change and needs extra validation.\n~~~\n\n### Collections <a name=\"relationshipCollection\"></a>\nWe cover collections in detail in our [collection section](../core/elements/collection.md#collectionQuery) with advanced topics like inverting or compressing collections."
  },
  {
    "path": "docs/src/pages/production/faq.md",
    "content": "# FAQ (Frequently Asked Questions)\n\n# Table of Contents\n1. [Should I prefer assets with a lot of prims or prefer combined meshes?](#faqPrimCount)\n1. [How is \"Frames Per Second\" (FPS) handled in USD?](#faqFPS)\n1. [How is the scene scale unit handled in USD?](#faqSceneScale)\n\n## Should I prefer assets with a lot of prims or prefer combined meshes? <a name=\"faqPrimCount\"></a>\nWhen working in hierarchy based formats, an important influence factor of performance is the hierarchy size.\n\n~~~admonish important title=\"Pro Tip | Hierarchy Size\"\nBasically it boils down to these rules:\nKeep hierarchies as small as possible at all times, only start creating separates meshes when:\n- your mesh point/prim count starts going into the millions\n- you need to assign different render geometry settings\n- you need to add different transforms\n- you need to hide the prims individually\n- you need separate materials (We can also use `UsdGeom.Subset`s, which are face selections per mesh, to assign materials, to workaround this)\n~~~\n\nAt the end of the day it is a balancing act of **What do I need to be able to access separately in the hierarchy** vs **I have a prim that is super heavy (100 Gbs of data) and takes forever to load**.\nA good viewpoint is the one of a lighting/render artist, as they are the ones that need to often work on individual (sub-)hierarchies and can say how it should be segmented.\n\n## How is \"frames per second\" (FPS) handled in USD? <a name=\"faqFPS\"></a>\nOur time samples that are written in the time unit-less `{<frame>: <value> }` format are interpreted based on the `timeCodesPerSecond`/`framesPerSecond` metadata set in the session/root layer.\n\n```python\n(\n    endTimeCode = 1010\n    framesPerSecond = 24\n    metersPerUnit = 1\n    startTimeCode = 1001\n    timeCodesPerSecond = 24\n)\n```\nYou can find more details about the specific metadata priority and how to set the metadata in our [animation section](../core/elements/animation.html#animationMetadata).\n\n## How is the scene scale unit and up axis handled in USD? <a name=\"faqSceneScale\"></a>\nWe can supply an up axis and scene scale hint in the layer metadata, but this does not seem to be used by most DCCs or in fact Hydra itself when rendering the geo. So if you have a mixed values, you'll have to counter correct via transforms yourself.\n\nThe default scene `metersPerUnit` value is centimeters (0.01) and the default `upAxis` is `Y`.\n\nYou can find more details about how to set these metrics see our [layer metadata section](../core/elements/metadata.md#readingwriting-stage-and-layer-metrics-fpsscene-unit-scaleup-axis-highlow-level-api)."
  },
  {
    "path": "docs/src/pages/production/overview.md",
    "content": "# USD in Production\nIn this section we'll take a look at USD from a production perspective.\n\nIt aims to cover more higher level concepts and pitfalls that we should avoid when first starting out in USD.\n"
  },
  {
    "path": "docs/src/pages/production/prerequisites.md",
    "content": "# 'Are we ready for production'? Here is a preflight checklist for your USD pipeline\nNow that you know the basics (if you did your homework 😉), let's make sure you are ready for your first test flight.\n\nBelow is a checklist that you can use to test if everything is ready to go.\n\n~~~admonish warning title=\"\"\nYou can never prepare a 100%, some times you gotta run before you walk as the experience (and pressure) from an actual project running on USD will be more valuable than any RnD. So make sure you have kept the points below in mind to at least some degree.\n~~~\n\nVocabulary:\n- Usd comes with a whole lot of new words, as a software developer you'll get used to it quite quickly, but don't forget about your users. Having an onboarding for vocab is definitely worth it, otherwise everyone speaks a different language which can cause a lot of communication overhead. \n\nPlugins (Covered in our [plugins](../core/plugins/overview.md) section):\n- **Kinds** (Optional, Recommended): All you need for this one, is a simple .json file that you put in your `PXR_PLUGINPATH_NAME` search path. \n- **Schemas** (Optional, Recommended): There are two flavours of creating custom schemas: Codeless (only needs a `schema.usda` + `plugInfo.json` file) and compiled schemas (Needs compilation, but gives your software devs a better UX). If you don't have the resources for a C++ developer, codeless schemas are the way to go and more than enough to get you started.\n- **Asset Resolver** (Mandatory): You unfortunately can't get around not using one, luckily we got you covered with our production ready asset resolvers over in our [VFX-UsdAssetResolver GitHub Repo](https://github.com/LucaScheller/VFX-UsdAssetResolver).\n\nData IO and Data Flow:\n- As a pipeline/software developer the core thing that has to work is data IO. This is something a user should never have to think about. What does this mean for you:\n    - Make sure your UX experience isn't too far from what artists already know.\n- Make sure that your system of tracking layers and how your assets/shots are structured is solid enough to handle these cases:\n    - Assets with different layers (model/material/fx/lighting)\n    - FX (Asset and Shot FX, also make sure that you can also track non USD dependencies, like .bgeo, via metadata/other means)\n    - Assemblies (Assets that reference other assets)\n    - Multi-Shot workflows (Optional)\n    - Re-times (Technically these are not possible via USD (at least over a whole layer stack), so be aware of the restrictions and communicate these!)\n- It is very likely that you have to adjust certain aspects of how you handle composition at some point. In our [composition](../core/composition/overview.md) section we cover composition from an abstract implementation viewpoint, that should help keep your pipeline flexible down the line. It is one of the ways how you can be prepared for future eventualities, it does add a level of complexity though to your setups (pipeline wise, users should not have to worry about this).\n\n"
  },
  {
    "path": "docs/src/pages/production/schemas.md",
    "content": "# Commonly used schemas ('Classes' in OOP terminology) for production\n\nHere is a list of the most used production schemas with a short explanation of what the schema provides:\n\n- Typed:\n    - [UsdGeom.Imageable](https://openusd.org/dev/api/class_usd_geom_imageable.html): Purpose, Visibility, Bounding Box\n        - [UsdGeom](https://openusd.org/dev/api/usd_geom_page_front.html)\n            - [UsdGeom.PointInstancer](https://openusd.org/dev/api/class_usd_geom_point_instancer.html): PointInstancers\n            - [UsdGeom.PointBased](https://openusd.org/dev/api/class_usd_geom_point_based.html):\n                - [UsdGeom.Mesh](https://openusd.org/dev/api/class_usd_geom_mesh.html): Polygon Meshes\n                - [UsdGeom.Points](https://openusd.org/dev/api/class_usd_geom_points.html): Points\n                - [UsdGeom.Curves](https://openusd.org/dev/api/class_usd_geom_curves.html): Curves\n            - [UsdVol.Volume](https://openusd.org/dev/api/class_usd_vol_volume.html): Volumes\n                - [UsdVol.OpenVDBAsset](https://openusd.org/dev/api/class_usd_vol_open_v_d_b_asset.html): VDB Volumes\n            - [UsdGeom.Xformable](https://openusd.org/dev/api/class_usd_geom_xformable.html): Transforms\n            - [UsdGeom.Boundable](https://openusd.org/dev/api/class_usd_geom_boundable.html): Extents\n            - [UsdGeom.Camera](https://openusd.org/dev/api/class_usd_geom_camera.html): Camera Attributes, Access to Gf.Camera\n- API:\n    - [Usd.ModeAPI](https://openusd.org/dev/api/class_usd_model_a_p_i.html): Asset info, Kind \n    - [UsdGeom.ModelAPI](https://openusd.org/dev/api/class_usd_geom_model_a_p_i.html): Draw Mode, ExtentHint\n    - [Usd.ClipsAPI](https://openusd.org/dev/api/class_usd_clips_a_p_i.html): Value Clips (Metadata for per frame caches)\n    - [Usd.CollectionAPI](https://openusd.org/dev/api/class_usd_collection_a_p_i.html): Collections\n    - [Usd.PrimvarsAPI](https://openusd.org/dev/api/class_usd_geom_primvars_a_p_i.html): Primvars Attributes\n    - [UsdGeom.XformCommonAPI](https://openusd.org/dev/api/class_usd_geom_xform_common_a_p_i.html): Simplified transforms\n    - [Usd.VisibilityAPI (Beta)](https://openusd.org/dev/api/class_usd_geom_visibility_a_p_i.html): Visibility per purpose\n    - [UsdSkel.BindingAPI](https://openusd.org/dev/api/class_usd_skel_binding_a_p_i.html): Skeleton bindings\n    - [UsdShade.ConnectableAPI](https://openusd.org/dev/api/class_usd_shade_connectable_a_p_i.html): Shader connections\n    - [UsdShade.CoordSysAPI](https://openusd.org/dev/api/class_usd_shade_coord_sys_a_p_i.html): Coordinate spaces for shaders\n- Graphics Foundations (Gf):\n    - [Gf.Camera](https://openusd.org/dev/api/class_gf_camera.html): Camera\n    - [Gf.Frustum](https://openusd.org/dev/api/class_gf_frustum.html): Frustum"
  },
  {
    "path": "docs/src/template.md",
    "content": "# Section Name\nEnter example intro.\n\n~~~admonish question title=\"Still under construction!\"\nThis sub-section is still under development, it is subject to change and needs extra validation.\n~~~\n\n# Table of Contents\n1. [<Topic> In-A-Nutshell](#summary)\n1. [What should I use it for?](#usage)\n1. [Resources](#resources)\n1. [Overview](#overview)\n1. [Example A](#exampleA)\n    1. [Subexample A](#subexampleA)\n    1. [Subexample B](#subexampleB)\n\n## TL;DR - <Topic> In-A-Nutshell <a name=\"summary\"></a>\n- Main points to know\n\n## What should I use it for? <a name=\"usage\"></a>\n~~~admonish tip\nSummarize actual production relevance.\n~~~\n\n## Resources <a name=\"resources\"></a>\n- [API Docs]()\n\n## Overview <a name=\"overview\"></a>\nChart example\n```mermaid\nflowchart TD\n    usdObject([\"Usd.Object (Includes Metadata API)\"]) --> usdPrim([Usd.Prim])\n    usdObject --> usdProperty([Usd.Property])\n    usdProperty --> usdAttribute([Usd.Attribute])\n    usdProperty --> usdRelationship([Usd.Relationship])\n    usdStage([\"Usd.Stage (Includes Metadata API)\"])\n```\n\nLow Level API\n```mermaid\nflowchart TD\n    sdfSpec([\"Sdf.Spec (Includes Metadata API)\"]) --> sdfPropertySpec([Sdf.Property])\n    sdfSpec --> sdfPrimSpec([Sdf.PrimSpec])\n    sdfSpec --> sdfVariantSetSpec([Sdf.VariantSetSpec])\n    sdfSpec --> sdfVariantSpec([Sdf.VariantSpec])\n    sdfPropertySpec --> sdfAttributeSpec([Sdf.AttributeSpec])\n    sdfPropertySpec --> sdfRelationshipSpec([Sdf.RelationshipSpec])\n    sdfLayer([\"Sdf.Layer (Includes Metadata API)\"])\n\n```\n\n~~~admonish tip\nExample tip\n~~~\n\n## Example A <a name=\"exampleA\"></a>\nExample A\n\n### Subexample A <a name=\"subexampleA\"></a>\nExample A\n\n### Subexample B <a name=\"subexampleB\"></a>\nExample A"
  },
  {
    "path": "docs/theme/ext/css/custom.css",
    "content": "table {\n    width:100%;\n}\n\n:root {\n    --sidebar-width: 485px;\n    --content-max-width: 1300px;\n}\n\n.chapter li {\n    color: inherit;\n}\n\n.chapter > .chapter-item:first-child {\n    font-weight: bold;\n    font-size: 150%;\n}\n\nol.chapter li ol.section li.chapter-item.expanded a.active {\n    font-size: 1em;\n    font-weight: 400;\n    display: inline-block;\n    border-left: .25rem solid transparent;\n    border-left-color: var(--inline-code-color);\n    padding: .35rem 1rem .35rem 1.25rem;\n    box-sizing: border-box;\n}\n\n.nav-chapters {\nmax-width: 35px;\nmin-width: 30px;\n}"
  },
  {
    "path": "docs/theme/ext/css/mdbook-admonish.css",
    "content": "@charset \"UTF-8\";\n:root {\n  --md-admonition-icon--note:\n    url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20.71 7.04c.39-.39.39-1.04 0-1.41l-2.34-2.34c-.37-.39-1.02-.39-1.41 0l-1.84 1.83 3.75 3.75M3 17.25V21h3.75L17.81 9.93l-3.75-3.75L3 17.25z'/></svg>\");\n  --md-admonition-icon--abstract:\n    url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M17 9H7V7h10m0 6H7v-2h10m-3 6H7v-2h7M12 3a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1m7 0h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2z'/></svg>\");\n  --md-admonition-icon--info:\n    url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M13 9h-2V7h2m0 10h-2v-6h2m-1-9A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10A10 10 0 0 0 12 2z'/></svg>\");\n  --md-admonition-icon--tip:\n    url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M17.66 11.2c-.23-.3-.51-.56-.77-.82-.67-.6-1.43-1.03-2.07-1.66C13.33 7.26 13 4.85 13.95 3c-.95.23-1.78.75-2.49 1.32-2.59 2.08-3.61 5.75-2.39 8.9.04.1.08.2.08.33 0 .22-.15.42-.35.5-.23.1-.47.04-.66-.12a.58.58 0 0 1-.14-.17c-1.13-1.43-1.31-3.48-.55-5.12C5.78 10 4.87 12.3 5 14.47c.06.5.12 1 .29 1.5.14.6.41 1.2.71 1.73 1.08 1.73 2.95 2.97 4.96 3.22 2.14.27 4.43-.12 6.07-1.6 1.83-1.66 2.47-4.32 1.53-6.6l-.13-.26c-.21-.46-.77-1.26-.77-1.26m-3.16 6.3c-.28.24-.74.5-1.1.6-1.12.4-2.24-.16-2.9-.82 1.19-.28 1.9-1.16 2.11-2.05.17-.8-.15-1.46-.28-2.23-.12-.74-.1-1.37.17-2.06.19.38.39.76.63 1.06.77 1 1.98 1.44 2.24 2.8.04.14.06.28.06.43.03.82-.33 1.72-.93 2.27z'/></svg>\");\n  --md-admonition-icon--success:\n    url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='m9 20.42-6.21-6.21 2.83-2.83L9 14.77l9.88-9.89 2.83 2.83L9 20.42z'/></svg>\");\n  --md-admonition-icon--question:\n    url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='m15.07 11.25-.9.92C13.45 12.89 13 13.5 13 15h-2v-.5c0-1.11.45-2.11 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41a2 2 0 0 0-2-2 2 2 0 0 0-2 2H8a4 4 0 0 1 4-4 4 4 0 0 1 4 4 3.2 3.2 0 0 1-.93 2.25M13 19h-2v-2h2M12 2A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10c0-5.53-4.5-10-10-10z'/></svg>\");\n  --md-admonition-icon--warning:\n    url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M13 14h-2V9h2m0 9h-2v-2h2M1 21h22L12 2 1 21z'/></svg>\");\n  --md-admonition-icon--failure:\n    url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6.91 17.09 4 12 9.09 6.91 4 4 6.91 9.09 12 4 17.09 6.91 20 12 14.91 17.09 20 20 17.09 14.91 12 20 6.91z'/></svg>\");\n  --md-admonition-icon--danger:\n    url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M11 15H6l7-14v8h5l-7 14v-8z'/></svg>\");\n  --md-admonition-icon--bug:\n    url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M14 12h-4v-2h4m0 6h-4v-2h4m6-6h-2.81a5.985 5.985 0 0 0-1.82-1.96L17 4.41 15.59 3l-2.17 2.17a6.002 6.002 0 0 0-2.83 0L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8z'/></svg>\");\n  --md-admonition-icon--example:\n    url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M7 13v-2h14v2H7m0 6v-2h14v2H7M7 7V5h14v2H7M3 8V5H2V4h2v4H3m-1 9v-1h3v4H2v-1h2v-.5H3v-1h1V17H2m2.25-7a.75.75 0 0 1 .75.75c0 .2-.08.39-.21.52L3.12 13H5v1H2v-.92L4 11H2v-1h2.25z'/></svg>\");\n  --md-admonition-icon--quote:\n    url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M14 17h3l2-4V7h-6v6h3M6 17h3l2-4V7H5v6h3l-2 4z'/></svg>\");\n  --md-details-icon:\n    url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M8.59 16.58 13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.42Z'/></svg>\");\n}\n\n:is(.admonition) {\n  display: flow-root;\n  margin: 1.5625em 0;\n  padding: 0 1.2rem;\n  color: var(--fg);\n  page-break-inside: avoid;\n  background-color: var(--bg);\n  border: 0 solid black;\n  border-inline-start-width: 0.4rem;\n  border-radius: 0.2rem;\n  box-shadow: 0 0.2rem 1rem rgba(0, 0, 0, 0.05), 0 0 0.1rem rgba(0, 0, 0, 0.1);\n}\n@media print {\n  :is(.admonition) {\n    box-shadow: none;\n  }\n}\n:is(.admonition) > * {\n  box-sizing: border-box;\n}\n:is(.admonition) :is(.admonition) {\n  margin-top: 1em;\n  margin-bottom: 1em;\n}\n:is(.admonition) > .tabbed-set:only-child {\n  margin-top: 0;\n}\nhtml :is(.admonition) > :last-child {\n  margin-bottom: 1.2rem;\n}\n\na.admonition-anchor-link {\n  display: none;\n  position: absolute;\n  left: -1.2rem;\n  padding-right: 1rem;\n}\na.admonition-anchor-link:link, a.admonition-anchor-link:visited {\n  color: var(--fg);\n}\na.admonition-anchor-link:link:hover, a.admonition-anchor-link:visited:hover {\n  text-decoration: none;\n}\na.admonition-anchor-link::before {\n  content: \"§\";\n}\n\n:is(.admonition-title, summary) {\n  position: relative;\n  min-height: 4rem;\n  margin-block: 0;\n  margin-inline: -1.6rem -1.2rem;\n  padding-block: 0.8rem;\n  padding-inline: 4.4rem 1.2rem;\n  font-weight: 700;\n  background-color: rgba(68, 138, 255, 0.1);\n  display: flex;\n}\n:is(.admonition-title, summary) p {\n  margin: 0;\n}\nhtml :is(.admonition-title, summary):last-child {\n  margin-bottom: 0;\n}\n:is(.admonition-title, summary)::before {\n  position: absolute;\n  top: 0.625em;\n  inset-inline-start: 1.6rem;\n  width: 2rem;\n  height: 2rem;\n  background-color: #448aff;\n  mask-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"></svg>');\n  -webkit-mask-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"></svg>');\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-size: contain;\n  content: \"\";\n}\n:is(.admonition-title, summary):hover a.admonition-anchor-link {\n  display: initial;\n}\n\ndetails.admonition > summary.admonition-title::after {\n  position: absolute;\n  top: 0.625em;\n  inset-inline-end: 1.6rem;\n  height: 2rem;\n  width: 2rem;\n  background-color: currentcolor;\n  mask-image: var(--md-details-icon);\n  -webkit-mask-image: var(--md-details-icon);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-size: contain;\n  content: \"\";\n  transform: rotate(0deg);\n  transition: transform 0.25s;\n}\ndetails[open].admonition > summary.admonition-title::after {\n  transform: rotate(90deg);\n}\n\n:is(.admonition):is(.note) {\n  border-color: #448aff;\n}\n\n:is(.note) > :is(.admonition-title, summary) {\n  background-color: rgba(68, 138, 255, 0.1);\n}\n:is(.note) > :is(.admonition-title, summary)::before {\n  background-color: #448aff;\n  mask-image: var(--md-admonition-icon--note);\n  -webkit-mask-image: var(--md-admonition-icon--note);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.abstract, .summary, .tldr) {\n  border-color: #00b0ff;\n}\n\n:is(.abstract, .summary, .tldr) > :is(.admonition-title, summary) {\n  background-color: rgba(0, 176, 255, 0.1);\n}\n:is(.abstract, .summary, .tldr) > :is(.admonition-title, summary)::before {\n  background-color: #00b0ff;\n  mask-image: var(--md-admonition-icon--abstract);\n  -webkit-mask-image: var(--md-admonition-icon--abstract);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.info, .todo) {\n  border-color: #00b8d4;\n}\n\n:is(.info, .todo) > :is(.admonition-title, summary) {\n  background-color: rgba(0, 184, 212, 0.1);\n}\n:is(.info, .todo) > :is(.admonition-title, summary)::before {\n  background-color: #00b8d4;\n  mask-image: var(--md-admonition-icon--info);\n  -webkit-mask-image: var(--md-admonition-icon--info);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.tip, .hint, .important) {\n  border-color: #00bfa5;\n}\n\n:is(.tip, .hint, .important) > :is(.admonition-title, summary) {\n  background-color: rgba(0, 191, 165, 0.1);\n}\n:is(.tip, .hint, .important) > :is(.admonition-title, summary)::before {\n  background-color: #00bfa5;\n  mask-image: var(--md-admonition-icon--tip);\n  -webkit-mask-image: var(--md-admonition-icon--tip);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.success, .check, .done) {\n  border-color: #00c853;\n}\n\n:is(.success, .check, .done) > :is(.admonition-title, summary) {\n  background-color: rgba(0, 200, 83, 0.1);\n}\n:is(.success, .check, .done) > :is(.admonition-title, summary)::before {\n  background-color: #00c853;\n  mask-image: var(--md-admonition-icon--success);\n  -webkit-mask-image: var(--md-admonition-icon--success);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.question, .help, .faq) {\n  border-color: #64dd17;\n}\n\n:is(.question, .help, .faq) > :is(.admonition-title, summary) {\n  background-color: rgba(100, 221, 23, 0.1);\n}\n:is(.question, .help, .faq) > :is(.admonition-title, summary)::before {\n  background-color: #64dd17;\n  mask-image: var(--md-admonition-icon--question);\n  -webkit-mask-image: var(--md-admonition-icon--question);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.warning, .caution, .attention) {\n  border-color: #ff9100;\n}\n\n:is(.warning, .caution, .attention) > :is(.admonition-title, summary) {\n  background-color: rgba(255, 145, 0, 0.1);\n}\n:is(.warning, .caution, .attention) > :is(.admonition-title, summary)::before {\n  background-color: #ff9100;\n  mask-image: var(--md-admonition-icon--warning);\n  -webkit-mask-image: var(--md-admonition-icon--warning);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.failure, .fail, .missing) {\n  border-color: #ff5252;\n}\n\n:is(.failure, .fail, .missing) > :is(.admonition-title, summary) {\n  background-color: rgba(255, 82, 82, 0.1);\n}\n:is(.failure, .fail, .missing) > :is(.admonition-title, summary)::before {\n  background-color: #ff5252;\n  mask-image: var(--md-admonition-icon--failure);\n  -webkit-mask-image: var(--md-admonition-icon--failure);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.danger, .error) {\n  border-color: #ff1744;\n}\n\n:is(.danger, .error) > :is(.admonition-title, summary) {\n  background-color: rgba(255, 23, 68, 0.1);\n}\n:is(.danger, .error) > :is(.admonition-title, summary)::before {\n  background-color: #ff1744;\n  mask-image: var(--md-admonition-icon--danger);\n  -webkit-mask-image: var(--md-admonition-icon--danger);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.bug) {\n  border-color: #f50057;\n}\n\n:is(.bug) > :is(.admonition-title, summary) {\n  background-color: rgba(245, 0, 87, 0.1);\n}\n:is(.bug) > :is(.admonition-title, summary)::before {\n  background-color: #f50057;\n  mask-image: var(--md-admonition-icon--bug);\n  -webkit-mask-image: var(--md-admonition-icon--bug);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.example) {\n  border-color: #7c4dff;\n}\n\n:is(.example) > :is(.admonition-title, summary) {\n  background-color: rgba(124, 77, 255, 0.1);\n}\n:is(.example) > :is(.admonition-title, summary)::before {\n  background-color: #7c4dff;\n  mask-image: var(--md-admonition-icon--example);\n  -webkit-mask-image: var(--md-admonition-icon--example);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.quote, .cite) {\n  border-color: #9e9e9e;\n}\n\n:is(.quote, .cite) > :is(.admonition-title, summary) {\n  background-color: rgba(158, 158, 158, 0.1);\n}\n:is(.quote, .cite) > :is(.admonition-title, summary)::before {\n  background-color: #9e9e9e;\n  mask-image: var(--md-admonition-icon--quote);\n  -webkit-mask-image: var(--md-admonition-icon--quote);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n.navy :is(.admonition) {\n  background-color: var(--sidebar-bg);\n}\n\n.ayu :is(.admonition), .coal :is(.admonition) {\n  background-color: var(--theme-hover);\n}\n\n.rust :is(.admonition) {\n  background-color: var(--sidebar-bg);\n  color: var(--sidebar-fg);\n}\n.rust .admonition-anchor-link:link, .rust .admonition-anchor-link:visited {\n  color: var(--sidebar-fg);\n}\n"
  },
  {
    "path": "docs/theme/ext/js/custom.js",
    "content": ""
  },
  {
    "path": "docs/theme/ext/js/mermaid-init.js",
    "content": "mermaid.initialize({startOnLoad:true});\n"
  },
  {
    "path": "docs/theme/head.hbs.bkp",
    "content": "<!-- SEO \n<meta name=\"robots\" content=\"index, follow\">\n<meta name=\"googlebot\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\">\n<meta name=\"bingbot\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\">\n-->"
  },
  {
    "path": "docs/theme/header.hbs",
    "content": "\n<div  class=\"\" style=\"display: none; width:100%; position: relative; top: 25.0px; margin-bottom: -45.0px; z-index: 1000;\">\n<div id=\"admonition-success\" class=\"admonition success\">\n<div class=\"admonition-title\">\n<p>Siggraph Presentation</p>\n<p><a class=\"admonition-anchor-link\" href=\"#admonition-success\"></a></p>\n</div>\n<div>\n<p>This guide will be officially introduced at <a href=\"https://www.sidefx.com/houdini-hive/siggraph-2023/\">Siggraph 2023 - Houdini Hive</a> on Wednesday, 9. of August 2023 at 11:00 AM PST.</p>\n</div>\n</div>\n</div>"
  },
  {
    "path": "docs.bat",
    "content": "REM Source setup\nset REPO_ROOT=%~dp0\nREM Clean existing build\nrmdir %REPO_ROOT%docs\\book /S /Q\nREM Build book\nmdbook serve --open %REPO_ROOT%docs"
  },
  {
    "path": "docs.sh",
    "content": "# Source setup\nexport REPO_ROOT=$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" &> /dev/null && (pwd -W 2> /dev/null || pwd))\n# Clean existing builds\nrm -R ${REPO_ROOT}/docs/book\n# Build book\nmdbook serve --open ${REPO_ROOT}/docs\n"
  },
  {
    "path": "files/composition/pixar/faq/WhenCanYouDeleteAReference/assembly.usda",
    "content": "#usda 1.0\n(\n    defaultPrim = \"FlexibleSet\"\n)\n\ndef Xform \"FlexibleSet\"\n{\n    def \"Model_1\" (\n        prepend variantSets = \"dressingVariant\"\n        variants = {\n            string dressingVariant = \"default\"\n        }\n    )\n    {\n        variantSet \"dressingVariant\" = {\n            \"default\" (\n                references = @assets.usda@</CubeModel>\n            )\n            {\n            }\n        }\n\n        # Anything added at the set level has nesting level 1\n        custom int levelOfNesting = 1\n    }\n}\n"
  },
  {
    "path": "files/composition/pixar/faq/WhenCanYouDeleteAReference/assembly_with_all_variants.usda",
    "content": "#usda 1.0\n(\n    defaultPrim = \"FlexibleSet\"\n)\n\ndef Xform \"FlexibleSet\"\n{\n    def \"Model_1\" (\n        prepend variantSets = \"dressingVariant\"\n        variants = {\n            string dressingVariant = \"default\"\n        }\n    )\n    {\n        variantSet \"dressingVariant\" = {\n            \"default\" (\n                references = @assets.usda@</CubeModel>\n            )\n            {\n            }\n\t    \"shotOverride_1\" (\n\t\t    references = @assets.usda@</SphereModel>\n\t    )\n\t    {\n\t    }\n        }\n\n        # Anything added at the set level has nesting level 1\n        custom int levelOfNesting = 1\n    }\n}\n"
  },
  {
    "path": "files/composition/pixar/faq/WhenCanYouDeleteAReference/assets.usda",
    "content": "#usda 1.0\n\ndef Xform \"CubeModel\"\n{\n    custom int levelOfNesting = 0\n\n    def Cube \"Gprim\"\n    {\n    }\n}\n\ndef Xform \"SphereModel\"\n{\n    custom int levelOfNesting = 0\n\n    def Sphere \"Gprim\"\n    {\n    }\n}\n"
  },
  {
    "path": "files/composition/pixar/faq/WhenCanYouDeleteAReference/shot.usda",
    "content": "#usda 1.0\n(\n    defaultPrim = \"World\"\n)\n\ndef Xform \"World\"\n{\n    def \"ShapeFactory\" (\n        references = @assembly.usda@\n    )\n    {\n        over \"Model_1\" (\n            prepend variantSets = \"dressingVariant\"\n            variants = {\n                string dressingVariant = \"shotOverride_1\"\n            }\n        )\n        {\n            variantSet \"dressingVariant\" = {\n                \"shotOverride_1\" (\n                    references = @assets.usda@</SphereModel>\n                )\n                {\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "files/composition/pixar/faq/WhenCanYouDeleteAReference/shot_variant_switch.usda",
    "content": "#usda 1.0\n(\n    defaultPrim = \"World\"\n)\n\ndef Xform \"World\"\n{\n    def \"ShapeFactory\" (\n        references = @assembly_with_all_variants.usda@\n    )\n    {\n        over \"Model_1\" (\n\n            variants = {\n                string dressingVariant = \"shotOverride_1\"\n            }\n        )\n        {\n        }\n    }\n}\n"
  },
  {
    "path": "files/composition/pixar/glossary/inherits/Forest.usd",
    "content": "#usda 1.0\n\n# A new prim, of the same name as the original inherits target, providing new overrides\nclass \"_class_Tree\"\n{\n    token size = \"small\"\n\n    # It's autumn in California\n    over \"Leaves\"\n    {\n        color3f[] primvars:displayColor = [(1.0, .1, .1)]\n    }\n}\n\n# TreeB_1 still inherits from _class_Tree because its referent does\ndef \"TreeB_1\" (\n    references = @./Trees.usd@</TreeB>\n)\n{\n}\n"
  },
  {
    "path": "files/composition/pixar/glossary/inherits/Trees.usd",
    "content": "#usda 1.0\n\nclass Xform \"_class_Tree\"\n{\n    def Mesh \"Trunk\"\n    {\n        color3f[] primvars:displayColor = [(.8, .8, .2)]\n    }\n\n    def Mesh \"Leaves\"\n    {\n        color3f[] primvars:displayColor = [(0, 1, 0)]\n    }\n}\n\ndef \"TreeA\" (\n    inherits = </_class_Tree>\n)\n{\n}\n\ndef \"TreeB\" (\n    inherits = </_class_Tree>\n)\n{\n    over \"Leaves\"\n    {\n        color3f[] primvars:displayColor = [(0.8, 1, 0)]\n    }\n}\n"
  },
  {
    "path": "files/composition/pixar/glossary/references/FlattenedMarbleCollection.usd",
    "content": "#usda 1.0\n\ndef Xform \"MarbleCollection\" (\n    kind = \"assembly\"\n)\n{\n    def Xform \"Marble_Green\" (\n        kind = \"component\"\n    )\n    {\n        double3 xformOp:translate = (-10, 0, 0)\n        uniform token[] xformOpOrder = [ \"xformOp:translate\" ]\n\n        def Sphere \"marble_geom\"\n        {\n            color3f[] primvars:displayColor = [ (0, 1, 0) ]\n        }\n    }\n\n    def Xform \"Marble_Red\" (\n        kind = \"component\"\n    )\n    {\n        double3 xformOp:translate = (5, 0, 0)\n        uniform token[] xformOpOrder = [ \"xformOp:translate\" ]\n\n        def Sphere \"marble_geom\"\n        {\n            color3f[] primvars:displayColor = [ (1, 0, 0) ]\n        }\n    }\n}\n\n\n"
  },
  {
    "path": "files/composition/pixar/glossary/references/Marble.usd",
    "content": "#usda 1.0\n(\n    defaultPrim = \"Marble\"\n)\n\ndef Xform \"Marble\" (\n    kind = \"component\"\n)\n{\n    def Sphere \"marble_geom\"\n    {\n        color3f[] primvars:displayColor = [ (0, 1, 0) ]\n    }\n}\n"
  },
  {
    "path": "files/composition/pixar/glossary/references/MarbleCollection.usd",
    "content": "#usda 1.0\n\ndef Xform \"MarbleCollection\" (\n    kind = \"assembly\"\n)\n{\n    def \"Marble_Green\" (\n            references = @Marble.usd@\n        )\n    {\n        double3 xformOp:translate = (-10, 0, 0)\n        uniform token[] xformOpOrder = [ \"xformOp:translate\" ]\n    }\n\n    def \"Marble_Red\" (\n        references = @Marble.usd@\n    )\n    {\n        double3 xformOp:translate = (5, 0, 0)\n        uniform token[] xformOpOrder = [ \"xformOp:translate\" ]\n\n        over \"marble_geom\"\n        {\n            color3f[] primvars:displayColor = [ (1, 0, 0) ]\n        }\n    }\n}\n"
  },
  {
    "path": "files/composition/pixar/glossary/specializes/Robot.usd",
    "content": "#usda 1.0\n\ndef Xform \"Robot\"\n{\n    def Scope \"Materials\"\n    {\n        def Material \"Metal\"\n        {\n            # Interface inputs drive shader parameters of the encapsulated\n            # network. We are not showing the connections, nor how we encode\n            # that the child Shader \"Surface\" is the primary output for the\n            # material.\n            float inputs:diffuseGain = 0\n            float inputs:specularRoughness = 0\n\n            def Shader \"Surface\"\n            {\n                asset info:id = @PxrSurface@\n            }\n        }\n\n        def Material \"CorrodedMetal\" (\n            specializes = </Robot/Materials/Metal>\n        )\n        {\n            # specialize roughness...\n            float inputs:specularRoughness = 0.2\n\n            # Adding a pattern to drive Surface bump\n            def Shader \"Corrosion\"\n            {\n                asset info:id = @PxrOSL@\n                vector3f outputs:disp\n            }\n\n            over \"Surface\"\n            {\n                # Override that would connect specularBump to Corrosion\n                # pattern's \"outputs:disp\" attribute\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "files/composition/pixar/glossary/specializes/RobotScene.usd",
    "content": "#usda 1.0\n\ndef Xform \"World\"\n{\n    def Xform \"Characters\"\n    {\n        def \"Rosie\" (\n            references = @./Robot.usd@</Robot>\n        )\n        {\n            over \"Materials\"\n            {\n                over \"Metal\"\n                {\n                     float inputs:diffuseGain = 0.3\n                     float inputs:specularRoughness = 0.1\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "files/composition/usdSurvivalGuide/.gitignore",
    "content": "*.usdnc"
  },
  {
    "path": "files/dcc/houdini/points/pythonWrangle.py",
    "content": "import pxr\nimport numpy as np\n\nclass Tokens():\n    mode = \"vfxSurvivalGuide:attributeKernel:mode\"\n    module_code = \"vfxSurvivalGuide:attributeKernel:moduleCode\"\n    execute_code = \"vfxSurvivalGuide:attributeKernel:executeCode\"\n    bindings = \"vfxSurvivalGuide:attributeKernel:bindings\"\n\nclass Binding():\n    fallback_value_type_name = pxr.Sdf.ValueTypeNames.FloatArray\n    def __init__(self):\n        self.property_name = \"\"\n        self.variable_name = \"\"\n        self.value_type_name = \"\"\n\nclass Point():\n    def __init__(self, bindings):\n        self.ptnum = -1\n        self.bindings = bindings\n        for binding in self.bindings:\n            setattr(self, binding.variable_name, None)\n                \nclass Points():\n    def __init__(self):\n        self.bindings = []\n        for binding in self.bindings:\n            setattr(self, binding.variable_name, [])\n          \ndef run_kernel(stage, frame):\n    # Process\n    for prim in stage.Traverse():\n        attr = prim.GetAttribute(Tokens.bindings)\n        if not attr:\n            continue\n        if not attr.HasValue():\n            continue\n\n        mode = prim.GetAttribute(Tokens.mode).Get(frame)\n        module_code = prim.GetAttribute(Tokens.module_code).Get(frame)\n        execute_code = prim.GetAttribute(Tokens.execute_code).Get(frame)\n        bindings_serialized = eval(prim.GetAttribute(Tokens.bindings).Get(frame))\n        \n        # Bindings\n        bindings = []\n        for binding_dict in bindings_serialized:\n            binding = Binding()\n            binding.property_name = binding_dict[\"property_name\"]\n            binding.variable_name = binding_dict[\"variable_name\"]\n            binding.value_type_name = binding_dict[\"value_type_name\"]\n            bindings.append(binding)\n        # Kernel\n        module_code_compiled = compile(module_code, \"module_code\", \"exec\")\n        execute_code_compiled = compile(execute_code, \"code\", \"exec\")\n        exec(module_code_compiled)\n        # Read data\n        input_data = {}\n        input_point_count = -1\n        output_data = {}\n        output_point_count = -1\n        initialize_attrs = []\n        for binding in bindings:\n            # Read attribute or create default fallback value\n            attr = prim.GetAttribute(binding.property_name)\n            if not attr:   \n                value_type_name_str = binding.fallback_value_type_name if binding.value_type_name == \"automatic\" else binding.value_type_name\n                value_type_name = getattr(pxr.Sdf.ValueTypeNames, value_type_name_str)\n                attr = prim.CreateAttribute(binding.property_name, value_type_name)\n            if attr.HasValue():\n                input_data[binding.property_name] = np.array(attr.Get(frame))\n                input_point_count = max(input_point_count, len(input_data[binding.property_name]))\n            else:\n                initialize_attrs.append(attr)\n            # Enforce interpolation to points\n            attr.SetMetadata(pxr.UsdGeom.Tokens.interpolation, pxr.UsdGeom.Tokens.vertex)\n            output_data[binding.property_name] = []\n        for initialize_attr in initialize_attrs:\n            input_data[initialize_attr.GetName()] = np.array([initialize_attr.GetTypeName().scalarType.defaultValue] * input_point_count)\n        # Utils\n        def npoints():\n            return input_point_count\n        # Modes\n        if mode == \"kernel\":\n            # Kernel Utils\n            points_add = []\n            points_remove = set()\n            def create_point():\n                point = Point(bindings)\n                points_add.append(point)\n            def copy_point(source_point):\n                point = Point(source_point.bindings)\n                for binding in point.bindings:\n                    setattr(point, binding.variable_name, np.copy(getattr(source_point, binding.variable_name)))\n                points_add.append(point)\n                return point\n            def remove_point(point):\n                points_remove.add(point.ptnum)\n            # Kernel\n            point = Point(bindings)\n            for elemnum in range(len(list(input_data.values())[0])):\n                point.ptnum = elemnum\n                for binding in bindings:\n                    setattr(point, binding.variable_name, input_data[binding.property_name][elemnum])\n                # User Kernel Start\n                exec(execute_code_compiled)\n                # User Kernel End\n                if points_remove and point.ptnum in points_remove:\n                    continue\n                for binding in bindings:\n                    output_data[binding.property_name].append(getattr(point, binding.variable_name))\n            for binding in bindings:\n                for point_add in points_add:\n                    output_data[binding.property_name].append(getattr(point_add, binding.variable_name))\n            for binding in bindings:\n                output_data[binding.property_name] = np.array(output_data[binding.property_name])\n                output_point_count = max(output_point_count, len(output_data[binding.property_name]))\n        elif mode == \"array\":\n            points = Points()\n            for binding in bindings:\n                setattr(points, binding.variable_name, input_data[binding.property_name])\n            # User Kernel Start\n            exec(execute_code_compiled)\n            # User Kernel End\n            for binding in bindings:\n                output_data[binding.property_name] = getattr(points, binding.variable_name)\n                output_point_count = max(output_point_count, len(output_data[binding.property_name]))\n        # If the output is invalid, block it to prevent segfaults\n        if input_point_count != output_point_count:\n            for attr in prim.GetAttributes():\n                if attr.GetName() in input_data.keys():\n                    continue\n                if not attr.HasValue():\n                    continue\n                if not attr.GetTypeName().isArray:\n                    continue\n                if len(attr.Get(frame)) == output_point_count:\n                    continue\n                attr.Set(pxr.Sdf.ValueBlock())\n        # Write data\n        for binding in bindings:\n            attr = prim.GetAttribute(binding.property_name)\n            if len(output_data[binding.property_name]) != output_point_count:\n                attr.Set(pxr.Sdf.ValueBlock())\n                continue\n            attr_class = attr.GetTypeName().type.pythonClass\n            attr.Set(attr_class.FromNumpy(output_data[binding.property_name]), frame)\n        # Re-Compute extent hints\n        boundable_api = pxr.UsdGeom.Boundable(prim)\n        extent_attr = boundable_api.GetExtentAttr()\n        extent_value = pxr.UsdGeom.Boundable.ComputeExtentFromPlugins(boundable_api, frame)\n        if extent_value:\n            extent_attr.Set(extent_value, frame)\n"
  },
  {
    "path": "files/dcc/houdini/points/renderPreFrame.py",
    "content": "import os\nimport sys\nfrom imp import reload\n# Python Wrangle Module\ndir_path = os.path.dirname(hou.hipFile.path())\nif dir_path not in sys.path:\n    sys.path.insert(0, dir_path)\nimport pythonWrangle\nreload(pythonWrangle)\nfrom pythonWrangle import run_kernel\n\nframe = hou.frame()\nrun_kernel(stage, frame)\n"
  },
  {
    "path": "files/dcc/houdini/profiling/report.json",
    "content": "{\"traceEvents\":[{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::Sdf_FileFormatRegistry::FindByExtension\",\"ts\":46468169463.494,\"ph\":\"X\",\"dur\":4.529},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::SdfLayer::_InitializeFromIdentifier\",\"ts\":46468169473.904,\"ph\":\"X\",\"dur\":2.585},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::Sdf_LayerRegistry::InsertOrUpdate\",\"ts\":46468169475.046,\"ph\":\"X\",\"dur\":1.182},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::Sdf_FileFormatRegistry::FindByExtension\",\"ts\":46468169483.783,\"ph\":\"X\",\"dur\":0.531},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::SdfLayer::_InitializeFromIdentifier\",\"ts\":46468169488.231,\"ph\":\"X\",\"dur\":1.333},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::Sdf_LayerRegistry::InsertOrUpdate\",\"ts\":46468169488.762,\"ph\":\"X\",\"dur\":0.681},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::PcpLayerStack\",\"ts\":46468169505.003,\"ph\":\"X\",\"dur\":13.736},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::PcpLayerStack::_Compute\",\"ts\":46468169505.243,\"ph\":\"X\",\"dur\":13.385},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::PcpMapFunction::Create\",\"ts\":46468169510.112,\"ph\":\"X\",\"dur\":0.481},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::PcpMapFunction::Create\",\"ts\":46468169515.873,\"ph\":\"X\",\"dur\":0.13},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::PcpComputePrimIndex\",\"ts\":46468169531.974,\"ph\":\"X\",\"dur\":6.512},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::Pcp_PrimIndexIsInstanceable\",\"ts\":46468169536.061,\"ph\":\"X\",\"dur\":0.301},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::PcpPrimIndex_Graph::Finalize\",\"ts\":46468169536.562,\"ph\":\"X\",\"dur\":1.413},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::PcpPrimIndex_Graph::_ComputeStrengthOrderIndexMapping\",\"ts\":46468169536.732,\"ph\":\"X\",\"dur\":0.611},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::PcpPrimIndex_Graph::_ComputeEraseCulledNodeIndexMapping\",\"ts\":46468169537.534,\"ph\":\"X\",\"dur\":0.311},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::PcpPrimIndex::ComputePrimChildNames\",\"ts\":46468169542.604,\"ph\":\"X\",\"dur\":0.701},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::Usd_InstanceCache::ProcessChanges\",\"ts\":46468169546.681,\"ph\":\"X\",\"dur\":1.102},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::UsdStage::_ComposeSubtreesInParallel\",\"ts\":46468169549.977,\"ph\":\"X\",\"dur\":10.009},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::UsdStage::_GetMetadata\",\"ts\":46468169555.027,\"ph\":\"X\",\"dur\":1.493},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::PcpPrimIndex::ComputePrimChildNames\",\"ts\":46468169558.163,\"ph\":\"X\",\"dur\":0.21},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::SdfPath\",\"ts\":46468169602.547,\"ph\":\"X\",\"dur\":12.053},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::PcpCache::FindSiteDependencies\",\"ts\":46468169649.094,\"ph\":\"X\",\"dur\":0.491},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::PcpChanges::DidChange\",\"ts\":46468169649.906,\"ph\":\"X\",\"dur\":7.424},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::PcpCache::FindSiteDependencies\",\"ts\":46468169652.942,\"ph\":\"X\",\"dur\":1.062},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::PcpCache::Apply\",\"ts\":46468169659.173,\"ph\":\"X\",\"dur\":1.733},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::PcpComputePrimIndex\",\"ts\":46468169683.95,\"ph\":\"X\",\"dur\":5.811},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::PcpPrimIndex_Graph::New\",\"ts\":46468169685.523,\"ph\":\"X\",\"dur\":0.301},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::Pcp_PrimIndexIsInstanceable\",\"ts\":46468169688.809,\"ph\":\"X\",\"dur\":0.16},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::PcpPrimIndex_Graph::Finalize\",\"ts\":46468169689.11,\"ph\":\"X\",\"dur\":0.06},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::PcpPrimIndex::ComputePrimChildNames\",\"ts\":46468169692.326,\"ph\":\"X\",\"dur\":1.092},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::Usd_InstanceCache::ProcessChanges\",\"ts\":46468169696.434,\"ph\":\"X\",\"dur\":1.363},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::PcpPrimIndex::ComputePrimChildNames\",\"ts\":46468169700.401,\"ph\":\"X\",\"dur\":1.533},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::UsdStage::_ComposeSubtreesInParallel\",\"ts\":46468169704.198,\"ph\":\"X\",\"dur\":93.987},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"pxrInternal_v0_22__pxrReserved__::UsdStage::_DestroyPrimsInParallel\",\"ts\":46468169798.777,\"ph\":\"X\",\"dur\":0.501},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"Python func: foo\",\"ts\":46468169877.054,\"ph\":\"B\"},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"Python func: foo\",\"ph\":\"E\",\"ts\":46468169983.876},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"InnerScope\",\"ts\":46468169888.977,\"ph\":\"B\"},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Main Thread\",\"name\":\"InnerScope\",\"ph\":\"E\",\"ts\":46468169976.793},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Thread 140229356811968\",\"name\":\"pxrInternal_v0_22__pxrReserved__::_GetPrimSpecifierImpl\",\"ts\":46468169716.792,\"ph\":\"X\",\"dur\":1.072},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Thread 140229356811968\",\"name\":\"pxrInternal_v0_22__pxrReserved__::Usd_ClipCache::PopulateClipsForPrim\",\"ts\":46468169785.612,\"ph\":\"X\",\"dur\":7.684},{\"cat\":\"Default\",\"libTraceCatId\":0,\"pid\":0,\"tid\":\"Thread 140229356811968\",\"name\":\"pxrInternal_v0_22__pxrReserved__::PcpPrimIndex::ComputePrimChildNames\",\"ts\":46468169793.868,\"ph\":\"X\",\"dur\":1.663}]}"
  },
  {
    "path": "files/dcc/houdini/profiling/report.trace",
    "content": "\nTree view  ==============\n   inclusive    exclusive        \n    0.519 ms     0.246 ms       1 samples    Main Thread\n    0.005 ms     0.005 ms       2 samples    | pxrInternal_v0_22__pxrReserved__::Sdf_FileFormatRegistry::FindByExtension\n    0.004 ms     0.002 ms       2 samples    | pxrInternal_v0_22__pxrReserved__::SdfLayer::_InitializeFromIdentifier\n    0.002 ms     0.002 ms       2 samples    |   pxrInternal_v0_22__pxrReserved__::Sdf_LayerRegistry::InsertOrUpdate\n    0.014 ms     0.000 ms       1 samples    | pxrInternal_v0_22__pxrReserved__::PcpLayerStack\n    0.013 ms     0.013 ms       1 samples    |   pxrInternal_v0_22__pxrReserved__::PcpLayerStack::_Compute\n    0.001 ms     0.001 ms       2 samples    |   | pxrInternal_v0_22__pxrReserved__::PcpMapFunction::Create\n    0.012 ms     0.010 ms       2 samples    | pxrInternal_v0_22__pxrReserved__::PcpComputePrimIndex\n    0.000 ms     0.000 ms       2 samples    |   pxrInternal_v0_22__pxrReserved__::Pcp_PrimIndexIsInstanceable\n    0.001 ms     0.000 ms       2 samples    |   pxrInternal_v0_22__pxrReserved__::PcpPrimIndex_Graph::Finalize\n    0.001 ms     0.001 ms       1 samples    |   | pxrInternal_v0_22__pxrReserved__::PcpPrimIndex_Graph::_ComputeStrengthOrderIndexMapping\n    0.000 ms     0.000 ms       1 samples    |   | pxrInternal_v0_22__pxrReserved__::PcpPrimIndex_Graph::_ComputeEraseCulledNodeIndexMapping\n    0.000 ms     0.000 ms       1 samples    |   pxrInternal_v0_22__pxrReserved__::PcpPrimIndex_Graph::New\n    0.003 ms     0.003 ms       3 samples    | pxrInternal_v0_22__pxrReserved__::PcpPrimIndex::ComputePrimChildNames\n    0.002 ms     0.002 ms       2 samples    | pxrInternal_v0_22__pxrReserved__::Usd_InstanceCache::ProcessChanges\n    0.104 ms     0.102 ms       2 samples    | pxrInternal_v0_22__pxrReserved__::UsdStage::_ComposeSubtreesInParallel\n    0.001 ms     0.001 ms       1 samples    |   pxrInternal_v0_22__pxrReserved__::UsdStage::_GetMetadata\n    0.000 ms     0.000 ms       1 samples    |   pxrInternal_v0_22__pxrReserved__::PcpPrimIndex::ComputePrimChildNames\n    0.012 ms     0.012 ms       1 samples    | pxrInternal_v0_22__pxrReserved__::SdfPath\n    0.000 ms     0.000 ms       1 samples    | pxrInternal_v0_22__pxrReserved__::PcpCache::FindSiteDependencies\n    0.007 ms     0.006 ms       1 samples    | pxrInternal_v0_22__pxrReserved__::PcpChanges::DidChange\n    0.001 ms     0.001 ms       1 samples    |   pxrInternal_v0_22__pxrReserved__::PcpCache::FindSiteDependencies\n    0.002 ms     0.002 ms       1 samples    | pxrInternal_v0_22__pxrReserved__::PcpCache::Apply\n    0.001 ms     0.001 ms       1 samples    | pxrInternal_v0_22__pxrReserved__::UsdStage::_DestroyPrimsInParallel\n    0.107 ms     0.019 ms       1 samples    | Python func: foo\n    0.088 ms     0.088 ms       1 samples    |   InnerScope\n    0.079 ms     0.068 ms       1 samples    Thread 140229356811968\n    0.001 ms     0.001 ms       1 samples    | pxrInternal_v0_22__pxrReserved__::_GetPrimSpecifierImpl\n    0.008 ms     0.008 ms       1 samples    | pxrInternal_v0_22__pxrReserved__::Usd_ClipCache::PopulateClipsForPrim\n    0.002 ms     0.002 ms       1 samples    | pxrInternal_v0_22__pxrReserved__::PcpPrimIndex::ComputePrimChildNames\n\n"
  },
  {
    "path": "files/plugins/kinds/plugInfo.json",
    "content": "{\n    \"Plugins\":[\n       {\n           \"Type\": \"python\",\n           \"Name\": \"usdSurvivalGuideKinds\", \n         \"Info\":{\n             \"Kinds\":{\n                \"character\":{\n                   \"baseKind\":\"component\",\n                   \"description\":\"A (hero) character\"\n                },\n                \"prop\":{\n                   \"baseKind\":\"component\",\n                   \"description\":\"A generic prop asset\"\n                },\n                \"fx\":{\n                   \"baseKind\":\"component\",\n                   \"description\":\"A FX asset\"\n                },\n                \"environment\":{\n                   \"baseKind\":\"assembly\",\n                   \"description\":\"A large scale environment like a city.\"\n                },\n                \"set\":{\n                   \"baseKind\":\"assembly\",\n                   \"description\":\"A individual section of an environment, typically a movie set placed in an environment.\"\n                }\n             }\n          }\n       }\n    ]\n }"
  },
  {
    "path": "files/plugins/metadata/plugInfo.json",
    "content": "{\n   \"Plugins\": [\n       {\n           \"Name\": \"usdSurvivalGuideMetadata\",\n           \"Type\": \"resource\",\n           \"Info\": {\n               \"SdfMetadata\": {\n                   \"usdSurvivalGuideOverrideTimeCode\": {\n                       \"type\": \"double[]\",\n                       \"appliesTo\": \"layers\",\n                       \"default\": [1001.0, 1050.0]\n                   },\n                   \"usdSurvivalGuideFloat\": {\n                       \"type\": \"double\",\n                       \"appliesTo\": \"prims\",\n                       \"default\": 5\n                   },\n                   \"usdSurvivalGuideAssetDependencies\": {\n                    \"type\": \"stringlistop\",\n                    \"appliesTo\": \"prims\"\n                   }\n               }\n           }\n       }\n   ]\n}"
  },
  {
    "path": "files/plugins/schemas/codelessSchema/build.sh",
    "content": "# Source setup\nif [ ! $REPO_SOURCED ]\nthen\n    source ../../../setup.sh\nfi\n# Clear existing build data\nrm -R dist\n# Invoke usdGenSchema\nusdGenSchema schema.usda ./dist\n# Set plugin path\ncurrent_dir=$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" &> /dev/null && (pwd -W 2> /dev/null || pwd))\nif [[ \"$PXR_PLUGINPATH_NAME\" != *\"$current_dir/dist\"* ]]; then\n  export PXR_PLUGINPATH_NAME=$current_dir/dist:${PXR_PLUGINPATH_NAME}\n  echo \"Added $current_dir/dist to the PXR_PLUGINPATH_NAME environment variable.\"\nfi\n\n#rm -R build\n#rm -R dist\n#cmake . -B build\n#cmake --build build --clean-first              # make clean all\n#cmake --install build                          # make install\n"
  },
  {
    "path": "files/plugins/schemas/codelessSchema/dist/generatedSchema.usda",
    "content": "#usda 1.0\n(\n    \"WARNING: THIS FILE IS GENERATED BY usdGenSchema.  DO NOT EDIT.\"\n)\n\nclass \"SimplePrim\" (\n    doc = \"\"\"An example of an untyped schema prim. Note that it does not \n    specify a typeName\"\"\"\n)\n{\n    int intAttr = 0 (\n        doc = \"An integer attribute with fallback value of 0.\"\n    )\n    rel target (\n        doc = \"\"\"A relationship called target that could point to another prim\n        or a property\"\"\"\n    )\n}\n\nclass ComplexPrim \"ComplexPrim\" (\n    doc = \"An example of a untyped IsA schema prim\"\n)\n{\n    string complexString = \"somethingComplex\"\n    int intAttr = 0 (\n        doc = \"An integer attribute with fallback value of 0.\"\n    )\n    rel target (\n        doc = \"\"\"A relationship called target that could point to another prim\n        or a property\"\"\"\n    )\n}\n\nclass \"ParamsAPI\"\n{\n    double params:mass (\n        doc = \"Double value denoting mass\"\n    )\n    double params:velocity (\n        doc = \"Double value denoting velocity\"\n    )\n    double params:volume (\n        doc = \"Double value denoting volume\"\n    )\n}\n\n"
  },
  {
    "path": "files/plugins/schemas/codelessSchema/dist/plugInfo.json",
    "content": "# Portions of this file auto-generated by usdGenSchema.\n# Edits will survive regeneration except for comments and\n# changes to types with autoGenerated=true.\n{\n    \"Plugins\": [\n        {\n            \"Info\": {\n                \"Types\": {\n                    \"UsdSchemaExamplesComplex\": {\n                        \"alias\": {\n                            \"UsdSchemaBase\": \"ComplexPrim\"\n                        }, \n                        \"autoGenerated\": true, \n                        \"bases\": [\n                            \"UsdSchemaExamplesSimple\"\n                        ], \n                        \"schemaKind\": \"concreteTyped\"\n                    }, \n                    \"UsdSchemaExamplesParamsAPI\": {\n                        \"alias\": {\n                            \"UsdSchemaBase\": \"ParamsAPI\"\n                        }, \n                        \"autoGenerated\": true, \n                        \"bases\": [\n                            \"UsdAPISchemaBase\"\n                        ], \n                        \"schemaKind\": \"singleApplyAPI\"\n                    }, \n                    \"UsdSchemaExamplesSimple\": {\n                        \"alias\": {\n                            \"UsdSchemaBase\": \"SimplePrim\"\n                        }, \n                        \"autoGenerated\": true, \n                        \"bases\": [\n                            \"UsdTyped\"\n                        ], \n                        \"schemaKind\": \"abstractTyped\"\n                    }\n                }\n            }, \n            \"LibraryPath\": \".\", \n            \"Name\": \"usdSchemaExamples\", \n            \"ResourcePath\": \".\", \n            \"Root\": \".\", \n            \"Type\": \"resource\"\n        }\n    ]\n}\n"
  },
  {
    "path": "files/plugins/schemas/codelessSchema/schema.usda",
    "content": "#usda 1.0\n(\n    \"\"\" This file contains an example schemata for code generation using\n        usdGenSchema.\n    \"\"\"\n    subLayers = [\n        @usd/schema.usda@\n    ]\n) \n\nover \"GLOBAL\" (\n    customData = {\n        string libraryName       = \"usdSchemaExamples\"\n        string libraryPath       = \".\"\n        string libraryPrefix     = \"UsdSchemaExamples\"\n        bool skipCodeGeneration = true\n    }\n) {\n}\n\nclass \"SimplePrim\" (\n    doc = \"\"\"An example of an untyped schema prim. Note that it does not \n    specify a typeName\"\"\"\n    # IsA schemas should derive from </Typed>, which is defined in the sublayer\n    # usd/lib/usd/schema.usda.\n    inherits = </Typed>\n    customData = {\n        # Provide a different class name for the C++ and python schema classes.\n        # This will be prefixed with libraryPrefix.\n        # In this case, the class name becomes UsdSchemaExamplesSimple.\n        string className = \"Simple\"\n        }\n    )  \n{\n    int intAttr = 0 (\n        doc = \"An integer attribute with fallback value of 0.\"\n    )\n    rel target (\n        doc = \"\"\"A relationship called target that could point to another prim\n        or a property\"\"\"\n    )\n}\n\n# Note that it does not specify a typeName.\nclass ComplexPrim \"ComplexPrim\" (\n    doc = \"\"\"An example of a untyped IsA schema prim\"\"\"\n    # Inherits from </SimplePrim> defined in simple.usda.\n    inherits = </SimplePrim>\n    customData = {\n        string className = \"Complex\"\n    }\n)  \n{\n    string complexString = \"somethingComplex\"\n}\n    \nclass \"ParamsAPI\" (\n    inherits = </APISchemaBase>\n)\n{\n    double params:mass (\n        # Informs schema generator to create GetMassAttr() method\n        # instead of GetParamsMassAttr() method\n        customData = {\n            string apiName = \"mass\"\n        }\n        doc = \"Double value denoting mass\"\n    )\n    double params:velocity (\n        customData = {\n            string apiName = \"velocity\"\n        }\n        doc = \"Double value denoting velocity\"\n    )\n    double params:volume (\n        customData = {\n            string apiName = \"volume\"\n        }\n        doc = \"Double value denoting volume\"\n    )\n}"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/.gitignore",
    "content": "dist\n"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/CMakeLists.txt",
    "content": "### Configuration ###\n# Here we declare some custom variables that configure namings\nset(USDSG_PROJECT_NAME UsdExamplesSchemas)\n\nset(USDSG_EXAMPLESCHEMAS_USD_PLUGIN_NAME usdExampleSchemas)\nset(USDSG_EXAMPLESCHEMAS_USD_CXX_CLASS_NAME UsdExampleSchemas)\nset(USDSG_EXAMPLESCHEMAS_USD_PYTHON_MODULE_NAME UsdExampleSchemas)\nset(USDSG_EXAMPLESCHEMAS_TARGET_LIB usdExampleSchemas)\nset(USDSG_EXAMPLESCHEMAS_TARGET_PYTHON _${USDSG_EXAMPLESCHEMAS_TARGET_LIB})\n\n# Arch\nset(USDSG_ARCH_LIB_SUFFIX so)\n# Houdini\nset(USDSG_HOUDINI_ROOT $ENV{HFS})\nset(USDSG_HOUDINI_LIB_DIR ${USDSG_HOUDINI_ROOT}/dsolib)\nset(USDSG_HOUDINI_INCLUDE_DIR ${USDSG_HOUDINI_ROOT}/toolkit/include)\n# Usd\nset(USDSG_PXR_LIB_DIR ${USDSG_HOUDINI_ROOT}/dsolib)\nset(USDSG_PXR_LIB_PREFIX \"pxr_\")\nset(USDSG_PXR_INCLUDE_DIR ${USDSG_HOUDINI_INCLUDE_DIR})\n# Python\nset(USDSG_PYTHON_LIB_DIR ${USDSG_HOUDINI_ROOT}/python/lib)\nset(USDSG_PYTHON_LIB python3.9)\nset(USDSG_PYTHON_LIB_NUMBER python39)\nset(USDSG_PYTHON_LIB_SITEPACKAGES ${USDSG_PYTHON_LIB_DIR}/${USDSG_PYTHON_LIB}/site-packages)\nset(USDSG_PYTHON_INCLUDE_DIR ${USDSG_HOUDINI_INCLUDE_DIR}/${USDSG_PYTHON_LIB})\n# Boost\nset(USDSG_BOOST_NAMESPACE hboost)\nset(USDSG_BOOST_INCLUDE_DIR \"${USDSG_HOUDINI_INCLUDE_DIR}/${USDSG_BOOST_NAMESPACE}\")\nset(USDSG_BOOST_PYTHON_LIB ${USDSG_BOOST_NAMESPACE}_${USDSG_PYTHON_LIB_NUMBER})\n# usdGenSchema plugInfo.json vars\nset(PLUG_INFO_ROOT \".\")\nset(PLUG_INFO_LIBRARY_PATH \"../lib/${USDSG_EXAMPLESCHEMAS_TARGET_LIB}.${USDSG_ARCH_LIB_SUFFIX}\")\nset(PLUG_INFO_RESOURCE_PATH \".\")\n\n### Init ###\ncmake_minimum_required(VERSION 3.14 FATAL_ERROR)\nproject(${USDSG_PROJECT_NAME} VERSION 1.0.0 LANGUAGES CXX)\n\n### CPP Settings ###\nset(BUILD_SHARED_LIBS ON)\n# Preprocessor Defines (Same as #define)\nadd_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0 HBOOST_ALL_NO_LIB BOOST_ALL_NO_LIB)\n# This is the same as set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -DHBOOST_ALL_NO_LIB -D_GLIBCXX_USE_CXX11_ABI=0\")\n# Compiler Options\nadd_compile_options(-fPIC -Wno-deprecated -Wno-deprecated-declarations -Wno-changes-meaning) # -Zc:inline-\n\n### Packages ### (Settings for all targets)\n# Houdini\nlink_directories(${USDSG_HOUDINI_LIB_DIR})\n# Usd (Already provided via Houdini)\n# link_directories(${USDSG_PXR_LIB_DIR})\n# Python (Already provided via Houdini)\n# link_directories(${USDSG_PYTHON_LIB_DIR})\n\n### CPP Settings ###\nSET(CMAKE_INSTALL_PREFIX \"${CMAKE_SOURCE_DIR}/dist\" CACHE PATH \"Default install dir \" FORCE)\n\n### Targets ###\n## Target library > usdSchemaExamples ##\nadd_library(${USDSG_EXAMPLESCHEMAS_TARGET_LIB}\n    SHARED\n        src/complex.cpp\n        src/paramsAPI.cpp\n        src/simple.cpp\n        src/tokens.cpp\n)\n# Libs\ntarget_link_libraries(${USDSG_EXAMPLESCHEMAS_TARGET_LIB}\n    ${USDSG_PXR_LIB_PREFIX}tf\n    ${USDSG_PXR_LIB_PREFIX}vt\n    ${USDSG_PXR_LIB_PREFIX}usd\n    ${USDSG_PXR_LIB_PREFIX}sdf\n)\n# Headers\ntarget_include_directories(${USDSG_EXAMPLESCHEMAS_TARGET_LIB}\n    PUBLIC\n    ${USDSG_BOOST_INCLUDE_DIR}\n    ${USDSG_PYTHON_INCLUDE_DIR}\n    ${USDSG_PXR_INCLUDE_DIR}\n)\n# Props\n# Remove default \"lib\" prefix\nset_target_properties(${USDSG_EXAMPLESCHEMAS_TARGET_LIB} PROPERTIES PREFIX \"\")\n# Preprocessor Defines (Same as #define)\ntarget_compile_definitions(${USDSG_EXAMPLESCHEMAS_TARGET_LIB}\n    PRIVATE\n        # USD Plugin Internal Namings\n        MFB_PACKAGE_NAME=${USDSG_EXAMPLESCHEMAS_USD_PLUGIN_NAME}\n)\n# Install\nconfigure_file(src/plugInfo.json plugInfo.json)\ninstall(FILES ${CMAKE_CURRENT_BINARY_DIR}/plugInfo.json DESTINATION resources)\ninstall(FILES src/generatedSchema.usda DESTINATION resources)\ninstall(TARGETS ${USDSG_EXAMPLESCHEMAS_TARGET_LIB} RUNTIME DESTINATION lib)\n\n## Target library > usdSchemaExamples Python ##\nadd_library(${USDSG_EXAMPLESCHEMAS_TARGET_PYTHON}\n    SHARED\n        src/wrapComplex.cpp\n        src/wrapParamsAPI.cpp\n        src/wrapSimple.cpp\n        src/wrapTokens.cpp\n        src/module.cpp\n        src/moduleDeps.cpp\n)\n# Libs\ntarget_link_libraries(${USDSG_EXAMPLESCHEMAS_TARGET_PYTHON}\n    ${USDSG_EXAMPLESCHEMAS_TARGET_LIB}\n    ${USDSG_BOOST_PYTHON_LIB}\n)\n# Headers\ntarget_include_directories(${USDSG_EXAMPLESCHEMAS_TARGET_PYTHON}\n    PUBLIC\n        ${USDSG_BOOST_INCLUDE_DIR}\n        ${USDSG_PYTHON_INCLUDE_DIR}\n        ${USDSG_PXR_INCLUDE_DIR}\n)\n# Props\n# Remove default \"lib\" prefix\nset_target_properties(${USDSG_EXAMPLESCHEMAS_TARGET_PYTHON} PROPERTIES PREFIX \"\")\n# Preprocessor Defines (Same as #define)\ntarget_compile_definitions(${USDSG_EXAMPLESCHEMAS_TARGET_PYTHON}\n    PRIVATE\n        # USD Plugin Internal Namings\n        MFB_PACKAGE_NAME=${USDSG_EXAMPLESCHEMAS_USD_PLUGIN_NAME}\n        MFB_PACKAGE_MODULE=${USDSG_EXAMPLESCHEMAS_USD_PYTHON_MODULE_NAME}\n)\n# Install\ninstall(FILES src/__init__.py DESTINATION lib/python/${USDSG_EXAMPLESCHEMAS_USD_PYTHON_MODULE_NAME})\ninstall(\n    TARGETS ${USDSG_EXAMPLESCHEMAS_TARGET_PYTHON}\n    DESTINATION lib/python/${USDSG_EXAMPLESCHEMAS_USD_PYTHON_MODULE_NAME}\n)\n\n# Status\nmessage(STATUS \"--- Usd Example Schemas Instructions Start ---\")\nmessage(NOTICE \"To use the compiled files, set the following environment variables:\")\nmessage(NOTICE \"export PYTHONPATH=${CMAKE_INSTALL_PREFIX}/lib/python:${USDSG_PYTHON_LIB_SITEPACKAGES}:$PYTHONPATH\")\nmessage(NOTICE \"export PXR_PLUGINPATH_NAME=${CMAKE_INSTALL_PREFIX}/resources:$PXR_PLUGINPATH_NAME\")\nmessage(NOTICE \"export LD_LIBRARY_PATH=${CMAKE_INSTALL_PREFIX}/lib:${HFS}/python/lib:${HFS}/dsolib:$LD_LIBRARY_PATH\")\nmessage(STATUS \"--- Usd Example Schemas Instructions End ---\\n\")\n\n"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/auxiliary/__init__.py",
    "content": "#\n# Copyright 2016 Pixar\n#\n# Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n# with the following modification; you may not use this file except in\n# compliance with the Apache License and the following modification to it:\n# Section 6. Trademarks. is deleted and replaced with:\n#\n# 6. Trademarks. This License does not grant permission to use the trade\n#    names, trademarks, service marks, or product names of the Licensor\n#    and its affiliates, except as required to comply with Section 4(c) of\n#    the License and to reproduce the content of the NOTICE file.\n#\n# You may obtain a copy of the Apache License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the Apache License with the above modification is\n# distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, either express or implied. See the Apache License for the specific\n# language governing permissions and limitations under the Apache License.\n#\nfrom pxr import Tf\nTf.PreparePythonModule()\ndel Tf"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/auxiliary/module.cpp",
    "content": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the following modification; you may not use this file except in\n// compliance with the Apache License and the following modification to it:\n// Section 6. Trademarks. is deleted and replaced with:\n//\n// 6. Trademarks. This License does not grant permission to use the trade\n//    names, trademarks, service marks, or product names of the Licensor\n//    and its affiliates, except as required to comply with Section 4(c) of\n//    the License and to reproduce the content of the NOTICE file.\n//\n// You may obtain a copy of the Apache License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the Apache License with the above modification is\n// distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, either express or implied. See the Apache License for the specific\n// language governing permissions and limitations under the Apache License.\n//\n#include \"pxr/base/tf/pySafePython.h\"\n#include \"pxr/pxr.h\"\n#include \"pxr/base/tf/pyModule.h\"\n\nPXR_NAMESPACE_USING_DIRECTIVE\n\nTF_WRAP_MODULE\n{\n    TF_WRAP(UsdSchemaExamplesSimple);\n    TF_WRAP(UsdSchemaExamplesComplex);\n    TF_WRAP(UsdSchemaExamplesParamsAPI);\n    TF_WRAP(UsdSchemaExamplesTokens);\n}"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/auxiliary/moduleDeps.cpp",
    "content": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the following modification; you may not use this file except in\n// compliance with the Apache License and the following modification to it:\n// Section 6. Trademarks. is deleted and replaced with:\n//\n// 6. Trademarks. This License does not grant permission to use the trade\n//    names, trademarks, service marks, or product names of the Licensor\n//    and its affiliates, except as required to comply with Section 4(c) of\n//    the License and to reproduce the content of the NOTICE file.\n//\n// You may obtain a copy of the Apache License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the Apache License with the above modification is\n// distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, either express or implied. See the Apache License for the specific\n// language governing permissions and limitations under the Apache License.\n//\n////////////////////////////////////////////////////////////////////////\n\n#include \"pxr/pxr.h\"\n#include \"pxr/base/tf/registryManager.h\"\n#include \"pxr/base/tf/scriptModuleLoader.h\"\n#include \"pxr/base/tf/token.h\"\n\n#include <vector>\n\nPXR_NAMESPACE_OPEN_SCOPE\n\nTF_REGISTRY_FUNCTION(TfScriptModuleLoader) {\n    // List of direct dependencies for this library.\n    const std::vector<TfToken> reqs = {\n        TfToken(\"sdf\"),\n        TfToken(\"tf\"),\n        TfToken(\"usd\"),\n        TfToken(\"vt\")\n    };\n    TfScriptModuleLoader::GetInstance().\n        RegisterLibrary(TfToken(\"usdSchemaExamples\"), TfToken(\"UsdSchemaExamples\"), reqs);\n}\n\nPXR_NAMESPACE_CLOSE_SCOPE\n\n"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/build.sh",
    "content": "# Source setup\nif [ ! $REPO_SOURCED ]\nthen\n    source ../../../setup.sh\nfi\n# Clear existing build data\nrm -R src\n# Invoke usdGenSchema\nusdGenSchema schema.usda ./src\n# Copy auxiliary files\ncp -r auxiliary/* src\n# Clear build & install dirs\nrm -R build\nrm -R dist\n# Build\ncmake . -B build\ncmake --build build --clean-first              # make clean all\ncmake --install build                          # make install\n# Set plugin path\ncurrent_dir=$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" &> /dev/null && (pwd -W 2> /dev/null || pwd))\nif [[ \"$PXR_PLUGINPATH_NAME\" != *\"$current_dir/dist\"* ]]; then\n  export PXR_PLUGINPATH_NAME=$current_dir/dist:${PXR_PLUGINPATH_NAME}\n  echo \"Added $current_dir/dist to the PXR_PLUGINPATH_NAME environment variable.\"\nfi"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/schema.usda",
    "content": "#usda 1.0\n(\n    \"\"\" This file contains an example schemata for code generation using\n        usdGenSchema.\n    \"\"\"\n    subLayers = [\n        @usd/schema.usda@\n    ]\n) \n\nover \"GLOBAL\" (\n    customData = {\n        string libraryName       = \"usdSchemaExamples\"\n        string libraryPath       = \".\"\n        string libraryPrefix     = \"UsdSchemaExamples\"\n    }\n) {\n}\n\nclass \"SimplePrim\" (\n    doc = \"\"\"An example of an untyped schema prim. Note that it does not \n    specify a typeName\"\"\"\n    # IsA schemas should derive from </Typed>, which is defined in the sublayer\n    # usd/lib/usd/schema.usda.\n    inherits = </Typed>\n    customData = {\n        # Provide a different class name for the C++ and python schema classes.\n        # This will be prefixed with libraryPrefix.\n        # In this case, the class name becomes UsdSchemaExamplesSimple.\n        string className = \"Simple\"\n        }\n    )  \n{\n    int intAttr = 0 (\n        doc = \"An integer attribute with fallback value of 0.\"\n    )\n    rel target (\n        doc = \"\"\"A relationship called target that could point to another prim\n        or a property\"\"\"\n    )\n}\n\n# Note that it does not specify a typeName.\nclass ComplexPrim \"ComplexPrim\" (\n    doc = \"\"\"An example of a untyped IsA schema prim\"\"\"\n    # Inherits from </SimplePrim> defined in simple.usda.\n    inherits = </SimplePrim>\n    customData = {\n        string className = \"Complex\"\n    }\n)  \n{\n    string complexString = \"somethingComplex\"\n}\n    \nclass \"ParamsAPI\" (\n    inherits = </APISchemaBase>\n)\n{\n    double params:mass (\n        # Informs schema generator to create GetMassAttr() method\n        # instead of GetParamsMassAttr() method\n        customData = {\n            string apiName = \"mass\"\n        }\n        doc = \"Double value denoting mass\"\n    )\n    double params:velocity (\n        customData = {\n            string apiName = \"velocity\"\n        }\n        doc = \"Double value denoting velocity\"\n    )\n    double params:volume (\n        customData = {\n            string apiName = \"volume\"\n        }\n        doc = \"Double value denoting volume\"\n    )\n}"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/__init__.py",
    "content": "#\n# Copyright 2016 Pixar\n#\n# Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n# with the following modification; you may not use this file except in\n# compliance with the Apache License and the following modification to it:\n# Section 6. Trademarks. is deleted and replaced with:\n#\n# 6. Trademarks. This License does not grant permission to use the trade\n#    names, trademarks, service marks, or product names of the Licensor\n#    and its affiliates, except as required to comply with Section 4(c) of\n#    the License and to reproduce the content of the NOTICE file.\n#\n# You may obtain a copy of the Apache License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the Apache License with the above modification is\n# distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, either express or implied. See the Apache License for the specific\n# language governing permissions and limitations under the Apache License.\n#\nfrom pxr import Tf\nTf.PreparePythonModule()\ndel Tf"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/api.h",
    "content": "//\n// Copyright 2017 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the following modification; you may not use this file except in\n// compliance with the Apache License and the following modification to it:\n// Section 6. Trademarks. is deleted and replaced with:\n//\n// 6. Trademarks. This License does not grant permission to use the trade\n//    names, trademarks, service marks, or product names of the Licensor\n//    and its affiliates, except as required to comply with Section 4(c) of\n//    the License and to reproduce the content of the NOTICE file.\n//\n// You may obtain a copy of the Apache License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the Apache License with the above modification is\n// distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, either express or implied. See the Apache License for the specific\n// language governing permissions and limitations under the Apache License.\n//\n#ifndef USDSCHEMAEXAMPLES_API_H\n#define USDSCHEMAEXAMPLES_API_H\n\n#include \"pxr/base/arch/export.h\"\n\n#if defined(PXR_STATIC)\n#   define USDSCHEMAEXAMPLES_API\n#   define USDSCHEMAEXAMPLES_API_TEMPLATE_CLASS(...)\n#   define USDSCHEMAEXAMPLES_API_TEMPLATE_STRUCT(...)\n#   define USDSCHEMAEXAMPLES_LOCAL\n#else\n#   if defined(USDSCHEMAEXAMPLES_EXPORTS)\n#       define USDSCHEMAEXAMPLES_API ARCH_EXPORT\n#       define USDSCHEMAEXAMPLES_API_TEMPLATE_CLASS(...) ARCH_EXPORT_TEMPLATE(class, __VA_ARGS__)\n#       define USDSCHEMAEXAMPLES_API_TEMPLATE_STRUCT(...) ARCH_EXPORT_TEMPLATE(struct, __VA_ARGS__)\n#   else\n#       define USDSCHEMAEXAMPLES_API ARCH_IMPORT\n#       define USDSCHEMAEXAMPLES_API_TEMPLATE_CLASS(...) ARCH_IMPORT_TEMPLATE(class, __VA_ARGS__)\n#       define USDSCHEMAEXAMPLES_API_TEMPLATE_STRUCT(...) ARCH_IMPORT_TEMPLATE(struct, __VA_ARGS__)\n#   endif\n#   define USDSCHEMAEXAMPLES_LOCAL ARCH_HIDDEN\n#endif\n\n#endif\n"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/complex.cpp",
    "content": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the following modification; you may not use this file except in\n// compliance with the Apache License and the following modification to it:\n// Section 6. Trademarks. is deleted and replaced with:\n//\n// 6. Trademarks. This License does not grant permission to use the trade\n//    names, trademarks, service marks, or product names of the Licensor\n//    and its affiliates, except as required to comply with Section 4(c) of\n//    the License and to reproduce the content of the NOTICE file.\n//\n// You may obtain a copy of the Apache License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the Apache License with the above modification is\n// distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, either express or implied. See the Apache License for the specific\n// language governing permissions and limitations under the Apache License.\n//\n#include \"./complex.h\"\n#include \"pxr/usd/usd/schemaRegistry.h\"\n#include \"pxr/usd/usd/typed.h\"\n\n#include \"pxr/usd/sdf/types.h\"\n#include \"pxr/usd/sdf/assetPath.h\"\n\nPXR_NAMESPACE_OPEN_SCOPE\n\n// Register the schema with the TfType system.\nTF_REGISTRY_FUNCTION(TfType)\n{\n    TfType::Define<UsdSchemaExamplesComplex,\n        TfType::Bases< UsdSchemaExamplesSimple > >();\n    \n    // Register the usd prim typename as an alias under UsdSchemaBase. This\n    // enables one to call\n    // TfType::Find<UsdSchemaBase>().FindDerivedByName(\"ComplexPrim\")\n    // to find TfType<UsdSchemaExamplesComplex>, which is how IsA queries are\n    // answered.\n    TfType::AddAlias<UsdSchemaBase, UsdSchemaExamplesComplex>(\"ComplexPrim\");\n}\n\n/* virtual */\nUsdSchemaExamplesComplex::~UsdSchemaExamplesComplex()\n{\n}\n\n/* static */\nUsdSchemaExamplesComplex\nUsdSchemaExamplesComplex::Get(const UsdStagePtr &stage, const SdfPath &path)\n{\n    if (!stage) {\n        TF_CODING_ERROR(\"Invalid stage\");\n        return UsdSchemaExamplesComplex();\n    }\n    return UsdSchemaExamplesComplex(stage->GetPrimAtPath(path));\n}\n\n/* static */\nUsdSchemaExamplesComplex\nUsdSchemaExamplesComplex::Define(\n    const UsdStagePtr &stage, const SdfPath &path)\n{\n    static TfToken usdPrimTypeName(\"ComplexPrim\");\n    if (!stage) {\n        TF_CODING_ERROR(\"Invalid stage\");\n        return UsdSchemaExamplesComplex();\n    }\n    return UsdSchemaExamplesComplex(\n        stage->DefinePrim(path, usdPrimTypeName));\n}\n\n/* virtual */\nUsdSchemaKind UsdSchemaExamplesComplex::_GetSchemaKind() const\n{\n    return UsdSchemaExamplesComplex::schemaKind;\n}\n\n/* static */\nconst TfType &\nUsdSchemaExamplesComplex::_GetStaticTfType()\n{\n    static TfType tfType = TfType::Find<UsdSchemaExamplesComplex>();\n    return tfType;\n}\n\n/* static */\nbool \nUsdSchemaExamplesComplex::_IsTypedSchema()\n{\n    static bool isTyped = _GetStaticTfType().IsA<UsdTyped>();\n    return isTyped;\n}\n\n/* virtual */\nconst TfType &\nUsdSchemaExamplesComplex::_GetTfType() const\n{\n    return _GetStaticTfType();\n}\n\nUsdAttribute\nUsdSchemaExamplesComplex::GetComplexStringAttr() const\n{\n    return GetPrim().GetAttribute(UsdSchemaExamplesTokens->complexString);\n}\n\nUsdAttribute\nUsdSchemaExamplesComplex::CreateComplexStringAttr(VtValue const &defaultValue, bool writeSparsely) const\n{\n    return UsdSchemaBase::_CreateAttr(UsdSchemaExamplesTokens->complexString,\n                       SdfValueTypeNames->String,\n                       /* custom = */ false,\n                       SdfVariabilityVarying,\n                       defaultValue,\n                       writeSparsely);\n}\n\nnamespace {\nstatic inline TfTokenVector\n_ConcatenateAttributeNames(const TfTokenVector& left,const TfTokenVector& right)\n{\n    TfTokenVector result;\n    result.reserve(left.size() + right.size());\n    result.insert(result.end(), left.begin(), left.end());\n    result.insert(result.end(), right.begin(), right.end());\n    return result;\n}\n}\n\n/*static*/\nconst TfTokenVector&\nUsdSchemaExamplesComplex::GetSchemaAttributeNames(bool includeInherited)\n{\n    static TfTokenVector localNames = {\n        UsdSchemaExamplesTokens->complexString,\n    };\n    static TfTokenVector allNames =\n        _ConcatenateAttributeNames(\n            UsdSchemaExamplesSimple::GetSchemaAttributeNames(true),\n            localNames);\n\n    if (includeInherited)\n        return allNames;\n    else\n        return localNames;\n}\n\nPXR_NAMESPACE_CLOSE_SCOPE\n\n// ===================================================================== //\n// Feel free to add custom code below this line. It will be preserved by\n// the code generator.\n//\n// Just remember to wrap code in the appropriate delimiters:\n// 'PXR_NAMESPACE_OPEN_SCOPE', 'PXR_NAMESPACE_CLOSE_SCOPE'.\n// ===================================================================== //\n// --(BEGIN CUSTOM CODE)--\n"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/complex.h",
    "content": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the following modification; you may not use this file except in\n// compliance with the Apache License and the following modification to it:\n// Section 6. Trademarks. is deleted and replaced with:\n//\n// 6. Trademarks. This License does not grant permission to use the trade\n//    names, trademarks, service marks, or product names of the Licensor\n//    and its affiliates, except as required to comply with Section 4(c) of\n//    the License and to reproduce the content of the NOTICE file.\n//\n// You may obtain a copy of the Apache License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the Apache License with the above modification is\n// distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, either express or implied. See the Apache License for the specific\n// language governing permissions and limitations under the Apache License.\n//\n#ifndef USDSCHEMAEXAMPLES_GENERATED_COMPLEX_H\n#define USDSCHEMAEXAMPLES_GENERATED_COMPLEX_H\n\n/// \\file usdSchemaExamples/complex.h\n\n#include \"pxr/pxr.h\"\n#include \"./api.h\"\n#include \"./simple.h\"\n#include \"pxr/usd/usd/prim.h\"\n#include \"pxr/usd/usd/stage.h\"\n#include \"./tokens.h\"\n\n#include \"pxr/base/vt/value.h\"\n\n#include \"pxr/base/gf/vec3d.h\"\n#include \"pxr/base/gf/vec3f.h\"\n#include \"pxr/base/gf/matrix4d.h\"\n\n#include \"pxr/base/tf/token.h\"\n#include \"pxr/base/tf/type.h\"\n\nPXR_NAMESPACE_OPEN_SCOPE\n\nclass SdfAssetPath;\n\n// -------------------------------------------------------------------------- //\n// COMPLEXPRIM                                                                //\n// -------------------------------------------------------------------------- //\n\n/// \\class UsdSchemaExamplesComplex\n///\n/// An example of a untyped IsA schema prim\n///\nclass UsdSchemaExamplesComplex : public UsdSchemaExamplesSimple\n{\npublic:\n    /// Compile time constant representing what kind of schema this class is.\n    ///\n    /// \\sa UsdSchemaKind\n    static const UsdSchemaKind schemaKind = UsdSchemaKind::ConcreteTyped;\n\n    /// Construct a UsdSchemaExamplesComplex on UsdPrim \\p prim .\n    /// Equivalent to UsdSchemaExamplesComplex::Get(prim.GetStage(), prim.GetPath())\n    /// for a \\em valid \\p prim, but will not immediately throw an error for\n    /// an invalid \\p prim\n    explicit UsdSchemaExamplesComplex(const UsdPrim& prim=UsdPrim())\n        : UsdSchemaExamplesSimple(prim)\n    {\n    }\n\n    /// Construct a UsdSchemaExamplesComplex on the prim held by \\p schemaObj .\n    /// Should be preferred over UsdSchemaExamplesComplex(schemaObj.GetPrim()),\n    /// as it preserves SchemaBase state.\n    explicit UsdSchemaExamplesComplex(const UsdSchemaBase& schemaObj)\n        : UsdSchemaExamplesSimple(schemaObj)\n    {\n    }\n\n    /// Destructor.\n    USDSCHEMAEXAMPLES_API\n    virtual ~UsdSchemaExamplesComplex();\n\n    /// Return a vector of names of all pre-declared attributes for this schema\n    /// class and all its ancestor classes.  Does not include attributes that\n    /// may be authored by custom/extended methods of the schemas involved.\n    USDSCHEMAEXAMPLES_API\n    static const TfTokenVector &\n    GetSchemaAttributeNames(bool includeInherited=true);\n\n    /// Return a UsdSchemaExamplesComplex holding the prim adhering to this\n    /// schema at \\p path on \\p stage.  If no prim exists at \\p path on\n    /// \\p stage, or if the prim at that path does not adhere to this schema,\n    /// return an invalid schema object.  This is shorthand for the following:\n    ///\n    /// \\code\n    /// UsdSchemaExamplesComplex(stage->GetPrimAtPath(path));\n    /// \\endcode\n    ///\n    USDSCHEMAEXAMPLES_API\n    static UsdSchemaExamplesComplex\n    Get(const UsdStagePtr &stage, const SdfPath &path);\n\n    /// Attempt to ensure a \\a UsdPrim adhering to this schema at \\p path\n    /// is defined (according to UsdPrim::IsDefined()) on this stage.\n    ///\n    /// If a prim adhering to this schema at \\p path is already defined on this\n    /// stage, return that prim.  Otherwise author an \\a SdfPrimSpec with\n    /// \\a specifier == \\a SdfSpecifierDef and this schema's prim type name for\n    /// the prim at \\p path at the current EditTarget.  Author \\a SdfPrimSpec s\n    /// with \\p specifier == \\a SdfSpecifierDef and empty typeName at the\n    /// current EditTarget for any nonexistent, or existing but not \\a Defined\n    /// ancestors.\n    ///\n    /// The given \\a path must be an absolute prim path that does not contain\n    /// any variant selections.\n    ///\n    /// If it is impossible to author any of the necessary PrimSpecs, (for\n    /// example, in case \\a path cannot map to the current UsdEditTarget's\n    /// namespace) issue an error and return an invalid \\a UsdPrim.\n    ///\n    /// Note that this method may return a defined prim whose typeName does not\n    /// specify this schema class, in case a stronger typeName opinion overrides\n    /// the opinion at the current EditTarget.\n    ///\n    USDSCHEMAEXAMPLES_API\n    static UsdSchemaExamplesComplex\n    Define(const UsdStagePtr &stage, const SdfPath &path);\n\nprotected:\n    /// Returns the kind of schema this class belongs to.\n    ///\n    /// \\sa UsdSchemaKind\n    USDSCHEMAEXAMPLES_API\n    UsdSchemaKind _GetSchemaKind() const override;\n\nprivate:\n    // needs to invoke _GetStaticTfType.\n    friend class UsdSchemaRegistry;\n    USDSCHEMAEXAMPLES_API\n    static const TfType &_GetStaticTfType();\n\n    static bool _IsTypedSchema();\n\n    // override SchemaBase virtuals.\n    USDSCHEMAEXAMPLES_API\n    const TfType &_GetTfType() const override;\n\npublic:\n    // --------------------------------------------------------------------- //\n    // COMPLEXSTRING \n    // --------------------------------------------------------------------- //\n    /// \n    ///\n    /// | ||\n    /// | -- | -- |\n    /// | Declaration | `string complexString = \"somethingComplex\"` |\n    /// | C++ Type | std::string |\n    /// | \\ref Usd_Datatypes \"Usd Type\" | SdfValueTypeNames->String |\n    USDSCHEMAEXAMPLES_API\n    UsdAttribute GetComplexStringAttr() const;\n\n    /// See GetComplexStringAttr(), and also \n    /// \\ref Usd_Create_Or_Get_Property for when to use Get vs Create.\n    /// If specified, author \\p defaultValue as the attribute's default,\n    /// sparsely (when it makes sense to do so) if \\p writeSparsely is \\c true -\n    /// the default for \\p writeSparsely is \\c false.\n    USDSCHEMAEXAMPLES_API\n    UsdAttribute CreateComplexStringAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const;\n\npublic:\n    // ===================================================================== //\n    // Feel free to add custom code below this line, it will be preserved by \n    // the code generator. \n    //\n    // Just remember to: \n    //  - Close the class declaration with }; \n    //  - Close the namespace with PXR_NAMESPACE_CLOSE_SCOPE\n    //  - Close the include guard with #endif\n    // ===================================================================== //\n    // --(BEGIN CUSTOM CODE)--\n};\n\nPXR_NAMESPACE_CLOSE_SCOPE\n\n#endif\n"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/generatedSchema.usda",
    "content": "#usda 1.0\n(\n    \"WARNING: THIS FILE IS GENERATED BY usdGenSchema.  DO NOT EDIT.\"\n)\n\nclass \"SimplePrim\" (\n    doc = \"\"\"An example of an untyped schema prim. Note that it does not \n    specify a typeName\"\"\"\n)\n{\n    int intAttr = 0 (\n        doc = \"An integer attribute with fallback value of 0.\"\n    )\n    rel target (\n        doc = \"\"\"A relationship called target that could point to another prim\n        or a property\"\"\"\n    )\n}\n\nclass ComplexPrim \"ComplexPrim\" (\n    doc = \"An example of a untyped IsA schema prim\"\n)\n{\n    string complexString = \"somethingComplex\"\n    int intAttr = 0 (\n        doc = \"An integer attribute with fallback value of 0.\"\n    )\n    rel target (\n        doc = \"\"\"A relationship called target that could point to another prim\n        or a property\"\"\"\n    )\n}\n\nclass \"ParamsAPI\"\n{\n    double params:mass (\n        doc = \"Double value denoting mass\"\n    )\n    double params:velocity (\n        doc = \"Double value denoting velocity\"\n    )\n    double params:volume (\n        doc = \"Double value denoting volume\"\n    )\n}\n\n"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/module.cpp",
    "content": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the following modification; you may not use this file except in\n// compliance with the Apache License and the following modification to it:\n// Section 6. Trademarks. is deleted and replaced with:\n//\n// 6. Trademarks. This License does not grant permission to use the trade\n//    names, trademarks, service marks, or product names of the Licensor\n//    and its affiliates, except as required to comply with Section 4(c) of\n//    the License and to reproduce the content of the NOTICE file.\n//\n// You may obtain a copy of the Apache License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the Apache License with the above modification is\n// distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, either express or implied. See the Apache License for the specific\n// language governing permissions and limitations under the Apache License.\n//\n#include \"pxr/base/tf/pySafePython.h\"\n#include \"pxr/pxr.h\"\n#include \"pxr/base/tf/pyModule.h\"\n\nPXR_NAMESPACE_USING_DIRECTIVE\n\nTF_WRAP_MODULE\n{\n    TF_WRAP(UsdSchemaExamplesSimple);\n    TF_WRAP(UsdSchemaExamplesComplex);\n    TF_WRAP(UsdSchemaExamplesParamsAPI);\n    TF_WRAP(UsdSchemaExamplesTokens);\n}"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/moduleDeps.cpp",
    "content": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the following modification; you may not use this file except in\n// compliance with the Apache License and the following modification to it:\n// Section 6. Trademarks. is deleted and replaced with:\n//\n// 6. Trademarks. This License does not grant permission to use the trade\n//    names, trademarks, service marks, or product names of the Licensor\n//    and its affiliates, except as required to comply with Section 4(c) of\n//    the License and to reproduce the content of the NOTICE file.\n//\n// You may obtain a copy of the Apache License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the Apache License with the above modification is\n// distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, either express or implied. See the Apache License for the specific\n// language governing permissions and limitations under the Apache License.\n//\n////////////////////////////////////////////////////////////////////////\n\n#include \"pxr/pxr.h\"\n#include \"pxr/base/tf/registryManager.h\"\n#include \"pxr/base/tf/scriptModuleLoader.h\"\n#include \"pxr/base/tf/token.h\"\n\n#include <vector>\n\nPXR_NAMESPACE_OPEN_SCOPE\n\nTF_REGISTRY_FUNCTION(TfScriptModuleLoader) {\n    // List of direct dependencies for this library.\n    const std::vector<TfToken> reqs = {\n        TfToken(\"sdf\"),\n        TfToken(\"tf\"),\n        TfToken(\"usd\"),\n        TfToken(\"vt\")\n    };\n    TfScriptModuleLoader::GetInstance().\n        RegisterLibrary(TfToken(\"usdSchemaExamples\"), TfToken(\"UsdSchemaExamples\"), reqs);\n}\n\nPXR_NAMESPACE_CLOSE_SCOPE\n\n"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/paramsAPI.cpp",
    "content": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the following modification; you may not use this file except in\n// compliance with the Apache License and the following modification to it:\n// Section 6. Trademarks. is deleted and replaced with:\n//\n// 6. Trademarks. This License does not grant permission to use the trade\n//    names, trademarks, service marks, or product names of the Licensor\n//    and its affiliates, except as required to comply with Section 4(c) of\n//    the License and to reproduce the content of the NOTICE file.\n//\n// You may obtain a copy of the Apache License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the Apache License with the above modification is\n// distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, either express or implied. See the Apache License for the specific\n// language governing permissions and limitations under the Apache License.\n//\n#include \"./paramsAPI.h\"\n#include \"pxr/usd/usd/schemaRegistry.h\"\n#include \"pxr/usd/usd/typed.h\"\n#include \"pxr/usd/usd/tokens.h\"\n\n#include \"pxr/usd/sdf/types.h\"\n#include \"pxr/usd/sdf/assetPath.h\"\n\nPXR_NAMESPACE_OPEN_SCOPE\n\n// Register the schema with the TfType system.\nTF_REGISTRY_FUNCTION(TfType)\n{\n    TfType::Define<UsdSchemaExamplesParamsAPI,\n        TfType::Bases< UsdAPISchemaBase > >();\n    \n}\n\nTF_DEFINE_PRIVATE_TOKENS(\n    _schemaTokens,\n    (ParamsAPI)\n);\n\n/* virtual */\nUsdSchemaExamplesParamsAPI::~UsdSchemaExamplesParamsAPI()\n{\n}\n\n/* static */\nUsdSchemaExamplesParamsAPI\nUsdSchemaExamplesParamsAPI::Get(const UsdStagePtr &stage, const SdfPath &path)\n{\n    if (!stage) {\n        TF_CODING_ERROR(\"Invalid stage\");\n        return UsdSchemaExamplesParamsAPI();\n    }\n    return UsdSchemaExamplesParamsAPI(stage->GetPrimAtPath(path));\n}\n\n\n/* virtual */\nUsdSchemaKind UsdSchemaExamplesParamsAPI::_GetSchemaKind() const\n{\n    return UsdSchemaExamplesParamsAPI::schemaKind;\n}\n\n/* static */\nbool\nUsdSchemaExamplesParamsAPI::CanApply(\n    const UsdPrim &prim, std::string *whyNot)\n{\n    return prim.CanApplyAPI<UsdSchemaExamplesParamsAPI>(whyNot);\n}\n\n/* static */\nUsdSchemaExamplesParamsAPI\nUsdSchemaExamplesParamsAPI::Apply(const UsdPrim &prim)\n{\n    if (prim.ApplyAPI<UsdSchemaExamplesParamsAPI>()) {\n        return UsdSchemaExamplesParamsAPI(prim);\n    }\n    return UsdSchemaExamplesParamsAPI();\n}\n\n/* static */\nconst TfType &\nUsdSchemaExamplesParamsAPI::_GetStaticTfType()\n{\n    static TfType tfType = TfType::Find<UsdSchemaExamplesParamsAPI>();\n    return tfType;\n}\n\n/* static */\nbool \nUsdSchemaExamplesParamsAPI::_IsTypedSchema()\n{\n    static bool isTyped = _GetStaticTfType().IsA<UsdTyped>();\n    return isTyped;\n}\n\n/* virtual */\nconst TfType &\nUsdSchemaExamplesParamsAPI::_GetTfType() const\n{\n    return _GetStaticTfType();\n}\n\nUsdAttribute\nUsdSchemaExamplesParamsAPI::GetMassAttr() const\n{\n    return GetPrim().GetAttribute(UsdSchemaExamplesTokens->paramsMass);\n}\n\nUsdAttribute\nUsdSchemaExamplesParamsAPI::CreateMassAttr(VtValue const &defaultValue, bool writeSparsely) const\n{\n    return UsdSchemaBase::_CreateAttr(UsdSchemaExamplesTokens->paramsMass,\n                       SdfValueTypeNames->Double,\n                       /* custom = */ false,\n                       SdfVariabilityVarying,\n                       defaultValue,\n                       writeSparsely);\n}\n\nUsdAttribute\nUsdSchemaExamplesParamsAPI::GetVelocityAttr() const\n{\n    return GetPrim().GetAttribute(UsdSchemaExamplesTokens->paramsVelocity);\n}\n\nUsdAttribute\nUsdSchemaExamplesParamsAPI::CreateVelocityAttr(VtValue const &defaultValue, bool writeSparsely) const\n{\n    return UsdSchemaBase::_CreateAttr(UsdSchemaExamplesTokens->paramsVelocity,\n                       SdfValueTypeNames->Double,\n                       /* custom = */ false,\n                       SdfVariabilityVarying,\n                       defaultValue,\n                       writeSparsely);\n}\n\nUsdAttribute\nUsdSchemaExamplesParamsAPI::GetVolumeAttr() const\n{\n    return GetPrim().GetAttribute(UsdSchemaExamplesTokens->paramsVolume);\n}\n\nUsdAttribute\nUsdSchemaExamplesParamsAPI::CreateVolumeAttr(VtValue const &defaultValue, bool writeSparsely) const\n{\n    return UsdSchemaBase::_CreateAttr(UsdSchemaExamplesTokens->paramsVolume,\n                       SdfValueTypeNames->Double,\n                       /* custom = */ false,\n                       SdfVariabilityVarying,\n                       defaultValue,\n                       writeSparsely);\n}\n\nnamespace {\nstatic inline TfTokenVector\n_ConcatenateAttributeNames(const TfTokenVector& left,const TfTokenVector& right)\n{\n    TfTokenVector result;\n    result.reserve(left.size() + right.size());\n    result.insert(result.end(), left.begin(), left.end());\n    result.insert(result.end(), right.begin(), right.end());\n    return result;\n}\n}\n\n/*static*/\nconst TfTokenVector&\nUsdSchemaExamplesParamsAPI::GetSchemaAttributeNames(bool includeInherited)\n{\n    static TfTokenVector localNames = {\n        UsdSchemaExamplesTokens->paramsMass,\n        UsdSchemaExamplesTokens->paramsVelocity,\n        UsdSchemaExamplesTokens->paramsVolume,\n    };\n    static TfTokenVector allNames =\n        _ConcatenateAttributeNames(\n            UsdAPISchemaBase::GetSchemaAttributeNames(true),\n            localNames);\n\n    if (includeInherited)\n        return allNames;\n    else\n        return localNames;\n}\n\nPXR_NAMESPACE_CLOSE_SCOPE\n\n// ===================================================================== //\n// Feel free to add custom code below this line. It will be preserved by\n// the code generator.\n//\n// Just remember to wrap code in the appropriate delimiters:\n// 'PXR_NAMESPACE_OPEN_SCOPE', 'PXR_NAMESPACE_CLOSE_SCOPE'.\n// ===================================================================== //\n// --(BEGIN CUSTOM CODE)--\n"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/paramsAPI.h",
    "content": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the following modification; you may not use this file except in\n// compliance with the Apache License and the following modification to it:\n// Section 6. Trademarks. is deleted and replaced with:\n//\n// 6. Trademarks. This License does not grant permission to use the trade\n//    names, trademarks, service marks, or product names of the Licensor\n//    and its affiliates, except as required to comply with Section 4(c) of\n//    the License and to reproduce the content of the NOTICE file.\n//\n// You may obtain a copy of the Apache License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the Apache License with the above modification is\n// distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, either express or implied. See the Apache License for the specific\n// language governing permissions and limitations under the Apache License.\n//\n#ifndef USDSCHEMAEXAMPLES_GENERATED_PARAMSAPI_H\n#define USDSCHEMAEXAMPLES_GENERATED_PARAMSAPI_H\n\n/// \\file usdSchemaExamples/paramsAPI.h\n\n#include \"pxr/pxr.h\"\n#include \"./api.h\"\n#include \"pxr/usd/usd/apiSchemaBase.h\"\n#include \"pxr/usd/usd/prim.h\"\n#include \"pxr/usd/usd/stage.h\"\n#include \"./tokens.h\"\n\n#include \"pxr/base/vt/value.h\"\n\n#include \"pxr/base/gf/vec3d.h\"\n#include \"pxr/base/gf/vec3f.h\"\n#include \"pxr/base/gf/matrix4d.h\"\n\n#include \"pxr/base/tf/token.h\"\n#include \"pxr/base/tf/type.h\"\n\nPXR_NAMESPACE_OPEN_SCOPE\n\nclass SdfAssetPath;\n\n// -------------------------------------------------------------------------- //\n// PARAMSAPI                                                                  //\n// -------------------------------------------------------------------------- //\n\n/// \\class UsdSchemaExamplesParamsAPI\n///\n///\nclass UsdSchemaExamplesParamsAPI : public UsdAPISchemaBase\n{\npublic:\n    /// Compile time constant representing what kind of schema this class is.\n    ///\n    /// \\sa UsdSchemaKind\n    static const UsdSchemaKind schemaKind = UsdSchemaKind::SingleApplyAPI;\n\n    /// Construct a UsdSchemaExamplesParamsAPI on UsdPrim \\p prim .\n    /// Equivalent to UsdSchemaExamplesParamsAPI::Get(prim.GetStage(), prim.GetPath())\n    /// for a \\em valid \\p prim, but will not immediately throw an error for\n    /// an invalid \\p prim\n    explicit UsdSchemaExamplesParamsAPI(const UsdPrim& prim=UsdPrim())\n        : UsdAPISchemaBase(prim)\n    {\n    }\n\n    /// Construct a UsdSchemaExamplesParamsAPI on the prim held by \\p schemaObj .\n    /// Should be preferred over UsdSchemaExamplesParamsAPI(schemaObj.GetPrim()),\n    /// as it preserves SchemaBase state.\n    explicit UsdSchemaExamplesParamsAPI(const UsdSchemaBase& schemaObj)\n        : UsdAPISchemaBase(schemaObj)\n    {\n    }\n\n    /// Destructor.\n    USDSCHEMAEXAMPLES_API\n    virtual ~UsdSchemaExamplesParamsAPI();\n\n    /// Return a vector of names of all pre-declared attributes for this schema\n    /// class and all its ancestor classes.  Does not include attributes that\n    /// may be authored by custom/extended methods of the schemas involved.\n    USDSCHEMAEXAMPLES_API\n    static const TfTokenVector &\n    GetSchemaAttributeNames(bool includeInherited=true);\n\n    /// Return a UsdSchemaExamplesParamsAPI holding the prim adhering to this\n    /// schema at \\p path on \\p stage.  If no prim exists at \\p path on\n    /// \\p stage, or if the prim at that path does not adhere to this schema,\n    /// return an invalid schema object.  This is shorthand for the following:\n    ///\n    /// \\code\n    /// UsdSchemaExamplesParamsAPI(stage->GetPrimAtPath(path));\n    /// \\endcode\n    ///\n    USDSCHEMAEXAMPLES_API\n    static UsdSchemaExamplesParamsAPI\n    Get(const UsdStagePtr &stage, const SdfPath &path);\n\n\n    /// Returns true if this <b>single-apply</b> API schema can be applied to \n    /// the given \\p prim. If this schema can not be a applied to the prim, \n    /// this returns false and, if provided, populates \\p whyNot with the \n    /// reason it can not be applied.\n    /// \n    /// Note that if CanApply returns false, that does not necessarily imply\n    /// that calling Apply will fail. Callers are expected to call CanApply\n    /// before calling Apply if they want to ensure that it is valid to \n    /// apply a schema.\n    /// \n    /// \\sa UsdPrim::GetAppliedSchemas()\n    /// \\sa UsdPrim::HasAPI()\n    /// \\sa UsdPrim::CanApplyAPI()\n    /// \\sa UsdPrim::ApplyAPI()\n    /// \\sa UsdPrim::RemoveAPI()\n    ///\n    USDSCHEMAEXAMPLES_API\n    static bool \n    CanApply(const UsdPrim &prim, std::string *whyNot=nullptr);\n\n    /// Applies this <b>single-apply</b> API schema to the given \\p prim.\n    /// This information is stored by adding \"ParamsAPI\" to the \n    /// token-valued, listOp metadata \\em apiSchemas on the prim.\n    /// \n    /// \\return A valid UsdSchemaExamplesParamsAPI object is returned upon success. \n    /// An invalid (or empty) UsdSchemaExamplesParamsAPI object is returned upon \n    /// failure. See \\ref UsdPrim::ApplyAPI() for conditions \n    /// resulting in failure. \n    /// \n    /// \\sa UsdPrim::GetAppliedSchemas()\n    /// \\sa UsdPrim::HasAPI()\n    /// \\sa UsdPrim::CanApplyAPI()\n    /// \\sa UsdPrim::ApplyAPI()\n    /// \\sa UsdPrim::RemoveAPI()\n    ///\n    USDSCHEMAEXAMPLES_API\n    static UsdSchemaExamplesParamsAPI \n    Apply(const UsdPrim &prim);\n\nprotected:\n    /// Returns the kind of schema this class belongs to.\n    ///\n    /// \\sa UsdSchemaKind\n    USDSCHEMAEXAMPLES_API\n    UsdSchemaKind _GetSchemaKind() const override;\n\nprivate:\n    // needs to invoke _GetStaticTfType.\n    friend class UsdSchemaRegistry;\n    USDSCHEMAEXAMPLES_API\n    static const TfType &_GetStaticTfType();\n\n    static bool _IsTypedSchema();\n\n    // override SchemaBase virtuals.\n    USDSCHEMAEXAMPLES_API\n    const TfType &_GetTfType() const override;\n\npublic:\n    // --------------------------------------------------------------------- //\n    // MASS \n    // --------------------------------------------------------------------- //\n    /// Double value denoting mass\n    ///\n    /// | ||\n    /// | -- | -- |\n    /// | Declaration | `double params:mass` |\n    /// | C++ Type | double |\n    /// | \\ref Usd_Datatypes \"Usd Type\" | SdfValueTypeNames->Double |\n    USDSCHEMAEXAMPLES_API\n    UsdAttribute GetMassAttr() const;\n\n    /// See GetMassAttr(), and also \n    /// \\ref Usd_Create_Or_Get_Property for when to use Get vs Create.\n    /// If specified, author \\p defaultValue as the attribute's default,\n    /// sparsely (when it makes sense to do so) if \\p writeSparsely is \\c true -\n    /// the default for \\p writeSparsely is \\c false.\n    USDSCHEMAEXAMPLES_API\n    UsdAttribute CreateMassAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const;\n\npublic:\n    // --------------------------------------------------------------------- //\n    // VELOCITY \n    // --------------------------------------------------------------------- //\n    /// Double value denoting velocity\n    ///\n    /// | ||\n    /// | -- | -- |\n    /// | Declaration | `double params:velocity` |\n    /// | C++ Type | double |\n    /// | \\ref Usd_Datatypes \"Usd Type\" | SdfValueTypeNames->Double |\n    USDSCHEMAEXAMPLES_API\n    UsdAttribute GetVelocityAttr() const;\n\n    /// See GetVelocityAttr(), and also \n    /// \\ref Usd_Create_Or_Get_Property for when to use Get vs Create.\n    /// If specified, author \\p defaultValue as the attribute's default,\n    /// sparsely (when it makes sense to do so) if \\p writeSparsely is \\c true -\n    /// the default for \\p writeSparsely is \\c false.\n    USDSCHEMAEXAMPLES_API\n    UsdAttribute CreateVelocityAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const;\n\npublic:\n    // --------------------------------------------------------------------- //\n    // VOLUME \n    // --------------------------------------------------------------------- //\n    /// Double value denoting volume\n    ///\n    /// | ||\n    /// | -- | -- |\n    /// | Declaration | `double params:volume` |\n    /// | C++ Type | double |\n    /// | \\ref Usd_Datatypes \"Usd Type\" | SdfValueTypeNames->Double |\n    USDSCHEMAEXAMPLES_API\n    UsdAttribute GetVolumeAttr() const;\n\n    /// See GetVolumeAttr(), and also \n    /// \\ref Usd_Create_Or_Get_Property for when to use Get vs Create.\n    /// If specified, author \\p defaultValue as the attribute's default,\n    /// sparsely (when it makes sense to do so) if \\p writeSparsely is \\c true -\n    /// the default for \\p writeSparsely is \\c false.\n    USDSCHEMAEXAMPLES_API\n    UsdAttribute CreateVolumeAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const;\n\npublic:\n    // ===================================================================== //\n    // Feel free to add custom code below this line, it will be preserved by \n    // the code generator. \n    //\n    // Just remember to: \n    //  - Close the class declaration with }; \n    //  - Close the namespace with PXR_NAMESPACE_CLOSE_SCOPE\n    //  - Close the include guard with #endif\n    // ===================================================================== //\n    // --(BEGIN CUSTOM CODE)--\n};\n\nPXR_NAMESPACE_CLOSE_SCOPE\n\n#endif\n"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/plugInfo.json",
    "content": "# Portions of this file auto-generated by usdGenSchema.\n# Edits will survive regeneration except for comments and\n# changes to types with autoGenerated=true.\n{\n    \"Plugins\": [\n        {\n            \"Info\": {\n                \"Types\": {\n                    \"UsdSchemaExamplesComplex\": {\n                        \"alias\": {\n                            \"UsdSchemaBase\": \"ComplexPrim\"\n                        }, \n                        \"autoGenerated\": true, \n                        \"bases\": [\n                            \"UsdSchemaExamplesSimple\"\n                        ], \n                        \"schemaKind\": \"concreteTyped\"\n                    }, \n                    \"UsdSchemaExamplesParamsAPI\": {\n                        \"alias\": {\n                            \"UsdSchemaBase\": \"ParamsAPI\"\n                        }, \n                        \"autoGenerated\": true, \n                        \"bases\": [\n                            \"UsdAPISchemaBase\"\n                        ], \n                        \"schemaKind\": \"singleApplyAPI\"\n                    }, \n                    \"UsdSchemaExamplesSimple\": {\n                        \"alias\": {\n                            \"UsdSchemaBase\": \"SimplePrim\"\n                        }, \n                        \"autoGenerated\": true, \n                        \"bases\": [\n                            \"UsdTyped\"\n                        ], \n                        \"schemaKind\": \"abstractTyped\"\n                    }\n                }\n            }, \n            \"LibraryPath\": \"@PLUG_INFO_LIBRARY_PATH@\", \n            \"Name\": \"usdSchemaExamples\", \n            \"ResourcePath\": \"@PLUG_INFO_RESOURCE_PATH@\", \n            \"Root\": \"@PLUG_INFO_ROOT@\", \n            \"Type\": \"library\"\n        }\n    ]\n}\n"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/simple.cpp",
    "content": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the following modification; you may not use this file except in\n// compliance with the Apache License and the following modification to it:\n// Section 6. Trademarks. is deleted and replaced with:\n//\n// 6. Trademarks. This License does not grant permission to use the trade\n//    names, trademarks, service marks, or product names of the Licensor\n//    and its affiliates, except as required to comply with Section 4(c) of\n//    the License and to reproduce the content of the NOTICE file.\n//\n// You may obtain a copy of the Apache License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the Apache License with the above modification is\n// distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, either express or implied. See the Apache License for the specific\n// language governing permissions and limitations under the Apache License.\n//\n#include \"./simple.h\"\n#include \"pxr/usd/usd/schemaRegistry.h\"\n#include \"pxr/usd/usd/typed.h\"\n\n#include \"pxr/usd/sdf/types.h\"\n#include \"pxr/usd/sdf/assetPath.h\"\n\nPXR_NAMESPACE_OPEN_SCOPE\n\n// Register the schema with the TfType system.\nTF_REGISTRY_FUNCTION(TfType)\n{\n    TfType::Define<UsdSchemaExamplesSimple,\n        TfType::Bases< UsdTyped > >();\n    \n}\n\n/* virtual */\nUsdSchemaExamplesSimple::~UsdSchemaExamplesSimple()\n{\n}\n\n/* static */\nUsdSchemaExamplesSimple\nUsdSchemaExamplesSimple::Get(const UsdStagePtr &stage, const SdfPath &path)\n{\n    if (!stage) {\n        TF_CODING_ERROR(\"Invalid stage\");\n        return UsdSchemaExamplesSimple();\n    }\n    return UsdSchemaExamplesSimple(stage->GetPrimAtPath(path));\n}\n\n\n/* virtual */\nUsdSchemaKind UsdSchemaExamplesSimple::_GetSchemaKind() const\n{\n    return UsdSchemaExamplesSimple::schemaKind;\n}\n\n/* static */\nconst TfType &\nUsdSchemaExamplesSimple::_GetStaticTfType()\n{\n    static TfType tfType = TfType::Find<UsdSchemaExamplesSimple>();\n    return tfType;\n}\n\n/* static */\nbool \nUsdSchemaExamplesSimple::_IsTypedSchema()\n{\n    static bool isTyped = _GetStaticTfType().IsA<UsdTyped>();\n    return isTyped;\n}\n\n/* virtual */\nconst TfType &\nUsdSchemaExamplesSimple::_GetTfType() const\n{\n    return _GetStaticTfType();\n}\n\nUsdAttribute\nUsdSchemaExamplesSimple::GetIntAttrAttr() const\n{\n    return GetPrim().GetAttribute(UsdSchemaExamplesTokens->intAttr);\n}\n\nUsdAttribute\nUsdSchemaExamplesSimple::CreateIntAttrAttr(VtValue const &defaultValue, bool writeSparsely) const\n{\n    return UsdSchemaBase::_CreateAttr(UsdSchemaExamplesTokens->intAttr,\n                       SdfValueTypeNames->Int,\n                       /* custom = */ false,\n                       SdfVariabilityVarying,\n                       defaultValue,\n                       writeSparsely);\n}\n\nUsdRelationship\nUsdSchemaExamplesSimple::GetTargetRel() const\n{\n    return GetPrim().GetRelationship(UsdSchemaExamplesTokens->target);\n}\n\nUsdRelationship\nUsdSchemaExamplesSimple::CreateTargetRel() const\n{\n    return GetPrim().CreateRelationship(UsdSchemaExamplesTokens->target,\n                       /* custom = */ false);\n}\n\nnamespace {\nstatic inline TfTokenVector\n_ConcatenateAttributeNames(const TfTokenVector& left,const TfTokenVector& right)\n{\n    TfTokenVector result;\n    result.reserve(left.size() + right.size());\n    result.insert(result.end(), left.begin(), left.end());\n    result.insert(result.end(), right.begin(), right.end());\n    return result;\n}\n}\n\n/*static*/\nconst TfTokenVector&\nUsdSchemaExamplesSimple::GetSchemaAttributeNames(bool includeInherited)\n{\n    static TfTokenVector localNames = {\n        UsdSchemaExamplesTokens->intAttr,\n    };\n    static TfTokenVector allNames =\n        _ConcatenateAttributeNames(\n            UsdTyped::GetSchemaAttributeNames(true),\n            localNames);\n\n    if (includeInherited)\n        return allNames;\n    else\n        return localNames;\n}\n\nPXR_NAMESPACE_CLOSE_SCOPE\n\n// ===================================================================== //\n// Feel free to add custom code below this line. It will be preserved by\n// the code generator.\n//\n// Just remember to wrap code in the appropriate delimiters:\n// 'PXR_NAMESPACE_OPEN_SCOPE', 'PXR_NAMESPACE_CLOSE_SCOPE'.\n// ===================================================================== //\n// --(BEGIN CUSTOM CODE)--\n"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/simple.h",
    "content": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the following modification; you may not use this file except in\n// compliance with the Apache License and the following modification to it:\n// Section 6. Trademarks. is deleted and replaced with:\n//\n// 6. Trademarks. This License does not grant permission to use the trade\n//    names, trademarks, service marks, or product names of the Licensor\n//    and its affiliates, except as required to comply with Section 4(c) of\n//    the License and to reproduce the content of the NOTICE file.\n//\n// You may obtain a copy of the Apache License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the Apache License with the above modification is\n// distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, either express or implied. See the Apache License for the specific\n// language governing permissions and limitations under the Apache License.\n//\n#ifndef USDSCHEMAEXAMPLES_GENERATED_SIMPLE_H\n#define USDSCHEMAEXAMPLES_GENERATED_SIMPLE_H\n\n/// \\file usdSchemaExamples/simple.h\n\n#include \"pxr/pxr.h\"\n#include \"./api.h\"\n#include \"pxr/usd/usd/typed.h\"\n#include \"pxr/usd/usd/prim.h\"\n#include \"pxr/usd/usd/stage.h\"\n#include \"./tokens.h\"\n\n#include \"pxr/base/vt/value.h\"\n\n#include \"pxr/base/gf/vec3d.h\"\n#include \"pxr/base/gf/vec3f.h\"\n#include \"pxr/base/gf/matrix4d.h\"\n\n#include \"pxr/base/tf/token.h\"\n#include \"pxr/base/tf/type.h\"\n\nPXR_NAMESPACE_OPEN_SCOPE\n\nclass SdfAssetPath;\n\n// -------------------------------------------------------------------------- //\n// SIMPLEPRIM                                                                 //\n// -------------------------------------------------------------------------- //\n\n/// \\class UsdSchemaExamplesSimple\n///\n/// An example of an untyped schema prim. Note that it does not \n/// specify a typeName\n///\nclass UsdSchemaExamplesSimple : public UsdTyped\n{\npublic:\n    /// Compile time constant representing what kind of schema this class is.\n    ///\n    /// \\sa UsdSchemaKind\n    static const UsdSchemaKind schemaKind = UsdSchemaKind::AbstractTyped;\n\n    /// Construct a UsdSchemaExamplesSimple on UsdPrim \\p prim .\n    /// Equivalent to UsdSchemaExamplesSimple::Get(prim.GetStage(), prim.GetPath())\n    /// for a \\em valid \\p prim, but will not immediately throw an error for\n    /// an invalid \\p prim\n    explicit UsdSchemaExamplesSimple(const UsdPrim& prim=UsdPrim())\n        : UsdTyped(prim)\n    {\n    }\n\n    /// Construct a UsdSchemaExamplesSimple on the prim held by \\p schemaObj .\n    /// Should be preferred over UsdSchemaExamplesSimple(schemaObj.GetPrim()),\n    /// as it preserves SchemaBase state.\n    explicit UsdSchemaExamplesSimple(const UsdSchemaBase& schemaObj)\n        : UsdTyped(schemaObj)\n    {\n    }\n\n    /// Destructor.\n    USDSCHEMAEXAMPLES_API\n    virtual ~UsdSchemaExamplesSimple();\n\n    /// Return a vector of names of all pre-declared attributes for this schema\n    /// class and all its ancestor classes.  Does not include attributes that\n    /// may be authored by custom/extended methods of the schemas involved.\n    USDSCHEMAEXAMPLES_API\n    static const TfTokenVector &\n    GetSchemaAttributeNames(bool includeInherited=true);\n\n    /// Return a UsdSchemaExamplesSimple holding the prim adhering to this\n    /// schema at \\p path on \\p stage.  If no prim exists at \\p path on\n    /// \\p stage, or if the prim at that path does not adhere to this schema,\n    /// return an invalid schema object.  This is shorthand for the following:\n    ///\n    /// \\code\n    /// UsdSchemaExamplesSimple(stage->GetPrimAtPath(path));\n    /// \\endcode\n    ///\n    USDSCHEMAEXAMPLES_API\n    static UsdSchemaExamplesSimple\n    Get(const UsdStagePtr &stage, const SdfPath &path);\n\n\nprotected:\n    /// Returns the kind of schema this class belongs to.\n    ///\n    /// \\sa UsdSchemaKind\n    USDSCHEMAEXAMPLES_API\n    UsdSchemaKind _GetSchemaKind() const override;\n\nprivate:\n    // needs to invoke _GetStaticTfType.\n    friend class UsdSchemaRegistry;\n    USDSCHEMAEXAMPLES_API\n    static const TfType &_GetStaticTfType();\n\n    static bool _IsTypedSchema();\n\n    // override SchemaBase virtuals.\n    USDSCHEMAEXAMPLES_API\n    const TfType &_GetTfType() const override;\n\npublic:\n    // --------------------------------------------------------------------- //\n    // INTATTR \n    // --------------------------------------------------------------------- //\n    /// An integer attribute with fallback value of 0.\n    ///\n    /// | ||\n    /// | -- | -- |\n    /// | Declaration | `int intAttr = 0` |\n    /// | C++ Type | int |\n    /// | \\ref Usd_Datatypes \"Usd Type\" | SdfValueTypeNames->Int |\n    USDSCHEMAEXAMPLES_API\n    UsdAttribute GetIntAttrAttr() const;\n\n    /// See GetIntAttrAttr(), and also \n    /// \\ref Usd_Create_Or_Get_Property for when to use Get vs Create.\n    /// If specified, author \\p defaultValue as the attribute's default,\n    /// sparsely (when it makes sense to do so) if \\p writeSparsely is \\c true -\n    /// the default for \\p writeSparsely is \\c false.\n    USDSCHEMAEXAMPLES_API\n    UsdAttribute CreateIntAttrAttr(VtValue const &defaultValue = VtValue(), bool writeSparsely=false) const;\n\npublic:\n    // --------------------------------------------------------------------- //\n    // TARGET \n    // --------------------------------------------------------------------- //\n    /// A relationship called target that could point to another prim\n    /// or a property\n    ///\n    USDSCHEMAEXAMPLES_API\n    UsdRelationship GetTargetRel() const;\n\n    /// See GetTargetRel(), and also \n    /// \\ref Usd_Create_Or_Get_Property for when to use Get vs Create\n    USDSCHEMAEXAMPLES_API\n    UsdRelationship CreateTargetRel() const;\n\npublic:\n    // ===================================================================== //\n    // Feel free to add custom code below this line, it will be preserved by \n    // the code generator. \n    //\n    // Just remember to: \n    //  - Close the class declaration with }; \n    //  - Close the namespace with PXR_NAMESPACE_CLOSE_SCOPE\n    //  - Close the include guard with #endif\n    // ===================================================================== //\n    // --(BEGIN CUSTOM CODE)--\n};\n\nPXR_NAMESPACE_CLOSE_SCOPE\n\n#endif\n"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/tokens.cpp",
    "content": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the following modification; you may not use this file except in\n// compliance with the Apache License and the following modification to it:\n// Section 6. Trademarks. is deleted and replaced with:\n//\n// 6. Trademarks. This License does not grant permission to use the trade\n//    names, trademarks, service marks, or product names of the Licensor\n//    and its affiliates, except as required to comply with Section 4(c) of\n//    the License and to reproduce the content of the NOTICE file.\n//\n// You may obtain a copy of the Apache License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the Apache License with the above modification is\n// distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, either express or implied. See the Apache License for the specific\n// language governing permissions and limitations under the Apache License.\n//\n#include \"./tokens.h\"\n\nPXR_NAMESPACE_OPEN_SCOPE\n\nUsdSchemaExamplesTokensType::UsdSchemaExamplesTokensType() :\n    complexString(\"complexString\", TfToken::Immortal),\n    intAttr(\"intAttr\", TfToken::Immortal),\n    paramsMass(\"params:mass\", TfToken::Immortal),\n    paramsVelocity(\"params:velocity\", TfToken::Immortal),\n    paramsVolume(\"params:volume\", TfToken::Immortal),\n    target(\"target\", TfToken::Immortal),\n    allTokens({\n        complexString,\n        intAttr,\n        paramsMass,\n        paramsVelocity,\n        paramsVolume,\n        target\n    })\n{\n}\n\nTfStaticData<UsdSchemaExamplesTokensType> UsdSchemaExamplesTokens;\n\nPXR_NAMESPACE_CLOSE_SCOPE\n"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/tokens.h",
    "content": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the following modification; you may not use this file except in\n// compliance with the Apache License and the following modification to it:\n// Section 6. Trademarks. is deleted and replaced with:\n//\n// 6. Trademarks. This License does not grant permission to use the trade\n//    names, trademarks, service marks, or product names of the Licensor\n//    and its affiliates, except as required to comply with Section 4(c) of\n//    the License and to reproduce the content of the NOTICE file.\n//\n// You may obtain a copy of the Apache License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the Apache License with the above modification is\n// distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, either express or implied. See the Apache License for the specific\n// language governing permissions and limitations under the Apache License.\n//\n#ifndef USDSCHEMAEXAMPLES_TOKENS_H\n#define USDSCHEMAEXAMPLES_TOKENS_H\n\n/// \\file usdSchemaExamples/tokens.h\n\n// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n// \n// This is an automatically generated file (by usdGenSchema.py).\n// Do not hand-edit!\n// \n// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n\n#include \"pxr/pxr.h\"\n#include \"./api.h\"\n#include \"pxr/base/tf/staticData.h\"\n#include \"pxr/base/tf/token.h\"\n#include <vector>\n\nPXR_NAMESPACE_OPEN_SCOPE\n\n\n/// \\class UsdSchemaExamplesTokensType\n///\n/// \\link UsdSchemaExamplesTokens \\endlink provides static, efficient\n/// \\link TfToken TfTokens\\endlink for use in all public USD API.\n///\n/// These tokens are auto-generated from the module's schema, representing\n/// property names, for when you need to fetch an attribute or relationship\n/// directly by name, e.g. UsdPrim::GetAttribute(), in the most efficient\n/// manner, and allow the compiler to verify that you spelled the name\n/// correctly.\n///\n/// UsdSchemaExamplesTokens also contains all of the \\em allowedTokens values\n/// declared for schema builtin attributes of 'token' scene description type.\n/// Use UsdSchemaExamplesTokens like so:\n///\n/// \\code\n///     gprim.GetMyTokenValuedAttr().Set(UsdSchemaExamplesTokens->complexString);\n/// \\endcode\nstruct UsdSchemaExamplesTokensType {\n    USDSCHEMAEXAMPLES_API UsdSchemaExamplesTokensType();\n    /// \\brief \"complexString\"\n    /// \n    /// UsdSchemaExamplesComplex\n    const TfToken complexString;\n    /// \\brief \"intAttr\"\n    /// \n    /// UsdSchemaExamplesSimple\n    const TfToken intAttr;\n    /// \\brief \"params:mass\"\n    /// \n    /// UsdSchemaExamplesParamsAPI\n    const TfToken paramsMass;\n    /// \\brief \"params:velocity\"\n    /// \n    /// UsdSchemaExamplesParamsAPI\n    const TfToken paramsVelocity;\n    /// \\brief \"params:volume\"\n    /// \n    /// UsdSchemaExamplesParamsAPI\n    const TfToken paramsVolume;\n    /// \\brief \"target\"\n    /// \n    /// UsdSchemaExamplesSimple\n    const TfToken target;\n    /// A vector of all of the tokens listed above.\n    const std::vector<TfToken> allTokens;\n};\n\n/// \\var UsdSchemaExamplesTokens\n///\n/// A global variable with static, efficient \\link TfToken TfTokens\\endlink\n/// for use in all public USD API.  \\sa UsdSchemaExamplesTokensType\nextern USDSCHEMAEXAMPLES_API TfStaticData<UsdSchemaExamplesTokensType> UsdSchemaExamplesTokens;\n\nPXR_NAMESPACE_CLOSE_SCOPE\n\n#endif\n"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/wrapComplex.cpp",
    "content": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the following modification; you may not use this file except in\n// compliance with the Apache License and the following modification to it:\n// Section 6. Trademarks. is deleted and replaced with:\n//\n// 6. Trademarks. This License does not grant permission to use the trade\n//    names, trademarks, service marks, or product names of the Licensor\n//    and its affiliates, except as required to comply with Section 4(c) of\n//    the License and to reproduce the content of the NOTICE file.\n//\n// You may obtain a copy of the Apache License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the Apache License with the above modification is\n// distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, either express or implied. See the Apache License for the specific\n// language governing permissions and limitations under the Apache License.\n//\n#include \"./complex.h\"\n#include \"pxr/usd/usd/schemaBase.h\"\n\n#include \"pxr/usd/sdf/primSpec.h\"\n\n#include \"pxr/usd/usd/pyConversions.h\"\n#include \"pxr/base/tf/pyContainerConversions.h\"\n#include \"pxr/base/tf/pyResultConversions.h\"\n#include \"pxr/base/tf/pyUtils.h\"\n#include \"pxr/base/tf/wrapTypeHelpers.h\"\n\n#include <hboost/python.hpp>\n\n#include <string>\n\nusing namespace hboost::python;\n\nPXR_NAMESPACE_USING_DIRECTIVE\n\nnamespace {\n\n#define WRAP_CUSTOM                                                     \\\n    template <class Cls> static void _CustomWrapCode(Cls &_class)\n\n// fwd decl.\nWRAP_CUSTOM;\n\n        \nstatic UsdAttribute\n_CreateComplexStringAttr(UsdSchemaExamplesComplex &self,\n                                      object defaultVal, bool writeSparsely) {\n    return self.CreateComplexStringAttr(\n        UsdPythonToSdfType(defaultVal, SdfValueTypeNames->String), writeSparsely);\n}\n\nstatic std::string\n_Repr(const UsdSchemaExamplesComplex &self)\n{\n    std::string primRepr = TfPyRepr(self.GetPrim());\n    return TfStringPrintf(\n        \"UsdSchemaExamples.Complex(%s)\",\n        primRepr.c_str());\n}\n\n} // anonymous namespace\n\nvoid wrapUsdSchemaExamplesComplex()\n{\n    typedef UsdSchemaExamplesComplex This;\n\n    class_<This, bases<UsdSchemaExamplesSimple> >\n        cls(\"Complex\");\n\n    cls\n        .def(init<UsdPrim>(arg(\"prim\")))\n        .def(init<UsdSchemaBase const&>(arg(\"schemaObj\")))\n        .def(TfTypePythonClass())\n\n        .def(\"Get\", &This::Get, (arg(\"stage\"), arg(\"path\")))\n        .staticmethod(\"Get\")\n\n        .def(\"Define\", &This::Define, (arg(\"stage\"), arg(\"path\")))\n        .staticmethod(\"Define\")\n\n        .def(\"GetSchemaAttributeNames\",\n             &This::GetSchemaAttributeNames,\n             arg(\"includeInherited\")=true,\n             return_value_policy<TfPySequenceToList>())\n        .staticmethod(\"GetSchemaAttributeNames\")\n\n        .def(\"_GetStaticTfType\", (TfType const &(*)()) TfType::Find<This>,\n             return_value_policy<return_by_value>())\n        .staticmethod(\"_GetStaticTfType\")\n\n        .def(!self)\n\n        \n        .def(\"GetComplexStringAttr\",\n             &This::GetComplexStringAttr)\n        .def(\"CreateComplexStringAttr\",\n             &_CreateComplexStringAttr,\n             (arg(\"defaultValue\")=object(),\n              arg(\"writeSparsely\")=false))\n\n        .def(\"__repr__\", ::_Repr)\n    ;\n\n    _CustomWrapCode(cls);\n}\n\n// ===================================================================== //\n// Feel free to add custom code below this line, it will be preserved by \n// the code generator.  The entry point for your custom code should look\n// minimally like the following:\n//\n// WRAP_CUSTOM {\n//     _class\n//         .def(\"MyCustomMethod\", ...)\n//     ;\n// }\n//\n// Of course any other ancillary or support code may be provided.\n// \n// Just remember to wrap code in the appropriate delimiters:\n// 'namespace {', '}'.\n//\n// ===================================================================== //\n// --(BEGIN CUSTOM CODE)--\n\nnamespace {\n\nWRAP_CUSTOM {\n}\n\n}\n"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/wrapParamsAPI.cpp",
    "content": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the following modification; you may not use this file except in\n// compliance with the Apache License and the following modification to it:\n// Section 6. Trademarks. is deleted and replaced with:\n//\n// 6. Trademarks. This License does not grant permission to use the trade\n//    names, trademarks, service marks, or product names of the Licensor\n//    and its affiliates, except as required to comply with Section 4(c) of\n//    the License and to reproduce the content of the NOTICE file.\n//\n// You may obtain a copy of the Apache License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the Apache License with the above modification is\n// distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, either express or implied. See the Apache License for the specific\n// language governing permissions and limitations under the Apache License.\n//\n#include \"./paramsAPI.h\"\n#include \"pxr/usd/usd/schemaBase.h\"\n\n#include \"pxr/usd/sdf/primSpec.h\"\n\n#include \"pxr/usd/usd/pyConversions.h\"\n#include \"pxr/base/tf/pyAnnotatedBoolResult.h\"\n#include \"pxr/base/tf/pyContainerConversions.h\"\n#include \"pxr/base/tf/pyResultConversions.h\"\n#include \"pxr/base/tf/pyUtils.h\"\n#include \"pxr/base/tf/wrapTypeHelpers.h\"\n\n#include <hboost/python.hpp>\n\n#include <string>\n\nusing namespace hboost::python;\n\nPXR_NAMESPACE_USING_DIRECTIVE\n\nnamespace {\n\n#define WRAP_CUSTOM                                                     \\\n    template <class Cls> static void _CustomWrapCode(Cls &_class)\n\n// fwd decl.\nWRAP_CUSTOM;\n\n        \nstatic UsdAttribute\n_CreateMassAttr(UsdSchemaExamplesParamsAPI &self,\n                                      object defaultVal, bool writeSparsely) {\n    return self.CreateMassAttr(\n        UsdPythonToSdfType(defaultVal, SdfValueTypeNames->Double), writeSparsely);\n}\n        \nstatic UsdAttribute\n_CreateVelocityAttr(UsdSchemaExamplesParamsAPI &self,\n                                      object defaultVal, bool writeSparsely) {\n    return self.CreateVelocityAttr(\n        UsdPythonToSdfType(defaultVal, SdfValueTypeNames->Double), writeSparsely);\n}\n        \nstatic UsdAttribute\n_CreateVolumeAttr(UsdSchemaExamplesParamsAPI &self,\n                                      object defaultVal, bool writeSparsely) {\n    return self.CreateVolumeAttr(\n        UsdPythonToSdfType(defaultVal, SdfValueTypeNames->Double), writeSparsely);\n}\n\nstatic std::string\n_Repr(const UsdSchemaExamplesParamsAPI &self)\n{\n    std::string primRepr = TfPyRepr(self.GetPrim());\n    return TfStringPrintf(\n        \"UsdSchemaExamples.ParamsAPI(%s)\",\n        primRepr.c_str());\n}\n\nstruct UsdSchemaExamplesParamsAPI_CanApplyResult : \n    public TfPyAnnotatedBoolResult<std::string>\n{\n    UsdSchemaExamplesParamsAPI_CanApplyResult(bool val, std::string const &msg) :\n        TfPyAnnotatedBoolResult<std::string>(val, msg) {}\n};\n\nstatic UsdSchemaExamplesParamsAPI_CanApplyResult\n_WrapCanApply(const UsdPrim& prim)\n{\n    std::string whyNot;\n    bool result = UsdSchemaExamplesParamsAPI::CanApply(prim, &whyNot);\n    return UsdSchemaExamplesParamsAPI_CanApplyResult(result, whyNot);\n}\n\n} // anonymous namespace\n\nvoid wrapUsdSchemaExamplesParamsAPI()\n{\n    typedef UsdSchemaExamplesParamsAPI This;\n\n    UsdSchemaExamplesParamsAPI_CanApplyResult::Wrap<UsdSchemaExamplesParamsAPI_CanApplyResult>(\n        \"_CanApplyResult\", \"whyNot\");\n\n    class_<This, bases<UsdAPISchemaBase> >\n        cls(\"ParamsAPI\");\n\n    cls\n        .def(init<UsdPrim>(arg(\"prim\")))\n        .def(init<UsdSchemaBase const&>(arg(\"schemaObj\")))\n        .def(TfTypePythonClass())\n\n        .def(\"Get\", &This::Get, (arg(\"stage\"), arg(\"path\")))\n        .staticmethod(\"Get\")\n\n        .def(\"CanApply\", &_WrapCanApply, (arg(\"prim\")))\n        .staticmethod(\"CanApply\")\n\n        .def(\"Apply\", &This::Apply, (arg(\"prim\")))\n        .staticmethod(\"Apply\")\n\n        .def(\"GetSchemaAttributeNames\",\n             &This::GetSchemaAttributeNames,\n             arg(\"includeInherited\")=true,\n             return_value_policy<TfPySequenceToList>())\n        .staticmethod(\"GetSchemaAttributeNames\")\n\n        .def(\"_GetStaticTfType\", (TfType const &(*)()) TfType::Find<This>,\n             return_value_policy<return_by_value>())\n        .staticmethod(\"_GetStaticTfType\")\n\n        .def(!self)\n\n        \n        .def(\"GetMassAttr\",\n             &This::GetMassAttr)\n        .def(\"CreateMassAttr\",\n             &_CreateMassAttr,\n             (arg(\"defaultValue\")=object(),\n              arg(\"writeSparsely\")=false))\n        \n        .def(\"GetVelocityAttr\",\n             &This::GetVelocityAttr)\n        .def(\"CreateVelocityAttr\",\n             &_CreateVelocityAttr,\n             (arg(\"defaultValue\")=object(),\n              arg(\"writeSparsely\")=false))\n        \n        .def(\"GetVolumeAttr\",\n             &This::GetVolumeAttr)\n        .def(\"CreateVolumeAttr\",\n             &_CreateVolumeAttr,\n             (arg(\"defaultValue\")=object(),\n              arg(\"writeSparsely\")=false))\n\n        .def(\"__repr__\", ::_Repr)\n    ;\n\n    _CustomWrapCode(cls);\n}\n\n// ===================================================================== //\n// Feel free to add custom code below this line, it will be preserved by \n// the code generator.  The entry point for your custom code should look\n// minimally like the following:\n//\n// WRAP_CUSTOM {\n//     _class\n//         .def(\"MyCustomMethod\", ...)\n//     ;\n// }\n//\n// Of course any other ancillary or support code may be provided.\n// \n// Just remember to wrap code in the appropriate delimiters:\n// 'namespace {', '}'.\n//\n// ===================================================================== //\n// --(BEGIN CUSTOM CODE)--\n\nnamespace {\n\nWRAP_CUSTOM {\n}\n\n}\n"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/wrapSimple.cpp",
    "content": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the following modification; you may not use this file except in\n// compliance with the Apache License and the following modification to it:\n// Section 6. Trademarks. is deleted and replaced with:\n//\n// 6. Trademarks. This License does not grant permission to use the trade\n//    names, trademarks, service marks, or product names of the Licensor\n//    and its affiliates, except as required to comply with Section 4(c) of\n//    the License and to reproduce the content of the NOTICE file.\n//\n// You may obtain a copy of the Apache License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the Apache License with the above modification is\n// distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, either express or implied. See the Apache License for the specific\n// language governing permissions and limitations under the Apache License.\n//\n#include \"./simple.h\"\n#include \"pxr/usd/usd/schemaBase.h\"\n\n#include \"pxr/usd/sdf/primSpec.h\"\n\n#include \"pxr/usd/usd/pyConversions.h\"\n#include \"pxr/base/tf/pyContainerConversions.h\"\n#include \"pxr/base/tf/pyResultConversions.h\"\n#include \"pxr/base/tf/pyUtils.h\"\n#include \"pxr/base/tf/wrapTypeHelpers.h\"\n\n#include <hboost/python.hpp>\n\n#include <string>\n\nusing namespace hboost::python;\n\nPXR_NAMESPACE_USING_DIRECTIVE\n\nnamespace {\n\n#define WRAP_CUSTOM                                                     \\\n    template <class Cls> static void _CustomWrapCode(Cls &_class)\n\n// fwd decl.\nWRAP_CUSTOM;\n\n        \nstatic UsdAttribute\n_CreateIntAttrAttr(UsdSchemaExamplesSimple &self,\n                                      object defaultVal, bool writeSparsely) {\n    return self.CreateIntAttrAttr(\n        UsdPythonToSdfType(defaultVal, SdfValueTypeNames->Int), writeSparsely);\n}\n\nstatic std::string\n_Repr(const UsdSchemaExamplesSimple &self)\n{\n    std::string primRepr = TfPyRepr(self.GetPrim());\n    return TfStringPrintf(\n        \"UsdSchemaExamples.Simple(%s)\",\n        primRepr.c_str());\n}\n\n} // anonymous namespace\n\nvoid wrapUsdSchemaExamplesSimple()\n{\n    typedef UsdSchemaExamplesSimple This;\n\n    class_<This, bases<UsdTyped> >\n        cls(\"Simple\");\n\n    cls\n        .def(init<UsdPrim>(arg(\"prim\")))\n        .def(init<UsdSchemaBase const&>(arg(\"schemaObj\")))\n        .def(TfTypePythonClass())\n\n        .def(\"Get\", &This::Get, (arg(\"stage\"), arg(\"path\")))\n        .staticmethod(\"Get\")\n\n        .def(\"GetSchemaAttributeNames\",\n             &This::GetSchemaAttributeNames,\n             arg(\"includeInherited\")=true,\n             return_value_policy<TfPySequenceToList>())\n        .staticmethod(\"GetSchemaAttributeNames\")\n\n        .def(\"_GetStaticTfType\", (TfType const &(*)()) TfType::Find<This>,\n             return_value_policy<return_by_value>())\n        .staticmethod(\"_GetStaticTfType\")\n\n        .def(!self)\n\n        \n        .def(\"GetIntAttrAttr\",\n             &This::GetIntAttrAttr)\n        .def(\"CreateIntAttrAttr\",\n             &_CreateIntAttrAttr,\n             (arg(\"defaultValue\")=object(),\n              arg(\"writeSparsely\")=false))\n\n        \n        .def(\"GetTargetRel\",\n             &This::GetTargetRel)\n        .def(\"CreateTargetRel\",\n             &This::CreateTargetRel)\n        .def(\"__repr__\", ::_Repr)\n    ;\n\n    _CustomWrapCode(cls);\n}\n\n// ===================================================================== //\n// Feel free to add custom code below this line, it will be preserved by \n// the code generator.  The entry point for your custom code should look\n// minimally like the following:\n//\n// WRAP_CUSTOM {\n//     _class\n//         .def(\"MyCustomMethod\", ...)\n//     ;\n// }\n//\n// Of course any other ancillary or support code may be provided.\n// \n// Just remember to wrap code in the appropriate delimiters:\n// 'namespace {', '}'.\n//\n// ===================================================================== //\n// --(BEGIN CUSTOM CODE)--\n\nnamespace {\n\nWRAP_CUSTOM {\n}\n\n}\n"
  },
  {
    "path": "files/plugins/schemas/compiledSchema/src/wrapTokens.cpp",
    "content": "//\n// Copyright 2016 Pixar\n//\n// Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n// with the following modification; you may not use this file except in\n// compliance with the Apache License and the following modification to it:\n// Section 6. Trademarks. is deleted and replaced with:\n//\n// 6. Trademarks. This License does not grant permission to use the trade\n//    names, trademarks, service marks, or product names of the Licensor\n//    and its affiliates, except as required to comply with Section 4(c) of\n//    the License and to reproduce the content of the NOTICE file.\n//\n// You may obtain a copy of the Apache License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the Apache License with the above modification is\n// distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n// KIND, either express or implied. See the Apache License for the specific\n// language governing permissions and limitations under the Apache License.\n//\n// GENERATED FILE.  DO NOT EDIT.\n#include <hboost/python/class.hpp>\n#include \"./tokens.h\"\n\nPXR_NAMESPACE_USING_DIRECTIVE\n\nnamespace {\n\n// Helper to return a static token as a string.  We wrap tokens as Python\n// strings and for some reason simply wrapping the token using def_readonly\n// bypasses to-Python conversion, leading to the error that there's no\n// Python type for the C++ TfToken type.  So we wrap this functor instead.\nclass _WrapStaticToken {\npublic:\n    _WrapStaticToken(const TfToken* token) : _token(token) { }\n\n    std::string operator()() const\n    {\n        return _token->GetString();\n    }\n\nprivate:\n    const TfToken* _token;\n};\n\ntemplate <typename T>\nvoid\n_AddToken(T& cls, const char* name, const TfToken& token)\n{\n    cls.add_static_property(name,\n                            hboost::python::make_function(\n                                _WrapStaticToken(&token),\n                                hboost::python::return_value_policy<\n                                    hboost::python::return_by_value>(),\n                                hboost::mpl::vector1<std::string>()));\n}\n\n} // anonymous\n\nvoid wrapUsdSchemaExamplesTokens()\n{\n    hboost::python::class_<UsdSchemaExamplesTokensType, hboost::noncopyable>\n        cls(\"Tokens\", hboost::python::no_init);\n    _AddToken(cls, \"complexString\", UsdSchemaExamplesTokens->complexString);\n    _AddToken(cls, \"intAttr\", UsdSchemaExamplesTokens->intAttr);\n    _AddToken(cls, \"paramsMass\", UsdSchemaExamplesTokens->paramsMass);\n    _AddToken(cls, \"paramsVelocity\", UsdSchemaExamplesTokens->paramsVelocity);\n    _AddToken(cls, \"paramsVolume\", UsdSchemaExamplesTokens->paramsVolume);\n    _AddToken(cls, \"target\", UsdSchemaExamplesTokens->target);\n}\n"
  },
  {
    "path": "files/plugins/schemas/exampleSchema.usda",
    "content": "#usda 1.0\n(\n    \"\"\" This file contains an example schemata for code generation using\n        usdGenSchema.\n    \"\"\"\n    subLayers = [\n        @usd/schema.usda@\n    ]\n) \n\nover \"GLOBAL\" (\n    customData = {\n        string libraryName       = \"usdSchemaExamples\"\n        string libraryPath       = \".\"\n        string libraryPrefix     = \"UsdSchemaExamples\"\n    }\n) {\n}\n\nclass \"SimplePrim\" (\n    doc = \"\"\"An example of an untyped schema prim. Note that it does not \n    specify a typeName\"\"\"\n    # IsA schemas should derive from </Typed>, which is defined in the sublayer\n    # usd/lib/usd/schema.usda.\n    inherits = </Typed>\n    customData = {\n        # Provide a different class name for the C++ and python schema classes.\n        # This will be prefixed with libraryPrefix.\n        # In this case, the class name becomes UsdSchemaExamplesSimple.\n        string className = \"Simple\"\n        }\n    )  \n{\n    int intAttr = 0 (\n        doc = \"An integer attribute with fallback value of 0.\"\n    )\n    rel target (\n        doc = \"\"\"A relationship called target that could point to another prim\n        or a property\"\"\"\n    )\n}\n\n# Note that it does not specify a typeName.\nclass ComplexPrim \"ComplexPrim\" (\n    doc = \"\"\"An example of a untyped IsA schema prim\"\"\"\n    # Inherits from </SimplePrim> defined in simple.usda.\n    inherits = </SimplePrim>\n    customData = {\n        string className = \"Complex\"\n    }\n)  \n{\n    string complexString = \"somethingComplex\"\n}\n    \nclass \"ParamsAPI\" (\n    inherits = </APISchemaBase>\n)\n{\n    double params:mass (\n        # Informs schema generator to create GetMassAttr() method\n        # instead of GetParamsMassAttr() method\n        customData = {\n            string apiName = \"mass\"\n        }\n        doc = \"Double value denoting mass\"\n    )\n    double params:velocity (\n        customData = {\n            string apiName = \"velocity\"\n        }\n        doc = \"Double value denoting velocity\"\n    )\n    double params:volume (\n        customData = {\n            string apiName = \"volume\"\n        }\n        doc = \"Double value denoting volume\"\n    )\n}"
  },
  {
    "path": "setup.sh",
    "content": "# Source repo\nif [ ! $REPO_SOURCED ]\nthen\n    # Define repo root\n    export REPO_SOURCED=1\n    export REPO_ROOT=$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" &> /dev/null && (pwd -W 2> /dev/null || pwd))\n    # Source Houdini (This defines what Houdini version to compile against)\n    pushd /opt/hfs19.5 > /dev/null\n    source houdini_setup\n    popd > /dev/null\n    export HOUDINI_LMINFO_VERBOSE=1\nfi\n\n\n"
  }
]