In general, we have followed a design pattern in CAT where functional groups have been separated out into unit pieces. The functional units are :
The controllers in a unit are inter-dependent and cannot be constructed or used in isolation. Apart from a Hub (which is a single bone), there is a central class that holds data common to the unit and provides management functions, called a Data or a Manager class. There is one data class created to manage each unit. These data classes are LimbData
, BoneData
, DigitData
, SpineData
, and TailData
. Each one of these data classes is responsible for the creation and maintenance of its associated node controllers.
Note from the rig layout diagram – BoneData
is somewhat of a special case. BoneData
is the class that provides the transform for an individual limb bone. It is managed by LimbData
, but it is also a manager itself. It manages an array of 1-to-N BoneSegTrans
classes. This is because although the limb is a functional unit made up of many limb bones, each limb bone can also be broken down into segments to provide twisting. The BoneSegTrans
class looks to BoneData
to manage it, and BoneData
looks to LimbData
to manage it.
CATControl
This class is at the root of the rig control structure in CAT. Its job is to provide the common functionality required by all the classes that make up CAT's rig structure, and a method of iterating all the controls that make up a given CAT rig.
Some major functionality provided:
CATNodeControl
: CATControl
The CATNodeControl
class specializes the CATControl
class for the Matrix3 controllers applied to INodes
. This class is the primary workhorse of the CATSystem
. It provides all the functions for managing the rig elements data, and returning values to Max. In general, if 3ds Max calls a function on a CAT element, CATNodeControl
will be the class that implements the function.
Primary tasks:
CATNodeControl
provides a framework for evaluating CAT data to generate a Matrix3.CATNodeControl
also provides the functionality for inheritance, rig stretching, locking, limits, etc.
The structure of the GetValue/SetValue function should also be examined.ArbBones
is essentially an implementation of CATNodeControl
without any element-specific functionality. All ArbBone
management happens on CATNodeControl
CATNodeControl
is deleted, it is its own responsibility to re-parent any CATNodeControl
children it may have to its parent. This is to allow (for example) removing spine links, and have the hub at the end of the spine re-parented to whatever link is now at the end of the spine. The same concept applies to all CAT nodes, when it is deleted, any children will be reparented to maintain the hierarchy structure.CATNodeControl
contains no animation data. Therefore, all they keyframing methods (defined by Animatable) need to passed through to the Layer controller which handles the animation data.CATClipValue
This class is the base of the layer system. A layer is essentially a list controller – it contains an array of generic Max controllers, and it merges their values according to the rules of the layer. The rules are specified by the type of layer, this data is stored on the CATClipRoot
LayerDesc classes.
Originally, we had an implementation of CATClipValue
for every value type in Max – float, position, rotation, point3 etc. However, over time we have removed almost all these layer types, and now simply provide implementations of float (CATClipFloat
) for scalar values, and Matrix3 (CATClipMatrix3
) for transform values.
The basic list behavior functionality is implemented in CATClipValue
. Here you can find the code for adding/removing layers, cloning, maintaining weights etc. The implementation's main job is to calculate the value of the appropriate type. CATClipFloat
is fairly simple, but CATClipMatrix3
contains a lot of calculation to generate its values and handle things like inheritance correctly.