Wednesday, 29 June 2016

Yup, its time for more Maya python tips...

Well, I couldn't really keep away from posting Maya python material forever, so here's another installment of various tips, techniques and well, python-goodness!  This time I'm throwing up a handful of additional snippets of code for your tool productions and UI's...



Does ctrlVariable = cmds.control name?

One of my students the other week did point out to me that using a name at the start of any of the control statements means that I can then refer to it by its name without needing to store its path in a variable (which I had been doing previously).  Now I think about it, it was fairly obvious when you consider that you can name your window using a windowID of sorts. Doh!

# Create a textfield control with the name "txtField"
cmds.textField('txtField', tx="I am txtField")

With a name, we can easily reference the contents.  In my previous blog posts, I had used variables everywhere (which isn't necessarily a bad thing).  In this example, I'm using the named formLayout and textField control to position the textField.

cmds.window('ctrlNameUI')
cmds.formLayout('fUI')
cmds.textField('txtField', tx="I am txtField", w=100)

# Edit the form and place the control, using their names
cmds.formLayout('fUI', e=True, af=[('txtField', 'top', 25)])

cmds.showWindow()

Of course, that doesn't necessarily cancel out the need for variables to refer to a control, but its worth noting as it can make all of your scripting a lot easier (and a lot shorter).

Sittin on the dock of the bay...

"I'll be sittin' when the coding's done..."  Ahem!  Sorry, went off on a slight musical tangent there.

Docking windows - I've seen a few more complex ways to set this up over the last couple of years in the form of code snippets, but surprisingly there is actually a handy layout that we can use to make any of our UI windows dock into the Maya UI.  Why this is cool - well, imagine making a UI that can just sit on the right of the Maya interface along with the Attribute editor...  It becomes accessible quickly, and you don't need someone to launch your script to bring a window up each time to use it.

The nice thing is that it can be done in one fell swoop by simply replacing the cmds.showWindow() with cmds.dockControl()!  Here's a quick example below...

# Test to see if this UI is in existance...
if cmds.window('dockT', exists = True):
    print "User just has to close the dock control"
else:
    cmds.window('dockT')
    cmds.columnLayout()
    cmds.button(label = "A button")
    cmds.button(label = "B button")

# Dock and display the control.  Note the retain flag below.
    cmds.dockControl(l="DockTab", a='right', con='dockT', ret=False)

There is a flag called ret (retain).  Its purpose is to specify whether the window UI is retained in memory when the dock is closed.  By setting it to false, it is deleted when the dock control window is deleted (ie. basically does a deleteUI for us).  Nice and clean.

If we use the DeleteUI statement as we usually would with a normal window, any dock control is not removed, and we can start to stock pile empty tabs pretty quickly.  This can leave a lot of empty tabs...  This method instead requires the user to delete the dock window first, and therefore just foregoes any such issue.

Of course, there are methods to remove these dock's I'm sure.  But for now, this approach works just great!

Drag n drop

Dragging controls is done with a middle-mouse click and drag.  We can take advantage of this functionality to add some pizazz to our UI's, offering such things as a 'drag to trash can' or 'drag new controls onto a form'.

You may have noticed that most controls in Maya have two callback flags - one for when a control is dragged (dgc - or dragCallback), the other when it is dropped (dpc - or dropCallback).  When these are used, all information regarding pixel locations, names of controls that were both dragged and dropped on is returned.  Extremely useful!

Here is a quick example.  Drag a simple red button onto a blank area at the top-left of the window.  The drop callback returns the pixel location within the blank control.  With this blank area up, slap bang in the top-left, we are essentially getting back the pixel location within the window itself...  We can use this to place other controls (say as a way to create an interactive rig-picker creation tool (my initial mini-project this came in handy for))

import maya.cmds as cmds

# Define callback when control is being dragged
def dragging(*args):
    print "dragging ",args[0]
 
# Define callback when something is dropped on control
def dropped(*args):
    print "dropped onto ",args[1]
    print "drop location x=",args[3]," , y=",args[4]

# Create our UI
newUI = "dragAndDrop"
if cmds.window(newUI, exists = True):
    cmds.deleteUI(newUI)

cmds.window(newUI)

# A formLayout lets us place controls at pixel locations
cmds.formLayout('ddUI')

# Two controls here - a blank separator with a white background for dropping onto
cmds.separator('bSpace', dpc=dropped, st='none', w=300, h=300, bgc=(1,1,1))
# A red button we can middle-click and drag
cmds.button('redB',l='',dgc=dragging,w=32,h=32,bgc=(1,0,0))

# Position controls - blank on top-left, button on bottom-right
cmds.formLayout('ddUI', e=True, af=[('bSpace', 'top', 0),('bSpace','left',0)])
cmds.formLayout('ddUI', e=True, af=[('redB', 'bottom', 25),('redB','right',25)])

cmds.showWindow()

# Final edit to force window size...
cmds.window(newUI, e=True, w=400, h=400)

Obviously just the thought of being able to drag and drop in a UI can open up a vast amount of ideas how best to take advantage of it!  I'm sure you can already think of a dozen, right?

So there you have it...

Another small handful of additional tips that hopefully you can make use of in your Maya script development.  I've got a pile of additional things coming in the pipeline later this year, so will definitely be back soon to share more.

Enjoy!

1 comment :