Sunday, 24 February 2013

New Facebook Page!

I thought I'd put a Facebook page out there as an easier way to get comments and feedback. This blog will always be the main source for updates and code snippets etc, but I figure a general Facepage could also be very useful for many. Great suggestion Josh by the way.... so here it is:

Thanks for all the support


Friday, 22 February 2013

New Features Coming soon!!

Well I've been busy over the last few nights trying to get a ton of updates into the pack.

PoseSaver now supports SubFolders:

SubFolders will switch the UI to display all child folders from the current PosePath, ie, PosePath/subFolders, selecting any of these will switch the UI to show poses in the chosen subFolder. I've clamped it to a single child folder as I really didn't want this UI to get out of hand. I guess it could expand with double click and single click commands but let's see how we get on. The Clear button will clear the subFolder text and thus return you to the root folder poses.

Also added is a tool that I used to death at Eurocom, an automated cameraTracker. This is great for moCap deliveries as it means you can just select a controller, or mesh and have the camera track the motion, saves continually shifting cameras to see deliveries. It's also great for seeing things like walk and run loops on the spot or aiming in on facial.

Working process: you select something for the tracker to aim at and choose either panning or tracking camera. The code will use the current camera in the current modelling panel and track the selected over time. As with all the Red9 code timeRange is either the current playback timerange, OR the area in the timeslider highlighted in Red. Tracking moves the camera, panning leaves it where it is and just aims at. This is a really simple bit of code, all it's doing is hacking into Maya's viewFit calls, the same thing you do when you hit the 'F' key. The option box lets you set the framestep used between samples.

Code Cleanups:
The AnimationFunctions class now takes a matchMethod arg which switches how nodes are matched during node processing. By default when it tries matching nodes in 2 hierarchy it allows prefixes, so SID_L_Wrist will match L_Wrist. I do a test to see if either name ends with the other, if it does it's considered a match. Now this can fall down if you have similarly named nodes in a hiererchy, like in facial you may have L_LowerLip and L_LowerLip_f, now these technically in the current setting will clash and may give unwanted results. So the arg flag is there to modify this. I've not yet exposed it to the UI but may add a settings optionBox in there somewhere to allow you to modify this flag.

 Note: the PoseSaver code already uses a more precise node match.

This new build is in testing at the moment



Friday, 15 February 2013

MetaData....the what and the why?

Before I go and do a new set of Vimeo vid's on the MetaClass API in Red9 I thought I'd go through a few of the basics. This is kind of triggered from a few mails I've had from people asking what the concept behind the MetaData API is and how it might benefit them. MetaData is nothing more than an API, how you use it is down to you...

Part1 -The Factory:

So in a nut shell, it's a factory class with very careful over-loading of some of the key Python calls. The factory stuff really isn't that complex. It's one of those concepts that sounds hard but actually it's really simple. The idea with mine is that any Maya node with an 'mClass' attribute on it, where that attr value matches a pre-registered class, will return that class in all the get() calls in the api ..... example:

  • 'myNode' has an attribute called 'mClass' who's value is 'metaRig' 
  • 'metaRig' is a registered class that inherits from r9Meta.MetaClass 
  • metaRig class is automatically registered to the systems by an internal function that maps all inheritances from MetaClass r9Meta.registerMClassInheritanceMapping()  

The factory part of meta goes like this:

  • r9Meta.getMetaNodes() or r9Meta.getConnectedMetaNodes() will look first for nodes that have the mClass attribute on them. The search is clamped to registered nodeTypes managed by a call that can be run to register any nodeType to the systems so you can expand as needed.
  • resulting nodes are passed in to the __new__() of MetaClass 
  • the mClass attr 'metaRig' is matched to the registered class 
  • that class is instantiated and returned back to you 

