Custom joint type with Maya Python API 1.0 or 2.0


#1

Previously asked here.

I’m looking to subclass Maya’s default joint and hand it a few extra attributes, but I can’t find any suitable class nor example of how to go about it.

I managed to put together a transform like this…

myTransform.py

from maya import OpenMaya
from maya import OpenMayaMPx


class MyNode(OpenMayaMPx.MPxTransform):
    name = "myNode"
    id = OpenMaya.MTypeId(0x87014)
    matrixId = OpenMaya.MTypeId(0x87015)

    @classmethod
    def create(cls):
        return OpenMayaMPx.asMPxPtr(cls())

    @classmethod
    def init(cls):
        numFn = OpenMaya.MFnNumericAttribute()

        cls.myAttr = numFn.create(
            "myAttr", "mya", OpenMaya.MFnNumericData.kDouble, 0.0
        )

        numFn.setKeyable(True)
        numFn.setAffectsWorldSpace(True)

        cls.addAttribute(cls.myAttr)

    @classmethod
    def matrix(cls):
        class _(OpenMayaMPx.MPxTransformationMatrix):
            pass

        return OpenMayaMPx.asMPxPtr(_())


def initializePlugin(mobject):
    mplugin = OpenMayaMPx.MFnPlugin(mobject)
    mplugin.registerTransform(
        MyNode.name,
        MyNode.id,
        MyNode.create,
        MyNode.init,
        MyNode.matrix,
        MyNode.matrixId
    )


def uninitializePlugin(mobject):
    mplugin = OpenMayaMPx.MFnPlugin(mobject)
    mplugin.deregisterNode(MyNode.id)

But how does one make a new joint type? I could settle for a re-implementation of a new joint, starting from MPxTransform as that’s what it looks to be originally subclassed from.


#2

If all you want to do is add attributes, you might just want to make an MDagMessage callbakck to add the attributes: it will be much less complex over than maintaining a completely new class.

The rocking transfomr example in C++ gives a proper example of how to implement a custom transform if you actually want to create custom behaviors; translating it to api 2 is pretty simple. As I said, however, I thnk it’s overkill for most purposes


#3

Thanks @Theodox, in this particular case I’m already maintaining a series of nodes and the joint class is currently the odd one out.

Do you know if I could use that mechanism to make updates to the attributes after the node has been created? My motivation for using a custom node to begin with was because I found myself manually updating old attributes and adding new ones to old scenes and enjoyed the reference-like behaviour of a custom node where I could update a class and both existing and new scenes would follow suite.

Also I would much prefer not to alter the default joint type.


#4

I’d try a two-step solution: a file open callback that looks for nodes with out of date attributes and updates them, and a message callback that adds them as needed.

In either case the big problem is the same: if the spec changes over time, old scenes won’t know what to do. One slight improvement is to make a custom node type for the attribute holder and them connect instances of that to the joints via a message attribute, instead of adding the attribute set to the joints directly. That makes it much easier to manage and version the data.


#5

Yeah, a separate node with attributes connected to each joint is what I’ve got now and it’s working swell. Before that I was creating joints from a common function that added attributes as needed, similar to a callback approach.

Both of these approaches work well, the current approach all the better. But I still manage two nodes for every one joint, and so if there is a way to merge these - like I have with various transform-inherited nodes - then I’d be all the more happy.

My impression so far is that the joint type isn’t exposed by Maya, which is a little unfortunate but the sooner I get confirmation of this the sooner I can move on to greener plains.


#6

For future readers, I’ve gotten confirmation from Cyrille that this is indeed not possible. Instead, one would need to subclass MPxNode or the like and re-implement all of what it means to be a joint. Even though that information likely isn’t readily available; it’d be reverse engineering which defeats the purpose (for me) to append to the existing joint type.