/////////////////////////////////////////////////////////////
// CINEMA SDK : PARTICLES    															 //
/////////////////////////////////////////////////////////////
// VERSION    : CINEMA 4D V7 AMBER												 //
/////////////////////////////////////////////////////////////
// (c) 1989-2003 MAXON Computer GmbH, all rights reserved	 //
/////////////////////////////////////////////////////////////

#ifndef __C4D_PARTICLESNEU_H
#define __C4D_PARTICLESNEU_H

////////////////////////////////
#define ID_THINKINGPARTICLES			1001428
#define ID_TP_PGROUP							1001381
#define ID_TP_PARTICLEGEOMETRY		1001414	

#define ID_TP_VALUE_TYPE_PARTICLE	1001394
#define ID_TP_DATA_TYPE_PARTICLE	1001395
#define ID_TP_VALUE_TYPE_SHAPE		1001396
#define ID_TP_DATA_TYPE_SHAPE			1001397
#define ID_TP_VALUE_TYPE_GROUP		1001398
#define ID_TP_DATA_TYPE_GROUP			1001399
#define ID_TP_VALUE_TYPE_SPIN			1001433
#define ID_TP_DATA_TYPE_SPIN			1001434


#define ID_TP_OPCLASS							1001385
#define ID_TP_OPGROUP_CONDITION		1001386
#define ID_TP_OPGROUP_HELPER			1001387
#define ID_TP_OPGROUP_INITIATOR		1001388
#define ID_TP_OPGROUP_GENERATOR		1001389
#define ID_TP_OPGROUP_STANDARD		1001390	
#define ID_TP_OPGROUP_DYNAMIC			1001391	


#define ID_TP_OP_STORM						1001382
#define ID_TP_IN_SELFDYNAMIC			1001435
#define ID_TP_HP_PARTICLEDATA			1001403
#define ID_TP_OP_PARTICLEDATA			1001404
#define ID_TP_IN_INTERACT					1001405
#define ID_TP_IF_PARTICLEAGE			1001406
#define ID_TP_HP_SPINCONVERT			1001408	
#define ID_TP_HP_PGROUP						1001409	
#define ID_TP_HP_VELOCITYCONVERT	1001410	
#define ID_TP_OP_DEFLECTOR				1001411	
#define ID_TP_OP_POSFOLLOW				1001412	
#define ID_TP_OP_OBJECTSHAPE			1001413	
#define ID_TP_OP_SPIN							1001415	
#define ID_TP_OP_ALIGNMENT				1001416	
#define ID_TP_OP_PGROUP						1001417	
#define ID_TP_OP_MASS							1001418	
#define ID_TP_OP_SIZE							1001419	
#define ID_TP_OP_SCALE						1001420
#define ID_TP_OP_FRICTION					1001421
#define ID_TP_OP_VELOCITY					1001422
#define ID_TP_OP_MOTIONINHERI			1001423
#define ID_TP_OP_BUBBLE						1001424
#define ID_TP_OP_DIE							1001425
#define ID_TP_OP_GRAVITY					1001426
#define ID_TP_OP_WIND							1001427
#define ID_TP_HP_TIMER						1001429
#define ID_TP_HP_CHRONOMETER			1001430
#define ID_TP_OP_FRAGMENT					1001431
#define ID_TP_OP_FREEZE						1001432
#define ID_TP_OP_REPULSEBOUNCE		1001436
#define ID_TP_OP_ROLLING					1001437
#define ID_TP_IF_LIGHT						1001438
#define ID_THINKINGCOMMAND				1001439
#define ID_TP_HP_SURFACEPOSITION	1001440
#define ID_TP_HP_VOLUMEPOSITION		1001441
#define ID_TP_OP_BORN							1001442
#define ID_TP_REGISTER						1001443
#define ID_TP_OP_BLURP						1001444
#define ID_TP_OP_PARTICLEDRAW			1001445
#define ID_TP_OP_PARTICLEDRAWTOOL	1001446
#define ID_TP_OP_MATTERWAVES			1001447
////////////////////////////////

#include "ge_math.h"
#include "ge_mtools.h"
#include "c4d_library.h"
#include "c4d_string.h"
#include "c4d_baselist.h"
#include "c4d_nodedata.h"
#include "c4d_objectdata.h"
#include "c4d_graphview.h"
#include "c4d_baseobject.h"
#include "c4d_basedocument.h"
#include "lib_collider.h"