So what???????? Well imagine you do getMetaNodes() on your rig scene that has an mRig node 


 Now mRig is a class object of type 'metaRig' and that is a subclass of Meta so has all the attribute handlers available. Basically that Maya node is now bound to a given class like Pymel does, you do pm.selected() on a transform you get back a pymel.Transform class object, you do the same on a light....etc. Well in the same way MetaClass does the same for any Maya nodes. More importantly by subclassing MetaClass you can bind your own classes up to your own nodes in any system.

So lets quickly look at the metaRig setup in the Red9 unitTests:

#cast the MayaNode to a metaRig object
assert mRig.L_ArmSystem.L_ArmSupport.mNode=='L_ArmSupport'
assert mRig.L_ArmSystem.L_ArmSupport.SUP_IKHandle[0]=='|World_Ctrl|L_Wrist_Ctrl|ikHandle1'

Note here that I can just use dot complete to actually walk the metaRig network. This is because by getting the attribute of type message the code looks at the linked nodes, if they too have the mClass attr they are returned as python metaClass objects too, so you can just keep walking down the tree. This makes finding nodes in complex systems like rigs an absolute doddle.

Part2 -Attribute Handlers:

So above we saw that metaClass gives you the ability to turn any Maya node into a class bound to that node, so what? Well in the rigs case it means that we can get data dead easily. This is because I've also very carefully managed all attribute calls via the MetaClass api. In doing the mRig.L_ArmSystem call above the code first tests the type of attribute, in this case a message, and uses the listConnections call to get back the data.

The attribute handlers in Meta seamlessly deal with getAttr, setAttr and addAttr, in fact addAttr manages all the flags for you, you can even add the attr without telling it the type, I derive it from the value you pass in if I can. Also you can pass ANY node into the MetaClass api, the node doesn't have to take advantage of the factory stuff, you can just use it as an attribute handler if you like. 
Hint: When a node is passed into MetaClass all attributes show on the dot-compete in the script editor ;).

Currently I support:

  • floats 
  • doubles
  • ints
  • bools
  • strings    ( automatically serializes and deserializes to JSON if the value is complex)
  • enums    ( allows you to set the data via the int or string representation )
  • message ( get runs listConnections, returning mClass objects if found, set will automatically connect)
  • doubleArrays (sets the structures up for you when adding)
  • double3
  • float3 

Even better, and here's where it gets fun, if you pass a python dict, or complex structure to a string attr, it's serialized and stored via JSON for you. Here at work we store our zero pose, generated by the
poseSaver, actually on the mRig node itself as a json string. Same way that the SceneReview serializing all the comment data from an internal dict straight to the 'time1' node in Maya. The AttrMap is also doing this when you serializeToNode.

Part3 - The Big One!

 The big one though is this..... any node in Maya that has the mClass attr, that is valid, will give you back the correct class automatically! You don't have to worry about what class to call, what function is in what class and if node==this do that, elif to this.... the node comes back as the correct Python object ready for you without any work. There is a direct correlation between the MayaNode and the class that manages it, like Pymel all the functions you may need, code in the class for that node. It keeps code clean and means that by subclassing you get all functionality for all similar node types for free, and get access to all the core stuff in Meta....which is expanding fast.

I've added a ton of hooks in there recently as I've been working with Josh Burton on the new Morpheus project. These all allow you to sub-class and register new types a lot easier. Most of the code we now write at work is based on Meta, either because it's so easy to get data and attributes back, or because we have many nodes for many reasons, facialRig, supportNodes, exportTags managing systems....

Hope that helps a little?

Have a read of the unitTests and examples folders in the Red9 pack, they're there for a reason and might shed some light on all of this ;)


Friday, 1 February 2013

LockChannlesUI and AttrMaps

Another Vimeo video! This one goes through the LockChannelsUI which is fairly self explanatory hopefully. It also covers the concept of the AttrMap which for riggers is a godsend, a way of storing out the status of every channel in a hierarchy and restoring it when needed. The attrMap can be stored to file OR serialized to a node on the rig itself!