Question

So this first part shouldn't matter too much to the code, but just fyi for anyone who knows it, I'm writing this inside of The Foundry's 'Nuke'. Creating a pythonPanel GUI.

So when I'm creating my panel, it starts:

class notePanel(nukescripts.PythonPanel):
    def __init__(self):
        nukescripts.PythonPanel.__init__(self, 'Note Panel', 'com.ohufx.notePanel')

With the init(self): part.

When I'm adding knobs, or UI controls, to this panel, I use sometihng like:

    self.proj = nuke.String_Knob('proj', 'Project:', os.environ['SHOW'])
    self.addKnob(self.proj)
    self.proj.setFlag(nuke.STARTLINE)

Which works fine. Also, when I'm creating scripts that run in the panel I do something like:

def launchSGPage(self):
    pr = self.proj.value()
    sh = self.shot.value()
    url = shotgun.getURL(pr,sh)
    webbrowser.get('/usr/bin/google-chrome %s').open(url)

Also using self, which works great.

My problem is that in my first step, when I'm adding knobs (Like the string knob I created) and I want to make one of my functions (Like the launchSGPage above) the script that runs on a specific button, if I do this:

    self.sgpage = nuke.PyScript_Knob('sgpage', 'Open SG page', 'self.launchSGPage()')

the self.launchSGPage() gives me an error. For some reason self isnt working in this context, and so far the only way ive gotten this to work is by naming me panel when I add it to the ui (in this case I named it nPanel) and using its name to call my function, like this below:

def addnotePanel():
    global nPanel
    nPanel = notePanel()
    return nPanel.addToPane()

and so my script button would look like:

    self.sgpage = nuke.PyScript_Knob('sgpage', 'Open SG page', 'nPanel.launchSGPage()')

This works for all intents and purposes but just seems... dirty and unclean to me. I'm not sure what, but something tells me theres something wrong with this. Can anyone clear up for me a BETTER way to link to my functions in this class rather than by a global variable name?

Was it helpful?

Solution

When the button is clicked your panel's knobChanged method will be called. You can check if your button was clicked, and call the appropriate method like any other:

class notePanel(nukescripts.PythonPanel):
    def __init__(self):
        nukescripts.PythonPanel.__init__(self, 'Note Panel', 'com.ohufx.notePanel')

        self.sgpage = nuke.PyScript_Knob('sgpage', 'Open SG page', '')

    def knobChanged(self, knob):
        if knob is self.sgpage:
            self.launchSGPage()

    def launchSGPage(self):
        pr = self.proj.value()
        sh = self.shot.value()
        url = shotgun.getURL(pr,sh)
        webbrowser.get('/usr/bin/google-chrome %s').open(url)

OTHER TIPS

Using self gives you an error, because you provide this script as a string. It is evaluated in a different lexical environment, in which even if there is something bound to self, it is not "your" self, that you want to use.

I understand why using global variables like that makes you feel icky. I would have the same. You essentially have two options:

  • Try to pass a lambda as a 3rd argument to PyScript_Knob constructor, like so:

    self.sgpage = nuke.PyScript_Knob('sgpage', 'Open SG page', lambda: self.launchSGPage())
    
  • If that doesn't work (I have not worked with nuke, so I don't know if they support this), looking at documentation available here: http://docs.thefoundry.co.uk/nuke/63/pythonreference/nuke.PyScript_Knob-class.html, I would just write my own subclass of Script_Knob that would allow taking a lambda like that. I guess you'd need to override only the constructor, and the execute() method to make it work. Bonus points for overriding command() and setCommand().

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top