/*****************************************************************************
 * $Id: mod_pony_view.cc,v 1.1 2006/11/24 21:56:58 devel Exp $
 * @file
 * @author	Jim E. Brooks  http://www.jimbrooks.org
 * @brief	Module Pony View classes.
 * @remarks	For 2D drawing, the geometry passed to GFX_BEGIN_2D(Geom*) is relative
 *          (contained in) the viewport geometry passed to View::SetViewportGeom().
 *//*
 * LEGAL:	COPYRIGHT (C) 2004 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE (GPL).
 *****************************************************************************/

#define MOD_PONY_VIEW_CC 1
#include "mod_pony_common.hh"
#include "mod_pony_view.hh"
#include "mod_base_craft.hh"

////////////////////////////////////////////////////////////////////////////////
//////////////////////////////  ViewModulePony  ////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

/*****************************************************************************
 * Constructor.
 *****************************************************************************/
ViewModulePony::ViewModulePony( ViewMaster& master )
:   View(master)
{
	SetViewportGeom( 0, 0, gEng.mView.GetWidth(), gEng.mView.GetHeight() );
	mVisible = mTexturing = true;
}

////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////  ViewRadar  //////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

/*****************************************************************************
 * Constructor.
 *****************************************************************************/
ViewRadar::ViewRadar( ViewMaster& master, eRadar radar )
:   View(master)
{
	mVisible = true;
	mRadar   = radar;
}

/*****************************************************************************
 * Draw.
 *****************************************************************************/
const fp sRadarAlpha = 0.4;
static void
DrawRadarBlipsForEachCraft( CraftPtrConst craft, long userdata )
{
	ViewRadar* view = reinterpret_cast<ViewRadar*>( userdata );

	// Don't show player's own craft in radar.
	//if ( craft == gModule.GetPlayerCraft() ) return;

	// Don't show destroyed (hit) craft.
	if ( craft->IfDestroyed() ) return;

	// Compute a 2D coord for the radar viewport from eye's 3D position.
	const Matrix& playerMatrix = gEng.mEye.mCm;
	Pos2d<fp> pos(0,0);
	switch ( view->mRadar )
	{
		// pos.x,y holds distance between this craft and player.
		case ViewRadar::eRadar_HORIZON:
		pos.x = ABS(craft->mCm[Ox]) - ABS(playerMatrix[Ox]);
		pos.y = ABS(craft->mCm[Oy]) - ABS(playerMatrix[Oy]);
		break;

		case ViewRadar::eRadar_OVERHEAD:
		pos.x =   ABS(craft->mCm[Ox]) - ABS(playerMatrix[Ox]);
		pos.y = -(ABS(craft->mCm[Oz]) - ABS(playerMatrix[Oz]));
		break;

		default: ASSERT(0);
		break;
	}

	// Project onto viewport.
	pos.x = Remap( pos.x, gWorld.GetQuadrantEdge(), view->ViewportWidth()  );
	pos.y = Remap( pos.y, gWorld.GetQuadrantEdge(), view->ViewportHeight() );
	const fp zoom = 8;
	pos.x *= zoom;
	pos.y *= zoom;
	pos.x += view->ViewportWidth()  / 2; // translate to center of viewport
	pos.y += view->ViewportHeight() / 2;

	// Draw a radar blip as a small rectangle.
	const fp blipWidth  = 4;
	const fp blipHeight = 4;
	static const RGBA rgba_friendly( 0.0, 0.0, 1.0, sRadarAlpha ); // blue
	static const RGBA rgba_hostile(  1.0, 0.0, 0.0, sRadarAlpha ); // red
	GFX_RGBA( gModule.IsFriendlyCraft( *craft ) ? rgba_friendly : rgba_hostile );
	GFX_BEGIN( GP_POLYGON );
		Rect<fp> rect;
		rect.x1 = pos.x;
		rect.x2 = pos.x + blipWidth;
		rect.y1 = pos.y;
		rect.y2 = pos.y + blipHeight;
		GFX_VERTEX_2D( rect.x1, rect.y1 ); // NW
		GFX_VERTEX_2D( rect.x1, rect.y2 ); // SW
		GFX_VERTEX_2D( rect.x2, rect.y2 ); // SE
		GFX_VERTEX_2D( rect.x2, rect.y1 ); // NE
	GFX_END();
}
void
ViewRadar::Draw( void )
{
	if ( mVisible && gEng.GetSpeed() != eSpeed_FAST )
	{
		static const RGBA rgbaRadarSky( 0.27, 0.67, 0.94, 0.6 );
		static const RGBA rgbaRadarLand( 0.05, 0.45, 0.05, sRadarAlpha );

		// Draw radar blips for each craft.
		GrabFocus();
		Geom<int> geom2d( 0, 0, ViewportWidth(), ViewportHeight() );
		GFX_BEGIN_2D( &geom2d );
		GFX_BEGIN_BLEND();
		switch ( mRadar )
		{
			case eRadar_HORIZON:
			{
				// Draw land.
				// To indicate altitude, move horizon according to player's altitude.
				const Matrix& playerMatrix = gModule.GetPlayerMatrix();
				int y = (int)Remap( ABS(playerMatrix[Oy]),
	                                WORLD(10000.0),
	                                (fp)ViewportHeight() );
				int y2 = mGeomViewport.h - y;
				y2 = Range( y2, 5, mGeomViewport.h-5 ); // keep some sky if at ground
				Rect<int> rectLand( 0, 0, mGeomViewport.w, y2 );
				DrawRect2D( rectLand, rgbaRadarLand );
				// Draw sky.
				Rect<int> rectSky( 0, y2, mGeomViewport.w, mGeomViewport.h );
				DrawRect2D( rectSky, rgbaRadarSky );
			}
			break;

			case eRadar_OVERHEAD:
			{
				Rect<int> rect( 0, 0, mGeomViewport.w, mGeomViewport.h );
				DrawRect2D( rect, rgbaRadarLand );
			}
			break;

			default: ASSERT(0); break;
		}
		ForEachCraft( DrawRadarBlipsForEachCraft, (long)this );
		GFX_END_BLEND();
		GFX_END_2D();
	}
}

/*****************************************************************************
 * Reshape.
 *****************************************************************************/
void
ViewRadar::Reshape( int w, int h )
{
	const int padding = 4;
	const int radarWidth = w/4;
	const int panelHeight = h / 10;
	switch ( mRadar )
	{
		case eRadar_HORIZON:
		SetViewportGeom( radarWidth*2+padding, h-panelHeight, radarWidth, panelHeight );
		break;

		case eRadar_OVERHEAD:
		SetViewportGeom( radarWidth-padding, h-panelHeight, radarWidth, panelHeight );
		break;
	}
}
