Hello,
in my plugin, I support Fields. I have a FIELDLIST
element in my .res
file, and I can get the FieldList
custom datatype, et cetera.
But there are some things I really don't know how to handle:
1. Dirtyness
I need to track dirtyness of all Field objects in the list, so I can determine when to rebuild my plugin object's cache. FieldList::GetDirty()
seems to catch only changes that were made to the list, not to any of the stuff in the list. I found that the IsDirty()
functions often report dirtyness when actually nothing has changed, so I am using the GetDirty()
function of each Field object, then store the dirty checksums and later compare if the checksums I get from the Field objects to see if they have changed.
This seems to work ok. However, it's quit a lot of code required, just for tracking the dirtyness:
// Check for dirty fields
GeData geFieldData;
if (op->GetParameter(MYOBJECT_FIELDS_LIST, geFieldData, DESCFLAGS_GET::NONE))
{
// Get FieldList
CustomDataType* const fieldData = geFieldData.GetCustomDataType(CUSTOMDATATYPE_FIELDLIST);
FieldList* const fieldList = static_cast<FieldList*>(fieldData);
if (fieldList && fieldList->HasContent())
{
// Dirty fieldList
_currentDirtyChecksum_fieldList = fieldList->GetDirty(doc);
needsEvaluation |= _currentDirtyChecksum_fieldList != _compareDirtyChecksum_fieldList;
// Dirty field objects
GeListHead *listHead = fieldList->GetLayersRoot();
if (listHead)
{
_currentDirtyChecksum_fieldLayers = 0;
_currentDirtyChecksum_fieldObjects = 0;
for (FieldLayer *layer = static_cast<FieldLayer*>(listHead->GetFirst()); layer; layer = IterateNextFieldLayer(layer))
{
// Layer node (in list)
_currentDirtyChecksum_fieldLayers += layer->GetDirty(DIRTYFLAGS::DATA);
GePrint(layer->GetName());
// Actual field object
const FieldLayerLink layerLink = layer->GetLinkedObject(doc);
BaseObject *fieldObject = static_cast<BaseObject*>(layerLink._object);
if (fieldObject)
{
_currentDirtyChecksum_fieldObjects += fieldObject->GetDirty(DIRTYFLAGS::CACHE|DIRTYFLAGS::DATA|DIRTYFLAGS::MATRIX);
}
}
needsEvaluation |= _currentDirtyChecksum_fieldLayers != _compareDirtyChecksum_fieldLayers;
needsEvaluation |= _currentDirtyChecksum_fieldObjects != _compareDirtyChecksum_fieldObjects;
}
}
}
_currentDirtyChecksum_fieldObjects
, _currentDirtyChecksum_fieldLayers
, _compareDirtyChecksum_fieldLayers
, and _compareDirtyChecksum_fieldObjects
are members of my NodeData
. The _compare*
checksums are later updated with the values from the _current*
checksums.
2. FieldList contents
There are the functions FieldList::HasContent()
and FieldList::GetCount()
. Why is this:
- Removing Field objects from the
FieldList
correctly decreases the return value ofGetCount()
, and, after removing the last Field object from the list, makesHasContent()
returnfalse
. - Deleting Field objects that are linked in the
FieldList
from the document does not decrease the the return value ofGetCount()
andHasContent()
always returnstrue
.
That means, if the user deletes linked Field objects in the Object Manager, my plugin object is permanently broken. It behaves as if there still were Field objects to take into account. And the user has no chance of repairing it, because the FieldList
appears empty to the user.
I know this behaviour is consistent with the InExcludeList
, which also maintains zombie BaseLinks. But I never understood the use of this. I also tried iterating the list and removing all zombie elements by deleting the list item if GetLinkedObject()
does not return a valid pointer, but unfortunately that would also remove folders in the FieldList
.
MoGraph seems to handle it well. If I delete a Field object that is linked in an effector object, the effector will show full effect, even though there should be a zombie link in the FieldList
. What does MoGraph do to handle this so robustly?
It really is a pity that there's not a single example in the SDK (not in the GitHub repo either) that uses a FieldList
.
Thanks for any help!
Cheers,
Frank