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

	NOM DU FICHIER :CEditeurBande.cpp

	DESCRIPTION :	Implémentation des fonctions de l'objet dérivé CEditeurBande

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

	DATE DE CRÉATION : 2004-3-16

	MISES À JOUR :

===============================================================================*/
#include <cmath>
#ifndef M_PI
#define M_PI (3.14159265358979323846264338327950288419716939937510)
#endif

#include <fstream>
#include <cstring>
#include "CPngTexture.h"
#include "CEditeurTerrain.h"
#include <GL/glut.h>
#include <qevent.h>
using namespace std;

CPngTexture CEditeurTerrain::TexGazon; //Texture du gazon
CPngTexture CEditeurTerrain::TexBordures; //Texture des bordures
CPngTexture CEditeurTerrain::TexEfface; //Texture de l'efface

/*------------------------------------------------------------------
  Fonction :	CEditeurTerrain::AssocieTuile

  Description :	Associe un vecteur à une tuile
				Utilisée dans l'algorithme des bordures automatiques

  Paramètres :
		CVector3f Position : Position de la tuile

  Valeur retournée :	CVector3f : Vecteur associé à la tuiles

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
vector2f CEditeurTerrain::AssocieTuile(vector2f Position) const
{
    switch (Grille[(int)Position.GetPosX()+1][(int)Position.GetPosY()+1])
    {
    case EDITEURTUILE_NONE:
	return vector2f(-2,-2);
	break;
    case EDITEURTUILE_SQUARE:
	return vector2f(0,0);
	break;
    case EDITEURTUILE_UL:
	return vector2f(1,-1);
	break;
    case EDITEURTUILE_UR:
	return vector2f(-1,-1);
	break;
    case EDITEURTUILE_DR:
	return vector2f(-1,1);
	break;
    case EDITEURTUILE_DL:
	return vector2f(1,1);
	break;
    }
}

/*------------------------------------------------------------------
  Fonction :	CEditeurTerrain::BordureATracer

  Description :	Détermine si une bordure doit être tracée pour les côtés "droits"

  Paramètres :
	 CVector3f Position : 
	 CVector3f Direction : 

  Valeur retournée :	bool : 

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
bool CEditeurTerrain::BordureATracer(vector2f Position, vector2f Direction) const
{
    vector2f PosToCheck = Position+Direction;
    vector2f TileToCheck = AssocieTuile(PosToCheck);
    vector2f SideTile = vector2f(Direction.GetPosY(),-Direction.GetPosX());
    if (TileToCheck == vector2f(0,0) ||
	TileToCheck == Direction+SideTile ||
	TileToCheck == Direction-SideTile)
	return false;
    return true;
}

/*------------------------------------------------------------------
  Fonction :	CEditeurTerrain::DepPourDiago

  Description :	Retourne le déplacement nécessaire de l'un des deux points
				inconnus d'une bordure qui est diagonale

  Paramètres :
	 CVector3f Position : Position de la tuile testée
	 CVector3f Direction : Orientation de la bordure
	 CVector3f A : Point de la bordure qui est cherché

  Valeur retournée :	float : Déplacement correspondant à l'angle

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
float CEditeurTerrain::DepPourDroite(vector2f Position, vector2f Direction, vector2f A)
{
    vector2f VerifTuile;
    //En face
    {
	VerifTuile = AssocieTuile(Position+Direction);
	//45 degrés
	if (VerifTuile == (-Direction-A))
	    return -(BORDER_WIDTH/tan(22.5*M_PI/180.0));
    }
    //En coin
    {
	VerifTuile = AssocieTuile(Position+Direction+A);
	//90 degrés
	if (VerifTuile == vector2f(0,0) ||
	    VerifTuile == (Direction+A) ||
	    VerifTuile == (-Direction+A))
	    return -BORDER_WIDTH;
	//135 degrés
	if (VerifTuile == (Direction-A))
	    return -BORDER_WIDTH*tan(22.5*M_PI/180.0);
    }
    //A côté
    {
	VerifTuile = AssocieTuile(Position+A);
	//180 degrés
	if (VerifTuile == vector2f(0,0) ||
	    VerifTuile == (-Direction+A) ||
	    VerifTuile == (-Direction-A))
	    return 0;
	//225 degrés
	if (VerifTuile == (Direction+A))
	    return BORDER_WIDTH*tan(22.5*M_PI/180.0);
    }
    //Autre
    {
	VerifTuile = AssocieTuile(Position);
	//270 degrés
	if (VerifTuile == vector2f(0,0) ||
	    VerifTuile == (-Direction-A))
	    return BORDER_WIDTH;
	//315 degrés
	if (VerifTuile == (-Direction+A))
	    return BORDER_WIDTH/tan(22.5*M_PI/180.0);
    }
    return 0;
}

/*------------------------------------------------------------------
  Fonction :	CEditeurTerrain::DepPourDiago

  Description :	Détermine l'inconnue du 3e ou 4e point d'une bordure
				diagonale

  Paramètres :
		CVector3f Position : Position de la tuile
		CVector3f Direction : Bordure à tester
		CVector3f A : 3e ou 4e point (orientation par rapport
										à la direction)

  Valeur retournée :	float : l'inconnu correspondant à l'angle
								formé par la bordure à ce point

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
float CEditeurTerrain::DepPourDiago(vector2f Position, vector2f Direction, vector2f A)
{
    vector2f VerifTuile;
    //À côté
    {
	VerifTuile = AssocieTuile(Position+(Direction+A)/2.0f);
	//45 degrés
	if (VerifTuile == vector2f(0,0) ||
	    VerifTuile == Direction ||
	    VerifTuile == A)
	    return -(BORDER_WIDTH/tan(22.5*M_PI/180.0));
	//90 degrés
	if (VerifTuile == -A)
	    return -BORDER_WIDTH;
    }
    //Diago
    {
	VerifTuile = AssocieTuile(Position+A);
	//135 degrés
	if (VerifTuile == vector2f(0,0) ||
	    VerifTuile == -Direction ||
	    VerifTuile == A)
	    return -BORDER_WIDTH*tan(22.5*M_PI/180.0);
	//180 degrés
	if (VerifTuile == Direction)
	    return 0;
    }
    //"Sous"
    {
	VerifTuile = AssocieTuile(Position-(Direction-A)/2.0f);
	//225 degrés
	if (VerifTuile == vector2f(0,0) ||
	    VerifTuile == -Direction ||
	    VerifTuile == -A)
	    return BORDER_WIDTH*tan(22.5*M_PI/180.0);
	//270 degrés
	if (VerifTuile == A)
	    return BORDER_WIDTH;
    }
    //Autre
    {
	//315 degrés
	return BORDER_WIDTH/tan(22.5*M_PI/180.0);
    }
}

/*------------------------------------------------------------------
  Fonction :	CEditeurTerrain::AfficheBordures

  Description :	Affiche les bordures en OpenGL

  Paramètres :
	 CVector3f Position : 

  Valeur retournée :	void : 

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
void CEditeurTerrain::AfficheBordures(vector2f Position)
{
    int i;
    float Tmp;
    vector2f Points[4];
    int PosX = Position.GetPosX();
    int PosY = Position.GetPosY();
    
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D,TexBordures.GetID());
    glEnable(GL_TEXTURE_GEN_S);
    glEnable(GL_TEXTURE_GEN_T);
    GLfloat stable[4] = {5.0,0.0,0.0,0.0};
    GLfloat ttable[4] = {0.0,5.0,0.0,0.0};
    glTexGenfv(GL_S,GL_OBJECT_PLANE,stable);
    glTexGenfv(GL_T,GL_OBJECT_PLANE,ttable);
    glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);
    glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    
    //HAUT (Dir = (0,1))
    if ((Grille[PosX+1][PosY+1] == EDITEURTUILE_SQUARE ||
	 Grille[PosX+1][PosY+1] == EDITEURTUILE_UL ||
	 Grille[PosX+1][PosY+1] == EDITEURTUILE_UR) && BordureATracer(Position,vector2f(0,1)))
    {
	vector2f Dir(0,1);
	vector2f Perp = vector2f(Dir.GetPosY(),-Dir.GetPosX());
	Points[0] = vector2f(PosX,PosY+1);
	Points[1] = vector2f(PosX+1,PosY+1);
	Points[2] = vector2f(PosX+1+DepPourDroite(Position,Dir,Perp),PosY+1+BORDER_WIDTH);
	Points[3] = vector2f(PosX-DepPourDroite(Position,Dir,-Perp),PosY+1+BORDER_WIDTH);
	glBegin(GL_QUADS);
	{
	    for (i = 0; i < 4; i++)
	    {
		glVertex2f(Points[i].GetPosX(),Points[i].GetPosY());
	    }
	}
	glEnd();
    }
    //HAUT_DROITE (Dir = (1,1))
    if (Grille[PosX+1][PosY+1] == EDITEURTUILE_DL)
    {
	vector2f Dir(1,1);
	vector2f Perp = vector2f(Dir.GetPosY(),-Dir.GetPosX());
	Points[0] = vector2f(PosX,PosY+1);
	Points[1] = vector2f(PosX+1,PosY);
	Tmp = DepPourDiago(Position,Dir,Perp);
	Points[2] = vector2f(PosX+1,PosY)+Tmp*Perp.GetNormalVector()+BORDER_WIDTH*Dir.GetNormalVector();
	Tmp = DepPourDiago(Position,Dir,-Perp);
	Points[3] = vector2f(PosX,PosY+1)-Tmp*Perp.GetNormalVector()+BORDER_WIDTH*Dir.GetNormalVector();
	glBegin(GL_QUADS);
	{
	    for (i = 0; i < 4; i++)
	    {
		glVertex2f(Points[i].GetPosX(),Points[i].GetPosY());
	    }
	}
	glEnd();
    }
    
    //DROITE (Dir = (1,0))
    if ((Grille[PosX+1][PosY+1] == EDITEURTUILE_SQUARE ||
	 Grille[PosX+1][PosY+1] == EDITEURTUILE_UR ||
	 Grille[PosX+1][PosY+1] == EDITEURTUILE_DR) && BordureATracer(Position,vector2f(1,0)))
    {
	vector2f Dir(1,0);
	vector2f Perp = vector2f(Dir.GetPosY(),-Dir.GetPosX());
	Points[0] = vector2f(PosX+1,PosY+1);
	Points[1] = vector2f(PosX+1,PosY);
	Points[2] = vector2f(PosX+1+BORDER_WIDTH,PosY-DepPourDroite(Position,Dir,Perp));
	Points[3] = vector2f(PosX+1+BORDER_WIDTH,PosY+1+DepPourDroite(Position,Dir,-Perp));
	glBegin(GL_QUADS);
	{
	    for (i = 0; i < 4; i++)
	    {
		glVertex2f(Points[i].GetPosX(),Points[i].GetPosY());
	    }
	}
	glEnd();
    }
    
    //BAS_DROITE (Dir = (1,-1))
    if (Grille[PosX+1][PosY+1] == EDITEURTUILE_UL)
    {
	vector2f Dir(1,-1);
	vector2f Perp = vector2f(Dir.GetPosY(),-Dir.GetPosX());
	Points[0] = vector2f(PosX+1,PosY+1);
	Points[1] = vector2f(PosX,PosY);
	Tmp = DepPourDiago(Position,Dir,Perp);
	Points[2] = vector2f(PosX,PosY)+Tmp*Perp.GetNormalVector()+BORDER_WIDTH*Dir.GetNormalVector();
	Tmp = DepPourDiago(Position,Dir,-Perp);
	Points[3] = vector2f(PosX+1,PosY+1)-Tmp*Perp.GetNormalVector()+BORDER_WIDTH*Dir.GetNormalVector();
	glBegin(GL_QUADS);
	{
	    for (i = 0; i < 4; i++)
	    {
		glVertex2f(Points[i].GetPosX(),Points[i].GetPosY());
	    }
	}
	glEnd();
    }
    
    //BAS (Dir = (0,-1))
    if ((Grille[PosX+1][PosY+1] == EDITEURTUILE_SQUARE ||
	 Grille[PosX+1][PosY+1] == EDITEURTUILE_DL ||
	 Grille[PosX+1][PosY+1] == EDITEURTUILE_DR) && BordureATracer(Position,vector2f(0,-1)))
    {
	vector2f Dir(0,-1);
	vector2f Perp = vector2f(Dir.GetPosY(),-Dir.GetPosX());
	Points[0] = vector2f(PosX+1,PosY);
	Points[1] = vector2f(PosX,PosY);
	Points[2] = vector2f(PosX-DepPourDroite(Position,Dir,Perp),PosY-BORDER_WIDTH);
	Points[3] = vector2f(PosX+1+DepPourDroite(Position,Dir,-Perp),PosY-BORDER_WIDTH);
	glBegin(GL_QUADS);
	{
	    for (i = 0; i < 4; i++)
	    {
		glVertex2f(Points[i].GetPosX(),Points[i].GetPosY());
	    }
	}
	glEnd();
    }
    
    //BAS_GAUCHE (Dir = (-1,-1))
    if (Grille[PosX+1][PosY+1] == EDITEURTUILE_UR)
    {
	vector2f Dir(-1,-1);
	vector2f Perp = vector2f(Dir.GetPosY(),-Dir.GetPosX());
	Points[0] = vector2f(PosX+1,PosY);
	Points[1] = vector2f(PosX,PosY+1);
	Tmp = DepPourDiago(Position,Dir,Perp);
	Points[2] = vector2f(PosX,PosY+1)+Tmp*Perp.GetNormalVector()+BORDER_WIDTH*Dir.GetNormalVector();
	Tmp = DepPourDiago(Position,Dir,-Perp);
	Points[3] = vector2f(PosX+1,PosY)-Tmp*Perp.GetNormalVector()+BORDER_WIDTH*Dir.GetNormalVector();
	glBegin(GL_QUADS);
	{
	    for (i = 0; i < 4; i++)
	    {
		glVertex2f(Points[i].GetPosX(),Points[i].GetPosY());
	    }
	}
	glEnd();
    }
    
    //GAUCHE (Dir = (-1,0))
    if ((Grille[PosX+1][PosY+1] == EDITEURTUILE_SQUARE ||
	 Grille[PosX+1][PosY+1] == EDITEURTUILE_UL ||
	 Grille[PosX+1][PosY+1] == EDITEURTUILE_DL) && BordureATracer(Position,vector2f(-1,0)))
    {
	vector2f Dir(-1,0);
	vector2f Perp = vector2f(Dir.GetPosY(),-Dir.GetPosX());
	Points[0] = vector2f(PosX,PosY);
	Points[1] = vector2f(PosX,PosY+1);
	Points[2] = vector2f(PosX-BORDER_WIDTH,PosY+1+DepPourDroite(Position,Dir,Perp));
	Points[3] = vector2f(PosX-BORDER_WIDTH,PosY-DepPourDroite(Position,Dir,-Perp));
	glBegin(GL_QUADS);
	{
	    for (i = 0; i < 4; i++)
	    {
		glVertex2f(Points[i].GetPosX(),Points[i].GetPosY());
	    }
	}
	glEnd();
    }
    
    //HAUT_GAUCHE (Dir = (-1,1))
    if (Grille[PosX+1][PosY+1] == EDITEURTUILE_DR)
    {
	vector2f Dir(-1,1);
	vector2f Perp = vector2f(Dir.GetPosY(),-Dir.GetPosX());
	Points[0] = vector2f(PosX,PosY);
	Points[1] = vector2f(PosX+1,PosY+1);
	Tmp = DepPourDiago(Position,Dir,Perp);
	Points[2] = vector2f(PosX+1,PosY+1)+Tmp*Perp.GetNormalVector()+BORDER_WIDTH*Dir.GetNormalVector();
	Tmp = DepPourDiago(Position,Dir,-Perp);
	Points[3] = vector2f(PosX,PosY)-Tmp*Perp.GetNormalVector()+BORDER_WIDTH*Dir.GetNormalVector();
	glBegin(GL_QUADS);
	{
	    for (i = 0; i < 4; i++)
	    {
		glVertex2f(Points[i].GetPosX(),Points[i].GetPosY());
	    }
	}
	glEnd();
    }
    
    glDisable(GL_TEXTURE_GEN_S);
    glDisable(GL_TEXTURE_GEN_T);
    glDisable(GL_TEXTURE_2D);
}

/*------------------------------------------------------------------
  Fonction :	CEditeurTerrain::DessineTuile

  Description :	Dessine une tuile en OpenGL

  Paramètres :
	 int PosX : Position en x du coin gauche de la tuile
	 int PosY : Position en y du coin gauche de la tuile
	 type_jeutuile Type : Type de tuile

  Valeur retournée :	void : 

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
void CEditeurTerrain::DessineTuile(int PosX, int PosY, type_editeurtuile Type)
{
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D,TexGazon.GetID());
    glEnable(GL_TEXTURE_GEN_S);
    glEnable(GL_TEXTURE_GEN_T);
    GLfloat stable[4] = {1.5,0.0,0.0,0.0};
    GLfloat ttable[4] = {0.0,1.5,0.0,0.0};
    glTexGenfv(GL_S,GL_OBJECT_PLANE,stable);
    glTexGenfv(GL_T,GL_OBJECT_PLANE,ttable);
    glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);
    glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    switch (Type)
    {
    case EDITEURTUILE_SQUARE:
	glBegin(GL_QUADS);
	{
	    glVertex2f(PosX,PosY);
	    glVertex2f(PosX,PosY+1);
	    glVertex2f(PosX+1,PosY+1);
	    glVertex2f(PosX+1,PosY);
	}
	glEnd();
	break;
    case EDITEURTUILE_DL:
	glBegin(GL_TRIANGLES);
	{
	    glVertex2f(PosX,PosY);
	    glVertex2f(PosX,PosY+1);
	    glVertex2f(PosX+1,PosY);
	}
	glEnd();
	break;
    case EDITEURTUILE_DR:
	glBegin(GL_TRIANGLES);
	{
	    glVertex2f(PosX,PosY);
	    glVertex2f(PosX+1,PosY+1);
	    glVertex2f(PosX+1,PosY);
	}
	glEnd();
	break;
    case EDITEURTUILE_UR:
	glBegin(GL_TRIANGLES);
	{
	    glVertex2f(PosX,PosY+1);
	    glVertex2f(PosX+1,PosY+1);
	    glVertex2f(PosX+1,PosY);
	}
	glEnd();
	break;
    case EDITEURTUILE_UL:
	glBegin(GL_TRIANGLES);
	{
	    glVertex2f(PosX,PosY);
	    glVertex2f(PosX,PosY+1);
	    glVertex2f(PosX+1,PosY+1);
	}
	glEnd();
	break;
    }
    glDisable(GL_TEXTURE_GEN_S);
    glDisable(GL_TEXTURE_GEN_T);
    glDisable(GL_TEXTURE_2D);
}	

#ifdef DEBUG_CORNERS
/*------------------------------------------------------------------
  Fonction :	CEditeurTerrain::RempliCoins

  Description :	Remplit le tableau de booléens en indiquant s'il y a un coin
				qui doit être considéré pour les collisions

  Paramètres :

  Valeur retournée :	void : 

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
void CEditeurTerrain::RempliCoins()
{
    int i,j;
    for (i = 1; i < GRILLE_W+1; i++)
    {
	for (j = 1; j < GRILLE_H+1; j++)
	{
	    switch (Grille[i][j])
	    {
			case EDITEURTUILE_NONE:
			    //4 coins à vérifier
			    //UL
			    if ((Grille[i-1][j] == EDITEURTUILE_UL || Grille[i-1][j] == EDITEURTUILE_UR || Grille[i-1][j] == EDITEURTUILE_SQUARE) &&
				(Grille[i-1][j+1] == EDITEURTUILE_SQUARE || Grille[i-1][j+1] == EDITEURTUILE_DR) &&
				(Grille[i][j+1] == EDITEURTUILE_UL || Grille[i][j+1] == EDITEURTUILE_DL || Grille[i][j+1] == EDITEURTUILE_SQUARE) &&
				(Grille[i-1][j] != Grille[i][j+1] || Grille[i-1][j] == EDITEURTUILE_SQUARE))
				BoolCoins[i][j+1]=true;
			    //UR
			    if ((Grille[i+1][j] == EDITEURTUILE_UL || Grille[i+1][j] == EDITEURTUILE_UR || Grille[i+1][j] == EDITEURTUILE_SQUARE) &&
				(Grille[i+1][j+1] == EDITEURTUILE_SQUARE || Grille[i+1][j+1] == EDITEURTUILE_DL) &&
				(Grille[i][j+1] == EDITEURTUILE_DR || Grille[i][j+1] == EDITEURTUILE_UR || Grille[i][j+1] == EDITEURTUILE_SQUARE) &&
				(Grille[i+1][j] != Grille[i][j+1] || Grille[i+1][j] == EDITEURTUILE_SQUARE))
				BoolCoins[i+1][j+1]=true;
			    //DR
			    if ((Grille[i+1][j] == EDITEURTUILE_DR || Grille[i+1][j] == EDITEURTUILE_DL || Grille[i+1][j] == EDITEURTUILE_SQUARE) &&
				(Grille[i+1][j-1] == EDITEURTUILE_SQUARE || Grille[i+1][j-1] == EDITEURTUILE_UL) &&
				(Grille[i][j-1] == EDITEURTUILE_DR || Grille[i][j-1] == EDITEURTUILE_UR || Grille[i][j-1] == EDITEURTUILE_SQUARE) &&
				(Grille[i+1][j] != Grille[i][j-1] || Grille[i+1][j] == EDITEURTUILE_SQUARE))
				BoolCoins[i+1][j]=true;
			    //DL
			    if ((Grille[i-1][j] == EDITEURTUILE_DR || Grille[i-1][j] == EDITEURTUILE_DL || Grille[i-1][j] == EDITEURTUILE_SQUARE) &&
				(Grille[i-1][j-1] == EDITEURTUILE_SQUARE || Grille[i-1][j-1] == EDITEURTUILE_UR) &&
				(Grille[i][j-1] == EDITEURTUILE_UL || Grille[i][j-1] == EDITEURTUILE_DL || Grille[i][j-1] == EDITEURTUILE_SQUARE) &&
				(Grille[i-1][j] != Grille[i][j-1] || Grille[i-1][j] == EDITEURTUILE_SQUARE))
				BoolCoins[i][j]=true;
			    break;
			case EDITEURTUILE_SQUARE:
			    //Ne peut pas causer un coin
			    break;
			case EDITEURTUILE_UL:
			    //DR
			    if ((Grille[i+1][j] == EDITEURTUILE_DR || Grille[i+1][j] == EDITEURTUILE_DL || Grille[i+1][j] == EDITEURTUILE_SQUARE) &&
				(Grille[i+1][j-1] == EDITEURTUILE_SQUARE || Grille[i+1][j-1] == EDITEURTUILE_UL) &&
				(Grille[i][j-1] == EDITEURTUILE_DR || Grille[i][j-1] == EDITEURTUILE_UR || Grille[i][j-1] == EDITEURTUILE_SQUARE) &&
				(Grille[i+1][j] != Grille[i][j-1] || Grille[i+1][j] == EDITEURTUILE_SQUARE))
				BoolCoins[i+1][j]=true;
			    //UR POINTE
			    if ((Grille[i][j+1] != EDITEURTUILE_UL && Grille[i][j+1] != EDITEURTUILE_DL && Grille[i][j+1] != EDITEURTUILE_NONE) &&
				(Grille[i+1][j+1] == EDITEURTUILE_SQUARE || Grille[i+1][j+1] == EDITEURTUILE_DL) &&
				((Grille[i][j+1] == EDITEURTUILE_SQUARE || Grille[i][j+1] == EDITEURTUILE_DR) ||
				 (Grille[i+1][j] == EDITEURTUILE_SQUARE || Grille[i+1][j] == EDITEURTUILE_UL)))
				BoolCoins[i+1][j+1]=true;
			    //DL POINTE
			    if ((Grille[i-1][j] != EDITEURTUILE_UR && Grille[i-1][j] != EDITEURTUILE_UL && Grille[i-1][j] != EDITEURTUILE_NONE) &&
				(Grille[i-1][j-1] == EDITEURTUILE_SQUARE || Grille[i-1][j-1] == EDITEURTUILE_UR) &&
				((Grille[i][j-1] == EDITEURTUILE_SQUARE || Grille[i][j-1] == EDITEURTUILE_UL) ||
				 (Grille[i-1][j] == EDITEURTUILE_SQUARE || Grille[i-1][j] == EDITEURTUILE_DR)))
				BoolCoins[i][j]=true;
			    break;
			case EDITEURTUILE_UR:
			    //DL
			    if ((Grille[i-1][j] == EDITEURTUILE_DR || Grille[i-1][j] == EDITEURTUILE_DL || Grille[i-1][j] == EDITEURTUILE_SQUARE) &&
				(Grille[i-1][j-1] == EDITEURTUILE_SQUARE || Grille[i-1][j-1] == EDITEURTUILE_UR) &&
				(Grille[i][j-1] == EDITEURTUILE_UL || Grille[i][j-1] == EDITEURTUILE_DL || Grille[i][j-1] == EDITEURTUILE_SQUARE) &&
				(Grille[i-1][j] != Grille[i][j-1] || Grille[i-1][j] == EDITEURTUILE_SQUARE))
				BoolCoins[i][j]=true;
			    //UL POINTE
			    if ((Grille[i][j+1] != EDITEURTUILE_DR && Grille[i][j+1] != EDITEURTUILE_UR && Grille[i][j+1] != EDITEURTUILE_NONE) &&
				(Grille[i-1][j+1] == EDITEURTUILE_SQUARE || Grille[i-1][j+1] == EDITEURTUILE_DR) &&
				((Grille[i][j+1] == EDITEURTUILE_SQUARE || Grille[i][j+1] == EDITEURTUILE_DL) ||
				 (Grille[i-1][j] == EDITEURTUILE_SQUARE || Grille[i-1][j] == EDITEURTUILE_UR)))
				BoolCoins[i][j+1]=true;
			    //DR POINTE
			    if ((Grille[i+1][j] != EDITEURTUILE_UL && Grille[i+1][j] != EDITEURTUILE_UR && Grille[i+1][j] != EDITEURTUILE_NONE) &&
				(Grille[i+1][j-1] == EDITEURTUILE_SQUARE || Grille[i+1][j-1] == EDITEURTUILE_UL) &&
				((Grille[i][j-1] == EDITEURTUILE_SQUARE || Grille[i][j-1] == EDITEURTUILE_UR) ||
				 (Grille[i+1][j] == EDITEURTUILE_SQUARE || Grille[i+1][j] == EDITEURTUILE_DL)))
				BoolCoins[i+1][j]=true;
			    break;
			case EDITEURTUILE_DR:
			    //UL
			    if ((Grille[i-1][j] == EDITEURTUILE_UL || Grille[i-1][j] == EDITEURTUILE_UR || Grille[i-1][j] == EDITEURTUILE_SQUARE) &&
				(Grille[i-1][j+1] == EDITEURTUILE_SQUARE || Grille[i-1][j+1] == EDITEURTUILE_DR) &&
				(Grille[i][j+1] == EDITEURTUILE_UL || Grille[i][j+1] == EDITEURTUILE_DL || Grille[i][j+1] == EDITEURTUILE_SQUARE) &&
				(Grille[i-1][j] != Grille[i][j+1] || Grille[i-1][j] == EDITEURTUILE_SQUARE))
				BoolCoins[i][j+1]=true;
			    //UR POINTE
			    if ((Grille[i+1][j] != EDITEURTUILE_DL && Grille[i+1][j] != EDITEURTUILE_DR && Grille[i+1][j] != EDITEURTUILE_NONE) &&
				(Grille[i+1][j+1] == EDITEURTUILE_SQUARE || Grille[i+1][j+1] == EDITEURTUILE_DL) &&
				((Grille[i][j+1] == EDITEURTUILE_SQUARE || Grille[i][j+1] == EDITEURTUILE_DR) ||
				 (Grille[i+1][j] == EDITEURTUILE_SQUARE || Grille[i+1][j] == EDITEURTUILE_UL)))
				BoolCoins[i+1][j+1]=true;
			    //DL POINTE
			    if ((Grille[i][j-1] != EDITEURTUILE_UR && Grille[i][j-1] != EDITEURTUILE_DR && Grille[i][j-1] != EDITEURTUILE_NONE) &&
				(Grille[i-1][j-1] == EDITEURTUILE_SQUARE || Grille[i-1][j-1] == EDITEURTUILE_UR) &&
				((Grille[i][j-1] == EDITEURTUILE_SQUARE || Grille[i][j-1] == EDITEURTUILE_UL) ||
				 (Grille[i-1][j] == EDITEURTUILE_SQUARE || Grille[i-1][j] == EDITEURTUILE_DR)))
				BoolCoins[i][j]=true;
			    break;
			case EDITEURTUILE_DL:
			    //UR
			    if ((Grille[i+1][j] == EDITEURTUILE_UL || Grille[i+1][j] == EDITEURTUILE_UR || Grille[i+1][j] == EDITEURTUILE_SQUARE) &&
				(Grille[i+1][j+1] == EDITEURTUILE_SQUARE || Grille[i+1][j+1] == EDITEURTUILE_DL) &&
				(Grille[i][j+1] == EDITEURTUILE_DR || Grille[i][j+1] == EDITEURTUILE_UR || Grille[i][j+1] == EDITEURTUILE_SQUARE) &&
				(Grille[i+1][j] != Grille[i][j+1] || Grille[i+1][j] == EDITEURTUILE_SQUARE))
				BoolCoins[i+1][j+1]=true;
			    //UL POINTE
			    if ((Grille[i-1][j] != EDITEURTUILE_DL && Grille[i-1][j] != EDITEURTUILE_DR && Grille[i-1][j] != EDITEURTUILE_NONE) &&
				(Grille[i-1][j+1] == EDITEURTUILE_SQUARE || Grille[i-1][j+1] == EDITEURTUILE_DR) &&
				((Grille[i][j+1] == EDITEURTUILE_SQUARE || Grille[i][j+1] == EDITEURTUILE_DL) ||
				 (Grille[i-1][j] == EDITEURTUILE_SQUARE || Grille[i-1][j] == EDITEURTUILE_UR)))
				BoolCoins[i][j+1]=true;
			    //DR POINTE
			    if ((Grille[i][j-1] != EDITEURTUILE_UL && Grille[i][j-1] != EDITEURTUILE_DL && Grille[i][j-1] != EDITEURTUILE_NONE) &&
				(Grille[i+1][j-1] == EDITEURTUILE_SQUARE || Grille[i+1][j-1] == EDITEURTUILE_UL) &&
				((Grille[i][j-1] == EDITEURTUILE_SQUARE || Grille[i][j-1] == EDITEURTUILE_UR) ||
				 (Grille[i+1][j] == EDITEURTUILE_SQUARE || Grille[i+1][j] == EDITEURTUILE_DL)))
				BoolCoins[i+1][j]=true;
			    break;
			}
	}
    }
}
#endif

/*------------------------------------------------------------------
  Fonction :	CEditeurTerrain::AfficheTuiles

  Description :	Affiche toutes les tuiles de la grille

  Paramètres :

  Valeur retournée :	void : 

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
void CEditeurTerrain::AfficheTuiles(bool Pixmap)
{
	bool MouseOut = false;
    float MouseX = MousePosition.GetPosX();
    float MouseY = MousePosition.GetPosY();
    if (MouseX < 0 || MouseX >= GRILLE_W ||
		MouseY < 0 || MouseY >= GRILLE_H) MouseOut = true;
    int i,j;
#ifdef DEBUG_CORNERS
	if (!Pixmap)
	{
		for (i = 0; i < GRILLE_W+3; i++)
		{
			for (j = 0; j < GRILLE_H+3; j++)
			{
				BoolCoins[i][j]=false;
			}
		}
		RempliCoins();
	}
#endif
    for (i = 0; i < GRILLE_W; i++)
    {
		for (j = 0; j < GRILLE_H; j++)
		{
			DessineTuile(i,j,Grille[i+1][j+1]);
			AfficheBordures(vector2f(i,j));
		}
    }
    if (!Pixmap && !MouseOut && this->ModeEfface && Grille[int(MouseX)+1][int(MouseY)+1] != EDITEURTUILE_NONE)
    {
		bool Found = false;
		std::list< CEditeurObjet * >::const_iterator it;
		//Vérifier si la souris est sur un objet
		for (it = LesObjets.begin(); it != LesObjets.end(); it++)
		{
			if ((*it)->MouseOverRectangle(MouseX,MouseY))
			{
			Found = true;
			}
		}
		if (!Found)
		{
			glColor4f(1.0f,0.0f,0.0f,0.7f);
			glBegin(GL_QUADS);
			{
			glVertex2f(int(MouseX),int(MouseY));
			glVertex2f(int(MouseX)+1,int(MouseY));
			glVertex2f(int(MouseX)+1,int(MouseY)+1);
			glVertex2f(int(MouseX),int(MouseY)+1);
			}
			glEnd();
			glColor4f(1.0f,1.0f,1.0f,1.0f);
		}
    }
#ifdef DEBUG_CORNERS
	if (!Pixmap)
	{
		for (i = 0; i < GRILLE_W; i++)
		{
			for (j = 0; j < GRILLE_H; j++)
			{
				glColor3f(1,0,0);
				if (BoolCoins[i+1][j+1])
				{
				glBegin(GL_QUADS);
				{
					glVertex2f(i,j);
					glVertex2f(i,j+0.03);
					glVertex2f(i+0.03,j+0.03);
					glVertex2f(i+0.03,j);
				}
				glEnd();
				}
				glColor3f(1,1,1);
			}
		}
	}
#endif
}

/*------------------------------------------------------------------
  Fonction :	CEditeurTerrain::AfficheObjets

  Description :	Fonction qui affiche les AfficheGL de chaque objet de la liste

  Paramètres :

  Valeur retournée :	void : 

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
void CEditeurTerrain::AfficheObjets(bool Pixmap)
{
    std::list<CEditeurObjet *>::const_iterator it;
	bool MouseOut = false;
    float MouseX = MousePosition.GetPosX();
    float MouseY = MousePosition.GetPosY();
    if (MouseX < 0 || MouseX >= GRILLE_W ||
		MouseY < 0 || MouseY >= GRILLE_H) MouseOut = true;
	if (Pixmap || MouseOut)
	{
		for (it = LesObjets.begin();
		it != LesObjets.end();
		it++)
		{			
			(*it)->Affiche(!ValidePositionObjet((*it)));
		}
	} else {
		type_editeurtuile Tmp = Grille[int(MouseX)+1][int(MouseY)+1];
		bool OverAnObject = false;
		for (it = LesObjets.begin();
		it != LesObjets.end();
		it++)
		{
			if ((*it)->MouseOverRectangle(MouseX, MouseY))
			OverAnObject = true;
		}
		if (TuileCourante != EDITEURTUILE_NONE && !this->ModeEfface)
		{
			Grille[int(MouseX)+1][int(MouseY)+1] = TuileCourante;
		}
		if (ModeEfface && !OverAnObject)
		{
			Grille[int(MouseX)+1][int(MouseY)+1] = EDITEURTUILE_NONE;
		}
		for (it = LesObjets.begin();
		it != LesObjets.end();
		it++)
		{			
			(*it)->Affiche(!ValidePositionObjet((*it)));
		}
		Grille[int(MouseX)+1][int(MouseY)+1] = Tmp;	
    }
}

// Contructeur par défaut
CEditeurTerrain::CEditeurTerrain() : LesObjets()
{
    for (int i = 0; i < GRILLE_W + 2; i++)
	for (int j = 0; j < GRILLE_H + 2; j++)
	    Grille[i][j] = EDITEURTUILE_NONE;
    TuileCourante = EDITEURTUILE_NONE;
    ObjetCourant = 0;
    ModeEfface = false;
}

// Contructeur par copie
CEditeurTerrain::CEditeurTerrain(const CEditeurTerrain& copie)
{
    for (int i = 0; i < GRILLE_W + 2; i++)
	for (int j = 0; j < GRILLE_H + 2; j++)
	    Grille[i][j] = copie.Grille[i][j];
    
    for (std::list<CEditeurObjet*>::const_iterator it = copie.LesObjets.begin();
    it != copie.LesObjets.end(); it++)
    {
	LesObjets.push_back((*it)->GetNewCopy());
    }
    TuileCourante = EDITEURTUILE_NONE;
    ObjetCourant = 0;
    ModeEfface = false;
}

// Opérateur d'assignation
const CEditeurTerrain& CEditeurTerrain::operator =(const CEditeurTerrain& copie)
						  {
    for (int i = 0; i < GRILLE_W + 2; i++)
	for (int j = 0; j < GRILLE_H + 2; j++)
	    Grille[i][j] = copie.Grille[i][j];
    
    for (std::list<CEditeurObjet *>::iterator it = LesObjets.begin();
    it != LesObjets.end();)
    {
	delete (*it);
	it = LesObjets.erase(it);
    }
    
    for (std::list<CEditeurObjet *>::const_iterator const_it = copie.LesObjets.begin();
    const_it != copie.LesObjets.end(); const_it++)
    {
	LesObjets.push_back((*const_it)->GetNewCopy());
    }
    
    return *this;
}

/*------------------------------------------------------------------
  Fonction :	CEditeurTerrain::ChargeTextures

  Description :	Charge la texture du gazon et des bordures

  Paramètres :

  Valeur retournée :	bool : Vrai

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
bool CEditeurTerrain::ChargeTextures()
{
    // FONCTION À ÉCRIRE
    TexGazon.LoadPNG("editeur/images/Gazon.png");
    TexBordures.LoadPNG("editeur/images/Bordures.png");
    TexEfface.LoadPNG("editeur/images/efface_ul1.png");
    return true;
}

/*------------------------------------------------------------------
  Fonction :	CEditeurTerrain::DechargeTextures

  Description :	Décharge la texture du gazon et des bordures

  Paramètres :

  Valeur retournée :	bool : Vrai

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
bool CEditeurTerrain::DechargeTextures()
{
    TexGazon.Unload();
    TexBordures.Unload();
    return true;
}



// Fonctions qui affichent

//Cette fonction dessine la sélection courante (tuile/objet)
//Elle doit vérifier si l'objet peut être placé à cet endroit!
void CEditeurTerrain::DrawSelection()
{
    int iPosX = int(MousePosition.GetPosX());
    int iPosY = int(MousePosition.GetPosY());
    if (iPosX < 0) iPosX = 0;
	if (iPosX >= GRILLE_W) iPosX = GRILLE_W-1;
	if (iPosY < 0) iPosY = 0;
	if (iPosY >= GRILLE_H) iPosY = GRILLE_H-1;
    if (this->TuileCourante != EDITEURTUILE_NONE)
    {
	if (this->TuileCourante != Grille[iPosX+1][iPosY+1])
	{
		if (Grille[iPosX+1][iPosY+1] != EDITEURTUILE_NONE)
		{
			glColor4f(1,0,0,0.6);
			glBegin(GL_QUADS);
			{
				glVertex2f(iPosX,iPosY);
				glVertex2f(iPosX,iPosY+1);
				glVertex2f(iPosX+1,iPosY+1);
				glVertex2f(iPosX+1,iPosY);
			}
			glEnd();		
		}
	    glColor4f(1,1,1,0.8);
	    DessineTuile(iPosX,iPosY,TuileCourante);
	}
    } else if (this->ObjetCourant != 0) {
	ObjetCourant->setPosition(vector2f(MousePosition.GetPosX(),MousePosition.GetPosY()));
	ObjetCourant->Affiche(!ValidePositionObjet(ObjetCourant));
    }
    glColor4f(1,1,1,1);
}

/*------------------------------------------------------------------
  Fonction :	CEditeurTerrain::DrawEfface

  Description :	Dessine l'efface sur l'écran

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
void CEditeurTerrain::DrawEfface()
{
    if (!this->ModeEfface) return;
    //MousePosition
    glColor4f(1,1,1,1);
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, TexEfface.GetID());
    glBegin(GL_QUADS);
    {
	glTexCoord2i(0,0); glVertex2f(MousePosition.GetPosX(), MousePosition.GetPosY());
	glTexCoord2i(0,1); glVertex2f(MousePosition.GetPosX(), MousePosition.GetPosY()+0.75f);
	glTexCoord2i(1,1); glVertex2f(MousePosition.GetPosX()+0.75f, MousePosition.GetPosY()+0.75f);
	glTexCoord2i(1,0); glVertex2f(MousePosition.GetPosX()+0.75f, MousePosition.GetPosY());
    }
    glEnd();
    glDisable(GL_TEXTURE_2D);
    glColor4f(0.0f,0.0f,0.0f,0.5f);
    glBegin(GL_LINES);
    {
	glVertex2f(MousePosition.GetPosX(),MousePosition.GetPosY());
	glVertex2f(MousePosition.GetPosX()+0.1f,MousePosition.GetPosY());
	glVertex2f(MousePosition.GetPosX(),MousePosition.GetPosY());
	glVertex2f(MousePosition.GetPosX(),MousePosition.GetPosY()+0.1f);
    }
    glEnd();
    glColor4f(1.0f,1.0f,1.0f,1.0f);
}

/*------------------------------------------------------------------
  Fonction :	CEditeurTerrain::Affiche

  Description :	Dessine le terrain

  Paramètre : bool Pixmap : Dessine-t-on le pixmap?

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
void CEditeurTerrain::Affiche(bool Pixmap)
{
    glColor4f(1,1,1,1);
    AfficheTuiles(Pixmap);
    AfficheObjets(Pixmap);
}

/*------------------------------------------------------------------
  Fonction :	CEditeurTerrain::AfficheGrille

  Description :	Dessine la grille

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
void CEditeurTerrain::AfficheGrille(void)
{
    // FONCTION À ÉCRIRE
    
    glColor4f(0,0,0,0.7);
    
    glBegin(GL_LINES);
    for (int i = 0; i < GRILLE_W+1; i++)
    {
	glVertex2i(i, 0);
	glVertex2i(i, GRILLE_H);
    }
    for (int j = 0; j < GRILLE_H+1; j++)
    {
	glVertex2i(0, j);
	glVertex2i(GRILLE_W, j);
    }
    glEnd();
}

/*------------------------------------------------------------------
  Fonction :	CEditeurTerrain::setTuile

  Description :	Change une tuile du terrain et efface
					les objets qui deviennent invalides

	Paramètres : position de la tuile
				type de tuile

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
void CEditeurTerrain::setTuile(int x, int y, type_editeurtuile EDITEURTUILE)
{
    Grille[x][y] = EDITEURTUILE;
    std::list<CEditeurObjet *>::iterator it;
    for (it = LesObjets.begin();
    it != LesObjets.end();
    )
    {
	if (!ValidePositionObjet((*it)))
	{
	    delete (*it);
	    it = LesObjets.erase(it);
	} else {
	    it++;
	}
    }
}

type_editeurtuile CEditeurTerrain::getTuile(int x, int y) const
{
    return Grille[x][y];
}

void CEditeurTerrain::AjouteObjet(CEditeurObjet* objet)
{
    LesObjets.push_back(objet);
}

/*------------------------------------------------------------------
  Fonction :	CEditeurTerrain::AjoutObjetCourant

  Description :	Ajoute l'objet présentement sélectionné
					et fait la gestion d'invalidité

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
void CEditeurTerrain::AjoutObjetCourant()
{
    std::list< CEditeurObjet * >::iterator it;
    if (ObjetCourant == 0) return;
    if (!ValidePositionObjet(ObjetCourant)) return;
    if (ObjetCourant->GetType() == EDITEUROBJET_TROU) 
    {
	//On vérifie s'il y a déjà un trou
	for (it = LesObjets.begin(); it != LesObjets.end();)
	{
	    //Si on trouve un trou existant, on l'enlève
	    if ((*it)->GetType() == EDITEUROBJET_TROU)
	    {
		delete (*it);
		it = LesObjets.erase(it);
	    } else {
		it++;
	    }
	}	
	//On vérifie s'il y a déjà un départ
    } else if (ObjetCourant->GetType() >= EDITEUROBJET_DEPART_UP &&
	       ObjetCourant->GetType() <= EDITEUROBJET_DEPART_LEFT)
    {
	for (it = LesObjets.begin(); it != LesObjets.end();)
	{
	    //Si on trouve un départ existant, on l'enlève
	    if ((*it)->GetType() >= EDITEUROBJET_DEPART_UP &&
		(*it)->GetType() <= EDITEUROBJET_DEPART_LEFT)
	    {
		delete (*it);
		it = LesObjets.erase(it);
	    } else {
		it++;
	    }
	}
    }
    AjouteObjet(ObjetCourant->GetNewCopy());
}

/*------------------------------------------------------------------
  Fonction :	CEditeurTerrain::EnleveObjet

  Description :	Enleve un objet de la liste d'objets

  Paramètre : objet : L'objet à enlever

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
bool CEditeurTerrain::EnleveObjet(CEditeurObjet* objet)
{
    std::list<CEditeurObjet *>::iterator ItEfface;
    for (ItEfface = LesObjets.begin(); ItEfface != LesObjets.end();)
    {
	if(*ItEfface == objet)
	{
	    ItEfface = LesObjets.erase(ItEfface);
	    return true;
	} else {
	    ItEfface++;
	}
    }
    return false;
}

const std::list<CEditeurObjet*>& CEditeurTerrain::getListeObjets() const
{
    return LesObjets;
}

type_editeurtuile CEditeurTerrain::GetTuileCourante() const
{
    return this->TuileCourante;
}

void CEditeurTerrain::SetTuileCourante(const type_editeurtuile Tuile)
{
    this->TuileCourante = Tuile;
}

type_editeurobjet CEditeurTerrain::GetObjetCourant() const
{
    if (ObjetCourant == 0) return EDITEUROBJET_NONE;
    else return (ObjetCourant->GetType());
}

void CEditeurTerrain::SetObjetCourant(const type_editeurobjet Objet)
{
    if (ObjetCourant != 0)
    {
	delete ObjetCourant;
	ObjetCourant = 0;
    }
    if (Objet != EDITEUROBJET_NONE)
    {
	ObjetCourant = CEditeurObjet::CreerObjet(Objet,vector2f(MousePosition.GetPosX(),MousePosition.GetPosY()));
    }
}

//Position courante de la souris
	//Mise à jour lorsque la souris bouge sur le widget
void CEditeurTerrain::SetMousePosition(float PosX, float PosY)
{
    MousePosition.SetPosX(PosX);
    MousePosition.SetPosY(PosY);
}



/**************************************************************************************
Cette fonction permet de vérifier s'il existe un chemin valide entre le départ et
le trou d'un terrain.

  Paramètres :	vector2f posDepart --> position du départ
				vector2f posTrou   --> position du trou
				
  Valeur de retour: booléenne
***************************************************************************************/
#define DepX (int)posDepart.GetPosX()
#define DepY (int)posDepart.GetPosY()
//Tableau permettant de retenir quels endroits de la grille ont été visités
bool Visited[GRILLE_W+2][GRILLE_H+2];

bool CEditeurTerrain::TrajetValide(vector2f posDepart, vector2f posTrou)
{
    
    if (Visited[DepX][DepY])
	return false;
    else
	Visited[DepX][DepY] = true;
    
    if (posDepart == posTrou)
	return true;
    
    //À GAUCHE
    if (Grille[DepX][DepY] == EDITEURTUILE_SQUARE || Grille[DepX][DepY] == EDITEURTUILE_UL ||
	Grille[DepX][DepY] == EDITEURTUILE_DL)
    {
	if (Grille[DepX-1][DepY] == EDITEURTUILE_SQUARE || Grille[DepX-1][DepY] == EDITEURTUILE_UR ||
	    Grille[DepX-1][DepY] == EDITEURTUILE_DR)
	{
	    if (TrajetValide(vector2f(posDepart.GetPosX() -1.0f, posDepart.GetPosY()), posTrou))
		return true;
	}
    }
    
    //À DROITE
    if (Grille[DepX][DepY] == EDITEURTUILE_SQUARE || Grille[DepX][DepY] == EDITEURTUILE_UR ||
	Grille[DepX][DepY] == EDITEURTUILE_DR)
    {
	if (Grille[DepX+1][DepY] == EDITEURTUILE_SQUARE || Grille[DepX+1][DepY] == EDITEURTUILE_UL ||
	    Grille[DepX+1][DepY] == EDITEURTUILE_DL)
	{
	    if (TrajetValide(vector2f(posDepart.GetPosX() +1.0f, posDepart.GetPosY()), posTrou))
		return true;
	}
    }
    
    //EN HAUT
    if (Grille[DepX][DepY] == EDITEURTUILE_SQUARE || Grille[DepX][DepY] == EDITEURTUILE_UL ||
	Grille[DepX][DepY] == EDITEURTUILE_UR)
    {
	if (Grille[DepX][DepY+1] == EDITEURTUILE_SQUARE || Grille[DepX][DepY+1] == EDITEURTUILE_DL ||
	    Grille[DepX][DepY+1] == EDITEURTUILE_DR)
	{
	    if (TrajetValide(vector2f(posDepart.GetPosX(), posDepart.GetPosY() + 1.0f), posTrou))
		return true;
	}
    }
    
    //EN BAS
    if (Grille[DepX][DepY] == EDITEURTUILE_SQUARE || Grille[DepX][DepY] == EDITEURTUILE_DR ||
	Grille[DepX][DepY] == EDITEURTUILE_DL)
    {
	if (Grille[DepX][DepY-1] == EDITEURTUILE_SQUARE || Grille[DepX][DepY-1] == EDITEURTUILE_UR ||
	    Grille[DepX][DepY-1] == EDITEURTUILE_UL)
	{
	    if (TrajetValide(vector2f(posDepart.GetPosX(), posDepart.GetPosY() -1.0f), posTrou))
		return true;
	}
    }
    
    return false;
    
    //tempo
    return true;
}

/**************************************************************************************
Cette fonction permet de vérifier si le terrain créé est valide, i.e. s'il a un début
et une fin ET s'il existe un chemin valide entre le départ et le trou.

  Paramètres :	
  
  Valeur de retour: 0 si Valide
					1 si pas de trou
					2 si pas de départ
					3 si pas de départ ni de trou
					4 si chemin invalide entre départ et trou
***************************************************************************************/
int CEditeurTerrain::TerrainValide()
{
    int i, j;
    bool IsDepart=false, IsTrou=false;
    vector2f LeTrou, LeDepart;
    
    //Trouver le départ et le trou dans la liste, s'il y a lieu
    std::list< CEditeurObjet* >::iterator it;
    for (it = LesObjets.begin(); it != LesObjets.end(); ++it)
    {
	if ((*it)->GetType() == EDITEUROBJET_DEPART_UP ||(*it)->GetType() == EDITEUROBJET_DEPART_RIGHT
	    ||(*it)->GetType() == EDITEUROBJET_DEPART_DOWN || (*it)->GetType() == EDITEUROBJET_DEPART_LEFT)
	{
	    IsDepart = true;
	    LeDepart = vector2f((int)((*it)->getPosition().GetPosX()+1.0f),(int)((*it)->getPosition().GetPosY()+1.0f));
	}
	
	if ((*it)->GetType() == EDITEUROBJET_TROU)
	{
	    IsTrou = true;
	    LeTrou = vector2f((int)((*it)->getPosition().GetPosX()+1.0f),(int)((*it)->getPosition().GetPosY()+1.0f));
	}
    }
    //les cas sont séparés pour savoir la raison de l'échec lors de l'appel à partir
    //de la fct enregistrer....
    
    if( !IsTrou )
    {
	//pas de trou NI de départ
	if (!IsDepart)
	    return 3;
	//pas de trou, mais départ
	else
	    return 1;
    }
    //pas de départ, mais trou
    else if (!IsDepart)
	return 2;
    
    //trajet invalide, mais trou ET départ
    else
    {
	for (i = 0; i < GRILLE_W+2; i++)
	{
	    for (j = 0; j < GRILLE_H+2; j++)
	    {
		Visited[i][j] = false;
	    }
	}
	if (!TrajetValide(LeDepart, LeTrou))
	    return 4;
    }
    
    //valide :)
    return 0;
}

/*------------------------------------------------------------------
  Fonction :	CEditeurTerrain::Enregistre

  Description :	Enregistre le terrain actuel
					-> Enregistre aussi l'image correspondant
						à ce terrain

  Paramètre : NomFic : Nom du fichier à sauvegarder
				Widget : Le widget permettant d'effectuer une
						capture d'écran

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
void CEditeurTerrain::Enregistre(const char* NomFic, glEditeurWidget* Widget)
{
    char buffer[] = "carmonit";
    
    std::ofstream Fic(NomFic, std::ios::binary);
    
    // Écriture de notre entête de fichier
    Fic.write( (char *) buffer, 8*sizeof(char));
    
    // Écriture de l'apercu du trou
    Widget->SetDrawingPixmap(true);
	Widget->updateGL();
	Widget->grabFrameBuffer(true).scale(128,128).save(QString(NomFic) + ".png", "PNG");
	Widget->SetDrawingPixmap(false);
	
    int TamponEntier;
    float TamponReel;
    
    // Écriture de la grille
    
    Fic.write( (char *) Grille, (GRILLE_W+2)*(GRILLE_H+2)*sizeof(type_editeurtuile));
    
    // Écriture de la liste d'objets
    
    // On commence par le nombre d'objet
    TamponEntier = LesObjets.size();
    Fic.write( (char *) &TamponEntier, sizeof(int));
    
    for (std::list<CEditeurObjet*>::const_iterator it = LesObjets.begin();
    it != LesObjets.end(); it++)
    {
	TamponEntier = (int) ((*it)->GetType());
	Fic.write( (char *) &TamponEntier, sizeof(int));
	TamponReel = (*it)->getPosition().GetPosX();
	Fic.write( (char *) &TamponReel, sizeof(int));
	TamponReel = (*it)->getPosition().GetPosY();
	Fic.write( (char *) &TamponReel, sizeof(int));
    }
    
    Fic.close();
}


// Macro
#define VALIDE               \
if (Fic.fail() || Fic.eof()) \
{                            \
			     Fic.close();              \
			     return false;             \
			 }

/*------------------------------------------------------------------
  Fonction :	CEditeurTerrain::Charge

  Description :	Charge un terrain

  Paramètre : NomFic : Nom du fichier à charger

  Retour : bool : si tout se passe bien

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
bool CEditeurTerrain::Charge(const char* NomFic)
{
    for (std::list<CEditeurObjet *>::iterator it = LesObjets.begin();
    it != LesObjets.end();)
    {
	delete (*it);
	it = LesObjets.erase(it);
    }
    
    char buffer[] = "carmonit";
    
    std::ifstream Fic(NomFic, std::ios::binary);
    VALIDE
	    
	    // Lecture de notre entête de fichier
	    Fic.read( (char *) buffer, 8*sizeof(char));
    VALIDE
	    
	    if (strcmp(buffer, "carmonit") != 0)
    {
	Fic.close();
	return false;
    }
    
    // Lecture de la grille
    Fic.read( (char *) Grille, (GRILLE_W+2)*(GRILLE_H+2)*sizeof(type_editeurtuile));
    VALIDE
	    
	    int NbObjets, Type;
    float X, Y;
    CEditeurObjet* NouvelObjet;
    
    Fic.read( (char *) &NbObjets, sizeof(int));
    VALIDE
	    
	    // Lecture des objets
	    for (int i = 0; i < NbObjets; i++)
    {
	Fic.read( (char *) &Type, sizeof(int));
	VALIDE
		Fic.read( (char *) &X, sizeof(int));
	VALIDE
		Fic.read( (char *) &Y, sizeof(int));
	VALIDE
		NouvelObjet = CEditeurObjet::CreerObjet( (type_editeurobjet) Type, vector2f(X, Y));
	if (NouvelObjet == 0)
	{
	    Fic.close();
	    return false;
	}
	LesObjets.push_back(NouvelObjet);
    }
    
    Fic.close();
    
    return true;
}


/*------------------------------------------------------------------
  Fonction :	CEditeurTerrain::Efface

  Description :	Effectue l'effacement

  Par : 2004-3-16 Martin Bisson, Anne-Marie Buki, Mylene Denis & Jean-Francois Pérusse
  MAJ: 
------------------------------------------------------------------*/
void CEditeurTerrain::Efface()
{
    std::list< CEditeurObjet * >::iterator it;
	std::list< CEditeurObjet * >::reverse_iterator rit;
    //Vérifier si la souris est sur un objet
    for (rit = LesObjets.rbegin(); rit != LesObjets.rend(); ++rit)
    {
		//Si oui, enlever l'objet
		if ((*rit)->MouseOverRectangle(MousePosition.GetPosX(),MousePosition.GetPosY()))
		{
			delete (*rit);
			LesObjets.remove(*rit);
			return;
		}
    }
	if (Grille[int(MousePosition.GetPosX())+1][int(MousePosition.GetPosY())+1] != EDITEURTUILE_NONE)
	{
	    //Effacer la tuile
	    Grille[int(MousePosition.GetPosX())+1][int(MousePosition.GetPosY())+1] = EDITEURTUILE_NONE;
	    //Effacer les objets en contact avec la tuile
	    for (it = LesObjets.begin(); it != LesObjets.end();)
	    {
		if (!ValidePositionObjet((*it)))
		{
		    delete (*it);
		    it = LesObjets.erase(it);
		} else {
		    ++it;
		}
	    }
    }
}
/**************************************************************************************
Cette fonction permet de vérifier s'il y a une intersection entre deux segments de
droite.

  Paramètres :	4 points du plan xy: A1, A2, B1, B2 ---> vector2f
  
  Valeur de retour: TRUE s'il y a une intersection entre le segment (A1,A2) et le
					segment (B1,B2)
					FALSE sinon
***************************************************************************************/
bool CEditeurTerrain::Intersection(const vector2f A1, const vector2f A2, const vector2f B1, const vector2f B2) const
{
    vector2f B1A1, B1B2, B1A2, A1B2, A1A2, A1B1;
    float Validation1, Validation2;
    
    B1A1 = A1-B1;
    B1B2 = B2-B1;
    B1A2 = A2-B1;
    A1B2 = B2-A1;
    A1A2 = A2-A1;
    A1B1 = B1-A1;
    
    Validation1 = (B1A1.SideProduct(B1B2))*(B1A2.SideProduct(B1B2));
    Validation2 = (A1B2.SideProduct(A1A2))*(A1B1.SideProduct(A1A2));
    if (Validation1 < 0.0f && Validation2 < 0.0f)
	return true;
    else
	return false;
}

