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

		ModelerActions.cpp

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

		Author:	Jerome Bignon
		Date:	05/26/99

		Revision History

		when		who			what & why
		==========	==========	======================================================
		06/27/99	cph			added include for MCCountedPtrHelper.h
		05/26/99	Jerome		Creation

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

#include "math.h"
#include "ModelerActions.h"
#include "ModelerDef.h"
#include "IShUtilities.h"
#include "IMCGraphicContext.h"
#include "I3DShModule.h"
#include "MCCountedPtrHelper.h"


void ModelerAction::Create(	IShAction**	outAction,
							TreeData* treedata,
							Modeler* modeler )
{
	TMCCountedCreateHelper<IShAction> result(outAction);
	result = new ModelerAction( treedata, modeler );
}

ModelerAction::ModelerAction(TreeData* treedata, Modeler* modeler)
{
	fNewTreeData = treedata;
	fModeler = modeler;
}

MCCOMErr ModelerAction::Do()
{
	fModeler->GetTreePrimNoAddRef()->GetData(&fOldTreeData);
	if (fModeler->GetTreePrimNoAddRef()->SetData( fNewTreeData ) )
		fModeler->GetI3DShPrimNoAddRef()->ChangedData();
	fModeler->ImmediateUpdate();

	return MC_S_OK;
}

MCCOMErr ModelerAction::Undo()
{	
	if ( fModeler->GetTreePrimNoAddRef()->SetData( fOldTreeData ) )
		fModeler->GetI3DShPrimNoAddRef()->ChangedData();
	fModeler->ImmediateUpdate();

	return MC_S_OK;
}

MCCOMErr ModelerAction::Redo()
{
	if ( fModeler->GetTreePrimNoAddRef()->SetData( fNewTreeData ) )
		fModeler->GetI3DShPrimNoAddRef()->ChangedData();
	fModeler->ImmediateUpdate();

	return MC_S_OK;
}

MCCOMErr ModelerAction::GetName(TMCString& name)
{
	TBasicAction::GetName( name );
	return MC_S_OK;
}

boolean	ModelerAction::WillCauseChange()
{
	return true;
}

boolean	ModelerAction::CanUndo()
{ 
	return true; 
}
	

void ModelerAction::GetPartToRedraw(IMFPart** outPart, int32 stage)
{
	TMCCountedGetHelper<IMFPart> result(outPart);
	if (fModeler)
		result = fModeler->GetIMFPartNoAddRef();
}


// ModelerMouseAction -----------------------------------------------------------------

void ModelerMouseAction::Create(	IShMouseAction**	outAction,
									TreeData*			treedata,
									Modeler*			modeler )
{
	TMCCountedCreateHelper<IShMouseAction> result(outAction);
	result = new ModelerMouseAction(treedata, modeler);
}

ModelerMouseAction::ModelerMouseAction(TreeData* treedata ,Modeler* modeler)
{
	fNewTreeData = treedata;
	fModeler = (Modeler *)modeler;
	fNumView = fModeler->GetPartNoAddRef()->GetViewSide();
	fZoom    = fModeler->GetPartNoAddRef()->GetZoom();
	fActionNumber = 0;
	fModeler->GetTreePrimNoAddRef()->GetData(&fOldTreeData);
	fDataChanged = false;
}

MCCOMErr ModelerMouseAction::Do()
{		
	fDataChanged = fModeler->GetTreePrimNoAddRef()->SetData( fNewTreeData );	
	if ( fModeler->GetTreePrimNoAddRef()->GetIfDataChanged() )
	{
		fModeler->GetI3DShPrimNoAddRef()->ChangedData();
		fModeler->ImmediateUpdate();
	}
	return MC_S_OK;	
}

MCCOMErr ModelerMouseAction::Undo()
{	
	fDataChanged = fModeler->GetTreePrimNoAddRef()->SetData( fOldTreeData );	
	if ( fDataChanged )
	{
		fModeler->GetI3DShPrimNoAddRef()->ChangedData();
		fModeler->ImmediateUpdate();
	}
	return MC_S_OK;
}

