// CameraPosWnd.cpp : Implementation file
//


#include "stdafx.h"
#include "CameraPosWnd.h"
#include "CPCInfo.h"
#include "VAIBODef.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

// The window that contains an image frame has width: 108 and height: 84
// The actual drawing area is width: 104 and height: 80
// The local coordinates of the starting point are (52,20)

#define		DRAW_RECT_W		104		// Drawing range W
#define		DRAW_RECT_H		80		// Drawing range H
#define		FRAME_OFFSET	2

#define		POINT_HOME_X	( DRAW_RECT_W / 2 )				// Home position X coordinate
#define		POINT_HOME_Y	40/*20*/						// Home position Y coordinate
#define		HEIGHT_UP		( POINT_HOME_Y )				// The height of the top from the origin
#define		HEIGHT_DOWN		( DRAW_RECT_H - POINT_HOME_Y )	// The height of the bottom from the origin

/*
	Tilt range	(Top)		(Bottom)
	STAND	:	 20			-60
	SIT		:	-10			-75
	SLEEP	:	 20			-60
*/
// Allowable upward camera view.
const CameraPosRec	cameraParam[3] = {
	{ -32 ,		47 ,	0	},		// Sleep
	{ -10 ,		47,		0	},		// Sit
	{ -28 ,		45 ,	0	}		// Stand
};


/////////////////////////////////////////////////////////////////////////////
// CCameraPosWnd

CCameraPosWnd::CCameraPosWnd(CWnd* pParent)
{
	m_pParent = pParent;

	m_CameraPos.x = POINT_HOME_X + FRAME_OFFSET;
	m_CameraPos.y = POINT_HOME_Y + FRAME_OFFSET;
	m_ballPos.x = 0;
	m_ballPos.y = 0;
}



CCameraPosWnd::~CCameraPosWnd()
{
}


BEGIN_MESSAGE_MAP(CCameraPosWnd, CWnd)
	//{{AFX_MSG_MAP(CCameraPosWnd)
	ON_WM_ERASEBKGND()
	ON_WM_PAINT()
	ON_WM_CONTEXTMENU()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CCameraPosWnd message handlers



BOOL CCameraPosWnd::OnEraseBkgnd(CDC* pDC)
{
	return 0;
//	return CWnd::OnEraseBkgnd(pDC);
}

/*---------------------------------------------------------
	SetCameraPos	:	Set camera position

	Argument
		pos		:	Position (angle)
				:	+ (left),-(right) , +(up) , -(down)
		posture	:	Posture (POSE_NORMAL..POSE_STATION)
	Return value
		NONE
	Explanation
		Compensation for the camera position is necessary for different postures.
		SIT:-25 degrees ,LIE:-11 degrees
 ---------------------------------------------------------*/
void CCameraPosWnd::SetCameraPos( CPoint pos,UINT posture )
{
	CalcPosition( pos, posture, m_CameraPos );

	CRect rc;
	GetClientRect( &rc );

	// Enlarge it a little.
	rc.InflateRect( 3, 3 );
	InvalidateRect( &rc );

	UpdateWindow();
}

/*---------------------------------------------------------
	SetBallPos	:	Ball position display

	Argument
		Position of a ball (X = [-2..2] , Y = [0..2])
	Return value
		NONE
	Explanation
		If Y=0, the ball will not be displayed.
 ---------------------------------------------------------*/
void CCameraPosWnd::SetBallPos( CPoint pos )
{
	// Calculation of the coordinates
	m_ballPos.x = pos.x * 14 + POINT_HOME_X + 1;
	m_ballPos.y = pos.y;

	CRect rc;
	GetClientRect(&rc);
	ClientToScreen(&rc);
	m_pParent->ScreenToClient(&rc);

	// Enlarge it a little.
	rc.InflateRect(3, 3);
	m_pParent->InvalidateRect(&rc);

	m_pParent->UpdateWindow();
}

void CCameraPosWnd::OnPaint()
{
	CRect	rect;
	CRect	drawRect;
	CBrush	br2;

	CPaintDC dc(this);

	GetClientRect( &rect );
	drawRect = rect;
	CRect rcEllips(-3, -3, 4, 4);

	rcEllips.OffsetRect( m_CameraPos.x, m_CameraPos.y );

	CBrush br( RGB( 50, 250, 0 ) );
	CPen pen( PS_SOLID, 0, RGB( 50, 250, 0 ) );
	br2.CreateStockObject( GRAY_BRUSH );

	CBrush* pOldBr = dc.SelectObject( &br );
	CPen* pOldPen = dc.SelectObject( &pen );

	// Camera position drawing
	dc.FillRect( &drawRect, &br2 );
	dc.MoveTo( rect.left+FRAME_OFFSET, POINT_HOME_Y+FRAME_OFFSET );
	dc.LineTo( rect.right-FRAME_OFFSET, POINT_HOME_Y+FRAME_OFFSET );
	dc.MoveTo( POINT_HOME_X+FRAME_OFFSET, rect.top+FRAME_OFFSET );
	dc.LineTo( POINT_HOME_X+FRAME_OFFSET, rect.bottom-FRAME_OFFSET);
	dc.Ellipse(rcEllips);

	// Draw ball
	if ( m_ballPos.y ) {
		// Draw a pink ball.
		CRect	ball( -3, -3, 4, 4 );
		ball.OffsetRect( m_ballPos.x, m_CameraPos.y );
		CBrush	br2( RGB( 255, 0, 255 ) );	// Pink
		CPen	pen2( PS_SOLID, 0, RGB( 255, 0, 255 ) );
		dc.SelectObject( &br2 );
		dc.SelectObject( &pen2 );
		dc.Ellipse( ball );
		if ( pOldBr ) {
			dc.SelectObject( pOldBr );
		}
		if ( pOldPen ) {
			dc.SelectObject( pOldPen );
		}
		br2.DeleteObject();
		pen2.DeleteObject();
	}

	if ( pOldBr ) {
		dc.SelectObject( pOldBr );
	}
	if ( pOldPen ) {
		dc.SelectObject( pOldPen );
	}

	br.DeleteObject();
	br2.DeleteObject();
	pen.DeleteObject();
}