#define IsInRect(pointx,pointy,left,right,top,bottom) \
(pointx >= left-0.001f*left && pointx <= right+0.001f*right && pointy >= bottom-0.001f*bottom && pointy <= top+0.001f*top)
	
	/*****************************************************
Cette fonction vérifie la position actuelle d'un objet
afin de valider celle-ci. De plus, elle vérifie si
l'efface est présentement placée sur cet objet.

---Cette fonction DÉTERMINE SI L'OBJET DOIT ÊTRE DESSINÉ
	EN ROUGE---
	
Retour:
	Vrai : si la position est valide et que l'efface
		n'est pas sur l'objet.
	Faux : si la position n'est pas valide ou si
		l'efface est sur l'objet.
*****************************************************/
	bool CEditeurTerrain::ValidePositionObjet(CEditeurObjet* Objet) const
{
    int i,j;
	bool MouseOut = false;
    float MouseX = MousePosition.GetPosX();
    float MouseY = MousePosition.GetPosY();
    if (MouseX < 0 || MouseX >= GRILLE_W ||
		MouseY < 0 || MouseY >= GRILLE_H) MouseOut = true;
    std::list< CEditeurObjet * >::const_iterator it;
	std::list< CEditeurObjet * >::const_reverse_iterator rit;
    //vérifie si l'efface est sur l'objet mais pas sur un autre plus haut
	bool FoundOne = false;
	if (this->ModeEfface && !MouseOut)
	{
		for (rit = LesObjets.rbegin(); rit != LesObjets.rend(); rit++)
			if ((*rit)->MouseOverRectangle(MouseX, MouseY))
				if ((*rit)!=Objet)
				{
					FoundOne = true;
					break;
				} else
					break;
		if (!FoundOne && Objet->MouseOverRectangle(MouseX, MouseY))
			return false;
	}
    //vérifie la position de l'objet sur les tuiles
    //OBJET DANS LE VIDE
    float PosX = Objet->getPosition().GetPosX();
    float PosY = Objet->getPosition().GetPosY();
    float RelX = PosX - (float)(int(PosX));
    float RelY = PosY - (float)(int(PosY));
    switch (Grille[(int)PosX+1][(int)PosY+1])
    {
    case EDITEURTUILE_NONE:
	return false;
	break;
    case EDITEURTUILE_UL:
	if (RelY <= RelX)
	    return false;
	break;
    case EDITEURTUILE_UR:
	if (RelY <= (float)((int)RelX+1)-RelX)
	    return false;
	break;
    case EDITEURTUILE_DL:
	if (RelX >= (float)((int)RelY+1)-RelY)
	    return false;
	break;
    case EDITEURTUILE_DR:
	if (RelX <= RelY)
	    return false;
	break;
    }
    //INTERSECTION CÔTÉ HAUT
    for (i = (int)Objet->GetLeft(); i <= (int)Objet->GetRight(); i++)
    {
	j = (int)Objet->GetTop();
	switch (Grille[i+1][j+1])
	{
		case EDITEURTUILE_NONE:
		    return false;
		    break;
		case EDITEURTUILE_SQUARE:
		    if (BordureATracer(vector2f(i,j),vector2f(-1,0)) &&
			Intersection(vector2f(Objet->GetLeft(),Objet->GetTop()),
				     vector2f(Objet->GetRight(),Objet->GetTop()),
				     vector2f(i,j),
				     vector2f(i,j+1)))
			return false;
		    if (BordureATracer(vector2f(i,j),vector2f(1,0)) && \
			Intersection(vector2f(Objet->GetLeft(),Objet->GetTop()),
				     vector2f(Objet->GetRight(),Objet->GetTop()),
				     vector2f(i+1,j),
				     vector2f(i+1,j+1)))
			return false;
		    break;
		case EDITEURTUILE_UL:
		    if (BordureATracer(vector2f(i,j),vector2f(-1,0)) &&
			Intersection(vector2f(Objet->GetLeft(),Objet->GetTop()),
				     vector2f(Objet->GetRight(),Objet->GetTop()),
				     vector2f(i,j),
				     vector2f(i,j+1)))
			return false;
		    if (Intersection(vector2f(Objet->GetLeft(),Objet->GetTop()),
				     vector2f(Objet->GetRight(),Objet->GetTop()),
				     vector2f(i,j),
				     vector2f(i+1,j+1)))
			return false;
		    break;
		case EDITEURTUILE_UR:
		    if (BordureATracer(vector2f(i,j),vector2f(1,0)) && \
			Intersection(vector2f(Objet->GetLeft(),Objet->GetTop()),
				     vector2f(Objet->GetRight(),Objet->GetTop()),
				     vector2f(i+1,j),
				     vector2f(i+1,j+1)))
			return false;
		    if (Intersection(vector2f(Objet->GetLeft(),Objet->GetTop()),
				     vector2f(Objet->GetRight(),Objet->GetTop()),
				     vector2f(i+1,j),
				     vector2f(i,j+1)))
			return false;
		    break;
		case EDITEURTUILE_DL:
		    if (BordureATracer(vector2f(i,j),vector2f(-1,0)) &&
			Intersection(vector2f(Objet->GetLeft(),Objet->GetTop()),
				     vector2f(Objet->GetRight(),Objet->GetTop()),
				     vector2f(i,j),
				     vector2f(i,j+1)))
			return false;
		    if (Intersection(vector2f(Objet->GetLeft(),Objet->GetTop()),
				     vector2f(Objet->GetRight(),Objet->GetTop()),
				     vector2f(i+1,j),
				     vector2f(i,j+1)))
			return false;
		    break;
		case EDITEURTUILE_DR:
		    if (BordureATracer(vector2f(i,j),vector2f(1,0)) && \
			Intersection(vector2f(Objet->GetLeft(),Objet->GetTop()),
				     vector2f(Objet->GetRight(),Objet->GetTop()),
				     vector2f(i+1,j),
				     vector2f(i+1,j+1)))
			return false;
		    if (Intersection(vector2f(Objet->GetLeft(),Objet->GetTop()),
				     vector2f(Objet->GetRight(),Objet->GetTop()),
				     vector2f(i,j),
				     vector2f(i+1,j+1)))
			return false;
		    break;
		}
    }
    //INTERSECTION CÔTÉ DROIT
    for (i = (int)Objet->GetBottom(); i <= (int)Objet->GetTop(); i++)
    {
	j = (int)Objet->GetRight();
	switch (Grille[j+1][i+1])
	{
		case EDITEURTUILE_NONE:
		    return false;
		    break;
		case EDITEURTUILE_SQUARE:
		    if (BordureATracer(vector2f(j,i),vector2f(1,0)) && \
			Intersection(vector2f(Objet->GetLeft(),Objet->GetTop()),
				     vector2f(Objet->GetRight(),Objet->GetTop()),
				     vector2f(j+1,i),
				     vector2f(j+1,i+1)))
			return false;
		    if (BordureATracer(vector2f(j,i),vector2f(0,-1)) && \
			Intersection(vector2f(Objet->GetRight(),Objet->GetBottom()),
				     vector2f(Objet->GetRight(),Objet->GetTop()),
				     vector2f(j,i),
				     vector2f(j+1,i)))
			return false;
		    if (BordureATracer(vector2f(j,i),vector2f(0,1)) && \
			Intersection(vector2f(Objet->GetRight(),Objet->GetBottom()),
				     vector2f(Objet->GetRight(),Objet->GetTop()),
				     vector2f(j,i+1),
				     vector2f(j+1,i+1)))
			return false;
		    break;
		case EDITEURTUILE_UL:
		    if (BordureATracer(vector2f(j,i),vector2f(0,1)) && \
			Intersection(vector2f(Objet->GetRight(),Objet->GetBottom()),
				     vector2f(Objet->GetRight(),Objet->GetTop()),
				     vector2f(j,i+1),
				     vector2f(j+1,i+1)))
			return false;
		    if (Intersection(vector2f(Objet->GetRight(),Objet->GetBottom()),
				     vector2f(Objet->GetRight(),Objet->GetTop()),
				     vector2f(j,i),
				     vector2f(j+1,i+1)))
			return false;
		    break;
		case EDITEURTUILE_UR:
		    if (BordureATracer(vector2f(j,i),vector2f(0,1)) && \
			Intersection(vector2f(Objet->GetRight(),Objet->GetBottom()),
				     vector2f(Objet->GetRight(),Objet->GetTop()),
				     vector2f(j,i+1),
				     vector2f(j+1,i+1)))
			return false;
		    if (Intersection(vector2f(Objet->GetRight(),Objet->GetBottom()),
				     vector2f(Objet->GetRight(),Objet->GetTop()),
				     vector2f(j+1,i),
				     vector2f(j,i+1)))
			return false;
		    break;
		case EDITEURTUILE_DL:
		    if (BordureATracer(vector2f(j,i),vector2f(0,-1)) && \
			Intersection(vector2f(Objet->GetRight(),Objet->GetBottom()),
				     vector2f(Objet->GetRight(),Objet->GetTop()),
				     vector2f(j,i),
				     vector2f(j+1,i)))
			return false;
		    if (Intersection(vector2f(Objet->GetRight(),Objet->GetBottom()),
				     vector2f(Objet->GetRight(),Objet->GetTop()),
				     vector2f(j+1,i),
				     vector2f(j,i+1)))
			return false;
		    break;
		case EDITEURTUILE_DR:
		    if (BordureATracer(vector2f(j,i),vector2f(0,-1)) && \
			Intersection(vector2f(Objet->GetRight(),Objet->GetBottom()),
				     vector2f(Objet->GetRight(),Objet->GetTop()),
				     vector2f(j,i),
				     vector2f(j+1,i)))
			return false;
		    if (Intersection(vector2f(Objet->GetRight(),Objet->GetBottom()),
				     vector2f(Objet->GetRight(),Objet->GetTop()),
				     vector2f(j,i),
				     vector2f(j+1,i+1)))
			return false;
		    break;
		}
    }
    //INTERSECTION CÔTÉ BAS
    for (i = (int)Objet->GetLeft(); i <= (int)Objet->GetRight(); i++)
    {
	j = (int)Objet->GetBottom();
	switch (Grille[i+1][j+1])
	{
		case EDITEURTUILE_NONE:
		    return false;
		    break;
		case EDITEURTUILE_SQUARE:
		    if (BordureATracer(vector2f(i,j),vector2f(-1,0)) && \
			Intersection(vector2f(Objet->GetLeft(),Objet->GetBottom()),
				     vector2f(Objet->GetRight(),Objet->GetBottom()),
				     vector2f(i,j),
				     vector2f(i,j+1)))
			return false;
		    if (BordureATracer(vector2f(i,j),vector2f(1,0)) && \
			Intersection(vector2f(Objet->GetLeft(),Objet->GetBottom()),
				     vector2f(Objet->GetRight(),Objet->GetBottom()),
				     vector2f(i+1,j),
				     vector2f(i+1,j+1)))
			return false;
		    break;
		case EDITEURTUILE_UL:
		    if (BordureATracer(vector2f(i,j),vector2f(-1,0)) && \
			Intersection(vector2f(Objet->GetLeft(),Objet->GetBottom()),
				     vector2f(Objet->GetRight(),Objet->GetBottom()),
				     vector2f(i,j),
				     vector2f(i,j+1)))
			return false;
		    if (Intersection(vector2f(Objet->GetLeft(),Objet->GetBottom()),
				     vector2f(Objet->GetRight(),Objet->GetBottom()),
				     vector2f(i,j),
				     vector2f(i+1,j+1)))
			return false;
		    break;
		case EDITEURTUILE_UR:
		    if (BordureATracer(vector2f(i,j),vector2f(1,0)) && \
			Intersection(vector2f(Objet->GetLeft(),Objet->GetBottom()),
				     vector2f(Objet->GetRight(),Objet->GetBottom()),
				     vector2f(i+1,j),
				     vector2f(i+1,j+1)))
			return false;
		    if (Intersection(vector2f(Objet->GetLeft(),Objet->GetBottom()),
				     vector2f(Objet->GetRight(),Objet->GetBottom()),
				     vector2f(i+1,j),
				     vector2f(i,j+1)))
			return false;
		    break;
		case EDITEURTUILE_DL:
		    if (BordureATracer(vector2f(i,j),vector2f(-1,0)) && \
			Intersection(vector2f(Objet->GetLeft(),Objet->GetBottom()),
				     vector2f(Objet->GetRight(),Objet->GetBottom()),
				     vector2f(i,j),
				     vector2f(i,j+1)))
			return false;
		    if (Intersection(vector2f(Objet->GetLeft(),Objet->GetBottom()),
				     vector2f(Objet->GetRight(),Objet->GetBottom()),
				     vector2f(i+1,j),
				     vector2f(i,j+1)))
			return false;
		    break;
		case EDITEURTUILE_DR:
		    if (BordureATracer(vector2f(i,j),vector2f(1,0)) && \
			Intersection(vector2f(Objet->GetLeft(),Objet->GetBottom()),
				     vector2f(Objet->GetRight(),Objet->GetBottom()),
				     vector2f(i+1,j),
				     vector2f(i+1,j+1)))
			return false;
		    if (Intersection(vector2f(Objet->GetLeft(),Objet->GetBottom()),
				     vector2f(Objet->GetRight(),Objet->GetBottom()),
				     vector2f(i,j),
				     vector2f(i+1,j+1)))
			return false;
		    break;
		}
    }
    //INTERSECTION CÔTÉ GAUCHE
    for (i = (int)Objet->GetBottom(); i <= (int)Objet->GetTop(); i++)
    {
	j = (int)Objet->GetLeft();
	switch (Grille[j+1][i+1])
	{
		case EDITEURTUILE_NONE:
		    return false;
		    break;
		case EDITEURTUILE_SQUARE:
		    if (BordureATracer(vector2f(j,i),vector2f(0,-1)) && \
			Intersection(vector2f(Objet->GetLeft(),Objet->GetBottom()),
				     vector2f(Objet->GetLeft(),Objet->GetTop()),
				     vector2f(j,i),
				     vector2f(j+1,i)))
			return false;
		    if (BordureATracer(vector2f(j,i),vector2f(0,1)) && \
			Intersection(vector2f(Objet->GetLeft(),Objet->GetBottom()),
				     vector2f(Objet->GetLeft(),Objet->GetTop()),
				     vector2f(j,i+1),
				     vector2f(j+1,i+1)))
			return false;
		    break;
		case EDITEURTUILE_UL:
		    if (BordureATracer(vector2f(j,i),vector2f(0,1)) && \
			Intersection(vector2f(Objet->GetLeft(),Objet->GetBottom()),
				     vector2f(Objet->GetLeft(),Objet->GetTop()),
				     vector2f(j,i+1),
				     vector2f(j+1,i+1)))
			return false;
		    if (Intersection(vector2f(Objet->GetLeft(),Objet->GetBottom()),
				     vector2f(Objet->GetLeft(),Objet->GetTop()),
				     vector2f(j,i),
				     vector2f(j+1,i+1)))
			return false;
		    break;
		case EDITEURTUILE_UR:
		    if (BordureATracer(vector2f(j,i),vector2f(0,1)) && \
			Intersection(vector2f(Objet->GetLeft(),Objet->GetBottom()),
				     vector2f(Objet->GetLeft(),Objet->GetTop()),
				     vector2f(j,i+1),
				     vector2f(j+1,i+1)))
			return false;
		    if (Intersection(vector2f(Objet->GetLeft(),Objet->GetBottom()),
				     vector2f(Objet->GetLeft(),Objet->GetTop()),
				     vector2f(j+1,i),
				     vector2f(j,i+1)))
			return false;
		    break;
		case EDITEURTUILE_DL:
		    if (BordureATracer(vector2f(j,i),vector2f(0,-1)) && \
			Intersection(vector2f(Objet->GetLeft(),Objet->GetBottom()),
				     vector2f(Objet->GetLeft(),Objet->GetTop()),
				     vector2f(j,i),
				     vector2f(j+1,i)))
			return false;
		    if (Intersection(vector2f(Objet->GetLeft(),Objet->GetBottom()),
				     vector2f(Objet->GetLeft(),Objet->GetTop()),
				     vector2f(j+1,i),
				     vector2f(j,i+1)))
			return false;
		    break;
		case EDITEURTUILE_DR:
		    if (BordureATracer(vector2f(j,i),vector2f(0,-1)) && \
			Intersection(vector2f(Objet->GetLeft(),Objet->GetBottom()),
				     vector2f(Objet->GetLeft(),Objet->GetTop()),
				     vector2f(j,i),
				     vector2f(j+1,i)))
			return false;
		    if (Intersection(vector2f(Objet->GetLeft(),Objet->GetBottom()),
				     vector2f(Objet->GetLeft(),Objet->GetTop()),
				     vector2f(j,i),
				     vector2f(j+1,i+1)))
			return false;
		    break;
		}
    }
    //CARRÉS À L'INTÉRIEUR DE L'OBJET
    for (i = (int)Objet->GetLeft()+2; i <= (int)Objet->GetRight(); i++)
    {
	for (j = (int)Objet->GetBottom()+2; j <= (int)Objet->GetTop(); j++)
	{
	    if (Grille[i][j] != EDITEURTUILE_SQUARE)
		return false;
	}
    }
    //vérifie la position de l'objet par rapport aux autres objets 
    for (it = LesObjets.begin(); it != LesObjets.end(); it++)
    {
	if ((*it) != Objet &&
	    !((*it)->GetType() == EDITEUROBJET_TROU && Objet->GetType() == EDITEUROBJET_TROU) &&
	    !(((*it)->GetType() >= EDITEUROBJET_DEPART_UP && (*it)->GetType() <= EDITEUROBJET_DEPART_LEFT) \
	      && (Objet->GetType() >= EDITEUROBJET_DEPART_UP && Objet->GetType() <= EDITEUROBJET_DEPART_LEFT)))
	{
	    //HAUT GAUCHE
	    if (IsInRect(Objet->GetLeft(),Objet->GetTop(),(*it)->GetLeft(),\
			 (*it)->GetRight(),(*it)->GetTop(),(*it)->GetBottom()))
		return false;
	    if (IsInRect((*it)->GetLeft(),(*it)->GetTop(),Objet->GetLeft(),\
			 Objet->GetRight(),Objet->GetTop(),Objet->GetBottom()))
		return false;
	    //HAUT DROIT
	    if (IsInRect(Objet->GetRight(),Objet->GetTop(),(*it)->GetLeft(),\
			 (*it)->GetRight(),(*it)->GetTop(),(*it)->GetBottom()))
		return false;
	    if (IsInRect((*it)->GetRight(),(*it)->GetTop(),Objet->GetLeft(),\
			 Objet->GetRight(),Objet->GetTop(),Objet->GetBottom()))
		return false;
	    //BAS GAUCHE
	    if (IsInRect(Objet->GetLeft(),Objet->GetBottom(),(*it)->GetLeft(),\
			 (*it)->GetRight(),(*it)->GetTop(),(*it)->GetBottom()))
		return false;
	    if (IsInRect((*it)->GetLeft(),(*it)->GetBottom(),Objet->GetLeft(),\
			 Objet->GetRight(),Objet->GetTop(),Objet->GetBottom()))
		return false;
	    //BAS DROIT
	    if (IsInRect(Objet->GetRight(),Objet->GetBottom(),(*it)->GetLeft(),\
			 (*it)->GetRight(),(*it)->GetTop(),(*it)->GetBottom()))
		return false;
	    if (IsInRect((*it)->GetRight(),(*it)->GetBottom(),Objet->GetLeft(),\
			 Objet->GetRight(),Objet->GetTop(),Objet->GetBottom()))
		return false;
	    //CENTRE
	    if (IsInRect(PosX,PosY,(*it)->GetLeft(),\
			 (*it)->GetRight(),(*it)->GetTop(),(*it)->GetBottom()))
		return false;
	    if (IsInRect((*it)->getPosition().GetPosX(),(*it)->getPosition().GetPosY(),Objet->GetLeft(),\
			 Objet->GetRight(),Objet->GetTop(),Objet->GetBottom()))
		return false;			
	}
    }
    return true;
}
