#include "lib_sculpt.h"
#include "c4d.h"

SculptLibrary *lib_sculpt = NULL;

static SculptLibrary *CheckSculptLib(LONG offset)
{
	return (SculptLibrary*)CheckLib(LIBRARY_SCULPT,offset,(C4DLibrary**)&lib_sculpt);
}

#define SculptLibCall(b) 			SculptLibrary *lib = CheckSculptLib(LIBOFFSET(SculptLibrary, b)); \
									if (!lib || !lib->b) return; \
									(lib->b)

#define SculptLibCallR(r,b)  		SculptLibrary *lib = CheckSculptLib(LIBOFFSET(SculptLibrary, b)); \
									if (!lib || !lib->b) return r; \
									return (lib->b)

//==============================================================================
SculptObject *SculptTag::GetSculptObject() { SculptLibCallR(NULL,sculpttagGetSculptObject)(this); }

//==============================================================================

//SculptLayerData
LONG						SculptLayerData::GetSubdivisionLevel() { SculptLibCallR(0,sculptlayerdataGetSubdivisionLevel)(this); }
LONG						SculptLayerData::GetPointCount() { SculptLibCallR(0,sculptlayerdataGetPointCount)(this); }
Bool						SculptLayerData::GetOffset(LONG index, Vector &offset) { SculptLibCallR(FALSE,sculptlayerdataGetOffset)(this,index, offset); }									
void						SculptLayerData::SetOffset(LONG index, const Vector &fullOffset) { SculptLibCall(sculptlayerdataSetOffset)(this,index, fullOffset); }			
void						SculptLayerData::AddOffset(LONG index, const Vector &offset) { SculptLibCall(sculptlayerdataAddOffset)(this,index, offset); }	
Bool						SculptLayerData::GetMask(LONG index, SReal &mask) { SculptLibCallR(FALSE,sculptlayerdataGetMask)(this,index, mask); }	
void						SculptLayerData::SetMask(LONG index, SReal mask) { SculptLibCall(sculptlayerdataSetMask)(this,index, mask); }	
void						SculptLayerData::AddToMask(LONG index, SReal mask) { SculptLibCall(sculptlayerdataAddToMask)(this,index, mask); }	
Bool						SculptLayerData::HasMask() { SculptLibCallR(FALSE,sculptlayerdataHasMask)(this); }	

//SculptLayerBase
Bool						SculptLayerBase::Select() { SculptLibCallR(FALSE,sculptlayerbaseSelect)(this);}
Bool						SculptLayerBase::IsVisible() { SculptLibCallR(FALSE,sculptlayerbaseIsVisible)(this);}
void						SculptLayerBase::SetVisible(Bool value) { SculptLibCall(sculptlayerbaseSetVisible)(this,value);}
Bool						SculptLayerBase::IsLocked()	{ SculptLibCallR(FALSE,sculptlayerbaseIsLocked)(this);}
void						SculptLayerBase::SetLocked(Bool value) { SculptLibCall(sculptlayerbaseSetLocked)(this,value);}
Real						SculptLayerBase::GetStrength()	{ SculptLibCallR(1.0,sculptlayerbaseGetStrength)(this);}
void						SculptLayerBase::SetStrength(Real value) { SculptLibCall(sculptlayerbaseSetStrength)(this,value);}

//SculptLayer
SculptLayerData*SculptLayer::GetSculptLayerData() { SculptLibCallR(NULL,sculptlayerGetSculptLayerData)(this); } 
LONG						SculptLayer::GetPointCount() { SculptLibCallR(0,sculptlayerGetPointCount)(this); }
Bool						SculptLayer::GetOffset(LONG index, Vector &offset) { SculptLibCallR(FALSE,sculptlayerGetOffset)(this,index, offset); }									
void						SculptLayer::SetOffset(LONG index, const Vector &fullOffset) { SculptLibCall(sculptlayerSetOffset)(this,index, fullOffset); }			
void						SculptLayer::AddOffset(LONG index, const Vector &offset) { SculptLibCall(sculptlayerAddOffset)(this,index, offset); }	
Bool						SculptLayer::GetMask(LONG index, SReal &mask) { SculptLibCallR(FALSE,sculptlayerGetMask)(this,index, mask); }	
void						SculptLayer::SetMask(LONG index, SReal mask) { SculptLibCall(sculptlayerSetMask)(this,index, mask); }	
void						SculptLayer::AddToMask(LONG index, SReal mask) { SculptLibCall(sculptlayerAddToMask)(this,index, mask); }	
Bool						SculptLayer::IsBaseLayer() { SculptLibCallR(FALSE,sculptlayerIsBaseLayer)(this);}
Bool						SculptLayer::HasMask() { SculptLibCallR(FALSE,sculptlayerHasMask)(this);}
Bool						SculptLayer::IsMaskEnabled() { SculptLibCallR(FALSE,sculptlayerIsMaskEnabled)(this); }	
void						SculptLayer::SetMaskEnabled(Bool value) { SculptLibCall(sculptlayerSetMaskEnabled)(this,value); }	

//Sculpt Object
LONG								SculptObject::GetSubdivisionCount() { SculptLibCallR(0,sculptobjGetSubdivisionCount)(this); }
PolygonObject*			SculptObject::GetPolygonCopy(LONG subdivisionLevel, Bool includeTopLevels) { SculptLibCallR(NULL,sculptobjGetPolygonCopy)(this,subdivisionLevel,includeTopLevels); }
PolygonObject *			SculptObject::GetOriginalObject() { SculptLibCallR(NULL,sculptobjGetOriginalObject)(this); }
LONG								SculptObject::GetPolygonCount()		{ SculptLibCallR(0,sculptobjGetPolygonCount)(this);	}
SculptLayerBase*		SculptObject::GetCurrentLayer()		{ SculptLibCallR(NULL,sculptobjGetCurrentLayer)(this);	}
LONG								SculptObject::GetCurrentLevel()		{ SculptLibCallR(0,sculptobjGetCurrentLevel)(this);	}
ULONG								SculptObject::GetMemoryUsage()		{ SculptLibCallR(0,sculptobjGetMemoryUsage)(this);		}
Bool								SculptObject::Hit(BaseDraw* bd, Real mx, Real my, SculptHitData  &hitData) { SculptLibCallR(FALSE,sculptobjHitScreen)(this,bd,mx,my,hitData);	}
Bool								SculptObject::Hit(const Vector &rayp, const Vector &rayv, SculptHitData  &hitData) { SculptLibCallR(FALSE,sculptobjHitObject)(this,rayp,rayv,hitData);	}
SculptLayer*				SculptObject::AddLayer() { SculptLibCallR(NULL,sculptobjAddLayer)(this);}
SculptFolder*				SculptObject::AddFolder() { SculptLibCallR(NULL,sculptobjAddFolder)(this);}
Bool								SculptObject::DeleteSelectedLayer() { SculptLibCallR(FALSE,sculptobjDeleteSelectedLayer)(this);}
void								SculptObject::Update() { SculptLibCall(sculptobjUpdate)(this); }
Bool								SculptObject::Subdivide() { SculptLibCallR(FALSE,sculptobjSubdivide)(this); } 
Bool								SculptObject::IncreaseSubdivisionLevel() { SculptLibCallR(FALSE,sculptobjIncreaseSubdivisionLevel)(this); } 
Bool								SculptObject::DecreaseSubdivisionLevel() { SculptLibCallR(FALSE,sculptobjDecreaseSubdivisionLevel)(this); } 
SculptLayerBase*		SculptObject::GetFirstLayer() { SculptLibCallR(FALSE,sculptobjGetFirstLayer)(this); } 
SculptLayer*				SculptObject::GetBaseLayer() { SculptLibCallR(FALSE,sculptobjGetBaseLayer)(this); } 
Bool								SculptObject::IsFrozen() { SculptLibCallR(FALSE,sculptobjIsFrozen)(this); } 
void								SculptObject::SetFrozen(Bool value) { SculptLibCall(sculptobjSetFrozen)(this,value); } 
void								SculptObject::UpdateCollision() { SculptLibCall(sculptobjUpdateCollision)(this); } 
void								SculptObject::NeedCollisionUpdate(Bool fullUpdate) { SculptLibCall(sculptobjNeedCollisionUpdate)(this,fullUpdate); } 
Bool								SculptObject::GetAllowDeformations() { SculptLibCallR(FALSE,sculptobjGetAllowDeformations)(this); }
void								SculptObject::SetAllowDeformations(Bool value) { SculptLibCall(sculptobjSetAllowDeformations)(this,value); }

//==============================================================================

#if 0 //TODO:  we have problem with  AutoAlloc<AtomArray>   apear to be undefined !?!?!
SculptObject *GetSelectedSculptObject(BaseDocument *doc)
{
	if(doc)
	{
		AutoAlloc<AtomArray> selection;
		doc->GetActiveObjects(selection, GETACTIVEOBJECTFLAGS_0);

		LONG a;
		for(a = 0; a < selection->GetCount(); ++a)
		{
			C4DAtom *atom = selection->GetIndex(a);

			if(atom && atom->IsInstanceOf(Obase))
			{
				BaseObject *pBase = (BaseObject*)atom;
				BaseTag *pTag = pBase->GetTag(Tsculpt);
				if(pTag)
				{				
					SculptTag *pSculptTag = (SculptTag*)pTag;
					return pSculptTag->GetSculptObject();
				}
			}
		}
	}
	return NULL;
}
#endif

BaseObject *GetCurrentStateObject(BaseObject *obj, BaseDocument *doc, Bool no_generate)
{
	ModelingCommandData cd;
	if (!obj) return NULL;

	BaseObject		*op = obj;
	BaseContainer bc;

	bc.SetBool(MDATA_CURRENTSTATETOOBJECT_NOGENERATE, no_generate);

	cd.doc = doc;
	cd.op = op;
	cd.bc = &bc;

	Bool	res = SendModelingCommand(MCOMMAND_CURRENTSTATETOOBJECT, cd);
	if (no_generate || !res || !cd.result) return NULL;

	BaseObject	*ro = (BaseObject *) cd.result->GetIndex(0);
	return ro;
}

SculptObject *MakeSculptObject(PolygonObject *poly, BaseDocument *doc)
{
	if(!poly) return NULL;
	SculptTag *pSculptTag  = (SculptTag*)poly->GetTag(Tsculpt);
	if(!pSculptTag) 
	{
		pSculptTag = (SculptTag*)poly->MakeTag(Tsculpt);
		if(!pSculptTag) return NULL;
		GetCurrentStateObject(poly,doc,TRUE);
	}
	return pSculptTag->GetSculptObject();
}



