Red9_PoseSaver

Red9_PoseSaver is designed as a generic module for storing and dealing with poses inside Maya. The PoseData object is the base for all of this and is what’s wrapped by the AnimUI and the MetaData.poseCacheLoad() calls.

There’s also a powerful setup for testing a rigs current pose against a previously stored pose file, or you can test poseObjectA==poseObjectB or even poseFileA==poseFileB

This is a new implementation of the PoseSaver core, same file format and ConfigObj but now supports relative pose data handled via a posePointCloud and the snapping core

Note

I use the node short name as the key in the dictionary so ALL NODES must have unique names or you may get unexpected results!

Core Pose Classes

DataMap([filterSettings]) New base class for handling data storage and reloading with intelligence
PoseData([filterSettings]) The PoseData is stored per node inside an internal dict as follows:
PosePointCloud(nodes[, filterSettings, meshes]) PosePointCloud is the technique inside the PoseSaver used to snap the pose into relative space.
PoseCompare(currentPose, referencePose[, ...]) This is aimed at comparing a rigs current pose with a given one, be that a pose file on disc, a pose class object, or even a poseObject against another.
getFolderPoseHandler(posePath)

Check if the given directory contains a poseHandler.py file if so return the filename. PoseHandlers are a way of extending or over-loading the standard behaviour of the poseSaver, see Vimeo for a more detailed explanation.

TODO: have this also accept a pointer to a handler file rather than a direct poseHnadler.py file in each folder. This means we could point a folder to a generic handler inside our presets folder rather than having the code logic in each folder.

class DataMap(filterSettings=None, *args, **kws)

Bases: object

New base class for handling data storage and reloading with intelligence

The idea of the DataMap is to make the node handling part of any system generic. This allows us to use this baseClass to build up things like poseSavers and all we have to worry about is the data save / extraction part, all the node handling and file handling is already done by this class ;)

Note that we’re not passing any data in terms of nodes here, We’ll deal with those in the Save and Load calls.

metaPose

this flag adds in the additional MetaData block for all the matching code and info extraction. True if self.metaRig is filled, self.settings.metaRig=True or self.metaPose=True

filepath
setMetaRig(node)

Master call to bind and set the mRig for the DataMap

Parameters:node – node to set the mRig from or instance of an mRig object
hasFolderOverload()

modified so you can now prefix the poseHandler.py file makes it easier to keep track of in a production environment

getNodesFromFolderConfig(rootNode, mode)

if the poseFolder has a poseHandler.py file use that to return the nodes to use for the pose instead

Parameters:
  • rootNode – rootNode passed to the search poseHandlers poseGetNodesLoad or poseGetNodesSave functions
  • mode – ‘save’ or ‘load’
getNodes(nodes)

get the nodes to process This is designed to allow for specific hooks to be used from user code stored in the pose folder itself.

Parameters:nodes – nodes passed to the filter calls

Note

Update : Aug 2016 Because this calls FilterNode to get the data when useFilter=True it allows for any mRig with internal filterSettings bound to it to dynamically modify the settings on the fly to suit. This is a big update in handling for ProPack to integrate without having to massively restructure

getSkippedAttrs(rootNode=None)

the returned list of attrs from this function will be COMPLETELY ignored by the pose system. They will not be saved or loaded.

Note

Currently only supported under MetaRig

getMaintainedAttrs(nodesToLoad, parentSpaceAttrs)

Attrs returned here will be cached prior to pose load, then restored in-tact afterwards

Parameters:
  • nodesToLoad – nodes that the pose is about to load the data too, this is the already processed nodeList
  • parentSpaceAttrs – attributes we want to be ignored by the load system
buildBlocks_fill(nodes=None)

To Be Overloaded : What capture routines to run in order to build the DataMap up. Note that the self._buildBlock_poseDict(nodes) calls the self._collectNodeData per node as a way of gathering what info to be stored against each node.

buildDataMap(nodes)

