Here comes a stupid question, but say I want to modify a UI of Maya, namely the “imagePlane settings UI”.
In my case I just want a UI with these three sliders. I did create a UI with three sliders like this, but was curious if there was another way to do it by modifying Maya’s native UI:s so it will have the same connections if images were plugged into the slots.
Here’s my own window
import maya.cmds as cmds
cmds.window()
form = cmds.frameLayout(mw=10, mh=10)
cmds.colorSliderGrp( label='Color Gain', rgb=(0, 0, 1) )
cmds.colorSliderGrp( label='Color Offset', hsv=(120, 1, 1) )
cmds.attrFieldSliderGrp(label='Alpha Gain', min=0, max=1)
cmds.showWindow()
So I started digging around the scripts folder and found these two files, but I can’t seem to use these or I don’t understand.
C:\Program Files\Autodesk\Maya2024\scripts\others\buildImagePlaneMenu.mel
C:\Program Files\Autodesk\Maya2024\scripts\AETemplates\AEimagePlaneTemplate.mel
Now I’m guessing many of the UI elements/windows are built at runtime and doesn’t exist as physical UI-files? I’m severly lacking in my understanding of Maya’s UI. How the migration to Qt went and how things used to work as opposed to now. I have a faint memory that all of Maya’s UI and window could be found as MEL-files and modified to create new windows by copying/pasting of elements from different scripts.
For backwards compatibility reasons, most of Maya’s QT conversion happened at the level of replacing the implementation of the old native MEL based UI commands. If you poke around in your install you will see that there are tons of files like the buildImagePlaneMenu.mel
you found, which create the UI at runtime using basic mel programming (most of the menus, for example, will have their own build_____Menu.mel
, which run either the first time time or every time the menu is touched by the user.
The AETemplate system is a bit more complex. The job of an AE Template is to generate UI for objects of a particular type. They a can be a bit hard to read because they have to account for localization (you’ll see a lot of calles to uiRes()
which is the function that gets the localized strings) and because they use the editorTemplate()
command to actually hook attributes to to the UI. Depending on how deeply nested this is, it can be a real pain to manage, but you can generally count on three things:
-
the actual template function will match the node name in pascalCase but with the prefix AE
and the suffix Template
– hence AEimagePlaneTenmplate
(note capitalization there, it’s an easy thing to miss)
-
they will be one function which takes as single string argument, $nodeName
. I believe you need to use that exact name for the variable
-
Inside they do a lot of this:
editorTemplate -label "Frustrum NearZ" -addControl "nearZ"
where the label argument is the name of a control and the string after -addControl
is the name of the attribute being affected (you don’t get a choice of what the control is, you’ll get the right type for the attribute type)
So if you want to add/modify the basic UI you have two options.
-
The easy/lazy way – you just hack the MEL files to add controls or functions you want. The downsides here: (a) you will need to redo this work with every version change and (b) you can’t share this work with people who don’t have admin rights in their program files filder, a common situation in many outsource studios.
-
The more modern way is to monkeypatch the originals. MEL has only one global namespace, and you can overwrite a MEL procedure in memory by re-executing the mel. And if you want to avoid writing any more MEL than is absolutely necessary, you can redefine it so that your replacement function just calls a python function. Here’s a contrived example:
maya.mel.eval("source buildShaderMenus.mel");
# this defines a replacement mel procedure in a string.
# this unfortunately involves some irritating nested string
# escapes
menu_shim = """global proc buildShaderMenus (string $item)
{
string $py = "import myShaderMenu; myShaderMenu.create(";
$py = $py + "\"" + $item + "\""; + ")";
python ($py);
}
"""
# running this will replace Maya's native `buildShaderMenus()` function
# with myShaderMenu.create() in your python module,
# where you can do whatever you want.
maya.mel.eval(menu_shim)
If you insert that replacement bit early in your startup phase, it will be invisible to your users and you can replace the original UI with whatever you like. Most AETemplates and menus are instantiated the first time the user interacts with them and then stay alive for the rest of the session, so you want to get your shims in as early as possible.
There’s a gist which can be helpful for creating patches like these here . However you’d need to do some digging into any of the maya UI build scripts to figure out what to patch. In general – and unfortunately for your use case – the AETemplate scripts can’t easily be patched with a simple before/after callback the way the menus can. So you might need to make a copy of the original MEL and insert appropriate callbacks directly into the right places.
3 Likes
Hi and thank you so much for the info and explanation.
I will definitely look into this.