/** SGX

The   sss    gggg x   x   
     s      g      x x    Engine
      sss   g  gg   x
         s  g   g  x x          Copyright 1995-2008.
     ssss    gggg x   x         Steven Goodwin. All Rights Reserved.
    
This version has been released under the GNU Public License v2.0.

Please see the license files for details.

File: src/sgx/graphics/sprites.cpp

*/

#include "sgx/core/core.hpp"
#include "sgx/graphics/graphics.hpp"

CGraphicSprite::CGraphicSprite()
{
	setOrigin(eCentre);
	unit();

	vtx[0].u = vtx[0].v = 0;
	vtx[1].u = 1; vtx[1].v = 0;
	vtx[2].u = 1; vtx[2].v = 1;
	vtx[3].u = 0; vtx[3].v = 1;

	rotation = 0;

	for(int i=0;i<4;++i) {
		vtx[i].color = sgxColorRGBA::White;
	}

	pTexture = NULL;
}

void	
CGraphicSprite::setOrigin(const tSpriteOrigin origin) 
{
	m_Origin = origin;

	switch(origin) {
	case	eCentre:
		m_OriginMulX = m_OriginMulY = 0.5f;
		break;

	case	eTopLeft:
		m_OriginMulX = m_OriginMulY = 0;
		break;

	case	eBottomCentre:
		m_OriginMulX = 0.5f;
		m_OriginMulY = 1;
		break;

	default:
		sgxError("Invalid sprite origin");
	}
}

void
CGraphicSprite::setUV(const sgxUV &uv)
{
	vtx[0].u = uv.u1;
	vtx[0].v = uv.v1;
	vtx[1].u = uv.u2;
	vtx[1].v = uv.v1;
	vtx[2].u = uv.u2;
	vtx[2].v = uv.v2;
	vtx[3].u = uv.u1;
	vtx[3].v = uv.v2;
}

CGraphicSprite::tSpriteOrigin	
CGraphicSprite::getOrigin() const
{
	return m_Origin;
}

void			
CGraphicSprite::getCentre(sgxVector2 &centre) const
{
	centre.x = (vtx[2].vect.x - vtx[0].vect.x) * 0.5f + vtx[0].vect.x;
	centre.y = (vtx[2].vect.y - vtx[0].vect.y) * 0.5f + vtx[0].vect.y;
}

void	
CGraphicSprite::setSize(const tREAL32 width, const tREAL32 height)
{
	// Determine the top-left position, based around the origin
	switch(m_Origin) {
	case	eCentre:
		vtx[0].vect.x = -width*0.5f;
		vtx[0].vect.y = -height*0.5f;
		break;

	case	eTopLeft:
		vtx[0].vect = sgxVector2::Origin;
		break;

	case	eBottomCentre:
		vtx[0].vect.x = -width*0.5f;
		vtx[0].vect.y = -height;
		break;

	default:
		sgxError("Invalid sprite origin");
	}

	vtx[1].vect = vtx[0].vect + sgxVector2(width, 0.f);
	vtx[2].vect = vtx[0].vect + sgxVector2(width, height);
	vtx[3].vect = vtx[0].vect + sgxVector2(0.f, height);

	// TODO: FIX THIS TO USE THE 'CORRECT' vect code above, and m_Origin
#if 1
	vtx[0].vect = sgxVector2(width*m_OriginMulX, height*m_OriginMulY);
	vtx[1].vect = vtx[0].vect - sgxVector2(width, 0.f);
	vtx[2].vect = vtx[0].vect - sgxVector2(width, height);
	vtx[3].vect = vtx[0].vect - sgxVector2(0.f, height);
#endif
}

void 
CGraphicSprite::unit()
{
	setSize(1,1);
}


void
CGraphicSprite::draw(const sgxVector3 &pos) const
{
	CSGXGraphicsEngine::get()->drawSprite(*this, pos);
}

//
void 
CSGXGraphicsEngine::drawSprite(const CGraphicSprite &sprite, const sgxVector3 &pos)
{
	// create a genuine 3D polygon from the 2D sprite information. This
	// can then be renderer in 3D space, along with everything else
	// in the alpha sorter.
	sgxGfxPolygon poly;
	sgxMatrix43 transform;

	tREAL32 theta;
	theta = SGX_PI-sgxAtan2(m_ViewTransform.at.x, m_ViewTransform.at.z);

	transform.setRotateAxis(theta, sgxVector3::UnitY);
	transform.pos = pos;

	poly.pTexture = sprite.pTexture;

	sgxVector2 centre;
	sgxPolyVtx pv;
	
	sprite.getCentre(centre);
	
	for(int idx=0;idx<4;++idx) {
		sgxVector2 v(sprite.vtx[idx].vect.x, sprite.vtx[idx].vect.y);
		v.rotate(centre, sprite.rotation);
		pv.vect = sgxVector3(v.x, v.y, 0);
		pv.u = sprite.vtx[idx].u;
		pv.v = sprite.vtx[idx].v;
		pv.color = sprite.vtx[idx].color;
		poly.vtx.push_back(pv);
	}

	drawPolygon(poly, transform);
}

//
void 
CSGXGraphicsEngine::drawSprite(const CGraphicSprite &sprite, const sgxMatrix43 &transform)
{
	drawSprite(sprite, transform.pos);
}

