Last Updated: 08.19.2020

Common Flags

There's some general flags to be aware of:

  • asMeta | Most queries that can be have the asMeta kw which returns the data as meta nodes

Name Tagging

One of the things that is tedious beyond belief is naming all the little things created in a coherent manner. We got tired of doing this and so decided to do something about it. This system utilized the NameFactory which resides in cgmMeta. Some bits about this:

  • In order to do this, we have something we call name tags that are tagged to any object
  • These tags can be strings, messages, or whatever
  • Objects generate a name dict from their own data and that of their parents
  • Some name tags can be inheritted
  • Most often inheritance is from parent to child
  • In the case of an un-type tagged group, it will inherit from it's child
  • Some tags check against a settings file for short hand names for tags ? for example joint to jnt
  • Our current tags are as follows: cgmDirection, cgmDirectionModifier, cgmPosition, cgmName, cgmType, cgmTypeModifier


This is our root metaClass which almost all other cgmMetaClasses are descendants of. It itself is a subclass of r9Meta.MetaClass and thus inherits all functions added to the core Red9 metaclass

  • Superclass | r9Meta.MetaClass
  • Location | cgmc.core.cgm_Meta.cgmNode


  • node | string | Node to initialize
  • name | string | Name for the node
  • nodeType | string | type of node to create if it doesn't exist
  • setClass | bool | whether to set the mClass attribute on initialization

What are the differences between a cgmMeta.cgmNode and a r9Meta.MetaClass

  • Many added functions
  • msgList handling
  • connectChild/Children/Parent nodes - we wanted a different connection type than the one red9 used. Ours is objChild.msgHook >> objHolder.msgAttr. If memory serves, red9s is objChild.msgAttr >> objHolder.msgAttr.
  • Component mode ability - ability to say metaClass a vertice or ep
  • Message handling in general - we allow for message like storage of attributes and not just nodes
  • Access to the insanity of the NameFactory and all the wonders therein.


isAttrKeyed() | ...

  • parameters :

    • attr string (None) | Attribute to query ('tx' for example)
  • returns : status bool

  • relates to : ATTR.is_keyed

isAttrConnected() | ...

  • parameters :

    • attr string (None) | Attribute to query ('tx' for example)
  • returns : status bool

  • relates to : ATTR.is_keyed

  • doStore | ATTR.store_info | Supported: message,doubleArray,json dicts and much more
  • copyAttrTo | ATTR.copy_to | Copy attributes from one object to another as well as other options. If the attribute already exists, it'll copy the values. If it doesn't, it'll make it. If it needs to convert, it can. It will not make toast
  • getMayaAttr | ATTR.get
  • setMayaAttr | ATTR.set
  • getMayaAttrString | "{0}.{1}".format(getattr(NAMES,nameCall)(self.mNode), attr)
  • getEnumValueString | Get the string value of an enum | ATTR.get_enumValueString
  • getAttrs | mc.listAttr
  • doRemove | Remove an attribute
  • resetAttrs | Reset all or filtered attributes
  • verifyAttrDict | Verify a dictionary of attributes by type
  • doOverrideColor | RIGGING.override_color
  • doConnectIn | Wiring call inbound
  • doConnectOut | Wiring call outbound
mLoc = cgmMeta.asMeta(mc.spaceLocator()[0])
mLoc2 = cgmMeta.asMeta(mc.spaceLocator()[0])



  • uiPrompt_rename | Provides ui prompt to rename a node and renames it if OK.
  • getNameShort | short name
  • getNameLong | long name
  • getNameBase | shortest name option stripped of all pomp and circumstance
  • asAttrString | Returns name with an arg attr as 'Node.attr'
  • getNameMatches | Find name matches for a given object. report arg if you want a report
  • getReferencePrefix | ...
  • doName | Name a given node based on cgmNameTags
  • doGetNameDictame | Get a dict of the name tags
  • doTagAndName | Apply a dict of name tags and then name the node
  • getNameAlias | Get name alias for ui functions or other stuff we do
  • doCopyNameTagsFromObject | Grab name tags from another node


Super class functions we overload

  • __setMessageAttr__ | Overload for red9's message handling to follow ours
  • addAttr | Added initialValue kw as well as few other items
  • connectChildNode | Replacing Mark's connect child with our own which connects to .message connections.
  • connectParentNode | Replacing Mark's connect child with our own which connects to .message connections.
  • connectChildrenNodes | Replacing Mark's connect child with our own which connects to .message connections.
  • __repr__ | "(node: '{0}' | mClass: {1} | class: {2})"


  • p_referencePrefix | ( getReferencePrefix ) - get the reference prefix
  • p_nameBase | clean name string
  • p_nameLong | node long name
  • p_nameShort | node short name
  • p_parent | get/set parent of an object (set only currently on cgmObject)


  • getMayaType | VALID.get_mayaType
  • getPositionOutPlug | Look for an outplug on a given node
  • getMessage | This maybe odd to some, but we treat traditional nodes as regular message connections. However, sometimes, you want a message like connection to an attribute. To do this, we devised a method of creating a compaptble attr on the object to recieve the message, connecting the attribute you want to connect to that attribute and then when you call an attribute as getMessage, if it is not a message attr it tries to trace back that connection to an attribute. simple MUST be True by default
  • getMessageAsMeta | ... but return asMeta


  • getParent | ...
  • getSiblings | ...
  • getComponent | Only if this is a component node
  • isComponent | bool check
  • getComponents | By arg type


  • getPosition | TRANS.position_get
  • doDuplicate | Node duplication with some options like breaking connections
  • getDag | Get the dag of a node if this node isn't one


Very specialized stuff or tech we do.


This is our answer to the frustration with how multiMessage attrs work in maya when you need lists to be intact.

The following should work for msgList or datList. A msgList assumes node connections. A datList can be strings or whatever kind of data you want.

  • x_connect | Wire
  • x_get | Query
  • x_append | ...
  • x_index | Get index of arg if in list
  • x_remove | By index
  • x_purge | Purge the datList from the node which means deleting all the sequential attributes
  • x_clean | Remove empty entries in the series and reconnect
  • x_exists | Is it there?
  • getSequentialAttrDict | Get a sequential attr dict. Our attr should be listed without the tail '_' ex: {0: u'back_to_back_0', 1: u'back_to_back_1'}
#>>msgList ====================================================================================
#Let's look at the concept of the msgList
mi_catcherObj = cgmMeta.cgmObject(name = 'msgListCather')

#First we're gonna make some objects to deal with, say 5
md_msgListObjs = {}
ml_msgListObjs = []
for i in range(5):
    try:mObj= cgmMeta.cgmObject('msgListObj_%i'%i)
    except:mObj= cgmMeta.cgmObject(name = 'msgListObj_%i'%i)
    md_msgListObjs[i] = mObj

#Connect the first two objects, you can pass metaclass or string objects
ml_msgListObjs[0].connectBack#what do you know, we connected back to our holder we can also dance a little with that...
ml_msgListObjs[0].connectBack.msgAttr_0.connectBack.msgAttr_1#The mind truly spins....:)

#Let's query it
mi_catcherObj.msgList_get('msgAttr')#Query our list, it's going to default to do it as meta

#Say we wanted just the objlist

#We can also do a getMessage call which offers a few more options
mi_catcherObj.msgList_getMessage('msgAttr',longNames = True)

#Appending is supported
mi_catcherObj.msgList_get('msgAttr',False) #What do you know, we have the new on there...

#Indexing is supported
#As is checking if we have a msgList on an attr name

#Let's remove the first
mi_catcherObj.msgList_get('msgAttr',False) #We Removed the first

#Let's store em all
#Let's delete number 2....
mi_catcherObj.msgList_get('msgAttr',asMeta=False,cull = False)#That entry is empty now...When cull is off, on by default
#What if we want to clean this list without the empty
#And we have a clean list again...

#Say we wanna purge this data...
mi_catcherObj.msgList_purge('msgAttr')#Our attrs are gone... so sad....


(self, module = None,  func = '', *args,**kws)

Function to call from a given module a function by string name with args and kws.

The general idea is to call any function with the node as it's first arg.


Create a locator at a node or component's position.


Message treatment

#>>message Treatment =========================================================================
#We have made several changes to r9's stuff in how we do messages, it is however compatible with r9's stuff
#One of our calls to store info is doStore
#First we're gonna make a catcher node
mi_catchMeObj = cgmMeta.cgmObject(name = 'catchMe')
mi_catcherObj = cgmMeta.cgmObject(name = 'msgCather')

#One of our calls to store info is doStore
mi_catcherObj.doStore('objNoMessage',mi_catchMeObj.mNode,overideMessageCheck = True)#It's gonna just store a string, no message....
mi_catcherObj.doStore('objNoMessage',mi_catchMeObj.mNode,overideMessageCheck = False)#Now it's a message...woot!
#So maya can do that, what if you wanted to do something neater like say, store an attribute
mi_catcherObj.doStore('objTX',"%s.tx"%mi_catchMeObj.mNode)#It's gonna just store a string, no message....
mi_catchMeObj.tx = 4#our attribute changed. That's because, this storage method stores on a compatible attribute format
#That's great and all, but we were talking about messages...
mi_catcherObj.getMessage('objTX')# we get the attribute, neato...
mi_catcherObj.getMessageAsMeta('objTX')# we get the attribute, neato...cgmAttr for the win
#implementing attr setup to msgLists is on the ToDO list

Component Use

One of the areas, where we differ is with component use. We can wrap cv's,vertices, etc.

#>>Component use ==============================================================================
#We'll make a shphere and buffer that...
l_sphereReturn = mc.sphere(nsp  = 4, name = 'MySphere')
mi_sphere = cgmMeta.cgmNode(l_sphereReturn[0])#We'll meta the sphere object
mi_sphere.mNode#Just like an mNode, but what if we wanna instance a component...
mi_cv = cgmMeta.cgmNode("[3][0]"%mi_sphere.mNode)#metaNode a cv
mi_cv.mNode#We get the shape back
mi_cv.getComponent()#We get the component
mi_sphere.isComponent()'s a sphere
mi_sphere.getComponents('cv')#List of cv's
mi_sphere.getPosition()#Get our position,arg is world space or not, default is worldspace(True)
mi_cv.getPosition()#Get the position of the cv
mi_cv.getTransform()#Ger the transform of the component


We've added some properties to our metaclass for easy call/set ability.

#>>Properties =================================================================================
mi_sphere.p_nameBase#name string along
mi_sphere.p_nameLong#long name form
mi_sphere.p_nameShort#short name form
mi_sphere.p_referencePrefix#Gonna be false as we're not referenced
mi_sphere.p_parent#returns our parent, on cgmObject, you can set as well, we'll get more into it there


#>>Other Calls ================================================================================
mi_cv.getMayaType()#Because maya's type return thing isn't so hot....
mi_sphere.doDuplicate()#its gonna give us a duplicate, but only a null?....
mi_dup = mi_sphere.doDuplicate(parentOnly=False)#Now it works

mi_loc = mi_sphere.doLoc()#We can loc items with the same maker cgmLocinator uses
mi_cvLoc = mi_cv.doLoc()#We can loc components too...

#We're gonna add an enum to look at something...
mi_sphere.addAttr('testEnum',attrType = 'enum')
mi_sphere.testEnum#nice, but what if we want as a string

mi_loc.returnPositionOutPlug()#This is a wip one but it works for most necessary things, handy for nodal work


If the object has a dag, this is what we generally use

  • Superclass | MetaClass|cgmNode
  • Location | cgmc.core.cgm_Meta.cgmObject


  • node | string | Node to initialize
  • name | string | Name for the node
  • nodeType | string | type of node to create if it doesn't exist
  • setClass | bool | whether to set the mClass attribute on initialization


dagLock() | For locking/unlocking nodes.

  • parameters :

    • state bool (True)
    • ignore list (None) | Don't do these attributes
    • visibility bool (True)
    • keyable bool (False)
  • returns : None