#define THINKINGPARTICLES_VERSION			0
#define THINKINGPARTICLES_PRIORITY		GRAPHVIEW_HOOK_PRIORITY - 100



class TP_PGroup;
class TP_ParticleNode;
class TP_MasterSystem;


#define TP_PGroupInfo	      	BaseContainer

#define TP_DataChannelInfo		BaseContainer
#define DATACHANNEL_INFO_CHAN	100
#define DATACHANNEL_INFO_NAME	101
#define DATACHANNEL_INFO_TYPE	102



class TP_PGroupArray : public GeTempDynArray <TP_PGroup> { };

struct TP_Spin
{
	Vector axis;
	Real   speed;
};

// used with SetPGroupHierarchy()
enum TP_InsertMode
{
	TP_INSERT_NONE = 0,
	TP_INSERT_UNDERFIRST,
	TP_INSERT_UNDERLAST,
	TP_INSERT_BEFORE,
	TP_INSERT_AFTER
};
////////////////////////////////
// used with GetParticleGroups()
enum TP_GetPGroupMode
{
	TP_GETPGROUP_ALL = 0,
	TP_GETPGROUP_WITHPARTICLES,
	TP_GETPGROUP_SELECTED
};
////////////////////////////////



#define TP_Collision	LONG


class TP_BaseCollision;

struct TP_CollisionInterface
{
	TP_BaseCollision *base;

	Bool (TP_BaseCollision::*CheckCollision)(TP_Collision collision, TP_MasterSystem *msys, LONG pid, Real t, Vector &pos, Vector &vel, TP_Spin &spin, Real dt, Real &ct);
};
struct TP_PShape
{
	TP_PShape(void) : owner_id(NOTOK) { }
	
	LONG	owner_id;
};


class TP_BaseShape;

struct TP_PShapeInterface
{
	TP_BaseShape *base;

	TP_PShape*  (TP_BaseShape::*GetShapeClone)         (TP_PShape *shape , TP_MasterSystem *msys, LONG pid, LONG flags, AliasTrans *trn);
	TP_PShape*  (TP_BaseShape::*GetShape)              (TP_PShape *shape , TP_MasterSystem *msys, LONG pid, LONG owner_id);
	BaseObject* (TP_BaseShape::*GetShapeVirtualObjects)(TP_PShape *shape , TP_MasterSystem *msys, LONG pid, BaseDocument *doc, HierarchyHelp *hh);
	Real        (TP_BaseShape::*GetShapeScale)         (TP_PShape *shape , TP_MasterSystem *msys, LONG pid);
	void        (TP_BaseShape::*FreeShape)             (TP_PShape *&shape, TP_MasterSystem *msys, LONG pid);
};



//CallBacks
struct TP_FreeParticle_CB
{
	void (*FreeParticle)(TP_FreeParticle_CB *cb, LONG pid);
};

struct TP_FreePShape_CB
{
	void (*FreePShape)(TP_FreePShape_CB *cb, LONG pid, TP_PShape *shape);
};
//




#define TP_MSG_START_ID		1000000	 

enum
{
	TP_MSG_PGROUP_PREREMOVE = TP_MSG_START_ID,	//data *TP_PGroup
	TP_MSG_PGROUP_TREECHANGED,									//data NULL
	TP_MSG_DCHANNEL_PREREMOVE,									//data chan
	TP_MSG_DCHANNEL_CHANGED,										//data NULL
	TP_MSG_OBJECT_GETPARTICLES,									//data *TP_PGroupArray
	TP_MSG_GET_PSHAPEINTERFACE,									//data **TP_PShapeInterface
	TP_MSG_GET_COLLISIONINTERFACE								//data **TP_CollisionInterface
};

struct TP_Msg
{
	LONG             msg;
	TP_MasterSystem *msys;
	void            *data;
};

struct TP_PGroupPreRemove
{
	TP_PGroup *pgroup;
	Bool       used;
};



