Search code examples
pythonmaya

why is my scripJob in Maya not detecting a light name change in the outliner?


I have a tool that populates a GUI with the lights in a Maya scene, and if the user renames a light in the outliner, I would like the GUI to reflect the new light name. I tried to set up a scriptJob to detect the rename event, but so far it is not working. What am I doing wrong?

import maya.cmds as cmds
import os
import maya.OpenMayaUI as mui
from PySide2 import QtWidgets,QtCore,QtGui
import shiboken2

class widget():
    def __init__(self):
        self.lights = cmds.ls(type = "VRayLightRectShape")

    def clearLayout(self):
        layout = self.vertical_layout
        if layout is not None:
            while layout.count():
                item = layout.takeAt(0)
                widget = item.widget()
                if widget is not None:
                    widget.setParent(None)
                else:
                    self.clearLayout(item.layout())        

    def light_button_event(self, text):
        print("this is the pressed button's label", text)

    def populate_lights(self):
        self.clearLayout()
        for light in self.lights:
            light_btn = QtWidgets.QPushButton(light)
            light_btn.clicked.connect(partial(self.light_button_event, light))
            self.vertical_layout.addWidget(light_btn)

    def light_window(self):
        windowName = "lights_palette"
        if cmds.window(windowName,exists = True):
            cmds.deleteUI(windowName, wnd = True)
        pointer = mui.MQtUtil.mainWindow()
        parent = shiboken2.wrapInstance(long(pointer),QtWidgets.QWidget)
        self.window = QtWidgets.QMainWindow(parent)
        self.window.setObjectName(windowName)
        self.window.setWindowTitle(windowName)
        self.mainWidget = QtWidgets.QWidget()
        self.window.setCentralWidget(self.mainWidget)
        self.vertical_layout = QtWidgets.QVBoxLayout(self.mainWidget)
        self.populate_lights()        
        self.window.setAttribute(QtCore.Qt.WA_DeleteOnClose)
        for light in self.lights:
            job = self.myScriptJobID = cmds.scriptJob(p = windowName, nodeNameChanged=[light, self.populate_lights])
        self.window.show()


w = widget()
w.light_window()

Solution

  • You are collecting the lights in the constructor. The result is a list of strings which have no connection to the original objects. If I execute the tool here, I can see that the scriptjob called the "populate_lights()" method, but it only reads the existing self.lights list which did not change. So you could simply reread the light list in the populate_lights() method.

    If you want to avoid this, you could try PyMel which returns objects instead of strings. You can fill a list of ligths and always get the name of the objects which reflect the current state of the node.