#include "c4d_objectplugin.h"
#include "c4d_memory.h"
#include "c4d_general.h"
#include "c4d_tools.h"
#include "c4d_basebitmap.h"
#include "c4d_file.h"
#include "c4d_resource.h"
#include "c4d_baseobject.h"
#include "c4d_basedraw.h"

void ObjectData::GetDimension(PluginObject *op, Vector *mp, Vector *rad) 
{
}

Bool ObjectData::Draw(PluginObject *op, LONG drawpass, BaseDraw *bd, BaseDrawHelp *bh) 
{ 
	if (drawpass!=DRAWPASS_HANDLES) return TRUE;

	LONG	 i;
	Vector p;
	LONG   cnt = GetHandleCount(op);
	if (!cnt) return TRUE;

	Matrix mg=bh->GetMg();
	bd->SetPen(GetWorldColor(COLOR_ACTIVEPOINT));
	for (i=0; i<cnt; i++)
	{
		p = GetHandle(op,i)*mg;
		bd->Handle3D(p,HANDLE_BIG);
		bd->Line3D(Vector(0.0,0.0,0.0)*mg,p);
	}
	return TRUE;
}

Vector ObjectData::GetHandle(PluginObject *op, LONG i)
{
	return 0.0;
}

void ObjectData::SetHandle(PluginObject *op, LONG i, Vector p)
{
}

LONG ObjectData::GetHandleCount(PluginObject *op)
{
	return 0;
}

LONG ObjectData::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<GetHandleCount(op); i++)
	{
		p = GetHandle(op,i);
		if (bd->PointInRange(p*mg,x,y)) 
		{
			ret=i;
			if (!(qualifier&QUALIFIER_SHIFT)) break;
		}
	}
	return ret;
}

Bool ObjectData::MoveHandle(PluginObject *op, PluginObject *undo, const Matrix &tm, LONG hit_id, LONG qualifier) 
{ 
	Matrix mg=op->GetMg(),mi=!mg;

	Vector p = ((ObjectData*)undo->GetNodeData())->GetHandle(undo,hit_id);
	SetHandle(op,hit_id,tm*p);

	return TRUE;
}

SplineObject* ObjectData::GetContour(PluginObject *op, BaseDocument *doc, Real lod, BaseThread *bt) 
{ 
	return NULL; 
}

BaseObject* ObjectData::GetVirtualObjects(PluginObject *op, HierarchyHelp *hh) 
{ 
	return NULL; 
}

Bool ObjectData::ModifyObject(PluginObject *op, BaseDocument *doc, BaseObject *mod, const Matrix &op_mg, const Matrix &mod_mg, Real lod, LONG flags, BaseThread *thread) 
{ 
	return TRUE; 
}

void ObjectData::CheckDirty(PluginObject *op, BaseDocument *doc) 
{
}

void ObjectData::ModifyParticles(PluginObject *op, Particle *pp, BaseParticle *ss, LONG pcnt, Real diff)
{
}

Bool ObjectData::AddToExecution(PluginObject *op, PriorityList *list)
{
	return FALSE;
}

LONG ObjectData::Execute(PluginObject *op, BaseDocument *doc, BaseThread *bt, LONG priority, LONG flags)
{
	return EXECUTION_RESULT_OK;
}

static void FillObjectPlugin(OBJECTPLUGIN *np, DataAllocator *npalloc, LONG info, LONG disklevel, BaseBitmap *icon, BaseBitmap *icon_small, void *emulation)
{
	FillNodePlugin(np,info,npalloc,icon_small,disklevel,emulation);

	np->command_icon				= icon;
	np->GetDimension				= &ObjectData::GetDimension;
	np->Draw								= &ObjectData::Draw;
	np->DetectHandle				= &ObjectData::DetectHandle;
	np->MoveHandle					= &ObjectData::MoveHandle;
	np->Execute							= &ObjectData::Execute;
	np->AddToExecution			= &ObjectData::AddToExecution;
}

Bool RegisterObjectPlugin(LONG id, const String &str, LONG info, DataAllocator *g, const String &description, LONG disklevel)
{
	return RegisterObjectPlugin(id,str,info,g,description,NULL,NULL,disklevel,NULL);
}

Bool RegisterObjectPlugin(LONG id, const String &str, LONG info, DataAllocator *npalloc, const String &description, String icon, String icon_small, LONG disklevel)
{
	Bool ok=FALSE;

	AutoAlloc<BaseBitmap> icon1;
	AutoAlloc<BaseBitmap> icon2;

	if (icon1 && icon1->Init(GeGetPluginPath()+String("res")+icon)==IMAGE_OK &&
	    icon2 && icon2->Init(GeGetPluginPath()+String("res")+icon_small)==IMAGE_OK)
		ok=RegisterObjectPlugin(id,str,info,npalloc,description,icon1,icon2,disklevel);

	return ok;
}

Bool RegisterObjectPlugin(LONG id, const String &str, LONG objectinfo, DataAllocator *npalloc, const String &description, BaseBitmap *icon, BaseBitmap *icon_small, LONG disklevel, void *emulation)
{
	if (description.Content() && !RegisterDescription(id,description)) return FALSE;

	OBJECTPLUGIN np;
	ClearMem(&np,sizeof(np));
	FillObjectPlugin(&np,npalloc,objectinfo,disklevel,icon,icon_small,emulation);

	if (objectinfo&OBJECT_MODIFIER)
	{
		np.CheckDirty		= &ObjectData::CheckDirty;
		np.ModifyObject	= &ObjectData::ModifyObject;
	}
	else if (objectinfo&OBJECT_SPLINE)
		np.GetContour = &ObjectData::GetContour;
	else if (objectinfo&OBJECT_GENERATOR)
		np.GetVirtualObjects = &ObjectData::GetVirtualObjects;
	else if (objectinfo&OBJECT_PARTICLEMODIFIER)
		np.ModifyParticles = &ObjectData::ModifyParticles;

	return GeRegisterPlugin(C4DPL_OBJECT,id,str,&np,sizeof(np));
}
