From 2c3e551ce60c9a885bb73310ed17641b701102bd Mon Sep 17 00:00:00 2001 From: hikerstk Date: Thu, 6 Dec 2007 04:04:21 +0000 Subject: [PATCH] Applied Paul's patch for selecting the screen resolution via the option menu (I added some minor modifications to get it to work with windows as well). git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@1321 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/gui/config_display.cpp | 152 ++++++++++++++++++++++++++++++++++++- src/gui/config_display.hpp | 11 +++ src/gui/menu_manager.cpp | 16 +++- src/gui/menu_manager.hpp | 1 + src/gui/race_gui.cpp | 2 +- src/sdldrv.cpp | 9 ++- src/sdldrv.hpp | 3 +- 7 files changed, 184 insertions(+), 10 deletions(-) diff --git a/src/gui/config_display.cpp b/src/gui/config_display.cpp index aa0c0b40c..c3451d96e 100644 --- a/src/gui/config_display.cpp +++ b/src/gui/config_display.cpp @@ -24,18 +24,36 @@ #include "sdldrv.hpp" #include "translation.hpp" +#include + +#if defined(WIN32) && !defined(__CYGWIN__) +# define snprintf _snprintf +#endif + enum WidgetTokens { WTOK_TITLE, WTOK_FULLSCREEN, + + WTOK_INCR_RES, + + WTOK_DECR_RES, + + WTOK_CURRENT_RES, + + WTOK_APPLY_RES, WTOK_EMPTY, + + WTOK_EMPTY1, + + WTOK_EMPTY2, WTOK_QUIT }; ConfigDisplay::ConfigDisplay() -{ +{ const bool SHOW_RECT = true; const bool SHOW_TEXT = true; widget_manager->set_initial_rect_state(SHOW_RECT, WGT_AREA_ALL, WGT_TRANS_BLACK); @@ -55,17 +73,52 @@ ConfigDisplay::ConfigDisplay() { widget_manager->set_wgt_text( WTOK_FULLSCREEN, _("Fullscreen mode")); } - + widget_manager->add_wgt( WTOK_EMPTY, 40, 2); widget_manager->deactivate_wgt( WTOK_EMPTY ); widget_manager->hide_wgt_rect( WTOK_EMPTY ); widget_manager->hide_wgt_text( WTOK_EMPTY ); - + + widget_manager->add_wgt( WTOK_CURRENT_RES, 40, 7); + widget_manager->set_wgt_text( WTOK_CURRENT_RES, _("Current: ****x****")); + + widget_manager->add_wgt( WTOK_INCR_RES, 40, 7); + widget_manager->set_wgt_text( WTOK_INCR_RES, _("Increase Resolution")); + + widget_manager->add_wgt( WTOK_DECR_RES, 40, 7); + widget_manager->set_wgt_text( WTOK_DECR_RES, ("Decrease Resolution")); + + widget_manager->add_wgt( WTOK_EMPTY2, 40, 2); + widget_manager->deactivate_wgt( WTOK_EMPTY2 ); + widget_manager->hide_wgt_rect( WTOK_EMPTY2 ); + widget_manager->hide_wgt_text( WTOK_EMPTY2 ); + + widget_manager->add_wgt( WTOK_APPLY_RES, 40, 7); + widget_manager->set_wgt_text( WTOK_APPLY_RES, ("Apply ")); + + widget_manager->add_wgt( WTOK_EMPTY1, 40, 7); + widget_manager->deactivate_wgt( WTOK_EMPTY1 ); + widget_manager->hide_wgt_rect( WTOK_EMPTY1 ); + widget_manager->hide_wgt_text( WTOK_EMPTY1 ); + widget_manager->add_wgt( WTOK_QUIT, 40, 7); widget_manager->set_wgt_text( WTOK_QUIT, _("Press to go back")); widget_manager->set_wgt_text_size( WTOK_QUIT, WGT_FNT_SML ); widget_manager->layout( WGT_AREA_ALL ); + + //get current resolution and set wgt txt + getScreenModes(); + if (m_sizes_index == -1) + { + snprintf (m_resolution, MAX_MESSAGE_LENGTH, "Current: %dx%d", user_config->m_width, user_config->m_height); + widget_manager->set_wgt_text(WTOK_CURRENT_RES, m_resolution); + } + else + { + snprintf(m_resolution, MAX_MESSAGE_LENGTH, "Current: %dx%d",m_sizes[m_sizes_index].first,m_sizes[m_sizes_index].second); + widget_manager->set_wgt_text(WTOK_CURRENT_RES, m_resolution); + } } //----------------------------------------------------------------------------- @@ -96,10 +149,32 @@ void ConfigDisplay::select() // widgetSet, etc. // CreateMenu(); if(user_config->m_fullscreen) + { widget_manager->set_wgt_text( WTOK_FULLSCREEN, _("Window mode")); + } else + { widget_manager->set_wgt_text( WTOK_FULLSCREEN, _("Fullscreen mode")); + } + menu_manager->refreshMenu(); break; + case WTOK_INCR_RES: + m_sizes_index = std::min(m_sizes_size-1,m_sizes_index+1); + snprintf(m_resolution, MAX_MESSAGE_LENGTH, "Apply %dx%d",m_sizes[m_sizes_index].first,m_sizes[m_sizes_index].second); + widget_manager->set_wgt_text(WTOK_APPLY_RES, m_resolution); + break; + case WTOK_DECR_RES: + m_sizes_index = std::max(0,m_sizes_index-1); + snprintf(m_resolution, MAX_MESSAGE_LENGTH, "Apply %dx%d",m_sizes[m_sizes_index].first,m_sizes[m_sizes_index].second); + widget_manager->set_wgt_text(WTOK_APPLY_RES, m_resolution); + break; + case WTOK_APPLY_RES: + changeResolution(m_sizes[m_sizes_index].first,m_sizes[m_sizes_index].second); + snprintf (m_resolution, MAX_MESSAGE_LENGTH, "Current: %dx%d", user_config->m_width, user_config->m_height); + widget_manager->set_wgt_text(WTOK_CURRENT_RES, m_resolution); + + break; + case WTOK_QUIT: menu_manager->popMenu(); break; @@ -107,5 +182,74 @@ void ConfigDisplay::select() } } +//----------------------------------------------------------------------------- +void ConfigDisplay::changeResolution(int width, int height) +{ + user_config->m_width = width; + user_config->m_height = height; + + setVideoMode(); + + menu_manager->refreshMenu(); + + glViewport(0,0,user_config->m_width, user_config->m_height); + glScissor(0,0,user_config->m_width, user_config->m_height); +} - +//----------------------------------------------------------------------------- +//This gets the available screen resolutions available on the hardware and +//populates a vector with them. +void ConfigDisplay::getScreenModes() +{ + if (m_sizes.empty()) //has this data been collected before + { + SDL_Rect **modes = SDL_ListModes(NULL, SDL_OPENGL | SDL_FULLSCREEN | SDL_HWSURFACE ); + + //Check if any modes are available + if (!modes) + { + std::cerr << "No Screen Modes available" < (modes[i]->w, modes[i]->h)); + + //Sort the entries + sort (m_sizes.begin(), m_sizes.end()); + + //Prevent use of very small resolutions + const int minRes = 640; + m_sizes_size = m_sizes.size(); + + for (int i = m_sizes_size-1; i >= 0; --i) + { + if (m_sizes[i].first < minRes) //find largest width less than minRes + { + m_sizes.erase(m_sizes.begin(),m_sizes.begin()+i+1); //remove all resolutions prior + break; + } + } + } + }// m_sizes.empty() + + // search m_sizes for the current resolution + m_sizes_index = -1; + m_sizes_size = m_sizes.size(); + for (int i = 0; i < m_sizes_size; i++) + { + if (m_sizes[i].first == user_config->m_width + && m_sizes[i].second == user_config->m_height) + { + m_sizes_index = i; + break; + } + } + + +} diff --git a/src/gui/config_display.hpp b/src/gui/config_display.hpp index f1796c5a2..d3c478918 100644 --- a/src/gui/config_display.hpp +++ b/src/gui/config_display.hpp @@ -20,7 +20,10 @@ #ifndef HEADER_CONFIGDISPLAY_H #define HEADER_CONFIGDISPLAY_H +#include + #include "base_gui.hpp" +#include "translation.hpp" class ConfigDisplay: public BaseGUI { @@ -33,6 +36,14 @@ public: private: int m_fullscreen_menu_id; + + std::vector > m_sizes; + int m_sizes_index; + int m_sizes_size; + char m_resolution[MAX_MESSAGE_LENGTH]; + + void changeResolution(int width, int height); + void getScreenModes(); }; #endif diff --git a/src/gui/menu_manager.cpp b/src/gui/menu_manager.cpp index 2a963713f..ba9043213 100644 --- a/src/gui/menu_manager.cpp +++ b/src/gui/menu_manager.cpp @@ -97,11 +97,11 @@ void MenuManager::update() if (m_handled_size != m_menu_stack.size()) { if (m_RaceGUI - && m_current_menu == m_RaceGUI) + && m_current_menu == m_RaceGUI) { m_RaceGUI = 0; - drv_setMode(MENU); - } + drv_setMode(MENU); + } delete m_current_menu; m_current_menu= NULL; @@ -207,6 +207,16 @@ void MenuManager::update() } } // update +//----------------------------------------------------------------------------- +//Used to create a new instance of the present menu, which updates the widgets +//text and/or location, if they have been changed by selecting an entry in the menu. +//eg: after a change of screen resolution + +void MenuManager::refreshMenu() +{ + widget_manager->layout(); +} + //----------------------------------------------------------------------------- void MenuManager::switchToGrandPrixEnding() { diff --git a/src/gui/menu_manager.hpp b/src/gui/menu_manager.hpp index 414ba750b..391955d8b 100644 --- a/src/gui/menu_manager.hpp +++ b/src/gui/menu_manager.hpp @@ -73,6 +73,7 @@ public: void switchToGrandPrixEnding(); void switchToRace(); void switchToMainMenu(); + void refreshMenu(); // use this function within menu classes void pushMenu(MenuManagerIDs id); diff --git a/src/gui/race_gui.cpp b/src/gui/race_gui.cpp index 17e2afd3b..65e54df4a 100644 --- a/src/gui/race_gui.cpp +++ b/src/gui/race_gui.cpp @@ -130,7 +130,7 @@ RaceGUI::handle(GameAction ga, int value) // to reload all textures, display lists etc. Fullscreen can // be toggled from the main menu (options->display). case GA_TOGGLE_FULLSCREEN: - drv_toggleFullscreen(0); // 0: do not reset textures + drv_toggleFullscreen(false); // 0: do not reset textures // Fall through to put the game into pause mode. #endif case GA_LEAVE_RACE: diff --git a/src/sdldrv.cpp b/src/sdldrv.cpp index f8730a448..4a67b987b 100755 --- a/src/sdldrv.cpp +++ b/src/sdldrv.cpp @@ -103,7 +103,7 @@ hidePointer() SDL_ShowCursor(SDL_DISABLE); } //----------------------------------------------------------------------------- -void drv_toggleFullscreen(int resetTextures) +void drv_toggleFullscreen(bool resetTextures) { user_config->m_fullscreen = !user_config->m_fullscreen; @@ -118,7 +118,14 @@ void drv_toggleFullscreen(int resetTextures) } else if(menu_manager->isSomewhereOnStack(MENUID_RACE)) hidePointer(); + + setVideoMode(resetTextures); +} +//----------------------------------------------------------------------------- +void setVideoMode(bool resetTextures) +{ + //Is SDL_FreeSurface necessary? SDL wiki says not?? SDL_FreeSurface(mainSurface); mainSurface = SDL_SetVideoMode(user_config->m_width, user_config->m_height, 0, flags); diff --git a/src/sdldrv.hpp b/src/sdldrv.hpp index fc25589f8..3bdf81d9c 100755 --- a/src/sdldrv.hpp +++ b/src/sdldrv.hpp @@ -47,7 +47,8 @@ struct StickInfo { void drv_init(); void drv_deinit(); -void drv_toggleFullscreen(int resetTextures=1); +void drv_toggleFullscreen(bool resetTextures=1); +void setVideoMode(bool resetTextures=1); void drv_loop();