Feb 112013
 

Many operations in Maya will run faster if Maya doesn’t have to refresh the viewport while running them. For example, if you switch the viewport to only show the Graph Editor before baking animation, or caching particles or Alembic geometry, the operation will happen much faster than if Maya had to actually display the geometry for each frame that it’s being baked. There is probably a way via the API to tell Maya’s viewport not to refresh, but since I don’t know shit about the API, here’s a workaround using a few of Maya’s less-documented MEL commands and some Python.

I wrote this method assuming that artists would want to cache out information frequently without it disrupting their workflow. That means that I needed to first store the user’s current panel layout, then switch it to something that doesn’t require a refresh on every frame (like the Graph Editor), and then restore the previously restored layout.

I prefer coding in Python, but some of the procedures I’m running are MEL functions that are found in scripts/startup and so they’re not documented and they don’t have Python equivalents. A hybrid approach is the best way to handle it, since MEL is terrible.

Click for some Python code…

Anyways, some code. First, creating a layout:

layout = cmds.panelConfiguration(l='tempLayout', sc=0)

This creates a saved layout configuration with the label “tempLayout.” You could access this layout by going to Panels > Saved Layouts and then selecting “tempLayout,” but doing so will return an error since nothing has been written to this layout configuration. To save the current window settings, there’s a MEL procedure found in scripts/startup/updatePanelLayoutFromCurrent.mel called “updatePanelLayoutFromCurrent.” (I discovered this by storing layouts with “Echo All Commands” in the Script Editor, and then running “whatIs updatePanelLayoutFromCurrent” in the MEL tab.) To run this from Python I just used mel.eval():

 mel.eval('updatePanelLayoutFromCurrent "tempLayout"') 

That stores the layout information. Next, I want to switch to a layout that doesn’t have any viewports that need to refresh. First, I’m going to simplify the layout by setting it to Single Perspective View. (There isn’t any default saved view that doesn’t involve a perspective window, unfortunately, so I’d have to create my own if I wanted to use it). There’s another MEL procedure for it called “setNamedPanelLayout”:

 mel.eval('setNamedPanelLayout "Single Perspective View"')

Now I can use a couple Python commands to get the single panel from the new layout, and assign the Graph Editor to it:

perspPane=cmds.getPanel(vis=1)
cmds.scriptedPanel('graphEditor1',e=1,rp=perspPane[0])

So the first half is done. Now I can run my bake operation, and when I’m done, I just have to restore the temporary layout I saved, and then delete it.

First, we use the same MEL procedure we used before to restore a saved layout:

mel.eval('setNamedPanelLayout "tempLayout"')

Next I just have to delete the old one. The getPanel() command has a flag called ConfigWithLabel that allows you to get a panel configuration by label. Then we can run deleteUI() on that config, making sure to specify that we’re deleting a panel configuration.

killMe = cmds.getPanel(cwl='tempLayout')
cmds.deleteUI(killMe,pc=1)

I know this is all easy code, but it seriously took me all afternoon to dig through MEL scripts and try to figure out how this whole panel configuration system works. Here’s the final code, in the form of two methods:

import maya.cmds as cmds
import maya.mel as mel

def makeHiddenLayout(name):
    # store a temporary panel configuration.
    layout = cmds.panelConfiguration(l=name, sc=0)
    evalStr = 'updatePanelLayoutFromCurrent "'+name+'"'
    mel.eval(evalStr)
    # switch to fast "hidden" layout
    evalStr = 'setNamedPanelLayout "Single Perspective View"'
    mel.eval(evalStr)
    perspPane = cmds.getPanel(vis=1)
    cmds.scriptedPanel('graphEditor1',e=1,rp=perspPane[0])
    return name
    
def restoreLayout(name):
    # restore the layout returned from makeHiddenLayout.
    evalStr = 'setNamedPanelLayout "'+name+'"'
    mel.eval(evalStr)
    # now delete the old layout.
    killMe = cmds.getPanel(cwl=name)
    cmds.deleteUI(killMe,pc=1)

If I were using this script in production, I’d keep it inside a try... finally clause, or else an error within the baking operation (or whatever it is) would prevent my layout from restoring itself, and could potentially leave temporary layouts saved to disk. It’s a pretty simple thing to do:

makeHiddenLayout('tempLayout')
try:
    runSomeBakingMethod()
    maybeSomeOtherMethodHere()
finally:
    restoreLayout('tempLayout')

The finally clause will execute regardless of errors in the try clause, so you can be sure that the layout will properly restore itself no matter what (excluding an application crash, I guess…)

Sorry, the comment form is closed at this time.