Last active
February 15, 2024 04:38
-
-
Save BigRoy/1895108757a9122f9cb90abf08c70015 to your computer and use it in GitHub Desktop.
Quick and dirty example functions/UI to light link with USD in Python for Maya
This file contains hidden or 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
"""Minimal example of how to 'light link' with USD in maya via a quick and dirty UI | |
Basically all the buttons behave in the way that anything that is valid for UsdLux.LightAPI | |
is considered to be a Light, anything else in your current selection is a target. | |
USD manages both an *Includes* relationship and *Excludes* relationship - the UI | |
basically exposes both to 'add', 'remove' or 'clear' these relationships for a given | |
light. When adding or removing all selected objects in your selection that are not | |
a light are processed as the target. | |
This UI currently always uses a light link collection named `lightLink`. | |
""" | |
import logging | |
from functools import partial | |
from PySide2 import QtWidgets | |
import shiboken2 | |
import maya.OpenMayaUI as apiUI | |
from maya import cmds | |
import mayaUsd.ufe | |
from pxr import Usd, UsdLux | |
log = logging.getLogger(__name__) | |
def get_maya_main_window(): | |
"""Get the Maya main window. | |
Returns: | |
PySide2.QtWidgets.QWidget: Maya main window. | |
""" | |
ptr = apiUI.MQtUtil.mainWindow() | |
if ptr is not None: | |
return shiboken2.wrapInstance(int(ptr), QtWidgets.QWidget) | |
def get_selected_prims(): | |
"""Return selected Usd.Prim list from Maya's UFE selection | |
Returns: | |
list[Usd.Prim]: Selected prims | |
""" | |
paths = cmds.ls(selection=True, ufeObjects=True, long=True, absoluteName=True) | |
prims = [] | |
for path in paths: | |
prim = mayaUsd.ufe.ufePathToPrim(path) | |
if prim: | |
prims.append(prim) | |
return prims | |
def get_selected_lights_and_targets(): | |
"""Return selected lights and targets in selection. | |
Returns: | |
tuple[list[Usd.Prim], list[Usd.Prim]]: | |
Two-tuple containing a list of list and a list of targets | |
""" | |
lights = [] | |
targets = [] | |
for prim in get_selected_prims(): | |
is_light = bool(UsdLux.LightAPI(prim)) | |
if is_light: | |
lights.append(prim) | |
else: | |
targets.append(prim) | |
return lights, targets | |
def set_tip(widget, tip): | |
"""Set tooltip and status tip for a QWidget.""" | |
widget.setToolTip(tip) | |
widget.setStatusTip(tip) | |
class UsdLightLinkUI(QtWidgets.QDialog): | |
Add = 0 | |
Remove = 1 | |
Clear = 2 | |
def __init__(self, parent=None): | |
super(UsdLightLinkUI, self).__init__(parent=parent) | |
self.setWindowTitle("USD Light Link") | |
layout = QtWidgets.QVBoxLayout(self) | |
add_include = QtWidgets.QPushButton("Add selected") | |
set_tip(add_include, "Add selected objects to the includes list of selected lights") | |
remove_include = QtWidgets.QPushButton("Remove selected") | |
set_tip(remove_include, "Remove selected objects from the includes list of selected lights") | |
clear_includes = QtWidgets.QPushButton("Clear all") | |
set_tip(clear_includes, "Clear the includes list for all selected lights") | |
add_exclude = QtWidgets.QPushButton("Add selected") | |
set_tip(add_exclude, "Add selected objects to the excludes list of selected lights") | |
remove_exclude = QtWidgets.QPushButton("Remove selected") | |
set_tip(remove_exclude, "Remove selected objects from the excludes list of selected lights") | |
clear_excludes = QtWidgets.QPushButton("Clear all") | |
set_tip(clear_excludes, "Clear the excludes list for all selected lights") | |
layout.addWidget(QtWidgets.QLabel("<b>Include</b>")) | |
layout.addWidget(add_include) | |
layout.addWidget(remove_include) | |
layout.addWidget(clear_includes) | |
layout.addWidget(QtWidgets.QLabel("<b>Exclude</b>")) | |
layout.addWidget(add_exclude) | |
layout.addWidget(remove_exclude) | |
layout.addWidget(clear_excludes) | |
add_include.clicked.connect(partial(self.apply, action=self.Add, include=True)) | |
remove_include.clicked.connect(partial(self.apply, action=self.Remove, include=True)) | |
clear_includes.clicked.connect(partial(self.apply, action=self.Clear, include=True)) | |
add_exclude.clicked.connect(partial(self.apply, action=self.Add, exclude=True)) | |
remove_exclude.clicked.connect(partial(self.apply, action=self.Remove, exclude=True)) | |
clear_excludes.clicked.connect(partial(self.apply, action=self.Clear, exclude=True)) | |
def apply(self, action, include=False, exclude=False): | |
lights, targets = get_selected_lights_and_targets() | |
def _apply(relationship, targets, action): | |
if action == self.Add: | |
for target in targets: | |
relationship.AddTarget(target.GetPath()) | |
elif action == self.Remove: | |
for target in targets: | |
relationship.RemoveTarget(target.GetPath()) | |
elif action == self.Clear: | |
relationship.ClearTargets(True) | |
for light in lights: | |
print("Processing light:", light) | |
collection = Usd.CollectionAPI(light, "lightLink") | |
if include: | |
includes = collection.GetIncludesRel() | |
_apply(includes, targets, action) | |
if exclude: | |
excludes = collection.GetExcludesRel() | |
_apply(excludes, targets, action) | |
maya_window = get_maya_main_window() | |
dialog = UsdLightLinkUI(parent=maya_window) | |
dialog.resize(200, 200) | |
dialog.show() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Written as example for Maya USD Light Link discussion here.