/*====================ÉCOLE POLYTECHNIQUE DE MONTRÉAL============================

	NOM DU FICHIER :CAnimation.cpp

	DESCRIPTION :	Implémentation des fonctions de la classe CAnimation

	AUTEUR : Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse

===============================================================================*/
#include "Temps.h"
#include "CAnimation.h"
#include <GL/glut.h>

/*------------------------------------------------------------------
  Fonction :	CAnimation()

  Description :	Constructeur d'une animation

  Paramètres :
	-int PosX : Position en X de l'animation
	-int PosY : Position en Y de l'animation
	-int Width : Largeur de l'animation
	-int Height : Hauteur de l'animation
	-unsigned int msPerFrame : Milisecondes par image
	-bool Loop : L'animation doit-elle reprendre au début une fois terminée?
	-bool Visible : L'animation est-elle visible?
	
	***Ces paramètres peuvent êtres modifiés à l'aide de la fonction Setup()***

  Valeur retournée :	void : 

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
CAnimation::CAnimation(float PosX, float PosY, float Width, float Height, unsigned int msPerFrame, bool Loop, bool Visible)
{
	Setup(PosX, PosY, Width, Height, msPerFrame, Loop, Visible);
}

/*------------------------------------------------------------------
  Fonction :	CAnimation()

  Description :	Changement des paramètres de l'animation

  Paramètres :
	-int PosX : Position en X de l'animation
	-int PosY : Position en Y de l'animation
	-int Width : Largeur de l'animation
	-int Height : Hauteur de l'animation
	-unsigned int msPerFrame : Milisecondes par image
	-bool Loop : L'animation doit-elle reprendre au début une fois terminée?
	-bool Visible : L'animation est-elle visible?
	
	***Ces paramètres peuvent êtres modifiés à l'aide de la fonction Setup()***

  Valeur retournée :	void : 

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
void CAnimation::Setup(float PosX, float PosY, float Width, float Height, unsigned int msPerFrame, bool Loop, bool Visible)
{
	this->Visible = Visible;
	this->Loop = Loop;
	this->msPerFrame = msPerFrame;
	this->IsPlaying = false;
	this->CurrentFrame = 0;
	this->PosX = PosX;
	this->PosY = PosY;
	this->Width = Width;
	this->Height = Height;
}

/*------------------------------------------------------------------
  Fonction :	Play

  Description :	Commence à jouer l'animation à l'image courante
                    - La fonction Update() fera passer l'image courant à la suivante
	    s'il est temps.
 

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
void CAnimation::Play()
{
	if (IsPlaying) return;

	this->IsPlaying = true;
	this->LastFrameTime = GetTemps();
}

/*------------------------------------------------------------------
  Fonction :	Stop

  Description :	L'animation est arrêtée et retournée à la première image

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
void CAnimation::Stop()
{
	this->IsPlaying = false;
	this->CurrentFrame = 0;
}

/*------------------------------------------------------------------
  Fonction :	Pause

  Description :	L'animation est pausée sur l'image courante

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
void CAnimation::Pause()
{
	this->IsPlaying = false;
}

/*------------------------------------------------------------------
  Fonction :	AddFile()

  Description :	Ajoute une image PNG à la fin de la liste pour l'animation
  
  Paramètres :	- const char* FileName : Nom du fichier PNG à charger
		- int Mipmap : utilisation de mipmaps? 0 pour non
		- int Transparency : Transparence si disponible?
			       (-2) pour transparence, (-1) sans transparence
		- unsigned int msPerFrame : milisecondes par image
  
  Retour : bool : Vrai si le chargement se passe normalement

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
bool CAnimation::AddFile(const char* FileName, int Mipmap, int Transparency, unsigned int msPerFrame)
{
	CPngTexture NewTexture;
	if(!NewTexture.LoadPNG(FileName, Mipmap, Transparency))
	{
	    return false;
	}
	this->Images.push_back(NewTexture);
	if (msPerFrame == 0) FramesMs.push_back(this->msPerFrame);
	else FramesMs.push_back(msPerFrame);
	return true;
}

/*------------------------------------------------------------------
  Fonction :	Clear

  Description :	Toutes les images sont détruites et retirées de l'animation

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
void CAnimation::Clear()
{
	FramesMs.clear();
	for (vector<CPngTexture>::iterator i = Images.begin(); i != Images.end();)
	{
		i->Unload();
		i = Images.erase(i);
	}
}

/*------------------------------------------------------------------
  Fonction :	Draw

  Description :	Dessine l'image courante de l'animation selon l'emplacement
                                           et la taille spécifiés par le constructeur (ou la fonction Setup())

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
void CAnimation::Draw()
{
    glColor4f(1,1,1,1);
	if (!Visible) return;
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, this->Images[this->CurrentFrame].GetID());
	glBegin(GL_QUADS);
	{
	    glNormal3f(0,0,1);
	    glTexCoord2f(0,0);
	    glVertex2f(PosX,PosY+Height);
	    glTexCoord2f(0,1);
	    glVertex2f(PosX,PosY);
	    glTexCoord2f(1,1);
	    glVertex2f(PosX+Width,PosY);
	    glTexCoord2f(1,0);
	    glVertex2f(PosX+Width,PosY+Height);
	}
	glEnd();
	glDisable(GL_TEXTURE_2D);
}

/*------------------------------------------------------------------
  Fonction :	DrawAt

  Description :	Dessine l'image courante de l'animation selon l'emplacement (x,y)
                                           en paramètres et la taille spécifiée par le constructeur
                                          (ou la fonction Setup())

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
void CAnimation::DrawAt(float x, float y)
{
    glColor4f(1,1,1,1);
	if (!Visible) return;
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, this->Images[this->CurrentFrame].GetID());
	glBegin(GL_QUADS);
	{
	    glNormal3f(0,0,1);
	    glTexCoord2f(0,0);
	    glVertex2f(x,y+Height);
	    glTexCoord2f(0,1);
	    glVertex2f(x,y);
	    glTexCoord2f(1,1);
	    glVertex2f(x+Width,y);
	    glTexCoord2f(1,0);
	    glVertex2f(x+Width,y+Height);
	}
	glEnd();
	glDisable(GL_TEXTURE_2D);
}

/*------------------------------------------------------------------
  Fonction :	Update

  Description :	Met à jour l'image courante

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
void CAnimation::Update()
{
	if (!this->IsPlaying) return;

	unsigned long Interval = GetTemps() - this->LastFrameTime;
	if (Interval >= this->FramesMs[CurrentFrame])
	{
		//int NumFrames = Interval / this->FramesMs[CurrentFrame];
		int NumFrames = 1;
		while (NumFrames > 0)
		{
			if (this->CurrentFrame < this->Images.size()-1)
		    	this->CurrentFrame++;
			else
				if (!Loop)
					Stop();
				else
					this->CurrentFrame = 0;
			NumFrames--;
			
		}
		this->LastFrameTime += Interval;
	}
}