build the internal dataMap dict, useful as a separate func so it can be used in the PoseCompare class easily. This is the main internal call for managing the actual pose data for save

Note

this replaces the original pose call self.buildInternalPoseData()

processPoseFile(nodes)

pre-loader function that processes all the nodes and data prior to actually calling the load... why? this is for the poseMixer for speed. This reads the file, matches the nodes to the internal file data and fills up the self.matchedPairs data [(src,dest),(src,dest)]

Note

this replaced the original call self._poseLoad_buildcache()

matchInternalPoseObjects(nodes=None, fromFilter=True)

This is a throw-away and only used in the UI to select for debugging! from a given poseFile return or select the internal stored objects

saveData(nodes, filepath=None, useFilter=True, storeThumbnail=True, force=False)

Generic entry point for the Data Save.

Parameters:
  • nodes – nodes to store the data against OR the rootNode if the filter is active.
  • filepath – posefile to save - if not given the pose is cached on this class instance.
  • useFilter – use the filterSettings or not.
  • storeThumbnail – save a thumbnail or not
  • force – force write the data even if the file is read-only
loadData(nodes, filepath=None, useFilter=True, *args, **kws)

Generic entry point for the Data Load.

Parameters:
  • nodes – if given load the data to only these. If given and filter=True this is the rootNode for the filter.
  • filepath – file to load - if not given the pose is loaded from a cached instance on this class.
  • useFilter – If the pose has an active Filter_Settings block and this is True then use the filter on the destination hierarchy.
class PoseData(filterSettings=None, *args, **kws)

Bases: Red9.core.Red9_PoseSaver.DataMap

The PoseData is stored per node inside an internal dict as follows:

>>> node = '|group|Rig|Body|TestCtr'
>>> poseDict['TestCtr'] 
>>> poseDict['TestCtr']['ID'] = 0   index in the Hierarchy used to build the data up 
>>> poseDict['TestCtr']['longName'] = '|group|Rig|Body|TestCtr' 
>>> poseDict['TestCtr']['attrs']['translateX'] = 0.5 
>>> poseDict['TestCtr']['attrs']['translateY'] = 1.0 
>>> poseDict['TestCtr']['attrs']['translateZ'] = 22 
>>> 
<<<<<<< HEAD
>>> # if we're storing as MetaData we also include:
=======
>>> #if we're storing as MetaData we also include:
>>>>>>> d7ab8a039c4da0838a07bf4a9ec3ad957667b21e
>>> poseDict['TestCtr']['metaData']['metaAttr'] = CTRL_L_Thing    = the attr that wires this node to the MetaSubsystem
>>> poseDict['TestCtr']['metaData']['metaNodeID'] = L_Arm_System  = the metaNode this node is wired to via the above attr

Matching of nodes against this dict is via either the nodeName, nodeIndex (ID) or the metaData block.

New functionality allows you to use the main calls to cache a pose and reload it from this class instance, wraps things up nicely for you:

>>> pose=r9Pose.PoseData()
>>> pose.metaPose=True
>>>
<<<<<<< HEAD
>>> # cache the pose (just don't pass in a filePath)
>>> pose.poseSave(cmds.ls(sl=True))
>>> # reload the cache you just stored
>>> pose.poseLoad(cmds.ls(sl=True))

We can also load in a percentage of a pose by running the PoseData._applyData(percent) as follows:

>>> pose=r9Pose.PoseData()
>>> pose.metaPose=True
>>> pose.filepath='C:/mypose.pose'
>>> 
>>> # processPoseFile does just that, processes and build up the list of data but doesn't apply it
>>> pose.processPoseFile(nodes='myRootNode')
>>> 
>>> # now we can dial in a percentage of the pose, we bind this to a floatSlider in the UI
>>> pose._applyData(percent=20)
======= >>> #cache the pose (just don't pass in a filePath) >>> pose.poseSave(cmds.ls(sl=True)) >>> #reload the cache you just stored >>> pose.poseLoad(cmds.ls(sl=True))