0

I am writing a deformer node which takes as inputs the worldMatrix and visibility of cylinders. The cylinders are organised into groups, and this structure is mirrored on my deformer. I have a 2D array, organised by groups with cylinders for children, and each array is a compound attribute, so I can control an entire groups visibility and individual holes.

This is the attribute setup:

aVisibility = nAttr.create("Visibility", "vis", MFnNumericData::kBoolean);
CHECK_MSTATUS(addAttribute(aVisibility));

aTransform = mAttr.create("Transform", "trans", MFnMatrixAttribute::kDouble);
nAttr.setDisconnectBehavior(MFnAttribute::DisconnectBehavior::kDelete);
CHECK_MSTATUS(addAttribute(aTransform));

aCylinders = cAttr.create("Cylinders", "cylinders");
cAttr.addChild(aTransform);
cAttr.addChild(aVisibility);
cAttr.setArray(true);
CHECK_MSTATUS(addAttribute(aCylinders));

aGroupVisibility = nAttr.create("GroupVisibility", "grpVis", MFnNumericData::kBoolean, true);
nAttr.setDisconnectBehavior(MFnAttribute::DisconnectBehavior::kDelete);
CHECK_MSTATUS(addAttribute(aGroupVisibility));

aGroups = cAttr.create("Groups", "grps");
cAttr.addChild(aGroupVisibility);
cAttr.addChild(aGroupHoles);
cAttr.setArray(true);
CHECK_MSTATUS(addAttribute(aGroups));

I have written python scripts to add a cylinder to this, which will figure out which group it should belong to, add a new entry and connect the visibility and worldMatrix up.

I have a couple of problems with this setup. First, deleting a cylinder acts as I would expect since I have defined disconnectBehaviour to delete the instance in the array. However deleting a group leaves a disconnected attribute at the top level of the hierarchy which I have to clean up manually.

Second, while deleting works quite well, it would be really handy if duplication could be used as well. So if somebody duplicated a cylinder, an array entry was created and the necessary attributes connected. Is this possible? So far people using the deformer have naturally attempted this, and I have had to make them use a script.

jhod91
  • 3
  • 2

1 Answers1

0

It seems you have some missing parts to the array deletion according to the documentation. Taken from the API docs:

If the kDelete behaviour is set on an array attribute which is a compound, that will only handle the case where the connection is to the parent attribute not to its children. So breaking a connection to an element of the parent (e.g. node.parent[3]) would cause that element to be removed, but breaking a connection to a child (e.g. node.parent[3].child) would leave the element intact, even if it was the last such connection.

To have the parent array element deleted when the last connection to a child is broken, you must set the kDelete behaviour on the connectable children as well.

On the line where you create your matrix attribute, the following line should be this:

aTransform = mAttr.create("Transform", "trans", MFnMatrixAttribute::kDouble);
mAttr.setDisconnectBehavior(MFnAttribute::DisconnectBehavior::kDelete);

Not this:

aTransform = mAttr.create("Transform", "trans", MFnMatrixAttribute::kDouble);
nAttr.setDisconnectBehavior(MFnAttribute::DisconnectBehavior::kDelete);

Notice the nAttr.setDiconnectBehavior should be mAttr, otherwise you are applying it to the first visibility attribute.

So according to the documentation, you need to set the disconnect behavior for both the child and the array attribute so when the last child attribute is disconnected, it will delete the parent array element. So this is what I think it should look like:

aVisibility = nAttr.create("Visibility", "vis", MFnNumericData::kBoolean);
nAttr.setDisconnectBehavior(MFnAttribute::DisconnectBehavior::kDelete);
CHECK_MSTATUS(addAttribute(aVisibility));

aTransform = mAttr.create("Transform", "trans", MFnMatrixAttribute::kDouble);
mAttr.setDisconnectBehavior(MFnAttribute::DisconnectBehavior::kDelete);
CHECK_MSTATUS(addAttribute(aTransform));

aCylinders = cAttr.create("Cylinders", "cylinders");
cAttr.addChild(aTransform);
cAttr.addChild(aVisibility);
cAttr.setArray(true);
cAttr.setDisconnectBehavior(MFnAttribute::DisconnectBehavior::kDelete);
CHECK_MSTATUS(addAttribute(aCylinders));

aGroupVisibility = nAttr.create("GroupVisibility", "grpVis", MFnNumericData::kBoolean, true);
nAttr.setDisconnectBehavior(MFnAttribute::DisconnectBehavior::kDelete);
CHECK_MSTATUS(addAttribute(aGroupVisibility));

aGroups = cAttr.create("Groups", "grps");
cAttr.addChild(aGroupVisibility);
cAttr.addChild(aGroupHoles);
cAttr.setArray(true);
cAttr.setDisconnectBehavior(MFnAttribute::DisconnectBehavior::kDelete);
CHECK_MSTATUS(addAttribute(aGroups));

I see a missing attribute "aGroupHoles" in this code snippet so you have to make sure you set the disconnected behavior accordingly there as well.

Your second problem with the duplication. I would say the best thing to do is have a script that your users call that handles this properly.

Community
  • 1
  • 1
scottiedoo
  • 309
  • 2
  • 10
  • Thanks @scottiedoo, stupid copy and paste error at the top. I've also added the DisconnectBehaviors you suggested, unfortuantely my problem is still there. When deleting a group directly, the instance of the array is left there at the same index with no connections. However if I delete the cylinders first, emptying the child array, and then the group, the instance deletes normally. I thought that aGroupVisibility would trigger the DisconnectBehavior but it hasn't seemed to. My guess is that because the parent deletion doesn't trigger the child deletion, the element persists. – jhod91 Apr 21 '16 at 08:58
  • Sounds like a bug in Maya that it doesn't see a child of compound group that is a compound array being deleted. I guess you will have to have a script for this too for deleting so it does the proper clean up. Sorry but I am out of ideas, short of restructuring your attributes if it's that important. – scottiedoo Apr 21 '16 at 16:05
  • no worries, I've got python scripts doing the clean-up, I just figured I'd ask to see if I was doing anything wrong/there was a better way. I may get in touch with Autodesk – jhod91 Apr 22 '16 at 10:26