I'm writing a C++ plugin using the Maya API.
I have a custom data-type, that I want to expose to all Dag nodes as an extension-attribute.
I've searched the documentation, the DevKit examples, in forums and just by google search. I couldn't find any example of how to do that (I'm starting to think that what I'm trying to do is not possible or not supported by Maya).
There are examples on how to add dynamic-attributes, but that is not what I'm after.
I've been able to expose it as a dynamic-attribute, but I then need to add it to every node that is being queried/edited, if it doesn't exist, and this gets complicated when supporting undo (even using MDGModifier).
According to the Maya documentations, there should be 3 ways to add extension-attributes:
1. Using 'addExtensios' MEL command
2. Using MNodeClass::addExtensionAttribute(<attr>)
3. Using MDGModifier::addExtensionAttribute(<node-class>,<attr>)
I put the code that adds the extension-attribute in the plugin's -initialization function, and a corresponding code for deleting it in the plugin's uninitialize function.
I am able to use the MEL option with:
MGlobal::executeCommand("addExtension -nt dagNode -sn S -ln L -dt T;");
(where: 'S' and 'L' are the attr-name, and 'T' is my datat-type's name)
The attribute even shows-up in the attribute-editor of all dag-nodes inthe 'Extended' section.
But then when I try to get the value of it later, it fails.
The code I'm using to get the data is taken from the blindComlexData example.
Within a MItSelectionList itereator, I do (satus-handling code excluded for clarity):
MObject node;
iter.getDependNode(node);
MFnDependencyNode fnNode;
fnNode.setObject(node);
plug = fnNode.findPlug(S, false);
MObject sData;
plug.getValue(sData);
MFnPluginData fnData(sData);
data = (MyMPx*)fnData.constData();
(Where: 'S' is the short-name of the attribute, and MyMPx is my custom-data class)
The last-line fails, when it tries to case the data back to my custom-class.
When using the other two options, I can't even initialize the plugin if I use status-checking code - and there are absolutly no examples about how to do that anywhere (not that I could find, and I think I can search pretty well).
I've tried everythin I can think of, and then some guess-work.. (a LOT actually..)
I first have to define/create an attribute, of-course, before I pass it along to any of the functions that would add it as an extension attribute.
I actually found out that it doesn't matter what kind of attribute I created, using MFnTypedAttribute - even creating a built-in attribute-type, causes the same kind of failure:
MFnTypedAttribute fnAttr;
MObject attr = fnAttr.create(L, S, MFnStringData::kString);
BTW, if I add this right after: MFnData::Type t = fnAttr.attrType();
Then 't' is 'kInvalid', which I find odd - can't I even create a normal typed-attribute properly?
If I do this, though, then 't' is 'kString':
MFnTypedAttribute fnAttr;
MString defaultString("");
MFnStringData defaultTextData;
MObject defaultTextAttr = defaultTextData.create(defaultString);
MObject attr = fnAttr.create(L, S, MFnStringData::kString, defaultTextAttr, &status);
MFnData::Type t = fnAttr.attrType();
Using MNodeClass, I've tried doing:
MTypeId mDagNodeTypeID(MFn::kDagNode);
const MNodeClass mnDagNodeClass(mDagNodeTypeID);
status = mnDagNodeClass.addExtensionAttribute(attr);
CHECK_MSTATUS_AND_RETURN_IT(status);
The status-check fails and returns immediately.
Using MDGModifier, I've tried doing:
MTypeId mDagNodeTypeID(MFn::kDagNode);
const MNodeClass mnDagNodeClass(mDagNodeTypeID);
MDGModifier mDgMod;
status = mDgMod.addExtensionAttribute(mnDagNodeClass, attr);
CHECK_MSTATUS_AND_RETURN_IT(status);
The status-check fails and returns immediately.
So it can't even be the way I try to create my custom-typed attribute.
But just for completion-sake, here is what I've tried:
MFnTypedAttribute fnAttr;
MObject attr = fnAttr.create(L, S, MyMPx::id);
MFnData::Type t = fnAttr.attrType();
Doesn't work...
't' is 'kInvalid', and trying to add the attribute later as an extension-attribute (using either MNodeType or MDGModifier), fails the next status-check.
I then though, maybe it needs a default-value, so I first try:
MObject attr = fnAttr.create(L, S, MyMPx::id, MObject::kNullObj, &status);
CHECK_MSTATUS_AND_RETURN_IT(status);
MFnData::Type t = fnAttr.attrType();
Status-check passes, but 't' is still 'kInavalid', and again, can't add it as an extension-attribute later.
Lastly then tried:
MFnPluginData fnData;
MObject defaultData = fnData.create(MyMPx::id);
MTypeId tPluginData(MFnData::kPlugin);
MObject attr = fnAttr.create(L, S, tPluginData, defaultData, &status);
CHECK_MSTATUS_AND_RETURN_IT(status);
MFnData::Type t = fnAttr.attrType();
...
At this point, I am out of creative ideas...
Any help would be appreciated!