#include "Screen.h" using namespace std; // empty constructor graphic::Screen::Screen(Uint16 w, Uint16 h, Uint32 flags) { // saving flags value adding the OpenGL SDL flag (in case it misses) _flags = flags; // setting screen dimensions _width = w; _height = h; _num_screens = 0; InitScreen(); } // init the graphic contest void graphic::Screen::InitScreen() { #ifdef WITH_OPENGL // GL if(_flags & SDL_OPENGL) { // setting OpenGL attributes SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); // setting screen mode, get a screen from SDL _surface = SDL_SetVideoMode(_width, _height, 0, _flags); // setting projection matrix glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, _width, _height, 0, -1, 1); glMatrixMode(GL_MODELVIEW); glViewport(0, 0, _width, _height); // setting clear color glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // enabling texturing as everything is textured glEnable(GL_TEXTURE_2D); // enabling blending for transparency effects glEnable(GL_BLEND); // disabling depth test glDisable(GL_DEPTH); // setting blending function glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } // SDL else #endif _surface = SDL_SetVideoMode(_width, _height, 0, _flags); // an error occurred ==> throw an Exception if(_surface == NULL) throw Exception("Screen", SDL_GetError()); } // set screen flags void graphic::Screen::SetFlags(Uint32 flags) { _flags = flags; InitScreen(); } // set screen resolution void graphic::Screen::SetResolution(Uint16 w, Uint16 h) { // change resolution just if it really changes if(w != _width || h != _height) { _width = w; _height = h; InitScreen(); } } // go in fullscreen mode void graphic::Screen::GoFullScreen() { // set fullscreen just if the screen is in window mode if(!(_flags & SDL_FULLSCREEN)) { _flags |= SDL_FULLSCREEN; InitScreen(); } } // go in windowed mode void graphic::Screen::GoWindowed() { // set window mode just if the screen is fullscreen if(_flags & SDL_FULLSCREEN) { _flags &= ~SDL_FULLSCREEN; InitScreen(); } } // update the entire screen void graphic::Screen::Update() { #ifdef WITH_OPENGL if(_flags & SDL_OPENGL) SDL_GL_SwapBuffers(); else #endif SDL_Flip(_surface); } // update part of the screen void graphic::Screen::UpdateRect(SDL_Rect & rect) { if(!(_flags & SDL_OPENGL)) { if(rect.x < 0) rect.x = 0; if(rect.y < 0) rect.y = 0; if(rect.x + rect.w > _width) rect.x = _width - rect.w; if(rect.y + rect.h > _height) rect.y = _height - rect.h; SDL_UpdateRect(_surface, rect.x, rect.y, rect.w, rect.h); } #ifdef WITH_OPENGL else SDL_GL_SwapBuffers(); #endif } // fill the surface with a color void graphic::Screen::Fill(SDL_Color & color) { #ifdef WITH_OPENGL // GL if(_flags & SDL_OPENGL) { glPushAttrib( GL_COLOR_BUFFER_BIT ); glClearColor(color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); glPopAttrib(); } // SDL else #endif SDL_FillRect(_surface, NULL, SDL_MapRGB(_surface->format, color.r, color.g, color.b)); } // clear the screen void graphic::Screen::Clear() { #ifdef WITH_OPENGL if(_flags & SDL_OPENGL) glClear(GL_COLOR_BUFFER_BIT); else #endif SDL_FillRect(_surface, NULL, SDL_MapRGB(_surface->format, 0, 0, 0)); } #ifdef WITH_OPENGL // chage the graphic contest void graphic::Screen::ChangeGraphicMode(bool graphic) { // set GL mode if(graphic == GL_GRAPHIC) { std::cout << "GL graphic mode" << std::endl; _flags |= SDL_OPENGL; } // set GL mode else if (graphic == SDL_GRAPHIC) { std::cout << "SDL graphic mode" << std::endl; _flags &= ~SDL_OPENGL; } InitScreen(); } #endif // take a screenshot and save the PNG file in screens_dir void graphic::Screen::TakeScreenshot() { SDL_Surface * output_surf; Uint32 rmask, gmask, bmask, amask; #if SDL_BYTEORDER == SDL_BIG_ENDIAN rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff; #else rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; #endif #ifdef WITH_OPENGL if(_flags & SDL_OPENGL) { int row, stride; GLubyte * swapline; GLubyte * pixels; stride = _width * 4; // length of a line in bytes pixels = (GLubyte *) malloc(stride * _height); swapline = (GLubyte *) malloc(stride); glReadPixels(0, 0, _width, _height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); // vertical flip for(row = 0; row < _height/2; row++) { memcpy(swapline, pixels + row * stride, stride); memcpy(pixels + row * stride, pixels + (_height - row - 1) * stride, stride); memcpy(pixels + (_height - row -1) * stride, swapline, stride); } output_surf = SDL_CreateRGBSurfaceFrom(pixels, _width, _height, 32, _surface->pitch, rmask, gmask, bmask, amask); } else { #endif output_surf = SDL_CreateRGBSurface(_surface->flags, _width, _height, _surface->format->BitsPerPixel, rmask, gmask, bmask, _surface->format->BitsPerPixel<=24? 0: amask); SDL_BlitSurface(_surface, NULL, output_surf, NULL); #ifdef WITH_OPENGL } #endif std::ostringstream file; file << screens_dir << "/screen_" << _num_screens << ".png"; PngSaveSurface(file.str().c_str(), output_surf); cout << "Saved " << file.str() << endl; _num_screens++; }