SDL_Window.cpp

Aller à la documentation de ce fichier.
00001 #include "SDL_Window.h"
00002 
00003 using namespace std;
00004 
00005 //retourne true si un problème à eu lieu, false sinon.
00006 bool SDL_Window::Draw()
00007 {
00008     // calcul des coordonées absolues de la fenêtre
00009     SDL_Rect coordAbs=coord;
00010     calcCoord(&coordAbs);
00011 
00012     if(ClearWindow())
00013     {
00014         fprintf(stderr,"SDL_Window::Draw(), 1: Echec de ClearWindow\n");
00015         return true;
00016     }
00017     if(PrepareWindow())//cette fonction devra vérifier si il est nécessaire de refaire tous les calculs
00018     {
00019         fprintf(stderr,"SDL_Window::Draw(), 2: Echec de PrepareWindow\n");
00020         return true;
00021     }
00022     if(SDL_BlitSurface(screen,&coordAbs,shadow,NULL))//sauvegarde de l'écran
00023     {
00024         fprintf(stderr,"SDL_Window::Draw(), 3: Echec de SDL_BlitSurface:%s\n",SDL_GetError());
00025         return true;
00026     }
00027     if(SDL_BlitSurface(window,NULL,screen,&coordAbs))//affichage
00028     {
00029         fprintf(stderr,"SDL_Window::Draw(), 4: Echec de SDL_BlitSurface:%s\n",SDL_GetError());
00030         return true;
00031     }
00032 
00033     SDL_Window *ptrMere=mere;
00034     while(ptrMere)
00035     {fputc('\t',stderr);ptrMere=ptrMere->mere;}
00036     fprintf(stderr,"%x coord:(%d,%d)/(%d,%d)\toldCoord:(%d,%d)/(%d,%d)\n",(int)this,coord.x,coord.y,coord.w,coord.h,oldCoord.x,oldCoord.y,oldCoord.w,oldCoord.h);
00037     oldCoord=coord;
00038     for_each(filles.begin(),filles.end(), mem_fun(&SDL_Window::Draw));
00039 
00040     drawed=true;
00041     return false;
00042 }
00043 
00044 //Redimensionne la fenêtre
00045 //Si relative vaut:
00046 //0: données brutes
00047 //1: données relatives (agrandit ou rétrécit donc)
00048 //true si échec
00049 bool SDL_Window::Resize(short width, short height, unsigned char relative)
00050 {
00051     needInit=true;
00052     if(!relative)
00053     {
00054         if(height<0 || width<0)
00055         {
00056             fprintf(stderr,"SDL_Window::Resize(short,short,uchar), 1:height(=%d) ou width(=%d) sont nuls\n",height,width);
00057             return true;
00058         }
00059         coord.h=height;
00060         coord.w=width;
00061     }
00062     else
00063     {
00064         coord.h+=height;
00065         coord.w+=width;
00066     }
00067     return false;
00068 }
00069 
00070 //Redimensionne la fenêtre avec un pourcentage.
00071 //si target vaut 0: le pourcentage s'applique à la mère
00072 //si target vaut 1: le pourcentage s'applique à elle-même
00073 //true si échec
00074 bool SDL_Window::Resize(float width, float height, bool target)
00075 {
00076 
00077     if(!target)
00078     {
00079         if(!mere)
00080         {
00081             fprintf(stderr,"SDL_Window::Resize(float,float,uchar), 1:mere est nul\n");
00082             return true;
00083         }
00084         return Resize(mere->window->w*width,mere->window->h*height,0);
00085     }
00086     return Resize(window->w*width,window->h*height,1);
00087 }
00088 
00089 //Déplace la fenêtre.
00090 //Si relative vaut 1 et que la fenêtre est une fille, les valeurs sont relatives à la fenêtre mère.
00091 //Si relative vaut 2, les valeurs sont relatives à elle-même.
00092 //true si échec
00093 bool SDL_Window::Move(short x, short y, unsigned char relative)
00094 {
00095     if(relative==1)//relatif à la mère
00096     {
00097         if(!mere)
00098         {
00099             fprintf(stderr,"SDL_Window::Move(short,short,uchar), 1:mere est nul\n");
00100             return true;
00101         }
00102         coord.x=x;
00103         coord.y=y;
00104     }
00105     else if(relative==2)//relatif à elle même
00106     {
00107         coord.x+=x;
00108         coord.y+=y;
00109     }
00110     else//absolu
00111     {
00112         //soustraire tour à tour les coordonées de chaque mère pour avoir les coordonnées relatives finales.
00113         SDL_Window *ptrMere=mere;
00114         if(ptrMere)
00115         {
00116             coord.x=0;
00117             coord.y=0;
00118             while(ptrMere)
00119             {
00120                 coord.x+=ptrMere->coord.x;
00121                 coord.y+=ptrMere->coord.y;
00122                 ptrMere=ptrMere->mere;
00123             }//c contient les coordonnées du point 0,0 de la fenetre
00124             coord.x-=x;
00125             coord.y-=y;
00126         }
00127         else
00128         {
00129             coord.x=x;
00130             coord.y=y;
00131         }
00132     }
00133     return false;
00134 }
00135 
00136 //Déplace la fenêtre dans la fenêtre mère. Positions en % de la mère.
00137 //true si échec.
00138 bool SDL_Window::Move(float x, float y)
00139 {
00140 
00141     if(!mere)
00142     {
00143         fprintf(stderr,"SDL_Window::Move(float,float), 1:mere est nul\n");
00144         return true;
00145     }
00146     return Move((short)(mere->coord.w*x),(short)(mere->coord.h*y),1);
00147 }
00148 
00149 //Retourne true si un problème à eu lieu.
00150 bool SDL_Window::ClearWindow()
00151 {
00152 
00153     if(drawed)
00154     {
00155         // calcul des coordonées absolues de la fenêtre
00156         SDL_Rect coordAbs=oldCoord;
00157         SDL_Window *ptrMere=this;
00158         while(ptrMere->mere)
00159         {
00160             ptrMere=ptrMere->mere;
00161             coordAbs.x+=ptrMere->oldCoord.x;
00162             coordAbs.y+=ptrMere->oldCoord.y;
00163         }
00164 
00165         for_each(filles.rbegin(),filles.rend(),mem_fun(&SDL_Window::ClearWindow));
00166         if(SDL_BlitSurface(shadow,NULL,screen,&coordAbs))
00167         {
00168             fprintf(stderr,"SDL_Window::ClearWindow(), 1:Echec de BlitSurface:%s\n",SDL_GetError());
00169             return true;
00170         }
00171         drawed=false;
00172     }
00173     return false;
00174 }
00175 
00176 //retourne true si problème
00177 bool SDL_Window::PrepareWindow()
00178 {
00179 
00180     //NOTE regarder du côté de SDL_gfx pour gérer les zoom et agrandissements
00181     //NOTE pour éviter les problèmes: avoir des textures pour les traits de 1px de longueur OU calculer la dimension de la fenêtre précisément. Sinon, risque d'avoir un empiètement sur les coins.
00182     if(!needInit)
00183         return false;
00184     if(!border || !body)
00185     {
00186         fprintf(stderr,"SDL_Window::PrepareWindow(), 1: border(=%x) ou body(=%x) n'ont pas été initialisé\n",(unsigned int)border,(unsigned int)body);
00187         return true; //si border n'à pas été initialisée, retourner une erreur
00188     }
00189     SDL_Rect destRect= {0,0,0,0};
00190     Uint32 flags=(screen->flags)&(SDL_SWSURFACE|SDL_HWSURFACE|SDL_SRCCOLORKEY|SDL_SRCALPHA);
00191     int bpp=screen->format->BitsPerPixel;
00192 
00193     SDL_FreeSurface(shadow);
00194     SDL_FreeSurface(window);
00195     shadow=SDL_CreateRGBSurface(flags,coord.w, coord.h, bpp, 0, 0, 0, 0);
00196     if(!shadow)
00197     {
00198         fprintf(stderr,"SDL_Window::PrepareWindow(), 2: shadow non initialisé: %s\n",SDL_GetError());
00199         return true;
00200     }
00201 
00202     window=SDL_CreateRGBSurface(flags,coord.w, coord.h, bpp, Rmask, Gmask, Bmask, Amask);
00203     if(!window)
00204     {
00205         fprintf(stderr,"SDL_Window::PrepareWindow(), 3: window non initialisé: %s\n",SDL_GetError());
00206         return true;
00207     }
00208 
00209     destRect.x=border->width[HAUTDROITE];
00210     destRect.y=border->height[HAUTGAUCHE];
00211     if(SDL_BlitSurface(body,NULL,window, &destRect))
00212     {
00213         fprintf(stderr,"SDL_Window::PrepareWindow(), 4: Echec de BlitSurface: %s\n",SDL_GetError());
00214         return true;
00215     }
00216 
00217     destRect.x=0;
00218     destRect.y=0;
00219     destRect.w=coord.w;
00220     destRect.h=coord.h;
00221     border->Draw(window,&destRect);
00222 
00223     needInit=false;
00224     return false;
00225 }
00226 
00227 SDL_Window::SDL_Window(void)
00228     :Rmask(0)
00229     ,Gmask(0)
00230     ,Bmask(0)
00231     ,Amask(0)
00232     ,filles()
00233     ,coord()
00234     ,mere(0)
00235     ,shadow(0)
00236     ,window(0)
00237     ,body(0)
00238     ,border(0)
00239     ,gesEvent()
00240     ,screen(0)
00241     ,oldCoord()
00242     ,drawed(false)
00243     ,needInit(true)
00244 {
00245     if(SDL_InitSubSystem(SDL_INIT_VIDEO))
00246         fprintf(stderr,"SDL_Window::SDL_Window(void), 1:Impossible d'initialiser le sous-système vidéo:%s\n",SDL_GetError()); //TODO (#9) Il faudrait aussi utiliser une exception pour empêcher la création d'une fenêtre si le sous-système vidéo à foiré
00247     if(!(screen=SDL_GetVideoSurface()))
00248         fprintf(stderr,"SDL_Window::SDL_Window(void), 2:Echec de SDL_GetVideoSurface(): %s\n",SDL_GetError());
00249     coord.h=0;
00250     coord.w=0;
00251     coord.x=0;
00252     coord.y=0;
00253 }
00254 
00255 SDL_Window::SDL_Window(SDL_Window *Mere)
00256     :Rmask(0)
00257     ,Gmask(0)
00258     ,Bmask(0)
00259     ,Amask(0)
00260     ,filles()
00261     ,coord()
00262     ,mere(Mere)
00263     ,shadow(0)
00264     ,window(0)
00265     ,body(0)
00266     ,border(0)
00267     ,gesEvent()
00268     ,screen(mere->screen)
00269     ,oldCoord()
00270     ,drawed(false)
00271     ,needInit(true)
00272 {
00273 }
00274 
00275 void SDL_Window::SetMasks(unsigned long rmask, unsigned long gmask, unsigned long bmask, unsigned long amask)
00276 {
00277     needInit=true;
00278     Rmask=rmask;
00279     Gmask=gmask;
00280     Bmask=bmask;
00281     Amask=amask;
00282 }
00283 
00284 list<SDL_Window*>::iterator SDL_Window::CreateSubWindow(void)
00285 {
00286     filles.push_front(new SDL_Window(this));
00287     return filles.begin();
00288 }
00289 
00290 //si tout est ok, renvoie false.
00291 bool SDL_Window::InitTextures(BorderTexture *bordTex,char* filebody)
00292 {
00293     needInit=true;
00294     border=bordTex;
00295     SDL_FreeSurface(body);
00296     if(!filebody)
00297     {
00298         fprintf(stderr,"SDL_Window::InitTextures(BorderTexture *,char*), 1:filebody vaut NULL\n");
00299         return false;
00300     }
00301     if(!border)
00302     {
00303         fprintf(stderr,"SDL_Window::InitTextures(BorderTexture *,char*), 2:bordTex vaut NULL\n");
00304         return false;
00305     }
00306     if(!(body=SDL_LoadBMP(filebody)))
00307     {
00308         fprintf(stderr,"SDL_Window::InitTextures(BorderTexture *,char*), 3:Echec de SDL_LoadBMP: %s\n",SDL_GetError());
00309         return true;
00310     }
00311 
00312     if(border->isInit())
00313         return false;
00314     return true;
00315 }
00316 
00317 bool SDL_Window::SetAlpha(unsigned char alpha,bool srcAlpha,bool rleAccel)
00318 {
00319     Amask=alpha;
00320     if(SDL_SetAlpha(window,(srcAlpha*SDL_SRCALPHA)|(rleAccel*SDL_RLEACCEL),alpha))
00321     {
00322         fprintf(stderr,"SDL_Window::SetAlpha(uchar, bool, bool), 1:Echec de SDL_SetAlpha: %s\n",SDL_GetError());
00323         return true;
00324     }
00325     return false;
00326 }
00327 
00328 void SDL_Window::calcCoord(SDL_Rect *c)
00329 {
00330     // calcul des coordonées absolues de la fenêtre
00331     SDL_Window *ptrMere=this;
00332     while(ptrMere->mere)
00333     {
00334         ptrMere=ptrMere->mere;
00335         c->x+=ptrMere->coord.x;
00336         c->y+=ptrMere->coord.y;
00337     }
00338 }
00339 
00340 SDL_Window::~SDL_Window()
00341 {
00342     if(mere)
00343         mere->filles.remove(this);
00344 
00345     while (!filles.empty())
00346         delete filles.front();
00347     SDL_FreeSurface(shadow);
00348     SDL_FreeSurface(window);
00349     SDL_FreeSurface(body);
00350 }
00351 
00352 SDL_Window::SDL_Window(SDL_Window &source, SDL_Window *Mere)
00353     :Rmask(source.Rmask)
00354     ,Gmask(source.Gmask)
00355     ,Bmask(source.Bmask)
00356     ,Amask(source.Amask)
00357     ,filles()
00358     ,coord(source.coord)
00359     ,mere(source.mere)
00360     ,shadow(0)
00361     ,window(0)
00362     ,body(source.body)
00363     ,border(source.border)
00364     ,gesEvent()
00365     ,screen(source.screen)
00366     ,oldCoord()
00367     ,drawed(false)
00368     ,needInit(true) // window et shadow DOIVENT être réinitialisées (ou alors, il faut que je les duplique, ce qui pourrait économiser de la ressource de calcul)
00369 {
00370     list<SDL_Window*>::iterator it;
00371     coord.h=source.coord.h;
00372     coord.w=source.coord.w;
00373     coord.x=source.coord.x;
00374     coord.y=source.coord.y;
00375 
00376     if(Mere)
00377         mere=Mere;
00378 
00379     if(mere)
00380         (mere->filles).push_back(this);
00381 
00382     if(body)
00383         body->refcount++;
00384     for(it=source.filles.begin();it!=source.filles.end();it++)
00385         filles.push_back(new SDL_Window(**it,this));
00386 }
00387 
00388 SDL_Window &SDL_Window::operator=(SDL_Window &source)
00389 {
00390     Rmask=source.Rmask;
00391     Gmask=source.Gmask;
00392     Bmask=source.Bmask;
00393     Amask=source.Amask;
00394     coord.h=source.coord.h;
00395     coord.w=source.coord.w;
00396     coord.x=source.coord.x;
00397     coord.y=source.coord.y;
00398     mere=source.mere;
00399     shadow=0;
00400     window=0;
00401     body=source.body;
00402     border=source.border;
00403     screen=source.screen;
00404     drawed=false;
00405     needInit=true; // window et shadow DOIVENT être réinitialisées (ou alors, il faut que je les duplique, ce qui pourrait économiser de la ressource de calcul)
00406 
00407     list<SDL_Window*>::iterator it;
00408 
00409     if(mere)
00410         (mere->filles).push_back(this);
00411 
00412     if(body)
00413         body->refcount++;
00414 
00415     //trouver le moyen de remplacer par un for_each également
00416     for(it=source.filles.begin();it!=source.filles.end();it++)
00417         filles.push_back(new SDL_Window(**it,this));
00418     return *this;
00419     // TODO (Bérenger#9#): Méthode à tester. Devrait fonctionner, vu le peu de différences avec le constructeur de copie, mais prudence est mère de sûreté.
00420 }
00421 // TODO : vérifier que dans le cas ou 2 fenetres non affiliées dont l'ordre d'affichage ne suit aucun ordre prédéfini ne causent pas d'altération des graphismes lorsqu'elles se chevauchent
00422 
00423 /* TODO ajouter la gestion des évènements:
00424 
00425 algo:
00426 créer un stack<SDL_Event> pile
00427 while(!pollEvent(&event))
00428 {
00429     envoyer l'event aux filles
00430     comparer l'event aux event traités par l'objet
00431     si il doit être traité
00432         traiter
00433     sinon
00434         ajouter à pile
00435 }
00436 remettre la pile dans le stack en utilisant un iterateur inversé
00437 
00438 Questions:
00439 _ pomper tous les event dans la mère ou traiter ça dans la boucle principale du programme?
00440 _ la gestion de timer pourrait-elle être intéressante?
00441     _si oui, s'inspirer de la classe d'empilage d'event de référence:
00442 
00443 */

Généré le Sun Nov 15 16:53:06 2009 pour PFen par  doxygen 1.6.1