/////////////////////////////////////////////////////////////
// CINEMA 4D SDK                                           //
/////////////////////////////////////////////////////////////
// (c) 1989-2006 MAXON Computer GmbH, all rights reserved  //
/////////////////////////////////////////////////////////////

//----------------------------------------------------
//Falloff controller system
#include "c4d_falloffplugin.h"

//------------------------------------------
//FalloffData
Bool FalloffData::Init(FalloffDataData &falldata,BaseContainer *bc) { return TRUE; }
Bool FalloffData::InitFalloff(BaseContainer *bc, FalloffDataData &falldata)	{	return TRUE;	}
void FalloffData::Sample(const Vector &p, const FalloffDataData &data, Real *res)	{	(*res)=1.0;	}
void FalloffData::FreeFalloff(FalloffDataData &falldata)	{ }
Bool FalloffData::CheckDirty(BaseContainer *bc)	{	return FALSE;	}
Bool FalloffData::GetDVisible(DescID &id,BaseContainer *bc,BaseContainer *desc_bc)	{	return TRUE;	}
LONG FalloffData::GetHandleCount(BaseContainer *bc, const FalloffDataData &data)	{	return 0;	}
void FalloffData::GetHandle(BaseContainer *bc, LONG i, HandleInfo &info, const FalloffDataData &data)	{	}
void FalloffData::SetHandle(BaseContainer *bc, LONG i, Vector p, const FalloffDataData &data)	{	}
Bool FalloffData::Draw(const FalloffDataData &data, DRAWPASS drawpass, BaseDraw *bd, BaseDrawHelp *bh)	{	return TRUE;	}
Bool FalloffData::Message(LONG type,BaseContainer *bc,void *m_data) { return TRUE; }

//-------------------------------------------
//FalloffContol

FalloffControlLib	*falloff_libcache = NULL;

static FalloffControlLib *CheckFalloffLib(LONG offset)
{
	return (FalloffControlLib*)CheckLib(ID_C4DFALLOFFLIB,offset,(C4DLibrary**)&falloff_libcache);
}

BaseContainer* C4D_Falloff::GetContainerInstance(void)
{
	FalloffControlLib* flib = CheckFalloffLib(LIBOFFSET(FalloffControlLib, GetContainerInstance));
	if (!flib || !flib->GetContainerInstance) return NULL;

	return (((iC4D_Falloff*)this)->*(flib->GetContainerInstance))();
}

void C4D_Falloff::SetDirty(void)
{
	FalloffControlLib* flib = CheckFalloffLib(LIBOFFSET(FalloffControlLib, SetDirty));
	if (!flib || !flib->SetDirty) return;

	(((iC4D_Falloff*)this)->*(flib->SetDirty))();
}

LONG C4D_Falloff::GetDirty(BaseContainer *bc)
{
	FalloffControlLib* flib = CheckFalloffLib(LIBOFFSET(FalloffControlLib, GetDirty));
	if (!flib || !flib->GetDirty) return 0;

	return (((iC4D_Falloff*)this)->*(flib->GetDirty))(bc);
}

LONG	C4D_Falloff::GetHandleCount(BaseContainer *bc)
{
	FalloffControlLib* flib = CheckFalloffLib(LIBOFFSET(FalloffControlLib, GetHandleCount));
	if (!flib || !flib->GetHandleCount) return 0;

	return (((iC4D_Falloff*)this)->*(flib->GetHandleCount))(bc);
}

void	C4D_Falloff::GetHandle(LONG i, BaseContainer *bc, HandleInfo &info)
{
	FalloffControlLib* flib = CheckFalloffLib(LIBOFFSET(FalloffControlLib, GetHandle));
	if (!flib || !flib->GetHandle) return;

	(((iC4D_Falloff*)this)->*(flib->GetHandle))(i,bc, info);
}

void C4D_Falloff::SetHandle( LONG i, Vector p, BaseContainer *bc, const HandleInfo &info )
{
	FalloffControlLib* flib = CheckFalloffLib(LIBOFFSET(FalloffControlLib, SetHandle));
	if (!flib || !flib->SetHandle) return;

	(((iC4D_Falloff*)this)->*(flib->SetHandle))(i,p,bc,info);
}

void	C4D_Falloff::SetMg(Matrix mg)
{
	FalloffControlLib* flib = CheckFalloffLib(LIBOFFSET(FalloffControlLib, SetMg));
	if (!flib || !flib->SetMg) return;

	(((iC4D_Falloff*)this)->*(flib->SetMg))(mg);
}

Matrix	C4D_Falloff::GetMg(void)
{
	FalloffControlLib* flib = CheckFalloffLib(LIBOFFSET(FalloffControlLib, GetMg));
	if (!flib || !flib->GetMg) return Matrix();

	return (((iC4D_Falloff*)this)->*(flib->GetMg))();
}

void	C4D_Falloff::SetData(FalloffDataData falldata)
{
	FalloffControlLib* flib = CheckFalloffLib(LIBOFFSET(FalloffControlLib, SetData));
	if (!flib || !flib->SetData) return;

	(((iC4D_Falloff*)this)->*(flib->SetData))(falldata);
}

FalloffDataData	C4D_Falloff::GetData(void)
{
	FalloffControlLib* flib = CheckFalloffLib(LIBOFFSET(FalloffControlLib, GetData));
	if (!flib || !flib->GetData) return FalloffDataData();

	return (((iC4D_Falloff*)this)->*(flib->GetData))();
}

Bool C4D_Falloff::SetMode(LONG type,BaseContainer *bc)
{
	FalloffControlLib* flib = CheckFalloffLib(LIBOFFSET(FalloffControlLib, SetMode));
	if (!flib || !flib->SetMode) return FALSE;

	return (((iC4D_Falloff*)this)->*(flib->SetMode))(type,bc);
}

LONG	C4D_Falloff::GetMode(void)
{
	FalloffControlLib* flib = CheckFalloffLib(LIBOFFSET(FalloffControlLib, GetMode));
	if (!flib || !flib->GetMode) return 0;

	return (((iC4D_Falloff*)this)->*(flib->GetMode))();
}

void C4D_Falloff::SetTime(BaseTime time,BaseContainer *bc)
{
	FalloffControlLib* flib = CheckFalloffLib(LIBOFFSET(FalloffControlLib, SetTime));
	if (!flib || !flib->SetTime) return;

	(((iC4D_Falloff*)this)->*(flib->SetTime))(time,bc);
}

Bool C4D_Falloff::InitFalloff(BaseContainer *bc,BaseDocument *doc, BaseObject *op)
{
	FalloffControlLib* flib = CheckFalloffLib(LIBOFFSET(FalloffControlLib, InitFalloff));
	if (!flib || !flib->InitFalloff) return FALSE;

	return (((iC4D_Falloff*)this)->*(flib->InitFalloff))(bc,doc,op);
}

Bool C4D_Falloff::AddFalloffToDescription(Description *description,BaseContainer *bc)
{
	FalloffControlLib* flib = CheckFalloffLib(LIBOFFSET(FalloffControlLib, AddFalloffToDescription));
	if (!flib || !flib->AddFalloffToDescription) return FALSE;

	return (((iC4D_Falloff*)this)->*(flib->AddFalloffToDescription))(description,bc);
}

Bool	C4D_Falloff::Message(LONG id,BaseContainer *bc,void *m_data)
{
	FalloffControlLib* flib = CheckFalloffLib(LIBOFFSET(FalloffControlLib, Message));
	if (!flib || !flib->Message) return FALSE;

	return (((iC4D_Falloff*)this)->*(flib->Message))(id,bc,m_data);
}

Bool	C4D_Falloff::Draw(BaseDraw *bd, BaseDrawHelp *bh, DRAWPASS drawpass, BaseContainer *bc)
{
	FalloffControlLib* flib = CheckFalloffLib(LIBOFFSET(FalloffControlLib, Draw));
	if (!flib || !flib->Draw) return FALSE;

	return (((iC4D_Falloff*)this)->*(flib->Draw))(bd,bh,drawpass,bc);
}

void C4D_Falloff::Sample(const Vector &p,Real *result,Bool usespline,Real weight)
{
	FalloffControlLib* flib = CheckFalloffLib(LIBOFFSET(FalloffControlLib, Sample));
	if (!flib || !flib->Sample) return;

	(((iC4D_Falloff*)this)->*(flib->Sample))(p,result,usespline,weight);
}
void C4D_Falloff::MultiSample(const Vector *p,Real *result,LONG count,Bool usespline,Real weight)
{
	FalloffControlLib* flib = CheckFalloffLib(LIBOFFSET(FalloffControlLib, MultiSample));
	if (!flib || !flib->MultiSample) return;

	(((iC4D_Falloff*)this)->*(flib->MultiSample))(p,result,count,usespline,weight);
}



C4D_Falloff*	C4D_Falloff::Alloc(void)
{
	FalloffControlLib* flib = CheckFalloffLib(LIBOFFSET(FalloffControlLib, Alloc));
	if (!flib || !flib->Alloc) return NULL;

	return (C4D_Falloff*)flib->Alloc();
}

Bool C4D_Falloff::CopyTo(C4D_Falloff *dest)
{
	FalloffControlLib* flib = CheckFalloffLib(LIBOFFSET(FalloffControlLib, CopyTo));
	if (!flib || !flib->CopyTo) return FALSE;

	iC4D_Falloff *temp=(iC4D_Falloff*)dest;
	if (!temp) return FALSE;
	return (((iC4D_Falloff*)this)->*(flib->CopyTo))(temp);
}

void C4D_Falloff::Free(C4D_Falloff *&node)
{
	FalloffControlLib* flib = CheckFalloffLib(LIBOFFSET(FalloffControlLib, Free));
	if (!flib || !flib->Free) return;

	iC4D_Falloff* tmp=(iC4D_Falloff*)node;
	flib->Free(tmp);
	node=NULL;
}

//-----------------------------------
//Registration

void FillFalloffPlugin(FALLOFFPLUGIN *fp, LONG info, FalloffDataAllocator *g)
{
	fp->allocator				= g;
	fp->adr							= g();

	fp->Destructor			= &FalloffData::Destructor;

	fp->Init						= &FalloffData::Init;
	fp->InitFalloff			= &FalloffData::InitFalloff;
	fp->Sample					= &FalloffData::Sample;
	fp->FreeFalloff			= &FalloffData::FreeFalloff;
	fp->CheckDirty			= &FalloffData::CheckDirty;
	fp->Message					= &FalloffData::Message;
	fp->GetDVisible			= &FalloffData::GetDVisible;	
	fp->GetHandleCount	= &FalloffData::GetHandleCount;	
	fp->GetHandle				= &FalloffData::GetHandle;
	fp->SetHandle				= &FalloffData::SetHandle;
	fp->Draw						= &FalloffData::Draw;
	fp->info						= info;
}

Bool RegisterFalloffPlugin(LONG id, const String &str, LONG info, FalloffDataAllocator *g, const String &description)
{
	if (description.Content() &&!RegisterDescription(id,description)) return FALSE;

	FALLOFFPLUGIN fp;
	ClearMem(&fp,sizeof(fp));

	FillFalloffPlugin(&fp,info,g);
	return GeRegisterPlugin(PLUGINTYPE_FALLOFF,id,str,&fp,sizeof(fp)); //shoudl be used in the newer versions of cinema
}