THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 28/11/2002 at 09:26, xxxxxxxx wrote:
Hey, it's you guys forcing me to always mess up my SDK folder with stupid tests... :-)
Please forget ATOMOBJECT_PREVIEW (it's from another forum post showing how to use the bitmap button for previews). Here's a pristine version of RoundedTube.cpp with the spline code in Init() :
/////////////////////////////////////////////////////////////
// CINEMA SDK : OBJECT PLUGINS //
/////////////////////////////////////////////////////////////
// VERSION : CINEMA 4D //
/////////////////////////////////////////////////////////////
// (c) 1989-2002 MAXON Computer GmbH, all rights reserved //
/////////////////////////////////////////////////////////////
// generator object example (with no input objects)
#include "c4d.h"
#include "c4d_symbols.h"
#include "Oroundedtube.h"
class RoundedTube : public ObjectData
{
public:
String test;
virtual Bool Init (GeListNode *node);
virtual Bool Read (GeListNode *node, HyperFile *hf, LONG level);
virtual Bool Write (GeListNode *node, HyperFile *hf);
virtual void GetDimension (PluginObject *op, Vector *mp, Vector *rad);
virtual Bool Draw (PluginObject *op, LONG type, BaseDraw *bd, BaseDrawHelp *bh);
virtual LONG DetectHandle (PluginObject *op, BaseDraw *bd, LONG x, LONG y, LONG qualifier);
virtual Bool MoveHandle (PluginObject *op, PluginObject *undo, const Matrix &tm, LONG hit_id, LONG qualifier);
virtual BaseObject* GetVirtualObjects(PluginObject *op, HierarchyHelp *hh);
virtual Bool Message(GeListNode *node, LONG type, void *t_data);
static NodeData *Alloc(void) { return gNew RoundedTube; }
};
Bool RoundedTube::Message(GeListNode *node, LONG type, void *t_data)
{
if (type==MSG_DESCRIPTION_VALIDATE)
{
BaseContainer *data = ((BaseObject* )node)->GetDataInstance();
CutReal(*data,TUBEOBJECT_IRADX,0.0,data->GetReal(TUBEOBJECT_RAD));
CutReal(*data,TUBEOBJECT_ROUNDRAD,0.0,data->GetReal(TUBEOBJECT_IRADX));
}
else if (type==MSG_MENUPREPARE)
{
((BaseObject* )node)->SetPhong(TRUE,FALSE,0.0);
}
return TRUE;
}
void RoundedTube::GetDimension(PluginObject *op, Vector *mp, Vector *rad)
{
BaseContainer *data = op->GetDataInstance();
Real rado,radx,rady;
rado = data->GetReal(TUBEOBJECT_RAD);
radx = data->GetReal(TUBEOBJECT_IRADX);
rady = data->GetReal(TUBEOBJECT_IRADY);
*mp =0.0;
switch (data->GetLong(PRIM_AXIS))
{
case 0: case 1: *rad=Vector(rady,rado+radx,rado+radx); break;
case 2: case 3: *rad=Vector(rado+radx,rady,rado+radx); break;
case 4: case 5: *rad=Vector(rado+radx,rado+radx,rady); break;
}
}
static BaseObject *GenerateLathe(Vector *cpadr, LONG cpcnt, LONG sub, BaseThread *bt)
{
PolygonObject *op=NULL;
UVWStruct us;
UVWTag *tag =NULL;
Vector *padr=NULL;
Polygon *vadr=NULL;
LONG i,j,pcnt,vcnt,a,b,c,d;
Real len=0.0,sn,cs,v1,v2,*uvadr=NULL;
pcnt = cpcnt*sub;
vcnt = cpcnt*sub;
op=PolygonObject::Alloc(pcnt,vcnt);
if (!op) goto Error;
tag = (UVWTag* )op->MakeVariableTag(Tuvw,vcnt);
if (!tag) goto Error;
padr=op->GetPoint();
vadr=op->GetPolygon();
uvadr = (Real* ) GeAlloc(sizeof(Real)*(cpcnt+1));
if (!uvadr) goto Error;
uvadr[0]=0.0;
for (i=0; i<cpcnt; i++)
{
uvadr[i] = len;
len+=Len(cpadr[(i+1)%cpcnt]-cpadr[i]);
}
if (len>0.0) len=1.0/len;
for (i=0; i<cpcnt; i++)
uvadr[i]*=len;
uvadr[cpcnt]=1.0;
vcnt=0;
for (i=0; i<sub; i++)
{
SinCos(pi2*Real(i)/Real(sub),sn,cs);
v1=Real(i )/Real(sub);
v2=Real(i+1)/Real(sub);
if (bt && bt->TestBreak()) goto Error;
for (j=0; j<cpcnt; j++)
{
a = cpcnt*i+j;
padr[a] = Vector(cpadr[j].x*cs,cpadr[j].y,cpadr[j].x*sn);
if (i<sub)
{
b = cpcnt*i +((j+1)%cpcnt);
c = cpcnt*((i+1)%sub)+((j+1)%cpcnt);
d = cpcnt*((i+1)%sub)+j;
us = UVWStruct(Vector(v1,1.0-uvadr[j],0.0),Vector(v1,1.0-uvadr[j+1],0.0),Vector(v2,1.0-uvadr[j+1],0.0),Vector(v2,1.0-uvadr[j],0.0));
tag->Set(vcnt,us);
vadr[vcnt++] = Polygon(a,b,c,d);
}
}
}
GeFree(uvadr);
op->Message(MSG_UPDATE);
op->SetPhong(TRUE,TRUE,Rad(80.0));
return op;
Error:
GeFree(uvadr);
blDelete(op);
return NULL;
}
static LineObject *GenerateIsoLathe(Vector *cpadr, LONG cpcnt, LONG sub)
{
LONG i;
LineObject *op = LineObject::Alloc(cpcnt*4+sub*4,8); if (!op) return NULL;
Segment *sadr = op->GetSegment();
Vector *padr=op->GetPoint();
for (i=0; i<4; i++)
{
sadr[i].cnt = cpcnt;
sadr[i].closed = TRUE;
}
for (i=0; i<4; i++)
{
sadr[4+i].cnt = sub;
sadr[4+i].closed = TRUE;
}
Real sn,cs;
LONG j;
for (i=0; i<4; i++)
{
SinCos(Real(i)*pi05,sn,cs);
for (j=0; j<cpcnt; j++)
padr[i*cpcnt+j] = Vector(cpadr[j].x*cs,cpadr[j].y,cpadr[j].x*sn);
}
for (i=0; i<sub; i++)
{
SinCos(Real(i)/sub*pi2,sn,cs);
for (j=0; j<4; j++)
padr[4*cpcnt+j*sub+i] = Vector(cpadr[cpcnt/4*j].x*cs,cpadr[cpcnt/4*j].y,cpadr[cpcnt/4*j].x*sn);
}
op->Message(MSG_UPDATE);
return op;
}
Bool RoundedTube::Init(GeListNode *node)
{
test = String("Test");
BaseObject *op = (BaseObject* )node;
BaseContainer *data = op->GetDataInstance();
AutoAlloc<SplineData> falloffspline;
if ( !falloffspline ) return FALSE;
falloffspline->InsertKnot( 0.0, 0.0 );
falloffspline->InsertKnot( 1.0, 1.0 );
data->SetData(TUBEOBJECT_SEG + 42, GeData(CUSTOMDATATYPE_SPLINE, falloffspline) );
data->SetReal(TUBEOBJECT_RAD,200.0);
data->SetReal(TUBEOBJECT_IRADX,50.0);
data->SetReal(TUBEOBJECT_IRADY,50.0);
data->SetLong(TUBEOBJECT_SUB,1);
data->SetLong(TUBEOBJECT_ROUNDSUB,8);
data->SetReal(TUBEOBJECT_ROUNDRAD,10.0);
data->SetLong(TUBEOBJECT_SEG,36);
data->SetLong(PRIM_AXIS,PRIM_AXIS_YP);
return TRUE;
}
Bool RoundedTube::Read(GeListNode *node, HyperFile *hf, LONG level)
{
if (level>=0)
{
hf->ReadString(&test);
}
return TRUE;
}
Bool RoundedTube::Write(GeListNode *node, HyperFile *hf)
{
hf->WriteString(test);
return TRUE;
}
static void SetAxis(BaseObject *obj, LONG axis)
{
PointObject *op = ToPoint(obj);
if (axis==2) return;
Vector *padr = op->GetPoint();
LONG pcnt = op->GetPointCount(),i;
switch (axis)
{
case 0: // +X
for (i=0; i<pcnt; i++)
padr[i] = Vector(padr[i].y,-padr[i].x,padr[i].z);
break;
case 1: // -X
for (i=0; i<pcnt; i++)
padr[i] = Vector(-padr[i].y,padr[i].x,padr[i].z);
break;
case 3: // -Y
for (i=0; i<pcnt; i++)
padr[i] = Vector(-padr[i].x,-padr[i].y,padr[i].z);
break;
case 4: // +Z
for (i=0; i<pcnt; i++)
padr[i] = Vector(padr[i].x,-padr[i].z,padr[i].y);
break;
case 5: // -Z
for (i=0; i<pcnt; i++)
padr[i] = Vector(padr[i].x,padr[i].z,-padr[i].y);
break;
}
op->Message(MSG_UPDATE);
}
BaseObject *RoundedTube::GetVirtualObjects(PluginObject *op, HierarchyHelp *hh)
{
LineObject *lop = NULL;
BaseObject *ret = NULL;
Bool dirty = op->CheckCache(hh) || op->IsDirty(DIRTY_DATA);
if (!dirty) return op->GetCache(hh);
BaseContainer *data = op->GetDataInstance();
Real rad = data->GetReal(TUBEOBJECT_RAD,200.0);
Real iradx = data->GetReal(TUBEOBJECT_IRADX,50.0);
Real irady = data->GetReal(TUBEOBJECT_IRADY,50.0);
Real rrad = data->GetReal(TUBEOBJECT_ROUNDRAD,10.0);
LONG sub = CalcLOD(data->GetLong(TUBEOBJECT_SUB,1),hh->GetLOD(),1,1000);
LONG rsub = CalcLOD(data->GetLong(TUBEOBJECT_ROUNDSUB,8),hh->GetLOD(),1,1000);
LONG seg = CalcLOD(data->GetLong(TUBEOBJECT_SEG,36),hh->GetLOD(),3,1000);
LONG axis = data->GetLong(PRIM_AXIS);
LONG i;
Real sn,cs;
LONG cpcnt = 4*(sub+rsub);
Vector *cpadr = (Vector* )GeAlloc(cpcnt*sizeof(Vector));
if (!cpadr) return NULL;
for (i=0; i<sub; i++)
{
cpadr[i ]=Vector(rad-iradx,(1.0-Real(i)/Real(sub)*2.0)*(irady-rrad),0.0);
cpadr[i+ sub+rsub ]=Vector(rad+(Real(i)/Real(sub)*2.0-1.0)*(iradx-rrad),-irady,0.0);
cpadr[i+2*(sub+rsub)]=Vector(rad+iradx,(Real(i)/Real(sub)*2.0-1.0)*(irady-rrad),0.0);
cpadr[i+3*(sub+rsub)]=Vector(rad+(1.0-Real(i)/Real(sub)*2.0)*(iradx-rrad),irady,0.0);
}
for (i=0; i<rsub; i++)
{
SinCos(Real(i)/Real(rsub)*pi05,sn,cs);
cpadr[i+sub ]=Vector(rad-(iradx-rrad+cs*rrad),-(irady-rrad+sn*rrad),0.0);
cpadr[i+sub+ (sub+rsub)]=Vector(rad+(iradx-rrad+sn*rrad),-(irady-rrad+cs*rrad),0.0);
cpadr[i+sub+2*(sub+rsub)]=Vector(rad+(iradx-rrad+cs*rrad),+(irady-rrad+sn*rrad),0.0);
cpadr[i+sub+3*(sub+rsub)]=Vector(rad-(iradx-rrad+sn*rrad),+(irady-rrad+cs*rrad),0.0);
}
if (hh->GetVFlags()&VFLAG_POLYGONAL)
{
ret = GenerateLathe(cpadr,cpcnt,seg,hh->GetThread());
if (!ret) goto Error;
SetAxis(ret,axis);
ret->KillTag(Tphong);
if (!op->CopyTagsTo(ret,TRUE,FALSE,FALSE,NULL)) goto Error;
}
else
{
ret = PolygonObject::Alloc(0,0);
if (!ret) goto Error;
}
ret->SetName(op->GetName());
if (hh->GetVFlags()&VFLAG_ISOPARM)
{
lop = GenerateIsoLathe(cpadr,cpcnt,seg);
if (!lop) goto Error;
SetAxis(lop,axis);
ret->SetIsoparm(lop);
}
GeFree(cpadr);
return ret;
Error:
GeFree(cpadr);
blDelete(ret);
return NULL;
}
static Vector SwapPoint(const Vector &p, LONG axis)
{
switch (axis)
{
case 0: return Vector(p.y,-p.x,p.z); break;
case 1: return Vector(-p.y,p.x,p.z); break;
case 3: return Vector(-p.x,-p.y,p.z); break;
case 4: return Vector(p.x,-p.z,p.y); break;
case 5: return Vector(p.x,p.z,-p.y); break;
}
return p;
}
static Vector GetRTHandle(PluginObject *op, LONG id)
{
BaseContainer *data = op->GetDataInstance();
Vector p;
Real rad = data->GetReal(TUBEOBJECT_RAD);
Real iradx = data->GetReal(TUBEOBJECT_IRADX);
Real irady = data->GetReal(TUBEOBJECT_IRADY);
Real rrad = data->GetReal(TUBEOBJECT_ROUNDRAD);
LONG axis = data->GetLong(PRIM_AXIS);
switch (id)
{
case 0: p=Vector(rad,0.0,0.0); break;
case 1: p=Vector(rad+iradx,0.0,0.0); break;
case 2: p=Vector(rad,irady,0.0); break;
case 3: p=Vector(rad+iradx,irady-rrad,0.0); break;
case 4: p=Vector(rad+iradx-rrad,irady,0.0); break;
}
return SwapPoint(p,axis);
}
#define HANDLES 5
Bool RoundedTube::Draw(PluginObject *op, LONG type, BaseDraw *bd, BaseDrawHelp *bh)
{
if (type!=DRAWPASS_HANDLES) return TRUE;
BaseContainer *data = op->GetDataInstance();
LONG i;
Matrix m = bh->GetMg();
Real rad = data->GetReal(TUBEOBJECT_RAD);
Real iradx = data->GetReal(TUBEOBJECT_IRADX);
Real irady = data->GetReal(TUBEOBJECT_IRADY);
LONG axis = data->GetLong(PRIM_AXIS);
bd->SetPen(GetWorldColor(COLOR_ACTIVEPOINT));
for (i=0; i<HANDLES; i++)
bd->Handle3D(GetRTHandle(op,i)*m,HANDLE_BIG);
bd->Line3D(GetRTHandle(op,0)*m,GetRTHandle(op,1)*m);
bd->Line3D(GetRTHandle(op,0)*m,GetRTHandle(op,2)*m);
bd->Line3D(GetRTHandle(op,3)*m,SwapPoint(Vector(rad+iradx,irady,0.0),axis)*m);
bd->Line3D(GetRTHandle(op,4)*m,SwapPoint(Vector(rad+iradx,irady,0.0),axis)*m);
return TRUE;
}
LONG RoundedTube::DetectHandle(PluginObject *op, BaseDraw *bd, LONG x, LONG y, LONG qualifier)
{
if (qualifier&QUALIFIER_CTRL) return NOTOK;
Matrix mg = op->GetMg();
LONG i,ret=NOTOK;
Vector p;
for (i=0; i<HANDLES; i++)
{
p = GetRTHandle(op,i);
if (bd->PointInRange(p*mg,x,y))
{
ret=i;
if (!(qualifier&QUALIFIER_SHIFT)) break;
}
}
return ret;
}
Bool RoundedTube::MoveHandle(PluginObject *op, PluginObject *undo, const Matrix &tm, LONG hit_id, LONG qualifier)
{
BaseContainer *src = undo->GetDataInstance();
BaseContainer *dst = op ->GetDataInstance();
Vector handle_dir;
switch (hit_id)
{
case 0: handle_dir = Vector( 1.0, 0.0,0.0); break;
case 1: handle_dir = Vector( 1.0, 0.0,0.0); break;
case 2: handle_dir = Vector( 0.0, 1.0,0.0); break;
case 3: handle_dir = Vector( 0.0,-1.0,0.0); break;
case 4: handle_dir = Vector(-1.0, 0.0,0.0); break;
}
handle_dir=SwapPoint(handle_dir,src->GetLong(PRIM_AXIS));
Real val = tm.off*handle_dir;
switch (hit_id)
{
case 0: dst->SetReal(TUBEOBJECT_RAD,FCut(src->GetReal(TUBEOBJECT_RAD)+val,dst->GetReal(TUBEOBJECT_IRADX),MAXRANGE)); break;
case 1: dst->SetReal(TUBEOBJECT_IRADX,FCut(src->GetReal(TUBEOBJECT_IRADX)+val,dst->GetReal(TUBEOBJECT_ROUNDRAD),dst->GetReal(TUBEOBJECT_RAD))); break;
case 2: dst->SetReal(TUBEOBJECT_IRADY,FCut(src->GetReal(TUBEOBJECT_IRADY)+val,dst->GetReal(TUBEOBJECT_ROUNDRAD),MAXRANGE)); break;
case 3: case 4: dst->SetReal(TUBEOBJECT_ROUNDRAD,FCut(src->GetReal(TUBEOBJECT_ROUNDRAD)+val,0.0,FMin(dst->GetReal(TUBEOBJECT_IRADX),dst->GetReal(TUBEOBJECT_IRADY)))); break;
}
return TRUE;
}
// be sure to use a unique ID obtained from [www.plugincafe.com](http://www.plugincafe.com)
#define ID_ROUNDEDTUBEOBJECT 1001157
Bool RegisterRoundedTube(void)
{
// decide by name if the plugin shall be registered - just for user convenience
String name=GeLoadString(IDS_ROUNDED_TUBE); if (!name.Content()) return TRUE;
return RegisterObjectPlugin(ID_ROUNDEDTUBEOBJECT,name,OBJECT_GENERATOR,RoundedTube::Alloc,"Oroundedtube","roundedtube.tif","roundedtube_small.tif",0);
}
It works just as fine there. May I ask you to show some of your code that causes the crash? I'd be very interested in reproducing that...