void CCameraPosWnd::OnContextMenu(CWnd* pWnd, CPoint point)
{
}

LRESULT CCameraPosWnd::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
	/*
		Throw a mouse message to the parent window.
	*/
	if ( (message >= WM_MOUSEFIRST) && (message <= WM_MOUSELAST) ) {
		if ( m_pParent ) {
			POINT		pt;
			DWORD		lp;
			pt.x = LOWORD(lParam);
			pt.y = HIWORD(lParam);
			if ( message != WM_MOUSEWHEEL ) {
				// Change to the local coordinates of the parent window.
				this->ClientToScreen(&pt);
				m_pParent->ScreenToClient(&pt);
			}
			lp = (pt.y << 16) | pt.x;
			return m_pParent->PostMessage(message,wParam,(LPARAM)lp);
		}
	}
	return CWnd::DefWindowProc(message, wParam, lParam);
}

/*---------------------------------------------------------
	GetMousePos	:	Find the coordinates where the mouse was clicked.

	Argument
		mousePos	:	Mouse coordinates (screen coordinates)
		posture		:	Posture (POSE_NORMAL..POSE_STATION)
		pos			:	Coordinates pointer for the window ( -90 <= x <= 90 , -20 <= y <= 60 )
	Return value
		NONE
	Explanation
		Change the mouse coordinates into the position coordinates, and store it in pos.
		(the origin is 0,0) There is no compensation for the posture.
 ---------------------------------------------------------*/
void CCameraPosWnd::GetMousePos( CPoint mousePos,UINT posture,CPoint &pos )
{
	// Change to local coordinates.
	ScreenToClient( &mousePos );

	int		ix;
	switch ( posture ) {
		case ST_POS_LIE:
			ix = 0;
		case ST_POS_SIT:
			ix = 1;
		case ST_POS_STAND:
		default:
			ix = 2;
			break;
	}

	// Angle calculation in the X direction
	pos.x = - ( mousePos.x - POINT_HOME_X - FRAME_OFFSET ) * 90 / ( DRAW_RECT_W / 2 );
	if ( pos.x < -90 ) {
		pos.x = -90;
	}
	else if ( pos.x > 90 ) {
		pos.x = 90;
	}

	// Angle calculation in the Y direction
	int		y = mousePos.y - ( POINT_HOME_Y + FRAME_OFFSET );
	if ( y <= 0 ) {		// Upward direction
		pos.y = cameraParam[ ix ].pos_0 - y * ( cameraParam[ ix ].max - cameraParam[ ix ].pos_0 ) / HEIGHT_UP;
		if ( pos.y > cameraParam[ ix ].max ) {
			pos.y = cameraParam[ ix ].max;
		}
	}
	else {		// Downward direction
		pos.y = cameraParam[ ix ].pos_0 + y * ( cameraParam[ ix ].min - cameraParam[ ix ].pos_0 ) / HEIGHT_DOWN;
		if ( pos.y < cameraParam[ ix ].min ) {
			pos.y = cameraParam[ix].min;
		}
	}
}

/*---------------------------------------------------------
	CalcPosition	:	Camera position coordinates calculation

	Argument
		angle	:	Camera angle
		posture	:	Posture (POSE_NORMAL..POSE_STATION)
		pos		:	Camera coordinates storage
	Return value
		NONE
	Explanation
		Calculate the camera screen coordinates.
 ---------------------------------------------------------*/
void CCameraPosWnd::CalcPosition( CPoint angle, UINT posture, CPoint &pos )
{
	int		ix;
	switch ( posture ) {
		case ST_POS_LIE:
			ix = 0;
		case ST_POS_SIT:
			ix = 1;
		case ST_POS_STAND:
		default:
			ix = 2;
			break;
	}

	int		x, y;
	x = angle.x;
	y = angle.y;

	// The range limitation
	if ( x > 90 ) { x = 90; }
	if ( x < -90 ) { x = -90; }
	if ( y > cameraParam[ ix ].max ) { y = cameraParam[ ix ].max; }
	if ( y < cameraParam[ ix ].min ) { y = cameraParam[ ix ].min; }

/*
	                DRAW_RECT_W
	             90     0      -90
	             +------+------+ cameraParam[ ix ].max
	             |      |      |
	             |      |      |      HEIGHT_UP
	             |      |      |
	POINT_HOME_Y +------+------+ cameraParam[ ix ].pos_0
	             |      |      |
	             |      |      |     HEUGHT_DOWN
	             |      |      |
	             +------+------+ cameraParam[ ix ].min
	               POINT_HOME_X
*/

	// The coordinate calculation of the X-axis
	pos.x = POINT_HOME_X + ( ( DRAW_RECT_W / 2 ) * -x / 90 ) + FRAME_OFFSET;

	// The coordinate calculation of the Y-axis
	if ( y < cameraParam[ ix ].pos_0 ) {
		pos.y = POINT_HOME_Y + HEIGHT_DOWN * ( cameraParam[ ix ].pos_0 - y ) / ( cameraParam[ ix ].pos_0 - cameraParam[ ix ].min );
	}
	else {
		pos.y = POINT_HOME_Y - HEIGHT_UP * ( y - cameraParam[ ix ].pos_0 ) / ( cameraParam[ ix ].max - cameraParam[ ix ].pos_0 );
	}
}



