-
Notifications
You must be signed in to change notification settings - Fork 202
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unable to move mtl
materials into group above a sublayer or reference
#3466
Comments
Thank you for this feedback. The team has been discussing the topic of restrictions and possibly relaxing some of those restrictions. The intent that the system has now is to not allow the user to create cruft (orphaned opinions). We are seeing the need to be a little less restrictive at times on this front and will continue to look into this topic. As for the question of referencing the asset with the looks opinions: you are correct to encapsulate the mtl scope within the default prim. |
Is there any short-term solution, like an env var, to lift the restrictions currently?
Would it make sense that maybe a I also tried env var (Of course that does leave to wonder; what should the parent prims be defined as if not existing? Xform? Scope? And is that Def or Over?) Or would you maybe have any example USD API logic that for now could move the |
It seems that this works to e.g. reparent from maya import cmds
import mayaUsd
from pxr import Sdf
def reparent_prim_spec(layer, src_prim_path, dest_parent):
src_prim_path = Sdf.Path(src_prim_path)
dest_prim_path = Sdf.Path(dest_parent)
prim = layer.GetPrimAtPath(src_prim_path)
if not prim:
return
with Sdf.ChangeBlock():
edit = Sdf.BatchNamespaceEdit()
edit.Add(Sdf.NamespaceEdit.Reparent(src_prim_path, dest_parent, -1))
layer.Apply(edit)
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_prim_spec(layer, "/mtl", "/asset") But it does not update the material bindings :( Is there a better way to do this and bring along e.g. the shader assignments (material bindings on the other prims) I suppose this code is somewhat equivalent of what I'm trying to do so might be a good reference. And apparently edits like these are not simple/trivial currently but there is a namespace editing proposal underway, see OpenUSD-proposals: namespace editing. Nonetheless - if there's any code that could help with my case it'd be greatly appreciated! |
This appears to work: from maya import cmds
import mayaUsd
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
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) |
Describe the bug
I'd like to set up an asset building workflow where in a layer I can apply look overrides and make sure the materials end up in my asset hierarchy
/{asset}/mtl
however when creating materials they default to/mtl
However, I can't seem to move those into the correct place in the hierarchy due to:
Loading this
cube.usda
:As a sublayer gives me:
Assigning a material then gives me:
The material I created and assigned in my look layer that is above the loaded model:
I cannot seem to reparent the
/mtl
to/asset/mtl
to move into the correct place.However, I can create materials just fine directly in
/asset
or/asset/mtl
if I try so manually.Additionally - I can also reparent the
/mtl/UsdPreviewSurface1
into another path that is not from a sublayer or reference but as soon as I try to put it on there Maya is not happy and gives me:Which seems weird since that file doesn't have opinions there - of course the material itself has
over
bindings toasset/geo/cube
but still removing the assignment and then moving it also doesn't work.However, if I create the
asset/mtl/UsdPreviewSurface1
and then after add the model layer I can assign it fine and it's at the correct location so it is totally feasible to from that layer in USD data define opinions there. Unfortunately there's just something in Maya USD disallowing making those edits.Steps to reproduce
Steps to reproduce the behavior:
/asset/mtl
) - I can't make this workExpected behavior
It should be more trivial to allow reparenting or moving it around into the location I want it to be.
Also, bonus points if I can force by default the materials to go there for this USD Stage so I don't even need to reparent and that artists need less 'fixing' this.
Or better question; what is a good approach to load an
asset.usd
ormodel.usd
and start contributing my look opinions into the default prim (e.g./root
or/{asset_name}
depending on the USD asset structure) so the asset can be referenced elsewhere? (which requires referencing the (default) prim into another prim; and thus/mtl
should be encapsulated within it, right?)Attachments
If applicable, add screenshots, sample files, etc to help explain your problem.
Specs (if applicable):
Additional context
I also tried muting the
cube.usda
layer and then moving the materials, but unfortunately that's not allowed either:The text was updated successfully, but these errors were encountered: