home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2009 February / maximum-cd-2009-02.iso / DiscContents / SMC_1.6_win32.exe / src / video / video.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2008-09-26  |  57.6 KB  |  2,316 lines

  1. /***************************************************************************
  2.  * video.cpp  -  General video functions
  3.  *
  4.  * Copyright (C) 2005 - 2008 Florian Richter
  5.  ***************************************************************************/
  6. /*
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 3 of the License, or
  10.    (at your option) any later version.
  11.    
  12.    You should have received a copy of the GNU General Public License
  13.    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  14. */
  15.  
  16. #include "../video/video.h"
  17. #include "../gui/hud.h"
  18. #include "../user/preferences.h"
  19. #include "../core/framerate.h"
  20. #include "../video/font.h"
  21. #include "../core/game_core.h"
  22. #include "../video/img_settings.h"
  23. #include "../core/camera.h"
  24. #include "../input/mouse.h"
  25. #include "../video/gl_surface.h"
  26. #include "../video/renderer.h"
  27. #include "../core/main.h"
  28. #include "../core/math/utilities.h"
  29. #include "../core/i18n.h"
  30. #include "../core/math/size.h"
  31. // CEGUI
  32. #include "CEGUIDefaultResourceProvider.h"
  33. #include "CEGUIDefaultLogger.h"
  34. // boost filesystem
  35. #include "boost/filesystem/convenience.hpp"
  36. namespace fs = boost::filesystem;
  37. // png
  38. #include <png.h>
  39. #ifndef PNG_COLOR_TYPE_RGBA
  40.     #define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA
  41. #endif
  42.  
  43. /* *** *** *** *** *** *** *** *** Color struct *** *** *** *** *** *** *** *** *** */
  44.  
  45. Color :: Color( void )
  46. {
  47.     red = 0;
  48.     green = 0;
  49.     blue = 0;
  50.     alpha = 255;
  51. };
  52.  
  53. Color :: Color( Uint8 r, Uint8 g, Uint8 b, Uint8 a /* = 255 */ )
  54. {
  55.     red = r;
  56.     green = g;
  57.     blue = b;
  58.     alpha = a;
  59. };
  60.  
  61. Color :: Color( float r, float g, float b, float a /* = 1 */ )
  62. {
  63.     red = static_cast<Uint8>(r * 255);
  64.     green = static_cast<Uint8>(g * 255);
  65.     blue = static_cast<Uint8>(b * 255);
  66.     alpha = static_cast<Uint8>(a * 255);
  67. }
  68.  
  69. Color :: Color( Uint8 grey )
  70. {
  71.     red = grey;
  72.     green = grey;
  73.     blue = grey;
  74.     alpha = 255;
  75. };
  76.  
  77. Color :: Color( Uint32 color )
  78. {
  79.     //SDL_GetRGBA( mapcolor, format, &red, &green, &blue, &alpha );
  80. };
  81.  
  82. Color :: Color( SDL_Color color )
  83. {
  84.     red = color.r;
  85.     green = color.g;
  86.     blue = color.b;
  87.     alpha = 255;
  88. }
  89.  
  90. SDL_Color Color :: Get_SDL_Color( void )
  91. {
  92.     SDL_Color color;
  93.     color.r = red;
  94.     color.g = green;
  95.     color.b = blue;
  96.     return color;
  97. }
  98.  
  99. CEGUI::colour Color :: Get_cegui_Color( void )
  100. {
  101.     return CEGUI::colour( static_cast<float>(red) / 255, static_cast<float>(green) / 255, static_cast<float>(blue) / 255, static_cast<float>(alpha) / 255 );
  102. }
  103.  
  104. bool Color :: Compare( const Color color )
  105. {
  106.     return red == color.red && green == color.green && blue == color.blue && alpha == color.alpha;
  107. }
  108.  
  109. bool Color :: operator == ( const Color color ) const
  110. {
  111.     return red == color.red && green == color.green && blue == color.blue && alpha == color.alpha;
  112. }
  113.  
  114. bool Color :: operator == ( const SDL_Color color ) const
  115. {
  116.     return red == color.r && green == color.g && blue == color.b;
  117. }
  118.  
  119. /* *** *** *** *** *** *** *** CEGUI renderer fake class *** *** *** *** *** *** *** *** *** *** */
  120.  
  121. cFake_Renderer :: cFake_Renderer( void )
  122. {
  123.     d_identifierString = "Fake Renderer";
  124. }
  125.  
  126. cFake_Renderer :: ~cFake_Renderer( void )
  127. {
  128.  
  129. }
  130.  
  131. /* *** *** *** *** *** *** *** Video class *** *** *** *** *** *** *** *** *** *** */
  132.  
  133. cVideo :: cVideo( void )
  134. {
  135.     opengl_version = 0;
  136.  
  137.     double_buffer = 0;
  138.     hardware_surfaces = 0;
  139.  
  140.     rgb_size[0] = 0;
  141.     rgb_size[1] = 0;
  142.     rgb_size[2] = 0;
  143.  
  144.     default_buffer = GL_BACK;
  145.     
  146.     audio_init_failed = 0;
  147.     joy_init_failed = 0;
  148.     // default geometry detail is medium
  149.     geometry_detail = 0.5f;
  150.     // default texture detail is high
  151.     texture_detail = 0.75f;
  152.  
  153.     initialised = 0;
  154. }
  155.  
  156. cVideo :: ~cVideo( void )
  157. {
  158.  
  159. }
  160.  
  161. void cVideo :: Init_CEGUI_Fake( void )
  162. {
  163.     // create fake Resource Provider
  164.     CEGUI::DefaultResourceProvider *rp = new CEGUI::DefaultResourceProvider();
  165.     // set Resource Provider directories
  166.     if( CEGUI::System::getDefaultXMLParserName().compare( "XercesParser" ) == 0 )
  167.     {
  168.         // This is needed for Xerces to specify the schemas location
  169.         rp->setResourceGroupDirectory( "schemas", DATA_DIR "/" GAME_SCHEMA_DIR "/" );
  170.     }
  171.     // get a directory to dump the CEGUI log
  172.     string log_dump_dir;
  173. #ifdef _WIN32
  174.     log_dump_dir = Get_Temp_Directory() + "cegui.log";
  175. #else
  176.     log_dump_dir = "/dev/null";
  177. #endif
  178.     // create fake system and renderer
  179.     pGuiSystem = new CEGUI::System( new cFake_Renderer(), rp, NULL, NULL, "", log_dump_dir );
  180. }
  181.  
  182. void cVideo :: Delete_CEGUI_Fake( void )
  183. {
  184.     CEGUI::ResourceProvider *rp = pGuiSystem->getResourceProvider();
  185.     CEGUI::Renderer *renderer = pGuiSystem->getRenderer();
  186.  
  187.     delete pGuiSystem;
  188.     pGuiSystem = NULL;
  189.     delete renderer;
  190.     delete rp;
  191. }
  192.  
  193. void cVideo :: Init_CEGUI( void )
  194. {
  195.     // create renderer
  196.     try
  197.     {
  198.         pGuiRenderer = new CEGUI::OpenGLRenderer( 0, screen->w, screen->h );
  199.     }
  200.     // catch CEGUI Exceptions
  201.     catch( CEGUI::Exception &ex )
  202.     {
  203.         printf( "CEGUI Exception occurred : %s\n", ex.getMessage().c_str() );
  204.         exit( EXIT_FAILURE );
  205.     }
  206.  
  207.     /* create Resource Provider
  208.      * no need to destroy it later since it is handled by the CEGUI renderer
  209.     */
  210.     CEGUI::DefaultResourceProvider *rp = static_cast<CEGUI::DefaultResourceProvider *>(pGuiRenderer->createResourceProvider());
  211.  
  212.     // set Resource Provider directories
  213.     rp->setResourceGroupDirectory( "schemes", DATA_DIR "/" GUI_SCHEME_DIR "/" );
  214.     rp->setResourceGroupDirectory( "imagesets", DATA_DIR "/" GUI_IMAGESET_DIR "/" );
  215.     rp->setResourceGroupDirectory( "fonts", DATA_DIR "/" GUI_FONT_DIR "/" );
  216.     rp->setResourceGroupDirectory( "looknfeels", DATA_DIR "/" GUI_LOOKNFEEL_DIR "/" );
  217.     rp->setResourceGroupDirectory( "layouts", DATA_DIR "/" GUI_LAYOUT_DIR "/" );
  218.     if( CEGUI::System::getDefaultXMLParserName().compare( "XercesParser" ) == 0 )
  219.     {
  220.         // Needed for Xerces to specify the schemas location
  221.         rp->setResourceGroupDirectory( "schemas", DATA_DIR "/" GAME_SCHEMA_DIR "/" );
  222.     }
  223.  
  224.     // create logger
  225.     CEGUI::Logger *logger = new CEGUI::DefaultLogger();
  226.     // set logging level
  227. #ifdef _DEBUG
  228.     logger->setLoggingLevel( CEGUI::Informative );
  229. #else
  230.     logger->setLoggingLevel( CEGUI::Errors );
  231. #endif
  232.  
  233.     // create system
  234.     try
  235.     {
  236.         pGuiSystem = new CEGUI::System( pGuiRenderer, rp, NULL, NULL, "", user_data_dir + "cegui.log" );
  237.     }
  238.     // catch CEGUI Exceptions
  239.     catch( CEGUI::Exception &ex )
  240.     {
  241.         printf( "CEGUI Exception occurred : %s\n", ex.getMessage().c_str() );
  242.         exit( EXIT_FAILURE );
  243.     }
  244. }
  245.  
  246. void cVideo :: Init_CEGUI_Data( void )
  247. {
  248.     // set the default resource groups to be used
  249.     CEGUI::Scheme::setDefaultResourceGroup( "schemes" );
  250.     CEGUI::Imageset::setDefaultResourceGroup( "imagesets" );
  251.     CEGUI::Font::setDefaultResourceGroup( "fonts" );
  252.     CEGUI::WidgetLookManager::setDefaultResourceGroup( "looknfeels" );
  253.     CEGUI::WindowManager::setDefaultResourceGroup( "layouts" );
  254.     // only needed for Xerces
  255.     if( CEGUI::System::getDefaultXMLParserName().compare( "XercesParser" ) == 0 )
  256.     {
  257.         //XercesParser::setSchemaDefaultResourceGroup( "schemas" );
  258.     }
  259.  
  260.     // load the scheme file, which auto-loads the imageset
  261.     try
  262.     {
  263.         CEGUI::SchemeManager::getSingleton().loadScheme( "TaharezLook.scheme" );
  264.     }
  265.     // catch CEGUI Exceptions
  266.     catch( CEGUI::Exception &ex )
  267.     {
  268.         printf( "CEGUI Scheme Exception occurred : %s\n", ex.getMessage().c_str() );
  269.         exit( EXIT_FAILURE );
  270.     }
  271.  
  272.     // first font loaded automatically becomes the default font
  273.     try
  274.     {
  275.         CEGUI::FontManager::getSingleton().createFont( "bluebold1024_medium.font" );
  276.     }
  277.     // catch CEGUI Exceptions
  278.     catch( CEGUI::Exception &ex )
  279.     {
  280.         printf( "CEGUI Font Exception occurred : %s\n", ex.getMessage().c_str() );
  281.         exit( EXIT_FAILURE );
  282.     }
  283.  
  284.     // default mouse cursor
  285.     pGuiSystem->setDefaultMouseCursor( "TaharezLook", "MouseArrow" );
  286.     // force new mouse image
  287.     CEGUI::MouseCursor::getSingleton().setImage( &CEGUI::ImagesetManager::getSingleton().getImageset( "TaharezLook" )->getImage( "MouseArrow" ) );
  288.     // hide CEGUI mouse always because we render it manually
  289.     CEGUI::MouseCursor::getSingleton().hide();
  290.     // default tooltip
  291.     pGuiSystem->setDefaultTooltip( "TaharezLook/Tooltip" );
  292.     // create default root window
  293.     CEGUI::Window *window_root = CEGUI::WindowManager::getSingleton().loadWindowLayout( "default.layout" );
  294.     pGuiSystem->setGUISheet( window_root );
  295.     window_root->activate();
  296. }
  297.  
  298. void cVideo :: Init_SDL( void )
  299. {
  300.     if( SDL_Init( SDL_INIT_VIDEO ) == -1 )
  301.     {
  302.         printf( "Error : SDL initialization failed\nReason : %s\n", SDL_GetError() );
  303.         exit( EXIT_FAILURE );
  304.     }
  305.  
  306.     atexit( SDL_Quit );
  307.  
  308.     if( SDL_InitSubSystem( SDL_INIT_JOYSTICK ) == -1 )
  309.     {
  310.         printf( "Warning : SDL Joystick initialization failed\nReason : %s\n", SDL_GetError() );
  311.         joy_init_failed = 1;
  312.     }
  313.     else
  314.     {
  315.         joy_init_failed = 0;
  316.     }
  317.  
  318.     if( SDL_InitSubSystem( SDL_INIT_AUDIO ) == -1 )
  319.     {
  320.         printf( "Warning : SDL Audio initialization failed\nReason : %s\n", SDL_GetError() );
  321.         audio_init_failed = 1;
  322.     }
  323.     else
  324.     {
  325.         audio_init_failed = 0;
  326.     }
  327.  
  328.     SDL_EnableUNICODE( 1 );
  329.     // hide by default
  330.     SDL_ShowCursor( SDL_DISABLE );
  331. }
  332.  
  333. void cVideo :: Init_Video( bool reload_textures_from_file /* = 0 */, bool use_preferences /* = 1 */ )
  334. {
  335.     // set the video flags
  336.     int flags = SDL_OPENGL | SDL_SWSURFACE;
  337.  
  338.     // only enter fullscreen if set in preferences
  339.     if( use_preferences && pPreferences->video_fullscreen )
  340.     {
  341.         flags |= SDL_FULLSCREEN;
  342.     }
  343.  
  344.     int screen_w, screen_h, screen_bpp;
  345.  
  346.     // full initialization
  347.     if( use_preferences )
  348.     {
  349.         screen_w = pPreferences->video_screen_w;
  350.         screen_h = pPreferences->video_screen_h;
  351.         screen_bpp = pPreferences->video_screen_bpp;
  352.     }
  353.     // initialization with SDL defaults
  354.     else
  355.     {
  356.         screen_w = 800;
  357.         screen_h = 600;
  358.         screen_bpp = 16;
  359.     }
  360.  
  361.     // first initialization
  362.     if( !initialised )
  363.     {
  364.         // Set Caption
  365.         SDL_WM_SetCaption( CAPTION, NULL );
  366.         // Set Icon
  367.         string filename_icon = DATA_DIR "/" GAME_ICON_DIR "/window_32.png";
  368.         if( File_Exists( filename_icon ) )
  369.         {
  370.             SDL_Surface *icon = IMG_Load( filename_icon.c_str() );
  371.             SDL_WM_SetIcon( icon, NULL );
  372.             SDL_FreeSurface( icon );
  373.         }
  374.         else
  375.         {
  376.             printf( "Warning : Window icon %s does not exist\n", filename_icon.c_str() );
  377.         }
  378.     }
  379.  
  380.     // test screen mode
  381.     int screen_test = Test_Video( screen_w, screen_h, screen_bpp, flags );
  382.  
  383.     // failed
  384.     if( screen_test == 0 )
  385.     {
  386.         printf( "Warning : Video Resolution %dx%d is not supported\n", screen_w, screen_h );
  387.  
  388.         // set lowest available settings
  389.         screen_w = 640;
  390.         screen_h = 480;
  391.         screen_bpp = 0;
  392.  
  393.         // overwrite user settings
  394.         if( use_preferences )
  395.         {
  396.             pPreferences->video_screen_w = screen_w;
  397.             pPreferences->video_screen_h = screen_h;
  398.         }
  399.     }
  400.     // can not handle bits per pixel
  401.     else if( screen_test > 1 && screen_bpp > 0 && screen_test < screen_bpp )
  402.     {
  403.         printf( "Warning : Video Bpp %d is not supported but %d is\n", screen_bpp, screen_test );
  404.         // set closest supported bpp
  405.         screen_bpp = screen_test;
  406.  
  407.         // overwrite user settings
  408.         if( use_preferences )
  409.         {
  410.             pPreferences->video_screen_bpp = screen_bpp;
  411.         }
  412.     }
  413.  
  414.     int screen_rgb_size[3];
  415.  
  416.     // set bit per pixel sizes
  417.     if( screen_bpp == 8 )
  418.     {
  419.         screen_rgb_size[0] = 3;
  420.         screen_rgb_size[1] = 3;
  421.         screen_rgb_size[2] = 2;
  422.     }
  423.     else if( screen_bpp == 15 )
  424.     {
  425.         screen_rgb_size[0] = 5;
  426.         screen_rgb_size[1] = 5;
  427.         screen_rgb_size[2] = 5;
  428.     }
  429.     else if( screen_bpp == 24 )
  430.     {
  431.         screen_rgb_size[0] = 8;
  432.         screen_rgb_size[1] = 8;
  433.         screen_rgb_size[2] = 8;
  434.     }
  435.     // same as 24...
  436.     else if( screen_bpp == 32 )
  437.     {
  438.         screen_rgb_size[0] = 8;
  439.         screen_rgb_size[1] = 8;
  440.         screen_rgb_size[2] = 8;
  441.     }
  442.     else // 16 and default
  443.     {
  444.         screen_rgb_size[0] = 5;
  445.         screen_rgb_size[1] = 6;
  446.         screen_rgb_size[2] = 5;
  447.     }
  448.  
  449.     // request settings
  450.     SDL_GL_SetAttribute( SDL_GL_RED_SIZE, screen_rgb_size[0] );
  451.     SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, screen_rgb_size[1] );
  452.     SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, screen_rgb_size[2] );
  453.     // hangs on 16 bit
  454.     //SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 ); 
  455.     // not yet needed
  456.     //SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
  457.     SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
  458.     // if vertical synchronization is enabled
  459.     if( use_preferences && pPreferences->video_vsync )
  460.     {
  461.         SDL_GL_SetAttribute( SDL_GL_SWAP_CONTROL, 1 );
  462.     }
  463.  
  464.     // if reinitialization
  465.     if( initialised )
  466.     {
  467.         // check if CEGUI is initialized
  468.         bool cegui_initialized = pGuiSystem->getGUISheet() != NULL;
  469.  
  470.         // show loading screen
  471.         if( cegui_initialized )
  472.         {
  473.             Loading_Screen_Init();
  474.         }
  475.  
  476.         // save textures
  477.         pImage_Manager->Grab_Textures( reload_textures_from_file, cegui_initialized );
  478.         pFont->Grab_Textures();
  479.         pGuiRenderer->grabTextures();
  480.         pImage_Manager->Delete_Hardware_Textures();
  481.  
  482.         // exit loading screen
  483.         if( cegui_initialized )
  484.         {
  485.             Loading_Screen_Exit();
  486.         }
  487.     }
  488.  
  489.     // SDL handles the screen surface memory management
  490.     screen = SDL_SetVideoMode( screen_w, screen_h, screen_bpp, flags );
  491.  
  492.     if( !screen )
  493.     {
  494.         printf( "Error : Screen mode creation failed\nReason : %s\n", SDL_GetError() );
  495.         exit( EXIT_FAILURE );
  496.     }
  497.  
  498.     // check if fullscreen got set
  499.     if( use_preferences && pPreferences->video_fullscreen )
  500.     {
  501.         int is_fullscreen = ( ( screen->flags & SDL_FULLSCREEN ) == SDL_FULLSCREEN );
  502.  
  503.         if( !is_fullscreen )
  504.         {
  505.             printf( "Warning : Fullscreen mode could not be set\n" );
  506.         }
  507.     }
  508.  
  509.     // check if double buffering got set
  510.     int is_double_buffer;
  511.     SDL_GL_GetAttribute( SDL_GL_DOUBLEBUFFER, &is_double_buffer );
  512.     double_buffer = is_double_buffer > 0;
  513.  
  514.     if( !double_buffer )
  515.     {
  516.         // only important on full initialization
  517.         if( use_preferences )
  518.         {
  519.             printf( "Warning : Double Buffering could not be set\n" );
  520.         }
  521.     }
  522.  
  523.     // check if vertical synchronization got set
  524.     if( use_preferences && pPreferences->video_vsync )
  525.     {
  526.         int is_vsync;
  527.         // seems to return always true even if not available
  528.         SDL_GL_GetAttribute( SDL_GL_SWAP_CONTROL, &is_vsync );
  529.  
  530.         if( !is_vsync )
  531.         {
  532.             printf( "Warning : VSync could not be set\n" );
  533.         }
  534.     }
  535.  
  536.     // get color bit size
  537.     SDL_GL_GetAttribute( SDL_GL_RED_SIZE, &rgb_size[0] );
  538.     SDL_GL_GetAttribute( SDL_GL_GREEN_SIZE, &rgb_size[1] );
  539.     SDL_GL_GetAttribute( SDL_GL_BLUE_SIZE, &rgb_size[2] );
  540.  
  541.     // check if color bit size is set as wanted
  542.     if( use_preferences )
  543.     {
  544.         if( rgb_size[0] < screen_rgb_size[0] )
  545.         {
  546.             printf( "Warning : smaller red bit size %d as requested %d\n", rgb_size[0], screen_rgb_size[0] );
  547.         }
  548.  
  549.         if( rgb_size[1] < screen_rgb_size[1] )
  550.         {
  551.             printf( "Warning : smaller green bit size %d as requested %d\n", rgb_size[1], screen_rgb_size[1] );
  552.         }
  553.  
  554.         if( rgb_size[2] < screen_rgb_size[2] )
  555.         {
  556.             printf( "Warning : smaller blue bit size %d as requested %d\n", rgb_size[2], screen_rgb_size[2] );
  557.         }
  558.     }
  559.  
  560.     // remember default buffer
  561.     glGetIntegerv( GL_DRAW_BUFFER, &default_buffer );
  562.  
  563.     /* check if accelerated visual
  564.     int accelerated = 0;
  565.     SDL_GL_GetAttribute( SDL_GL_ACCELERATED_VISUAL, &accelerated );
  566.     printf( "accel %d\n", accelerated );*/
  567.  
  568.     // initialize opengl
  569.     Init_OpenGL();
  570.  
  571.     // if reinitialization
  572.     if( initialised )
  573.     {
  574.         // reset highest texture id
  575.         pImage_Manager->high_texture_id = 0;
  576.  
  577.         /* restore GUI textures
  578.          * must be the first CEGUI call after the grabTextures function
  579.         */
  580.         pGuiRenderer->restoreTextures();
  581.         pFont->Restore_Textures();
  582.  
  583.         // send new size to CEGUI
  584.         pGuiRenderer->setDisplaySize( CEGUI::Size( static_cast<float>(screen_w), static_cast<float>(screen_h) ) );
  585.  
  586.         // check if CEGUI is initialized
  587.         bool cegui_initialized = pGuiSystem->getGUISheet() != NULL;
  588.  
  589.         // show loading screen
  590.         if( cegui_initialized )
  591.         {
  592.             Loading_Screen_Init();
  593.         }
  594.  
  595.         // initialize new image cache
  596.         if( reload_textures_from_file )
  597.         {
  598.             Init_Image_Cache( 0, cegui_initialized );
  599.         }
  600.  
  601.         // restore textures
  602.         pImage_Manager->Restore_Textures( cegui_initialized );
  603.  
  604.         // exit loading screen
  605.         if( cegui_initialized )
  606.         {
  607.             Loading_Screen_Exit();
  608.         }
  609.     }
  610.     // finished first initialization
  611.     else
  612.     {
  613.         // get opengl version
  614.         opengl_version = static_cast<float>(atof( reinterpret_cast<const char*>(glGetString( GL_VERSION )) ));
  615.  
  616.         if( opengl_version < 1.4f )
  617.         {
  618.             printf( "Warning : OpenGL Version %f below optimal version 1.4 and higher\n", opengl_version );
  619.         }
  620.  
  621.         initialised = 1;
  622.     }
  623. }
  624.  
  625. void cVideo :: Init_OpenGL( void )
  626. {
  627.     // viewport should cover the whole screen
  628.     glViewport( 0, 0, pPreferences->video_screen_w, pPreferences->video_screen_h );
  629.  
  630.     // Camera projection matrix
  631.     glMatrixMode( GL_PROJECTION );
  632.     glLoadIdentity();
  633.     // Set up an Ortho Screen
  634.     glOrtho( 0, static_cast<float>(pPreferences->video_screen_w), static_cast<float>(pPreferences->video_screen_h), 0, -1, 1 );
  635.     
  636.     // matrix operations
  637.     glMatrixMode( GL_MODELVIEW );
  638.     glLoadIdentity();
  639.  
  640.     // Smooth Shading
  641.     glShadeModel( GL_SMOOTH );
  642.  
  643.     // clear color
  644.     glClearColor( 0, 0, 0, 1 );
  645.  
  646.     // Z-Buffer
  647.     glEnable( GL_DEPTH_TEST );
  648.  
  649.     // Depth function
  650.     glDepthFunc( GL_LEQUAL );
  651.     // Depth Buffer Setup
  652.     glClearDepth( 1 );
  653.  
  654.     // Blending
  655.     glEnable( GL_BLEND );
  656.     // Blending function
  657.     glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
  658.  
  659.     // Alpha
  660.     glEnable( GL_ALPHA_TEST );
  661.     // Alpha function
  662.     glAlphaFunc( GL_GREATER, 0.01f );
  663.  
  664.     // Geometry
  665.     Init_Geometry();
  666.     // texture detail
  667.     Init_Texture_Detail();
  668.     // Resolution Scale
  669.     Init_Resolution_Scale();
  670.  
  671.     // Clear Screen
  672.     Clear_Screen();
  673.  
  674.     SDL_GL_SwapBuffers();
  675. }
  676.  
  677. void cVideo :: Init_Geometry( void )
  678. {
  679.     // Geometry Anti-Aliasing
  680.     if( geometry_detail > 0.5f )
  681.     {
  682.         // Point
  683.         glEnable( GL_POINT_SMOOTH );
  684.         glHint( GL_POINT_SMOOTH_HINT, GL_NICEST );
  685.         // Line
  686.         glEnable( GL_LINE_SMOOTH );
  687.         glHint( GL_LINE_SMOOTH_HINT, GL_NICEST );
  688.         // Polygon - does not display correctly with open source ATi drivers ( 18.2.2008 )
  689.         //glEnable( GL_POLYGON_SMOOTH );
  690.         // Geforce 4 440 MX hangs if enabled
  691.         //glHint( GL_POLYGON_SMOOTH_HINT, GL_NICEST );
  692.     }
  693.     else
  694.     {
  695.         // Point
  696.         glEnable( GL_POINT_SMOOTH );
  697.         glHint( GL_POINT_SMOOTH_HINT, GL_FASTEST );
  698.         // Line
  699.         glEnable( GL_LINE_SMOOTH );
  700.         glHint( GL_LINE_SMOOTH_HINT, GL_FASTEST );
  701.     }
  702.  
  703.     /* Perspective Correction
  704.      * The quality of color, texture coordinate, and fog coordinate interpolation
  705.     */
  706.     if( geometry_detail > 0.25f )
  707.     {
  708.         // high quality
  709.         glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
  710.     }
  711.     else
  712.     {
  713.         // low quality
  714.         glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST );
  715.     }
  716. }
  717.  
  718. void cVideo :: Init_Texture_Detail( void )
  719. {
  720.     /* filter quality of generated mipmap images
  721.      * only available if OpenGL version is 1.4 or greater
  722.     */
  723.     if( opengl_version >= 1.4f )
  724.     {
  725.         if( texture_detail > 0.2f )
  726.         {
  727.             glHint( GL_GENERATE_MIPMAP_HINT, GL_NICEST );
  728.         }
  729.         else
  730.         {
  731.             glHint( GL_GENERATE_MIPMAP_HINT, GL_FASTEST );
  732.         }
  733.     }
  734. }
  735.  
  736. void cVideo :: Init_Resolution_Scale( void )
  737. {
  738.     // up scale
  739.     global_upscalex = static_cast<float>(pPreferences->video_screen_w) / static_cast<float>(game_res_w);
  740.     global_upscaley = static_cast<float>(pPreferences->video_screen_h) / static_cast<float>(game_res_h);
  741.     // down scale
  742.     global_downscalex = static_cast<float>(game_res_w) / static_cast<float>(pPreferences->video_screen_w);
  743.     global_downscaley = static_cast<float>(game_res_h) / static_cast<float>(pPreferences->video_screen_h);
  744. }
  745.  
  746. void cVideo :: Init_Image_Cache( bool recreate /* = 0 */, bool draw_gui /* = 0 */ )
  747. {
  748.     imgcache_dir = user_data_dir + USER_IMGCACHE_DIR;
  749.     string imgcache_dir_active = imgcache_dir + "/" + int_to_string( pPreferences->video_screen_w ) + "x" + int_to_string( pPreferences->video_screen_h );
  750.  
  751.     // if cache is disabled
  752.     if( !pPreferences->image_cache_enabled )
  753.     {
  754.         return;
  755.     }
  756.  
  757.     // if not the same game version
  758.     if( recreate || pPreferences->game_version != smc_version )
  759.     {
  760.         // delete all caches
  761.         if( fs::exists( fs::path( imgcache_dir, fs::native ) ) )
  762.         {
  763.             try
  764.             {
  765.                 fs::remove_all( fs::path( imgcache_dir, fs::native ) );
  766.             }
  767.             // could happen if a file is locked or no write rights
  768.             catch( const std::exception &ex )
  769.             {
  770.                 printf( "%s\n", ex.what() );
  771.  
  772.                 if( draw_gui )
  773.                 {
  774.                     // caching failed
  775.                     Loading_Screen_Draw_Text( _("Caching Images failed : Could not remove old images") );
  776.                     SDL_Delay( 1000 );
  777.                 }
  778.             }
  779.         }
  780.         
  781.         fs::create_directory( fs::path( imgcache_dir, fs::native ) );
  782.     }
  783.  
  784.     // no cache available
  785.     if( !fs::exists( fs::path( imgcache_dir_active, fs::native ) ) )
  786.     {
  787.         fs::create_directories( fs::path( imgcache_dir_active + "/" GAME_PIXMAPS_DIR, fs::native ) );
  788.     }
  789.     // cache available
  790.     else
  791.     {
  792.         imgcache_dir = imgcache_dir_active;
  793.         return;
  794.     }
  795.  
  796.     // texture detail should be maximum for caching
  797.     float real_texture_detail = texture_detail;
  798.     texture_detail = 1;
  799.  
  800.     CEGUI::ProgressBar *progress_bar = NULL;
  801.  
  802.     if( draw_gui )
  803.     {
  804.         // get progress bar
  805.         progress_bar = static_cast<CEGUI::ProgressBar *>(CEGUI::WindowManager::getSingleton().getWindow( "progress_bar" ));
  806.         progress_bar->setProgress( 0 );
  807.  
  808.         // set loading screen text
  809.         Loading_Screen_Draw_Text( _("Caching Images") );
  810.     }
  811.  
  812.     // get all files
  813.     vector<string> image_files = Get_Directory_Files( DATA_DIR "/" GAME_PIXMAPS_DIR, ".settings", 1 );
  814.  
  815.     unsigned int loaded_files = 0;
  816.     unsigned int file_count = image_files.size();
  817.  
  818.     // create directories, load images and save to cache
  819.     for( vector<string>::iterator itr = image_files.begin(), itr_end = image_files.end(); itr != itr_end; ++itr )
  820.     {
  821.         // get filename
  822.         string filename = (*itr);
  823.  
  824.         // remove data dir
  825.         string cache_filename = filename.substr( strlen( DATA_DIR "/" ) );
  826.  
  827.         // if directory
  828.         if( filename.rfind( "." ) == string::npos )
  829.         {
  830.             if( !fs::exists( fs::path( imgcache_dir_active + "/" + cache_filename, fs::native ) ) )
  831.             {
  832.                 fs::create_directory( fs::path( imgcache_dir_active + "/" + cache_filename, fs::native ) );
  833.             }
  834.  
  835.             loaded_files++;
  836.             continue;
  837.         }
  838.  
  839.         bool settings_file = 0;
  840.  
  841.         // Don't use .settings file type directly for image loading
  842.         if( filename.rfind( ".settings" ) != string::npos )
  843.         {
  844.             settings_file = 1;
  845.             filename.erase( filename.rfind( ".settings" ) );
  846.             filename.insert( filename.length(), ".png" );
  847.         }
  848.         
  849.         // load software image
  850.         cSoftware_Image software_image = Load_Image( filename );
  851.         SDL_Surface *sdl_surface = software_image.sdl_surface;
  852.         cImage_settings_data *settings = software_image.settings;
  853.  
  854.         // failed to load image
  855.         if( !sdl_surface )
  856.         {
  857.             continue;
  858.         }
  859.  
  860.         // no settings
  861.         if( !settings )
  862.         {
  863.             SDL_FreeSurface( sdl_surface );
  864.             continue;
  865.         }
  866.  
  867.         // create final image
  868.         sdl_surface = Convert_To_Final_Software_Image( sdl_surface );
  869.  
  870.         // get final size for this resolution
  871.         cSize_Float size = settings->Get_Surface_Size( sdl_surface );
  872.         int new_width = static_cast<int>(size.m_width);
  873.         int new_height = static_cast<int>(size.m_height);
  874.         delete settings;
  875.  
  876.         // does not need to be sampled down
  877.         if( new_width >= sdl_surface->w && new_height >= sdl_surface->h )
  878.         {
  879.             SDL_FreeSurface( sdl_surface );
  880.             continue;
  881.         }
  882.  
  883.         // calculate block reduction
  884.         int reduce_block_x = sdl_surface->w / new_width;
  885.         int reduce_block_y = sdl_surface->h / new_height;
  886.  
  887.         // create downsampled image
  888.         unsigned int image_bpp = sdl_surface->format->BytesPerPixel;
  889.         unsigned char *image_downsampled = new unsigned char[new_width * new_height * image_bpp];
  890.         bool sampled = Downscale_Image( static_cast<unsigned char*>(sdl_surface->pixels), sdl_surface->w, sdl_surface->h, image_bpp, image_downsampled, reduce_block_x, reduce_block_y );
  891.         SDL_FreeSurface( sdl_surface );
  892.         
  893.         // if image is available
  894.         if( sampled )
  895.         {
  896.             // save as png
  897.             if( settings_file )
  898.             {
  899.                 cache_filename.insert( cache_filename.length(), ".png" );
  900.             }
  901.  
  902.             // save image
  903.             Save_Surface( imgcache_dir_active + "/" + cache_filename, image_downsampled, new_width, new_height, image_bpp );
  904.         }
  905.  
  906.         delete image_downsampled;
  907.  
  908.         // count files
  909.         loaded_files++;
  910.  
  911.         // draw
  912.         if( draw_gui )
  913.         {
  914.             // update filename
  915.             GL_Surface *surface_filename = pFont->Render_Text( pFont->font_small, filename, white );
  916.  
  917.             // update progress
  918.             progress_bar->setProgress( static_cast<float>(loaded_files) / static_cast<float>(file_count) );
  919.  
  920.             // clear screen
  921.             Clear_Screen();
  922.             Draw_Rect( NULL, 0.01f, &black );
  923.  
  924.             // draw filename
  925.             surface_filename->Blit( game_res_w * 0.2f, game_res_h * 0.8f, 0.1f );
  926.  
  927.             // Render
  928.             pRenderer->Render();
  929.             pGuiSystem->renderGUI();
  930.             pRenderer_GUI->Render();
  931.             SDL_GL_SwapBuffers();
  932.             
  933.             // delete
  934.             delete surface_filename;
  935.         }
  936.     }
  937.  
  938.     // set back texture detail
  939.     texture_detail = real_texture_detail;
  940.     // set directory after surfaces got loaded from Load_GL_Surface()
  941.     imgcache_dir = imgcache_dir_active;
  942. }
  943.  
  944. int cVideo :: Test_Video( int width, int height, int bpp, int flags /* = 0 */ )
  945. {
  946.     // auto set the video flags
  947.     if( !flags )
  948.     {
  949.         flags = SDL_OPENGL | SDL_SWSURFACE;
  950.  
  951.         // if fullscreen is set
  952.         if( pPreferences->video_fullscreen )
  953.         {
  954.             flags |= SDL_FULLSCREEN;
  955.         }
  956.     }
  957.  
  958.     return SDL_VideoModeOK( width, height, bpp, flags );
  959. }
  960.  
  961. vector<cSize_Int> cVideo :: Get_Supported_Resolutions( int flags /* = 0 */ )
  962. {
  963.     vector<cSize_Int> valid_resolutions;
  964.  
  965.     // auto set the video flags
  966.     if( !flags )
  967.     {
  968.         // always set fullscreen
  969.         flags = SDL_OPENGL | SDL_SWSURFACE | SDL_FULLSCREEN;
  970.     }
  971.  
  972.     SDL_Rect** modes = SDL_ListModes( NULL, flags );
  973.     bool create_default_list = 0;
  974.  
  975.     // no dimension is available
  976.     if( modes == NULL )
  977.     {
  978.         create_default_list = 1;
  979.     }
  980.     // any dimension is allowed
  981.     else if( modes == (SDL_Rect**)-1 )
  982.     {
  983.         create_default_list = 1;
  984.     }
  985.     else
  986.     {
  987.         for( int i = 0; modes[i]; ++i )
  988.         {
  989.             valid_resolutions.push_back( cSize_Int( modes[i]->w, modes[i]->h ) );
  990.         }
  991.     }
  992.  
  993.     if( create_default_list )
  994.     {
  995.         valid_resolutions.push_back( cSize_Int( 2048, 1536 ) );
  996.         valid_resolutions.push_back( cSize_Int( 1600, 1200 ) );
  997.         valid_resolutions.push_back( cSize_Int( 1280, 1024 ) );
  998.         valid_resolutions.push_back( cSize_Int( 1024, 768 ) );
  999.         valid_resolutions.push_back( cSize_Int( 800, 600 ) );
  1000.         valid_resolutions.push_back( cSize_Int( 640, 480 ) );
  1001.     }
  1002.  
  1003.     return valid_resolutions;
  1004. }
  1005.  
  1006. void cVideo :: Clear_Screen( void )
  1007. {
  1008.     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  1009.     glLoadIdentity();
  1010. }
  1011.  
  1012. void cVideo :: Render( void )
  1013. {
  1014.     pRenderer->Render();
  1015.     pGuiSystem->renderGUI();
  1016.     pRenderer_GUI->Render();
  1017.     pMouseCursor->Render();
  1018.     SDL_GL_SwapBuffers();
  1019. }
  1020.  
  1021. void cVideo :: Toggle_Fullscreen( void )
  1022. {
  1023.     // toggle fullscreen
  1024.     pPreferences->video_fullscreen = !pPreferences->video_fullscreen;
  1025.  
  1026.     // save clear color
  1027.     GLclampf clear_color[4];
  1028.     glGetFloatv( GL_COLOR_CLEAR_VALUE, clear_color );
  1029.  
  1030. #ifdef WIN32
  1031.     // windows needs reinitialization
  1032.     Init_Video();
  1033. #else
  1034.     // works only for X11 platforms
  1035.     SDL_WM_ToggleFullScreen( screen );
  1036. #endif
  1037.  
  1038.     // set back clear color
  1039.     glClearColor( clear_color[0], clear_color[1], clear_color[2], clear_color[3] );
  1040. }
  1041.  
  1042. GL_Surface *cVideo :: Get_Surface( string filename, bool print_errors /* = 1 */ )
  1043. {
  1044.     // .settings file type can't be used directly
  1045.     if( filename.find( ".settings" ) != string::npos )
  1046.     {
  1047.         filename.erase( filename.find( ".settings" ) );
  1048.         filename.insert( filename.length(), ".png" );
  1049.     }
  1050.  
  1051.     // pixmaps dir must be given
  1052.     if( filename.find( DATA_DIR "/" GAME_PIXMAPS_DIR "/" ) == string::npos )
  1053.     {
  1054.         filename.insert( 0, DATA_DIR "/" GAME_PIXMAPS_DIR "/" );
  1055.     }
  1056.  
  1057.     // check if already loaded
  1058.     GL_Surface *image = pImage_Manager->Get_Pointer( filename );
  1059.     // already loaded
  1060.     if( image )
  1061.     {
  1062.         return image;
  1063.     }
  1064.     
  1065.     // load new image
  1066.     image = Load_GL_Surface( filename, 1, print_errors );
  1067.     // add new image
  1068.     if( image )
  1069.     {
  1070.         pImage_Manager->Add( image );
  1071.     }
  1072.     
  1073.     return image;
  1074. }
  1075.  
  1076. cVideo::cSoftware_Image cVideo :: Load_Image( string filename, bool load_settings /* = 1 */, bool print_errors /* = 1 */ )
  1077. {
  1078.     // pixmaps dir must be given
  1079.     if( filename.find( DATA_DIR "/" GAME_PIXMAPS_DIR "/" ) == string::npos ) 
  1080.     {
  1081.         filename.insert( 0, DATA_DIR "/" GAME_PIXMAPS_DIR "/" );
  1082.     }
  1083.  
  1084.     cSoftware_Image software_image = cSoftware_Image();
  1085.     SDL_Surface *sdl_surface = NULL;
  1086.     cImage_settings_data *settings = NULL;
  1087.  
  1088.     // load settings if available
  1089.     if( load_settings )
  1090.     {
  1091.         string settings_file = filename;
  1092.  
  1093.         // if not already set
  1094.         if( settings_file.rfind( ".settings" ) == string::npos )
  1095.         {
  1096.             settings_file.erase( settings_file.rfind( "." ) + 1 );
  1097.             settings_file.insert( settings_file.rfind( "." ) + 1, "settings" );
  1098.         }
  1099.  
  1100.         // if a settings file exists
  1101.         if( File_Exists( settings_file ) )
  1102.         {
  1103.             settings = pSettingsParser->Get( settings_file );
  1104.  
  1105.             // add cache dir and remove data dir
  1106.             string img_filename_cache = imgcache_dir + "/" + settings_file.substr( strlen( DATA_DIR "/" ) ) + ".png";
  1107.  
  1108.             // check if image cache file exists
  1109.             if( File_Exists( img_filename_cache ) )
  1110.             {
  1111.                 sdl_surface = IMG_Load( img_filename_cache.c_str() );
  1112.             }
  1113.             // image given in base settings
  1114.             else if( !settings->m_base.empty() )
  1115.             {
  1116.                 // use current directory
  1117.                 string img_filename = filename.substr( 0, filename.rfind( "/" ) + 1 ) + settings->m_base;
  1118.  
  1119.                 // not found
  1120.                 if( !File_Exists( img_filename ) )
  1121.                 {
  1122.                     // use data dir
  1123.                     img_filename = settings->m_base;
  1124.  
  1125.                     // pixmaps dir must be given
  1126.                     if( img_filename.find( DATA_DIR "/" GAME_PIXMAPS_DIR "/" ) == string::npos )
  1127.                     {
  1128.                         img_filename.insert( 0, DATA_DIR "/" GAME_PIXMAPS_DIR "/" );
  1129.                     }
  1130.                 }
  1131.  
  1132.                 sdl_surface = IMG_Load( img_filename.c_str() );
  1133.             }
  1134.         }
  1135.     }
  1136.  
  1137.     // if not set in image settings and file exists
  1138.     if( !sdl_surface && File_Exists( filename ) && ( !settings || settings->m_base.empty() ) )
  1139.     {
  1140.         sdl_surface = IMG_Load( filename.c_str() );
  1141.     }
  1142.  
  1143.     if( !sdl_surface )
  1144.     {
  1145.         if( settings )
  1146.         {
  1147.             delete settings;
  1148.             settings = NULL;
  1149.         }
  1150.  
  1151.         if( print_errors )
  1152.         {
  1153.             printf( "Error loading image : %s\nReason : %s\n", filename.c_str(), SDL_GetError() );
  1154.         }
  1155.  
  1156.         return software_image;
  1157.     }
  1158.  
  1159.     software_image.sdl_surface = sdl_surface;
  1160.     software_image.settings = settings;
  1161.     return software_image;
  1162. }
  1163.  
  1164. GL_Surface *cVideo :: Load_GL_Surface( string filename, bool use_settings /* = 1 */, bool print_errors /* = 1 */ )
  1165. {
  1166.     // pixmaps dir must be given
  1167.     if( filename.find( DATA_DIR "/" GAME_PIXMAPS_DIR "/" ) == string::npos ) 
  1168.     {
  1169.         filename.insert( 0, DATA_DIR "/" GAME_PIXMAPS_DIR "/" );
  1170.     }
  1171.  
  1172.     // load software image
  1173.     cSoftware_Image software_image = Load_Image( filename, use_settings, print_errors );
  1174.     SDL_Surface *sdl_surface = software_image.sdl_surface;
  1175.     cImage_settings_data *settings = software_image.settings;
  1176.  
  1177.     // final surface
  1178.     GL_Surface *image = NULL;
  1179.  
  1180.     // with settings
  1181.     if( settings )
  1182.     {
  1183.         // get the size
  1184.         cSize_Float size = settings->Get_Surface_Size( sdl_surface );
  1185.         // get basic settings surface
  1186.         image = pVideo->Create_Texture( sdl_surface, settings->m_mipmap, static_cast<unsigned int>(size.m_width), static_cast<unsigned int>(size.m_height) );
  1187.         // apply settings
  1188.         settings->Apply( image );
  1189.         delete settings;
  1190.     }
  1191.     // without settings
  1192.     else
  1193.     {
  1194.         image = Create_Texture( sdl_surface );
  1195.     }
  1196.  
  1197.     // set filename
  1198.     if( image )
  1199.     {
  1200.         image->filename = filename;
  1201.     }
  1202.     // print error
  1203.     else if( print_errors )
  1204.     {
  1205.         printf( "Error loading image : %s\nReason : %s\n", filename.c_str(), SDL_GetError() );
  1206.     }
  1207.  
  1208.     return image;
  1209. }
  1210.  
  1211. SDL_Surface *cVideo :: Convert_To_Final_Software_Image( SDL_Surface *surface )
  1212. {
  1213.     // get power of two size
  1214.     unsigned int width = Get_Power_of_2( surface->w );
  1215.     unsigned int height = Get_Power_of_2( surface->h );
  1216.  
  1217.     // if it needs to be changed
  1218.     if( width != surface->w || height != surface->h || surface->format->BitsPerPixel != 32 )
  1219.     {
  1220.         // create power of 2 and 32 bits per pixel surface
  1221.         SDL_Surface *final = SDL_CreateRGBSurface( SDL_SWSURFACE, width, height, 32,
  1222.         #if SDL_BYTEORDER == SDL_BIG_ENDIAN
  1223.                 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff );
  1224.         #else
  1225.                 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 );
  1226.         #endif
  1227.  
  1228.         // set the entire surface alpha to 0
  1229.         SDL_SetAlpha( surface, 0, SDL_ALPHA_TRANSPARENT );
  1230.         // blit to 32 bit surface
  1231.         SDL_BlitSurface( surface, NULL, final, NULL );
  1232.         // delete original surface
  1233.         SDL_FreeSurface( surface );
  1234.         // set new surface
  1235.         surface = final;
  1236.     }
  1237.  
  1238.     return surface;
  1239. }
  1240.  
  1241. GL_Surface *cVideo :: Create_Texture( SDL_Surface *surface, bool mipmap /* = 0 */, unsigned int force_width /* = 0 */, unsigned int force_height /* = 0 */ )
  1242. {
  1243.     if( !surface )
  1244.     {
  1245.         return NULL;
  1246.     }
  1247.  
  1248.     // create final image
  1249.     surface = Convert_To_Final_Software_Image( surface );
  1250.  
  1251.     // create one texture
  1252.     GLuint image_num = 0;
  1253.     glGenTextures( 1, &image_num );
  1254.  
  1255.     // if image id is 0 it failed
  1256.     if( !image_num )
  1257.     {
  1258.         printf( "Error : GL image generation failed\n" );
  1259.         SDL_FreeSurface( surface );
  1260.         return NULL;
  1261.     }
  1262.     
  1263.     // set highest texture id
  1264.     if( pImage_Manager->high_texture_id < image_num )
  1265.     {
  1266.         pImage_Manager->high_texture_id = image_num;
  1267.     }
  1268.  
  1269.     unsigned int width = surface->w;
  1270.     unsigned int height = surface->h;
  1271.  
  1272.     // new dimension is set
  1273.     if( force_width > 0 && force_height > 0 )
  1274.     {
  1275.         // get power of two size
  1276.         force_width = Get_Power_of_2( force_width );
  1277.         force_height = Get_Power_of_2( force_height );
  1278.  
  1279.         // scale
  1280.         if( force_width != width || force_height != height )
  1281.         {
  1282.             // create scaled image
  1283.             void *new_pixels = SDL_malloc( force_width * force_height * 4 );
  1284.             gluScaleImage( GL_RGBA, surface->w, surface->h, GL_UNSIGNED_BYTE, surface->pixels, force_width, force_height, GL_UNSIGNED_BYTE, new_pixels );
  1285.             SDL_free( surface->pixels );
  1286.             surface->pixels = new_pixels;
  1287.  
  1288.             // set new dimension
  1289.             width = force_width;
  1290.             height = force_height;
  1291.         }
  1292.         // set SDL_image pixel store mode
  1293.         else
  1294.         {
  1295.             glPixelStorei( GL_UNPACK_ROW_LENGTH, surface->pitch / surface->format->BytesPerPixel );
  1296.         }
  1297.     }
  1298.  
  1299.     // use the generated texture
  1300.     glBindTexture( GL_TEXTURE_2D, image_num );
  1301.  
  1302.     // set how this texture is drawn
  1303.     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
  1304.     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
  1305.     // set texture magnification function
  1306.     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
  1307.     // upload to OpenGL texture
  1308.     Create_GL_Texture( width, height, surface->pixels, mipmap );
  1309.     // unset pixel store mode
  1310.     glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
  1311.  
  1312.     SDL_FreeSurface( surface );
  1313.  
  1314.     // create OpenGL surface class
  1315.     GL_Surface *image = new GL_Surface();
  1316.     image->image = image_num;
  1317.     image->tex_w = width;
  1318.     image->tex_h = height;
  1319.     image->start_w = static_cast<float>(width);
  1320.     image->start_h = static_cast<float>(height);
  1321.     image->w = image->start_w;
  1322.     image->h = image->start_h;
  1323.     image->col_w = image->w;
  1324.     image->col_h = image->h;
  1325.  
  1326.     // if debug build check for errors
  1327. #ifdef _DEBUG
  1328.     GLenum error = glGetError();
  1329.     if( error != GL_NO_ERROR )
  1330.     {
  1331.         printf( "CreateTexture : GL Error found : %s\n", gluErrorString( error ) );
  1332.     }
  1333. #endif
  1334.  
  1335.     return image;
  1336. }
  1337.  
  1338. void cVideo :: Create_GL_Texture( unsigned int width, unsigned int height, void *pixels, bool mipmap /* = 0 */ )
  1339. {
  1340.     // create mipmaps
  1341.     if( mipmap )
  1342.     {
  1343.         // enable mipmap filter
  1344.         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
  1345.  
  1346.         // if OpenGL 1.4 or higher
  1347.         if( opengl_version >= 1.4f )
  1348.         {
  1349.             // use glTexImage2D to create Mipmaps
  1350.             glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, 1 );
  1351.             // copy the software bitmap into the opengl texture
  1352.             glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels );
  1353.         }
  1354.         // OpenGL below 1.4
  1355.         else
  1356.         {
  1357.             // use glu to create Mipmaps
  1358.             gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels );
  1359.         }
  1360.     }
  1361.     // no mipmaps
  1362.     else
  1363.     {
  1364.         // default texture minifying function
  1365.          glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
  1366.         // copy the software bitmap into the opengl texture
  1367.         glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels );
  1368.     }
  1369. }
  1370.  
  1371. Color cVideo :: Get_Pixel( int x, int y, GL_Surface *source /* = NULL */ )
  1372. {
  1373.     //glReadBuffer( GL_FRONT );
  1374.  
  1375.     float *pixel = new float[3];
  1376.     glLoadIdentity();
  1377.     glReadPixels( x, y, 1, 1, GL_RGB, GL_FLOAT, pixel );
  1378.  
  1379.     Color color = Color( pixel[0], pixel[1], pixel[2] );
  1380.     delete[] pixel;
  1381.  
  1382.     return color;
  1383. }
  1384.  
  1385. void cVideo :: Draw_Line( GL_line *line, float z, const Color *color, cLineRequest *request /* = NULL */ )
  1386. {
  1387.     if( !line )
  1388.     {
  1389.         return;
  1390.     }
  1391.  
  1392.     Draw_Line( line->x1, line->y1, line->x2, line->y2, z, color, request );
  1393. }
  1394.  
  1395. void cVideo :: Draw_Line( float x1, float y1, float x2, float y2, float z, const Color *color, cLineRequest *request /* = NULL */ )
  1396. {
  1397.     if( !color )
  1398.     {
  1399.         return;
  1400.     }
  1401.  
  1402.     bool create_request = 0;
  1403.  
  1404.     if( !request )
  1405.     {
  1406.         create_request = 1;
  1407.         // create request
  1408.         request = new cLineRequest();
  1409.     }
  1410.  
  1411.     // line
  1412.     request->line.x1 = x1;
  1413.     request->line.y1 = y1;
  1414.     request->line.x2 = x2;
  1415.     request->line.y2 = y2;
  1416.  
  1417.     // z position
  1418.     request->pos_z = z;
  1419.  
  1420.     // color
  1421.     request->color = *color;
  1422.  
  1423.     if( create_request )
  1424.     {
  1425.         // add request
  1426.         pRenderer->Add( request );
  1427.     }
  1428. }
  1429.  
  1430. void cVideo :: Draw_Rect( GL_rect *rect, float z, const Color *color, cRectRequest *request /* = NULL */ )
  1431. {
  1432.     if( !rect )
  1433.     {
  1434.         Draw_Rect( 0, 0, static_cast<float>(game_res_w), static_cast<float>(game_res_h), z, color, request );
  1435.     }
  1436.     else
  1437.     {
  1438.         Draw_Rect( rect->x, rect->y, rect->w, rect->h, z, color, request );
  1439.     }
  1440. }
  1441.  
  1442. void cVideo :: Draw_Rect( float x, float y, float width, float height, float z, const Color *color, cRectRequest *request /* = NULL */ )
  1443. {
  1444.     if( !color || height == 0 || width == 0 )
  1445.     {
  1446.         return;
  1447.     }
  1448.  
  1449.     bool create_request = 0;
  1450.  
  1451.     if( !request )
  1452.     {
  1453.         create_request = 1;
  1454.         // create request
  1455.         request = new cRectRequest();
  1456.     }
  1457.  
  1458.     // rect
  1459.     request->rect.x = x;
  1460.     request->rect.y = y;
  1461.     request->rect.w = width;
  1462.     request->rect.h = height;
  1463.  
  1464.     // z position
  1465.     request->pos_z = z;
  1466.  
  1467.     // color
  1468.     request->color = *color;
  1469.  
  1470.     if( create_request )
  1471.     {
  1472.         // add request
  1473.         pRenderer->Add( request );
  1474.     }
  1475. }
  1476.  
  1477. void cVideo :: Draw_Gradient( GL_rect *rect, float z, const Color *color_1, const Color *color_2, ObjectDirection direction, cGradientRequest *request /* = NULL */ )
  1478. {
  1479.     if( !rect )
  1480.     {
  1481.         Draw_Gradient( 0, 0, static_cast<float>(game_res_w), static_cast<float>(game_res_h), z, color_1, color_2, direction, request );
  1482.     }
  1483.     else
  1484.     {
  1485.         Draw_Gradient( rect->x, rect->y, rect->w, rect->h, z, color_1, color_2, direction, request );
  1486.     }
  1487. }
  1488.  
  1489. void cVideo :: Draw_Gradient( float x, float y, float width, float height, float z, const Color *color_1, const Color *color_2, ObjectDirection direction, cGradientRequest *request /* = NULL */ )
  1490. {
  1491.     if( !color_1 || !color_2 || height == 0 || width == 0 )
  1492.     {
  1493.         return;
  1494.     }
  1495.  
  1496.     bool create_request = 0;
  1497.  
  1498.     if( !request )
  1499.     {
  1500.         create_request = 1;
  1501.         // create request
  1502.         request = new cGradientRequest();
  1503.     }
  1504.  
  1505.     // rect
  1506.     request->rect.x = x;
  1507.     request->rect.y = y;
  1508.     request->rect.w = width;
  1509.     request->rect.h = height;
  1510.  
  1511.     // z position
  1512.     request->pos_z = z;
  1513.  
  1514.     // color
  1515.     request->color_1 = *color_1;
  1516.     request->color_2 = *color_2;
  1517.  
  1518.     // direction
  1519.     request->dir = direction;
  1520.  
  1521.     if( create_request )
  1522.     {
  1523.         // add request
  1524.         pRenderer->Add( request );
  1525.     }
  1526. }
  1527.  
  1528. void cVideo :: Draw_Circle( float x, float y, float radius, float z, Color *color, cCircleRequest *request /* = NULL */ )
  1529. {
  1530.     if( !color || radius <= 0 )
  1531.     {
  1532.         return;
  1533.     }
  1534.  
  1535.     bool create_request = 0;
  1536.  
  1537.     if( !request )
  1538.     {
  1539.         create_request = 1;
  1540.         // create request
  1541.         request = new cCircleRequest();
  1542.     }
  1543.  
  1544.     // position
  1545.     request->pos.x = x;
  1546.     request->pos.y = y;
  1547.     // radius
  1548.     request->radius = radius;
  1549.  
  1550.     // z position
  1551.     request->pos_z = z;
  1552.  
  1553.     // color
  1554.     request->color = *color;
  1555.  
  1556.     if( create_request )
  1557.     {
  1558.         // add request
  1559.         pRenderer->Add( request );
  1560.     }
  1561. }
  1562.  
  1563. float cVideo :: Get_Scale( GL_Surface *image, float width, float height, bool only_downscale /* = 1 */ )
  1564. {
  1565.     if( !image )
  1566.     {
  1567.         return 0;
  1568.     }
  1569.  
  1570.     // change size
  1571.     if( !( only_downscale && image->h <= height && image->w <= width ) )
  1572.     {
  1573.         float zoom = width / image->w;
  1574.  
  1575.         if( height / image->h < zoom ) // if height is smaller
  1576.         {
  1577.             zoom = height / image->h;
  1578.         }
  1579.  
  1580.         return zoom;
  1581.     }
  1582.  
  1583.     return 1;
  1584. }
  1585.  
  1586. /* function from Jonathan Dummer
  1587.  * from image helper functions
  1588.  * MIT license
  1589. */
  1590. bool cVideo :: Downscale_Image( const unsigned char* const orig, int width, int height, int channels, unsigned char* resampled, int block_size_x, int block_size_y )
  1591. {
  1592.     //    error check
  1593.     if( width <= 0 || height <= 0 || channels <= 0 || orig == NULL || resampled == NULL || block_size_x <= 0 || block_size_y <= 0 )
  1594.     {
  1595.         // invalid argument
  1596.         return 0;
  1597.     }
  1598.  
  1599.     int mip_width = width / block_size_x;
  1600.     int mip_height = height / block_size_y;
  1601.  
  1602.     // check size
  1603.     if( mip_width < 1 )
  1604.     {
  1605.         mip_width = 1;
  1606.     }
  1607.     if( mip_height < 1 )
  1608.     {
  1609.         mip_height = 1;
  1610.     }
  1611.  
  1612.     int j, i, c;
  1613.  
  1614.     for( j = 0; j < mip_height; ++j )
  1615.     {
  1616.         for( i = 0; i < mip_width; ++i )
  1617.         {
  1618.             for( c = 0; c < channels; ++c )
  1619.             {
  1620.                 const int index = (j * block_size_y) * width * channels + (i * block_size_x) * channels + c;
  1621.                 int sum_value;
  1622.                 int u,v;
  1623.                 int u_block = block_size_x;
  1624.                 int v_block = block_size_y;
  1625.                 int block_area;
  1626.  
  1627.                 /* do a bit of checking so we don't over-run the boundaries
  1628.                  * necessary for non-square textures!
  1629.                  */
  1630.                 if( block_size_x * (i + 1) > width )
  1631.                 {
  1632.                     u_block = width - i * block_size_y;
  1633.                 }
  1634.                 if( block_size_y * (j + 1) > height )
  1635.                 {
  1636.                     v_block = height - j * block_size_y;
  1637.                 }
  1638.                 block_area = u_block * v_block;
  1639.  
  1640.                 /* for this pixel, see what the average
  1641.                  * of all the values in the block are.
  1642.                  * note: start the sum at the rounding value, not at 0
  1643.                  */
  1644.                 sum_value = block_area >> 1;
  1645.                 for( v = 0; v < v_block; ++v )
  1646.                 {
  1647.                     for( u = 0; u < u_block; ++u )
  1648.                     {
  1649.                         sum_value += orig[index + v * width * channels + u * channels];
  1650.                     }
  1651.                 }
  1652.  
  1653.                 resampled[j * mip_width * channels + i * channels + c] = sum_value / block_area;
  1654.             }
  1655.         }
  1656.     }
  1657.  
  1658.     return 1;
  1659. }
  1660.  
  1661. void cVideo :: Save_Screenshot( void )
  1662. {
  1663.     string filename;
  1664.     
  1665.     for( unsigned int i = 1; i < 1000; i++ )
  1666.     {
  1667.         filename = user_data_dir + USER_SCREENSHOT_DIR "/" + int_to_string( i ) + ".png";
  1668.  
  1669.         if( !File_Exists( filename ) )
  1670.         {
  1671.             // create image data
  1672.             GLubyte *data = new GLubyte[pPreferences->video_screen_w * pPreferences->video_screen_h * 3];
  1673.             // read opengl screen
  1674.             glReadPixels( 0, 0, pPreferences->video_screen_w, pPreferences->video_screen_h, GL_RGB, GL_UNSIGNED_BYTE, static_cast<GLvoid *>(data) );
  1675.             // save
  1676.             Save_Surface( filename, data, pPreferences->video_screen_w, pPreferences->video_screen_h, 3, 1 );
  1677.             // clear data
  1678.             delete[] data;
  1679.  
  1680.             // show info
  1681.             debugdisplay->Set_Text( "Screenshot " + int_to_string( i ) + _(" saved"), speedfactor_fps * 2.5f );
  1682.  
  1683.             // finished
  1684.             return;
  1685.         }
  1686.     }
  1687. }
  1688.  
  1689. void cVideo :: Save_Surface( string filename, unsigned char *data, unsigned int width, unsigned int height, unsigned int bpp /* = 4 */, bool reverse_data /* = 0 */ )
  1690. {
  1691.     FILE *fp = NULL;
  1692.  
  1693.     fp = fopen( filename.c_str(), "wb" );
  1694.  
  1695.     if( !fp )
  1696.     {
  1697.         printf( "Could not save Surface\n" );
  1698.         return;
  1699.     }
  1700.  
  1701.     int png_color_type;
  1702.  
  1703.     if( bpp == 4 )
  1704.     {
  1705.         png_color_type = PNG_COLOR_TYPE_RGBA;
  1706.     }
  1707.     else if( bpp == 3 )
  1708.     {
  1709.         png_color_type = PNG_COLOR_TYPE_RGB;
  1710.     }
  1711.     else
  1712.     {
  1713.         printf( "Warning: cVideo :: Save_Surface : %s Unknown bytes per pixel %d\n", filename.c_str(), bpp );
  1714.         return;
  1715.     }
  1716.  
  1717.     png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
  1718.     png_infop info_ptr = png_create_info_struct( png_ptr );
  1719.  
  1720.     png_init_io( png_ptr, fp );
  1721.  
  1722.     png_set_IHDR( png_ptr, info_ptr,
  1723.         width, height, 8 /* bit depth */, png_color_type,
  1724.         PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT );
  1725.  
  1726.     png_write_info( png_ptr, info_ptr );
  1727.  
  1728.     png_uint_32 png_height = height;
  1729.     png_uint_32 row_bytes = width * bpp;
  1730.  
  1731.     png_byte *image = new png_byte[png_height * row_bytes];
  1732.     png_bytep *row_pointers = new png_bytep[png_height];
  1733.  
  1734.     // create image data
  1735.     int img_size = png_height * row_bytes;
  1736.     for( int i = 0; i < img_size; ++i )
  1737.     {
  1738.         image[i] = data[i];
  1739.     }
  1740.  
  1741.     // create row pointers
  1742.     if( reverse_data )
  1743.     {
  1744.         for( unsigned int i = 0; i < png_height; i++ )
  1745.         {
  1746.             // reverse direction because of opengl glReadPixels
  1747.             row_pointers[png_height - 1 - i] = image + (i * row_bytes);
  1748.         }
  1749.     }
  1750.     else
  1751.     {
  1752.         for( unsigned int i = 0; i < png_height; i++ )
  1753.         {
  1754.             row_pointers[i] = image + (i * row_bytes);
  1755.         }
  1756.     }
  1757.  
  1758.     png_write_image( png_ptr, row_pointers );
  1759.     png_write_end( png_ptr, info_ptr );
  1760.     png_destroy_write_struct( &png_ptr, &info_ptr );
  1761.  
  1762.     delete []image;
  1763.     delete []row_pointers;
  1764.  
  1765.     fclose( fp );
  1766. }
  1767.  
  1768. /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
  1769.  
  1770. void Draw_Effect_Out( Effect_Fadeout effect /* = EFFECT_OUT_RANDOM */, float speed /* = 1 */ )
  1771. {
  1772.     if( effect == EFFECT_OUT_RANDOM )
  1773.     {
  1774.         effect = static_cast<Effect_Fadeout>( ( rand() % (EFFECT_OUT_AMOUNT - 1) ) + 1 );
  1775.     }
  1776.  
  1777.     switch( effect )
  1778.     {
  1779.     case EFFECT_OUT_BLACK:
  1780.     {
  1781.         Color color = static_cast<Uint8>(0);
  1782.  
  1783.         for( float i = 1; i > 0; i -= ( speed / 30 ) * pFramerate->speedfactor )
  1784.         {
  1785.             color.alpha = static_cast<Uint8>( 45 - ( 45 * i ) );
  1786.  
  1787.             // create request
  1788.             cRectRequest *request = new cRectRequest();
  1789.             pVideo->Draw_Rect( NULL, 0.9f, &color, request );
  1790.             
  1791.             request->render_count = 2;
  1792.  
  1793.             // add request
  1794.             pRenderer->Add( request );
  1795.  
  1796.             pVideo->Render();
  1797.  
  1798.             pFramerate->Update();
  1799.             // maximum fps
  1800.             Correct_Frame_Time( 100 );
  1801.         }
  1802.         
  1803.         break;
  1804.     }
  1805.     case EFFECT_OUT_HORIZONTAL_VERTICAL:
  1806.     {
  1807.         float pos = 0;
  1808.         float size = 1;
  1809.         int hor = ( rand() % 2 ) - 1;
  1810.         Color color = Color( static_cast<Uint8>( rand() % 100 ), rand() % 100, rand() % 100, 150 );
  1811.  
  1812.         // horizontal
  1813.         if( hor )
  1814.         {
  1815.             pos = static_cast<float>(game_res_w);
  1816.         }
  1817.         // vertical
  1818.         else
  1819.         {
  1820.             pos = static_cast<float>(game_res_h);
  1821.         }
  1822.  
  1823.         while( pos > 0 )
  1824.         {
  1825.             // horizontal
  1826.             if( hor )
  1827.             {
  1828.                 // left/top
  1829.                 cRectRequest *rect_request = new cRectRequest();
  1830.                 pVideo->Draw_Rect( pos, 0, size, static_cast<float>(game_res_h), 0.9f, &color, rect_request );
  1831.                 rect_request->render_count = 2;
  1832.                 // add request
  1833.                 pRenderer->Add( rect_request );
  1834.  
  1835.                 // down/right
  1836.                 rect_request = new cRectRequest();
  1837.                 pVideo->Draw_Rect( static_cast<float>(game_res_w) - pos - size, 0, size, static_cast<float>(game_res_h), 0.9f, &color, rect_request );
  1838.                 rect_request->render_count = 2;
  1839.                 // add request
  1840.                 pRenderer->Add( rect_request );
  1841.  
  1842.                 size = 20 * pFramerate->speedfactor;
  1843.                 pos -= size;
  1844.             }
  1845.             // vertical
  1846.             else
  1847.             {
  1848.                 // left/top
  1849.                 cRectRequest *rect_request = new cRectRequest();
  1850.                 pVideo->Draw_Rect( 0, pos, static_cast<float>(game_res_w), size, 0.9f, &color, rect_request );
  1851.                 rect_request->render_count = 2;
  1852.                 // add request
  1853.                 pRenderer->Add( rect_request );
  1854.  
  1855.                 // down/right
  1856.                 rect_request = new cRectRequest();
  1857.                 pVideo->Draw_Rect( 0, static_cast<float>(game_res_h) - pos - size, static_cast<float>(game_res_w), size, 0.9f, &color, rect_request );
  1858.                 rect_request->render_count = 2;
  1859.                 // add request
  1860.                 pRenderer->Add( rect_request );
  1861.  
  1862.                 size = 15 * pFramerate->speedfactor;
  1863.                 pos -= size;
  1864.             }
  1865.  
  1866.             pVideo->Render();
  1867.  
  1868.             pFramerate->Update();
  1869.             // maximum fps
  1870.             Correct_Frame_Time( 100 );
  1871.         }
  1872.         break;
  1873.     }
  1874.     case EFFECT_OUT_BIG_ITEM:
  1875.     {
  1876.         float f = 0.1f;
  1877.         GL_Surface *image = NULL;
  1878.  
  1879.         // item based on the camera x position
  1880.         if( pActive_Camera->x < 2000 )
  1881.         {
  1882.             image = pVideo->Get_Surface( "game/items/mushroom_red.png" );
  1883.         }
  1884.         else if( pActive_Camera->x < 5000 )
  1885.         {
  1886.             image = pVideo->Get_Surface( "game/items/fireplant.png" );
  1887.         }
  1888.         else if( pActive_Camera->x < 10000 )
  1889.         {
  1890.             image = pVideo->Get_Surface( "game/items/mushroom_green.png" );
  1891.         }
  1892.         else if( pActive_Camera->x < 20000 )
  1893.         {
  1894.             image = pVideo->Get_Surface( "game/items/star.png" );
  1895.         }
  1896.         else
  1897.         {
  1898.             image = pVideo->Get_Surface( "game/items/moon_1.png" );
  1899.         }
  1900.  
  1901.         Color color = white;
  1902.  
  1903.         while( f < 50 )
  1904.         {
  1905.             Draw_Game();
  1906.  
  1907.             f += 0.9f * pFramerate->speedfactor * speed * ( f / 7 );
  1908.  
  1909.             color = Color( static_cast<Uint8>( 255 - ( f * 4 ) ), 255 - static_cast<Uint8>( f * 4 ), 255 - static_cast<Uint8>( f * 4 ), 200 - static_cast<Uint8>( f * 4 ) );
  1910.  
  1911.             // ## item
  1912.             // create request
  1913.             cSurfaceRequest *request = new cSurfaceRequest();
  1914.             image->Blit( ( game_res_w / 2 ) - ( ( image->w * f ) / 2 ) , game_res_h / 2 - ( ( image->h * f ) / 2 ), 0.9f, request );
  1915.  
  1916.             request->blend_sfactor = GL_SRC_ALPHA;
  1917.             request->blend_dfactor = GL_ONE;
  1918.  
  1919.             request->color = color;
  1920.  
  1921.             // scale
  1922.             request->scale_x = f;
  1923.             request->scale_y = f;
  1924.  
  1925.             // add request
  1926.             pRenderer->Add( request );
  1927.             
  1928.  
  1929.             // ## additional black fadeout
  1930.             color = Color( 0, 0, 0, static_cast<Uint8>( 50 + ( f * 4 ) ) );
  1931.  
  1932.             // create request
  1933.             cRectRequest *rect_request = new cRectRequest();
  1934.             pVideo->Draw_Rect( NULL, 0.901f, &color, rect_request );
  1935.  
  1936.             // add request
  1937.             pRenderer->Add( rect_request );
  1938.  
  1939.             pVideo->Render();
  1940.             pFramerate->Update();
  1941.         }
  1942.  
  1943.         break;
  1944.     }
  1945.     case EFFECT_OUT_RANDOM_COLOR_BOOST:
  1946.     {
  1947.         float f = 50;
  1948.         unsigned int rand_color = ( rand() % 4 );
  1949.  
  1950.         float xwidth = 45;
  1951.  
  1952.         GL_rect rect;
  1953.         
  1954.         while( f > 0 )
  1955.         {
  1956.             xwidth -= 0.1f + ( xwidth / 50 ) * pFramerate->speedfactor;
  1957.  
  1958.             rect.w = xwidth;
  1959.             rect.h = xwidth;
  1960.  
  1961.             for( unsigned int g = 0; g < 50; g++ )
  1962.             {
  1963.                 rect.x = Get_Random_Float( 0, static_cast<float>(game_res_w) );
  1964.                 rect.y = Get_Random_Float( 0, static_cast<float>(game_res_h) );
  1965.  
  1966.                 Color pixel = black;
  1967.  
  1968.                 // red
  1969.                 if( rand_color == 0 )
  1970.                 {
  1971.                     pixel = Color( 1, static_cast<Uint8>( 45 ), static_cast<Uint8>( 45 ), static_cast<Uint8>( 5 * pFramerate->speedfactor ) );
  1972.                 }
  1973.                 // green
  1974.                 else if( rand_color == 1 )
  1975.                 {
  1976.                     pixel = Color( static_cast<Uint8>( 45 ), 1, static_cast<Uint8>( 45 ), static_cast<Uint8>( 5 * pFramerate->speedfactor ) );
  1977.                 }
  1978.                 // blue
  1979.                 else if( rand_color == 2 )
  1980.                 {
  1981.                     pixel = Color( static_cast<Uint8>( 45 ), static_cast<Uint8>( 45 ), 1, static_cast<Uint8>( 5 * pFramerate->speedfactor ) );
  1982.                 }
  1983.                 // yellow
  1984.                 else
  1985.                 {
  1986.                     pixel = Color( 1, 1, static_cast<Uint8>( 45 ), static_cast<Uint8>( 6 * pFramerate->speedfactor ) );
  1987.                 }
  1988.  
  1989.                 // minimum alpha
  1990.                 if( pixel.alpha < 5 )
  1991.                 {
  1992.                     pixel.alpha = 5;
  1993.                 }
  1994.                 
  1995.                 // create request
  1996.                 cRectRequest *request = new cRectRequest();
  1997.                 pVideo->Draw_Rect( rect.x, rect.y, rect.w - (xwidth * 0.5f), rect.h - (xwidth * 0.5f), 0.9f, &pixel, request );
  1998.                 
  1999.                 request->render_count = 2;
  2000.  
  2001.                 request->blend_sfactor = GL_SRC_ALPHA;
  2002.                 request->blend_dfactor = GL_ONE_MINUS_SRC_COLOR;
  2003.  
  2004.                 // add request
  2005.                 pRenderer->Add( request );
  2006.             }
  2007.             
  2008.             f -= pFramerate->speedfactor;
  2009.  
  2010.             pVideo->Render();
  2011.             pFramerate->Update();
  2012.         }
  2013.         break;
  2014.     }
  2015.     case EFFECT_OUT_TILE_PIXELATION:
  2016.     {
  2017.         const unsigned int num_hor = 8;
  2018.         const unsigned int num_ver = 6;
  2019.         unsigned int num = num_hor * num_ver;
  2020.  
  2021.         bool grid[num_ver][num_hor];
  2022.  
  2023.         for( unsigned int i = 0; i < num_ver; i++ )
  2024.         {
  2025.             for( unsigned int j = 0; j < num_hor; j++ )
  2026.             {
  2027.                 grid[i][j] = 1;
  2028.             }
  2029.         }
  2030.         
  2031.         unsigned int select_x = 0, select_y = 0;
  2032.         unsigned int temp;
  2033.         GL_rect dest( 0, 0, static_cast<float>(game_res_w) / num_hor, static_cast<float>(game_res_h) / num_ver );
  2034.         
  2035.         for( unsigned int i = 0; i < num; i++ )
  2036.         {
  2037.             while( grid[select_y][select_x] == 0 ) // find a unused rect
  2038.             {
  2039.                 temp = rand()%( num );
  2040.  
  2041.                 select_y = temp / num_hor;
  2042.                 select_x = temp % num_hor;
  2043.             }
  2044.  
  2045.             grid[select_y][select_x] = 0;
  2046.             dest.x = select_x * dest.w;
  2047.             dest.y = select_y * dest.h;
  2048.             
  2049.             Color color = black;
  2050.  
  2051.             // create request
  2052.             cRectRequest *request = new cRectRequest();
  2053.             pVideo->Draw_Rect( &dest, 0.9f, &color, request );
  2054.             
  2055.             request->render_count = 2;
  2056.  
  2057.             // add request
  2058.             pRenderer->Add( request );
  2059.             
  2060.  
  2061.             pVideo->Render();
  2062.             pFramerate->Update();
  2063.             Correct_Frame_Time( speedfactor_fps ); // correction needed
  2064.         }
  2065.         break;
  2066.     }
  2067.     case EFFECT_OUT_FIXED_COLORBOX:
  2068.     {
  2069.         Color color( static_cast<Uint8>(0), 0, 0, 20 );
  2070.  
  2071.         unsigned int rand_color = ( rand() % 3 );
  2072.  
  2073.         // green
  2074.         if( rand_color == 0 )
  2075.         {
  2076.             color = Color( static_cast<Uint8>(10), 55, 10 );
  2077.         }
  2078.         // blue
  2079.         else if( rand_color == 1 )
  2080.         {
  2081.             color = Color( static_cast<Uint8>(10), 10, 55 );
  2082.         }
  2083.         // red - yellow
  2084.         else
  2085.         {
  2086.             color = Color( static_cast<Uint8>(55), 20, 10 );
  2087.         }
  2088.  
  2089.         // position
  2090.         float pos_x = 0;
  2091.         float pos_y = 0;
  2092.         // size
  2093.         float rect_size = 20;
  2094.         // counter
  2095.         float random_counter = 0;
  2096.         // temp rect for drawing
  2097.         GL_rect rect;
  2098.  
  2099.         // animate while size did not reach the limit
  2100.         while( rect_size < 30 )
  2101.         {
  2102.             // add size
  2103.             rect_size += 0.3f * pFramerate->speedfactor;
  2104.  
  2105.             // change position and color
  2106.             if( random_counter < rect_size )
  2107.             {
  2108.                 // color gets darker
  2109.                 if( color.red > 1 )
  2110.                 {
  2111.                     color.red = static_cast<Uint8>(color.red * 0.7f);
  2112.                     if( color.red < 1 )
  2113.                     {
  2114.                         color.red = 1;
  2115.                     }
  2116.                 }
  2117.                 if( color.green > 1 )
  2118.                 {
  2119.                     color.green = static_cast<Uint8>(color.green * 0.7f);
  2120.                     if( color.green < 1 )
  2121.                     {
  2122.                         color.green = 1;
  2123.                     }
  2124.                 }
  2125.                 if( color.blue > 1 )
  2126.                 {
  2127.                     color.blue = static_cast<Uint8>(color.blue * 0.7f);
  2128.                     if( color.blue < 1 )
  2129.                     {
  2130.                         color.blue = 1;
  2131.                     }
  2132.                 }
  2133.  
  2134.                 // random position advances with size
  2135.                 pos_x = Get_Random_Float( -(rect_size), 0 );
  2136.                 pos_y = Get_Random_Float( -(rect_size), 0 );
  2137.  
  2138.                 // set counter
  2139.                 random_counter = rect_size + 2;
  2140.             }
  2141.  
  2142.             // draw rects as a net
  2143.             // horizontal
  2144.             for( rect.x = pos_x; rect.x < game_res_w; rect.x += random_counter )
  2145.             {
  2146.                 // vertical
  2147.                 for( rect.y = pos_y; rect.y < game_res_h; rect.y += random_counter )
  2148.                 {
  2149.                     rect.w = Get_Random_Float( 0, random_counter );
  2150.                     rect.h = Get_Random_Float( 0, random_counter );
  2151.  
  2152.                     Color pixel_color = Color( 5 + ( rand() % color.red ), 5 + ( rand() % color.green ), 5 + ( rand() % color.blue ), color.alpha );
  2153.  
  2154.                     // create request
  2155.                     cRectRequest *request = new cRectRequest();
  2156.                     pVideo->Draw_Rect( &rect, 0.9f, &pixel_color, request );
  2157.  
  2158.                     request->render_count = 2;
  2159.  
  2160.                     request->blend_sfactor = GL_ONE_MINUS_SRC_ALPHA;
  2161.                     request->blend_dfactor = GL_ONE_MINUS_SRC_COLOR;
  2162.  
  2163.                     // add request
  2164.                     pRenderer->Add( request );
  2165.                 }
  2166.             }
  2167.  
  2168.             Color rect_color = color;
  2169.             rect_color.alpha = 120 - static_cast<Uint8>(rect_size * 3);
  2170.             // create request
  2171.             cRectRequest *request = new cRectRequest();
  2172.             pVideo->Draw_Rect( NULL, 0.9f, &rect_color, request );
  2173.             
  2174.             request->render_count = 2;
  2175.  
  2176.             request->blend_sfactor = GL_SRC_ALPHA;
  2177.             request->blend_dfactor = GL_ONE_MINUS_SRC_COLOR;
  2178.  
  2179.             // add request
  2180.             pRenderer->Add( request );
  2181.  
  2182.             pVideo->Render();
  2183.             pFramerate->Update();
  2184.         }
  2185.         break;
  2186.     }
  2187.     default:
  2188.         break;  // be happy
  2189.     }
  2190.     
  2191.     pFramerate->Update();
  2192. }
  2193.  
  2194. void Draw_Effect_In( Effect_Fadein effect /* = EFFECT_IN_RANDOM */, float speed /* = 1 */ )
  2195. {
  2196.     // Clear render cache
  2197.     pRenderer->Clear( 1 );
  2198.  
  2199.     if( effect == EFFECT_IN_RANDOM )
  2200.     {
  2201.         effect = static_cast<Effect_Fadein>( ( rand() % (EFFECT_IN_AMOUNT - 1) ) + 1 );
  2202.     }
  2203.  
  2204.     switch( effect )
  2205.     {
  2206.     case EFFECT_IN_BLACK:
  2207.     {
  2208.         Color color = static_cast<Uint8>(0);
  2209.  
  2210.         for( float i = 1; i > 0; i -= ( speed / 30 ) * pFramerate->speedfactor )
  2211.         {
  2212.             color.alpha = static_cast<Uint8>( 255 * i );
  2213.  
  2214.             // create request
  2215.             cRectRequest *request = new cRectRequest();
  2216.             pVideo->Draw_Rect( NULL, 0.9f, &color, request );
  2217.  
  2218.             // add request
  2219.             pRenderer->Add( request );
  2220.  
  2221.             Draw_Game();
  2222.  
  2223.             pVideo->Render();
  2224.  
  2225.             pFramerate->Update();
  2226.             // maximum fps
  2227.             Correct_Frame_Time( 100 );
  2228.         }
  2229.         
  2230.         break;
  2231.     }
  2232.     default:
  2233.         break;  // be happy
  2234.     }
  2235.     
  2236.     pFramerate->Update();
  2237. }
  2238.  
  2239. void Loading_Screen_Init( void )
  2240. {
  2241.     if( CEGUI::WindowManager::getSingleton().isWindowPresent( "loading" ) )
  2242.     {
  2243.         printf( "Warning: Loading Screen already initialized." );
  2244.         return;
  2245.     }
  2246.  
  2247.     CEGUI::Window *guisheet = pGuiSystem->getGUISheet();
  2248.  
  2249.     // hide all windows
  2250.     for( unsigned int i = 0, gui_windows = guisheet->getChildCount(); i < gui_windows; i++ )
  2251.     {
  2252.         guisheet->getChildAtIdx( i )->hide();
  2253.     }
  2254.  
  2255.     // Create loading window
  2256.     CEGUI::Window *loading_window = CEGUI::WindowManager::getSingleton().loadWindowLayout( "loading.layout" );
  2257.     guisheet->addChildWindow( loading_window );
  2258.  
  2259.     // set info text
  2260.     CEGUI::Window *text_default = static_cast<CEGUI::Window *>(CEGUI::WindowManager::getSingleton().getWindow( "text_loading" ));
  2261.     text_default->setText( _("Loading") );
  2262. }
  2263.  
  2264. void Loading_Screen_Draw_Text( string str_info /* = "Loading" */ )
  2265. {
  2266.     // set info text
  2267.     CEGUI::Window *text_default = static_cast<CEGUI::Window *>(CEGUI::WindowManager::getSingleton().getWindow( "text_loading" ));
  2268.     if( !text_default )
  2269.     {
  2270.         printf( "Warning: Loading Screen not initialized." );
  2271.         return;
  2272.     }
  2273.     text_default->setText( reinterpret_cast<const CEGUI::utf8*>(str_info.c_str()) );
  2274.  
  2275.     // clear screen
  2276.     pVideo->Clear_Screen();
  2277.     pVideo->Draw_Rect( NULL, 0.01f, &black );
  2278.  
  2279.     // Render
  2280.     pRenderer->Render();
  2281.     pGuiSystem->renderGUI();
  2282.     pRenderer_GUI->Render();
  2283.     SDL_GL_SwapBuffers();
  2284. }
  2285.  
  2286. void Loading_Screen_Exit( void )
  2287. {
  2288.     CEGUI::Window *loading_window = CEGUI::WindowManager::getSingleton().getWindow( "loading" );
  2289.  
  2290.     // loading window is present
  2291.     if( loading_window )
  2292.     {
  2293.         CEGUI::Window *guisheet = pGuiSystem->getGUISheet();
  2294.  
  2295.         // delete loading window
  2296.         guisheet->removeChildWindow( loading_window );
  2297.         CEGUI::WindowManager::getSingleton().destroyWindow( loading_window );
  2298.  
  2299.         // show windows again
  2300.         // fixme : this should only show the hidden windows again
  2301.         for( unsigned int i = 0, gui_windows = guisheet->getChildCount(); i < gui_windows; i++ )
  2302.         {
  2303.             guisheet->getChildAtIdx( i )->show();
  2304.         }
  2305.     }
  2306. }
  2307.  
  2308. /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
  2309.  
  2310. cVideo *pVideo = NULL;
  2311.  
  2312. CEGUI::OpenGLRenderer *pGuiRenderer = NULL;
  2313. CEGUI::System *pGuiSystem = NULL;
  2314.  
  2315. SDL_Surface *screen = NULL;
  2316.