-
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
Select objects bound to material #3328
Comments
This is a great request and something that I think would be useful, I will notify that team and bring it to their attention. |
wonderful! Thank you! |
Here's a quick Python code snippet: Maya USD Ufe Selection convert selection to bound materials (gist)from maya import cmds
import mayaUsd.ufe
from pxr import Usd, UsdShade
def pairwise(iterable):
it = iter(iterable)
return zip(it, it)
def iter_ufe_usd_selection():
for path in cmds.ls(selection=True,
ufeObjects=True,
long=True,
absoluteName=True):
if "," not in path:
continue
node, ufe_path = path.split(",", 1)
if cmds.nodeType(node) != "mayaUsdProxyShape":
continue
yield path
def get_ufe_path(proxy, prim):
prim_path = str(prim.GetPath())
return "{},{}".format(proxy, prim_path)
def convert_ufe_paths_to_bound_materials(
ufe_paths=None,
material_purpose=UsdShade.Tokens.allPurpose,
include_subsets=False
):
"""Convert selection or ufe node paths to bound materials
Arguments:
ufe_paths (Optional[list]): UFE paths to operate on.
If not provided current selection will be used.
material_purpose (UsdShade.Token): Material purpose
to return bounds for. Defaults to all purposes.
include_subsets (bool): Whether to include bound
materials from material bind subsets.
Returns:
list: UsdShadeMaterial UFE paths.
"""
if ufe_paths is None:
ufe_paths = list(iter_ufe_usd_selection())
targets = []
for path in ufe_paths:
proxy, prim_path = path.split(",", 1)
prim = mayaUsd.ufe.ufePathToPrim(path)
if not prim:
continue
search_from = [prim]
if include_subsets:
subsets = UsdShade.MaterialBindingAPI(prim).GetMaterialBindSubsets()
for subset in subsets:
search_from.append(subset.GetPrim())
bounds = UsdShade.MaterialBindingAPI.ComputeBoundMaterials(search_from, material_purpose)
for (material, relationship) in zip(*bounds):
material_prim = material.GetPrim()
if material_prim.IsValid():
material_prim_ufe_path = get_ufe_path(proxy, material_prim)
targets.append(material_prim_ufe_path)
return targets
targets = convert_ufe_paths_to_bound_materials(include_subsets=True)
if targets:
cmds.select(targets, replace=True, noExpand=True) _The above example does traverse from the prim downstream to its It would be more optimal to call The snippet van also here: Convert Maya USD Ufe Geometry selection to bound materials with Python How to use?
|
Just want to cross reference a discussion - this is somewhat related to the Material Relationships & Inheritance UI discussion so do definitely bring your opinions there as well. |
I noticed just now that you actually asked for the reverse. Material to bound objects Maya USD Ufe Material Selection convert to bound objects (gist)from maya import cmds
import mayaUsd.ufe
from pxr import Usd, UsdShade
from collections import defaultdict
def pairwise(iterable):
it = iter(iterable)
return zip(it, it)
def iter_ufe_usd_selection():
for path in cmds.ls(selection=True,
ufeObjects=True,
long=True,
absoluteName=True):
if "," not in path:
continue
node, ufe_path = path.split(",", 1)
if cmds.nodeType(node) != "mayaUsdProxyShape":
continue
yield path
def get_ufe_path(proxy, prim):
prim_path = str(prim.GetPath())
return "{},{}".format(proxy, prim_path)
def convert_ufe_paths_to_bound_geo(
ufe_paths=None,
material_purpose=UsdShade.Tokens.allPurpose
):
"""Convert USD material selection or ufe material node paths to bound objects.
Arguments:
ufe_paths (Optional[list]): UFE material paths to operate on.
If not provided current selection will be used.
material_purpose (UsdShade.Token): Material purpose
to return bounds for. Defaults to all purposes.
Returns:
list: UsdPrim UFE paths.
"""
if ufe_paths is None:
ufe_paths = list(iter_ufe_usd_selection())
targets = []
prims_per_proxy = defaultdict(set)
for path in ufe_paths:
prim = mayaUsd.ufe.ufePathToPrim(path)
if not prim:
continue
proxy, _prim_path = path.split(",", 1)
prims_per_proxy[proxy].add(prim)
bindings = defaultdict(set)
for proxy, prims in prims_per_proxy.items():
stage = next(iter(prims)).GetStage()
stage_prims = list(stage.Traverse())
bounds = UsdShade.MaterialBindingAPI.ComputeBoundMaterials(stage_prims, material_purpose)
for stage_prim, material, relationship in zip(stage_prims, bounds[0], bounds[1]):
material_prim = material.GetPrim()
if not material_prim.IsValid():
continue
bindings[material_prim].add(stage_prim)
for prim in prims:
for geo_prim in bindings.get(prim, []):
ufe_path = get_ufe_path(proxy, geo_prim)
targets.append(ufe_path)
return targets
targets = convert_ufe_paths_to_bound_geo()
if targets:
cmds.select(targets, replace=True, noExpand=True) |
@BigRoy thanks so much for sharing this. The second one works great. With the first one, I'm getting an error
|
Thanks. Updated the first snippet as well. |
Issue synced internally to EMSUSD-814 |
Is your feature request related to a problem? Please describe.
Currently, it appears there is no means to select objects bound to a material in Maya USD.
Describe the solution you'd like
Currently, you can see the material assigned to a mesh by right-clicking on it and choosing "show in LookdevX" which parallels "graph materials on viewport selection" in the Node Editor.
It would be nice to be able to do the inverse of this: select objects assigned to a material.
I would imagine this to entail right-clicking a material (i.e. its Shading Group) in either the Outliner or LookdevX and choosing "select objects with material" from the context menu, as you can in the Node Editor with Maya materials.
Describe alternatives you've considered
None that I know of
Additional context
FWIW Omniverse has a similar option called "select bound objects"
The text was updated successfully, but these errors were encountered: