Wednesday, March 30, 2016

Maya Picture in Picture Tool (PiP) Development Part 1

It's been a while since I last posted but I wanted to write about a tool I had been planning for a while and finally found some time to start developing.  For now, I would consider this tool in an alpha state and I do plan on having it available for download in the near future once it's fully vetted.


Alpha recording of PiP (Maya 2016)
This is PiP, it is a tool within Maya to create view port within a view port (picture in picture) setup. The original idea came from watching a lot of animators at work creating tear off model panels with a camera setup in the game camera's angle to see how their animation was reading visually.  Most of our animators have at least 2 monitors, their main monitor is typically where they animate on their primary view port, but they also tear off a copy of the model panel with the game camera ( along with the graph editor and other tools) thrown onto the secondary monitor.  This may not get to some people - but I have taken it as a personal goal to try to keep folks centered and focused in the same monitor space as much as possible - which led to the idea "can you nest a model panel into the existing model panel?"  Which leads to other crazy ideas such as "can graph splines be represented in the view port?" and "can we view silhouette and textures and animate at the same time?"

PiP allows the artist to view multiple cameras at once within the context of their main work and thought process - rather than diverting their gaze to a second monitor to see how things look, and later returning back to work.  You can make as many PiP window instances as you desire, resize them to your liking, and even play back animations in all view ports at once to really get a good idea of how things are working together.

Throughout the initial brain storming of this I started focusing on the other practices for multiple model panels and cameras such as a face camera or a face rig osipa-style slider control camera - seeing the multiple disciplinary uses for PiP really made me think twice about how useful it could be if I ever found time to develop it!

Well I found some time, it really isn't a large tool - I have parented ui objects to the view port in the past, it was more of figuring out the intricacies of doing it with model editor widgets.  I wanted the interface to be super simple for anyone to use, I also wanted to make sure older versions of Maya could use the tool.  I am using maya.cmds instead of pymel.core for a lot of the work just to help with speed although it's not really a very "procedurally heavy" tool, the speed differences are something I am lot more aware of in the past few years of working with pymel.  Any version of Maya that is older than 2014 will utilize PyQt for it's UI setup, and newer versions will utilize PySide.  This is just some of the code I used to configure which UI library to use based on the maya version.



# Maya libraries
import maya.OpenMaya as om
import maya.OpenMayaUI as omUI
import maya.cmds as cmds

# Find module file path used for icon relative path finding
module_file_path = __file__.replace( "\\", "/" ).rpartition( "/" )[0]
mayaMainWindowPtr = omUI.MQtUtil.mainWindow()
MAYA_VERSION = cmds.about( version=True ).replace( " x64", "" )
MAYA_UI_LIBRARY = "PyQt"

# PyQt
if int( MAYA_VERSION ) < 2014:
    from PyQt4 import QtGui
    from PyQt4 import QtCore
    import sip
    wrapInstance = sip.wrapinstance
    
# PySide
else:
    from PySide import QtCore
    from PySide import QtGui
    from shiboken import wrapInstance
    MAYA_UI_LIBRARY = "PySide"
    QString = str
    
mayaMainWindow = wrapInstance( long( mayaMainWindowPtr ), QtGui.QWidget )


And here is snippet of code used to make a new model editor nested to the main model editor.  Nothing super crazy, the main idea here is using maya's ui api to get the main view port - wrap it to a QWidget.  Then using Maya's cmds engine, create a new modelEditor, wrap it also to a QWidget - then parent them together.

This process was a little different for the older versions of Maya that used PyQt - the Maya view port ui is constructed a little differently which forced me to make a window with a layout containing the new modelEditor then parent the window into the main view port QWidget. 

        # cache the main viewport widget
        self.main_m3dView = omUI.M3dView()
        omUI.M3dView.getM3dViewFromModelPanel( self.defaultModelPanel, self.main_m3dView )
        viewWidget = wrapInstance( long( self.main_m3dView.widget() ), QtGui.QWidget )
        
        # Create modelEditor
        editor = cmds.modelEditor( self.nameInstance + "__ME" )
        cmds.modelEditor( editor, 
                          edit=True, 
                          camera=self.defaultCameraStart,
                          interactive=False,
                          displayAppearance='smoothShaded',
                          displayTextures=True,
                          headsUpDisplay=False,
                          shadows=True )

        # parent the modelEditor to the viewport
        ptr_me = omUI.MQtUtil.findControl( editor )
        wrap_me = wrapInstance( long( ptr_me ), QtGui.QWidget )
        wrap_me.setParent( viewWidget )
        self.window = wrap_me
        self.window.move( self.startingPos[0], self.startingPos[1] )
        self.window.setFixedSize( QtCore.QSize( self.windowSize[0], self.windowSize[1] ) )


Well, that's mostly all I wanted to cover for now.  It's been fun trying to think of cool ways to keep the users focused in the view port rather than spreading their gaze over more desktop space.  If someone else was looking for something similar hopefully this post has helped.  My part 2 will hopefully include a download link!