Last active
September 20, 2024 10:46
-
-
Save BigRoy/44250f5d9fdba79d127ce96e88bcc197 to your computer and use it in GitHub Desktop.
USD API move prim spec including repathing relationships and connections to it and its children in a single Sdf Layer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from pxr import Sdf, Usd | |
LIST_ATTRS = ['addedItems', 'appendedItems', 'deletedItems', 'explicitItems', | |
'orderedItems', 'prependedItems'] | |
def repath_properties(layer, old_path, new_path): | |
"""Re-path property relationship targets and attribute connections. | |
This will replace any relationship or connections from old path | |
to new path by replacing start of any path that matches the new path. | |
Args: | |
layer (Sdf.Layer): Layer to move prim spec path. | |
old_path (Union[Sdf.Path, str]): Source path to move from. | |
new_path (Union[Sdf.Path, str]): Destination path to move to. | |
Returns: | |
bool: Whether any re-pathing occurred for the given paths. | |
""" | |
old_path_str = str(old_path) | |
peformed_repath = False | |
def replace_in_list(spec_list): | |
"""Replace paths in SdfTargetProxy or SdfConnectionsProxy""" | |
for attr in LIST_ATTRS: | |
entries = getattr(spec_list, attr) | |
for i, entry in enumerate(entries): | |
entry_str = str(entry) | |
if entry == old_path or entry_str.startswith( | |
old_path_str + "/"): | |
# Repath | |
entries[i] = Sdf.Path( | |
str(new_path) + entry_str[len(old_path_str):]) | |
peformed_repath = True | |
def repath(path): | |
spec = layer.GetObjectAtPath(path) | |
if isinstance(spec, Sdf.RelationshipSpec): | |
replace_in_list(spec.targetPathList) | |
if isinstance(spec, Sdf.AttributeSpec): | |
replace_in_list(spec.connectionPathList) | |
# Repath any relationship pointing to this src prim path | |
layer.Traverse("/", repath) | |
return peformed_repath | |
def move_prim_spec(layer, src_prim_path, dest_prim_path): | |
"""Move a PrimSpec and repath connections. | |
Note that the parent path of the destination must | |
exist, otherwise the namespace edit to that path | |
will fail. | |
Args: | |
layer (Sdf.Layer): Layer to move prim spec path. | |
src_prim_path (Union[Sdf.Path, str]): Source path to move from. | |
dest_prim_path (Union[Sdf.Path, str]): Destination path to move to. | |
Returns: | |
bool: Whether the move was successful | |
""" | |
src_prim_path = Sdf.Path(src_prim_path) | |
dest_prim_path = Sdf.Path(dest_prim_path) | |
dest_parent = dest_prim_path.GetParentPath() | |
dest_name = dest_prim_path.name | |
layer.GetPrimAtPath(dest_prim_path) | |
with Sdf.ChangeBlock(): | |
reparent_edit = Sdf.NamespaceEdit.ReparentAndRename( | |
src_prim_path, | |
dest_parent, | |
dest_name, | |
-1 | |
) | |
edit = Sdf.BatchNamespaceEdit() | |
edit.Add(reparent_edit) | |
if not layer.Apply(edit) and layer.GetPrimAtPath(src_prim_path): | |
print("Failed prim spec move") | |
return False | |
repath_properties(layer, src_prim_path, dest_prim_path) | |
return True | |
# Example usage in Maya to move /mtl to /asset/mtl for all | |
# maya usd proxy shapes in the scene in their current edit target layer | |
from maya import cmds | |
import mayaUsd | |
proxies = cmds.ls(type="mayaUsdProxyShape", long=True) | |
for proxy in proxies: | |
stage = mayaUsd.ufe.getStage("|world" + proxy) | |
layers = stage.GetLayerStack() | |
targets = cmds.mayaUsdEditTarget(proxy, query=True, editTarget=True) | |
target = targets[0] # edit target layer identifier | |
layer = next( | |
layer for layer in stage.GetLayerStack() if layer.identifier == target) | |
# Reparent and repath connections and relationships | |
move_prim_spec(layer, "/mtl", "/asset/mtl") | |
# Force viewport reset because sometimes viewport doesn't recognize | |
# the shader moved | |
cmds.ogs(reset=True) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
As posted as a workaround for the issue in Maya USD unable to move shaders into asset structure.