On 03/03/2013 at 12:08, xxxxxxxx wrote:
User Information:
Cinema 4D Version: RXX
Platform: Windows ; Mac OSX ;
Language(s) : C++ ;
---------
After getting fed up trying to understand checking, getting, and setting dirty flags and counts, I decided to look at one of the SDK examples. It had a curious array to store each flag and dirty count for each flag. Now it makes perfect sense. This might not be news to some of you but I figured that I would put this code and the ideas out here for other developers who might struggle with dirty states.
So, basically, you have a set of bit flags to set or get the dirty state of something. The return value of GetDirty() is a running count that increments every time the dirty state changes - it is NOT the flags that are 'set'. You query on the state changes that you need to check using the DIRTYFLAGS_xxxx bitmask.
What I've found is that it is best to have Bool class members to track whether a change of interest occurred and ULONG class members to store the last dirty counts. The ULONG variables are set to 0 in Init(). If you need to do different things on, say, change of an object's data then when a change of the matrix occurs, you need to split it up and track each one separately. Nothing special code-wise but this is a good example of the 'micro-managing' that might be required when you only want to allocate or initialize data structures on certain specific conditions.
Here, I am showing an example of CheckDirty() for a deformer object plugin. For the linked object, its Bool dirty checks are set to TRUE when the object is dropped into the link to kickstart initialization of data structures. For both objects, the Bool dirty checks are set to TRUE on MSG_MULTI_DOCUMENTIMPORTED.
// ObjectData.CheckDirty
//*---------------------------------------------------------------------------*
void CollisionDeformerObj::CheckDirty(BaseObject* op, BaseDocument* doc)
//*---------------------------------------------------------------------------*
{
// Assume that nothing has changed
deformedDirtyMatrix = FALSE;
deformedDirtyData = FALSE;
colliderDirtyMatrix = FALSE;
colliderDirtyData = FALSE;
compositeDirty = FALSE;
if (!doc) return;
if (!op) return;
// Check for Collider object
BaseObject* dop = op->GetUp();
// - No object being deformed, get out!
if (!dop) return;
// - Get Data Container
BaseContainer* bc = op->GetDataInstance();
if (!bc) return;
// - Get linked object
BaseObject* lop = (BaseObject* )bc->GetLink(COLLISIONDEFORMER_OBJECT, doc, Obase);
// - No need to check dirty flags if no collider
if (!lop) return;
// Check Deformed object
ULONG dirty = dop->GetDirty(DIRTYFLAGS_MATRIX);
if (dirty != dmDirty)
{
dmDirty = dirty;
// For collision bounds checks
deformedDirtyMatrix = TRUE;
}
dirty = dop->GetDirty(DIRTYFLAGS_DATA);
if (dirty != ddDirty)
{
ddDirty = dirty;
// A data change constitutes a need to update deformedOp
deformedDirtyData = TRUE;
// A data change constitutes a need to recreate Mass-Spring System
needInitMassSpring = TRUE;
}
// Check Collider object
dirty = lop->GetDirty(DIRTYFLAGS_MATRIX);
if (dirty != cmDirty)
{
cmDirty = dirty;
// For collision bounds checks
colliderDirtyMatrix = TRUE;
}
dirty = lop->GetDirty(DIRTYFLAGS_DATA);
if (dirty != cdDirty)
{
cdDirty = dirty;
// A data change constitutes a need to update colliderOp
colliderDirtyData = TRUE;
}
// For faster bounds-check requirement determination
compositeDirty = (colliderDirtyData || deformedDirtyData || colliderDirtyMatrix || deformedDirtyMatrix);
// Data or matrix changes constitute a need to ModifyObject()
if (compositeDirty) op->SetDirty(DIRTYFLAGS_DATA);
}