/****************************************************************************************

		ModelerView.cpp

		Copyright (c)1990 - 1999 MetaCreations. All rights reserved.

		Author:	Jerome Bignon
		Date:	05/18/99

		Revision History

		when		who			what & why
		==========	==========	======================================================
		06/27/99	cph			added include for MCCountedPtrHelper.h
		06/11/99	Jerome		Added animation and saving
		05/18/99	Jerome		Creation

*****************************************************************************************/

#include <math.h>

#include "ModelerView.h"
#include "ModelerActions.h"
#include "COMSafeUtilities.h"
#include "IMCGraphicContext.h"
#include "IShUtilities.h"
#include "IMFResponder.h"
#include "TreePrim.h"
#include "COMUtilities.h"
#include "MCCountedPtrHelper.h"
#include "I3DShModule.h"

const MCGUID IID_IModelerView ( R_IID_IModelerView );
const MCGUID CLSID_ModelerView ( R_CLSID_ModelerView );

TMCRGBColor PenColor;

MCCOMErr ModelerView::QueryInterface(const MCIID& riid, void** ppvObj)
{
	if (MCIsEqualIID(riid, IID_IModelerView))
	{
		TMCCountedGetHelper<IModelerView>	result(ppvObj);
		result = this;
		return MC_S_OK;
	}
	else
		return TBasicPart::QueryInterface(riid, ppvObj);
}

ModelerView::ModelerView()
{
	fTreeModeler = NULL;
	fCameraPos.x = 150;
	fCameraPos.y = 300;
	ViewSide = 4;
	fZoom = 25.0f;
	fbackgroundColor.rr = 0;
	fbackgroundColor.gg = 0;
	fbackgroundColor.bb = 0;
}

uint32 ModelerView::AddRef()
{
	return TBasicPart::AddRef();
}



TMCPoint TreePoint3Dto2D( TVector3 *v , int16 numView, real zoom )
{
	TMCPoint pt;
	int16 v1,v2;
	short z,xsign;
	
	switch ( numView )
	{
		case  1 :
			v1 = 0; v2 = 2; z=0;xsign = 1;
			break;
		case  3 :
			v1 = 0; v2 = 2; z=0;xsign = -1;
			break;		
		case  6 :
			v1 = 1; v2 = 2; z=0;xsign = -1;
			break;
		case  4 :
			v1 = 1; v2 = 2; z=0;xsign = 1;
			break;
		case  8 :
			v1 = 0; v2 = 1; z=-100;xsign = 1;
			break;
		case  2 :
			v1 = 0; v2 = 1; z=-100;xsign = -1;
			break;		
		default :
			v1 = 1; v2 = 2; z=0;xsign = -1;
			break;		
	}
	
	pt.x = xsign*(short)((*v)[v1] * zoom  ) + 150   ;
	pt.y =      -(short)((*v)[v2] * zoom  ) + 300 +z;
	
	return pt;
}

void DrawTree( TFacet3D* facets, DrawTreePrivData* privData )
{
	IMCGraphicContext* fGC = (IMCGraphicContext*) privData->fGC;
	int16 numView = privData->fNumView;
	real zoom  = privData->fZoom;
	TMCPoint pt0,pt1,pt2;
	
	pt0 = TreePoint3Dto2D( &(facets->fVertices[0].fVertex) , numView , zoom );
	pt1 = TreePoint3Dto2D( &(facets->fVertices[1].fVertex) , numView , zoom );
	pt2 = TreePoint3Dto2D( &(facets->fVertices[2].fVertex) , numView , zoom );

	if ( fGC )
	{
		fGC->DrawLine( pt0.x, pt0.y , pt1.x, pt1.y  );
		fGC->DrawLine( pt0.x, pt0.y , pt2.x, pt2.y  );
		fGC->DrawLine( pt2.x, pt2.y , pt1.x, pt1.y  );
	}
}

