So, it seems like I have been going crazy with marking menus lately. I am really trying to get the most of them, and that would not be much if we could only use them in the viewports, so today we are going to look at how we can construct custom marking menus in maya editors.
tl;dr: We can query the current panel popup menu parent in maya with the
findPanelPopupParent MEL function, and we can use it as a parent to our
So, there are a couple of scenarios that we need to have a look at, as they should be approached differently. Although, not completely necessary I would suggest you have a look at my previous marking menu posts – Custom marking menu with Python and Custom hotkey marking menu – as I will try to not repeat myself.
Okay, let us crack on. Here are the two different situations for custom marking menus in maya editors we are going to look at.
In the viewport these are definitely the easier ones to set up as all we need to do is just create a
popupMenu with the specified modifiers –
alt, the chosen button and viewPanes as the
parent. When it comes to the different editors, though, it gets a bit trickier.
Let us take the node editor as an example.
If we are to create a marking menu in the node editor, it is a fairly simple process. We do exactly the same as before, but we pass
"nodeEditorPanel1" as the
parent argument. If you have a node editor opened when you run the
popupMenu command, you will be able to use your marking menu in there. The catch is though, that once you close the node editor the marking menu is deleted, so it is not available the next time you open the node editor.
Unfortunately, I do not have a great solution to this problem. In fact, it is a terrible solution, but I wanted to get it out there, so someone can see it, be appalled and correct me.
The second method – Custom hotkey trigger – is much nicer to work with. So, you might want to skip to that one.
What I do is, I create a hotkey for a command that invokes the specific editor (I only have marking menus in the node editor and the viewport) and runs the marking menu code after that. So, for example, here is my node editor hotkey (Alt+Q)
mc.NodeEditorWindow() if mc.popupMenu("vsNodeMarkingMenu", ex=1): mc.popupMenu("vsNodeMarkingMenu", dai=1, e=1) else: mc.popupMenu("vsNodeMarkingMenu", p="nodeEditorPanel1Window", b=2, ctl=1, alt=1, mm=1) mc.setParent("vsNodeMarkingMenu", m=1) from vsRigging.markingMenus import vsNodeMarkingMenu reload(vsNodeMarkingMenu)
That means that everytime I open the node editor with my hotkey I also create the marking menu in there, ready for me to use. As, I said, it is not a solution, but more of a workaround at this point. In my case, though, I never open the node editor through anything else than a hotkey, so it kind of works for me.
vsRigging.markingMenus.vsNodeMarkingMenu file is as simple as listing the
import maya.cmds as mc mc.menuItem(l="multiplyDivide", c="mc.createNode('multiplyDivide')", rp="N", i="multiplyDivide.svg") mc.menuItem(l="multDoubleLinear", c="mc.createNode('multDoubleLinear')", rp="NE", i="multDoubleLinear.svg") mc.menuItem(l="plusMinusAverage", c="mc.createNode('plusMinusAverage')", rp="S", i="plusMinusAverage.svg") mc.menuItem(l="condition", c="mc.createNode('condition')", rp="W", i="condition.svg") mc.menuItem(l="blendColors", c="mc.createNode('blendColors')", rp="NW", i="blendColors.svg") mc.menuItem(l="remapValue", c="mc.createNode('remapValue')", rp="SW", i="remapValue.svg") ...
A proper way of doing this would be to have a callback, so everytime the node editor gets built we can run our code. I have not found a way to do that though, other than ofcourse breaking apart maya’s internal code and overwriting it, which I wouldn’t go for.
Luckily, creating a custom marking menu bound to a custom hotkey actually works properly and is fairly easy. In fact, it is very similar to the Custom hotkey marking menu post. Let us have a look.
Now, when we are working with custom hotkeys we actually run the initialization of the
popupMenu everytime we press the hotkey. This means we have the ability to run code before we create the marking menu. Therefore, we can query the current panel and build our
popupMenu according to it. Here is an example
runTimeCommand, which is bound to a hotkey.
import maya.mel as mel name = "exampleMarkingMenu" if mc.popupMenu(name, ex=1): mc.deleteUI(name) parent = mel.eval("findPanelPopupParent") if "nodeEditor" in parent: popup = mc.popupMenu(name, b=1, sh=1, alt=0, ctl=0, aob=1, p=parent, mm=1) from markingMenus import exampleMarkingMenu reload(exampleMarkingMenu) else: popup = mc.popupMenu(name, b=1, sh=1, alt=0, ctl=0, aob=1, p=parent, mm=1) from markingMenus import fallbackMarkingMenu reload(fallbackMarkingMenu)
So, what we do here is, we start by cleaning up any existing versions of the marking menu. Then, we use the very handy
findPanelPopupParent MEL function to give us the parent to which we should bind our
popupMenus. Having that we check if the editor we want exists in the name of the parent. I could also compare it directly to a string, but the actual panel has a number at the end and I prefer just checking the base name. Then, depending on which panel I am working in at the moment, I build the appropriate custom marking menu.
Don’t forget that you need to create a release command as well, to delete the marking menu so it does not get in the way if you are not pressing the hotkey. It is a really simple command, that I went over in my previous marking menu post.
The obvious limitation here is that we have a hotkey defined and we cant just do ctrl+alt+MMB for example.
So, yeah, these tend to be a bit trickier than just creating ones in the viewport, but also I think there is more to be desired from some of maya’s editors *cough* node editor *cough*, and custom marking menus help a lot.