We've Moved

The blog has been retired - it's up for legacy reasons, but these days I'm blogging at blog.theodox.com. All of the content from this site has been replicated there, and that's where all of the new content will be posted. The new feed is here . I'm experimenting with crossposting from the live site, but if you want to keep up to date use blog.theodox.com or just theodox.com

Sunday, July 30, 2017

MGui 2.2 release is live

The latest next point release of mGui — the python module to streamline maya gui creation — is up on on Github, thanks in large part to +Bob White, who put in a lot of the work on this release.

Although this is a point release, it has some exciting improvements:

Improved Menu Support

We've added a more refined an elegant method for handling sub-menus with the SubMenu class. This works like a context manager, so the structure of the menu is obvious when reading the code.

    with Menu(label='TestMenu') as food_menu:            # conventional menu items          hotdog = MenuItem(label = 'Hot Dog')          burger = MenuItem(label = 'Burger')          taco = MenuItem(label = 'Taco')            # a submenu          with SubMenu(label='Pizza') as sm:              pepperoni = CheckBoxMenuItem(label='Pepperoni')              sausage = CheckBoxMenuItem(label='Sausage')              pineapples = CheckBoxMenuItem(label='Pineapples')              for each in (pepperoni, sausage, pineapples):                  each.command += pizza_selected              MenuDivider()            with SubMenu(label='Delivery') as sm:              with RadioMenuItemCollection() as radio:                  eatin = RadioMenuItem('Eat In')                  takeout = RadioMenuItem('Take Out')                  delivery = RadioMenuItem('Delivery')  

We've also enhance menus so they support the same kind of dot notation as other mGui controls. In this example that means you could get to the 'sausage' item as


which is going to be both more readable and more consistent with other mGui code. If you use the YAML menu loader, that also supports submenus:

        - !MMenuItem              key:  check              label:  checkboxes              annotation: Toggle me!              options:                checkBox: True              command: mGui.examples.menu_loader.checkbox              - !MSubMenu              key: submenu              label: submenus                items:                  - !MMenuItem                    key: sub1                    label: Item 1                    - !MMenuItem                    key: sub2                    label: Item 2  

Working with existing items

