video.cpp

Go to the documentation of this file.
00001 
00002 //            Copyright (C) 2004-2007 by The Allacrost Project
00003 //                         All Rights Reserved
00004 //
00005 // This code is licensed under the GNU GPL version 2. It is free software
00006 // and you may modify it and/or redistribute it under the terms of this license.
00007 // See http://www.gnu.org/copyleft/gpl.html for details.
00009 
00010 /*!****************************************************************************
00011  * \file    video.cpp
00012  * \author  Raj Sharma, roos@allacrost.org
00013  * \brief   Source file for video engine interface.
00014  *****************************************************************************/
00015 
00016 
00017 #include <cassert>
00018 #include <cstdarg>
00019 #include <math.h>
00020 #include <vector>
00021 
00022 #include "utils.h"
00023 #include "video.h"
00024 #include "context.h"
00025 #include "gui.h"
00026 #include "script.h"
00027 
00028 using namespace std;
00029 
00030 using namespace hoa_utils;
00031 using namespace hoa_video::private_video;
00032 
00033 
00034 
00035 
00036 
00037 template<> hoa_video::GameVideo* Singleton<hoa_video::GameVideo>::_singleton_reference = NULL;
00038 
00039 namespace hoa_video {
00040 
00041 GameVideo* VideoManager = NULL;
00042 bool VIDEO_DEBUG = false;
00043 
00044 //-----------------------------------------------------------------------------
00045 // Static variables
00046 //-----------------------------------------------------------------------------
00047 
00048 Color Color::clear (0.0f, 0.0f, 0.0f, 0.0f);
00049 Color Color::white (1.0f, 1.0f, 1.0f, 1.0f);
00050 Color Color::gray  (0.5f, 0.5f, 0.5f, 1.0f);
00051 Color Color::black (0.0f, 0.0f, 0.0f, 1.0f);
00052 Color Color::red   (1.0f, 0.0f, 0.0f, 1.0f);
00053 Color Color::orange(1.0f, 0.4f, 0.0f, 1.0f);
00054 Color Color::yellow(1.0f, 1.0f, 0.0f, 1.0f);
00055 Color Color::green (0.0f, 1.0f, 0.0f, 1.0f);
00056 Color Color::aqua  (0.0f, 1.0f, 1.0f, 1.0f);
00057 Color Color::blue  (0.0f, 0.0f, 1.0f, 1.0f);
00058 Color Color::violet(0.0f, 0.0f, 1.0f, 1.0f);
00059 Color Color::brown (0.6f, 0.3f, 0.1f, 1.0f);
00060 
00061 
00062 //-----------------------------------------------------------------------------
00063 // Lerp: linearly interpolates value between initial and final
00064 //-----------------------------------------------------------------------------
00065 
00066 float Lerp(float alpha, float initial, float final)
00067 {
00068   return alpha * final + (1.0f-alpha) * initial;
00069 }
00070 
00071 
00072 //-----------------------------------------------------------------------------
00073 // RandomFloat: returns a random float between a and b
00074 //-----------------------------------------------------------------------------
00075 
00076 float RandomFloat(float a, float b)
00077 {
00078   if(a == b)
00079     return a;
00080 
00081   if(a > b)
00082   {
00083     float c = a;  // swap
00084     a = b;
00085     b = c;
00086   }
00087 
00088   float r = float(rand()%10001);
00089 
00090   return a + (b - a) * r / 10000.0f;
00091 }
00092 
00093 
00094 //-----------------------------------------------------------------------------
00095 // RotatePoint: rotates (x,y) around origin by angle radians
00096 //-----------------------------------------------------------------------------
00097 
00098 void RotatePoint(float &x, float &y, float angle)
00099 {
00100   float old_x = x;
00101   float cos_angle = cosf(angle);
00102   float sin_angle = sinf(angle);
00103 
00104   x = x * cos_angle - y * sin_angle;
00105   y = y * cos_angle + old_x * sin_angle;
00106 }
00107 
00108 //-----------------------------------------------------------------------------
00109 // GameVideo
00110 //-----------------------------------------------------------------------------
00111 
00112 GameVideo::GameVideo()
00113 {
00114   _width = 0;
00115   _height = 0;
00116   _fullscreen = false;
00117   _temp_width = 0;
00118   _temp_height = 0;
00119   _temp_fullscreen = false;
00120   _blend = 0;
00121   _x_align = -1;
00122   _y_align = -1;
00123   _x_flip = 0;
00124   _y_flip = 0;
00125   _current_debug_TexSheet = -1;
00126   _uses_lights = false;
00127   _light_overlay = 0xFFFFFFFF;
00128   _last_tex_ID = 0xFFFFFFFF;
00129   _num_tex_switches = 0;
00130   _advanced_display = false;
00131   _fps_display = false;
00132   _x_shake = 0;
00133   _y_shake = 0;
00134   _gamma_value = 1.0f;
00135   _fog_color = Color(1.0f, 1.0f, 1.0f, 1.0f);
00136   _fog_intensity = 0.0f;
00137   _light_color = Color(1.0f, 1.0f, 1.0f, 1.0f);
00138   _current_text_color = Color(1.0f, 1.0f, 1.0f, 1.0f);
00139   _text_shadow = false;
00140   _coord_sys = CoordSys(0.0f, 1024.0f, 0.0f, 768.0f);
00141   _scissor_enabled = false;
00142   _viewport = ScreenRect(0, 0, 100, 100);
00143   _scissor_rect = ScreenRect(0, 0, 1024, 768);
00144   _animation_counter = 0;
00145   _current_frame_diff = 0;
00146   _lightning_active = false;
00147   _lightning_current_time = 0;
00148   _lightning_end_time = 0;
00149   _target = VIDEO_TARGET_SDL_WINDOW;
00150   _x = 0;
00151   _y = 0;
00152 
00153   if (VIDEO_DEBUG)
00154     cout << "VIDEO: GameVideo constructor invoked\n";
00155 
00156   strcpy(_next_temp_file, "00000000");
00157 }
00158 
00159 
00160 //-----------------------------------------------------------------------------
00161 // SingletonInitialize: called to actually initialize the video engine
00162 //-----------------------------------------------------------------------------
00163 
00164 bool GameVideo::SingletonInitialize()
00165 {
00166   if(VIDEO_DEBUG)
00167     cout << "VIDEO: Initializing SDL subsystem\n";
00168 
00169   // Set the window title and icon name
00170   if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
00171   {
00172     fprintf(stderr, "Barf! SDL Video Initialization failed!\n");
00173     exit(1);
00174   }
00175 
00176   // initialize SDL_ttf
00177   if(TTF_Init() < 0)
00178   {
00179     if(VIDEO_DEBUG)
00180       cerr << "VIDEO ERROR: SDL_ttf did not initialize! (TTF_Init() failed)" << endl;
00181     return false;
00182   }
00183 
00184   if(VIDEO_DEBUG)
00185     cout << "VIDEO: setting video mode\n";
00186 
00187   // Get the current system color depth and resolution
00188   const SDL_VideoInfo* video_info (0);
00189   video_info = SDL_GetVideoInfo ();
00190 
00191   hoa_script::ReadScriptDescriptor settings_lua;
00192   static const char *settings_filename = "dat/config/settings.lua";
00193 
00194   if (!settings_lua.OpenFile(settings_filename))
00195   {
00196     fprintf(stderr, "Failed to load file '%s'.\n", settings_filename);
00197     exit(1);
00198   }
00199 
00200   settings_lua.OpenTable("video_settings");
00201   int32  settings_width      = settings_lua.ReadInt("screen_resx");
00202   int32  settings_height     = settings_lua.ReadInt("screen_resy");
00203   bool settings_fullscreen = settings_lua.ReadBool("full_screen");
00204   settings_lua.CloseTable();
00205 
00206   settings_lua.CloseFile();
00207 
00208   if (video_info)
00209   {
00210     // Set the resolution to be the highest possible (lower than the user one)
00211     if (video_info->current_w > settings_width && video_info->current_h > settings_height)
00212     {
00213       SetResolution (settings_width, settings_height);
00214     }
00215     else if (video_info->current_w > 1024 && video_info->current_h > 768)
00216     {
00217       SetResolution (1024, 768);
00218     }
00219     else if (video_info->current_w > 800 && video_info->current_h > 600)
00220     {
00221       SetResolution (800, 600);
00222     }
00223     else
00224     {
00225       SetResolution (640, 480);
00226     }
00227   }
00228   else
00229   {
00230     // Default resoltion if we could not retrieve the resolution of the user
00231     SetResolution(settings_width, settings_height);
00232   }
00233 
00234   SetFullscreen(settings_fullscreen);
00235 
00236   if(!ApplySettings())
00237   {
00238     if(VIDEO_DEBUG)
00239       cerr << "VIDEO ERROR: ChangeMode() failed in GameVideo::SingletonInitialize()!" << endl;
00240     return false;
00241   }
00242 
00243   if(VIDEO_DEBUG)
00244     cout << "VIDEO: Loading default font\n";
00245 
00246   if(!LoadFont("img/fonts/tarnhalo.ttf", "debug_font", 16))
00247   {
00248     if(VIDEO_DEBUG)
00249       cerr << "VIDEO ERROR: Could not load tarnhalo.ttf file!" << endl;
00250     return false;
00251   }
00252 
00253   if(VIDEO_DEBUG)
00254     cout << "VIDEO: Creating texture sheets\n";
00255 
00256 
00257   // create our default texture sheets
00258 
00259   if(!_CreateTexSheet(512, 512, VIDEO_TEXSHEET_32x32, false))
00260   {
00261     if(VIDEO_DEBUG)
00262       cerr << "VIDEO ERROR: could not create default 32x32 tex sheet!" << endl;
00263     return false;
00264   }
00265 
00266   if(!_CreateTexSheet(512, 512, VIDEO_TEXSHEET_32x64, false))
00267   {
00268     if(VIDEO_DEBUG)
00269       cerr << "VIDEO ERROR: could not create default 32x64 tex sheet!" << endl;
00270     return false;
00271   }
00272 
00273   if(!_CreateTexSheet(512, 512, VIDEO_TEXSHEET_64x64, false))
00274   {
00275     if(VIDEO_DEBUG)
00276       cerr << "VIDEO ERROR: could not create default 64x64 tex sheet!" << endl;
00277     return false;
00278   }
00279 
00280   if(!_CreateTexSheet(512, 512, VIDEO_TEXSHEET_ANY,   true))
00281   {
00282     if(VIDEO_DEBUG)
00283       cerr << "VIDEO ERROR: could not create default static  var-sized tex sheet!" << endl;
00284     return false;
00285   }
00286 
00287   if(!_CreateTexSheet(512, 512, VIDEO_TEXSHEET_ANY,   false))
00288   {
00289     if(VIDEO_DEBUG)
00290       cerr << "VIDEO ERROR: could not create default var-sized tex sheet!" << endl;
00291     return false;
00292   }
00293 
00294   // Create and initialize the GUI sub-system
00295   GUIManager = GUISupervisor::SingletonCreate();
00296   GUIManager->SingletonInitialize();
00297 
00298   // make a temp directory and make sure it doesn't contain any files
00299   // (in case the game crashed during a previous run, leaving stuff behind)
00300 
00301   // enable text shadows
00302   EnableTextShadow(true);
00303 
00304   // set default menu cursor
00305 
00306   if(VIDEO_DEBUG)
00307     cout << "VIDEO: Setting default menu cursor" << endl;
00308 
00309   if(!SetDefaultCursor("img/menus/cursor.png"))
00310   {
00311     if(VIDEO_DEBUG)
00312       cerr << "VIDEO ERROR: problem loading default menu cursor" << endl;
00313   }
00314 
00315 
00316   if(VIDEO_DEBUG)
00317     cout << "VIDEO: Erasing the screen\n";
00318 
00319 
00320   // set up the screen for rendering
00321   if(!Clear())
00322   {
00323     if(VIDEO_DEBUG)
00324       cerr << "VIDEO ERROR: first call to Clear() in GameVideo::SingletonInitialize() failed!" << endl;
00325     return false;
00326   }
00327 
00328   if(!Display(0))
00329   {
00330     if(VIDEO_DEBUG)
00331       cerr << "VIDEO ERROR: Display() in GameVideo::SingletonInitialize() failed!" << endl;
00332     return false;
00333   }
00334 
00335   if(!Clear())
00336   {
00337     if(VIDEO_DEBUG)
00338       cerr << "VIDEO ERROR: second call to Clear() in GameVideo::SingletonInitialize() failed!" << endl;
00339     return false;
00340   }
00341 
00342   if(VIDEO_DEBUG)
00343     cout << "VIDEO: GameVideo::SingletonInitialize() returned successfully" << endl;
00344 
00345   _rectangle_image.SetFilename("");
00346   if (!_rectangle_image.Load())
00347   {
00348     if(VIDEO_DEBUG)
00349       cerr << "VIDEO ERROR: quad StillImage for rendering rectangles could not be created" << endl;
00350     return false;
00351   }
00352 
00353   return true;
00354 }
00355 
00356 
00357 //-----------------------------------------------------------------------------
00358 // MakeScreenshot: create a screenshot and save as screenshot.jpg
00359 //-----------------------------------------------------------------------------
00360 
00361 bool GameVideo::MakeScreenshot()
00362 {
00363   private_video::ImageLoadInfo buffer;
00364 
00365   if(VIDEO_DEBUG)
00366     cout << "VIDEO: Entering MakeScreenshot()" << endl;
00367 
00368   // Retrieve width/height of the viewport
00369   GLint viewport_dimensions[4];
00370   glGetIntegerv(GL_VIEWPORT, viewport_dimensions);
00371 
00372   // Buffer to store the image before it is flipped
00373   buffer.width = viewport_dimensions[2];
00374   buffer.height = viewport_dimensions[3];
00375   buffer.pixels = malloc(buffer.width * buffer.height * 3);
00376 
00377   // Read pixel data
00378   glReadPixels(0, 0, buffer.width, buffer.height, GL_RGB, GL_UNSIGNED_BYTE, buffer.pixels);
00379 
00380   if(glGetError())
00381   {
00382     if(VIDEO_DEBUG)
00383       cerr << "VIDEO_DEBUG: glReadPixels() returned an error inside GameVideo::CaptureScreen!" << endl;
00384 
00385     free(buffer.pixels);
00386     return false;
00387   }
00388 
00389   // Flip vertically the image
00390   void* buffer_temp = malloc(buffer.width * buffer.height * 3);
00391   for (int32 i=0; i<buffer.height; ++i)
00392   {
00393     memcpy ((uint8*)buffer_temp+i*buffer.width*3, (uint8*)buffer.pixels+(buffer.height-i-1)*buffer.width*3, buffer.width*3);
00394   }
00395   free (buffer.pixels);
00396   buffer.pixels = buffer_temp;
00397 
00398   _SaveJpeg("screenshot.jpg", buffer);
00399 
00400   free(buffer.pixels);
00401 
00402   return true;
00403 }
00404 
00405 
00406 //-----------------------------------------------------------------------------
00407 // ~GameVideo
00408 //-----------------------------------------------------------------------------
00409 
00410 GameVideo::~GameVideo()
00411 {
00412   if (VIDEO_DEBUG)
00413     cout << "VIDEO: GameVideo destructor invoked" << endl;
00414 
00415   // destroy particle manager
00416   _particle_manager.Destroy();
00417 
00418   // delete GUI
00419   GUIManager->SingletonDestroy();
00420 
00421   // delete font properties
00422 
00423   map<string, FontProperties *>::iterator iFontProp    = _font_map.begin();
00424   map<string, FontProperties *>::iterator iFontPropEnd = _font_map.end();
00425 
00426   while(iFontProp != _font_map.end())
00427   {
00428     FontProperties *fp = iFontProp->second;
00429 
00430     if(fp->ttf_font)
00431       TTF_CloseFont(fp->ttf_font);
00432 
00433     if(fp->glyph_cache)
00434     {
00435       for(std::map<uint16, FontGlyph *>::iterator glyphitr = fp->glyph_cache->begin(); glyphitr != fp->glyph_cache->end(); glyphitr++)
00436       {
00437         // Possibly de-init the GL texture
00438         delete (*glyphitr).second;
00439       }
00440 
00441       delete fp->glyph_cache;
00442     }
00443 
00444     delete fp;
00445     ++iFontProp;
00446   }
00447 
00448 
00449   // uninitialize SDL_ttf
00450   TTF_Quit();
00451 
00452   // delete texture sheets
00453   vector<TexSheet *>::iterator iSheet      = _tex_sheets.begin();
00454   vector<TexSheet *>::iterator iSheetEnd   = _tex_sheets.end();
00455 
00456   while(iSheet != iSheetEnd)
00457   {
00458     delete *iSheet;
00459     ++iSheet;
00460   }
00461 
00462   // delete images
00463   map<string, Image *>::iterator iImage     = _images.begin();
00464   map<string, Image *>::iterator iImageEnd  = _images.end();
00465 
00466   while(iImage != iImageEnd)
00467   {
00468     delete iImage->second;
00469     ++iImage;
00470   }
00471 }
00472 
00473 
00474 //-----------------------------------------------------------------------------
00475 // SetCoordSys: sets the current coordinate system
00476 //-----------------------------------------------------------------------------
00477 
00478 void GameVideo::SetCoordSys(const CoordSys &coordinate_system)
00479 {
00480   _coord_sys = coordinate_system;
00481 
00482   glMatrixMode(GL_PROJECTION);
00483   glLoadIdentity();
00484   glOrtho(_coord_sys.GetLeft(), _coord_sys.GetRight(), _coord_sys.GetBottom(), _coord_sys.GetTop(), -1, 1);
00485 
00486   // Removed this code bleow
00487   glMatrixMode(GL_MODELVIEW);
00488   glLoadIdentity();
00489 }
00490 
00491 
00492 //-----------------------------------------------------------------------------
00493 // SetCoordSys: sets the current coordinate system
00494 //-----------------------------------------------------------------------------
00495 
00496 void GameVideo::SetCoordSys
00497 (
00498   float left,
00499   float right,
00500   float bottom,
00501   float top
00502 )
00503 {
00504   SetCoordSys(CoordSys(left, right, bottom, top));
00505 }
00506 
00507 
00508 //-----------------------------------------------------------------------------
00509 // SetDrawFlags: used for controlling various flags like blending, flipping, etc.
00510 //-----------------------------------------------------------------------------
00511 
00512 void GameVideo::SetDrawFlags(int32 first_flag, ...)
00513 {
00514   int32 flag = first_flag;
00515   va_list args;
00516 
00517   va_start(args, first_flag);
00518   while( flag != 0 )
00519   {
00520     switch (flag) {
00521     case VIDEO_X_LEFT: _x_align=-1; break;
00522     case VIDEO_X_CENTER: _x_align=0; break;
00523     case VIDEO_X_RIGHT: _x_align=1; break;
00524 
00525     case VIDEO_Y_TOP: _y_align=1; break;
00526     case VIDEO_Y_CENTER: _y_align=0; break;
00527     case VIDEO_Y_BOTTOM: _y_align=-1; break;
00528 
00529     case VIDEO_X_NOFLIP: _x_flip=0; break;
00530     case VIDEO_X_FLIP: _x_flip=1; break;
00531 
00532     case VIDEO_Y_NOFLIP: _y_flip=0; break;
00533     case VIDEO_Y_FLIP: _y_flip=1; break;
00534 
00535     case VIDEO_NO_BLEND: _blend=0; break;
00536     case VIDEO_BLEND: _blend=1; break;
00537     case VIDEO_BLEND_ADD: _blend=2; break;
00538 
00539     default:
00540       if(VIDEO_DEBUG)
00541         cerr << "Unknown flag " << flag << " passed to SetDrawFlags()\n";
00542       break;
00543     }
00544     flag = va_arg(args, int32);
00545   }
00546   va_end(args);
00547 }
00548 
00549 
00550 //-----------------------------------------------------------------------------
00551 // ApplySettings: after you change the resolution and/or fullscreen settings,
00552 //                calling this function actually applies those settings
00553 //-----------------------------------------------------------------------------
00554 
00555 bool GameVideo::ApplySettings()
00556 {
00557   // Used by the game Hero of Allacrost, an SDL application
00558   if (_target == VIDEO_TARGET_SDL_WINDOW) {
00559     // Losing GL context, so unload images first
00560     if  (!UnloadTextures())
00561     {
00562       cerr << "VIDEO: Failed to delete OpenGL textures during a context change" << endl;
00563     }
00564 
00565     int32 flags = SDL_OPENGL;
00566 
00567     if (_temp_fullscreen == true) {
00568       flags |= SDL_FULLSCREEN;
00569     }
00570 
00571     SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
00572     SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
00573     SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
00574     SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
00575     SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
00576     SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
00577     
00578     // set up multisampling
00579     SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 2);
00580     SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
00581     
00582     // set up vsync
00583     SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);
00584 
00585     if (!SDL_SetVideoMode(_temp_width, _temp_height, 0, flags)) {
00586     // RGB values of 1 for each and 8 for depth seemed to be sufficient.
00587     // 565 and 16 here because it works with them on this computer.
00588     // NOTE from prophile: this ought to be changed to 5558
00589       SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
00590       SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
00591       SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
00592       SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
00593       SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0);
00594       
00595       // kill multisampling
00596       SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
00597       SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
00598       
00599       // cancel vsync
00600       SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 0);
00601 
00602       if (!SDL_SetVideoMode(_temp_width, _temp_height, 0, flags)) {
00603         if (VIDEO_DEBUG) {
00604           cerr << "VIDEO ERROR: SDL_SetVideoMode() failed with error: " << SDL_GetError() << endl;
00605         }
00606         _temp_fullscreen = _fullscreen;
00607         _temp_width      = _width;
00608         _temp_height     = _height;
00609 
00610         if (_width > 0) { // Test to see if we already had a valid video mode
00611           ReloadTextures();
00612         }
00613         return false;
00614       }
00615     }
00616     
00617     // turn off writing to the depth buffer
00618     glDepthMask ( GL_FALSE );
00619 
00620     _width      = _temp_width;
00621     _height     = _temp_height;
00622     _fullscreen = _temp_fullscreen;
00623 
00624     ReloadTextures();
00625 
00626     EnableFog(_fog_color, _fog_intensity);
00627 
00628     return true;
00629   } // if (_target == VIDEO_TARGET_SDL_WINDOW)
00630 
00631   // Used by the Allacrost editor, which uses QT4
00632   else if (_target == VIDEO_TARGET_QT_WIDGET)
00633   {
00634     _width      = _temp_width;
00635     _height     = _temp_height;
00636     _fullscreen = _temp_fullscreen;
00637 
00638     return true;
00639   }
00640 
00641   return false;
00642 }
00643 
00644 
00645 //-----------------------------------------------------------------------------
00646 // SetViewport: set the rectangle of the screen onto which all drawing maps to,
00647 //              the arguments are percentages so 0, 0, 100, 100 would mean the
00648 //              whole screen
00649 //-----------------------------------------------------------------------------
00650 
00651 void GameVideo::SetViewport(float left, float right, float bottom, float top)
00652 {
00653   assert(left < right);
00654   assert(bottom < top);
00655 
00656   int32 l=int32(left*_width*.01f);
00657   int32 b=int32(bottom*_height*.01f);
00658   int32 r=int32(right*_width*.01f);
00659   int32 t=int32(top*_height*.01f);
00660 
00661   if (l<0) l=0;
00662   if (b<0) b=0;
00663   if (r>_width) r=_width;
00664   if (t>_height) t=_height;
00665 
00666   _viewport = ScreenRect(l, b, r-l+1, t-b+1);
00667   glViewport(l, b, r-l+1, t-b+1);
00668 }
00669 
00670 
00671 //-----------------------------------------------------------------------------
00672 // Clear: clear the screen to black, it doesnt clear other buffers, that can be
00673 //        done by videostates that use them
00674 //-----------------------------------------------------------------------------
00675 
00676 bool GameVideo::Clear()
00677 {
00678   if(_uses_lights)
00679     return Clear(_light_color);
00680   else
00681     return Clear(Color::black);
00682 }
00683 
00684 
00685 
00686 //-----------------------------------------------------------------------------
00687 // Clear: clear the screen to given color, it doesnt clear other buffers, that can be
00688 //        done by videostates that use them
00689 //-----------------------------------------------------------------------------
00690 
00691 bool GameVideo::Clear(const Color &c)
00692 {
00693   SetViewport(0,100,0,100);
00694   glClearColor(c[0], c[1], c[2], c[3]);
00695   glClear(GL_COLOR_BUFFER_BIT);
00696 
00697   _num_tex_switches = 0;
00698 
00699   if(glGetError())
00700     return false;
00701 
00702   return true;
00703 }
00704 
00705 //-----------------------------------------------------------------------------
00706 // AccumulateLights: if real lights are enabled, then you must call DrawLight()
00707 //                   for each light, and then call AccumulateLights() to
00708 //                   save the lighting information into the overlay
00709 //-----------------------------------------------------------------------------
00710 /*bool GameVideo::AccumulateLights()
00711 {
00712   if(_light_overlay != 0xFFFFFFFF)
00713   {
00714     _BindTexture(_light_overlay);
00715     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, 1024, 1024, 0);
00716   }
00717 
00718   return true;
00719 }*/
00720 
00721 
00722 //-----------------------------------------------------------------------------
00723 // Display: if running in double buffered mode then flip the other buffer to the
00724 //          screen
00725 //-----------------------------------------------------------------------------
00726 
00727 bool GameVideo::Display(int32 frame_time)
00728 {
00729   // update particle effects
00730   _particle_manager.Update(frame_time);
00731 
00732   // update shaking effect
00733   _PushContext();
00734   SetCoordSys(0, 1024, 0, 768);
00735   _UpdateShake(frame_time);
00736 
00737   // update lightning timer
00738   _lightning_current_time += frame_time;
00739 
00740   if(_lightning_current_time > _lightning_end_time)
00741     _lightning_active = false;
00742 
00743   // show an overlay over the screen if we're fading
00744   if(_fader.ShouldUseFadeOverlay())
00745   {
00746     Color c = _fader.GetFadeOverlayColor();
00747     StillImage fade_overlay;
00748     fade_overlay.SetDimensions(1024.0f, 768.0f);
00749     fade_overlay.SetColor(c);
00750     LoadImage(fade_overlay);
00751     SetDrawFlags(VIDEO_X_LEFT, VIDEO_Y_BOTTOM, 0);
00752     PushState();
00753     Move(0, 0);
00754     DrawImage(fade_overlay);
00755     PopState();
00756     DeleteImage(fade_overlay);
00757   }
00758 
00759   // this must be called before DrawFPS and all, because we only
00760   // want to count texture switches related to the game itself, not the
00761   // ones used to draw debug text and things like that.
00762 
00763   if(_advanced_display)
00764     _DEBUG_ShowAdvancedStats();
00765 
00766   if(_fps_display)
00767     DrawFPS(frame_time);
00768 
00769   if(!_DEBUG_ShowTexSheet())
00770   {
00771     if(VIDEO_DEBUG)
00772     {
00773       // keep track of whether we've already shown this error.
00774       // If we've shown it once, stop showing it so we don't clog up
00775       // the debug output with the same message 1000 times
00776       static bool has_failed = false;
00777 
00778       if(!has_failed)
00779       {
00780         cerr << "VIDEO ERROR: _DEBUG_ShowTexSheet() failed\n";
00781         has_failed = true;
00782       }
00783     }
00784   }
00785 
00786   _PopContext();
00787 
00788   SDL_GL_SwapBuffers();
00789 
00790   _fader.Update(frame_time);
00791 
00792   // update animation timers
00793 
00794   int32 old_frame_index = _animation_counter / VIDEO_ANIMATION_FRAME_PERIOD;
00795   _animation_counter += frame_time;
00796   int32 current_frame_index = _animation_counter / VIDEO_ANIMATION_FRAME_PERIOD;
00797 
00798   _current_frame_diff = current_frame_index - old_frame_index;
00799 
00800   return true;
00801 }
00802 
00803 
00804 //-----------------------------------------------------------------------------
00805 // IsFullscreen: returns true if we're in fullscreen mode, false if windowed
00806 //-----------------------------------------------------------------------------
00807 
00808 bool GameVideo::IsFullscreen()
00809 {
00810   return _fullscreen;
00811 }
00812 
00813 
00814 //-----------------------------------------------------------------------------
00815 // SetFullscreen: if you pass in true, makes the game fullscreen, otherwise
00816 //                makes it windowed. Returns false on failure.
00817 // NOTE: to actually apply the change, call ApplySettings()
00818 //-----------------------------------------------------------------------------
00819 
00820 bool GameVideo::SetFullscreen(bool fullscreen)
00821 {
00822   _temp_fullscreen = fullscreen;
00823   return true;
00824 }
00825 
00826 
00827 //-----------------------------------------------------------------------------
00828 // ToggleFullscreen: if game is currently windowed, makes it fullscreen and
00829 //                   vica versa. Returns false on failure.
00830 // NOTE: to actually apply the change, call ApplySettings()
00831 //-----------------------------------------------------------------------------
00832 
00833 bool GameVideo::ToggleFullscreen()
00834 {
00835   return SetFullscreen(!_temp_fullscreen);
00836 }
00837 
00838 
00839 //-----------------------------------------------------------------------------
00840 // SetResolution: sets the resolution
00841 // NOTE: to actually apply the change, call ApplySettings()
00842 //-----------------------------------------------------------------------------
00843 
00844 bool GameVideo::SetResolution(int32 width, int32 height)
00845 {
00846   if (width <= 0 || height <= 0)
00847   {
00848     if (VIDEO_DEBUG)
00849       cerr << "VIDEO ERROR: invalid width and/or height passed to SetResolution!" << endl;
00850     return false;
00851   }
00852 
00853   _temp_width  = width;
00854   _temp_height = height;
00855   return true;
00856 }
00857 
00858 
00859 //-----------------------------------------------------------------------------
00860 // _DEBUG_ShowAdvancedStats: display # of tex switches and other useful runtime
00861 //                           statistics
00862 //-----------------------------------------------------------------------------
00863 
00864 bool GameVideo::_DEBUG_ShowAdvancedStats()
00865 {
00866   // display to screen
00867   char text[50];
00868   sprintf(text, "Switches: %d\nParticles: %d", _num_tex_switches, _particle_manager.GetNumParticles());
00869 
00870   if( !SetFont("debug_font"))
00871     return false;
00872 
00873   Move(896.0f, 690.0f);
00874   if( !DrawText(text))
00875     return false;
00876 
00877   return true;
00878 }
00879 
00880 
00881 
00882 //-----------------------------------------------------------------------------
00883 // Move: move relativly x+=rx, y+=ry
00884 //-----------------------------------------------------------------------------
00885 
00886 void GameVideo::Move(float tx, float ty)
00887 {
00888 #ifndef NDEBUG
00889   GLint matrix_mode;
00890   glGetIntegerv(GL_MATRIX_MODE, &matrix_mode);
00891   assert(matrix_mode == GL_MODELVIEW);
00892 #endif
00893   glLoadIdentity();
00894   glTranslatef(tx, ty, 0);
00895   _x = tx;
00896   _y = ty;
00897 }
00898 
00899 //-----------------------------------------------------------------------------
00900 // MoveRelative:
00901 //-----------------------------------------------------------------------------
00902 void GameVideo::MoveRelative(float tx, float ty)
00903 {
00904 #ifndef NDEBUG
00905   GLint matrix_mode;
00906   glGetIntegerv(GL_MATRIX_MODE, &matrix_mode);
00907   assert(matrix_mode == GL_MODELVIEW);
00908 #endif
00909   glTranslatef(tx, ty, 0);
00910   _x += tx;
00911   _y += ty;
00912 }
00913 
00914 //-----------------------------------------------------------------------------
00915 // GetDrawPosition: Get the location that the draw cursor is currently located at.
00916 //-----------------------------------------------------------------------------
00917 void GameVideo::GetDrawPosition(float &x, float &y)
00918 {
00919   x = _x;
00920   y = _y;
00921 }
00922 
00923 //-----------------------------------------------------------------------------
00924 // Rotate: rotates the coordinate axes anticlockwise by acAngle degrees, think
00925 //         about this CARFULLY before you call it
00926 //-----------------------------------------------------------------------------
00927 
00928 void GameVideo::Rotate(float ac_angle)
00929 {
00930 #ifndef NDEBUG
00931   GLint matrix_mode;
00932   glGetIntegerv(GL_MATRIX_MODE, &matrix_mode);
00933   assert(matrix_mode == GL_MODELVIEW);
00934 #endif
00935   glRotatef(ac_angle, 0, 0, 1);
00936 }
00937 
00938 
00939 //-----------------------------------------------------------------------------
00940 // Scale: scales the coordinate axes by xScale and yScale respectively
00941 //-----------------------------------------------------------------------------
00942 
00943 void GameVideo::Scale(float x, float y)
00944 {
00945 #ifndef NDEBUG
00946   GLint matrix_mode;
00947   glGetIntegerv(GL_MATRIX_MODE, &matrix_mode);
00948   assert(matrix_mode == GL_MODELVIEW);
00949 #endif
00950 
00951   glScalef(x, y, 1.0f);
00952 }
00953 
00954 
00955 
00956 //-----------------------------------------------------------------------------
00957 // PushState: saves your current position in a stack, bewarned this stack is
00958 //            small ~32 so use it wisely
00959 //-----------------------------------------------------------------------------
00960 
00961 void GameVideo::PushState()
00962 {
00963   _PushContext();
00964 }
00965 
00966 
00967 //-----------------------------------------------------------------------------
00968 // PopState: restores last position, read PushState()
00969 //-----------------------------------------------------------------------------
00970 
00971 void GameVideo::PopState()
00972 {
00973   _PopContext();
00974 }
00975 
00976 
00977 //-----------------------------------------------------------------------------
00978 // Menu Methods
00979 //-----------------------------------------------------------------------------
00980 
00981 bool GameVideo::LoadMenuSkin(std::string skin_name, std::string border_image, std::string background_image, bool make_default)
00982 {
00983   return GUIManager->LoadMenuSkin(skin_name, border_image, background_image,
00984     Color::clear, Color::clear, Color::clear, Color::clear, make_default);
00985 }
00986 
00987 
00988 
00989 bool GameVideo::LoadMenuSkin(std::string skin_name, std::string border_image, Color background_color, bool make_default)
00990 {
00991   return GUIManager->LoadMenuSkin(skin_name, border_image, "",
00992     background_color, background_color, background_color, background_color, make_default);
00993 }
00994 
00995 
00996 
00997 bool GameVideo::LoadMenuSkin(std::string skin_name, std::string border_image, Color top_left, Color top_right,
00998   Color bottom_left, Color bottom_right, bool make_default)
00999 {
01000   return GUIManager->LoadMenuSkin(skin_name, border_image, "",
01001     top_left, top_right, bottom_left, bottom_right, make_default);
01002 }
01003 
01004 
01005 
01006 bool GameVideo::LoadMenuSkin(std::string skin_name, std::string border_image, std::string background_image,
01007   Color background_color, bool make_default)
01008 {
01009   return GUIManager->LoadMenuSkin(skin_name, border_image, background_image,
01010     background_color, background_color, background_color, background_color, make_default);
01011 }
01012 
01013 
01014 
01015 bool GameVideo::LoadMenuSkin(std::string skin_name, std::string border_image, std::string background_image,
01016   Color top_left, Color top_right, Color bottom_left, Color bottom_right, bool make_default)
01017 {
01018   return GUIManager->LoadMenuSkin(skin_name, border_image, background_image,
01019     top_left, top_right, bottom_left, bottom_right, make_default);
01020 }
01021 
01022 //-----------------------------------------------------------------------------
01023 // _BindTexture: wraps call to glBindTexture(), plus some extra checking to
01024 //              discard the call if we try to bind the same texture twice
01025 //-----------------------------------------------------------------------------
01026 
01027 bool GameVideo::_BindTexture(GLuint tex_ID)
01028 {
01029   if(tex_ID != _last_tex_ID)
01030   {
01031     _last_tex_ID = tex_ID;
01032     glBindTexture(GL_TEXTURE_2D, tex_ID);
01033     ++_num_tex_switches;
01034   }
01035 
01036   if(glGetError())
01037     return false;
01038 
01039   return true;
01040 }
01041 
01042 
01043 //-----------------------------------------------------------------------------
01044 // ToggleAdvancedDisplay: toggles advanced display. When advanced display is
01045 //                        enabled, you can see things like how many texture
01046 //                        switches occurred during the current frame, etc.
01047 //-----------------------------------------------------------------------------
01048 
01049 bool GameVideo::ToggleAdvancedDisplay()
01050 {
01051   _advanced_display = !_advanced_display;
01052   return true;
01053 }
01054 
01055 
01056 
01057 //-----------------------------------------------------------------------------
01058 // EnableSceneLighting: sets lighting parameters for the scene, actually just a color
01059 //              unless we change the lighting system later on.
01060 //              NOTE: the color's alpha value (i.e. color[3]) must be 1.0f
01061 //-----------------------------------------------------------------------------
01062 bool GameVideo::EnableSceneLighting(const Color &color)
01063 {
01064   _light_color = color;
01065 
01066   if(color[3] != 1.0f)
01067   {
01068     if(VIDEO_DEBUG)
01069       cerr << "VIDEO ERROR: color passed to EnableSceneLighting() had alpha other than 1.0f!" << endl;
01070     _light_color[3] = 1.0f;
01071   }
01072 
01073   return true;
01074 }
01075 
01076 //-----------------------------------------------------------------------------
01077 // DisableSceneLighting: Turn off scene lighting
01078 //-----------------------------------------------------------------------------
01079 void GameVideo::DisableSceneLighting()
01080 {
01081   _light_color = Color::white;
01082 }
01083 
01084 //-----------------------------------------------------------------------------
01085 // GetLighting: returns the scene lighting color
01086 //-----------------------------------------------------------------------------
01087 
01088 Color &GameVideo::GetSceneLightingColor()
01089 {
01090   return _light_color;
01091 }
01092 
01093 
01094 
01095 //-----------------------------------------------------------------------------
01096 // EnableFog: sets fog parameters. Fog color is usually gray, and intensity can
01097 //         be from 0.0 (no fog) to 1.0 (entire screen is gray)
01098 //         To turn off fog, just call this function with intensity of 0.0f
01099 //-----------------------------------------------------------------------------
01100 bool GameVideo::EnableFog(const Color &color, float intensity)
01101 {
01102   // check if intensity is within bounds. If not, clamp it but display an
01103   // error message
01104 
01105   if(intensity < 0.0f)
01106   {
01107     intensity = 0.0f;
01108     if(VIDEO_DEBUG)
01109       cerr << "VIDEO ERROR: negative intensity passed to SetFog()" << endl;
01110   }
01111   else if(intensity > 1.0f)
01112   {
01113     intensity = 1.0f;
01114     if(VIDEO_DEBUG)
01115       cerr << "VIDEO ERROR: intensity larger than 1.0f passed to SetFog()" << endl;
01116   }
01117 
01118   // set the parameters
01119   _fog_color = color;
01120   _fog_intensity = intensity;
01121 
01122   // apply the new settings with OpenGL
01123   if(intensity == 0.0f)
01124   {
01125     glDisable(GL_FOG);
01126   }
01127   else
01128   {
01129     glEnable(GL_FOG);
01130     glHint(GL_FOG_HINT, GL_DONT_CARE);
01131     glFogf(GL_FOG_MODE, GL_LINEAR);
01132     glFogf(GL_FOG_START, 0.0f - intensity);
01133     glFogf(GL_FOG_END, 1.0f - intensity);
01134     glFogfv(GL_FOG_COLOR, (GLfloat *)color.GetColors());
01135   }
01136 
01137   return true;
01138 }
01139 
01140 //-----------------------------------------------------------------------------
01141 // DisableFog: Turns off fog
01142 //-----------------------------------------------------------------------------
01143 void GameVideo::DisableFog()
01144 {
01145   glDisable(GL_FOG);
01146   _fog_intensity = 0.0f;
01147 }
01148 
01149 
01150 //-----------------------------------------------------------------------------
01151 // SetTransform: set current OpenGL modelview matrix to the 4x4 matrix (16 values)
01152 //               that's passed in
01153 //-----------------------------------------------------------------------------
01154 void GameVideo::SetTransform(float m[16])
01155 {
01156   glMatrixMode(GL_MODELVIEW);
01157   glLoadIdentity();
01158   glLoadMatrixf(m);
01159 }
01160 
01161 //-----------------------------------------------------------------------------
01162 // EnablePointLights: call if this map uses point lights
01163 //-----------------------------------------------------------------------------
01164 bool GameVideo::EnablePointLights()
01165 {
01166   _light_overlay = _CreateBlankGLTexture(1024, 1024);
01167 
01168   _uses_lights = true;
01169 
01170   return true;
01171 }
01172 
01173 //-----------------------------------------------------------------------------
01174 // DisablePointLights: call when done with point lights
01175 //-----------------------------------------------------------------------------
01176 void GameVideo::DisablePointLights()
01177 {
01178   if(_light_overlay != 0xFFFFFFFF)
01179   {
01180     _DeleteTexture(_light_overlay);
01181   }
01182 
01183   _light_overlay = 0xFFFFFFFF;
01184 
01185   _uses_lights = false;
01186 }
01187 
01188 
01189 //-----------------------------------------------------------------------------
01190 // ApplyLightingOverlay: call after all map images are drawn to apply lighting.
01191 //                       All menu and text rendering should occur AFTER this
01192 //                       call, so that they are not affected by lighting.
01193 //-----------------------------------------------------------------------------
01194 bool GameVideo::ApplyLightingOverlay()
01195 {
01196   if(_light_overlay != 0xFFFFFFFF)
01197   {
01198     // Copy light overlay to opengl texture
01199     _BindTexture(_light_overlay);
01200     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, 1024, 1024, 0);
01201 
01202     CoordSys temp_CoordSys = _coord_sys;
01203 
01204     SetCoordSys(0.0f, 1.0f, 0.0f, 1.0f);
01205     float xlo = 0.0f, ylo = 0.0f, xhi = 1.0f, yhi = 1.0f;
01206     glEnable(GL_TEXTURE_2D);
01207 
01208     float mx = _width / 1024.0f;
01209     float my = _height / 1024.0f;
01210 
01211     glEnable(GL_BLEND);
01212     glBlendFunc(GL_DST_COLOR, GL_ZERO);
01213 
01214     _BindTexture(_light_overlay);
01215     
01216     GLfloat vertices[8] = { xlo, ylo, xhi, ylo, xhi, yhi, xlo, yhi };
01217     GLfloat tex_coords[8] = { 0.0f, 0.0f, mx, 0.0f, mx, my, 0.0f, my };
01218     
01219     glEnableClientState ( GL_VERTEX_ARRAY );
01220     glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
01221     
01222     glVertexPointer ( 2, GL_FLOAT, 0, vertices );
01223     glTexCoordPointer ( 2, GL_FLOAT, 0, tex_coords );
01224     
01225     glDrawArrays ( GL_QUADS, 0, 4 );
01226     
01227     glDisableClientState ( GL_TEXTURE_COORD_ARRAY );
01228     glDisableClientState ( GL_VERTEX_ARRAY );
01229     
01230     /*glBegin(GL_QUADS);
01231     glTexCoord2f(0.0f, 0.0f);
01232     glVertex2f(xlo, ylo); //bl
01233     glTexCoord2f(mx, 0.0f);
01234     glVertex2f(xhi, ylo); //br
01235     glTexCoord2f(mx, my);
01236     glVertex2f(xhi, yhi);//tr
01237     glTexCoord2f(0.0f, my);
01238     glVertex2f(xlo, yhi);//tl
01239     glEnd();*/
01240     SetCoordSys(temp_CoordSys.GetLeft(), temp_CoordSys.GetRight(), temp_CoordSys.GetBottom(), temp_CoordSys.GetTop());
01241   }
01242 
01243   return true;
01244 }
01245 
01246 
01247 //-----------------------------------------------------------------------------
01248 // CaptureScreen: captures the contents of the screen and saves it to an image
01249 //                descriptor. Note that this function ignores the filename
01250 //                and isStatic properties of the image descriptor. It will
01251 //                obey the color property though, in case you want to create
01252 //                a funky colored image of the screen...
01253 //
01254 //                NOTE: this function assumes that you will never have two
01255 //                      captured screens loaded at the same time. If it detects
01256 //                      that you try to capture the screen even though a
01257 //                      capture is already in memory, it is considered an error
01258 //-----------------------------------------------------------------------------
01259 
01260 bool GameVideo::CaptureScreen(StillImage &id)
01261 {
01262   if(VIDEO_DEBUG)
01263     cout << "VIDEO: Entering CaptureScreen()" << endl;
01264 
01265   // Retrieve width/height of the viewport
01266   GLint viewport_dimensions[4];
01267   glGetIntegerv(GL_VIEWPORT, viewport_dimensions);
01268 
01269   // Set up the screen rectangle to copy
01270   int32 width  = viewport_dimensions[2];
01271   int32 height = viewport_dimensions[3];
01272   ScreenRect    screen_rect(0, height, width, height);
01273 
01274   //TEMP TAGS
01275   // create an Image structure and store it our std::map of images
01276   if (id._filename == "")
01277     id._filename = "captured_screen";
01278   Image *new_image = new Image(id._filename, "<T>", width, height, false);
01279 
01280   // Try to create a texture sheet of screen size (rounded up)
01281   TexSheet *sheet = _CreateTexSheet(RoundUpPow2(width), RoundUpPow2(height), VIDEO_TEXSHEET_ANY, false);
01282 
01283   if(!sheet)
01284   {
01285     // This should never happen, unless we run out of memory or the
01286     // size of the screen texture is larger than the max available
01287     if (VIDEO_DEBUG)
01288       cerr << "VIDEO_DEBUG: GameVideo::_InsertImageInTexSheet() returned NULL!" << endl;
01289 
01290     return false;
01291   }
01292   if (!sheet->tex_mem_manager->Insert(new_image))
01293   {
01294     if (VIDEO_DEBUG)
01295       cerr << "VIDEO_DEBUG: TexMemMgr->Insert(image) returned NULL in " << __FUNCTION__ << endl;
01296     _RemoveSheet(sheet);
01297     return false;
01298   }
01299 
01300   if (!sheet->CopyScreenRect(0, 0, screen_rect))
01301   {
01302     if (VIDEO_DEBUG)
01303       cerr << "VIDEO_DEBUG: TexSheet->CopyScreenRect() failed in " << __FUNCTION__ << endl;
01304     _RemoveSheet(sheet);
01305     return false;
01306   }
01307 
01308   new_image->ref_count = 1;
01309 
01310   // if width or height are zero, that means to use the dimensions of image
01311   if(id._width == 0.0f)
01312     id._width  = (float)width;
01313 
01314   if(id._height == 0.0f)
01315     id._height = (float)height;
01316 
01317   // Store the new image element (flipped y)
01318   ImageElement element(new_image, 0, 0, 0.0f, 1.0f, 1.0f, 0.0f, id._width, id._height, id._color);
01319   id._elements.push_back(element);
01320 
01321   // Store the image in our std::map
01322   _images[id._filename] = new_image;
01323 
01324   return true;
01325 }
01326 
01327 
01328 //-----------------------------------------------------------------------------
01329 // SetGamma: Sets a new gamma value using SDL_SetGamma()
01330 //-----------------------------------------------------------------------------
01331 void GameVideo::SetGamma(float value)
01332 {
01333   _gamma_value = value;
01334 
01335   // Limit min/max gamma
01336   if (_gamma_value > 2.0f)
01337   {
01338     if(VIDEO_DEBUG) cout << "VIDEO: Tried to set gamma over 2.0f!" << endl;
01339     _gamma_value = 2.0f;
01340   }
01341   else if (_gamma_value < 0.0f)
01342   {
01343     if(VIDEO_DEBUG) cout << "VIDEO: Tried to set gamma below 0.0f!" << endl;
01344     _gamma_value = 0.0f;
01345   }
01346 
01347   SDL_SetGamma(_gamma_value, _gamma_value, _gamma_value);
01348 }
01349 
01350 
01351 //-----------------------------------------------------------------------------
01352 // Returns the gamma value
01353 //-----------------------------------------------------------------------------
01354 float GameVideo::GetGamma()
01355 {
01356   return _gamma_value;
01357 }
01358 
01359 
01360 //-----------------------------------------------------------------------------
01361 // ToggleFPS: toggles the FPS display
01362 //-----------------------------------------------------------------------------
01363 
01364 void GameVideo::ToggleFPS()
01365 {
01366   _fps_display = !_fps_display;
01367 }
01368 
01369 
01370 //-----------------------------------------------------------------------------
01371 // _CreateTempFilename
01372 //-----------------------------------------------------------------------------
01373 
01374 std::string GameVideo::_CreateTempFilename(const std::string &extension)
01375 {
01376   // figure out the temp filename to return
01377   string file_name = "/tmp/allacrost";
01378   file_name += _next_temp_file;
01379   file_name += extension;
01380 
01381   // increment the 8-character temp name
01382   // Note: assume that the temp name is currently set to
01383   //       a valid name
01384 
01385 
01386   for(int32 digit = 7; digit >= 0; --digit)
01387   {
01388     ++_next_temp_file[digit];
01389 
01390     if(_next_temp_file[digit] > 'z')
01391     {
01392       if(digit==0)
01393       {
01394         if(VIDEO_DEBUG)
01395           cerr << "VIDEO ERROR: _nextTempFile went past 'zzzzzzzz'" << endl;
01396         return file_name;
01397       }
01398 
01399       _next_temp_file[digit] = '0';
01400     }
01401     else
01402     {
01403       if(_next_temp_file[digit] > '9' && _next_temp_file[digit] < 'a')
01404         _next_temp_file[digit] = 'a';
01405 
01406       // if the digit did not overflow, then we don't need to carry over
01407       break;
01408     }
01409   }
01410 
01411   return file_name;
01412 }
01413 
01414 
01415 //-----------------------------------------------------------------------------
01416 // _PushContext: pushes transformation, coordsys, and draw flags so that
01417 //               GameVideo doesn't trample on client's settings
01418 //-----------------------------------------------------------------------------
01419 
01420 void GameVideo::_PushContext()
01421 {
01422   // push current modelview transformation
01423   glMatrixMode(GL_MODELVIEW);
01424   glPushMatrix();
01425 
01426   // save context information
01427   private_video::Context c;
01428   c.coordinate_system = _coord_sys;
01429   c.blend    = _blend;
01430   c.x_align   = _x_align;
01431   c.y_align   = _y_align;
01432   c.x_flip    = _x_flip;
01433   c.y_flip    = _y_flip;
01434 
01435   c.viewport = _viewport;
01436   c.scissor_rectangle = _scissor_rect;
01437   c.scissoring_enabled = _scissor_enabled;
01438 
01439   c.font      = _current_font;
01440   c.text_color = _current_text_color;
01441 
01442   _context_stack.push(c);
01443 }
01444 
01445 
01446 //-----------------------------------------------------------------------------
01447 // _PopContext: pops transformation, coordsys, and draw flags so that
01448 //              GameVideo doesn't trample on client's settings
01449 //-----------------------------------------------------------------------------
01450 
01451 void GameVideo::_PopContext()
01452 {
01453   // restore context information and pop it from stack
01454   private_video::Context c = _context_stack.top();
01455   SetCoordSys(c.coordinate_system);
01456   _blend  = c.blend;
01457   _x_align = c.x_align;
01458   _y_align = c.y_align;
01459   _x_flip  = c.x_flip;
01460   _y_flip  = c.y_flip;
01461 
01462   _current_font      = c.font;
01463   _current_text_color = c.text_color;
01464 
01465   _viewport = c.viewport;
01466   _scissor_rect = c.scissor_rectangle;
01467   _scissor_enabled = c.scissoring_enabled;
01468   _context_stack.pop();
01469 
01470   // restore modelview transformation
01471   glMatrixMode(GL_MODELVIEW);
01472   glPopMatrix();
01473 
01474   glViewport(_viewport.left, _viewport.top, _viewport.width, _viewport.height);
01475 
01476   if(_scissor_enabled)
01477   {
01478     glEnable(GL_SCISSOR_TEST);
01479     glScissor(_scissor_rect.left, _scissor_rect.top, _scissor_rect.width, _scissor_rect.height);
01480   }
01481   else
01482   {
01483     glDisable(GL_SCISSOR_TEST);
01484   }
01485 }
01486 
01487 
01488 //-----------------------------------------------------------------------------
01489 // _ConvertYAlign: convert a value like VIDEO_Y_BOTTOM to an offset like -1
01490 //-----------------------------------------------------------------------------
01491 
01492 int32 GameVideo::_ConvertYAlign(int32 y_align)
01493 {
01494   switch(y_align)
01495   {
01496     case VIDEO_Y_BOTTOM:
01497       return -1;
01498     case VIDEO_Y_CENTER:
01499       return 0;
01500     default:
01501       return 1;
01502   }
01503 }
01504 
01505 
01506 //-----------------------------------------------------------------------------
01507 // _ConvertXAlign: convert a value like VIDEO_X_LEFT to an offset like -1
01508 //-----------------------------------------------------------------------------
01509 
01510 int32 GameVideo::_ConvertXAlign(int32 x_align)
01511 {
01512   switch(x_align)
01513   {
01514     case VIDEO_X_LEFT:
01515       return -1;
01516     case VIDEO_X_CENTER:
01517       return 0;
01518     default:
01519       return 1;
01520   }
01521 }
01522 
01523 //-----------------------------------------------------------------------------
01524 // SetDefaultCursor: sets the default menu cursor, returns false if it fails
01525 //-----------------------------------------------------------------------------
01526 bool GameVideo::SetDefaultCursor(const std::string &cursor_image_filename)
01527 {
01528   _default_menu_cursor.SetFilename(cursor_image_filename);
01529   return LoadImage(_default_menu_cursor);
01530 }
01531 
01532 
01533 //-----------------------------------------------------------------------------
01534 // GetDefaultCursor: sets the gefault menu cursor, returns NULL if none is set
01535 //-----------------------------------------------------------------------------
01536 StillImage *GameVideo::GetDefaultCursor()
01537 {
01538   if(_default_menu_cursor.GetWidth() != 0.0f)  // cheap test if image is valid
01539     return &_default_menu_cursor;
01540   else
01541     return NULL;
01542 }
01543 
01544 
01545 //-----------------------------------------------------------------------------
01546 // PushMatrix: pushes the current model view transformation on to stack
01547 //             Note, this assumes that glMatrixMode(GL_MODELVIEW) has been called
01548 //-----------------------------------------------------------------------------
01549 void GameVideo::PushMatrix()
01550 {
01551   glPushMatrix();
01552 }
01553 
01554 //-----------------------------------------------------------------------------
01555 // PopMatrix: pops the current model view transformation from stack
01556 //            Note, this assumes that glMatrixMode(GL_MODELVIEW) has been called
01557 //-----------------------------------------------------------------------------
01558 void GameVideo::PopMatrix()
01559 {
01560   glPopMatrix();
01561 }
01562 
01563 
01564 
01565 //-----------------------------------------------------------------------------
01566 // EnableScissoring: enable/disable scissoring
01567 //-----------------------------------------------------------------------------
01568 void GameVideo::EnableScissoring(bool enable)
01569 {
01570   _scissor_enabled = enable;
01571 
01572   if(enable)
01573     glEnable(GL_SCISSOR_TEST);
01574   else
01575     glDisable(GL_SCISSOR_TEST);
01576 }
01577 
01578 
01579 //-----------------------------------------------------------------------------
01580 // SetScissorRect: set the scissoring rectangle, coordinates relative to the
01581 //                 current coord sys
01582 //-----------------------------------------------------------------------------
01583 void GameVideo::SetScissorRect(float left, float right, float bottom, float top)
01584 {
01585   _scissor_rect = CalculateScreenRect(left, right, bottom, top);
01586   glScissor(_scissor_rect.left, _scissor_rect.top, _scissor_rect.width, _scissor_rect.height);
01587 }
01588 
01589 
01590 //-----------------------------------------------------------------------------
01591 // SetScissorRect: set the scissoring rectangle
01592 //-----------------------------------------------------------------------------
01593 void GameVideo::SetScissorRect(const ScreenRect &rect)
01594 {
01595   _scissor_rect = rect;
01596   glScissor(rect.left, rect.top, rect.width, rect.height);
01597 }
01598 
01599 //-----------------------------------------------------------------------------
01600 // CalculateScreenRect: calculate a rectangle in screen coordinates given one
01601 //                       using our current coordinate system
01602 //-----------------------------------------------------------------------------
01603 ScreenRect GameVideo::CalculateScreenRect(float left, float right, float bottom, float top)
01604 {
01605   ScreenRect rect;
01606 
01607   int32 scr_left    = _ScreenCoordX(left);
01608   int32 scr_right   = _ScreenCoordX(right);
01609   int32 scr_bottom  = _ScreenCoordY(bottom);
01610   int32 scr_top     = _ScreenCoordY(top);
01611 
01612   int32 temp;
01613   if(scr_left > scr_right)
01614   {
01615     temp = scr_left;
01616     scr_left = scr_right;
01617     scr_right = temp;
01618   }
01619 
01620   if(scr_top > scr_bottom)
01621   {
01622     temp = scr_top;
01623     scr_top = scr_bottom;
01624     scr_bottom = temp;
01625   }
01626 
01627   rect.top    = scr_top;
01628   rect.left   = scr_left;
01629   rect.width  = scr_right - scr_left;
01630   rect.height = scr_bottom - scr_top;
01631 
01632   return rect;
01633 }
01634 
01635 
01636 //-----------------------------------------------------------------------------
01637 // _ScreenCoordX
01638 //-----------------------------------------------------------------------------
01639 
01640 int32 GameVideo::_ScreenCoordX(float x)
01641 {
01642   float percent;
01643   if(_coord_sys.GetLeft() < _coord_sys.GetRight())
01644     percent = (x - _coord_sys.GetLeft()) / (_coord_sys.GetRight() - _coord_sys.GetLeft());
01645   else
01646     percent = (x - _coord_sys.GetRight()) / (_coord_sys.GetLeft() - _coord_sys.GetRight());
01647 
01648   return int32(percent * float(_width));
01649 }
01650 
01651 
01652 //-----------------------------------------------------------------------------
01653 // _ScreenCoordY
01654 //-----------------------------------------------------------------------------
01655 
01656 int32 GameVideo::_ScreenCoordY(float y)
01657 {
01658   float percent;
01659   if(_coord_sys.GetTop() < _coord_sys.GetBottom())
01660     percent = (y - _coord_sys.GetTop()) / (_coord_sys.GetBottom() - _coord_sys.GetTop());
01661   else
01662     percent = (y - _coord_sys.GetBottom()) / (_coord_sys.GetTop() - _coord_sys.GetBottom());
01663 
01664   return int32(percent * float(_height));
01665 }
01666 
01667 
01668 //-----------------------------------------------------------------------------
01669 // _ShouldSmooth: call to check if textures should be smoothed to display
01670 //                nicely on non-natural (non 1024x768) resolutions
01671 //-----------------------------------------------------------------------------
01672 bool GameVideo::_ShouldSmooth() {
01673   return ( _width  != VIDEO_STANDARD_RES_WIDTH ||
01674      _height != VIDEO_STANDARD_RES_HEIGHT);
01675 }
01676 
01677 
01678 //-----------------------------------------------------------------------------
01679 // MakeLightning: creates a lightning effect
01680 //-----------------------------------------------------------------------------
01681 
01682 bool GameVideo::MakeLightning(const std::string &lit_file)
01683 {
01684   FILE *fp = fopen(lit_file.c_str(), "rb");
01685   if(!fp)
01686     return false;
01687 
01688   int32 data_size;
01689   if(!fread(&data_size, 4, 1, fp))
01690   {
01691     fclose(fp);
01692     return false;
01693   }
01694 
01695   // since this file was created on windows, it uses little endian byte order
01696   // Check if this processor uses big endian, and reorder bytes if so.
01697 
01698   #if SDL_BYTEORDER == SDL_BIG_ENDIAN
01699     data_size = ((data_size & 0xFF000000) >> 24) |
01700                ((data_size & 0x00FF0000) >> 8) |
01701                ((data_size & 0x0000FF00) << 8) |
01702                ((data_size & 0x000000FF) << 24);
01703   #endif
01704 
01705   uint8 *data = new uint8[data_size];
01706 
01707   if(!fread(data, data_size, 1, fp))
01708   {
01709     delete [] data;
01710     fclose(fp);
01711     return false;
01712   }
01713 
01714   fclose(fp);
01715 
01716   _lightning_data.clear();
01717 
01718   for(int32 j = 0; j < data_size; ++j)
01719   {
01720     float f = float(data[j]) / 255.0f;
01721     _lightning_data.push_back(f);
01722   }
01723 
01724   delete [] data;
01725 
01726   _lightning_active = true;
01727   _lightning_current_time = 0;
01728   _lightning_end_time = data_size * 1000 / 100;
01729 
01730   return true;
01731 }
01732 
01733 
01734 //-----------------------------------------------------------------------------
01735 // DrawLightning: draws lightning effect on the screen using a fullscreen overlay
01736 //-----------------------------------------------------------------------------
01737 
01738 bool GameVideo::DrawLightning()
01739 {
01740   if(!_lightning_active)
01741     return true;
01742 
01743   // convert milliseconds elapsed into data points elapsed
01744 
01745   float t = _lightning_current_time * 100.0f / 1000.0f;
01746 
01747   int32 rounded_t = static_cast<int32>(t);
01748   t -= rounded_t;
01749 
01750   // get 2 separate data points and blend together (linear interpolation)
01751 
01752   float data1 = _lightning_data[rounded_t];
01753   float data2 = _lightning_data[rounded_t+1];
01754 
01755   float intensity = data1 * (1-t) + data2 * t;
01756 
01757   DrawFullscreenOverlay(Color(1.0f, 1.0f, 1.0f, intensity));
01758 
01759   return true;
01760 }
01761 
01762 
01763 //-----------------------------------------------------------------------------
01764 // DrawFullscreenOverlay
01765 //-----------------------------------------------------------------------------
01766 
01767 bool GameVideo::DrawFullscreenOverlay(const Color &color)
01768 {
01769   PushState();
01770 
01771   SetCoordSys(0.0f, 1.0f, 0.0f, 1.0f);
01772   SetDrawFlags(VIDEO_X_LEFT, VIDEO_Y_BOTTOM, VIDEO_BLEND, 0);
01773   Move(0.0f, 0.0f);
01774   StillImage img;
01775   img.SetDimensions(1.0f, 1.0f);
01776   LoadImage(img);
01777   DrawImage(img, color);
01778 
01779   PopState();
01780 
01781   return true;
01782 }
01783 
01784 
01785 //-----------------------------------------------------------------------------
01786 // SetTarget: lets video engine know if it's drawing to an SDL window or a
01787 //            QT widget
01788 //-----------------------------------------------------------------------------
01789 
01790 bool GameVideo::SetTarget(VIDEO_TARGET target)
01791 {
01792   if(target <= VIDEO_TARGET_INVALID || target >= VIDEO_TARGET_TOTAL)
01793   {
01794     if(VIDEO_DEBUG)
01795       cerr << "VIDEO ERROR: tried to set video engine to invalid target (" << target << ")" << endl;
01796     return false;
01797   }
01798 
01799   _target = target;
01800   return true;
01801 }
01802 
01803 
01804 //-----------------------------------------------------------------------------
01805 // DrawGrid: draws a grid going from (x,y) to (maxX, maxY), with horizontal and
01806 //           vertical grid spacing of xstep and ystep, with a color 'c'
01807 //-----------------------------------------------------------------------------
01808 
01809 void GameVideo::DrawGrid(float x, float y, float x_step, float y_step, const Color &c)
01810 {
01811   PushState();
01812 
01813   Move(0, 0);
01814   
01815   float x_Max = _coord_sys.GetRight();
01816   float y_Max = _coord_sys.GetBottom();
01817   
01818   std::vector<GLfloat> vertices;
01819   int numvertices = 0;
01820   for (; x <= x_Max; x += x_step)
01821   {
01822     vertices.push_back(x);
01823     vertices.push_back(_coord_sys.GetBottom());
01824     vertices.push_back(x);
01825     vertices.push_back(_coord_sys.GetTop());
01826     numvertices += 2;
01827   }
01828   for (; y < y_Max; y += y_step)
01829   {
01830     vertices.push_back(_coord_sys.GetLeft());
01831     vertices.push_back(y);
01832     vertices.push_back(_coord_sys.GetRight());
01833     vertices.push_back(y);
01834     numvertices += 2;
01835   }
01836   glColor4fv(&c[0]);
01837   glEnableClientState ( GL_VERTEX_ARRAY );
01838   glVertexPointer ( 2, GL_FLOAT, 0, &(vertices[0]) );
01839   glDrawArrays ( GL_LINES, 0, numvertices );
01840   glDisableClientState ( GL_VERTEX_ARRAY );
01841   /*glBegin(GL_LINES);
01842   glColor4fv(&c[0]);
01843 
01844   for(; x <= x_Max; x += x_step)
01845   {
01846     glVertex2f(x, _coord_sys.GetBottom());
01847     glVertex2f(x, _coord_sys.GetTop());
01848   }
01849 
01850   for(; y <= y_Max; y += y_step)
01851   {
01852     glVertex2f(_coord_sys.GetLeft(), y);
01853     glVertex2f(_coord_sys.GetRight(), y);
01854   }
01855 
01856   glEnd();*/
01857   PopState();
01858 }
01859 
01860 //-----------------------------------------------------------------------------
01861 // Draws a solid rectangle of a given color.
01862 //-----------------------------------------------------------------------------
01863 void GameVideo::DrawRectangle(const float width, const float height, const Color &color)
01864 {
01865   _rectangle_image._elements[0].width = width;
01866   _rectangle_image._elements[0].height = height;
01867 
01868   VideoManager->DrawImage(_rectangle_image, color);
01869 }
01870 
01871 }  // namespace hoa_video

Generated on Fri Jul 6 23:11:26 2007 for Hero of Allacrost by  doxygen 1.5.1