Smooth Enum Space Switching with “AB Space” (working title)

As far as I’ve known during my time in rigging/animation, there have been two widely used methods of control for multi-space switching. Either you have an enum attribute with all the spaces or float attributes between two spaces, as more typically seen in IK FK switches, but sometimes with space switching as well.

Enum Attributes:

enum-2.gifThe Good- Easy and clean, expandable, current space is always clear

The Bad- Works like integers under the hood, so no smooth interpolation. So switching isn’t practical unless paired with a matching script. Even if Maya were to change somehow behave a bit more like floats between values, it’s not like blending between 2 and 5 would be direct.

 

Float Attributes:

float.gif
The Good- You can switch over a few frames or blend spaces rather than necessarily relying on matching scripts, making the whole thing a bit more lightweight and portable.

The Bad- This setup is typically confined to switching between two spaces (world space vs parent space, or something like that) with the only way of expanding typically being either adding more float attributes that sort of daisy chain and have a priority order or constraint-switch to another controller that in turn has more float or enum attributes.

Animator preference (and in turn, the rigging tools) at Insomniac is to use the float attributes largely because of the smooth interpolation. That being said, I’ve personally never been a fan of that setup largely because that sort of ties our hands for controllers where we’d like the give the animators more options without making a messy attribute-filled controller. So I’ve been tinkering with a C option.

 

A Quick Aside

The lookDevKit plugin that’s been shipping with the last few Maya versions is quickly becoming one of my favorites with its set of super useful utility nodes (god I’m such a nerd)

1

The one I’ve been using the most is floatMath because it conveniently combines a lot of operations in to one node, so one doesn’t have to deal with all the different nodes in the standard Maya set with their accompanying different behaviors and attribute naming conventions. So in general, the one stop-shop is my preference. Plus I feel less wasteful when I’m using them for my typical use of calculating single numbers where most of the old math nodes are designed for color and therefore you have to switch between having xyz or rgb attributes or different naming patterns  (again, that slightly different behavior can cause confusion and consternation, at least for me)2.png

In the cases were vectors/3 floats are needed, for most of these nodes, there are color variants, and occasionally they also have alpha attributes as well so you can maybe sneak in a forth attribute if needed. I dunno, I haven’t messed with those, but I’m assuming it would work though it may clamp values.3.png

In any case, there are a lot of other useful nodes in the kit. You should check it out. Now that’s enough with the evangelizing. Back to the subject at hand

 

Enums or Floats

da316kc-78a5aafd-6870-41f8-b83c-2f5374a19a7d

(Photo credit goes to theporkchopexpress on deviantart)

To try and get around the issue of getting the advantages of both floats and enums, I started playing around with a new scheme where there are two sets of enums for an “A Space” and a “B Space” with a float to blend between the two.

(This video was too long to convert to a GIF, and I’m too tired to recapture)

 

This setup uses floatLogic nodes (from the lookDevKit, though for people with older Maya builds, I think condition nodes would also work) and floatComposite set to mix mode (though blendTwoAttr would work, in fact, until I almost had finished writing this post, I was using blendTwoAttr, but realized I could use composite) to create a switchboard of sorts for connecting to constraint weights.

new_graph.png

For each of the target nodes in the Enum, You’ll need 2 floatLogic nodes and a blendTwoAttr to output to the weight attributes on the parent (or whatever else) constraint.

The floatLogic nodes for A or B space are set to output a bool for True if the enum attributes are set to the same index as the parent constraint target. The out bools are hooked up to the blendTwoAttr and blended between a space or b space by the followB float attribute. That way, it’s all set to 0 except for the chosen values for A and B space, which are set to 0 or 1 depending on which space is set using the followB attribute.

Annotation 2019-12-10 162505.png

One could potentially pack down the floatComposite nodes in multiples of 3 using colorComposite nodes, but I tend to prefer sticking to 1 dimensional nodes when possible and just making more of them when dealing with 1 dimensional attributes for readability purposes. To each their own though. Just saying it is possible to use the color nodes instead for that bit (using color logic instead for packing won’t work though since it compares all 3 attributes)

Here’s a quick script I hastily recreated because I’m away from my usual computer(s) because I’m on vacation in Morocco /humble-brag

import pymel.core as pm

sel = pm.selected()
controller = sel[-1]
targets = sel[:len(sel)-1]

# This setup presupposes a parent group for the controller to be constrained
const = pm.parentConstraint([targets, controller.getParent()], mo=True)  # or whatever else constraint
controller.addAttr('Space Switching', keyable=True, lock=True)
controller.addAttr('aSpace', at='enum', enum=[target.nodeName() for target in targets], keyable=True)
controller.addAttr('bSpace', at='enum', enum=[target.nodeName() for target in targets], keyable=True)
controller.addAttr('followB', at='double', min=0, max=1, keyable=True)

if not pm.pluginInfo('lookdevKit.mll', q=True, isLoaded=True):
    pm.loadPlugin('lookdevKit.mll', force=True)

for i, target in enumerate(targets):
    aspace_logic = pm.createNode('floatLogic', n='{}_aSpace_following_{}_equals'.format(controller, target))
    bSpace_logic = pm.createNode('floatLogic', n='{}_bSpace_following_{}_equals'.format(controller, target))
    blend = pm.createNode('floatComposite', n='{}_{}_blend'.format(controller, target))

    # Set the constants
    aspace_logic.floatB.set(i)
    bSpace_logic.floatB.set(i)
    blend.operation.set(2)  # mix

    # Make the connections
    controller.aSpace.connect(aspace_logic.floatA)
    controller.bSpace.connect(bSpace_logic.floatA)
    aspace_logic.outBool.connect(blend.floatA)
    bSpace_logic.outBool.connect(blend.floatB)
    controller.followB.connect(blend.factor)
    blend.outFloat.connect(filter(lambda x: x.endswith('W{}'.format(i)), const.listAttr(userDefined=True))[-1])

 

So I just thought I’d share this to see what people think about it because I haven’t really seen it done this way before. Plus to be honest, I’m not nuts about the attribute names for switching as far as clarity for animators goes. That’s actually the other reason I’m writing this post, to maybe crowdsource some better name ideas, so feel free to mention any ideas you might have if something comes to mind while reading, even if just for the setup itself (I’ve just been calling it AB Space, but am not wedded to it)

Anyways, let me know what you think, if you’d maybe like a more tutorialized post about the setup if the way it works isn’t clear enough, or if you spot any ways the setup could be a bit less node-heavy or as mentioned before if you have any bright ideas on attribute or setup naming.

One thought on “Smooth Enum Space Switching with “AB Space” (working title)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: