/////////////////////////////////////////////////////////////
// CINEMA SDK : TOOLS  																		 //
/////////////////////////////////////////////////////////////
// VERSION    : CINEMA 4D																	 //
/////////////////////////////////////////////////////////////
// (c) 1989-2002 MAXON Computer GmbH, all rights reserved	 //
/////////////////////////////////////////////////////////////

// example code for a metaball painting tool

#include "c4d.h"
#include "c4d_symbols.h"

class LiquidToolData : public ToolData
{
	public:
		virtual Bool			MouseInput(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, EditorWindow *win, const BaseContainer &msg);
		virtual LONG			GetState(BaseDocument *doc);
		virtual Bool      GetCursorInfo(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, Real x, Real y, BaseContainer &bc);
		virtual LONG      Draw(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, BaseDrawHelp *bh, BaseThread *bt,LONG flags);

		virtual SubDialog*	AllocSubDialog(BaseContainer* bc);
};

LONG LiquidToolData::GetState(BaseDocument *doc)
{
	if (doc->GetMode()==Mpaint) return 0;
	return CMD_ENABLED;
}

Bool LiquidToolData::MouseInput(BaseDocument *doc, BaseContainer &data, BaseDraw *bd,EditorWindow *win, const BaseContainer &msg)
{
	Real mx = msg.GetReal(BFM_INPUT_X);
	Real my = msg.GetReal(BFM_INPUT_Y);
	LONG button;
	
	switch (msg.GetLong(BFM_INPUT_CHANNEL))
	{
		case BFM_INPUT_MOUSELEFT : button=KEY_MLEFT; break;
		case BFM_INPUT_MOUSERIGHT: button=KEY_MRIGHT; break;
		default: return TRUE;
	}
	
	BaseObject	*cl=NULL,*null=NULL,*op=NULL;
	Vector			p=bd->SW(Vector(mx,my,500.0));
	Real				dx,dy,rad=5.0;
	Bool				newmeta=FALSE;

	op = BaseObject::Alloc(Osphere);
	if (!op) return FALSE;

	null = BaseObject::Alloc(Ometaball);
	{
		null->GetDataInstance()->SetReal(METABALLOBJECT_SUBEDITOR,10.0);
		null->MakeTag(Tphong);
	}
	newmeta=TRUE;

	doc->AddUndo(UNDO_NEW,null);

	if (newmeta)
	{
		doc->InsertObject(null,NULL,NULL);
		doc->SetActiveObject(null);
		DrawViews(DA_ONLY_ACTIVE_VIEW|DA_NO_THREAD|DA_NO_ANIMATION);
	}

	BaseContainer bc;
	BaseContainer device;
	win->MouseDragStart(button,mx,my,MOUSEDRAG_DONTHIDEMOUSE|MOUSEDRAG_NOMOVE);
	while (win->MouseDrag(&dx,&dy,&device)==MOUSEDRAG_CONTINUE)
	{
		bc=BaseContainer();
		win->BfGetInputEvent(BFM_INPUT_MOUSE,&bc);
		if (bc.GetLong(BFM_INPUT_CHANNEL)==BFM_INPUT_MOUSEWHEEL)
		{
			rad+=bc.GetReal(BFM_INPUT_VALUE)/120.0;
			rad=FCut(rad,0.1,MAXRANGE);
			GePrint(RealToString(rad));
		}

		if (dx==0.0 && dy==0.0) continue;

		mx+=dx;
		my+=dy;
		cl=(BaseObject*)op->GetClone(0,NULL);
		if (!cl) break;
		
		cl->GetDataInstance()->SetReal(PRIM_SPHERE_RAD,rad);

		cl->SetPos(bd->SW(Vector(mx,my,500.0)));
		cl->InsertUnder(null);
		DrawViews(DA_ONLY_ACTIVE_VIEW|DA_NO_THREAD|DA_NO_ANIMATION);
	}

	if (win->MouseDragEnd()==MOUSEDRAG_ESCAPE)
	{
		doc->EndUndo();
		doc->DoUndo();
	}

	BaseObject::Free(op);

	EventAdd();
	return TRUE;
}

Bool LiquidToolData::GetCursorInfo(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, Real x,Real y,BaseContainer &bc)
{
	bc.SetString(RESULT_BUBBLEHELP,GeLoadString(IDS_PRIMITIVETOOL));
	bc.SetLong(RESULT_CURSOR,MOUSE_POINT_HAND);
	return TRUE;
}

LONG LiquidToolData::Draw(BaseDocument *doc, BaseContainer &data, BaseDraw *bd, BaseDrawHelp *bh, BaseThread *bt,LONG flags)
{
	Vector p[3] = { Vector(0,0,0),Vector(100,0,0),Vector(50,100,0)};
	Vector f[3] = { Vector(1,0,0),Vector(1,0,0),Vector(1,0,0)};
	bd->Polygon3D(p,f,FALSE);

	return DRAW_HANDLES|DRAW_AXIS;
}

class LiquidToolDialog: public SubDialog
{
	private:
		BaseContainer *data;
	public:
		LiquidToolDialog(BaseContainer *bc) { data = bc; }

		virtual Bool CreateLayout(void);
		virtual Bool InitValues(void);

		virtual Bool InitDialog(void);
		virtual Bool Command(LONG id,const BaseContainer &msg);
};

Bool LiquidToolDialog::CreateLayout(void)
{
	GroupBegin(0,BFH_SCALEFIT,1,0,"",0);
		GroupBegin(0,BFH_SCALEFIT,2,0,"",0);
			GroupSpace(4,1);

			AddStaticText(0,0,0,0,"R",0);
			AddEditSlider(1000,BFH_SCALEFIT);

			AddStaticText(0,0,0,0,"G",0);
			AddEditSlider(1001,BFH_SCALEFIT);

			AddStaticText(0,0,0,0,"B",0);
			AddEditSlider(1002,BFH_SCALEFIT);
		GroupEnd();

	GroupEnd();
	return TRUE;
}

Bool LiquidToolDialog::InitValues(void)
{
	return InitDialog();
}

Bool LiquidToolDialog::InitDialog(void)
{
	return TRUE;
}

Bool LiquidToolDialog::Command(LONG id,const BaseContainer &msg)
{
	return TRUE;
}

SubDialog* LiquidToolData::AllocSubDialog(BaseContainer* bc)
{
	return gNew LiquidToolDialog(bc); 
}

#define ID_LIQUIDTOOL 1000973

Bool RegisterPrimitiveTool(void)
{
	// decide by name if the plugin shall be registered - just for user convenience
	String name=GeLoadString(IDS_PRIMITIVETOOL); if (!name.Content()) return TRUE;
	return RegisterToolPlugin(ID_LIQUIDTOOL,name,0,"liquid.tif","C++ SDK Liquid Painting Tool",gNew LiquidToolData);
}