isVisible() | If this node is visible.

  • parameters :

    • checkShapes bool (False)
  • returns : status bool


  • getConstraintsTo | Get constraints to this dag
  • getConstraintsFrom | Get constraints from this dag
  • getConstrainingObjects | What's driving this
    • select | bool | Select result
  • getConstraintsByDrivingObject | Connection walking
  • isConstrainedBy | Am I constrained by the arg


  • p_parent | get/set parent of an object (set only currently on cgmObject)
  • p_position | get/set
  • p_positionEuclid | get/set
  • p_orient | get/set
  • p_rotateAxis | get/set
  • p_rotatePivot | get/set
  • p_scalePivot | get/set


  • getPositionOutPlug | Get an out plug for a given node. as the ability to autoLoc as well for mNodes that don't have outPlugs
  • getDeformers | Get connected deformers
    • deformerTypes | What kind of deformes you want 'all', list args acceptable as well


  • getParent | ...
  • setParent | ...
  • getParents | ...
  • getSiblings | ...
  • getDescendents|getAllChildren | ...
  • getChildren | ...
  • getShapes | ...
  • getListPathTo | Get the list path from one node to another in a given heirarchy


  • isParentTo | bool
  • isChildTo | bool


  • doCopyPivot | RIGGING.copy_pivot | ....
  • doMatchTransform | RIGGING.match_transform | ....
  • doGroup | General dag grouping
    • maintain | bool | Maintain heirarchal place
    • parentTo | bool | Parent this to the new group or not
    • asMeta | bool | ...
    • typeModifier | bool | Tags the group name with a modifier and connects to the node as [typeModifier]Group
    • setClass | bool | Set mClass on creation if asMeta
  • doCreateAt | Create another object at this one
    • create | string | null,joint,locator, etc
    • copyAttrs | list | List of attributes to copy. When we use it's usually for a cgmNameTag or something
    • asMeta | bool | ...
#>>Parenting ====================================================================================
#First we're gonna make some objects to deal with, say 5
ml_cgmObjects = []
for i in range(5):
    mObj= cgmMeta.cgmObject(mc.joint(p = [0,0,2*i],name = 'generatedCGMObject_%i'%i))

#Neat,now we have a few joints to play with...let's play
ml_cgmObjects[1].p_parent = False #We're gonna parent the idx 1 joint to the world by passing it false

for mObj in ml_cgmObjects:mObj.p_parent = False #Let's parent them all to the world
for i,mObj in enumerate(ml_cgmObjects[1:]):mObj.p_parent = ml_cgmObjects[i] #Parent em back

#What if we wanted to parent idx 2 and 3 both to 1?
ml_cgmObjects[2].p_parent = ml_cgmObjects[0]#We can pass the mClass
ml_cgmObjects[2].tx = 2#just to be a little clearer

ml_cgmObjects[4].p_parent = ml_cgmObjects[1].mNode#We can pass the string mNode
ml_cgmObjects[1].tx = -2 #and a little more clear
ml_cgmObjects[4].tx = 0 #and a little more clear

ml_cgmObjects[4].p_parent #returns just the parent
ml_cgmObjects[4].getParent(asMeta = 1) #what if we want as a parent. the property uses this command with the default asMeta of False
ml_cgmObjects[4].getParent(asMeta = 1).p_nameShort #daisy chain the calls

#>>Family ====================================================================================
ml_cgmObjects[4].getAllParents()#we can get all the parents of an object as well as the imediate
ml_cgmObjects[4].getAllParents(fullPath = True)#We can get full paths
ml_cgmObjects[4].getAllParents(asMeta = 1)#We can get those as meta too

ml_cgmObjects[0].getChildren()#We can get immediate children
ml_cgmObjects[0].getChildren(asMeta = True)#as meta or full path too

ml_cgmObjects[0].getAllChildren()#We can get all dag children
ml_cgmObjects[0].getAllChildren(asMeta = True)#as meta or full path too

ml_cgmObjects[0].getShapes()# shapes, let's try something with shapes

mi_sphere = cgmMeta.cgmObject(mc.sphere()[0]) #let's wrap a sphere
mi_sphere.getShapes() #Get some shapes
mi_sphere.getShapes(asMeta = 1) #as meta too

#What about some other relative checks...
ml_cgmObjects[1].getSiblings() #What is a sibling? A sibling is a definition of our own...
#It is an object at the same heirarchal level as another object of matching type to our source
ml_cgmObjects[1].getSiblings(asMeta = 1) #Can do the asMeta call as well

ml_cgmObjects[1].getFamilyDict()#Another way to get a few bits of data...

ml_cgmObjects[4].isChildOf(ml_cgmObjects[0]) #We can check up the dag tree for a logic check..
ml_cgmObjects[4].isChildOf(ml_cgmObjects[2]) #This one is not a child of that joint

ml_cgmObjects[0].isParentOf(ml_cgmObjects[1]) #Can check the other relationship as well

ml_cgmObjects[4].getListPathTo(ml_cgmObjects[0])#Another way to get some data
ml_cgmObjects[0].getListPathTo(ml_cgmObjects[4])#front or back

#>>Name Stuff ====================================================================================
#Let's start by tagging our root joint
ml_cgmObjects[0].addAttr('cgmName','testing') #This is our main tag
ml_cgmObjects[0].doName()#Our object has been renamed with this name tag and it autotyped

#Let's add some direction tags to idx 1/2
ml_cgmObjects[1].addAttr('cgmDirection','left') #Direction tag of left
ml_cgmObjects[2].addAttr('cgmDirection','right') #...and right

for idx in [1,2]:ml_cgmObjects[idx].doName()
#Now our two joints are prefixed with their directions, note they have inherited their parent's name, note the children are not named...

for idx in [1,2]:ml_cgmObjects[idx].doName(nameChildren = True)# Neat, now the children are named
for idx in [1,2]:ml_cgmObjects[idx].doName(fastIterate = False, nameChildren = True)
#The most thorough name tag is turning off fastIterate, it is slower so we don't use very often. If you're just doing manual stuff if's fine.
#If you're running large processes, you'll wanna avoid

#Another thing nametags can be are messages, let's try that.
mi_locToName = cgmMeta.cgmObject(mc.spaceLocator()[0])
mi_locToName.addAttr('cgmName',ml_cgmObjects[0].mNode,attrType = 'messageSimple')#we're gonna store the first joint to the locators, cgmName tag
mi_locToName.doName() #You'll see it's taken the name of the name linked object and named with that

#So what's going on with this stuff? When objects are named, they generate a name dictionary and build a name from that...
ml_cgmObjects[4].getNameDict() #Even though this object has none of these cgmNameTag attributes, it nonethless, inherits those names
ml_cgmObjects[4].parent = False
ml_cgmObjects[4].getNameDict()#Now the only thing the name dict contains is it's type which all objects have
ml_cgmObjects[4].parent = ml_cgmObjects[1]#Parent back for now

#Let's add another tag to our root
ml_cgmObjects[0].doName(nameChildren = True) there are some tags which aren't inherited, type modifiers are not but types are
ml_cgmObjects[0].doName(nameChildren = True)#Positons are inheritable

#>>Rigging functions ==========================================================================
ml_cgmObjects[1].doGroup(maintain = True)#You'll see we get a new group maintaining our objects's position
ml_cgmObjects[1].doGroup(maintain = False)#This will not maintain our heirarchy and generate a new group

#Copy pivot this is for objects with shapes
mi_copyPivotToMe = cgmMeta.cgmObject(mc.sphere(name = 'copyPivotToMe')[0])
mi_copyPivotFromMe = cgmMeta.cgmObject(mc.sphere(name = 'copyPivotFromMe')[0])
mi_copyPivotFromMe.ty = 5
mi_copyPivotToMe.doCopyPivot(mi_copyPivotFromMe) at it's pivot

#Let's start by contrainting a couple of joints
mc.pointConstraint(ml_cgmObjects[4].mNode,ml_cgmObjects[3].mNode,maintainOffset = False)
mc.orientConstraint(ml_cgmObjects[2].mNode,ml_cgmObjects[3].mNode,maintainOffset = False)

#Great, now what....
ml_cgmObjects[3].getConstraintsTo()#Get the constraint to
ml_cgmObjects[3].getConstraintsTo(asMeta = True)

ml_cgmObjects[4].getConstraintsFrom()#Get the constraint from
ml_cgmObjects[4].getConstraintsFrom(asMeta = True)

