Hello,
I am working on a plugin that uses an In/Exclude list that the user will fill with Effectors and then I will use the new position provided from the Effectors to do other things.
My issue comes in when I initially drop an Effector into the In/Exclude while in R25. The initial values that I get from the Effectors are different than the ones I get from the next time it runs on a refresh.
This isn't an issue in other versions of Cinema because the code runs again immediately with the expected Effector values, meanwhile in R25 it doesn't run a second time until something causes a Cinema refresh which would cause a visual problem in my full plugin because the Effector values are not correct.
Running same circumstance in R23
I've only run into this issue in R25 with this particular In/Exclude for Effectors, in R25 with an In/Exclude for BaseObjects I haven't had this refresh issue. In R20 through R24 I haven't had this issue with any In/Exclude.
Below is the complete code trimmed down with the problem with the points shown via prints.
#define ID_EFFECTORTEST 1055750
#include "c4d.h"
#include "c4d_gui.h"
#include "c4d_baseeffectordata.h"
#include "customgui_inexclude.h"
class EffectorTestClass : public ObjectData
{
INSTANCEOF(EffectorTestClass, ObjectData)
public:
virtual Bool Init(GeListNode* node);
virtual Bool Message(GeListNode* node, Int32 type, void* data);
virtual SplineObject* GetContour(BaseObject* op, BaseDocument* doc, Float lod, BaseThread* bt);
virtual void CheckDirty(BaseObject *op, BaseDocument *doc);
static NodeData* Alloc() { return NewObjClear(EffectorTestClass); }
virtual Bool GetDDescription(GeListNode *node, Description *description, DESCFLAGS_DESC &flags);
virtual void RunEffectors(BaseObject *op, BaseDocument *doc, PolygonObject *poly);
maxon::BaseArray<BaseObject*> compareDirtyObj;
maxon::BaseArray<UInt32> dirtyNumber;
maxon::Result<void> resultVoid;
maxon::Result<Int32> resultInt;
maxon::Result<Vector> resultVector;
maxon::Result<BaseObject*> resultBaseObject;
UInt32 opDirtyCount = 0;
};
enum Controls
{
idMainTab = 100000,
idEffectorList,
};
Bool EffectorTestClass::Message(GeListNode* node, Int32 type, void* data)
{
return SUPER::Message(node, type, data);
}
Bool EffectorTestClass::GetDDescription(GeListNode *node, Description *description, DESCFLAGS_DESC &flags)
{
BaseContainer *datainstance;
const DescID *singleid;
if (!description->LoadDescription(node->GetType()))
{
}
datainstance = ((BaseList2D*)node)->GetDataInstance();
if (!datainstance)
return FALSE;
singleid = description->GetSingleDescID();
DescID cid;
DescID DescMainTabGroup = DescLevel(idMainTab, DTYPE_GROUP, 0);
if (!singleid || DescMainTabGroup.IsPartOf(*singleid, NULL))
{
BaseContainer bc;
bc = GetCustomDataTypeDefault(DTYPE_GROUP);
bc.SetString(DESC_NAME, "Effector Test"_s);
bc.SetInt32(DESC_COLUMNS, 1);
bc.SetInt32(DESC_DEFAULT, 1);
bc.SetBool(DESC_SCALEH, TRUE);
if (!description->SetParameter(DescMainTabGroup, bc, DescLevel(ID_EFFECTORTEST)))
return TRUE;
}
cid = DescLevel(idEffectorList, CUSTOMDATATYPE_INEXCLUDE_LIST, 0);
if (!singleid || cid.IsPartOf(*singleid, NULL))
{
BaseContainer bc;
bc = GetCustomDataTypeDefault(CUSTOMGUI_INEXCLUDE_LIST);
bc.SetString(DESC_NAME, "Effectors"_s);
BaseContainer acceptedObjects;
acceptedObjects.InsData(Obaseeffector, String());
acceptedObjects.InsData(Oweighteffector, String());
bc.SetInt32(IN_EXCLUDE_FLAG_INIT_STATE, 3);
bc.SetInt32(IN_EXCLUDE_FLAG_NUM_FLAGS, 2);
bc.SetInt32(IN_EXCLUDE_FLAG_IMAGE_01_ON, 300000131);
bc.SetInt32(IN_EXCLUDE_FLAG_IMAGE_01_OFF, 300000130);
bc.SetContainer(DESC_ACCEPT, acceptedObjects);
bc.SetBool(IN_EXCLUDE_FLAG_SEND_SELCHANGE_MSG, true);
bc.SetInt32(IN_EXCLUDE_FLAG_BIG_MODE_SIZE, 150);
if (!description->SetParameter(cid, bc, DescMainTabGroup))
return TRUE;
}
flags |= DESCFLAGS_DESC::LOADED | DESCFLAGS_DESC::RECURSIONLOCK;
return SUPER::GetDDescription(node, description, flags);
}
// Check if the child object, In/Exclude objects have been changed
void EffectorTestClass::CheckDirty(BaseObject *op, BaseDocument *doc)
{
if (doc == nullptr || op == nullptr)
return;
Bool setDirty = FALSE;
BaseContainer docdata = doc->GetData(DOCUMENTSETTINGS::GENERAL);
if (docdata == BaseContainer())
return;
BaseContainer *dataInstance = op->GetDataInstance();
maxon::BaseArray<BaseObject*> objArray;
if (op->GetDown() != nullptr)
resultBaseObject = objArray.Append(op->GetDown());
GeData tempdata;
dataInstance->GetParameter(idEffectorList, tempdata);
InExcludeData* data = static_cast<InExcludeData*>(tempdata.GetCustomDataType(CUSTOMDATATYPE_INEXCLUDE_LIST));
if (data != nullptr)
{
Int32 flags = 0;
for (Int32 objIndex = 0; objIndex < data->GetObjectCount(); objIndex++)
{
BaseObject* object = static_cast<BaseObject*>(data->ObjectFromIndex(doc, objIndex));
if (object != nullptr)
{
if (object->GetDeformMode())
{
flags = data->GetFlags(doc, object);
if ((flags & 1) == 1)
{
resultBaseObject = objArray.Append(object);
}
}
}
}
}
if (Int32(objArray.GetCount()) != Int32(compareDirtyObj.GetCount()))
{
setDirty = TRUE;
dirtyNumber.Reset();
}
if (Int32(dirtyNumber.GetCount()) != Int32(objArray.GetCount()))
{
for (Int32 objIndex = Int32(dirtyNumber.GetCount()); objIndex < Int32(objArray.GetCount()); objIndex++)
resultInt = dirtyNumber.Append(0);
}
compareDirtyObj.Reset();
resultVoid = compareDirtyObj.CopyFrom(objArray);
for (Int32 index = 0; index < Int32(objArray.GetCount()); index++)
{
if (dirtyNumber[index] != objArray[index]->GetDirty(DIRTYFLAGS::DATA | DIRTYFLAGS::MATRIX | DIRTYFLAGS::CHILDREN | DIRTYFLAGS::CACHE))
setDirty = TRUE;
dirtyNumber[index] = objArray[index]->GetDirty(DIRTYFLAGS::DATA | DIRTYFLAGS::MATRIX | DIRTYFLAGS::CHILDREN | DIRTYFLAGS::CACHE);
}
if (setDirty == TRUE || opDirtyCount != op->GetDirty(DIRTYFLAGS::MATRIX | DIRTYFLAGS::DATA))
{
opDirtyCount = op->GetDirty(DIRTYFLAGS::MATRIX | DIRTYFLAGS::DATA);
op->SetDirty(DIRTYFLAGS::DATA | DIRTYFLAGS::CACHE);
}
}
SplineObject* EffectorTestClass::GetContour(BaseObject* op, BaseDocument* doc, Float lod, BaseThread* bt)
{
PolygonObject *testObj = (PolygonObject*)op->GetDown();
if (testObj)
{
RunEffectors(op, doc, testObj);
}
opDirtyCount = op->GetDirty(DIRTYFLAGS::MATRIX | DIRTYFLAGS::DATA);
SplineObject * returnSpline = SplineObject::Alloc(0, SPLINETYPE::LINEAR);
return returnSpline;
}
Bool EffectorTestClass::Init(GeListNode* node)
{
opDirtyCount = 0;
return true;
}
void EffectorTestClass::RunEffectors(BaseObject *op, BaseDocument *doc, PolygonObject *poly)
{
BaseContainer *dataInstance = op->GetDataInstance();
maxon::BaseArray<Vector> originalCenterPoint;
const CPolygon *polyArray = poly->GetPolygonR();
if (polyArray == nullptr)
{
return;
}
Matrix objMx = poly->GetMg();
BaseObject *obj = (BaseObject*)Get();
BaseTag * motag = obj->GetTag(ID_MOTAGDATA);
if (motag == nullptr)
motag = obj->MakeTag(ID_MOTAGDATA);
if (motag == nullptr)
{
return;
}
BaseTag * polyObjMocacheTag = obj->GetTag(ID_MOBAKETAG);
GetMoDataMessage modataMsg = GetMoDataMessage();
modataMsg.index = 0;
if (polyObjMocacheTag)
{
polyObjMocacheTag->Message(MSG_GET_MODATA, &modataMsg);
}
BaseTag *objTag = obj->GetTag(ID_MOTAGDATA);
if (objTag)
objTag->Message(MSG_GET_MODATA, &modataMsg);
if (!modataMsg.modata)
{
if (!motag->Message(MSG_GET_MODATA, &modataMsg) || !modataMsg.modata)
{
return;
}
}
Float startingTimeA = GeGetMilliSeconds();
MoData *md = modataMsg.modata;
if (md)
{
maxon::BaseArray<Vector> centerPointArray;
maxon::BaseArray< maxon::BaseArray<Vector> > polyPointArray;
maxon::BaseArray<Vector> originalCenterArray;
md->GetAutoLock();
MDArray<Matrix> matrixArray;
maxon::BaseArray<Matrix> originalMatrixArray;
Int32 polygonCount = poly->GetPolygonCount();
Int32 pointCount = poly->GetPointCount();
const CPolygon* polygons = poly->GetPolygonR();
const Vector *posArray = poly->GetPointR();
// Get the center points of the various polygons
for (Int32 polyIndex = 0; polyIndex < polygonCount; polyIndex++)
{
Vector centerPointOfPolygon = Vector(0);
if (polygons[polyIndex].c == polygons[polyIndex].d)
{
centerPointOfPolygon += posArray[polygons[polyIndex].a];
centerPointOfPolygon += posArray[polygons[polyIndex].b];
centerPointOfPolygon += posArray[polygons[polyIndex].c];
centerPointOfPolygon = (centerPointOfPolygon / 3.0);
}
else
{
centerPointOfPolygon += posArray[polygons[polyIndex].a];
centerPointOfPolygon += posArray[polygons[polyIndex].b];
centerPointOfPolygon += posArray[polygons[polyIndex].c];
centerPointOfPolygon += posArray[polygons[polyIndex].d];
centerPointOfPolygon = (centerPointOfPolygon / 4.0);
}
centerPointOfPolygon = Vector(polyIndex * 10, polyIndex * 10, polyIndex * 10);
resultVector = originalCenterPoint.Append(centerPointOfPolygon);
resultVector = centerPointArray.Append(centerPointOfPolygon);
}
md->SetCount(Int32(centerPointArray.GetCount()));
matrixArray = md->GetMatrixArray(MODATA_MATRIX);
MDArray<Vector> setMtxColorArray = md->GetVectorArray(MODATA_COLOR);
MDArray<Vector> setMtxColorArra2y = md->GetVectorArray(MODATA_COLOR);
dataInstance = op->GetDataInstance();
const CustomDataType * effectorsraw = dataInstance->GetCustomDataType(idEffectorList, CUSTOMDATATYPE_INEXCLUDE_LIST);
InExcludeData * effectors = nullptr;
if (effectorsraw)
effectors = (InExcludeData*)effectorsraw;
resultVoid = originalMatrixArray.Resize(Int32(centerPointArray.GetCount()));
// Generate the matrices
for (Int32 centerIndex = 0; centerIndex < Int32(centerPointArray.GetCount()); centerIndex++)
{
Vector normal = CalcFaceNormal(posArray, polyArray[centerIndex]);
Vector upVector = Vector(0, 1, 0);
normal = normal;
normal.Normalize();
if (1.0 - abs(Dot(normal, upVector)) < .003)
{
upVector = Vector(0, 0, -1);
}
Vector z = normal;
z.Normalize();
Vector temp = Cross(upVector, z);
Vector y = Cross(z, temp);
y.Normalize();
Vector x = Cross(y, z);
x.Normalize();
matrixArray[centerIndex] = Matrix(centerPointArray[centerIndex], x, y, z);
}
// Runs through the effectors
if (effectors)
{
Effector_PassData emsg = Effector_PassData();
emsg.op = op;
emsg.md = md;
emsg.weight = 1.0;
emsg.thread = nullptr;
Int32 flags = 0;
for (Int i = 0; i < effectors->GetObjectCount(); i++)
{
BaseObject * e = (BaseObject*)effectors->ObjectFromIndex(doc, i);
if (!e)
continue;
if (!e->GetDeformMode())
continue;
flags = effectors->GetFlags(doc, e);
if (e != nullptr && e->GetDeformMode() == true && (flags & 1) == 1)
{
e->Message(MSG_EXECUTE_EFFECTOR, &emsg);
}
}
}
MDArray<Matrix> itemsMtxArray = md->GetMatrixArray(MODATA_MATRIX);
Int32 matrixItemCnt = Int32(md->GetCount());
ApplicationOutput("New run");
for (Int32 centerIndex = 0; centerIndex < matrixItemCnt; centerIndex++)
ApplicationOutput("Effector pos " + String::VectorToString(itemsMtxArray[centerIndex].off));
}
return;
}
Bool RegisterEffectorTest(Bool hideplugin)
{
return RegisterObjectPlugin(ID_EFFECTORTEST, "Effector Move"_s, OBJECT_GENERATOR | OBJECT_ISSPLINE | OBJECT_INPUT, EffectorTestClass::Alloc, "OEffectorTest"_s, AutoBitmap("circle.tif"_s), 0);
}
I am confused what the difference between R23 and R25 could be that is responsible for the latest version not to work the same way or is it purely coincidental that my R23 version worked?
Any help would be greatly appreciated.
John Terenece