Update Issue with ObjectData

On 31/01/2013 at 01:14, xxxxxxxx wrote:

User Information:
Cinema 4D Version:   R14 
Platform:   Windows  ;   
Language(s) :

---------
Hey guys,

I trying to do the following:
I got an objectdata generator plugin which takes a spline and generate maybe an extrude nurbs with that spline.
But here special is, that the spline should not be under the generator, it should be the previous or parent.

If I use spline = op->GetPred() it works but the editor does not update correct not until I click in the editor view.
If I use spline = op->GetUp() it does not work, c4d crash.
If I use spline = op->GetDown() all is fine.

Check dirty of spline does not work, but you will see the effect if you toggle xray or change any other data of the generator (color, name...).

#include "c4d.h"  
  
#define ID_PLUGIN_TESTOBJECT 12345678  
  
class TestObject : public ObjectData  
{  
   
  INSTANCEOF(TestObject, ObjectData)  
  
  public:  
      virtual BaseObject* GetVirtualObjects(BaseObject* op, HierarchyHelp* hh);  
  
      static NodeData* Alloc(void) { return gNew TestObject; }  
};  
  
BaseObject* TestObject::GetVirtualObjects(BaseObject* op, HierarchyHelp* hh)  
{  
  BaseObject *spline = op->GetPred();  
  //BaseObject *spline = op->GetUp();  
  //BaseObject *spline = op->GetDown();  
  if (!spline || (spline->GetInfo() & OBJECT_ISSPLINE) != OBJECT_ISSPLINE) return NULL;  
  
  // check cache for validity and check master object for changes  
  Bool dirty = op->CheckCache(hh) || op->IsDirty(DIRTYFLAGS_DATA);  
  
  // check spline for changes - does not work  
  dirty |= spline->IsDirty(DIRTYFLAGS_DATA) || spline->IsDirty(DIRTYFLAGS_MATRIX) || spline->IsDirty(DIRTYFLAGS_CACHE);  
  
  // if no change has been detected, return original cache  
  if (!dirty) return op->GetCache(hh);  
  
  BaseObject *obj = BaseObject::Alloc(Oextrude);  
  BaseObject *splineClone = (BaseObject* ) spline->GetClone(COPYFLAGS_0, NULL);  
  splineClone->InsertUnder(obj);  
  
  return obj;  
}  
  
Bool RegisterTestObject(void)  
{  
  return RegisterObjectPlugin(ID_PLUGIN_TESTOBJECT, "TestObject", OBJECT_GENERATOR, TestObject::Alloc, "", NULL, 0);  
}

On 31/01/2013 at 07:59, xxxxxxxx wrote:

Hi Toni,

With op->GetUp() it crashes because you call spline->GetClone() and both the spline and the generator itself are copied.
To only copy the spline, call spline->GetClone(COPYFLAGS_NO_HIERARCHY, NULL).

Generators aren't modifiers: you can't take a parent or sibling object as input object(s).
A generator object plugin can be registered with the OBJECT_INPUT flag but this will only work in the pipeline of CINEMA if you take the subobject(s) as input.

Also checking the dirty flag works better with C4DAtom::GetDirty():

ULONG dirty = spline->GetDirty(DIRTYFLAGS_DATA|DIRTYFLAGS_MATRIX);
if (dirty==this->dirtyCount)
    return op->GetCache(hh);

dirtyCount is a member of the generator and caches the last dirty count for the comparison.

On 31/01/2013 at 08:18, xxxxxxxx wrote:

Thank you for your replay.
You are right, the op->GetUp() was a silly idea. o.O

I figured out that spline->GetClone() is my problem. If I use a Generator with a Link Attribute (Linked to a spline) and use spline->GetClone(), the same "buggy" update happen:

GetVirtualObjects is called, but not until I click in the 3d view the editor is redrawn.

If I clone the spline manual (rewriting points and tangents) it works better.

Would it be save?

SplineObject* CopySpline(SplineObject *spline)  
{  
  LONG pcnt = spline->GetPointCount();  
  LONG scnt = spline->GetSegmentCount();  
  LONG tcnt = spline->GetTangentCount();  
  
  SplineObject *newSpline = SplineObject::Alloc(pcnt, spline->GetInterpolationType());  
  newSpline->ResizeObject(pcnt, scnt);  
  newSpline->SetData(spline->GetData(), FALSE);  
    
  // Copy Points  
  const Vector *points = spline->GetPointR();  
  Vector *newPoints = newSpline->GetPointW();  
  for (LONG i = 0; i < pcnt; i++)  
  {  
      newPoints[i] = points[i];  
  }  
  
  // Copy Tangents  
  const Tangent *tangents = spline->GetTangentR();  
  Tangent *newTangents = newSpline->GetTangentW();  
  for (LONG i = 0; i < tcnt; i++)  
  {  
      newTangents[i] = tangents[i];  
  }  
  
  const Segment *segment = spline->GetSegmentR();  
  Segment *newSegment = newSpline->GetSegmentW();  
  for (LONG i = 0; i < scnt; i++)  
  {  
      newSegment[i] = segment[i];  
  }  
  newSpline->Message(MSG_UPDATE);  
  
  return newSpline;  
}

On 01/02/2013 at 05:26, xxxxxxxx wrote:

Yes, it's safe if you copy manually all the spline data.