ml_cgmObjects[3].isConstrainedBy(ml_cgmObjects[2])#Get a constraint from one object to another


  • doSnapTo | TRANS.snap | ....
  • doAim | TRANS.aim | ....
  • doAimAtPoint | TRANS.aim_atPoint | ....


  • setPosition | TRANS.position_set | ....
  • getPositionAsEuclid | TRANS.getPosition | with asEuclid on


  • getOrient | TRANS.orient_get | ....
  • setOrient | TRANS.orient_set | ....
  • getRotateAxis | TRANS.rotateAxis_get | ....
  • setRotateAxis | TRANS.rotateAxis_set | ....


  • getScaleLossy | TRANS.scaleLossy_get | ....


  • getRotatePivot | TRANS.rotatePivot_get | ....
  • setRotatePivot | TRANS.rotatePivot_set | ....
  • getScalePivot | TRANS.scalePivot_get | ....
  • setScalePivot | TRANS.scalePivot_set | ....
  • p_rotatePivot | ....
  • p_scalePivot | ....
  • doPivotsRecenter | TRANS.pivots_recenter | ....
  • doPivotsZeroTransform | TRANS.pivots_zeroTransform | ....
  • getBBSize | POS.get_bb_size | ....
  • getBBCenter | POS.get_bb_center | ....


  • getAxisVector | TRANS.vector_byAxis | ....
  • createVectorLine | TRANS.create_vectorCurveFromObj | ....
  • getPositionByAxisDistance | TRANS.position_getByAxisDistance | ....
  • getWorldMatrix | TRANS.worldMatrix | ....
  • p_worldMatrix | ....

Transform Data

  • getTransformDirection | TRANS.transformDirection | ....
  • getTransformPoint | TRANS.transformPoint | ....
  • getTransformInverseDirection | TRANS.transformInverseDirection | ....
  • getTransformInversePoint | TRANS.transformInversePoint | ....
  • xxx | | ....


General animation control metaclass

  • Superclass | MetaClass.cgmNode.cgmObject
  • Location | cgmc.core.cgm_Meta.cgmControl


  • node | string | Node to initialize
  • name | string | Name for the node


  • _verifyMirrorable | Make sure the node is wired with r9Meta mirror attributes
  • isMirrorable | ...
  • doMirrorMe | ...
    • mode | string | red9 pass through
  • doPushToMirrorObject | ...
    • mode | string | red9 pass through


  • _setControlGroupLocks | Sets locks on control groups masterGroup, zeroGroup
    • lock | bool | state of the lock
    • constraintGroup | bool | whether to do a constraint group as well. Can probably depreciate this
  • controller_get | Gets a maya controller tag for this node and wires them to one another


  • _isAimable | If control has aim attributes
  • _verifyAimable | Ensures the object has aiming attributes SNAP.verify_aimAttrs
  • doAim | Aim it
    • target | node to aim at


  • Superclass | MetaClass.cgmNode
  • Location | cgmc.core.cgm_Meta.cgmObjectSet


  • setName | string | Name for the set
  • setType | bool |
  • qssState | bool | If this node should be a qss set
  • value | (x) | Value to set on call
  • nameOnCall | bool | If on, will add generate a uiPrompt to set name on creation

Set Types

These are our own thing to help organize sets.

  • Animation
  • layout
  • modeling
  • td
  • fx
  • lighting


  • isQss | ...
  • makeQss | Set the qss flag state
  • getSetType | ...
  • doSetType | ...
    • setType | What type to set to
  • getMetaList | Only works with string data
  • getList | ...
  • doSetList | Reset the list with the objects provided in objectList arg
  • log | Print a report of the objectSet dat to the script editor
  • deleteSet | Completely delete set


  • contains|doesContain | Returns if contains obj arg
  • getParents | Get parent Set
  • extend | ...
  • append|add | ...
  • addSelected | Add object or attribute if channelbox selection active
  • remove|removeObj | ...
  • removeSelected | ...
  • purge | ...
  • copy | Copy the set to a new one
  • select | Select set contents if possible
  • selectSelf | Select actual set node


  • key | Ket set contents
  • reset | reset ...
  • deleteKey | Selects then cutKey(*a,**kw) pass through
  • deleteCurrentKey | ...


  • value | getList, doSetList, deleteSet