// fk_TrackBallクラス
// マウスでの自由な視点操作を提供します。

#include "TrackBall.h"

// コンストラクタ
fk_TrackBall::fk_TrackBall(fk_Window *p_fk_win, fk_Model *p_camera)
{
	// ポインタ受け取り
	fk_win = p_fk_win;
	camera = p_camera;
	// ウィンドウオーバー時に座標を返さないかどうか
	overCheck = false;
	// 処理量初期値
	divPos = 10.0;
	divLook = 200.0;
	divDist = 1.0;

	echoX = 0;
	echoY = 0;

	lookButton = FK_MOUSE3;
	distButton[0] = FK_MOUSE1;
	distButton[1] = FK_MOUSE3;
	moveButton = FK_MOUSE2;

	bEcho = false;

	return;
}

// カメラの変更
void fk_TrackBall::setCamera(fk_Model *p_camera)
{
	// ポインタ受け取り
	camera = p_camera;

	return;
}

// 注視点の変更
void fk_TrackBall::setLookTo(fk_Vector vec)
{
	// 注視点受け取り
	lookPos = vec;
	camera->glFocus(lookPos);

	return;
}

// カメラポインタは渡されているか
bool fk_TrackBall::isSetCamera()
{
	if(camera != NULL) return true;
	else return false;
}

// ３人称視点位置制御
void fk_TrackBall::controlLookTo()
{
	// 初回クリック時
	if(fk_win->getMouseStatus(lookButton, overCheck) & !lookClick) {
		fk_win->getMousePosition(&oldX, &oldY, overCheck);
		lookClick = true;
		echoX = 0;
		echoY = 0;
	// クリック継続時
	} else if(fk_win->getMouseStatus(lookButton, overCheck) & lookClick) {
		fk_win->getMousePosition(&nowX, &nowY, overCheck);
		camera->glRotateWithVec(lookPos, fk_Y, (double)(oldX - nowX)/divLook);
		camera->glRotateWithVec(lookPos, lookPos+(camera->getVec()^camera->getUpVec()), (double)(oldY - nowY)/divLook);
		echoX = oldX - nowX;
		echoY = oldY - nowY;
		oldX = nowX;
		oldY = nowY;
	// リリース時
	} else {
		lookClick = false;
		if(bEcho) {
			camera->glRotateWithVec(lookPos, fk_Y, (double)echoX/divLook);
			camera->glRotateWithVec(lookPos, lookPos+(camera->getVec()^camera->getUpVec()), (double)echoY/divLook);
		}
	}
	// 注視点を向き続ける
	// camera->glFocus(lookPos);

	return;
}

// ３人称視点距離制御
void fk_TrackBall::controlLookToDist()
{
	static fk_Vector	prePos;
	prePos = camera->getPosition();
	bool bShiftState = fk_win->getSpecialKeyStatus(FK_SHIFT_L, false) || fk_win->getSpecialKeyStatus(FK_SHIFT_R, false);

	camera->loTranslate(0.0, 0.0, fk_win->getMouseWheelStatus()*5.0);
	if((lookPos - camera->getPosition()).dist() < 5.0) camera->glMoveTo(prePos);

	// 初回クリック時
	if( (fk_win->getMouseStatus(distButton[0], overCheck) & fk_win->getMouseStatus(distButton[1], overCheck) & !distClick)
		|| (bShiftState & fk_win->getMouseStatus(lookButton, overCheck) & !distClick) ) {
		fk_win->getMousePosition(&oldX, &oldY, overCheck);
		distClick = true;
	// クリック継続時
	} else if( (fk_win->getMouseStatus(distButton[0], overCheck) & fk_win->getMouseStatus(distButton[1], overCheck) & distClick)
		|| (bShiftState & fk_win->getMouseStatus(lookButton, overCheck) & distClick) ) {
		fk_win->getMousePosition(&nowX, &nowY, overCheck);
		camera->loTranslate(0.0, 0.0, (double)(nowY - oldY)/divPos + (double)(oldX - nowX)/divPos);	// 左右ドラッグでズーム操作を可能にした
		if((lookPos - camera->getPosition()).dist() < divDist) camera->glMoveTo(prePos);
		fk_win->getMousePosition(&oldX, &oldY, overCheck);
	// リリース時
	} else {
		distClick = false;
	}
	// 注視点を向き続ける
	// camera->glFocus(lookPos);

	return;
}

// ３人称視点注視点制御
void fk_TrackBall::controlLookToMove()
{
	// 初回クリック時
	if(fk_win->getMouseStatus(moveButton, overCheck) & !moveClick) {
		fk_win->getMousePosition(&oldX, &oldY, overCheck);
		moveClick = true;
	// クリック継続時
	} else if(fk_win->getMouseStatus(moveButton, overCheck) & moveClick) {
		static fk_Vector prePos;

		prePos = camera->getPosition();
		fk_win->getMousePosition(&nowX, &nowY, overCheck);
		camera->loTranslate(-(double)(nowX - oldX)/divPos, (double)(nowY - oldY)/divPos, 0.0);
		lookPos += camera->getPosition() - prePos;
		fk_win->getMousePosition(&oldX, &oldY, overCheck);
	// リリース時
	} else {
		moveClick = false;
	}
	// 注視点を向き続ける
	// camera->glFocus(lookPos);

	return;
}

// ３人称視点ショートカット制御
void fk_TrackBall::controlLookToSC()
{
	static double prevDist;
	prevDist = camera->getPosition().dist();

	if(fk_win->getKeyStatus('2', false) || Fl::get_key(FL_KP+'2')) {
		camera->glMoveTo(cos(FK_PI/2.0)*prevDist, 0.0, sin(FK_PI/2.0)*prevDist);
	} else if(fk_win->getKeyStatus('3', false) || Fl::get_key(FL_KP+'3')) {
		camera->glMoveTo(cos(FK_PI/4.0)*prevDist, 0.0, sin(FK_PI/4.0)*prevDist);
	} else if(fk_win->getKeyStatus('6', false) || Fl::get_key(FL_KP+'6')) {
		camera->glMoveTo(cos(0.0)*prevDist, 0.0, sin(0.0)*prevDist);
	} else if(fk_win->getKeyStatus('9', false) || Fl::get_key(FL_KP+'9')) {
		camera->glMoveTo(cos(-FK_PI/4.0)*prevDist, 0.0, sin(-FK_PI/4.0)*prevDist);
	} else if(fk_win->getKeyStatus('8', false) || Fl::get_key(FL_KP+'8')) {
		camera->glMoveTo(cos(-FK_PI/2.0)*prevDist, 0.0, sin(-FK_PI/2.0)*prevDist);
	} else if(fk_win->getKeyStatus('7', false) || Fl::get_key(FL_KP+'7')) {
		camera->glMoveTo(cos(-FK_PI*3.0/4.0)*prevDist, 0.0, sin(-FK_PI*3.0/4.0)*prevDist);
	} else if(fk_win->getKeyStatus('4', false) || Fl::get_key(FL_KP+'4')) {
		camera->glMoveTo(cos(-FK_PI)*prevDist, 0.0, sin(-FK_PI)*prevDist);
	} else if(fk_win->getKeyStatus('1', false) || Fl::get_key(FL_KP+'1')) {
		camera->glMoveTo(cos(FK_PI*3.0/4.0)*prevDist, 0.0, sin(FK_PI*3.0/4.0)*prevDist);
	} else if(fk_win->getKeyStatus('5', false) || Fl::get_key(FL_KP+'5')) {
		camera->glMoveTo(0.0, prevDist, 0.0);
	} else if(fk_win->getKeyStatus('0', false) || Fl::get_key(FL_KP+'0')) {
		fk_Vector	tmpVec(cos(FK_PI*3.0/4.0)*prevDist, 0.66*prevDist, sin(FK_PI*3.0/4.0)*prevDist);
		tmpVec.normalize();
		camera->glMoveTo(tmpVec*prevDist);
	}

	// 注視点を向き続ける
	// camera->glFocus(lookPos);

	return;
}
