Implement loading directly into a Maya USD Proxy Shape - #61
Conversation
| shape = mayaUsd_createStageWithNewLayer.createStageWithNewLayer() | ||
| stage = mayaUsd.ufe.getStage('|world' + shape) | ||
| prim_path = "/root" | ||
| UsdGeom.Xform.Define(stage, prim_path) |
There was a problem hiding this comment.
i got some error on this line when loading the USD. It appears that it cannot find the stage layer from the loaded usd(which is weird as it should be using the staging layer which is newly created)

During load error happened on Product: "usdAsset" Representation: "usd" Version: 7
Error message:
Error in 'pxrInternal_v0_23__pxrReserved__::UsdGeomXform::Define' at line 70 in file S:\jenkins\workspace\ECP\ecg-usd-build\ecg-usd-full-python3.11-windows\ecg-usd-build\usd\pxr\usd\usdGeom\xform.cpp : 'Invalid stage'
Traceback (most recent call last):
File "D:\ayon-core\client\ayon_core\tools\loader\models\actions.py", line 740, in _load_representations_by_loader
load_with_repre_context(
File "D:\ayon-core\client\ayon_core\pipeline\load\utils.py", line 325, in load_with_repre_context
return loader.load(repre_context, name, namespace, options)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\ayon-addon_template\ayon-maya\client\ayon_maya\plugins\load\load_maya_usd_add_reference.py", line 52, in load
UsdGeom.Xform.Define(stage, prim_path)
pxr.Tf.ErrorException:
Error in 'pxrInternal_v0_23__pxrReserved__::UsdGeomXform::Define' at line 70 in file S:\jenkins\workspace\ECP\ecg-usd-build\ecg-usd-full-python3.11-windows\ecg-usd-build\usd\pxr\usd\usdGeom\xform.cpp : 'Invalid stage'
| def load(self, context, name=None, namespace=None, options=None): | ||
|
|
||
| selection = list(iter_ufe_usd_selection()) | ||
| assert len(selection) == 1, "Select only one PRIM please" |
There was a problem hiding this comment.
The error means that you need to SELECT a PRIM inside the Maya USD Proxy to 'reference into'. Unfortunately since it 'references into a prim' there isn't really something more intuitive I could think of whilst still allowing to load anywhere inside the USD hierarchy.
There was a problem hiding this comment.
Pull request overview
This PR prototypes loading USD references and Maya references directly into Maya USD Proxy Shapes while keeping those loads manageable via AYON’s container/inventory workflow (update/switch/remove).
Changes:
- Add two new USD-proxy loaders: one for adding USD references and one for adding MayaReference prims.
- Introduce USD-utility helpers for UFE selection parsing, USD prim containerization metadata, and spec removal.
- Extend pipeline container discovery to include containerized USD prims inside mayaUsdProxyShape stages, and adapt member listing for UFE-path “containers”.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
client/ayon_maya/plugins/load/load_maya_usd_add_reference.py |
New loader to add USD references to a selected (or newly created) USD prim in a Maya USD stage. |
client/ayon_maya/plugins/load/load_maya_usd_add_maya_reference.py |
New loader to create MayaReference prims in a USD stage and manage them via inventory actions. |
client/ayon_maya/api/usdlib.py |
New USD helper module: UFE selection iteration, prim containerization, and Sdf spec deletion utilities. |
client/ayon_maya/api/pipeline.py |
Adds parsing/listing of USD-prim-backed containers traversed from mayaUsdProxyShape stages. |
client/ayon_maya/api/lib.py |
Treats UFE-path-based “containers” as single-member containers for downstream inventory operations. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| for prim in stage.TraverseAll(): | ||
| container = parse_usd_prim_container(prim, proxy=proxy) | ||
| if container: | ||
| yield container |
| for key, value in { | ||
| "ayon:schema": "openpype:container-2.0", | ||
| "ayon:id": AVALON_CONTAINER_ID, | ||
| "ayon:name": name, | ||
| "ayon:namespace": namespace, | ||
| "ayon:loader": loader, | ||
| "ayon:representation": context["representation"]["id"], | ||
| }.items(): | ||
| prim.SetCustomDataByKey(key, str(value)) |
| for references, index in self._get_prim_references(prim): | ||
| reference = references[index] | ||
| new_reference = Sdf.Reference( | ||
| assetPath=path, | ||
| customData=reference.customData, | ||
| layerOffset=reference.layerOffset, | ||
| primPath=reference.primPath | ||
| ) | ||
| references[index] = new_reference |
| assert len(selection) == 1, "Select only one PRIM please" | ||
| ufe_path = selection[0] | ||
| path = self.filepath_from_context(context) | ||
| # Make sure we can load the plugin |
| cmds.loadPlugin("mayaUsdPlugin", quiet=True) | ||
| import mayaUsdAddMayaReference | ||
|
|
||
| namespace = "test" |
| containerise_prim( | ||
| prim, | ||
| name=name, | ||
| namespace=namespace or "", | ||
| context=context, | ||
| loader=self.__class__.__name__ | ||
| ) | ||
|
|
||
| return prim |
| prim.SetCustomDataByKey( | ||
| "ayon:representation", str(representation["_id"]) | ||
| ) |

Changelog Description
Additional info
Separated from #2
Testing notes: