// GUIObjPanel.cpp : implementation file
//

#include "stdafx.h"
#include "MW4GameEd2.h"
#include "GUIObjPanel.h"
#include "EdGUIObject.h"
#include "UndoManager.h"
#include "CameraController.h"
#include "Refresher.h"
#include "ObjProps.h"

#define Round(x) floor((x)+.5f)
#define TruncateFloat(x) ( Round( (x)*10000.0f)/10000.0f)

/////////////////////////////////////////////////////////////////////////////
// GUIObjPanel dialog


GUIObjPanel::GUIObjPanel(EdGUIObject *gobj,UndoCommand **cmd,CWnd* pParent /*=NULL*/)
: CPanelDlg(GUIObjPanel::IDD, pParent)
{
	MyObj=gobj;
	CmdLst=cmd;
	MyMultiProps=NULL;
	//{{AFX_DATA_INIT(GUIObjPanel)
	m_HElevation = 0.0f;
	m_SnapGround = FALSE;
	m_Pitch = 0.0f;
	m_PosX = 0.0f;
	m_PosY = 0.0f;
	m_PosZ = 0.0f;
	m_Roll = 0.0f;
	m_Yaw = 0.0f;
	//}}AFX_DATA_INIT
}

GUIObjPanel::GUIObjPanel(CObjProps *gobj,CWnd* pParent): CPanelDlg(GUIObjPanel::IDD, pParent)   // standard constructor
{
	MyMultiProps=gobj;
	MyObj=NULL;
	CmdLst=NULL;

	m_HElevation = 0.0f;
	m_SnapGround = FALSE;
	m_Pitch = 0.0f;
	m_PosX = 0.0f;
	m_PosY = 0.0f;
	m_PosZ = 0.0f;
	m_Roll = 0.0f;
	m_Yaw = 0.0f;

}

