/********************************************************************/
/* Copyright (c) 2019 System fugen G.K. and Yuzi Mizuno          */
/* All rights reserved.                                             */
/* ***************************************************** */
/********************************************************************/
#include "stdafx.h"
#include "Undo/CameraAction.h"
#include "fugenView.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

void fugenView::ExecChangeCameraSetting(
	const MGVector& axisx,
	const MGVector& axisy
){
	CCameraAction* pAct = new CCameraAction(this);
	pAct->SaveEnvParam(IAction::ACTION_UNDO);

	const MGConstructionPlane& cpl = cplane();
	update_viewing_environment(cpl.plane());

	// アクションではなく自分でリフレッシュ
	Invalidate(FALSE);

	pAct->Do(); // SetLastAction したいがための空操作。
	pAct->SaveEnvParam(IAction::ACTION_REDO);
}

/// 操作履歴がつくカメラ位置移動処理
void fugenView::ExecChangeViewport(
	const MGVector& eyeP,///The camera(eye) position vector that looks at the origin.
		///Only the direction is used.
		///The actual position is obtained by initializeViewingEnvironmentByBox().
	const MGVector& viewUpVector
){
	CCameraAction* pAct = new CCameraAction(this);
	pAct->SaveEnvParam(IAction::ACTION_UNDO);
	setEyePositionUpVector(eyeP,viewUpVector);
	set_perspective(false);

	//Update construction plane's direction.
	MGConstructionPlane& cpl=cplane();
	const MGPlane& pl=cpl.plane();
	const MGPosition& C=pl.root_point();
	MGUnit_vector Y(viewUpVector);
	MGUnit_vector X=Y*eyeP;
	cpl.set_plane(MGPlane(X,Y,C));

	// ここで実際にはカメラ変更。
	const MGBox& box = defaultBoxModel();
	initializeViewingEnvironmentByBox(box);

	// アクションではなく自分でリフレッシュ
	Invalidate(FALSE);

	pAct->Do(); // SetLastAction したいがための空操作。
	pAct->SaveEnvParam(IAction::ACTION_REDO);
}

void fugenView::ExecInitModel(const MGBox& box){
	CCameraAction* pAct = new CCameraAction(this);
	pAct->SaveEnvParam(IAction::ACTION_UNDO);

	// ここで実際にはカメラ変更。
	initializeViewingEnvironmentByBox(box);
	pAct->Do(); // SetLastAction したいがための空操作。
	pAct->SaveEnvParam(IAction::ACTION_REDO);
}

void fugenView::ExecPanZoom(const MGBox& box){
	if(box.empty())
		return;
	CCameraAction* pAct = new CCameraAction(this);
	pAct->SaveEnvParam(IAction::ACTION_UNDO);

	// ここで実際にはカメラ変更。
	pan_zoom(box);
	Invalidate(FALSE); // 自力で再描画

	pAct->Do(); // SetLastAction したいがための空操作。
	pAct->SaveEnvParam(IAction::ACTION_REDO);
}

void fugenView::ExecPan(
	double dHorz,
	double dVert
){
	CCameraAction* pAct = new CCameraAction(this);
	pAct->SaveEnvParam(IAction::ACTION_UNDO);
	translate(dHorz, dVert);
	Invalidate(FALSE);
	pAct->Do();
	pAct->SaveEnvParam(IAction::ACTION_REDO);
}

void fugenView::ExecPanZoom(int x0, int y0, int x1, int y1){
	if(x1==x0 || y0==y1)
		return;

	if(x1<x0){
		int x0Save=x0;
		x0=x1;
		x1=x0Save;
	}
	if(y1<=y0){
		int y0Save=y0;
		y0=y1;
		y1=y0Save;
	}
	CCameraAction* pAct = new CCameraAction(this);
	pAct->SaveEnvParam(IAction::ACTION_UNDO);
	pan_zoom(x0, y0, x1, y1);
	Invalidate(FALSE);

	// 二度目の SaveEnvParam 前に Do() を呼び出し、
	// SetLastAction のみを実行させる。
	pAct->Do();
	pAct->SaveEnvParam(IAction::ACTION_REDO);
}

void fugenView::ExecRotate(
	float dAngle,
	float dX,
	float dY,
	float dZ){
	CCameraAction* pAct = new CCameraAction(this);
	pAct->SaveEnvParam(IAction::ACTION_UNDO);

	rotate(dAngle, dX, dY, dZ);

	Invalidate(FALSE);
	pAct->Do();
	pAct->SaveEnvParam(IAction::ACTION_REDO);
}

void fugenView::ExecZoom(double dFactor, const CPoint* cpoint){
	CCameraAction* pAct = new CCameraAction(this);
	pAct->SaveEnvParam(IAction::ACTION_UNDO);
	int center[2];
	int* centerP = nullptr;
	if(cpoint){
		change_sc(*cpoint, center[0], center[1]);
		centerP = center;
	}
	scale(dFactor, centerP);
	Invalidate(FALSE);

	// 二度目の SaveEnvParam 前に Do() を呼び出し、
	// SetLastAction のみを実行させる。
	pAct->Do();
	pAct->SaveEnvParam(IAction::ACTION_REDO);
}