At various points we supported three different idioms (Menu.from_existing()gui.derive() and Control.wrap(). for putting an mGui wrapper around existng controls. In this release these have been collapsed into a single function, gui.wrap() which has some cool new features:

  • It's automatically recursive. So if you wrap an existing menu, the returned object will have nested properties for all of the menuItems in the menu. If you wrap an existing layout, you'll have nested properties for all the layout's children.
  • It does a better job matching the underlying maya gui widgets to mGui wrapper classes than any of the previous methods. Because of some irregularities in the way Maya relates commands to objects there are still some edge cases the new wrap()should get most cases.
  • For maya objects with python callbacks, you can ask wrap() to convert them to [multicast delegates for you. This does not support mel callbacks yet, but we may be able to expand to supporting them in the future.

The new, improved gui.wrap() should make it much easier to add mGui controls or layouts to menus and windows that come from regular Maya.

For the time being, we've re-pointed gui.derive() at gui.wrap() under the hood so it won't break existing code — it will however issue a deprecation warning so that when we remove derive() in 2.3 people will have had plenty of warning.

Find() method for child controls

We've added a new method to all layouts that will collect all children of a layout by mGui type. This is handy for big complex layouts where you aren't quite sure what something should be called — or for layouts that you've gotten from gui.wrap().


We've also cleaned up and expanded the examples, added more test coverage, and fixed a few minor bugs (the most obvious one will be that the StretchForm() classes properly respect margins, at long last!).

We're starting to put more time into the project wiki, including some new tutorials. Feedback and suggestions are much appreciated! And of course if you run into any problems be sure to log them on the project issues page. We've been debated whether or not we should package the project for PyPi and/or the Maya app store — if you have an opinion you should chime in in the comments or on the issues page.

tags: mayamgui

Sunday, June 12, 2016

The New Hotness

I've finally completed rolling over to to a new, self-hosted blog platform!

The process took a bit longer than I wanted, mostly because it web development remains a messy, iterative process - at least for me.  Since I ended up unifying both the blog and the old Character Rigger's Cookbook as well as on old markdown wiki, I had to do a lot of little scripts to groom the old content into a consistent format and linking strategy.  Add in more than a modicum of CSS noodling and whatnot and my 'couple of weekends' project turned into a couple of months.

However all that is behind me now, and all my future updates are going to be coming up at theodox.github.io  (you can also use www.theodox.com).  If you're subscribed to the current feed, you should switch over to either http://theodox.github.io/feeds/atom.xml or http://theodox.github.io/feeds/rss.xml, depending on your reader; one of the nice side effects of the switch is that the new feeds are much cleaner than Blogger's -- no more CSS gibberish instead of article summaries, thank you very much!)

I'm going to leave this site intact, and I'll try to keep monitoring comments and so on here, but the new site is going to be where all the news stuff comes out.  I'm also going to change the blog.theodox.com redirect so it goes to the new site, so if you're using that in a blogroll you won't have to update it.

PS. I had to touch a lot of content during the migration: there are about 150 blog posts, several dozen wiki pages, and a bunch of articles that all had to be repointed and I'd be pretty surprised if nothing odd slipped through.  Please let me know using the comments at the new site so I can fix up anything that's confusing or misleading.

So, here one more link to the new site, just in case.  Hope to see you there!

Thursday, May 12, 2016

Shamless Job Plug

Just wanted to re-flag the two job openings I'm hiring for at Undead Labs right now.

We're looking for one TA with good python chops to ride herd on the python/maya toolkit, and another TA with good shading and GPU skills to help us wring the most out of the Unreal Engine.  Details of both positions are in the link above.

Contact me directly or apply via the Undead Labs website!

Thursday, April 28, 2016

minor minq manifestations

Blogging has been super light, thanks to the triple whammy of a milestone, a cold, and my grand plan to migrate this blog over to a static site generator.  However I did want to mention that I've been trying to update the minq wiki page so it is more accessible. I'd appreciate any feedback, comments or suggestions to make it clearer.  When you write something yourself you just accept as natural the quirks and habits of thought that go with it, so it's handy to have outside eyes when you're writing documentation.

I've added a couple of minor features as well.  There's a  bunch of operators for counting things -- for example you can get the vertex count of meshes with something like Meshes().get(VertCounts) . On a somewhat related note all streams have a count() function which will return the length of the stream, and a first() method which will pull the head item from a stream -- which is handy if you expect to narrow down to a single item and don't want a single-item iterable.

Last but not least I'd love to hear from the community about good minq hacks -- I'll be happy to add cool ones to the examples file. I'd also appreciate any bugs you find going into the issues page!

Sunday, April 3, 2016

Blogger blues

Wherein our author uses blogger to post a blog post blogging about how much he dislikes blogger.
It's late on a Sunday night and I need to get this off my chest.

I really have come to loathe Blogger.  The sluggish, overly complicated, JS heavy theme, the sluggish, too-complex-for-speed-but-too-simple-for-interesting-stuff editor, and the way it stuffs stylesheet info into the RSS feed come to mind. but overall... it's just gotten on my nerves.

So, I'm probably going to transition the blog over to something else.  My current leading candidate for a site generator is Pelican, a Python based static html site generator which seems to be powerful enough for my not-too-complex needs.  Jekyll is another candidate but all things being equal I'd rather stick with a Python-based setup and the final output will be pretty much the same.

I'm a tad nervous about what happens to old links and traffic so I assume that I'll probably transition over gradually with duplicate postings for a while. If any of you have done something similar in the past I'd be curious to hear about how it went.

In the meantime, I'll just add that I've been dealing with the transition in typical TA fashion. I hacked up a script to download all of the existing blog posts as XML, then used the html2text module on the cheese shop to convert the HTML from the posts into markdown text. I'm still going to have to hand-finish every pieces, cleaning up dead links and missing images and so on:  I'm sure it'll be a TA-style spit'n'bailing-wire party for a while yet.

In the meantime I'm all ears if anybody has more suggestions for site generators, or a reason to go with something other than a static site on github.io, please let me know in the comments!

update:  the new site is here

Saturday, March 26, 2016

mGui updates in the offing...

mGui updates in the offing... Changes on the way for mGui, the maya Gui framework

For those of you who’ve been using mGui to speed up and simplify your Maya gui coding, there are some interesting changes on the horizon. Although I’m not entirely ready to release the changes I have in mind they are mostly sitting in their own branch in the Github repo.

The upcoming version introduces some new idioms - in particular, it gets rid of the need for explicitly setting keys on new controls to get access to nested properties. In the first version of mGui you’d write something like this:

    with gui.Window('window', title = 'fred') as example_window:
        with VerticalForm('main') as main:
            Text(None, label = "Items without vertex colors")
            lists.VerticalList('lister' ).Collection < bind() < bound  
            with HorizontalStretchForm('buttons'):
                Button('refresh', l='Refresh')
                Button('close', l='Close')

With the new refactor that looks like this:

    with gui.Window('window', title = 'fred') as example_window:
        with VerticalForm() as main:
            Text(label = "Items without vertex colors")
            lister = lists.VerticalList()
            lister.collection < bind() < bound  
            with HorizontalStretchForm() as button_row:
                refresh = Button( label='Refresh')
                close = Button(label='Close')

The big advantage here is that those local variables are not scoped exclusively to the layout context managers where they live, which makes it easy to control when and where you hook up your event handlers: In the above example you could defer all the bindings and event handlers to the end of the script like this:

    with gui.Window('window', title = 'fred') as example_window:
        with VerticalForm() as main:
            Text(label = "Items without vertex colors")
            lister = lists.VerticalList()
            with HorizontalStretchForm() as button_row:
                refresh = Button( label='Refresh')
                close = Button(label='Close')

    lister.collection < bind() < bound
    refresh.command += refresh_def
    close.command += close_def

So far I’m really liking the new idiom, particularly eliminating the extra quotes and redundant None keys. However this is a minorly breaking change: in some cases, old code which relied on the key value to name and also label a control at the same time will when the keys become redundant. Moreover I bit the bullet and started to refactor the entire mGui module to use correct pep-8 naming conventions – in particular, member variables are no longer capitalized. So if you have code outside of mGui this will introduce some issues. When I converted my own code, most of the changes could be done with a regular expression but there were a few danglers.

I think the changes are worth the effort, but I’d be really interested in hearing from users before trying to bring the new mGui branch back into the main line. It should actually be possible to write a script that fixes most existing code automatically, that’s something we could refine collaboratively.Please let me know in the comments or by opening an issue on the GitHub site if you have comments or plans. As always, bug fixes and pull requests always entertained!

Sunday, March 20, 2016

Another Year, Another GDC...

Another year, another GDC GDC 2016 roundup It doesn’t take much super-secret industry-insider special knowledge to know that the big story this year was VR, VR and more VR – if the you had somehow managed to miss out on the pre-show hype the giant black Oculus booth looming like the Death Star right over the entrance to the expo floor told pretty much the whole story in one glance.

It is, however, interesting to note how cynical we’ve become as an industry about tech bubbles: from MMOs to Facebook games to In-app purchases and 3-D TVs, we’ve all lived through so many Next Big Things that we habitually reserve judgement – even on things like the latest crop of VR gear which sets our little nerdly hearts a-fluttering. I had a lot of conversations with people on the general theme of “wow, that’s cool. In three years most of them will be out of business, though.” – even with people in the VR business itself.
Personally, I think VR is going to survive but I don’t think it’ll be the kind of world-changing, ubiquitous tech that the broadband internet and handhelds have turned out to be. It’s an awesome geek toy and the gateway to many interesting and novel experiences. I see it sort of like that kayak in the garage: a cool thing that gets dusted off a few times a year but not a regular part of daily life, and never going to buffed up to the high consumerist gloss of an iPhone. Maybe in another decade, but for now it’s a really cool niche product. I hope all that crazy money sloshing around in VR land fuels some general purpose innovation : in particular, I hope that VR’s need for screaming framerates in two renders at once may make hardware that is more performant overall and also for split-screen friendly deferred rendering.
In the actual, as opposed to the virtual, world the highlight of the show for me is always the TA roundtables. It’s such a great resource for the community, and a chance for folks who often live a bit outside the main stream of their development teams to get together with people who share their unique and esoteric pain. Those three roundtables are the only room full of people who will chuckle at jokes about MaxScript and who truly appreciate the hopeless pathos of sending emails about proper check-in procedures to a team of artists. As always, hats off to +Jeff Hanna  for running the roundtables and also the TA Bootcamp, which I had to miss this year but sounded really good. I’m anxiously awaiting the release of the talks I missed on the GDC Vault.
In these annual roundups I usually try to note the size and intensity of the job market. This year was kind of difficult to gauge. The big mega-booths from mega-teams were largely absent this year: I didn’t see many of the long lines of students queuing up to show their portfolios to Blizzard, Bungie, or 343. On the other hand the general commercial tempo seemed pretty up beat. I think this reflects the general trend away from big, highly institutionalized teams and toward smaller, more agile (but also more fragile) groupings: the job market is more fragmented but not necessarily smaller than in years gone by. I could be wrong about that one, though – this might just be a mid-console-cycle lull.
To all the folks I saw down at the show – it was awesome! To those who didn’t make it this year – don’t miss it next time!

PS - one important thing that came out of the round table is that more and more people are signing up to the Tech artists slack channel.  If you're not already a member, follow that link to sign up.