void GUIObjPanel::DoDataExchange(CDataExchange* pDX)
{
	CPanelDlg::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(GUIObjPanel)
	DDX_Text(pDX, IDC_ELEVATION, m_HElevation);
	DDV_MinMaxFloat(pDX, m_HElevation, -10000.f, 10000.f);
	DDX_Check(pDX, IDC_SNAP, m_SnapGround);
	DDX_Text(pDX, IDC_PITCH, m_Pitch);
	DDX_Text(pDX, IDC_POSX, m_PosX);
	DDV_MinMaxFloat(pDX, m_PosX, -1.e+008f, 1.e+008f);
	DDX_Text(pDX, IDC_POSY, m_PosY);
	DDV_MinMaxFloat(pDX, m_PosY, -10000.f, 10000.f);
	DDX_Text(pDX, IDC_POSZ, m_PosZ);
	DDV_MinMaxFloat(pDX, m_PosZ, -1.e+008f, 1.e+008f);
	DDX_Text(pDX, IDC_ROLL, m_Roll);
	DDX_Text(pDX, IDC_YAW, m_Yaw);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(GUIObjPanel, CPanelDlg)
//{{AFX_MSG_MAP(GUIObjPanel)
ON_BN_CLICKED(IDC_CLEARROT, OnClearrot)
ON_BN_CLICKED(IDC_CAMERA_LOOKAT, OnCameraLookAt)
ON_BN_CLICKED(IDC_CAMERA_LOOKFROM, OnCameraLookFrom)
ON_BN_CLICKED(IDC_MOVEOBJECT_TOFOV, OnMoveObjectToFOV)
ON_BN_CLICKED(IDC_MOVEOBJECT_TOCAMERA, OnMoveObjectToCamera)
ON_EN_KILLFOCUS(IDC_POSX, OnKillfocusPosx)
ON_EN_KILLFOCUS(IDC_POSY, OnKillfocusPosy)
ON_EN_KILLFOCUS(IDC_POSZ, OnKillfocusPosz)
ON_EN_KILLFOCUS(IDC_ELEVATION, OnKillfocusElevation)
	ON_EN_CHANGE(IDC_PITCH, OnChangePitch)
	ON_EN_CHANGE(IDC_POSX, OnChangePosx)
	ON_EN_CHANGE(IDC_POSY, OnChangePosy)
	ON_EN_CHANGE(IDC_POSZ, OnChangePosz)
	ON_EN_CHANGE(IDC_ROLL, OnChangeRoll)
	ON_EN_CHANGE(IDC_YAW, OnChangeYaw)
	ON_EN_CHANGE(IDC_ELEVATION, OnChangeElevation)
	ON_BN_CLICKED(IDC_SNAP, OnSnap)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// GUIObjPanel message handlers
BOOL GUIObjPanel::OnInitDialog() 
{
	CPanelDlg::OnInitDialog();
	Point3D loc;
	YawPitchRoll rot;
	
	Verify(!(MyMultiProps && MyObj));
	if(MyMultiProps==NULL)
	{
		m_HElevation=MyObj->GetHoverElevation();
		m_SnapGround=MyObj->GetSnapToGround();
		
		m_SavedMatrix = MyObj->GetMat();
		
		if (CameraController::GetInstance() != 0)
		{
			m_SavedYPR = CameraController::GetInstance()->GetYawPitchRange();
			m_SavedLookAt = CameraController::GetInstance()->GetLookAt();
		}
		
		m_SavedSnapToGround = MyObj->GetSnapToGround();
		
		loc=MyObj->GetPos();
		rot=(YawPitchRoll)MyObj->GetRot();
	}
	else
	{
		m_HElevation=MyMultiProps->GetHoverElev();
		m_SnapGround=MyMultiProps->GetSnap();
		
		loc=MyMultiProps->GetPos();
		rot=MyMultiProps->GetRot();
		
	}
	
	m_PosX=loc.x;
	m_PosY=loc.y;
	m_PosZ=loc.z;
	m_Roll=rot.roll*Degrees_Per_Radian;
	m_Yaw=rot.yaw*Degrees_Per_Radian;
	m_Pitch=rot.pitch*Degrees_Per_Radian;
	m_Roll=(float)TruncateFloat(m_Roll);
	m_Yaw=(float)TruncateFloat(m_Yaw);
	m_Pitch=(float)TruncateFloat(m_Pitch);
	UpdateData(FALSE);
	ElevationChange=PitchChange=RollChange=YawChange=PosXChange=PosYChange=PosZChange=SnapChange=false;
	
	return TRUE;  // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}

void GUIObjPanel::OnOK() 
{
	UpdateData(TRUE);
	
	Verify(!(MyMultiProps && MyObj));
	if(MyMultiProps!=NULL)
	{
		
		if(ElevationChange) MyMultiProps->SetHoverElev(m_HElevation);
		if(SnapChange)		MyMultiProps->SetSnap(m_SnapGround==TRUE?true:false);
		if(YawChange)		MyMultiProps->SetYaw(m_Yaw*Radians_Per_Degree);
		if(PitchChange)		MyMultiProps->SetPitch(m_Pitch*Radians_Per_Degree);
		if(RollChange)		MyMultiProps->SetRoll(m_Roll*Radians_Per_Degree);
		if(PosXChange)		MyMultiProps->SetPosX(m_PosX);
		if(PosYChange)		MyMultiProps->SetPosY(m_PosY);
		if(PosZChange)		MyMultiProps->SetPosZ(m_PosZ);
		
	}
	else
	{
		UndoCommand *cmd=NULL;
		
		MyObj->SetMat(m_SavedMatrix);
		
		MyObj->SetHoverElevation(m_HElevation);
		MyObj->SetSnapToGround(m_SnapGround==TRUE?true:false);
		
		MyObj->SavePos(&cmd);
		MyObj->SaveRot(&cmd);
		
		YawPitchRoll newrot=YawPitchRoll(m_Yaw*Radians_Per_Degree,m_Pitch*Radians_Per_Degree,m_Roll*Radians_Per_Degree);
		UnitQuaternion newrotquat;
		newrotquat=newrot;
		
		Point3D oldpos=MyObj->GetPos();
		Point3D posoffset,newpos=Point3D(m_PosX,m_PosY,m_PosZ);
		posoffset=newpos;
		posoffset-=oldpos;
		
		LinearMatrix4D mat(newpos);
		mat.BuildRotation(newrotquat);
		MyObj->SetMat(mat);
		
		if(*CmdLst==NULL)
		{
			*CmdLst=cmd;
		}
		else
		{
			(*CmdLst)->Attach(cmd);
		}
	}
	//CPanelDlg::OnOK();
}

void GUIObjPanel::OnCancel()
{
if(MyObj==NULL) return;
	MyObj->SetMat(m_SavedMatrix);
	
	if (CameraController::GetInstance() != 0)
	{
		CameraController::GetInstance()->SetYawPitchRange(m_SavedYPR);
		CameraController::GetInstance()->SetLookAt(m_SavedLookAt,true);
	}
	
	MyObj->SetSnapToGround(m_SavedSnapToGround);
	
	if (Refresher::Instance != 0)
	{
		Refresher::Instance->DrawRefresh();
	}
	//	CDialog::OnCancel();
}


void GUIObjPanel::OnClearrot() 
{
	m_Pitch=m_Yaw=m_Roll=0.0f;
	UpdateData(FALSE);
}

void GUIObjPanel::OnCameraLookAt()
{
if(MyObj==NULL) return;
	if ((CameraController::GetInstance() == 0) ||
		(Refresher::Instance == 0))
	{
		return;
	}
	
	if (CameraController::GetInstance()->StaysInsideBounds(MyObj->GetPos(),
		CameraController::GetInstance()->GetYawPitchRange()) == true)
	{
		CameraController::GetInstance()->SetLookAtMode(true);
		CameraController::GetInstance()->SetLookAt(MyObj->GetPos(),false);
		CameraController::GetInstance()->Update();
		Refresher::Instance->DrawRefresh();
	}
}

void GUIObjPanel::OnCameraLookFrom()
{
if(MyObj==NULL) return;
	if ((CameraController::GetInstance() == 0) ||
		(Refresher::Instance == 0))
	{
		return;
	}
	
	CameraController::GetInstance()->SetLookAtMode(false);
	YawPitchRoll yawpitchroll(MyObj->GetRot());
	
	YawPitchRange ypr(Two_Pi - yawpitchroll.yaw,
		Two_Pi - yawpitchroll.pitch,
		CameraController::GetInstance()->GetYawPitchRange().range);
	
	Stuff::LinearMatrix4D matrix(MyObj->GetMat());
	matrix.BuildLookFrom(ypr);
	
	ypr.yaw = yawpitchroll.yaw;
	ypr.pitch = yawpitchroll.pitch;
	
	if (CameraController::GetInstance()->StaysInsideBounds((Point3D)matrix,ypr) == true)
	{
		CameraController::GetInstance()->SetYawPitchRange(ypr);
		CameraController::GetInstance()->SetLookAt((Point3D)matrix,false);
		CameraController::GetInstance()->Update();
		Refresher::Instance->DrawRefresh();
	}
}

void GUIObjPanel::OnMoveObjectToFOV()
{
if(MyObj==NULL) return;
	if ((CameraController::GetInstance() == 0)||
		(Refresher::Instance == 0))
	{
		return;
	}
	
	MyObj->SetPos(CameraController::GetInstance()->GetLookAt());
	Refresher::Instance->DrawRefresh();
	
	Stuff::YawPitchRoll ypr(MyObj->GetMat());
	
	m_HElevation = 0;
	m_PosX = MyObj->GetPos().x;
	m_PosY = MyObj->GetPos().y;
	m_PosZ = MyObj->GetPos().z;
	
	UpdateData(FALSE);
}

void GUIObjPanel::OnMoveObjectToCamera()
{
if(MyObj==NULL) return;
	if ((CameraController::GetInstance() == 0) ||
		(Refresher::Instance == 0))
	{
		return;
	}
	
	MyObj->SetSnapToGround(false);
	
	Stuff::LinearMatrix4D matrix(CameraController::GetInstance()->GetLookAt());
	matrix.BuildLookAt(CameraController::GetInstance()->GetYawPitchRange());
	
	MyObj->SetMat(matrix);
	Refresher::Instance->DrawRefresh();
	
	m_SnapGround = false;
	
	m_HElevation = 0;
	m_Pitch = CameraController::GetInstance()->GetYawPitchRange().pitch * Degrees_Per_Radian;
	m_PosX = MyObj->GetPos().x;
	m_PosY = MyObj->GetPos().y;
	m_PosZ = MyObj->GetPos().z;
	m_Roll = 0;
	m_Yaw = CameraController::GetInstance()->GetYawPitchRange().yaw * Degrees_Per_Radian;
	
	UpdateData(FALSE);
}

void GUIObjPanel::OnKillfocusPosx() 
{
	UpdateData(TRUE);	// Done here for range validation because of funny way that OnOK is called
}

void GUIObjPanel::OnKillfocusPosy() 
{
	UpdateData(TRUE);	// Done here for range validation because of funny way that OnOK is called
}

void GUIObjPanel::OnKillfocusPosz() 
{
	UpdateData(TRUE);	// Done here for range validation because of funny way that OnOK is called
}

void GUIObjPanel::OnKillfocusElevation() 
{
	UpdateData(TRUE);	// Done here for range validation because of funny way that OnOK is called
}

void GUIObjPanel::OnChangePitch()		{PitchChange=true;}
void GUIObjPanel::OnChangePosx()		{PosXChange=true;}
void GUIObjPanel::OnChangePosy()		{PosYChange=true;}
void GUIObjPanel::OnChangePosz()		{PosZChange=true;}
void GUIObjPanel::OnChangeRoll()		{RollChange=true;}
void GUIObjPanel::OnChangeYaw()			{YawChange=true;}
void GUIObjPanel::OnChangeElevation()	{ElevationChange=true;}
void GUIObjPanel::OnSnap()				{SnapChange=true;}
