Tip:
Highlight text to annotate it
X
Hi, my name's Alex Forsythe, and I'd like to show you a library called melgui that makes
it easier to write GUI tools for Maya.
To start with, we can use this Window class to create a window with a name, title, and
size.
And then we can simply show it.
This Window class takes care of all the setup, so we don't need to include any of the usual
boilerplate.
But the key feature of this library is the Gui class, which lets us create a bunch of
UI controls from a string declaration.
The syntax for a GUI declaration is similar to MEL, but with a few slight changes.
For one, every control is named, and for the sake of readability, the name goes at the
beginning of the line.
Then, after a colon, we have the control's type, and any flags we want to use when we
create it.
Unlike in MEL, we use indentation to determine how controls are parented.
So this button is a child underneath the main columnLayout.
We can keep adding controls, and it's easy to see how they're arranged and nested.
For example, another_button is at the same level as test_frame, so it'll be placed outside
the frame.
If we want it nested within the frame, all we have to do is indent.
So these string declarations allow us to define the structure of the GUI in a way that's easy
to read, write, and modify.
Once the GUI is created, we can access individual controls with square brackets, and we can
edit or query the controls' flag values.
So here we're accessing the control called test_button, and we're editing it so that
its command is this simple Python function.
We can also use the window to attach callbacks to Maya events.
This line creates a script job in Maya and ties it to the lifetime of the window.
So as long as the window exists, Maya will call our on_time_changed function whenever
the timeChanged event occurs.
And we can see here that the tool works the way we expect.
If we were to write the same tool with just the maya commands library, it would look something
like this.
Now look at the section where we define the layout of the GUI.
It's very ugly, and it's difficult to look at this code and have any idea what the resulting
UI looks like.
After writing some tools this way, I realized that it made a lot more sense to just use
MEL for the layout of the UI.
melgui is a further refinement of this process that includes some other utilities as well.
As an end result, we're able to write tools more succinctly.
Let's look at a complete example.
This very simple tool implements a counter. A label displays the current value of the
counter, starting from zero, and there are two buttons: reset and increment.
Whenever a tool has some form of internal state, it's a good idea to model that state
separately from the tool itself.
So here's a class that represents our counter: it has a count property, and it has two methods
that modify the count: reset and increment.
To tie this state object into our tool, we can extend from melgui's CallbackNotifier
class, which provides a simple implementation of the observer pattern.
When we initialize the Counter, we provide a list of events that the class supports.
In this case, we have just one: counterChanged.
The register method allows other code to provide callback functions which will be executed
when an event occurs.
In the case of our counter, we'll make a promise that we'll notify the callbacks associated
with the counterChanged event whenever the count value changes.
So we simply add a call the notify method everywhere that the count property is updated,
and our state object is complete.
With the internal state modeled as a class, we can create the tool itself in a single,
manageable function.
The first thing we do is to establish the state that's needed by the tool.
Once we instantiate our Counter class, we have a counter object that'll exist throughout
the lifetime of the tool.
Once that's done, we can define the GUI. We can see from the declaration that our GUI
includes a text label and two buttons grouped beneath a rowLayout.
With the state and the GUI established, we can define whatever functions we need to update
the tool as it's used.
In this case we have a single function, update_count_readout, that accesses the counter's count property
and updates the label with its current value.
Then, to actually create the tool, we simply make a new window with our Window class and
then create the GUI controls to populate it.
Once the controls are created, we hook up all the logic: first, we set the commands
on the buttons, which is very straightforward in this case: the reset button calls counter.reset,
and the increment button calls counter.increment.
We also register our update_count_readout function as a callback for the counterChanged
event, so that our text label will always reflect the current value of the counter.
With all that done, we simply set the initial state of the tool and then show the window.
And there we have a complete tool in about 50 lines.
This is how I write tools for Maya, and if you're interested in using this library yourself,
you're welcome to download it from GitHub and try it out.
It's released under an MIT License, so you can edit it and use it however you like.
Thanks for watching.