Autodesk / Autodesk/maya-usd

context.SetPruneChildren(True) does not prevent reading children in python PrimReader

Open
#4,355 4 comments 0 reactions 1 assignee Claimed by @santosg87 View on GitHub
bug
Dominant language
Wolfram Language
Stars
905
Forks
223
Avg merge
2d 9h
Merged PRs (30d)
17

Description

**Describe the bug**
Conventional examples of usd rigging workflows use assets the Usd description of the Maya Reference and the static/cached representation the asset in the composed stage are mutually exclusive variants in a given set.
I am currently prototyping a method to load a rig reference on-demand when using "editAsMaya" on the asset root (`character_01`) that does not require variant swaps or use of the Sdf API.

In this example the rigs to load are defined under a usd class:
```
#usda 1.0
(

)

def Scope "Assets" (
kind = "assembly"
) {
def Scope "characters" (
kind = "group"
) {
def Xform "character_01" (
kind = "assembly"
) {
def Xform "body" (
kind = "component"
) {

}
def Xform "eyes" (
kind = "component"
) {

}
def Xform "hair" (
kind = "component"
) {

}
class "rig" (
) {
def Scope "anim_rig" () {
def MayaReference "main" () {
asset mayaReference = @./my_rig.ma@
string mayaNamespace = "my_rig"
}
}
}

}
}
}
```

```python
import mayaUsd.lib
from maya import cmds
from maya.api import OpenMaya

def resolve_rig_path(prim):
maya_reference = prim.GetAttribute('mayaReference')
rig_path = maya_reference.Get().resolvedPath if maya_reference else ""

return rig_path

def get_rig_prims(prim):
# hardcoded example
rig_prim = prim.GetPrimAtPath('rig/anim_rig/main')
return [rig_prim] if rig_prim.IsValid() else []

class RigPrimReader(mayaUsd.lib.PrimReader):

@classmethod
def CanImport(cls, args, prim):
return mayaUsdLib.PrimReader.ContextSupport.Supported

def Read(self, context):

prim = self._GetArgs().GetUsdPrim()
print(f"[INFO] processing: {prim}")
if context.GetPruneChildren():
print(f'[INFO] processing children: {context.GetPruneChildren()}')
return False

rig_prims = get_rig_prims(prim)
if not rig_prims:
print(f"[INFO] skipping: {prim}")
return False
rig_network = cmds.createNode('transform', name=prim.GetName())

for rig_prim in rig_prims:
print(f"[INFO] Processing rig: {rig_prim}")
rig_parent = cmds.createNode('transform', name=rig_prim.GetName())

maya_file_path = resolve_rig_path(rig_prim)
ns_attr = rig_prim.GetAttribute("mayaNamespace")
namespace = ns_attr.Get() if ns_attr and ns_attr.HasAuthoredValueOpinion() else rig_prim.GetName()

print(f"[INFO] Loading rig: {maya_file_path} (ns={namespace})")
try:
ref_node = cmds.file(
maya_file_path,
reference=True,
namespace=namespace,
ignoreVersion=True,
mergeNamespacesOnClash=False,
options="v=0",
returnNewNodes=True
)
except RuntimeError as err:
print("[WARN] Maya RuntimeError suppressed:", err)
except Exception as e:
print("[WARN] Other error suppressed:", e)
finally:
print("[INFO] Rig reference attempted; continuing pipeline.")
print("+_+_+_+_+_+_+_+_+_+_+_")
print("[INFO] ref_node:", ref_node)
all_nodes = cmds.ls(ref_node, type="transform")
rig_top_nodes = [n for n in all_nodes if not cmds.listRelatives(n, parent=True)]
print("[INFO] ref_node:", rig_top_nodes)
if rig_top_nodes:
cmds.parent(rig_parent, rig_network)
cmds.parent(rig_top_nodes[0], rig_parent)
print(f'Read {prim.GetName()} - {rig_prim.GetName()} created')

# parent under __mayaUsd__
parent = context.GetMayaNode(prim.GetPath().GetParentPath(), True)
parentDagPath = OpenMaya.MFnDagNode(parent).fullPathName()
print("[INFO] parentDagPath:", rig_network, parentDagPath)
print("[INFO] DAG PATH Exist: ", cmds.objExists(parentDagPath))
cmds.parent(rig_network, parentDagPath)
selectionList = OpenMaya.MSelectionList()
selectionList.add(rig_network)
new_obj = selectionList.getDependNode(0)
context.RegisterNewMayaNode(prim.GetPath().pathString, new_obj)
# do not read children of character_01
context.SetPruneChildren(True)
print(f'[INFO] stopping at prim {prim}: {context.GetPruneChildren()}')
return True


class RigPrimUpdater(mayaUsd.lib.PrimUpdater):
@classmethod
def sRegister(cls):
print(f'Registering {cls.__qualname__}')
mayaUsd.lib.PrimUpdater.Register(
cls, "CustomRig", "transform", RigPrimUpdater.Supports.All.value
)
return True

@classmethod
def sUnregister(cls):
print(f'Un-registering {cls.__qualname__}')
mayaUsd.lib.PrimUpdater.Unregister(
cls, "CustomRig", "transform", RigPrimUpdater.Supports.All.value
)
return True

def canEditAsMaya(self):
print('canEditAsMaya', self.__class__.__name__)
return True

def editAsMaya(self):
print('[INFO] editAsMaya', self.__class__.__name__)
return super(RigPrimUpdater, self).editAsMaya()

def register():
RigPrimUpdater.sRegister()
mayaUsd.lib.PrimReader.Register(RigPrimReader, "CustomRig")

register()

def test_edit_as_maya(stage_dag_path, prim_path):
root_prim = mayaUsd.lib.GetPrim(stage_dag_path) # DAG path only
stage = root_prim.GetStage()
root_prim.GetPrimAtPath(prim_path).SetTypeName('CustomRig')

ufepath = f'{stage_dag_path},{prim_path}'
with mayaUsd.lib.OpUndoItemList():
mayaUsd.lib.PrimUpdaterManager.editAsMaya(ufepath)

# read character_01 via RigPrimReader
test_edit_as_maya('|shot|shotShape', '/Assets/characters/character_01')
```

**Steps to reproduce**
Steps to reproduce the behavior:
1. Create > USD > Stage From File...
2. pick `shot.usda` from `shot_and_rig.zip`
3. Run the code above

**Expected behavior**
The main rig is loaded under character_01 as expected.
The Maya transforms for /Assets/characters/character_01/body, eyes and hair should not be created, but they are (see screenshot).

**Attachments**

Image

Image

[shot_and_rig.zip](https://github.com/user-attachments/files/22987699/shot_and_rig.zip)

**Specs (if applicable):**
- OS & version: macOS 15.4.1
- Compiler & version Pre-Built version of the plug-in
- Maya version Maya 2026.2
- Maya USD commit SHA 0.33.0 (0.33.0_202507022244-1cbb7f7)
- Pixar USD commit SHA 0.24.11

**Additional context**
The idea is to ensure that the geometric description of the asset is still accessible on the stage via usd APIs and edits don't have to be routed through composition arcs like variants or prim references.

Looking at the code for [materialReader](https://github.com/Autodesk/maya-usd/blob/d1fb61847a534cd3fff953ff068da372c61fc6b1/lib/usd/translators/materialReader.cpp) and [testCustomRig.py](https://github.com/Autodesk/maya-usd/blob/d1fb61847a534cd3fff953ff068da372c61fc6b1/test/lib/mayaUsd/fileio/testCustomRig.py) it looked possible in principle.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.