void ModelerView::SelfDraw(IMCGraphicContext* graphicContext, const TMCRect& inZone)
{
	PenColor.rr = 30000;
	PenColor.gg = 45535;
	PenColor.bb = 30000;

	graphicContext->FillRect( inZone , fbackgroundColor);
	graphicContext->SetPen( kCopyPen , kSolidPen , 1 , PenColor);

	if ( GetModelerNoAddRef() )
	{
		DrawTreePrivData PrivData;		
		
		// Nbr branches total of the tree : ----------------------------
		TMCCountedPtr<TreeData> treeData;
		GetModelerNoAddRef()->GetTreePrimNoAddRef()->GetData(&treeData);		

		uint32 totalBranches = 1;
		uint16 i;

		for(i=1;i<=treeData->fRecursiv;i++) 
			totalBranches += RealPow(treeData->fNbBranches,i);
		
		PrivData.fGC = graphicContext;
		PrivData.fNumView = ViewSide;		
		PrivData.fZoom    = fZoom;

		TMCCountedPtr<FacetMesh> fmesh;

		GetModelerNoAddRef()->GetI3DExExPrimNoAddRef()->GetFacetMesh(uint32(0), &fmesh);
		
		FacetMeshFacetIterator facetIterator;
		facetIterator.Initialize(fmesh);
		TFacet3D facet;

		for (facetIterator.First(); facetIterator.More(); facetIterator.Next())
		{
			facet = facetIterator.GetFacet();
			DrawTree(&facet, &PrivData);
		}	
		
		
	}
}


void ModelerView::SetBackgroundColor( const TMCRGBColor &rgbcolor )
{
	if ( (fbackgroundColor.rr != rgbcolor.rr) || (fbackgroundColor.gg != rgbcolor.gg) || (fbackgroundColor.bb != rgbcolor.bb))
	{
		fbackgroundColor = rgbcolor;
	}
}	


Modeler*	ModelerView::GetModelerNoAddRef()
{ 	
	return fTreeModeler; 
}
	
void	ModelerView::SetModeler( Modeler* TheModeler )
{ 
	fTreeModeler = TheModeler; 
}

boolean ModelerView::SelfKeyDown(TMCPlatformEvent* event)
{
 	boolean result=true;

	switch( event->fKey )
	{
		case '1' :				
		case '2' :
		case '3' :
		case '4' :
		case '6' :
		case '8' :						
			SetViewSide( event->fChar - '0' );
			break;					
		case '+' :
			SetZoomPlus();			
			fThisPart->Invalidate();
			break;
		case '-' :
			SetZoomMinus();			
			fThisPart->Invalidate();
			break;
		default:
			result=false;
	}
	
	return result;
}

TMFEventResult ModelerView::SelfMouseDown(const TMCPoint& inWhere, const TMCPlatformEvent& inEvent)
{	
	int32 Tool = 9400;	// This way the default Tool is the selection

	gMenuUtilities->GetCurrentGlobalTool( Tool );

	switch ( Tool )
	{					
		case 9400 :	//Selection
			{
				TMCCountedPtr<IShMouseAction> action;
				TMCCountedPtr<TreeData> treedata;
				TMCPoint mouse;	 
		
				mouse.x = inWhere.x;
				mouse.y = inWhere.y;

				if (GetModelerNoAddRef()->GetTreePrimNoAddRef()) 
					GetModelerNoAddRef()->GetTreePrimNoAddRef()->GetData(&treedata);

				TMCCountedPtr<IMFResponder> context;
				QueryInterface(IID_IMFResponder, (void**) &context);

				TMCCountedPtr<IMFPart>		part;
				QueryInterface(IID_IMFPart, (void**) &part);

				ModelerMouseAction::Create(&action,  treedata , GetModelerNoAddRef());

				gActionManager->PostMouseAction( action,inEvent.fActionNumber,context,part,mouse);
			}
			break;
		
		case 9402 :	// Our ToolAction								
			break;				

		case 9420 :	// Zoom +
			{
				SetZoomPlus();	
				GetThisPartNoAddRef()->Invalidate();
				GetThisPartNoAddRef()->ProcessUpdatesPart();
			}
			break;

		case 9421 :	// Zoom -			
			{
				SetZoomMinus();
				GetThisPartNoAddRef()->Invalidate();
				GetThisPartNoAddRef()->ProcessUpdatesPart();
			}
			break;

		case 9422 :	// Zoom 1:1
			{
				SetZoom11(); 
				GetThisPartNoAddRef()->Invalidate();
				GetThisPartNoAddRef()->ProcessUpdatesPart();
			}
			break;				
	}
	return TMFEventResult(true, true);
}


void	ModelerView::SetViewSide( int16 ViewNumber )
{ 
	ViewSide = ViewNumber; 
	GetThisPartNoAddRef()->ProcessUpdatesPart(); 
}