MCCOMErr ModelerMouseAction::Redo()
{
	fDataChanged = fModeler->GetTreePrimNoAddRef()->SetData( fNewTreeData );
	if ( fDataChanged )
	{
		fModeler->GetI3DShPrimNoAddRef()->ChangedData();
		fModeler->ImmediateUpdate();
	}
	return MC_S_OK;
}

		
boolean	ModelerMouseAction::WillCauseChange()
{
	return fDataChanged;
}

boolean	ModelerMouseAction::CanUndo()
{ 
	return true; 
}

void ModelerMouseAction::GetPartToRedraw(IMFPart** outPart, int32 stage)
{
	TMCCountedGetHelper<IMFPart> result(outPart);
	if (fModeler)
		result = fModeler->GetIMFPartNoAddRef();
}

void ModelerMouseAction::Track(IMCGraphicContext* gc, int16 stage, TMCPoint& first, TMCPoint &prev, TMCPoint &cur,boolean moved, IShMouseAction**	nextAction)
{
	// Set nextAction to NULL if the tracking should stop and the action been discarded
	MCCOMErr	err = MC_S_OK;
	switch (stage)
	{
		case kBeginTracking :
			if (cur.x!=1 || cur.y!=1)
			{
				real angle;
				fCurrentPoint.x = (short)cur.x;
				fCurrentPoint.y = (short)cur.y;			
				angle = fModeler->GetTreePrimNoAddRef()->GetAngleAndPoint( &fCurrentPoint , &fContactPoint, fNumView, fZoom );
				if ( angle != 0.0 )
				{
					fSignAngle = ((fCurrentPoint.y-fContactPoint.y)>0) ? 1.0 : -1.0;	
					fActionNumber=1;
				}
				else 
				{
					err = MC_E_ABORT;
				}
			}
			break;

		case kContinueTracking :
		case kFinishTracking :
			if ( moved )
			{				
				fNewTreeData->fAngle += fSignAngle * (atan2( (real64)(cur.x-fContactPoint.x) , (real64)(cur.y-fContactPoint.y) ) - atan2( (real64)(fCurrentPoint.x-fContactPoint.x) , (real64)(fCurrentPoint.y-fContactPoint.y)));
				if ( fNewTreeData->fAngle < 2.0f*kRealDegToRad )		fNewTreeData->fAngle =  2.0f*kRealDegToRad; // mini is 2 deg
				if ( fNewTreeData->fAngle > 88.0f*kRealDegToRad )	fNewTreeData->fAngle = 88.0f*kRealDegToRad; // maxi is 88 deg
				fCurrentPoint.x = cur.x;
				fCurrentPoint.y = cur.y;							
			}			
			break;
	}

	if (err == MC_S_OK)
		TBasicMouseAction::Track( gc, stage, first, prev, cur, moved, nextAction );
	else
		*nextAction = NULL;
}

MCCOMErr  ModelerMouseAction::Feedback(IMCGraphicContext* gc, int16 stage,const TMCPoint& first,const TMCPoint &prev,const TMCPoint &cur,boolean moved,boolean show)
{
	switch( stage )
	{
		case kShBeginTracking :
			break;

		case kShContinueTracking:
			if ( moved && show )
			{				
				// Tree Update in real Time : we change fRecursiv (number of steps=2) to be faster.
				fNewTreeData->fRecursiv = 2;
				fModeler->GetTreePrimNoAddRef()->SetData( fNewTreeData );

				fModeler->GetIMFPartNoAddRef()->Invalidate();
				fModeler->GetIMFPartNoAddRef()->ProcessUpdatesPart();

				// Properties Update In real Time
				fNewTreeData->fRecursiv = fOldTreeData->fRecursiv; // fRecursiv take the correct
				fModeler->GetTreePrimNoAddRef()->SetData( fNewTreeData );

				fModeler->ImmediateUpdate();
			}
			break;

		case kShFinishTracking:
			fNewTreeData->fRecursiv = fOldTreeData->fRecursiv; //recover the good recursiv number			
			break;
	}
	return MC_S_OK;
}
	
MCCOMErr  ModelerMouseAction::Constrain(IMCGraphicContext* gc, int16 stage,const TMCPoint& first,const TMCPoint &prev,TMCPoint &cur,boolean moved)
{
	return MC_S_OK;
}

