The One Tool Challenge

Because there are so few useful and production ready Maya tools online. I was thinking how nice it would be, if every technical Maya user in the world would share (+support) even just one such tool in their lifetime. That way it sounds a lot more doable.
For myself I would only consider prSelectionUi (https://vimeo.com/pazrot/prselectionui) to be a success in that regard. After posting it on highend3d and making a Vimeo video in 2012 it self distributed and to this day I find it installed at every companies I go to and a lot of animators I talk to are using it. I personally only use it once every few weeks to manage vertex selections or visibilities (pose feature). But I think my latest tool prDeformPaint (see previous post) could be my "One Tool" for Riggers and Modelers. I haven't posted it anywhere yet but I'm also not in a rush, because I don't mind testing it longer in production before sharing it.

If someone is looking for useful tool ideas. The most fundamental Maya UIs have a lot of room for improvement, so pretty much ever Maya user would benefit from those:
  • Connection editor with name search/filter field to reduce the time and focus required to find the right attribute. Even with alphabetic ordering is it pretty tedious and that also does not work well together with child attributes because it orders them with the root attributes. In addition, it would also be nice to have an option to connect one output into multiple nodes input attributes at the same time.
  • Add and Edit Attribute Editor for the 21st century. Mayas add and edit attribute editors have probably not been changed since 1999 and could benefit a lot from a major overhaul. I would also merge them into one.
  • A non-destructive Node editor / Hypergraph: One that does not move the editor-view and nodes around on it's own when working with it. The node editor version would be a lot more work, so I would probably start with something closer to the Hypergraph.
  • Attribute editor for multiple nodes at once (setting values applies to all nodes, not just one). I don't know how the aeTemplate reading works, so it might be really hard to do. In that case an improved Attribute Spread Sheet could be a better goal.
I'm not much of a UI guy, so that's probably why those have been on my mind for a while and I haven't done any of them. They also don't have the biggest impact, but a huge target audience.
In general I would recommend to consider:
  • Is the tool actually useful? (doing something difficult != doing something useful)
  • Can it already be done in Maya?
  • Has someone else already done it and made it available?
  • Is it useful enough to be worth the time and effort to learn and install it and keep it installed?
  • Test it a while in production before sharing it.


prDeformPaint.py making of




Modeling brushes, mainly for blendshape targets (similar to DPK_paintDeform.mel)
The documentation is in the docstring of .../prmaya/scripts/prDeformPaint.py


Compared to not using any "Smooth delta" brush, I estimate that this tool improves my total productivity by ~4% (if ~20% of my time is spend on blendshapes/correctives and the tool speeds that up by ~20%). I try to be conservative in these kind of guesses, because it feels much more impactful when getting these quality of life improvements.
But the real impact should be measured relative to using the existing DPK_paintDeform.mel, in which case I would say it is half, so ~2%


In the past year I mostly worked on assets and used DPK_paintDeform.mel a lot (on almost all blendshape targets). I couldn't imagine working without it anymore. However, because it is so buggy and slow, that was pretty painful (see docstring headline "MOTIVATION"). That's why I recently wrote this improved version.
If you don't know the main purpose of "Smooth delta": It's used to smooth the effect of the whole deformation chain as a blendshape target.
For comparison: In a standard "blendShape -> skinCluster" setup, the Maya "Smooth Target Tool" does only smooth one blendShape target and is not aware of the other blendshape targets and skinCluster deformation.

Expanding functionality

I added a "Closest vertex" operation, which can be really handy when having to snap many vertex pairs that have a small offset (asymmetry, random fixes, ...). In the past I used my prClosestPoint deformer for those cases, but that is a lot less intuitive than a brush when modeling. Because it was almost no extra effort I also added "Closest point" (on surface) and "Average vertex" operations, which I rarely use. They can also already be done in default Maya, although in less convenient ways.

Code summary

MEL scripted brush tool interface, PyMEL UI, Python API 2.0 script to calculate the deltas, MPxCommand to move points (Python API 2.0 and C++ version).

Maya scripted brush (MEL)

To understand the scripted brush function calls I printed messages in each. The frequency and order that the functions get called in is not great and also has some behavior I would consider bugs (see prDeformPaintBrush.mel docstring).
At first I forwarded all function calls and arguments to the Python module, but then moved parts back in the Scripted Brush MEL file to improve performance. Because of the way I changed the calculation afterwards that benefit is not there anymore.
I'm using "setValueCommand" for gathering the vertex ids + weights and "duringStrokeCmd" to trigger the deformation (or "finalizeCmd" in some cases). That way it executes fast (batch run deformation command for multiple vertices at once and not for each vertex) and results in the expected deformation (calculate all data before deformation, instead of during the deformation loop, which creates random behavior depending on the vertex order).


TL;DR It is around four times faster than DPK_paintDeform.mel but could still benefit a lot from performance improvements when used on a production mesh (skinCluster and a blendshape target in edit mode). 

The tests listed here were done on a mesh with a skinCluster and a blendshape target in edit mode.

My initial comparisons were:
- MFnMesh vs. MItMeshVertex: No significant difference. Using MFnMesh results in a little bit slower doIt when initialized, but faster on undo/redo if stored in Cmd instance.
- old Python API vs. Python API 2.0: Insignificant speed improvement
- Merge delta calculation of Python API 2.0 script with the MPxCommand that sets the point position into one MPxCommand: No significant speed improvement
- Python API 2.0 vs. C++ API MPxCommand: Small speed improvement. The C++ version is not optimized. But I expected that even the basic version would run much faster than Python.

When even the C++ version was disappointing I reevaluated my testing and noticed that the main bottleneck was Mayas behavior when moving vertices on a mesh with a blendshape-target in edit-mode. It also makes a big difference if the target mesh still exists in the scene (that almost doubles the slow down). The skinCluster in the deformation chain also greatly slows it down.
Because some Maya tools don't seem to have that problem I'm still optimistic that there is a way to do it, even though I'm currently not aware of it.


It took me 1,5 days for the main functionality: smooth delta and copy vertex operations. I initially estimated for it to take 3 days. I am not coding much currently. Especially MPxCommand and Maya Scripted Brushes are something I haven't touched in years.
Because I had some extra time I ended up spending a few more days on extra functionality, UI features and the marginal performance improvements.


Big shout-out to Daniel Pook-Kolb who release the original tool almost 15 years ago:


prKeepOut.py making-of

A custom Maya node that can be found here:

A few months ago I started making improved array versions of Maya nodes for smaller, scalable, procedural graphs.
The prKeepOut node specifically had some relevance for production: I had an asset with around a hundred armor pieces and I thought about using keepOut nodes, but ended up deciding against them because it would have been overkill: Each armor piece would have required multiple keepOut nodes, which would have slowed down the rig a lot, take a long time to setup and probably never really work that well, because of multiple armor pieces overlapping in areas with multiple deformation axes. In the end I copied the skinCluster and blendShapes from the body and tweaked them to make the armor deform more rigid and add some offset controls for a few of the armor pieces.

It took me a few evenings after work to write prKeepOut, so in hindsight I wondered why I hadn't done it sooner. The "algorithm" is less than 100 lines and the rest is just the verbose Maya API way of creating/querying/setting attributes.
I thought about writing more about the making-of and reasoning. But it's open source and just basic Maya API, linear algebra usage. And I imagine the changes make sense to anyone who has used the 10 year old Maya keepOut node.
Initially I had shape inputs specific for each ray, too allow multi layer collision, but removed it, because it would make the node usage too complex and risk evaluation cycles.
With the recent input matrix announcement for transforms in Maya 2020+ I'm thinking about switching to matrix outputs.

A few weeks later Autodesk announced bifrost graph, which looks amazing and will hopefully make these kind of custom nodes obsolete.


New job at Reel FX

This week I started at Reel FX Montreal as Senior Rigging Artist and I'm really looking forward to working on their animated features.
When looking for a new job my main goal was to find the most interesting work. After five years in Germany where I had a lot of control on the whole rigging pipeline (I often was the only rigger on the project) and I completed some of my main goals:
- Create a non-destructive rigging pipeline in production: Almost complete freedom in the template and rig-built stage while always being able to undo/redo the rig build
- Improve modeling / topology skills by creating complete characters and topologies based on "The Art of Moving Points"


Maya API ramp attribute bug?

1. When saving:

2. What gets stored in the ascii file: 
setAttr -s 2 ".falloff[1]"  1 1 1;

3. After opening the scene again:

I recently noticed in Maya 2018 that custom Python API 1.0 node ramp attribute elements with position/value/interpolation : 0.0/0.0/linear do not get saved with the Maya scene (if their index is the lowest). I guess this is a bug. Some debug infos I gathered:
  • Probably bug source: By default Maya does not save attribute default values
  • Does not happen with default Maya nodes like remapValue
  • MPxNode.shouldSave documentation explains why this should not happen (but it is not true): "This method is not called for ramp attributes since they should always be written."
  • Since shouldSave gets wrongfully called it has to be overwritten to fix the problem
  • Only returning 'unknown' will not save the attribute. OpenMayaMPx.MPxNode.shouldSave(...) does exactly that.
  • The Python devkit example of shouldSave pyApiMeshShape.py is a bit misleading: From what I have tested all these return values seem to force save: True, False, None 

Implementations of this workaround can be found in prClosestPoint:


prPyMath.py making-of

A custom Maya node that can be found here:
Direct file link:

I wanted to create a node for some trigonometry functions, so I don't have to pollute the node graph with expressions. But after noticing that the functions I needed are all part of the Python math module I decided to just wrap the whole module, to make the node more useful.
There are only a few repeating argument in the whole module and all functions return one or two numbers. Which means there are also few Maya attributes needed to cover all cases.

A math node with that many operations is not typical for Maya.
When comparing such general purpose math nodes it might be better to just use a Python expression node like this one: http://around-the-corner.typepad.com/adn/2012/08/a-mathematical-dg-node.html

It was the first time I used the Maya Python API 2.0 for an MPxNode. But in this simple case it did not make a big difference. For the Attribute Editor buttons "Create element", "Delete element" I had to look into querying the node in the Attribute Editor context for the first time. Currently it is a workaround with a hidden textfield. I guess a global MEL variable might be the proper way to handle that?!

prClosestPoint.py making-of

A "new" Maya deformer that can be found here:
Direct file link:

Initially I just wanted to update my old prAttractNode from 2011 to work in Maya 2016+, for which I only had to update the envelope, inputGeom, outputGeom attributes (MPxGeometryFilter instead of MPxDeformerNode). But then I also added new attributes and changed the existing ones to make it more user-friendly, scalable, functional:
  • Added positions as target option 
  • Set all target type attributes to arrays 
  • Made all targets work simultaneously
  • Added on/off switch attributes
So almost every attribute changed and was not backwards compatible. Which is why I ended up giving the node a new name, that is also more suitable for the algorithm.

In production I mostly used prAttractNode when modeling. For sticky lips only once or twice. But that might be because of the kind of stylized projects I usually work on. It could be much more useful for visual programming, but many nodes are still missing for that in Maya. Python is also too slow for that, unless the affected vertex count is small enough. 

I would have liked to switch to the Python API 2.0, but the deformer proxy class has not been ported yet.
For the mesh input I switched from MMeshIntersector to MFnMesh, which is slower. I was having issues getting the matrix for MMeshIntersector to work. I used it in the past (see prAttractNode) so it might be a new bug, or I just made a mistake. On the upside it is more user friendly to not require the matrix input for mesh shapes.

The past ~5 years I haven't written any deformers with the Maya API. I mostly used it in Python scripts to improve performance and to use API exclusive features.
I find it strange that basic classes like MPxDeformerNode are still missing in the Maya Python API 2.0 after having tried it for the first time in early 2013.
A visual programming / procedural node option like Softimage ICE, Fabric Engine, Houdini would be a much better fit for most of my deformer needs. I was anticipating something similar for Maya in 2011, but after so many years and seeing what happend with Softimage and Fabric I have no idea if / when it will ever happen.
The verbose low level nature of C++ Maya deformers only seemed to have increased with the new MPxGPUDeformer class. I haven't really looked into it yet, but the devkit example MPxoffsetNode.cpp has ~600 lines of code for a simple one line vector offset algorithm. That seems quite far away from production problem solving and applied math that I would like to focus on when creating a deformer.

New github account

I recently started putting repositories on github:
The link is also in the sidebar

  • One central spot for all my public tools. Easier access, support (opposed to creativecrash / highend3d where I used to upload them)
  • Code samples when applying for jobs
  • Get feedback from / collaborate with community