struct C4D_TP_MASTERSYSTEM
{
	LONG (TP_MasterSystem::*AllocParticle   )(void);
	LONG (TP_MasterSystem::*AllocParticles  )(LONG num, LONG *ids);
	void (TP_MasterSystem::*FreeParticle    )(LONG pid); 
	void (TP_MasterSystem::*FreeAllParticles)(void); 
	
	TP_PGroup    *(TP_MasterSystem::*AllocParticleGroup)		(void);
	void				  (TP_MasterSystem::*FreeParticleGroup)			(TP_PGroup *&group); 
	Bool				  (TP_MasterSystem::*SetPGroupHierarchy)	  (TP_PGroup *parent , TP_PGroup *group, TP_InsertMode mode);
	LONG				  (TP_MasterSystem::*GetParticleGroups)	    (TP_PGroup *ingroup, TP_PGroupArray *gtab, TP_GetPGroupMode mode, Bool subgroups);
	LONG				  (TP_MasterSystem::*GetGroupParticleCount)	(TP_PGroup *ingroup, Bool subgroups);
	BaseObject   *(TP_MasterSystem::*GetVirtualObjects)     (TP_PGroup *ingroup, Bool inRender, Bool subgroups, HierarchyHelp *hh);
	TP_PGroupInfo*(TP_MasterSystem::*GetGroupInfo)    (TP_PGroup     *group);
	TP_PGroup*    (TP_MasterSystem::*GetGroupFromInfo)(TP_PGroupInfo *info );



	LONG       (TP_MasterSystem::*NumParticles)(void);
	Bool       (TP_MasterSystem::*Alive)       (LONG pid);
	Bool       (TP_MasterSystem::*IsBorn)      (LONG pid);
	Bool       (TP_MasterSystem::*IsDie)       (LONG pid);
	Bool       (TP_MasterSystem::*EntersGroup) (LONG pid);
	TP_PGroup* (TP_MasterSystem::*Group)       (LONG pid);
	Vector     (TP_MasterSystem::*Position)    (LONG pid);
	Vector     (TP_MasterSystem::*Velocity)    (LONG pid);	
	Real       (TP_MasterSystem::*Mass)        (LONG pid);	
	TP_Spin    (TP_MasterSystem::*Spin)        (LONG pid);
	Real       (TP_MasterSystem::*Size)        (LONG pid);
	Vector     (TP_MasterSystem::*Scale)       (LONG pid);
	BaseTime   (TP_MasterSystem::*Age)         (LONG pid);
	BaseTime   (TP_MasterSystem::*Life)        (LONG pid);
	Matrix     (TP_MasterSystem::*Alignment)   (LONG pid);
	LONG       (TP_MasterSystem::*Randomseed)  (LONG pid);
	TP_PShape* (TP_MasterSystem::*Shape)       (LONG pid);
	Matrix     (TP_MasterSystem::*Transform)   (LONG pid);
	UWORD      (TP_MasterSystem::*Flags)       (LONG pid);
	Real       (TP_MasterSystem::*DTFactor)    (LONG pid);
	
	void (TP_MasterSystem::*SetPosition)	(LONG pid, Vector &p);
	void (TP_MasterSystem::*SetVelocity)	(LONG pid, Vector &p);
	void (TP_MasterSystem::*SetMass)			(LONG pid, Real mass);
	void (TP_MasterSystem::*SetSpin)			(LONG pid, TP_Spin &spin);
	void (TP_MasterSystem::*SetAge)				(LONG pid, BaseTime &age);
	void (TP_MasterSystem::*SetLife)			(LONG pid, BaseTime &life);
	void (TP_MasterSystem::*SetGroup)			(LONG pid, TP_PGroup *group);
	void (TP_MasterSystem::*SetSize)			(LONG pid, Real size );
	void (TP_MasterSystem::*SetScale)			(LONG pid, Vector &scale);
	void (TP_MasterSystem::*SetAlignment)	(LONG pid, Matrix &align);
	void (TP_MasterSystem::*SetRandomseed)(LONG pid, LONG seed );
	void (TP_MasterSystem::*SetShape)			(LONG pid, TP_PShape *shape, Bool deleteold);
	void (TP_MasterSystem::*SetCollision)	(LONG pid, TP_Collision collision);	
	void (TP_MasterSystem::*SetDTFactor)	(LONG pid, Real dt    );	

	
	//Particle Data Channels
  Bool			(TP_MasterSystem::*AddDataChannel)			(GvDataID type, const String& str);
	Bool			(TP_MasterSystem::*RemoveDataChannel)		(LONG chan);
	LONG			(TP_MasterSystem::*NumDataChannels)			(void);
	GvDataID	(TP_MasterSystem::*DataChannelType)			(LONG chan);
	String		(TP_MasterSystem::*DataChannelName)			(LONG chan);
	LONG			(TP_MasterSystem::*DataChannelUniqueID)	(LONG chan);
	LONG			(TP_MasterSystem::*DataChannelID)				(LONG unique_id);

	Bool (TP_MasterSystem::*SetData)        (LONG pid, LONG chan, void *data, GvValueID type);
	Bool (TP_MasterSystem::*GetData)        (LONG pid, LONG chan, void *data, GvValueID type); 
	Bool (TP_MasterSystem::*SetDataFromPort)(LONG pid, LONG chan, GvPort *p, GvRun *r);
	Bool (TP_MasterSystem::*SetDataToPort)  (LONG pid, LONG chan, GvPort *p, GvRun *r); 
	
	TP_DataChannelInfo *(TP_MasterSystem::*GetDataChannelInfo)    (LONG chan);
	LONG                (TP_MasterSystem::*GetDataChannelFromInfo)(TP_DataChannelInfo *info);
	///

	//Call Backs
	void (TP_MasterSystem::*Reg_FreeParticle_CB) (TP_FreeParticle_CB *cb);
	void (TP_MasterSystem::*UReg_FreeParticle_CB)(TP_FreeParticle_CB *cb);
	void (TP_MasterSystem::*Reg_FreePShape_CB)   (TP_FreePShape_CB   *cb);
	void (TP_MasterSystem::*UReg_FreePShape_CB)  (TP_FreePShape_CB   *cb);
	//

	//Operator Link Table
	LONG            (TP_MasterSystem::*GetOperatorID)(GvNode *op);
	GvOperatorData *(TP_MasterSystem::*GetOperator)  (LONG    id);

	ULONG            (TP_MasterSystem::*GetDirty)(void);
	void             (TP_MasterSystem::*SetDirty)(void);

	// Collision 
	Bool (TP_MasterSystem::*CheckCollision)(TP_Collision collision, LONG pid, Real t, Vector &pos, Vector &vel, TP_Spin &spin, Real dt, Real &ct);
	
	//Particle Shape
	TP_PShape*  (TP_MasterSystem::*GetShapeClone)         (TP_PShape *shape , LONG pid, LONG flags, AliasTrans *trn);
	TP_PShape*  (TP_MasterSystem::*GetShape)              (TP_PShape *shape , LONG pid, LONG owner_id);
	BaseObject* (TP_MasterSystem::*GetShapeVirtualObjects)(TP_PShape *shape , LONG pid, BaseDocument *doc, HierarchyHelp *hh);
	Real        (TP_MasterSystem::*GetShapeScale)         (TP_PShape *shape , LONG pid);
	void        (TP_MasterSystem::*FreeShape)             (TP_PShape *&shape, LONG pid);

	//ColliderCache
	GeColliderCache *(TP_MasterSystem::*ColliderCache)(LONG pid);
};

struct C4D_TP_PGROUP
{
	LONG             (TP_PGroup::*GetLevel)      (void);
	TP_ParticleNode *(TP_PGroup::*GetFirstNode)  (void);
	TP_ParticleNode *(TP_PGroup::*GetLastNode )  (void);
	LONG             (TP_PGroup::*NumParticles)  (void);
	Bool             (TP_PGroup::*IsSubGroup  )  (TP_PGroup *group);
	LONG             (TP_PGroup::*GetGroupID  )  (void);
	const String     (TP_PGroup::*GetTitle)		   (void);
	void             (TP_PGroup::*SetTitle)      (const String &title);
	void             (TP_PGroup::*SetViewType)   (LONG type);
	LONG             (TP_PGroup::*GetViewType)   (void);
	void             (TP_PGroup::*SetShowObjects)(Bool show);
	Bool             (TP_PGroup::*GetShowObjects)(void);
	void             (TP_PGroup::*SetColor)      (Vector &col);
	Vector           (TP_PGroup::*GetColor)      (void);
	Bool             (TP_PGroup::*EditSettings)  (void);      
	Bool             (TP_PGroup::*IsSelected)    (void);      
	Bool             (TP_PGroup::*IsOpened)      (void);  
	void             (TP_PGroup::*Select)        (LONG mode);
	void             (TP_PGroup::*Open)					 (Bool onoff);
};

struct C4D_TP_PARTICLENODE
{
	LONG             (TP_ParticleNode::*GetParticleID)(void);
	TP_ParticleNode *(TP_ParticleNode::*GetNext      )(void);
	TP_ParticleNode *(TP_ParticleNode::*GetPrev      )(void);
};


struct C4DLibrary_TPOS : public C4DLibrary
{
	C4D_TP_MASTERSYSTEM   *MSYS;
	C4D_TP_PGROUP					*GROUP;
	C4D_TP_PARTICLENODE   *PART; 
};

extern C4DLibrary_TPOS *TPOS;








#define TpCall(fnc) (this->*TPOS->MSYS->fnc)

class TP_MasterSystem : public PluginSceneHook
{
public:
	LONG AllocParticle   (void)               { return TpCall(AllocParticle)(); }
	LONG AllocParticles  (LONG num, LONG *ids){ return TpCall(AllocParticles)(num, ids); }
	void FreeParticle    (LONG pid)           { TpCall(FreeParticle)(pid); } 
	void FreeAllParticles(void)               { TpCall(FreeAllParticles)(); }
	
	TP_PGroup     *AllocParticleGroup		(void){ return TpCall(AllocParticleGroup)(); }
	void				   FreeParticleGroup			(TP_PGroup *&group){ TpCall(FreeParticleGroup)(group); } 
	Bool				   SetPGroupHierarchy		(TP_PGroup *parent , TP_PGroup *group, TP_InsertMode mode){ return TpCall(SetPGroupHierarchy)(parent, group, mode); }
	LONG				   GetParticleGroups	    (TP_PGroup *ingroup, TP_PGroupArray *gtab, TP_GetPGroupMode mode, Bool subgroups = TRUE){ return TpCall(GetParticleGroups)(ingroup, gtab, mode, subgroups); }
	LONG				   GetGroupParticleCount	(TP_PGroup *ingroup, Bool subgroups = TRUE){ return TpCall(GetGroupParticleCount)(ingroup, subgroups); }
	BaseObject    *GetVirtualObjects     (TP_PGroup *ingroup, Bool inRender = TRUE, Bool subgroups = TRUE, HierarchyHelp *hh = NULL){ return TpCall(GetVirtualObjects)(ingroup, inRender, subgroups, hh); }
	TP_PGroupInfo *GetGroupInfo    (TP_PGroup     *group){ return TpCall(GetGroupInfo)(group);    }
	TP_PGroup     *GetGroupFromInfo(TP_PGroupInfo *info ){ return TpCall(GetGroupFromInfo)(info); }


	LONG       NumParticles(void)    { return TpCall(NumParticles)(); }
	Bool       Alive       (LONG pid){ return TpCall(Alive)(pid); }
	Bool       IsBorn      (LONG pid){ return TpCall(IsBorn)(pid); }
	Bool       IsDie       (LONG pid){ return TpCall(IsDie)(pid); }
	Bool       EntersGroup (LONG pid){ return TpCall(EntersGroup)(pid); }
	TP_PGroup *Group       (LONG pid){ return TpCall(Group)(pid); }
	Vector     Position    (LONG pid){ return TpCall(Position)(pid); }
	Vector     Velocity    (LONG pid){ return TpCall(Velocity)(pid); }	
	Real       Mass        (LONG pid){ return TpCall(Mass)(pid); }	
	TP_Spin    Spin        (LONG pid){ return TpCall(Spin)(pid); }
	Real       Size        (LONG pid){ return TpCall(Size)(pid); }
	Vector     Scale       (LONG pid){ return TpCall(Scale)(pid); }
	BaseTime   Age         (LONG pid){ return TpCall(Age)(pid); }
	BaseTime   Life        (LONG pid){ return TpCall(Life)(pid); }
	Matrix     Alignment   (LONG pid){ return TpCall(Alignment)(pid); }
	LONG       Randomseed  (LONG pid){ return TpCall(Randomseed)(pid); }
	TP_PShape *Shape       (LONG pid){ return TpCall(Shape)(pid); }
	Matrix     Transform   (LONG pid){ return TpCall(Transform)(pid); }
	UWORD      Flags       (LONG pid){ return TpCall(Flags)(pid); }
	Real       DTFactor    (LONG pid){ return TpCall(DTFactor)(pid); }


	
	void SetPosition	(LONG pid, Vector &p){ TpCall(SetPosition)(pid, p); }
	void SetVelocity	(LONG pid, Vector &p){ TpCall(SetVelocity)(pid, p); }
	void SetMass			(LONG pid, Real mass){ TpCall(SetMass)(pid, mass); }
	void SetSpin			(LONG pid, TP_Spin &spin){ TpCall(SetSpin)(pid, spin); }
	void SetAge				(LONG pid, BaseTime &age){ TpCall(SetAge)(pid, age); }
	void SetLife			(LONG pid, BaseTime &life){ TpCall(SetLife)(pid, life); }
	void SetGroup			(LONG pid, TP_PGroup *group){ TpCall(SetGroup)(pid, group); }
	void SetSize			(LONG pid, Real size ){ TpCall(SetSize)(pid, size); }
	void SetScale			(LONG pid, Vector &scale){ TpCall(SetScale)(pid, scale); }
	void SetAlignment	(LONG pid, Matrix &align){ TpCall(SetAlignment)(pid, align); }
	void SetRandomseed(LONG pid, LONG seed ){ TpCall(SetRandomseed)(pid, seed); }
	void SetShape			(LONG pid, TP_PShape *shape, Bool deleteold = TRUE){ TpCall(SetShape)(pid, shape, deleteold); }
	void SetCollision	(LONG pid, TP_Collision collision){ TpCall(SetCollision)(pid, collision); }	
	void SetDTFactor	(LONG pid, Real dt    ){ TpCall(SetDTFactor)(pid, dt); }	

	
	//Particle Data Channels
  Bool			AddDataChannel			(GvDataID type, const String& str){ return TpCall(AddDataChannel)(type, str); }
	Bool			RemoveDataChannel		(LONG chan){ return TpCall(RemoveDataChannel)(chan); }
	LONG			NumDataChannels			(void){ return TpCall(NumDataChannels)(); }
	GvDataID	DataChannelType			(LONG chan){ return TpCall(DataChannelType)(chan); }
	String 		DataChannelName			(LONG chan){ return TpCall(DataChannelName)(chan); }
	LONG			DataChannelUniqueID	(LONG chan){ return TpCall(DataChannelUniqueID)(chan); }
	LONG			DataChannelID				(LONG unique_id){ return TpCall(DataChannelID)(unique_id); }

	Bool SetData(LONG pid, LONG chan, void *data, GvValueID type) { return TpCall(SetData)(pid, chan, data, type); }
	Bool GetData(LONG pid, LONG chan, void *data, GvValueID type) { return TpCall(GetData)(pid, chan, data, type); }
	Bool SetDataFromPort(LONG pid, LONG chan, GvPort *p, GvRun *r){ return TpCall(SetDataFromPort)(pid, chan, p, r); }
	Bool SetDataToPort  (LONG pid, LONG chan, GvPort *p, GvRun *r){ return TpCall(SetDataToPort)(pid, chan, p, r);   } 
	TP_DataChannelInfo *GetDataChannelInfo    (LONG chan)         { return TpCall(GetDataChannelInfo)(chan);   } 
	LONG                GetDataChannelFromInfo(TP_DataChannelInfo *info){ return TpCall(GetDataChannelFromInfo)(info);   } 
	///


	//Call Backs
	void Reg_FreeParticle_CB (TP_FreeParticle_CB *cb){ TpCall(Reg_FreeParticle_CB)(cb);  }
	void UReg_FreeParticle_CB(TP_FreeParticle_CB *cb){ TpCall(UReg_FreeParticle_CB)(cb); }
	void Reg_DeletePShape_CB (TP_FreePShape_CB   *cb){ TpCall(Reg_FreePShape_CB)(cb);  }
	void UReg_DeletePShape_CB(TP_FreePShape_CB   *cb){ TpCall(UReg_FreePShape_CB)(cb); }
	//

	//Operator Link Table
	LONG            GetOperatorID(GvNode *op){ return TpCall(GetOperatorID)(op); }
	GvOperatorData *GetOperator  (LONG    id){ return TpCall(GetOperator)(id);   }

	ULONG            GetDirty(void){ return TpCall(GetDirty)(); }
	void             SetDirty(void){ TpCall(SetDirty)(); }

	// Collision 
	Bool CheckCollision(TP_Collision collision, LONG pid, Real t, Vector &pos, Vector &vel, TP_Spin &spin, Real dt, Real &ct){ return TpCall(CheckCollision)(collision, pid, t, pos, vel, spin, dt, ct); }
	
	//Particle Shape
	TP_PShape*  GetShapeClone         (TP_PShape *shape , LONG pid, LONG flags, AliasTrans *trn){ return TpCall(GetShapeClone)(shape, pid, flags, trn); }
	TP_PShape*  GetShape              (TP_PShape *shape , LONG pid, LONG owner_id){ return TpCall(GetShape)(shape, pid, owner_id); }
	BaseObject* GetShapeVirtualObjects(TP_PShape *shape , LONG pid, BaseDocument *doc, HierarchyHelp *hh){ return TpCall(GetShapeVirtualObjects)(shape, pid, doc, hh); }
	Real        GetShapeScale         (TP_PShape *shape , LONG pid){ return TpCall(GetShapeScale)(shape, pid); }
	void        FreeShape             (TP_PShape *&shape, LONG pid){ TpCall(FreeShape)(shape, pid); }

	// ColliderCache
	GeColliderCache* ColliderCache(LONG pid){ return TpCall(ColliderCache)(pid); }
};

#define PartCall(fnc) (this->*TPOS->PART->fnc)

class TP_ParticleNode
{
public:
	LONG             GetParticleID(void){ return PartCall(GetParticleID)(); }
	TP_ParticleNode *GetNext      (void){ return PartCall(GetNext)();       }
	TP_ParticleNode *GetPrev      (void){ return PartCall(GetPrev)();       }
};


#define PGroupCall(fnc) (this->*TPOS->GROUP->fnc)

class TP_PGroup : public BaseList2D
{
public:
	LONG             GetLevel(void)                  { return PGroupCall(GetLevel)();        }
	TP_ParticleNode *GetFirstNode(void)              { return PGroupCall(GetFirstNode)();    }
	TP_ParticleNode *GetLastNode(void)	             { return PGroupCall(GetLastNode)();     }
	LONG             NumParticles(void)              { return PGroupCall(NumParticles)();    }
	Bool             IsSubGroup(TP_PGroup *group)    { return PGroupCall(IsSubGroup)(group); }
	LONG             GetGroupID(void)                { return PGroupCall(GetGroupID)();      }
	const String     GetTitle(void)                  { return PGroupCall(GetTitle)();        }
	void             SetTitle(const String &title)   { PGroupCall(SetTitle)(title);          }
	void             SetViewType(LONG type)          { PGroupCall(SetViewType)(type);        }
	LONG             GetViewType(void)               { return PGroupCall(GetViewType)();     }
	void             SetShowObjects(Bool show)       { PGroupCall(SetShowObjects)(show);     }
	Bool             GetShowObjects(void)            { return PGroupCall(GetShowObjects)();  }
	void             SetColor(Vector &col)           { PGroupCall(SetColor)(col);            }
	Vector           GetColor(void)                  { return PGroupCall(GetColor)();        }
	Bool             EditSettings(void)              { return PGroupCall(EditSettings)();    }
	Bool             IsSelected(void)								 { return PGroupCall(IsSelected)();      }
	Bool             IsOpened(void)									 { return PGroupCall(IsOpened)();        }
	void             Select(LONG mode )							 { PGroupCall(Select)(mode);             }
	void             Open(Bool onoff)								 { PGroupCall(Open)(onoff);              }
};

////////////////////////////////

inline Bool InitThinkingParticles(void)
{
	return NULL != CheckLib(ID_THINKINGPARTICLES, 0, (C4DLibrary**)&TPOS);
}

////////////////////////////////

#endif //__C4D_PARTICLES_H

////////////////////////////////
