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.

CameraTracker:
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

cheers

Mark

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 

mRig=r9meta.getMetaNodes(cmds.ls(sl=True)[0])[0] 

 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
mRig=r9Meta.MetaClass('RED_Rig')
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 ;)

Mark

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!

 

cheers

Mark

Monday, 21 January 2013

Red9 Studio Pack v1.28 Released - MirrorSetups

Just a quick note to say that I've just updated the download lists to the latest build v1.28. See previous posts about the updates.

I've also added a new MirrorSetup UI for setting up the Mirror Markers and added a Vimeo demo of the setup.

 

 Enjoy!

Mark

Friday, 11 January 2013

SceneRestoreContext context manager for your viewports

Thought I'd breifly go through the SceneRestoreContext manager in the Red9.General module as it's something that came up today at work. So what is it, well it's a context manager that 's designed to store, and restore all your viewport settings including:

  • all viewport display options and shading states(for all 4 modelPanels)
  • playbackOptions including units, times, timeranges and settings 
  • scene units
  • current audio set in the timeline and it's active state
  • current main camera settings (tranforms)
  • cameras active in all the modelPanels 

Basically just about everything there is that makes that current session look as it does. Why?? Well sometimes when you're processing data you want to do things to the scene which you really want to restore afterwards. Lets say you're batching a ton of anim data, opening files, switching cameras etc and at the end of processing you want the scene to be set back to how it was. Now this isn't a scene load, this is a cache of all the main ui element settings.

This can be run in 2 ways, the best is to use it as designed, as a context manager:

import Red9_General as r9Gen
with r9Gen.SceneRestoreContext:
    do your code here

Now anybody who's used context managers in Python will get the syntax here. The 'with' is doing all the work for you. On entering the call it runs the internal __enter__ call, then runs everything inside the tab (your code), then when complete runs the internal __exit__ call. The great thing about context managers is that even if your code bombs, the __exit__ will still get called and the scene restored to it's cached state.

You can of course use it as you want, so you can take an instance of the object, run the store then when you need to, run the restore:

store=r9General.SceneRestoreContext()
store.storeSettings()

do your code here

store.restoreSettings()

it's just a function call at the end of the day and might prove useful to others whilst designing tools. If you find anything that you think this is not catching let me know. There's also an AnimationContext thats used in all the animation tools and a HIKContext for managing the set state of HIK rig nodes.

cheers

Mark

Tuesday, 8 January 2013

StudioPack V1.28

Well after the StudioPack v1.27 release at Christmas there have been a few important bug fixes I've caught in the setups. In the current build there's a bug which prevents the SceneReporter from opening properly, I'd made some last minute changes to MetaData that the unit-tests didn't pickup. Also a few extra unexpected issues in the animation setups which were picked up whilst I was doing the walk through video. These are now patched and I'll push the new build out later this week hopefully.

I've also added a ton of extra wrapping to the Meta Api and Pose libraries which will make it easier for those of you wanting to use meta to expand it for your own purposes. Have to say a big thank you to Josh Burton from CGMonks/Morpheus Kickstarter for all the nagging and pushing he's been doing as it's really helped expand and stabilize the api. This new build has many extra tweaks to the way attrs are handled, particularly enum attrs. I've also done some restructuring which again, is aimed at allowing you more flexibility to inherit and over-load some of the key functionality.

thanks for all the support

Mark

Tuesday, 1 January 2013

Another Video, this one explains the filterHierarchy

 And another video, this one follows on from the AnimationUI demo and takes you through the crucial filterHierarchy control in Tab2. This shows you how to tailor the systems for your rig, how to search for specific nodes in a hierarchy and how to setup the filter priorities list.

One thing I didn't run through was how to tweak the filter once saved by RMB clicking on the newly saved preset and opening up the cfg file itself. You'll notice for example in the Morpheus preset that the name search had regex clamps on the list, these were just manually edited after I'd made filter to ensure that the name pattern search didn't include namespaces and was clamped to the end of the string name.... see regex explanations, here's a great reference:

http://docs.activestate.com/komodo/4.4/regex-intro.html

cheers

 Mark