Skip to content

Month: July 2017

Pilot Season – Day 12 – Intro to OpenMaya2

Day 12 of the stream, originally intended to be focused on developing an FK IK switch Callback turned into a necessary introduction to dealing with transform attributes in OpenMaya2

While not necessarily what I was expecting to stream about I don’t regret going off this tangent.

Day 11 stream about callbacks is a prerequisite watch to understand this one, unless you only want to hear about OM2 quirks and how-to, in which case this stands on its own.

We start by designing the callback we want to implement starting from its boundaries, then do our shopping list, and finally we introduce all kind of OpenMaya2 related notions and quirks to make sure transforms and attributes come in correctly.

We don’t have a callback yet by the end, but we now have all the Maya API bits covered to develop one next stream.

Similarly to the previous episode (second half of day 11) it seems useful to commit a cleaned up transcription of the final script from the stream to make it available here. You will find it at the end of the page

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
from maya.api import OpenMaya as om2
 
def iterSelection():
    """
    generator style iterator over current Maya active selection
    :return: [MObject) an MObject for each item in the selection
    """
    sel = om2.MGlobal.getActiveSelectionList()
    for i in xrange(sel.length()):
        yield sel.getDependNode(i)
 
 
_MAYA_MATRIX_ATTRIBUTE_NAME = 'worldMatrix'
def wMtxFromMob(node_mob):
    """
    finds the world matrix attribute and returns its value in matrix form
    :param node_mob: [MObject] the node to get the world matrix from 
    :return: [MMatrix] the matrix value of the world transform on the argument node
    """
    if not node_mob.hasFn(om2.MFn.kDagNode):
        return None
 
    mfn_dag = om2.MFnDagNode(node_mob)
    wMtxPlug = mfn_dag.findPlug(_MAYA_MATRIX_ATTRIBUTE_NAME, False)
    elPlug = wMtxPlug.elementByLogicalIndex(0)
 
    node_mob_attr = elPlug.asMObject()
    mfn_mtxData = om2.MFnMatrixData(node_mob_attr)
    return mfn_mtxData.matrix()
 
 
_MAYA_OUTPUT_ATTRIBUTE_NAME = 'output'
def getMRotFromNodeOutput(node_mob, rotOrder = om2.MEulerRotation.kXYZ):
    """
    finds the angular output of the argument node and returns it
     as a Euler rotation where that angle is the X element
    :param node_mob: [MObject] the node to get the output port from
    :param rotOrder: [int] the factory constant for the desired rotation order
                            the returned Euler rotation should be set to
    :return: [MEulerRotation] the Euler rotation composition where the
                                angular output on the argument node is the X value
    """
    mfn_dep = om2.MFnDependencyNode(node_mob)
    angle = om2.MAngle(0.0)
    if node_mob.hasFn(om2.MFn.kAnimBlend) and mfn_dep.hasAttribute(_MAYA_OUTPUT_ATTRIBUTE_NAME):
        plug = mfn_dep.findPlug(_MAYA_OUTPUT_ATTRIBUTE_NAME, False)
        angle = plug.asMAngle()
 
    rot = om2.MEulerRotation(angle.asRadians(), 0.0, 0.0, rotOrder)
    return rot
 
 
mobTuple = tuple(iterSelection())
if len(mobTuple) >= 2:
    if mobTuple[0] is not None:
        srtWMtx = om2.MTransformationMatrix(wMtxFromMob(mobTuple[0]))
        srtWMtx.rotateBy(getMRotFromNodeOutput(mobTuple[1]), om2.MSpace.kWorld)