#include "lib_ca.h"

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

CALibrary *lib_ca = NULL;

static CALibrary *CheckCALib(LONG offset)
{
	return (CALibrary*)CheckLib(LIBRARY_CA,offset,(C4DLibrary**)&lib_ca);
}

#define CALibCall(b) 		CALibrary *lib = CheckCALib(LIBOFFSET(CALibrary, b)); \
															if (!lib || !lib->b) return; \
															(lib->b)

#define CALibCallR(a,b)  CALibrary *lib = CheckCALib(LIBOFFSET(CALibrary, b)); \
															if (!lib || !lib->b) return a; \
															return (lib->b)

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

BaseObject *CAWeightTag::GetJoint(LONG index, BaseDocument *doc) { CALibCallR(NULL,weightGetJoint)(this,index,doc); }
LONG CAWeightTag::GetJointCount() { CALibCallR(0,weightGetJointCount)(this); }
LONG CAWeightTag::FindJoint(BaseObject *op, BaseDocument *doc) { CALibCallR(NOTOK,weightFindJoint)(this,op,doc); }
JointRestState CAWeightTag::GetJointRestState(LONG index) { CALibCallR(JointRestState(),weightGetJointRestState)(this,index); }
void CAWeightTag::SetJointRestState(LONG index, const JointRestState &state) { CALibCall(weightSetJointRestState)(this,index,state); }
void CAWeightTag::GetWeightMap(LONG index, Real *map, LONG cnt) { CALibCall(weightGetWeightMap)(this,index,map,cnt); }
Bool CAWeightTag::SetWeightMap(LONG index, Real *map, LONG cnt) { CALibCallR(FALSE,weightSetWeightMap)(this,index,map,cnt); }
LONG CAWeightTag::GetWeightCount(LONG index) { CALibCallR(0,weightGetWeightCount)(this,index); }
void CAWeightTag::GetIndexWeight(LONG index, LONG windex, LONG &pntindex, Real &weight) { CALibCall(weightGetIndexWeight)(this,index,windex,pntindex,weight); }
Real CAWeightTag::GetWeight(LONG index, LONG pntindex) { CALibCallR(0.0,weightGetWeight)(this,index,pntindex); }
Bool CAWeightTag::SetWeight(LONG index, LONG pntindex, Real weight) { CALibCallR(FALSE,weightSetWeight)(this,index,pntindex,weight); }
ULONG CAWeightTag::GetDirty() { CALibCallR(0,weightGetDirty)(this); }
void CAWeightTag::Dirty() { CALibCall(weightDirty)(this); }

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

void CAJointObject::GetBone(Matrix &m, Real &len) { CALibCall(jointGetBone)(this,m,len); }
CAWeightTag *CAJointObject::GetWeightTag(LONG &index) { CALibCallR(NULL,jointGetWeightTag)(this,index); }

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

BrushBaseLibrary *lib_brushbase = NULL;

static BrushBaseLibrary *CheckBrushBaseLibrary(LONG offset)
{
	return (BrushBaseLibrary*)CheckLib(LIBRARY_BRUSH,offset,(C4DLibrary**)&lib_brushbase);
}

#define BrushBaseLibraryCall(b) 		BrushBaseLibrary *lib = CheckBrushBaseLibrary(LIBOFFSET(BrushBaseLibrary, b)); \
															if (!lib || !lib->b) return; \
															(((iBrushBase*)this)->*lib->b)

#define BrushBaseLibraryCallR(a,b)  BrushBaseLibrary *lib = CheckBrushBaseLibrary(LIBOFFSET(BrushBaseLibrary, b)); \
															if (!lib || !lib->b) return a; \
															return (((iBrushBase*)this)->*lib->b)

BrushBase* BrushBase::Alloc()
{
	BrushBaseLibrary *lib = CheckBrushBaseLibrary(LIBOFFSET(BrushBaseLibrary,Alloc)); if (!lib) return NULL;
	return (BrushBase*)lib->Alloc();
}

void BrushBase::Free(BrushBase *&p)
{
	if (!p) return;
	BrushBaseLibrary *lib = CheckBrushBaseLibrary(LIBOFFSET(BrushBaseLibrary,Free)); if (!lib) return;
	iBrushBase* i = (iBrushBase*)p;
	lib->Free(i);
	p = NULL;
}

Bool BrushBase::InitTool(BaseDocument* doc, BaseContainer& data, BaseThread* bt, BrushToolData *tool) { BrushBaseLibraryCallR(FALSE,InitTool)(doc,data,bt,tool); }
void BrushBase::FreeTool(BaseDocument* doc, BaseContainer& data) { BrushBaseLibraryCall(FreeTool)(doc,data); }
void BrushBase::InitDefaultSettings(BaseDocument *doc, BaseContainer &data) { BrushBaseLibraryCall(InitDefaultSettings)(doc,data); }
Bool BrushBase::GetDEnabling(BaseDocument* doc, BaseContainer& data, const DescID& id, GeData& t_data, LONG flags, const BaseContainer* itemdesc) { BrushBaseLibraryCallR(FALSE,GetDEnabling)(doc,data,id,t_data,flags,itemdesc); }
Bool BrushBase::SetDParameter(BaseDocument* doc, BaseContainer& data, const DescID& id, const GeData& t_data, LONG& flags) { BrushBaseLibraryCallR(FALSE,SetDParameter)(doc,data,id,t_data,flags); }
Bool BrushBase::GetDDescription(BaseDocument* doc, BaseContainer& data, Description* description, LONG& flags) { BrushBaseLibraryCallR(FALSE,GetDDescription)(doc,data,description,flags); }
Bool BrushBase::Message(BaseDocument *doc, BaseContainer &data, LONG type, void *t_data) { BrushBaseLibraryCallR(FALSE,Message)(doc,data,type,t_data); }
Bool BrushBase::GetCursorInfo(BaseDocument* doc, BaseContainer& data, BaseDraw* bd, Real x, Real y, BaseContainer& bc) { BrushBaseLibraryCallR(FALSE,GetCursorInfo)(doc,data,bd,x,y,bc); }
Bool BrushBase::MouseInput(BaseDocument* doc, BaseContainer& data, BaseDraw* bd, EditorWindow* win, const BaseContainer& msg) { BrushBaseLibraryCallR(FALSE,MouseInput)(doc,data,bd,win,msg); }
BrushVertexData *BrushBase::GetSelected(BaseDocument* doc, BaseContainer& data, BaseDraw* bd, LONG &vcnt, LONG x, LONG y, Real rad, BaseObject *op) { BrushBaseLibraryCallR(NULL,GetSelected)(doc,data,bd,vcnt,x,y,rad,op); }
Real BrushBase::GetCursor(LONG &x, LONG &y) { BrushBaseLibraryCallR(0.0,GetCursor)(x,y); }
void BrushBase::GetObjectInfo(BrushObjectData *data, BrushObjectInfo &info) { BrushBaseLibraryCall(GetObjectInfo)(data,info); }
Bool BrushBase::GetObjectInfo(BaseObject *op, BrushObjectInfo &info) { BrushBaseLibraryCallR(FALSE,GetObjectInfoOp)(op,info); }
BrushPixelData *BrushBase::GetObjectAt(LONG x, LONG y) { BrushBaseLibraryCallR(NULL,GetObjectAt)(x,y); }
Bool BrushBase::ValidateObjects(BaseDocument *doc, BaseContainer& data) { BrushBaseLibraryCallR(FALSE,ValidateObjects)(doc,data); }
Real BrushBase::GetFalloff(Real dst, LONG flags) { BrushBaseLibraryCallR(0.0,GetFalloff)(dst,flags); }
Bool BrushBase::GetObjects(BaseDocument *doc, AtomArray *objects) { BrushBaseLibraryCallR(FALSE,GetObjects)(doc,objects); }
Bool BrushBase::UpdateCache(BaseDocument *doc, BaseContainer& data, BaseDraw *bd, Bool force) { BrushBaseLibraryCallR(FALSE,UpdateCache)(doc,data,bd,force); }
Real *BrushBase::CalcSurfaceDistances(PolygonObject *pObject, BaseSelect *selected, Neighbor *pNeighbor, Vector *pNormals, Vector *pGlobalPoints, Real *pDistance) { BrushBaseLibraryCallR(NULL,CalcSurfaceDistances)(pObject,selected,pNeighbor,pNormals,pGlobalPoints,pDistance); }
Real *BrushBase::CalcSurfaceDistancesFromPoint(PolygonObject *pObject, LONG pindex, Neighbor *pNeighbor, Vector *pNormals, Vector *pGlobalPoints, Real *pDistance) { BrushBaseLibraryCallR(NULL,CalcSurfaceDistancesFromPoint)(pObject,pindex,pNeighbor,pNormals,pGlobalPoints,pDistance); }

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

Bool BrushToolData::InitTool(BaseDocument* doc, BaseContainer& data, BaseThread* bt)
{
	if (!m_pBrushBase) m_pBrushBase=BrushBase::Alloc();
	if (!m_pBrushBase) return FALSE;
	return m_pBrushBase->InitTool(doc,data,bt,this);
}
void BrushToolData::FreeTool(BaseDocument* doc, BaseContainer& data)
{
	if (m_pBrushBase) m_pBrushBase->FreeTool(doc,data);
	BrushBase::Free(m_pBrushBase);
}

void BrushToolData::InitDefaultSettings(BaseDocument *doc, BaseContainer &data)
{
	if (!m_pBrushBase) m_pBrushBase=BrushBase::Alloc();
	if (m_pBrushBase) m_pBrushBase->InitDefaultSettings(doc,data);
}
Bool BrushToolData::GetDEnabling(BaseDocument* doc, BaseContainer& data, const DescID& id, GeData& t_data, LONG flags, const BaseContainer* itemdesc) { return (m_pBrushBase)?m_pBrushBase->GetDEnabling(doc,data,id,t_data,flags,itemdesc):FALSE; }
Bool BrushToolData::SetDParameter(BaseDocument* doc, BaseContainer& data, const DescID& id, const GeData& t_data, LONG& flags) { return (m_pBrushBase)?m_pBrushBase->SetDParameter(doc,data,id,t_data,flags):FALSE; }
Bool BrushToolData::GetDDescription(BaseDocument* doc, BaseContainer& data, Description* description, LONG& flags)
{
	if (!SUPER::GetDDescription(doc,data,description,flags)) return FALSE;
	return (m_pBrushBase)?m_pBrushBase->GetDDescription(doc,data,description,flags):FALSE;
}
Bool BrushToolData::Message(BaseDocument *doc, BaseContainer &data, LONG type, void *t_data) { return (m_pBrushBase)?m_pBrushBase->Message(doc,data,type,t_data):FALSE; }
Bool BrushToolData::GetCursorInfo(BaseDocument* doc, BaseContainer& data, BaseDraw* bd, Real x, Real y, BaseContainer& bc) { return (m_pBrushBase)?m_pBrushBase->GetCursorInfo(doc,data,bd,x,y,bc):FALSE; }
Bool BrushToolData::MouseInput(BaseDocument* doc, BaseContainer& data, BaseDraw* bd, EditorWindow* win, const BaseContainer& msg) { return (m_pBrushBase)?m_pBrushBase->MouseInput(doc,data,bd,win,msg):FALSE; }
