有时候,我们将一些经常用到的重复性高的命令设置成快捷键以提高我们的效率,但我更喜欢用MarkingMenu,这样只需要甩鼠标就可以了,但是Maya默认的MarkingMenu只能通过UI来设置,如何通过脚本来实现,自己研究了一番,终于实现了,下面就具体说明下,
import maya.cmds as cmds
import pymel.core as pm
MEDIOCRE_MENU_NAME = "ANIMATION_MARKING_MENU"
SHOTGUN_MENU_NAME = "SHOTGUN_MARKING_MENU"
class MarkingMenu():
def __init__(self):
self._remove_old()
self._build()
def _build(self):
menu = cmds.popupMenu(MEDIOCRE_MENU_NAME, mm=1, b=1, aob=1, ctl=1, alt=0, sh=0, p="viewPanes", pmo=1, pmc=self._build_mediocre_markingMenu)
menu = cmds.popupMenu(SHOTGUN_MENU_NAME, mm=1, b=1, aob=1, ctl=0, alt=0, sh=1, p="viewPanes", pmo=1, pmc=self._build_shotgun_markingMenu)
def _remove_old(self):
if cmds.popupMenu(MEDIOCRE_MENU_NAME, ex=1):
cmds.deleteUI(MEDIOCRE_MENU_NAME)
if cmds.popupMenu(SHOTGUN_MENU_NAME, ex=1):
cmds.deleteUI(SHOTGUN_MENU_NAME)
def _build_mediocre_markingMenu(self, menu, parent):
'''This is where all the elements of the marking menu our built.'''
'''The radial positions are defined by the directions on a map - East, West, NorthEast, etc, just like the following map'''
'''
NW N NE
\ | /
\ | /
\ | /
__ W___ __\|/___ __ __E __
/|\
/ | \
/ | \
/ | \
SW S SE
'''
# Radial positioned
cmds.menuItem(p=menu, bld=1, l="Graph Editor", rp="W", c=self._trigger_graphEditor, i='menuIconWindow.png')
cmds.menuItem(p=menu, bld=1, l="Reference Editor", rp="NW", c=self._trigger_referenceEditor, i='menuIconWindow.png')
cmds.menuItem(p=menu, bld=1, l="Outliner", rp="N", c=self._trigger_outliner, i='menuIconFile.png')
cmds.menuItem(p=menu, bld=1, l="Curve", rp="E", c=self._trigger_curve_selection, i='pickCurveObj.png')
cmds.menuItem(p=menu, bld=1, l="Mesh", rp="SE", c=self._trigger_mesh_selection, i='pickGeometryObj.png')
subMenu = cmds.menuItem(p=menu, l="North Sub Menu", rp="N", subMenu=1)
cmds.menuItem(p=subMenu, l="North Sub Menu Item 1")
cmds.menuItem(p=subMenu, l="North Sub Menu Item 2")
cmds.menuItem(p=menu, l="South", rp="S", c="print 'South'")
cmds.menuItem(p=menu, ob=1, c="print 'South with Options'")
# List
cmds.menuItem(p=menu, l="First menu item")
cmds.menuItem(p=menu, l="Second menu item")
cmds.menuItem(p=menu, l="Third menu item")
cmds.menuItem(p=menu, l="Create poly cube", c="mc.polyCube()")
# Rebuild
cmds.menuItem(p=menu, l="Rebuild Marking Menu", c=rebuild_markingMenu)
def _build_shotgun_markingMenu(self, menu, parent):
cmds.menuItem(p=menu, bld=1, l="Push Movie", rp="N", c=self._trigger_pushmovie, i='menuIconFile.png')
cmds.menuItem(p=menu, bld=1, l="Loader", rp="NW", c=self._trigger_loader, i='menuIconFile.png')
cmds.menuItem(p=menu, bld=1, l="Sync Frame Range", rp="W", c=self._trigger_sync_frame_range, i='menuIconWindow.png')
cmds.menuItem(p=menu, bld=1, l="Publish...", rp="NE", c=self._trigger_publish, i='menuIconFile.png')
cmds.menuItem(p=menu, bld=1, l="Shotgun Save As", rp="S", c=self._trigger_save_as, i='menuIconWindow.png')
cmds.menuItem(p=menu, bld=1, l="Switch Asset", rp="SW", c=self._trigger_switch_asset, i='pickGeometryObj.png')
def _trigger_outliner(self, *args):
pm.mel.eval('OutlinerWindow')
def _trigger_graphEditor(self, *args):
pm.mel.eval('GraphEditor')
def _trigger_referenceEditor(self, *args):
pm.mel.eval('ReferenceEditor')
def _trigger_curve_selection(self, *args):
cmds.selectMode(object=1)
cmds.selectType(handle=0, ikHandle=0, joint=0, nurbsCurve=1, cos=1, stroke=1,
nurbsSurface=0, polymesh=0, subdiv=0, plane=0, lattice=0,
cluster=0, sculpt=0, nonlinear=0, particleShape=0, emitter=0,
field=0, spring=0, rigidBody=0, fluid=0, hairSystem=0,
follicle=0, nCloth=0, nRigid=0, dynamicConstraint=0, rigidConstraint=0,
collisionModel=0, light=0, camera=0, texture=0, ikEndEffector=0,
locator=0, dimension=0)
def _trigger_mesh_selection(self, *args):
cmds.selectMode(object=1)
cmds.selectType(handle=0, ikHandle=0, joint=0, nurbsCurve=1, cos=1, stroke=1,
nurbsSurface=1, polymesh=1, subdiv=1, plane=1, lattice=0,
cluster=0, sculpt=0, nonlinear=0, particleShape=0, emitter=0,
field=0, spring=0, rigidBody=0, fluid=0, hairSystem=0,
follicle=0, nCloth=0, nRigid=0, dynamicConstraint=0, rigidConstraint=0,
collisionModel=0, light=0, camera=0, texture=0, ikEndEffector=0,
locator=0, dimension=0)
def _trigger_pushmovie(self, *args):
import tank
engine = tank.platform.current_engine()
engine.commands['Push Movie']['callback']()
def _trigger_loader(self, *args):
import tank
engine = tank.platform.current_engine()
engine.commands['Loader...']['callback']()
def _trigger_publish(self, *args):
import tank
engine = tank.platform.current_engine()
engine.commands['Publish...']['callback']()
def _trigger_sync_frame_range(self, *args):
import tank
engine = tank.platform.current_engine()
engine.commands['Sync Frame Range|Rate with Shotgun']['callback']()
def _trigger_switch_asset(self, *args):
import tank
engine = tank.platform.current_engine()
engine.commands['Switch Asset']['callback']()
def _trigger_save_as(self, *args):
import tank
engine = tank.platform.current_engine()
engine.commands['Shotgun Save As...']['callback']()
def rebuild_markingMenu(*args):
cmds.evalDeferred("""reload(markingMenu);markingMenu.MarkingMenu()""")
if __name__ == '__main__':
MarkingMenu()
逻辑很简单,就是先判断MarkingMenu是否已经存在,存在了就删掉再重新创建;创建MarkingMenu用的popupMenu命令,将参数-mm(-markingmenu)设置为True,这里详细说明下MarkingMenu有两种排列方式,一种是放射状的,一种是列表状的,我在实例代码里给出了两种方式,就是menuItem的rp(radialposition)设置下,共有八种方位,和我们日常用到的方位一样,我把它做成一个图例,基本照着这个图填就行。
'''
NW N NE
\ | /
\ | /
\ | /
__ W___ __\|/___ __ __E __
/|\
/ | \
/ | \
/ | \
SW S SE
'''
list类型,就是我们最普通的列表方式,没方位设置,一次往下添加就行。
最后说明下rebuild,我们不想修改都跑下代码,只需要rebuild下就行,用到的是evalDeferred,顾名思义,就是延迟执行的意思,如果没有这个命令,直接reload是会报错的。最终的效果如下: