From afca5cf6c6c04f428cb5e41c5a23d22789ece71c Mon Sep 17 00:00:00 2001 From: cosmosninja Date: Tue, 20 Nov 2007 02:13:53 +0000 Subject: [PATCH] Removed the widget set and put in it's place a work-in-progress replacement git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@1293 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/Makefile.am | 4 +- src/gui/base_gui.cpp | 72 +- src/gui/char_sel.cpp | 99 +- src/gui/char_sel.hpp | 1 - src/gui/config_controls.cpp | 81 +- src/gui/config_controls.hpp | 2 +- src/gui/config_display.cpp | 75 +- src/gui/config_display.hpp | 3 +- src/gui/config_sound.cpp | 89 +- src/gui/config_sound.hpp | 1 - src/gui/credits_menu.cpp | 72 +- src/gui/credits_menu.hpp | 14 +- src/gui/difficulty.cpp | 50 +- src/gui/game_mode.cpp | 57 +- src/gui/grand_prix_ending.cpp | 46 +- src/gui/grand_prix_select.cpp | 85 +- src/gui/grand_prix_select.hpp | 1 - src/gui/help_menu.cpp | 335 +++++-- src/gui/help_menu.hpp | 4 +- src/gui/main_menu.cpp | 84 +- src/gui/menu_manager.cpp | 6 + src/gui/num_laps.cpp | 101 +- src/gui/num_players.cpp | 52 +- src/gui/options.cpp | 68 +- src/gui/options.hpp | 1 - src/gui/player_controls.cpp | 123 ++- src/gui/player_controls.hpp | 4 - src/gui/race_gui.cpp | 4 +- src/gui/race_menu.cpp | 57 +- src/gui/race_menu.hpp | 1 - src/gui/race_results_gui.cpp | 89 +- src/gui/scrolled_text.cpp | 124 --- src/gui/scrolled_text.hpp | 51 - src/gui/track_sel.cpp | 98 +- src/gui/track_sel.hpp | 4 +- src/main.cpp | 4 +- src/widget.cpp | 537 +++++++++++ src/widget.hpp | 180 ++++ src/widget_manager.cpp | 1152 +++++++++++++++++++++++ src/widget_manager.hpp | 191 ++++ src/widget_set.cpp | 1654 --------------------------------- src/widget_set.hpp | 339 ------- 42 files changed, 3363 insertions(+), 2652 deletions(-) delete mode 100644 src/gui/scrolled_text.cpp delete mode 100644 src/gui/scrolled_text.hpp create mode 100644 src/widget.cpp create mode 100644 src/widget.hpp create mode 100644 src/widget_manager.cpp create mode 100644 src/widget_manager.hpp delete mode 100644 src/widget_set.cpp delete mode 100644 src/widget_set.hpp diff --git a/src/Makefile.am b/src/Makefile.am index ccbd43824..96f0f7dbc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -67,7 +67,8 @@ supertuxkart_SOURCES = main.cpp \ shadow.cpp shadow.hpp \ particle_system.cpp particle_system.hpp \ game_manager.cpp game_manager.hpp \ - widget_set.cpp widget_set.hpp \ + widget_manager.cpp widget_manager.hpp \ + widget.cpp widget.hpp \ camera.cpp camera.hpp \ sdldrv.cpp sdldrv.hpp \ moveable.cpp moveable.hpp \ @@ -107,7 +108,6 @@ supertuxkart_SOURCES = main.cpp \ gui/main_menu.cpp gui/main_menu.hpp \ gui/help_menu.cpp gui/help_menu.hpp \ gui/credits_menu.cpp gui/credits_menu.hpp \ - gui/scrolled_text.cpp gui/scrolled_text.hpp \ gui/grand_prix_select.cpp gui/grand_prix_select.hpp \ gui/font.hpp gui/font.cpp \ robots/default_robot.cpp robots/default_robot.hpp \ diff --git a/src/gui/base_gui.cpp b/src/gui/base_gui.cpp index 6b3e6075b..a62ed412c 100644 --- a/src/gui/base_gui.cpp +++ b/src/gui/base_gui.cpp @@ -20,7 +20,7 @@ #include #include "base_gui.hpp" -#include "widget_set.hpp" +#include "widget_manager.hpp" #include "world.hpp" #include "menu_manager.hpp" @@ -31,6 +31,34 @@ void BaseGUI::input(InputType type, int id0, int id1, int id2, int value) case IT_KEYBOARD: inputKeyboard(id0, value); break; + + case IT_MOUSEMOTION: + { + const int PREV_SELECTED_WGT = widget_manager->get_selected_wgt(); + const int SELECTED_WGT = widget_manager->handle_mouse( id0, id1 ); + + //FIXME: I should take WGT_NONE out of the class. + if( SELECTED_WGT != WidgetManager::WGT_NONE ) + { + if( PREV_SELECTED_WGT != WidgetManager::WGT_NONE ) + { + widget_manager->darken_wgt_color( PREV_SELECTED_WGT ); + } + + widget_manager->lighten_wgt_color( SELECTED_WGT ); + widget_manager->pulse_wgt( SELECTED_WGT ); + } + +#ifdef ALT_MOUSE_HANDLING + if (id0 == 1 && value) + if (id1 == AD_NEGATIVE) + inputKeyboard(SDLK_UP, 1); + else + inputKeyboard(SDLK_DOWN, 1); +#endif + break; + } + case IT_MOUSEBUTTON: if (!value) // Act on button release only. switch (id0) @@ -105,7 +133,28 @@ void BaseGUI::inputKeyboard(int key, int pressed) case SDLK_RIGHT: case SDLK_UP: case SDLK_DOWN: - widgetSet->pulse(widgetSet->cursor(m_menu_id, key), 1.2f); + { + const int PREV_SELECTED_WGT = widget_manager->get_selected_wgt(); + const int SELECTED_WGT = widget_manager->handle_keyboard( key ); + + if( SELECTED_WGT != WidgetManager::WGT_NONE ) + { + if( PREV_SELECTED_WGT != WidgetManager::WGT_NONE ) + { + widget_manager->darken_wgt_color( PREV_SELECTED_WGT ); + } + + widget_manager->lighten_wgt_color( SELECTED_WGT ); + widget_manager->pulse_wgt( SELECTED_WGT ); + } + break; + } + + case SDLK_PLUS: + case SDLK_MINUS: + case SDLK_PAGEUP: + case SDLK_PAGEDOWN: + widget_manager->handle_keyboard( key ); break; case SDLK_SPACE: @@ -118,7 +167,7 @@ void BaseGUI::inputKeyboard(int key, int pressed) { if(menu_manager->isCurrentMenu(MENUID_RACEMENU)) world->unpause(); - + menu_manager->popMenu(); } break; @@ -131,14 +180,29 @@ void BaseGUI::inputKeyboard(int key, int pressed) void BaseGUI::inputPointer(int x, int y) { - widgetSet->pulse(widgetSet->point(m_menu_id, x, y), 1.2f); + const int PREV_SELECTED_WGT = widget_manager->get_selected_wgt(); + const int SELECTED_WGT = widget_manager->handle_mouse( x, y ); + + if( SELECTED_WGT != WidgetManager::WGT_NONE ) + { + if( PREV_SELECTED_WGT != WidgetManager::WGT_NONE ) + { + widget_manager->darken_wgt_color( PREV_SELECTED_WGT ); + } + + widget_manager->lighten_wgt_color( SELECTED_WGT ); + widget_manager->pulse_wgt( SELECTED_WGT ); + } } //----------------------------------------------------------------------------- void BaseGUI::update(float dt) { + widget_manager->update(dt); +#if 0 widgetSet -> timer(m_menu_id, dt) ; widgetSet -> paint(m_menu_id) ; +#endif } // update //----------------------------------------------------------------------------- diff --git a/src/gui/char_sel.cpp b/src/gui/char_sel.cpp index 4ef9f0025..0f3ecbf3c 100644 --- a/src/gui/char_sel.cpp +++ b/src/gui/char_sel.cpp @@ -23,7 +23,7 @@ #include "loader.hpp" #include "char_sel.hpp" #include "kart_properties_manager.hpp" -#include "widget_set.hpp" +#include "widget_manager.hpp" #include "race_manager.hpp" #include "user_config.hpp" #include "menu_manager.hpp" @@ -35,62 +35,78 @@ # define snprintf _snprintf #endif +enum WidgetTokens +{ + WTOK_RACER0, + WTOK_RACER1, + WTOK_RACER2, + WTOK_RACER3, + WTOK_RACER4, + WTOK_RACER5, + WTOK_RACER6, + WTOK_RACER7, + WTOK_RACER8, + WTOK_RACER9, + + WTOK_TITLE, + WTOK_NAME, + + WTOK_QUIT +}; + CharSel::CharSel(int whichPlayer) : m_kart(0), m_player_index(whichPlayer) { - // for some strange reasons plib calls makeCurrent() in ssgContextf + // For some strange reasons plib calls makeCurrent() in ssgContext // constructor, so we have to save the old one here and restore it ssgContext* oldContext = ssgGetCurrentContext(); m_context = new ssgContext; oldContext->makeCurrent(); - m_menu_id = widgetSet -> vstack(0); - const int HS1 = widgetSet -> hstack (m_menu_id); - widgetSet -> filler(HS1); - - // Due to widgetSet constraints, this must be static! - static char HEADING[MAX_MESSAGE_LENGTH]; + widget_manager->set_initial_activation_state(false); + widget_manager->add_wgt( WTOK_TITLE, 60, 10); + widget_manager->show_wgt_rect( WTOK_TITLE ); + char HEADING[MAX_MESSAGE_LENGTH]; snprintf(HEADING, sizeof(HEADING), _("Player %d, choose a driver"), m_player_index + 1); + widget_manager->set_wgt_text( WTOK_TITLE, HEADING); + widget_manager->set_wgt_text_size( WTOK_TITLE, WGT_FNT_LRG); + widget_manager->show_wgt_text( WTOK_TITLE ); + widget_manager->break_line(); - widgetSet -> label(HS1, HEADING, GUI_LRG, GUI_ALL, 0, 0); - widgetSet -> filler(HS1); + widget_manager->add_wgt( WidgetManager::WGT_NONE, 100, 2); + widget_manager->break_line(); - widgetSet -> filler(m_menu_id); - - const int HA = widgetSet -> harray(m_menu_id); - const int ICON_SIZE = 64; - - unsigned int lastKartId = user_config->m_player[m_player_index].getLastKartId(); - bool skipActivatingLast = false; + //FIXME: this supports only a static number of karts +// unsigned int lastKartId = user_config->m_player[m_player_index].getLastKartId(); +// bool skipActivatingLast = false; for (unsigned int i = 0; i < kart_properties_manager->getNumberOfKarts(); i++) { const KartProperties* kp= kart_properties_manager->getKartById(i); Material *m = material_manager->getMaterial(kp->getIconFile()); - const int C = widgetSet->image(HA, m->getState()->getTextureHandle(), - ICON_SIZE, ICON_SIZE); - widgetSet->activate_widget(C, i, 0); - - if (i == lastKartId) - { - widgetSet->set_active(C); - skipActivatingLast = true; - } - - if (!skipActivatingLast && - i == kart_properties_manager->getNumberOfKarts() - 1) - widgetSet->set_active(C); + widget_manager->add_wgt( WTOK_RACER0 + i, 10, 13); + widget_manager->show_wgt_rect( WTOK_RACER0 + i); + widget_manager->set_wgt_color( WTOK_RACER0 + i, WGT_GRAY); + widget_manager->set_wgt_texture( WTOK_RACER0 + i, m->getState()->getTextureHandle()); + widget_manager->show_wgt_texture( WTOK_RACER0 + i ); + widget_manager->activate_wgt( WTOK_RACER0 + i ); } - const int HS2 = widgetSet -> hstack(m_menu_id); - widgetSet -> filler (HS2); - m_kart_name_label = widgetSet -> label(HS2, _("No driver choosed"), - GUI_MED, GUI_ALL); - widgetSet -> filler (HS2); - widgetSet -> layout(m_menu_id, 0, 1); + + widget_manager->break_line(); + widget_manager->add_wgt( WidgetManager::WGT_NONE, 100, 2); + widget_manager->break_line(); + + //FIXME: the widget should check if the dimensions > 100 + widget_manager->add_wgt( WTOK_NAME, 20, 7); + widget_manager->show_wgt_rect( WTOK_NAME ); + widget_manager->show_wgt_text( WTOK_NAME ); + + //FIXME: widget_manager says that token -1 is already in use + widget_manager->layout(WGT_AREA_TOP); m_current_kart = -1; - switchCharacter(1); + switchCharacter(0); m_clock = 0; //test @@ -100,7 +116,7 @@ CharSel::CharSel(int whichPlayer) //----------------------------------------------------------------------------- CharSel::~CharSel() { - widgetSet -> delete_widget(m_menu_id) ; + widget_manager->delete_wgts(); ssgDeRefDelete(m_kart); delete m_context; @@ -112,7 +128,8 @@ void CharSel::switchCharacter(int n) const KartProperties* kp= kart_properties_manager->getKartById(n); if (m_current_kart != n && kp != NULL) { - widgetSet -> set_label(m_kart_name_label, kp->getName().c_str()); + //widgetSet -> set_label(m_kart_name_label, kp->getName().c_str()); + widget_manager->set_wgt_text( WTOK_NAME, kp->getName().c_str()); m_current_kart = n; ssgDeRefDelete(m_kart); @@ -130,7 +147,7 @@ void CharSel::update(float dt) m_clock += dt * 40.0f; BaseGUI::update(dt); - switchCharacter(widgetSet->get_token(widgetSet->click())); + switchCharacter(widget_manager->get_selected_wgt() - WTOK_RACER0); if (m_kart != NULL) { @@ -168,7 +185,7 @@ void CharSel::update(float dt) //---------------------------------------------------------------------------- void CharSel::select() { - const int TOKEN = widgetSet -> get_token (widgetSet -> click()); + const int TOKEN = 0; const KartProperties* KP = kart_properties_manager->getKartById(TOKEN); if (KP != NULL) { diff --git a/src/gui/char_sel.hpp b/src/gui/char_sel.hpp index 0edbf421a..52fa4254e 100644 --- a/src/gui/char_sel.hpp +++ b/src/gui/char_sel.hpp @@ -31,7 +31,6 @@ private: ssgContext* m_context; ssgTransform* m_kart; int m_current_kart; - int m_kart_name_label; float m_clock; int m_player_index; diff --git a/src/gui/config_controls.cpp b/src/gui/config_controls.cpp index 856348136..72507d662 100644 --- a/src/gui/config_controls.cpp +++ b/src/gui/config_controls.cpp @@ -18,19 +18,72 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "config_controls.hpp" -#include "widget_set.hpp" +#include "widget_manager.hpp" #include "menu_manager.hpp" #include "translation.hpp" #if defined(WIN32) && !defined(__CYGWIN__) # define snprintf _snprintf #endif + +enum WidgetTokens { + WTOK_TITLE, + + WTOK_PLYR1, + WTOK_PLYR2, + WTOK_PLYR3, + WTOK_PLYR4, + + WTOK_SPACE, + + WTOK_QUIT +}; + ConfigControls::ConfigControls() { - m_menu_id = widgetSet -> vstack(0); + + + const bool SHOW_RECT = true; + const bool SHOW_TEXT = true; + widget_manager->set_initial_rect_state(SHOW_RECT, WGT_AREA_ALL, WGT_TRANS_BLACK); + widget_manager->set_initial_text_state(SHOW_TEXT, "", WGT_FNT_MED, Font::ALIGN_CENTER, Font::ALIGN_CENTER ); + widget_manager->add_wgt( WTOK_TITLE, 60, 7 ); + widget_manager->set_wgt_text( WTOK_TITLE, _("Edit controls for which player?")); + widget_manager->break_line(); + + widget_manager->set_initial_activation_state(true); + widget_manager->add_wgt( WTOK_PLYR1 , 60, 7 ); + widget_manager->set_wgt_text( WTOK_PLYR1, _("Player 1")); + widget_manager->break_line(); + + widget_manager->add_wgt( WTOK_PLYR2 , 60, 7 ); + widget_manager->set_wgt_text( WTOK_PLYR2, _("Player 2")); + widget_manager->break_line(); + + widget_manager->add_wgt( WTOK_PLYR3 , 60, 7 ); + widget_manager->set_wgt_text( WTOK_PLYR3, _("Player 3")); + widget_manager->break_line(); + + widget_manager->add_wgt( WTOK_PLYR4 , 60, 7 ); + widget_manager->set_wgt_text( WTOK_PLYR4, _("Player 4")); + widget_manager->break_line(); + + widget_manager->add_wgt( WTOK_SPACE, 60, 5); + widget_manager->deactivate_wgt( WTOK_SPACE ); + widget_manager->hide_wgt_rect( WTOK_SPACE ); + widget_manager->hide_wgt_text( WTOK_SPACE ); + widget_manager->break_line(); + + widget_manager->add_wgt( WTOK_QUIT , 60, 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 ); +/* + * m_menu_id = widgetSet -> vstack(0); widgetSet -> label(m_menu_id, _("Edit controls for which player?"), GUI_LRG); const int VA = widgetSet -> varray(m_menu_id); - + static char playerN[4][MAX_MESSAGE_LENGTH]; for(int i=1; i<=4; i++) { @@ -45,33 +98,33 @@ ConfigControls::ConfigControls() widgetSet -> space(VA); widgetSet -> state(VA, _("Press to go back"), GUI_SML, 5); - widgetSet -> layout(m_menu_id, 0, 0); + widgetSet -> layout(m_menu_id, 0, 0);*/ } //----------------------------------------------------------------------------- ConfigControls::~ConfigControls() { - widgetSet -> delete_widget(m_menu_id) ; + widget_manager->delete_wgts(); +// widgetSet -> delete_widget(m_menu_id) ; } //----------------------------------------------------------------------------- -void ConfigControls::update(float dt) +/*void ConfigControls::update(float dt) { widgetSet -> timer(m_menu_id, dt) ; widgetSet -> paint(m_menu_id) ; } - +*/ //----------------------------------------------------------------------------- void ConfigControls::select() { - switch ( widgetSet -> get_token (widgetSet -> click()) ) + switch ( widget_manager->get_selected_wgt() ) { - case 1: menu_manager->pushMenu(MENUID_CONFIG_P1); break; - case 2: menu_manager->pushMenu(MENUID_CONFIG_P2); break; - case 3: menu_manager->pushMenu(MENUID_CONFIG_P3); break; - case 4: menu_manager->pushMenu(MENUID_CONFIG_P4); break; - case 5: menu_manager->popMenu(); break; - default: break; + case WTOK_PLYR1: menu_manager->pushMenu(MENUID_CONFIG_P1); break; + case WTOK_PLYR2: menu_manager->pushMenu(MENUID_CONFIG_P2); break; + case WTOK_PLYR3: menu_manager->pushMenu(MENUID_CONFIG_P3); break; + case WTOK_PLYR4: menu_manager->pushMenu(MENUID_CONFIG_P4); break; + case WTOK_QUIT: menu_manager->popMenu(); break; } } diff --git a/src/gui/config_controls.hpp b/src/gui/config_controls.hpp index 364a98499..e18329c61 100644 --- a/src/gui/config_controls.hpp +++ b/src/gui/config_controls.hpp @@ -28,7 +28,7 @@ public: ConfigControls(); ~ConfigControls(); - void update(float dt); +// void update(float dt); void select(); }; diff --git a/src/gui/config_display.cpp b/src/gui/config_display.cpp index aaff5910f..26306e417 100644 --- a/src/gui/config_display.cpp +++ b/src/gui/config_display.cpp @@ -18,70 +18,91 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "config_display.hpp" -#include "widget_set.hpp" +#include "widget_manager.hpp" #include "user_config.hpp" #include "menu_manager.hpp" #include "sdldrv.hpp" #include "translation.hpp" enum WidgetTokens { - WTOK_FULLSCREEN, WTOK_BACK + WTOK_TITLE, + + WTOK_FULLSCREEN, + + WTOK_EMPTY, + + WTOK_QUIT }; ConfigDisplay::ConfigDisplay() { - CreateMenu(); -} + const bool SHOW_RECT = true; + const bool SHOW_TEXT = true; + widget_manager->set_initial_rect_state(SHOW_RECT, WGT_AREA_ALL, WGT_TRANS_BLACK); + widget_manager->set_initial_text_state(SHOW_TEXT, "", WGT_FNT_MED, Font::ALIGN_CENTER, Font::ALIGN_CENTER ); -//----------------------------------------------------------------------------- -void ConfigDisplay::CreateMenu() -{ - m_menu_id = widgetSet -> vstack(0); - widgetSet -> label(m_menu_id, _("Display Settings"), GUI_LRG, GUI_ALL, 0, 0); - - const int VA = widgetSet -> varray(m_menu_id); - m_fullscreen_menu_id = widgetSet -> start(VA, _("Fullscreen mode"), GUI_MED, - WTOK_FULLSCREEN); + widget_manager->add_wgt( WTOK_TITLE, 40, 7); + widget_manager->set_wgt_text( WTOK_TITLE, _("Display Settings")); + widget_manager->break_line(); + widget_manager->set_initial_activation_state(true); + widget_manager->add_wgt( WTOK_FULLSCREEN, 40, 7); if(user_config->m_fullscreen) - widgetSet->set_label(m_fullscreen_menu_id, _("Window mode")); - widgetSet -> space(VA); - widgetSet -> state(VA, _("Press to go back"), GUI_SML, WTOK_BACK); - widgetSet -> layout(m_menu_id, 0, 0); -} // CreateMenu + { + widget_manager->set_wgt_text( WTOK_FULLSCREEN, _("Fullscreen mode")); + } + else + { + widget_manager->set_wgt_text( WTOK_FULLSCREEN, _("Fullscreen mode")); + } + widget_manager->break_line(); + + 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->break_line(); + + 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 ); +} //----------------------------------------------------------------------------- ConfigDisplay::~ConfigDisplay() { - widgetSet -> delete_widget(m_menu_id) ; +// widgetSet -> delete_widget(m_menu_id) ; + widget_manager->delete_wgts(); } //----------------------------------------------------------------------------- -void ConfigDisplay::update(float dt) +/*void ConfigDisplay::update(float dt) { widgetSet -> timer(m_menu_id, dt) ; widgetSet -> paint(m_menu_id) ; -} +}*/ //----------------------------------------------------------------------------- void ConfigDisplay::select() { - switch ( widgetSet -> get_token (widgetSet -> click()) ) + switch ( widget_manager->get_selected_wgt()) { case WTOK_FULLSCREEN: drv_toggleFullscreen(); - widgetSet -> delete_widget(m_menu_id) ; +// widgetSet -> delete_widget(m_menu_id) ; // Since changing the video mode in drv_toggleFullscreen deletes all // display lists, textures etc., we have to load the menu again. // drv_toggleFullscreen takes care of general material, general // widgetSet, etc. - CreateMenu(); +// CreateMenu(); if(user_config->m_fullscreen) - widgetSet->set_label(m_fullscreen_menu_id, _("Window mode")); + widget_manager->set_wgt_text( WTOK_FULLSCREEN, _("Window mode")); else - widgetSet->set_label(m_fullscreen_menu_id, _("Fullscreen mode")); + widget_manager->set_wgt_text( WTOK_FULLSCREEN, _("Fullscreen mode")); break; - case WTOK_BACK: + case WTOK_QUIT: menu_manager->popMenu(); break; default: break; diff --git a/src/gui/config_display.hpp b/src/gui/config_display.hpp index 4ffae729e..f1796c5a2 100644 --- a/src/gui/config_display.hpp +++ b/src/gui/config_display.hpp @@ -24,12 +24,11 @@ class ConfigDisplay: public BaseGUI { - void CreateMenu(); public: ConfigDisplay(); ~ConfigDisplay(); - void update(float dt); +// void update(float dt); void select(); private: diff --git a/src/gui/config_sound.cpp b/src/gui/config_sound.cpp index d0d5dae04..0cb688312 100644 --- a/src/gui/config_sound.cpp +++ b/src/gui/config_sound.cpp @@ -18,90 +18,109 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "config_sound.hpp" -#include "widget_set.hpp" +#include "widget_manager.hpp" #include "user_config.hpp" #include "menu_manager.hpp" #include "translation.hpp" enum WidgetTokens { + WTOK_TITLE, + WTOK_MUSIC, WTOK_SFX, - WTOK_BACK, + + WTOK_EMPTY, + + WTOK_QUIT, }; ConfigSound::ConfigSound() { - m_menu_id = widgetSet -> vstack(0); - widgetSet -> label(m_menu_id, _("Sound Settings"), GUI_LRG, GUI_ALL, 0, 0); + const bool SHOW_RECT = true; + const bool SHOW_TEXT = true; + widget_manager->set_initial_rect_state(SHOW_RECT, WGT_AREA_ALL, WGT_TRANS_BLACK); + widget_manager->set_initial_text_state(SHOW_TEXT, "", WGT_FNT_MED, Font::ALIGN_CENTER, Font::ALIGN_CENTER ); - const int VA = widgetSet -> varray(m_menu_id); - // The spaces are important, otherwise the set_label calls below will - // increase the width of the container, resulting in a warning being - // printed by widgetSet. + widget_manager->add_wgt(WTOK_TITLE, 40, 7); + widget_manager->set_wgt_text( WTOK_TITLE, _("Sound Settings")); + widget_manager->break_line(); + + widget_manager->set_initial_activation_state(true); + widget_manager->add_wgt(WTOK_MUSIC, 40, 7); if( user_config->doMusic() ) - m_music_menu_id = widgetSet->start(VA,_(" Turn off music "), - GUI_MED, WTOK_MUSIC, GUI_ON); + { + widget_manager->set_wgt_text( WTOK_MUSIC, _("Turn off music")); + } else - m_music_menu_id = widgetSet->start(VA,_(" Turn on music "), - GUI_MED, WTOK_MUSIC, GUI_OFF); + { + widget_manager->set_wgt_text( WTOK_MUSIC, _("Turn on music")); + } + widget_manager->break_line(); + widget_manager->add_wgt(WTOK_SFX, 40, 7); if( user_config->doSFX() ) - m_sfx_menu_id = widgetSet->state(VA,_(" Turn off sound effects "), - GUI_MED, WTOK_SFX, GUI_ON); + { + widget_manager->set_wgt_text( WTOK_SFX, _("Turn off sound effects")); + } else - m_sfx_menu_id = widgetSet->state(VA,_(" Turn on sound effects "), - GUI_MED, WTOK_SFX, GUI_OFF); + { + widget_manager->set_wgt_text( WTOK_SFX, _("Turn on sound effects")); + } + widget_manager->break_line(); - widgetSet -> space(VA); - widgetSet -> state(VA, _("Press to go back"), GUI_SML, WTOK_BACK); - widgetSet -> layout(m_menu_id, 0, 0); + widget_manager->add_wgt(WTOK_EMPTY, 40, 5); + widget_manager->deactivate_wgt(WTOK_EMPTY); + widget_manager->hide_wgt_rect(WTOK_EMPTY); + widget_manager->hide_wgt_text(WTOK_EMPTY); + widget_manager->break_line(); + + 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->break_line(); + + widget_manager->layout(WGT_AREA_ALL); } //----------------------------------------------------------------------------- ConfigSound::~ConfigSound() { - widgetSet -> delete_widget(m_menu_id) ; -} - -//----------------------------------------------------------------------------- -void ConfigSound::update(float dt) -{ - widgetSet -> timer(m_menu_id, dt) ; - widgetSet -> paint(m_menu_id) ; + widget_manager->delete_wgts(); } //----------------------------------------------------------------------------- void ConfigSound::select() { - switch ( widgetSet -> get_token (widgetSet -> click()) ) + switch ( widget_manager->get_selected_wgt()) { case WTOK_MUSIC: if(user_config->doMusic()) { user_config->setMusic(UserConfig::UC_DISABLE); - widgetSet->set_label(m_music_menu_id, _("Turn on music")); + widget_manager->set_wgt_text(WTOK_MUSIC, _("Turn on music")); } else { user_config->setMusic(UserConfig::UC_ENABLE); - widgetSet->set_label(m_music_menu_id, _("Turn off music")); + widget_manager->set_wgt_text(WTOK_MUSIC, _("Turn off music")); } - widgetSet->toggle(m_music_menu_id); +//FIXME:'Toggling' can be achieved with a simple color change, if desired. +// widgetSet->toggle(m_music_menu_id); break; case WTOK_SFX: if(user_config->doSFX()) { user_config->setSFX(UserConfig::UC_DISABLE); - widgetSet->set_label(m_sfx_menu_id, _("Turn on sound effects")); + widget_manager->set_wgt_text(WTOK_SFX, _("Turn on sound effects")); } else { user_config->setSFX(UserConfig::UC_ENABLE); - widgetSet->set_label(m_sfx_menu_id, _("Turn off sound effects")); + widget_manager->set_wgt_text(WTOK_SFX, _("Turn off sound effects")); } - widgetSet->toggle(m_sfx_menu_id); +// widgetSet->toggle(m_sfx_menu_id); break; - case WTOK_BACK: + case WTOK_QUIT: menu_manager->popMenu(); break; default: break; diff --git a/src/gui/config_sound.hpp b/src/gui/config_sound.hpp index b9d9a37b3..88d2c91d9 100644 --- a/src/gui/config_sound.hpp +++ b/src/gui/config_sound.hpp @@ -28,7 +28,6 @@ public: ConfigSound(); ~ConfigSound(); - void update(float dt); void select(); private: diff --git a/src/gui/credits_menu.cpp b/src/gui/credits_menu.cpp index 72cac7908..a60d984b9 100644 --- a/src/gui/credits_menu.cpp +++ b/src/gui/credits_menu.cpp @@ -16,48 +16,88 @@ // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +#include #include +#include #include "credits_menu.hpp" #include "loader.hpp" #include "translation.hpp" +#include "widget_manager.hpp" +#include "menu_manager.hpp" #if defined(WIN32) && !defined(__CYGWIN__) # define strdup _strdup #endif +enum WidgetTokens +{ + WTOK_CREDITS, + WTOK_QUIT +}; + CreditsMenu::CreditsMenu() { - std::string filename; - StringList credits_text_list; - try + std::string line; + std::string credits_text; + + filename = loader->getPath("data/CREDITS"); + std::ifstream file(filename.c_str()); + + if( file.is_open() ) { - filename = loader->getPath("data/CREDITS"); - //FIXME: we should change to c++ - filestreams - FILE *fd = fopen(filename.c_str(), "r"); - char s[1024]; - char *p; - while(fgets(s, 1023, fd)) + while( !file.eof() ) { - credits_text_list.push_back(std::string(s)); + getline(file, line); + credits_text.append(line); + credits_text.push_back('\n'); } // while - fclose(fd); - fd = NULL; + file.close(); } - catch(std::runtime_error& e) + else { printf(_("Couldn't load '%s'\n"),filename.c_str()); - credits_text_list.push_back(_("CREDIT file was not installed properly!!")); - credits_text_list.push_back(_("Please check 'data/CREDIT'!!")); + credits_text.append(_("CREDIT file was not installed properly!!\n")); + credits_text.append(_("Please check 'data/CREDITS'!!")); } - setText(credits_text_list); + + const bool SHOW_RECT = true; + const bool SHOW_TEXT = true; + const WidgetFontSize TEXT_SIZE = WGT_FNT_SML; + + widget_manager->set_initial_activation_state( true ); + widget_manager->set_initial_rect_state(SHOW_RECT, WGT_AREA_ALL, WGT_TRANS_BLACK); + widget_manager->set_initial_text_state(SHOW_TEXT, "", TEXT_SIZE, Font::ALIGN_CENTER, Font::ALIGN_CENTER); + + widget_manager->add_wgt( WTOK_CREDITS, 100, 93); + widget_manager->set_wgt_text( WTOK_CREDITS, credits_text ); + widget_manager->set_wgt_text_x_alignment( WTOK_CREDITS, Font::ALIGN_LEFT ); + //FIXME: maybe I should make scroll names more consistent + widget_manager->enable_wgt_scroll( WTOK_CREDITS ); + widget_manager->break_line(); + + widget_manager->add_wgt( WTOK_QUIT, 40, 7); + widget_manager->set_wgt_text( WTOK_QUIT, _("Go back to the main menu")); + + widget_manager->layout( WGT_AREA_TOP ); } // CreditsMenu //----------------------------------------------------------------------------- CreditsMenu::~CreditsMenu() { + widget_manager->delete_wgts() ; } // ~CreditsMenu +//----------------------------------------------------------------------------- +void CreditsMenu::select() +{ + switch( widget_manager->get_selected_wgt() ) + { + case WTOK_QUIT: + menu_manager->popMenu(); + break; + } +} /* EOF */ diff --git a/src/gui/credits_menu.hpp b/src/gui/credits_menu.hpp index b0ab410ab..a93cdb948 100644 --- a/src/gui/credits_menu.hpp +++ b/src/gui/credits_menu.hpp @@ -20,23 +20,17 @@ #ifndef HEADER_CREDITSMENU_H #define HEADER_CREDITSMENU_H -#include -#include -#include "scrolled_text.hpp" #include "base_gui.hpp" -#include "player.hpp" +//#include "player.hpp" -class CreditsMenu: public ScrolledText +class CreditsMenu: public BaseGUI { -private: - int m_xLeft, m_xRight, m_yBottom, m_yTop; - float m_yPos, m_ySpeed; - int m_numberOfLines; - int m_fontSize; public: CreditsMenu(); ~CreditsMenu(); + + void select (); }; #endif diff --git a/src/gui/difficulty.cpp b/src/gui/difficulty.cpp index df543e5ef..41cf61847 100644 --- a/src/gui/difficulty.cpp +++ b/src/gui/difficulty.cpp @@ -19,45 +19,63 @@ #include "difficulty.hpp" #include "race_manager.hpp" -#include "widget_set.hpp" +#include "widget_manager.hpp" #include "menu_manager.hpp" #include "translation.hpp" enum WidgetTokens { + WTOK_TITLE, + WTOK_HARD, WTOK_MEDIUM, WTOK_EASY, - WTOK_BACK + + WTOK_QUIT }; Difficulty::Difficulty() { - m_menu_id = widgetSet -> vstack(0); + const bool SHOW_RECT = true; + const bool SHOW_TEXT = true; + widget_manager->set_initial_rect_state(SHOW_RECT, WGT_AREA_ALL, WGT_TRANS_BLACK); + widget_manager->set_initial_text_state(SHOW_TEXT, "", WGT_FNT_MED, Font::ALIGN_CENTER, Font::ALIGN_CENTER ); - widgetSet -> label(m_menu_id, _("Choose your skill level"), GUI_LRG, GUI_ALL, 0, 0); + widget_manager->add_wgt(WTOK_TITLE, 60, 7); + widget_manager->show_wgt_rect(WTOK_TITLE); + widget_manager->show_wgt_text(WTOK_TITLE); + widget_manager->set_wgt_text(WTOK_TITLE, + _("Choose your skill level")); + widget_manager->break_line(); - const int VA = widgetSet -> varray(m_menu_id); - widgetSet -> space(m_menu_id); - widgetSet -> space(m_menu_id); - widgetSet -> state(VA, _("Racer"), GUI_MED, WTOK_HARD); - widgetSet -> state(VA, _("Driver"), GUI_MED, WTOK_MEDIUM); - widgetSet -> start(VA, _("Novice"), GUI_MED, WTOK_EASY); - widgetSet -> space(VA); - widgetSet -> state(VA, _("Press to go back"), GUI_SML, WTOK_BACK); + widget_manager->set_initial_activation_state(true); + widget_manager->add_wgt(WTOK_HARD, 60, 7); + widget_manager->set_wgt_text(WTOK_HARD, _("Racer")); + widget_manager->break_line(); - widgetSet -> layout(m_menu_id, 0, 0); + widget_manager->add_wgt(WTOK_MEDIUM, 60, 7); + widget_manager->set_wgt_text(WTOK_MEDIUM, _("Driver")); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_EASY, 60, 7); + widget_manager->set_wgt_text(WTOK_EASY, _("Novice")); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_QUIT, 60, 7); + widget_manager->set_wgt_text(WTOK_QUIT, _("Press to go back")); + + widget_manager->layout(WGT_AREA_ALL); } // Difficulty //----------------------------------------------------------------------------- Difficulty::~Difficulty() { - widgetSet -> delete_widget(m_menu_id) ; + widget_manager->delete_wgts(); } // ~Difficulty //----------------------------------------------------------------------------- void Difficulty::select() { - switch ( widgetSet -> get_token (widgetSet -> click()) ) + switch ( widget_manager->get_selected_wgt()) { case WTOK_EASY: race_manager->setDifficulty(RD_EASY); @@ -71,7 +89,7 @@ void Difficulty::select() race_manager->setDifficulty(RD_HARD); menu_manager->pushMenu(MENUID_CHARSEL_P1); break; - case WTOK_BACK: + case WTOK_QUIT: menu_manager->popMenu(); break; default: break; diff --git a/src/gui/game_mode.cpp b/src/gui/game_mode.cpp index 73edea9d7..c12a1c0a1 100644 --- a/src/gui/game_mode.cpp +++ b/src/gui/game_mode.cpp @@ -18,12 +18,13 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "game_mode.hpp" -#include "widget_set.hpp" +#include "widget_manager.hpp" #include "race_manager.hpp" #include "menu_manager.hpp" #include "translation.hpp" enum WidgetTokens { + WTOK_TITLE, WTOK_GP, WTOK_QUICKRACE, WTOK_TIMETRIAL, @@ -32,7 +33,52 @@ enum WidgetTokens { GameMode::GameMode() { - m_menu_id = widgetSet -> vstack(0); + widget_manager->add_wgt(WTOK_TITLE, 50, 7); + widget_manager->show_wgt_rect( WTOK_TITLE ); + widget_manager->set_wgt_text( WTOK_TITLE, _("Choose a Race Mode")); + widget_manager->set_wgt_text_size( WTOK_TITLE, WGT_FNT_LRG ); + widget_manager->show_wgt_text( WTOK_TITLE ); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_GP, 50, 7); + widget_manager->show_wgt_rect( WTOK_GP ); + widget_manager->set_wgt_text( WTOK_GP, _("Grand Prix")); + widget_manager->set_wgt_text_size( WTOK_GP, WGT_FNT_MED ); + widget_manager->show_wgt_text( WTOK_GP ); + widget_manager->activate_wgt( WTOK_GP ); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_QUICKRACE, 50, 7); + widget_manager->show_wgt_rect( WTOK_QUICKRACE ); + widget_manager->set_wgt_text( WTOK_QUICKRACE, _("Quick Race")); + widget_manager->set_wgt_text_size( WTOK_QUICKRACE, WGT_FNT_MED ); + widget_manager->show_wgt_text( WTOK_QUICKRACE ); + widget_manager->activate_wgt( WTOK_QUICKRACE ); + widget_manager->break_line(); + + if( race_manager->getNumPlayers() == 1 ) + { + widget_manager->add_wgt(WTOK_TIMETRIAL, 50, 7); + widget_manager->show_wgt_rect( WTOK_TIMETRIAL ); + widget_manager->set_wgt_text( WTOK_TIMETRIAL, _("Time Trial")); + widget_manager->set_wgt_text_size( WTOK_TIMETRIAL, WGT_FNT_MED ); + widget_manager->show_wgt_text( WTOK_TIMETRIAL ); + widget_manager->activate_wgt( WTOK_TIMETRIAL ); + widget_manager->break_line(); + } + + widget_manager->add_wgt(WidgetManager::WGT_NONE, 50, 7); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_BACK, 50, 7); + widget_manager->show_wgt_rect( WTOK_BACK ); + widget_manager->set_wgt_text( WTOK_BACK, _("Press to go back")); + widget_manager->set_wgt_text_size( WTOK_BACK, WGT_FNT_SML ); + widget_manager->show_wgt_text( WTOK_BACK ); + widget_manager->activate_wgt( WTOK_BACK ); + + widget_manager->layout(WGT_AREA_ALL); +/* m_menu_id = widgetSet -> vstack(0); widgetSet -> label(m_menu_id, _("Choose a Race Mode"), GUI_LRG); @@ -47,19 +93,20 @@ GameMode::GameMode() widgetSet -> space(VA); widgetSet -> state(VA,_("Press to go back"), GUI_SML, WTOK_BACK); widgetSet -> space(VA); - widgetSet -> layout(m_menu_id, 0, 0); + widgetSet -> layout(m_menu_id, 0, 0);*/ } //----------------------------------------------------------------------------- GameMode::~GameMode() { - widgetSet -> delete_widget(m_menu_id) ; + widget_manager->delete_wgts(); } //----------------------------------------------------------------------------- void GameMode::select() { - switch ( widgetSet -> get_token (widgetSet -> click()) ) +// switch ( widgetSet -> get_token (widgetSet -> click()) ) + switch ( widget_manager->get_selected_wgt() ) { case WTOK_GP: race_manager->setRaceMode(RaceSetup::RM_GRAND_PRIX); diff --git a/src/gui/grand_prix_ending.cpp b/src/gui/grand_prix_ending.cpp index 4c43a82c3..ecbf355d0 100644 --- a/src/gui/grand_prix_ending.cpp +++ b/src/gui/grand_prix_ending.cpp @@ -26,7 +26,7 @@ #include "sound_manager.hpp" #include "grand_prix_ending.hpp" #include "kart_properties_manager.hpp" -#include "widget_set.hpp" +#include "widget_manager.hpp" #include "race_manager.hpp" #include "game_manager.hpp" #include "user_config.hpp" @@ -39,6 +39,16 @@ #if defined(WIN32) && !defined(__CYGWIN__) # define snprintf _snprintf #endif + +enum WidgetTokens +{ + WTOK_TITLE, + WTOK_QUIT, + + WTOK_FIRSTKART +}; + + GrandPrixEnd::GrandPrixEnd() : m_kart(0) { @@ -48,7 +58,7 @@ GrandPrixEnd::GrandPrixEnd() m_context = new ssgContext; oldContext->makeCurrent(); - m_menu_id = widgetSet -> vstack(0); +// m_menu_id = widgetSet -> vstack(0); int highest = 0; //FIXME: We go from the back to the front because the players are in the @@ -64,13 +74,19 @@ GrandPrixEnd::GrandPrixEnd() static char output[MAX_MESSAGE_LENGTH]; snprintf(output, sizeof(output), _("The winner is %s!"),WINNING_KART->getName().c_str()); - widgetSet -> label(m_menu_id, output, GUI_LRG, GUI_ALL, 0, 0); + widget_manager->add_wgt( WTOK_TITLE, 60, 10); + widget_manager->show_wgt_rect(WTOK_TITLE); + widget_manager->show_wgt_text(WTOK_TITLE); + widget_manager->set_wgt_text(WTOK_TITLE, output); + widget_manager->set_wgt_text_size(WTOK_TITLE, WGT_FNT_LRG); + widget_manager->break_line(); +// widgetSet -> label(m_menu_id, output, GUI_LRG, GUI_ALL, 0, 0); const unsigned int MAX_STR_LEN = 60; const unsigned int NUM_KARTS = world->getNumKarts(); - const int VA = widgetSet->varray(m_menu_id); +// const int VA = widgetSet->varray(m_menu_id); Kart *kart; int *scores = new int[NUM_KARTS]; @@ -114,16 +130,25 @@ GrandPrixEnd::GrandPrixEnd() kart = world->getKart(position[i]); sprintf((char*)(m_score + MAX_STR_LEN * i), "%d. %s %d", i + 1, kart->getName().c_str(), scores[i]); - widgetSet -> label(VA, (char*)(m_score + MAX_STR_LEN * i), GUI_MED, - GUI_ALL); + + widget_manager->add_wgt(WTOK_FIRSTKART + i, 40, 5); + widget_manager->show_wgt_rect(WTOK_FIRSTKART + i); + widget_manager->show_wgt_text(WTOK_FIRSTKART + i); + widget_manager->set_wgt_text(WTOK_FIRSTKART + i, + (char*)(m_score + MAX_STR_LEN * i)); + widget_manager->set_wgt_text_size(WTOK_FIRSTKART + i, WGT_FNT_SML); + widget_manager->break_line(); } delete []scores; delete []position; - widgetSet -> space(m_menu_id); - widgetSet -> label(m_menu_id, _("Back to the main menu"), GUI_LRG, GUI_ALL, 0, 0); + widget_manager->add_wgt(WTOK_QUIT, 40, 7); + widget_manager->activate_wgt(WTOK_QUIT); + widget_manager->show_wgt_rect(WTOK_QUIT); + widget_manager->show_wgt_text(WTOK_QUIT); + widget_manager->set_wgt_text(WTOK_QUIT, _("Back to the main menu")); - widgetSet -> layout(m_menu_id, 0, 1); + widget_manager->layout(WGT_AREA_ALL); m_kart = new ssgTransform; m_kart->ref(); @@ -146,7 +171,8 @@ GrandPrixEnd::GrandPrixEnd() //----------------------------------------------------------------------------- GrandPrixEnd::~GrandPrixEnd() { - widgetSet -> delete_widget(m_menu_id); + widget_manager->delete_wgts(); + //widgetSet -> delete_widget(m_menu_id); ssgDeRefDelete(m_kart); delete m_context; diff --git a/src/gui/grand_prix_select.cpp b/src/gui/grand_prix_select.cpp index 8944a6f7f..8b0e2bb73 100644 --- a/src/gui/grand_prix_select.cpp +++ b/src/gui/grand_prix_select.cpp @@ -21,23 +21,42 @@ #include "loader.hpp" #include "string_utils.hpp" #include "grand_prix_select.hpp" -#include "widget_set.hpp" +#include "widget_manager.hpp" #include "menu_manager.hpp" #include "race_manager.hpp" #include "user_config.hpp" #include "font.hpp" #include "translation.hpp" +enum WidgetTokens +{ + WTOK_TITLE, + + //FIXME: finish the tokens + + WTOK_EMPTY0, + WTOK_DESCRIPTION, + WTOK_EMPTY1, + WTOK_QUIT, + + WTOK_FIRSTPRIX +}; + GrandPrixSelect::GrandPrixSelect() { - m_menu_id = widgetSet -> varray(0); + const bool SHOW_RECT = true; + const bool SHOW_TEXT = true; + widget_manager->set_initial_rect_state(SHOW_RECT, WGT_AREA_ALL, WGT_TRANS_BLACK); + widget_manager->set_initial_text_state(SHOW_TEXT, "", WGT_FNT_MED, Font::ALIGN_CENTER, Font::ALIGN_CENTER ); - widgetSet -> label(m_menu_id, _("Choose a Grand Prix"), GUI_LRG, GUI_ALL, 0, 0); - widgetSet -> space(m_menu_id); + widget_manager->add_wgt(WTOK_TITLE, 40, 7); + widget_manager->set_wgt_text(WTOK_TITLE, _("Choose a Grand Prix")); + widget_manager->break_line(); std::set result; loader->listFiles(result, "data"); + widget_manager->set_initial_activation_state(true); // Findout which grand prixs are available and load them int nId = 0; for(std::set::iterator i = result.begin(); @@ -48,37 +67,67 @@ GrandPrixSelect::GrandPrixSelect() std::string fullPath= "data/" + (std::string)*i; CupData cup(fullPath.c_str()); m_all_cups.push_back(cup); - if(nId==0) + widget_manager->add_wgt(WTOK_FIRSTPRIX + nId, 40, 7); + widget_manager->set_wgt_text(WTOK_FIRSTPRIX + nId, cup.getName()); +/* if(nId==0) { widgetSet -> start(m_menu_id, cup.getName(), GUI_SML, nId, 0); } else { widgetSet -> state(m_menu_id, cup.getName(), GUI_SML, nId, 0); - } + }*/ + widget_manager->break_line(); nId++; } // if } // for i - widgetSet -> space(m_menu_id); - widgetSet -> state(m_menu_id,_("Press to go back"), GUI_SML, -1); - widgetSet -> layout(m_menu_id, 0, 0); - m_rect = widgetSet->rect(10, 10, user_config->m_width-20, 34, GUI_ALL, 10); + + widget_manager->set_initial_activation_state(false); + widget_manager->add_wgt(WTOK_EMPTY0, 60, 7); + widget_manager->hide_wgt_rect(WTOK_EMPTY0); + widget_manager->hide_wgt_text(WTOK_EMPTY0); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_DESCRIPTION, 80, 7); + widget_manager->hide_wgt_rect(WTOK_DESCRIPTION); + widget_manager->set_wgt_text(WTOK_DESCRIPTION, _("No Grand Prix selected")); + widget_manager->set_wgt_text_size(WTOK_DESCRIPTION, WGT_FNT_SML); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_EMPTY1, 60, 7); + widget_manager->hide_wgt_rect(WTOK_EMPTY1); + widget_manager->hide_wgt_text(WTOK_EMPTY1); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_QUIT, 60, 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->activate_wgt(WTOK_QUIT); + + widget_manager->layout(WGT_AREA_ALL); + //m_rect = widgetSet->rect(10, 10, user_config->m_width-20, 34, GUI_ALL, 10);*/ } // GrandPrixSelect //----------------------------------------------------------------------------- GrandPrixSelect::~GrandPrixSelect() { - widgetSet -> delete_widget(m_menu_id) ; - glDeleteLists(m_rect, 1); + widget_manager->delete_wgts(); +// widgetSet -> delete_widget(m_menu_id) ; +// glDeleteLists(m_rect, 1); } // GrandPrixSelect //----------------------------------------------------------------------------- void GrandPrixSelect::update(float dt) { BaseGUI::update(dt); - const int CLICKED_TOKEN = widgetSet->get_token(widgetSet->click()); - if(CLICKED_TOKEN == -1) return; + const int CLICKED_TOKEN = widget_manager->get_selected_wgt(); + if(CLICKED_TOKEN < WTOK_FIRSTPRIX) return; + const CupData &cup = m_all_cups[CLICKED_TOKEN - WTOK_FIRSTPRIX]; + widget_manager->set_wgt_text(WTOK_DESCRIPTION, cup.getDescription()); + +//FIXME: The following triggers a crash; it is left to be investigated later. +#if 0 glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); @@ -90,14 +139,14 @@ void GrandPrixSelect::update(float dt) glBindTexture(GL_TEXTURE_2D, 0); const GLfloat BACKGROUND_COLOUR[4] = { 0.3f, 0.3f, 0.3f, 0.5f }; glColor4fv(BACKGROUND_COLOUR); - glCallList(m_rect); glPopMatrix(); - font_gui->Print(cup.getDescription(), GUI_MED, + font_gui->Print(cup.getDescription(), WGT_FNT_MED, Font::ALIGN_CENTER, -1, Font::ALIGN_BOTTOM, 10); glDisable(GL_BLEND); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); +#endif return; } @@ -105,8 +154,8 @@ void GrandPrixSelect::update(float dt) //----------------------------------------------------------------------------- void GrandPrixSelect::select() { - const int CLICKED_TOKEN = widgetSet->get_token(widgetSet->click()); - if(CLICKED_TOKEN == -1) + const int CLICKED_TOKEN = widget_manager->get_selected_wgt(); + if(CLICKED_TOKEN == WTOK_QUIT) { menu_manager->popMenu(); return; diff --git a/src/gui/grand_prix_select.hpp b/src/gui/grand_prix_select.hpp index e91adb90a..56c9a3840 100644 --- a/src/gui/grand_prix_select.hpp +++ b/src/gui/grand_prix_select.hpp @@ -28,7 +28,6 @@ class GrandPrixSelect: public BaseGUI { private: std::vector m_all_cups; - int m_rect; public: GrandPrixSelect(); ~GrandPrixSelect(); diff --git a/src/gui/help_menu.cpp b/src/gui/help_menu.cpp index def39b6d0..edc8a179c 100644 --- a/src/gui/help_menu.cpp +++ b/src/gui/help_menu.cpp @@ -18,7 +18,7 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "help_menu.hpp" -#include "widget_set.hpp" +#include "widget_manager.hpp" #include "race_manager.hpp" #include "menu_manager.hpp" #include "user_config.hpp" @@ -27,7 +27,46 @@ #include "material.hpp" #include "translation.hpp" -enum WidgetTokens { +enum WidgetTokens +{ +/* For the first screen */ + WTOK_MSG1, + WTOK_MSG2, + WTOK_MSG3, + WTOK_MSG4, + WTOK_MSG5, + + WTOK_EMPTY, + + //Change this so it's not a static amount of keys that is supported + WTOK_LEFT, + WTOK_RIGHT, + WTOK_ACCEL, + WTOK_BRAKE, + WTOK_WHEELIE, + WTOK_RESCUE, + WTOK_FIRE, + WTOK_JUMP, + + WTOK_LEFTKEY, + WTOK_RIGHTKEY, + WTOK_ACCELKEY, + WTOK_BRAKEKEY, + WTOK_WHEELIEKEY, + WTOK_RESCUEKEY, + WTOK_FIREKEY, + WTOK_JUMPKEY, + +/* For the second screen */ + WTOK_MSG6, + + WTOK_ITEMIMG1, WTOK_ITEMTXT1, + WTOK_ITEMIMG2, WTOK_ITEMTXT2, + WTOK_ITEMIMG3, WTOK_ITEMTXT3, + WTOK_ITEMIMG4, WTOK_ITEMTXT4, + WTOK_ITEMIMG5, WTOK_ITEMTXT5, + WTOK_ITEMIMG6, WTOK_ITEMTXT6, + WTOK_FIRST_PAGE, WTOK_SECOND_PAGE, WTOK_QUIT @@ -53,7 +92,7 @@ HelpMenu::HelpMenu() //----------------------------------------------------------------------------- HelpMenu::~HelpMenu() { - widgetSet -> delete_widget(m_menu_id) ; + widget_manager->delete_wgts() ; if (m_box != NULL && m_silver_coin != NULL && m_gold_coin != NULL && m_banana != NULL ) @@ -124,18 +163,26 @@ void HelpMenu::update(float dt) //----------------------------------------------------------------------------- void HelpMenu::switch_to_first_screen() { - m_menu_id = widgetSet->vstack(0); + const bool SHOW_RECT = true; + const bool SHOW_TEXT = true; + const WidgetFontSize TEXT_SIZE = WGT_FNT_SML; - //FIXME: if an hstack has no items, it segfaults - const int HS1 = widgetSet->hstack(m_menu_id); - widgetSet -> filler(HS1); - widgetSet -> label(HS1, _("Force your rivals bite *your* dust!"), GUI_SML); - widgetSet -> filler(HS1); + widget_manager->set_initial_rect_state( SHOW_RECT, WGT_AREA_ALL, WGT_TRANS_BLACK ); + widget_manager->set_initial_text_state( SHOW_TEXT, "", TEXT_SIZE, Font::ALIGN_CENTER, Font::ALIGN_CENTER ); - const int HS2 = widgetSet->harray(m_menu_id); - widgetSet->label(HS2, _("Avoid bananas"), GUI_SML); - widgetSet->label(HS2, _("Grab blue boxes and coins"), GUI_SML); + /*Help header*/ + widget_manager->add_wgt(WTOK_MSG1, 50, 7); + widget_manager->set_wgt_text( WTOK_MSG1, _("Force your rivals bite *your* dust!") ); + widget_manager->break_line(); + widget_manager->add_wgt(WTOK_MSG2, 60, 7); + widget_manager->set_wgt_text( WTOK_MSG2, _("Grab blue boxes and coins") ); + + widget_manager->add_wgt(WTOK_MSG3, 30, 7); + widget_manager->set_wgt_text( WTOK_MSG3, _("Avoid bananas") ); + widget_manager->break_line(); + + /*Rotating 3D models*/ ssgEntity* hm = herring_manager->getHerringModel(HE_RED); ssgDeRefDelete(m_box); m_box = new ssgTransform; @@ -160,119 +207,241 @@ void HelpMenu::switch_to_first_screen() m_banana->ref(); m_banana->addKid(hm); - widgetSet -> filler(m_menu_id); - widgetSet -> filler(m_menu_id); - widgetSet -> filler(m_menu_id); - widgetSet -> filler(m_menu_id); - widgetSet -> filler(m_menu_id); + /*Empty widget to cover the space for the 3D models*/ + widget_manager->add_wgt(WTOK_EMPTY, 100, 15); + widget_manager->hide_wgt_rect(WTOK_EMPTY); + widget_manager->hide_wgt_text(WTOK_EMPTY); + widget_manager->break_line(); - widgetSet -> filler(m_menu_id); - widgetSet -> filler(m_menu_id); - widgetSet -> filler(m_menu_id); - widgetSet -> filler(m_menu_id); - widgetSet -> filler(m_menu_id); - - widgetSet->multi(m_menu_id, + widget_manager->add_wgt(WTOK_MSG4, 100, 10); + widget_manager->set_wgt_text( WTOK_MSG4, //Next line starts at column 0 to avoid spaces in the GUI _("At high speeds wheelies drive you faster, but you can't steer. If you\n\ -get stuck or fall too far, use the rescue button to get back on track."), - GUI_SML); +get stuck or fall too far, use the rescue button to get back on track.")); + widget_manager->break_line(); - widgetSet -> filler(m_menu_id); + /*Current key bindings*/ + widget_manager->add_wgt(WTOK_MSG5, 70, 7); + widget_manager->set_wgt_text( WTOK_MSG5, + _("Check the current key bindings for the first player")); + widget_manager->break_line(); - widgetSet->label(m_menu_id, - _("Check the current keys bindings for the first player:"), - GUI_SML); + widget_manager->add_wgt(WTOK_LEFT, 20, 5); + widget_manager->set_wgt_round_corners(WTOK_LEFT, WGT_AREA_LFT ); + widget_manager->set_wgt_text(WTOK_LEFT, sKartAction2String[KC_LEFT]); + widget_manager->add_wgt(WTOK_LEFTKEY, 20, 5); + widget_manager->set_wgt_round_corners(WTOK_LEFTKEY, WGT_AREA_RGT ); + widget_manager->set_wgt_text(WTOK_LEFTKEY, + user_config->getInputAsString(0, (KartActions)KC_LEFT).c_str()); + widget_manager->break_line(); - const int HS3 = widgetSet->hstack(m_menu_id); - widgetSet -> filler(HS3); - const int CHANGE_ID = widgetSet->varray(HS3); - const int LABEL_ID = widgetSet->varray(HS3); - widgetSet -> filler(HS3); + widget_manager->add_wgt(WTOK_RIGHT, 20, 5); + widget_manager->set_wgt_round_corners(WTOK_RIGHT, WGT_AREA_LFT ); + widget_manager->set_wgt_text(WTOK_RIGHT, sKartAction2String[KC_RIGHT]); + widget_manager->add_wgt(WTOK_RIGHTKEY, 20, 5); + widget_manager->set_wgt_round_corners(WTOK_RIGHTKEY, WGT_AREA_RGT ); + widget_manager->set_wgt_text(WTOK_RIGHTKEY, + user_config->getInputAsString(0, (KartActions)KC_RIGHT).c_str()); + widget_manager->break_line(); - for(int i = KC_FIRST; i <= KC_LAST; i++) - { - // *sigh* widget set stores only pointer to strings, so - // to make sure that all key-strings are permanent, they - // are assigned to an array m_all_keys within this object. - m_all_keys[i]=user_config->getInputAsString(0, (KartActions)i); - widgetSet->label(LABEL_ID, sKartAction2String[i], GUI_SML, GUI_LFT); - widgetSet->label(CHANGE_ID, m_all_keys[i].c_str(), GUI_SML, GUI_RGT); - } - widgetSet->start(m_menu_id,_("Next screen"), GUI_SML, WTOK_SECOND_PAGE); - widgetSet->state(m_menu_id,_("Go back to the main menu"), GUI_SML, WTOK_QUIT); - widgetSet->layout(m_menu_id, 0, 0); + widget_manager->add_wgt(WTOK_ACCEL, 20, 5); + widget_manager->set_wgt_round_corners(WTOK_ACCEL, WGT_AREA_LFT ); + widget_manager->set_wgt_text(WTOK_ACCEL, sKartAction2String[KC_ACCEL]); + widget_manager->add_wgt(WTOK_ACCELKEY, 20, 5); + widget_manager->set_wgt_round_corners(WTOK_ACCELKEY, WGT_AREA_RGT ); + widget_manager->set_wgt_text(WTOK_ACCELKEY, + user_config->getInputAsString(0, (KartActions)KC_ACCEL).c_str()); + widget_manager->break_line(); + widget_manager->add_wgt(WTOK_BRAKE, 20, 5); + widget_manager->set_wgt_round_corners(WTOK_BRAKE, WGT_AREA_LFT ); + widget_manager->set_wgt_text(WTOK_BRAKE, sKartAction2String[KC_BRAKE]); + widget_manager->add_wgt(WTOK_BRAKEKEY, 20, 5); + widget_manager->set_wgt_round_corners(WTOK_BRAKEKEY, WGT_AREA_RGT ); + widget_manager->set_wgt_text(WTOK_BRAKEKEY, + user_config->getInputAsString(0, (KartActions)KC_BRAKE).c_str()); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_WHEELIE, 20, 5); + widget_manager->set_wgt_round_corners(WTOK_WHEELIE, WGT_AREA_LFT ); + widget_manager->set_wgt_text(WTOK_WHEELIE, sKartAction2String[KC_WHEELIE]); + widget_manager->add_wgt(WTOK_WHEELIEKEY, 20, 5); + widget_manager->set_wgt_round_corners(WTOK_WHEELIEKEY, WGT_AREA_RGT ); + widget_manager->set_wgt_text(WTOK_WHEELIEKEY, + user_config->getInputAsString(0, (KartActions)KC_WHEELIE).c_str()); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_RESCUE, 20, 5); + widget_manager->set_wgt_round_corners(WTOK_RESCUE, WGT_AREA_LFT ); + widget_manager->set_wgt_text(WTOK_RESCUE, sKartAction2String[KC_RESCUE]); + widget_manager->add_wgt(WTOK_RESCUEKEY, 20, 5); + widget_manager->set_wgt_round_corners(WTOK_RESCUEKEY, WGT_AREA_RGT ); + widget_manager->set_wgt_text(WTOK_RESCUEKEY, + user_config->getInputAsString(0, (KartActions)KC_RESCUE).c_str()); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_FIRE, 20, 5); + widget_manager->set_wgt_round_corners(WTOK_FIRE, WGT_AREA_LFT ); + widget_manager->set_wgt_text(WTOK_FIRE, sKartAction2String[KC_FIRE]); + widget_manager->add_wgt(WTOK_FIREKEY, 20, 5); + widget_manager->set_wgt_round_corners(WTOK_FIREKEY, WGT_AREA_RGT ); + widget_manager->set_wgt_text(WTOK_FIREKEY, + user_config->getInputAsString(0, (KartActions)KC_FIRE).c_str()); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_JUMP, 20, 5); + widget_manager->set_wgt_round_corners(WTOK_JUMP, WGT_AREA_LFT ); + widget_manager->set_wgt_text(WTOK_JUMP, sKartAction2String[KC_JUMP]); + widget_manager->add_wgt(WTOK_JUMPKEY, 20, 5); + widget_manager->set_wgt_round_corners(WTOK_JUMPKEY, WGT_AREA_RGT ); + widget_manager->set_wgt_text(WTOK_JUMPKEY, + user_config->getInputAsString(0, (KartActions)KC_JUMP).c_str()); + widget_manager->break_line(); + + /*Buttons at the bottom*/ + widget_manager->add_wgt(WTOK_SECOND_PAGE, 20, 7); + widget_manager->set_wgt_text(WTOK_SECOND_PAGE, _("Next screen")); + widget_manager->activate_wgt(WTOK_SECOND_PAGE); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_QUIT, 40, 7); + widget_manager->set_wgt_text(WTOK_QUIT, _("Go back to the main menu")); + widget_manager->activate_wgt(WTOK_QUIT); + + widget_manager->layout( WGT_AREA_TOP ); } //----------------------------------------------------------------------------- void HelpMenu::switch_to_second_screen() { - + /* Delete 3D models from the first screen */ ssgDeRefDelete(m_box); m_box = 0; ssgDeRefDelete(m_silver_coin); m_silver_coin = 0; ssgDeRefDelete(m_gold_coin); m_gold_coin = 0; ssgDeRefDelete(m_banana); m_banana = 0; - m_menu_id = widgetSet->vstack(0); + /* Add the widgets */ + const bool SHOW_RECT = true; + const WidgetFontSize TEXT_SIZE = WGT_FNT_SML; + widget_manager->set_initial_rect_state( SHOW_RECT, WGT_AREA_ALL, WGT_TRANS_BLACK ); + widget_manager->set_initial_text_state( false, "", TEXT_SIZE, Font::ALIGN_CENTER, Font::ALIGN_CENTER ); - widgetSet->label(m_menu_id, - _("To help you win, there are certain collectables you can grab:"), - GUI_SML); + widget_manager->add_wgt(WTOK_MSG6, 100, 8); + widget_manager->set_wgt_text(WTOK_MSG6, + _("To help you win, there are certain collectables you can grab:")); + widget_manager->show_wgt_text( WTOK_MSG6 ); + widget_manager->break_line(); - const int HA = widgetSet->hstack(m_menu_id); - const int LABEL_ID = widgetSet->varray(HA); - const int IMAGE_ID = widgetSet->vstack(HA); + /* Collectable images and descriptions */ + widget_manager->add_wgt(WTOK_ITEMIMG1, 10, 13); + widget_manager->set_wgt_texture(WTOK_ITEMIMG1, + collectable_manager->getIcon(COLLECT_MISSILE)->getState()->getTextureHandle()); + widget_manager->set_wgt_color(WTOK_ITEMIMG1, WGT_WHITE); + widget_manager->show_wgt_texture(WTOK_ITEMIMG1); + widget_manager->set_wgt_round_corners(WTOK_ITEMIMG1, WGT_AREA_NONE); - const int ICON_SIZE = 64; + widget_manager->add_wgt(WTOK_ITEMTXT1, 90, 13); + widget_manager->set_wgt_text( WTOK_ITEMTXT1, + _("Missile - fast stopper in a straight line")); + widget_manager->show_wgt_text( WTOK_ITEMTXT1 ); + widget_manager->break_line(); - widgetSet->image(IMAGE_ID, collectable_manager->getIcon(COLLECT_MISSILE)->getState()->getTextureHandle(), - ICON_SIZE, ICON_SIZE, GUI_NONE); - widgetSet->label(LABEL_ID, _("Missile - fast stopper in a straight line"), GUI_SML); + widget_manager->add_wgt(WTOK_ITEMIMG2, 10, 13); + widget_manager->set_wgt_texture(WTOK_ITEMIMG2, + collectable_manager->getIcon(COLLECT_HOMING_MISSILE)->getState()->getTextureHandle()); + widget_manager->set_wgt_color(WTOK_ITEMIMG2, WGT_WHITE); + widget_manager->show_wgt_texture( WTOK_ITEMIMG2 ); + widget_manager->set_wgt_round_corners(WTOK_ITEMIMG2, WGT_AREA_NONE); - widgetSet->image(IMAGE_ID, collectable_manager->getIcon(COLLECT_HOMING_MISSILE)->getState()->getTextureHandle(), - ICON_SIZE, ICON_SIZE, GUI_NONE); - widgetSet->label(LABEL_ID, _("Homing missile - follows rivals, but is slower than the missile"), GUI_SML); + widget_manager->add_wgt(WTOK_ITEMTXT2, 90, 13); + widget_manager->set_wgt_text( WTOK_ITEMTXT2, + _("Homing missile - follows rivals, but is slower than the missile")); + widget_manager->show_wgt_text( WTOK_ITEMTXT2 ); + widget_manager->break_line(); - widgetSet->image(IMAGE_ID, collectable_manager->getIcon(COLLECT_SPARK)->getState()->getTextureHandle(), - ICON_SIZE, ICON_SIZE, GUI_NONE); - widgetSet->label(LABEL_ID, _("Fuzzy blob/Spark - very slow, but bounces from walls"), GUI_SML); + widget_manager->add_wgt(WTOK_ITEMIMG3, 10, 13); + widget_manager->set_wgt_texture(WTOK_ITEMIMG3, + collectable_manager->getIcon(COLLECT_SPARK)->getState()->getTextureHandle()); + widget_manager->set_wgt_color(WTOK_ITEMIMG3, WGT_WHITE); + widget_manager->show_wgt_texture( WTOK_ITEMIMG3 ); + widget_manager->set_wgt_round_corners(WTOK_ITEMIMG3, WGT_AREA_NONE); - widgetSet->image(IMAGE_ID, collectable_manager->getIcon(COLLECT_ZIPPER)->getState()->getTextureHandle(), - ICON_SIZE, ICON_SIZE, GUI_NONE); - widgetSet->label(LABEL_ID, _("Zipper - speed boost"), GUI_SML); + widget_manager->add_wgt(WTOK_ITEMTXT3, 90, 13); + widget_manager->set_wgt_text( WTOK_ITEMTXT3, + _("Fuzzy blob/Spark - very slow, but bounces from walls")); + widget_manager->show_wgt_text( WTOK_ITEMTXT3 ); + widget_manager->break_line(); - widgetSet->image(IMAGE_ID, collectable_manager->getIcon(COLLECT_PARACHUTE)->getState()->getTextureHandle(), - ICON_SIZE, ICON_SIZE, GUI_NONE); - widgetSet->label(LABEL_ID, _("Parachute - slows down all karts in a better position!"), GUI_SML); + widget_manager->add_wgt(WTOK_ITEMIMG4, 10, 13); + widget_manager->set_wgt_texture(WTOK_ITEMIMG4, + collectable_manager->getIcon(COLLECT_ZIPPER)->getState()->getTextureHandle()); + widget_manager->set_wgt_color(WTOK_ITEMIMG4, WGT_WHITE); + widget_manager->show_wgt_texture( WTOK_ITEMIMG4 ); + widget_manager->set_wgt_round_corners(WTOK_ITEMIMG4, WGT_AREA_NONE); - widgetSet->image(IMAGE_ID, collectable_manager->getIcon(COLLECT_ANVIL)->getState()->getTextureHandle(), - ICON_SIZE, ICON_SIZE, GUI_NONE); - widgetSet->label(LABEL_ID, _("Anvil - slows down greatly the kart in the first position"), GUI_SML); + widget_manager->add_wgt(WTOK_ITEMTXT4, 90, 13); + widget_manager->set_wgt_text( WTOK_ITEMTXT4, + _("Zipper - speed boost")); + widget_manager->show_wgt_text( WTOK_ITEMTXT4 ); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_ITEMIMG5, 10, 13); + widget_manager->set_wgt_texture(WTOK_ITEMIMG5, + collectable_manager->getIcon(COLLECT_PARACHUTE)->getState()->getTextureHandle()); + widget_manager->set_wgt_color(WTOK_ITEMIMG5, WGT_WHITE); + widget_manager->show_wgt_texture( WTOK_ITEMIMG5 ); + widget_manager->set_wgt_round_corners(WTOK_ITEMIMG5, WGT_AREA_NONE); + + widget_manager->add_wgt(WTOK_ITEMTXT5, 90, 13); + widget_manager->set_wgt_text( WTOK_ITEMTXT5, + _("Parachute - slows down all karts in a better position!")); + widget_manager->show_wgt_text( WTOK_ITEMTXT5 ); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_ITEMIMG6, 10, 13); + widget_manager->set_wgt_texture(WTOK_ITEMIMG6, + collectable_manager->getIcon(COLLECT_ANVIL)->getState()->getTextureHandle()); + widget_manager->set_wgt_color(WTOK_ITEMIMG6, WGT_WHITE); + widget_manager->show_wgt_texture( WTOK_ITEMIMG6 ); + widget_manager->set_wgt_round_corners(WTOK_ITEMIMG6, WGT_AREA_NONE); + + widget_manager->add_wgt(WTOK_ITEMTXT6, 90, 13); + widget_manager->set_wgt_text( WTOK_ITEMTXT6, + _("Anvil - slows down greatly the kart in the first position")); + widget_manager->show_wgt_text( WTOK_ITEMTXT6 ); + widget_manager->break_line(); #ifdef USE_MAGNETS - widgetSet->image(IMAGE_ID, collectable_manager->getIcon(COLLECT_PARACHUTE)->getState()->getTextureHandle(), - ICON_SIZE, ICON_SIZE, GUI_NONE); - widgetSet->label(LABEL_ID, _("Missile - fast stopper in a straight line"), GUI_SML); + //Magnets are currently disabled. #endif - widgetSet->start(m_menu_id,_("Previous screen"), GUI_SML, WTOK_FIRST_PAGE); - widgetSet->state(m_menu_id,_("Go back to the main menu"), GUI_SML, WTOK_QUIT); - widgetSet->layout(m_menu_id, 0, 0); + /*Buttons at the bottom*/ + widget_manager->add_wgt(WTOK_FIRST_PAGE, 25, 7); + widget_manager->set_wgt_text(WTOK_FIRST_PAGE, _("Previous screen")); + widget_manager->show_wgt_text( WTOK_FIRST_PAGE ); + widget_manager->activate_wgt(WTOK_FIRST_PAGE); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_QUIT, 40, 7); + widget_manager->set_wgt_text(WTOK_QUIT, _("Go back to the main menu")); + widget_manager->show_wgt_text( WTOK_QUIT ); + widget_manager->activate_wgt(WTOK_QUIT); + + widget_manager->layout( WGT_AREA_TOP ); } //----------------------------------------------------------------------------- void HelpMenu::select() { - switch( widgetSet->get_token (widgetSet->click())) + switch ( widget_manager->get_selected_wgt() ) { case WTOK_FIRST_PAGE: - widgetSet -> delete_widget(m_menu_id) ; + widget_manager->delete_wgts(); switch_to_first_screen(); break; case WTOK_SECOND_PAGE: - widgetSet -> delete_widget(m_menu_id) ; + widget_manager->delete_wgts(); switch_to_second_screen(); break; diff --git a/src/gui/help_menu.hpp b/src/gui/help_menu.hpp index 3d2e482e3..ae39a873c 100644 --- a/src/gui/help_menu.hpp +++ b/src/gui/help_menu.hpp @@ -22,7 +22,7 @@ #include #include "base_gui.hpp" -#include "player.hpp" +//#include "player.hpp" class ssgTransform; class ssgContext; @@ -30,8 +30,6 @@ class ssgContext; class HelpMenu: public BaseGUI { private: - std::string m_all_keys[KC_LAST+1]; - ssgContext* m_context; ssgTransform* m_box; ssgTransform* m_banana; diff --git a/src/gui/main_menu.cpp b/src/gui/main_menu.cpp index eeb7a8155..b6d1316f2 100644 --- a/src/gui/main_menu.cpp +++ b/src/gui/main_menu.cpp @@ -20,7 +20,7 @@ #include #include "main_menu.hpp" -#include "widget_set.hpp" +#include "widget_manager.hpp" #include "race_manager.hpp" #include "menu_manager.hpp" #include "translation.hpp" @@ -29,38 +29,65 @@ enum WidgetTokens { WTOK_SINGLE, WTOK_MULTI, WTOK_OPTIONS, - WTOK_REPLAY, WTOK_QUIT, + WTOK_EMPTY, WTOK_HELP, - WTOK_CREDITS, + WTOK_CREDITS }; MainMenu::MainMenu() { - m_menu_id = widgetSet -> varray(0); - widgetSet -> space(m_menu_id); - widgetSet -> space(m_menu_id); - widgetSet -> start(m_menu_id, _("Single Player"), GUI_MED, WTOK_SINGLE); - widgetSet -> state(m_menu_id, _("Multiplayer"), GUI_MED, WTOK_MULTI); - widgetSet -> state(m_menu_id, _("Options"), GUI_MED, WTOK_OPTIONS); - widgetSet -> state(m_menu_id, _("Quit"), GUI_MED, WTOK_QUIT); - widgetSet -> space(m_menu_id); - widgetSet -> state(m_menu_id, _("Help"), GUI_SML, WTOK_HELP); - widgetSet -> state(m_menu_id, _("Credits"), GUI_SML, WTOK_CREDITS); - widgetSet -> space(m_menu_id); + const bool SHOW_RECT = true; + const bool SHOW_TEXT = true; + widget_manager->set_initial_activation_state(true); + widget_manager->set_initial_rect_state(SHOW_RECT, WGT_AREA_ALL, WGT_TRANS_BLACK); + widget_manager->set_initial_text_state(SHOW_TEXT, "", WGT_FNT_MED, Font::ALIGN_CENTER, Font::ALIGN_CENTER ); - widgetSet -> layout(m_menu_id, 0, 0); + widget_manager->add_wgt(WTOK_SINGLE, 25, 7); + widget_manager->set_wgt_text( WTOK_SINGLE, _("Single Player") ); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_MULTI, 25, 7); + widget_manager->set_wgt_text( WTOK_MULTI, _("Multiplayer") ); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_OPTIONS, 25, 7); + widget_manager->set_wgt_text( WTOK_OPTIONS, _("Options") ); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_QUIT, 25, 7); + widget_manager->set_wgt_text( WTOK_QUIT, _("Quit") ); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_EMPTY, 25, 7); + widget_manager->hide_wgt_text( WTOK_EMPTY ); + widget_manager->hide_wgt_rect( WTOK_EMPTY ); + widget_manager->deactivate_wgt( WTOK_EMPTY ); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_HELP, 25, 7); + widget_manager->set_wgt_text( WTOK_HELP, _("Help") ); + //FIXME: if text size is not set, we get a crash when resizing the rect to the text + widget_manager->set_wgt_text_size( WTOK_HELP, WGT_FNT_SML ); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_CREDITS, 25, 7); + widget_manager->set_wgt_text( WTOK_CREDITS, _("Credits") ); + widget_manager->set_wgt_text_size( WTOK_CREDITS, WGT_FNT_SML ); + + widget_manager->layout(WGT_AREA_ALL); } //----------------------------------------------------------------------------- MainMenu::~MainMenu() { - widgetSet -> delete_widget(m_menu_id) ; + widget_manager->delete_wgts() ; } //----------------------------------------------------------------------------- void MainMenu::select() { + #if 0 switch ( widgetSet -> get_token (widgetSet -> click()) ) { case WTOK_SINGLE: @@ -89,6 +116,31 @@ void MainMenu::select() menu_manager->pushMenu(MENUID_CREDITS); break; } + #endif + switch ( widget_manager->get_selected_wgt() ) + { + case WTOK_SINGLE: + race_manager->setNumPlayers(1); + menu_manager->pushMenu(MENUID_GAMEMODE); + break; + case WTOK_MULTI: + menu_manager->pushMenu(MENUID_NUMPLAYERS); + break; + + case WTOK_OPTIONS: + menu_manager->pushMenu(MENUID_OPTIONS); + break; + + case WTOK_QUIT: + menu_manager->pushMenu(MENUID_EXITGAME); + break; + case WTOK_HELP: + menu_manager->pushMenu(MENUID_HELP); + break; + case WTOK_CREDITS: + menu_manager->pushMenu(MENUID_CREDITS); + break; + } } //----------------------------------------------------------------------------- diff --git a/src/gui/menu_manager.cpp b/src/gui/menu_manager.cpp index fab724b11..fe1aa5d04 100644 --- a/src/gui/menu_manager.cpp +++ b/src/gui/menu_manager.cpp @@ -47,6 +47,7 @@ #include "grand_prix_select.hpp" #include "sound_manager.hpp" #include "sdldrv.hpp" +#include "widget_manager.hpp" MenuManager* menu_manager= new MenuManager(); @@ -187,6 +188,11 @@ void MenuManager::update() default: break; } // switch + + if( widget_manager->get_selected_wgt() != WidgetManager::WGT_NONE ) + { + widget_manager->lighten_wgt_color(widget_manager->get_selected_wgt()); + } } } diff --git a/src/gui/num_laps.cpp b/src/gui/num_laps.cpp index 6ef425ed2..6dfce74e8 100644 --- a/src/gui/num_laps.cpp +++ b/src/gui/num_laps.cpp @@ -19,19 +19,79 @@ #include "num_laps.hpp" #include "race_manager.hpp" -#include "widget_set.hpp" +#include "widget_manager.hpp" #include "menu_manager.hpp" #if defined(WIN32) && !defined(__CYGWIN__) # define snprintf _snprintf #endif +enum WidgetTokens { + WTOK_TITLE, + + WTOK_NUMLAPS, + + WTOK_LESS, + WTOK_MORE, + + WTOK_START, + WTOK_QUIT +}; + NumLaps::NumLaps() : laps(3) { - m_menu_id = widgetSet -> varray(0); + widget_manager->add_wgt(WTOK_TITLE, 50, 7); + widget_manager->show_wgt_rect(WTOK_TITLE); + widget_manager->show_wgt_text(WTOK_TITLE); + widget_manager->set_wgt_text(WTOK_TITLE, _("Choose number of laps")); + widget_manager->break_line(); + + widget_manager->add_wgt( WidgetManager::WGT_NONE, 100, 5); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_NUMLAPS, 20, 7); + widget_manager->show_wgt_rect(WTOK_NUMLAPS); + widget_manager->show_wgt_text(WTOK_NUMLAPS); + widget_manager->set_wgt_text(WTOK_NUMLAPS, _("Laps: 3")); + widget_manager->break_line(); + + widget_manager->add_wgt( WidgetManager::WGT_NONE, 100, 5); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_LESS, 20, 7); + widget_manager->show_wgt_rect(WTOK_LESS); + widget_manager->show_wgt_text(WTOK_LESS); + widget_manager->set_wgt_text(WTOK_LESS, _("Less")); + widget_manager->activate_wgt(WTOK_LESS); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_MORE, 20, 7); + widget_manager->show_wgt_rect(WTOK_MORE); + widget_manager->show_wgt_text(WTOK_MORE); + widget_manager->set_wgt_text(WTOK_MORE, _("More")); + widget_manager->activate_wgt(WTOK_MORE); + widget_manager->break_line(); + + widget_manager->add_wgt( WidgetManager::WGT_NONE, 100, 5); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_START, 30, 7); + widget_manager->show_wgt_rect(WTOK_START); + widget_manager->show_wgt_text(WTOK_START); + widget_manager->set_wgt_text(WTOK_START, _("Start race")); + widget_manager->activate_wgt(WTOK_START); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_QUIT, 50, 7); + widget_manager->show_wgt_rect(WTOK_QUIT); + widget_manager->show_wgt_text(WTOK_QUIT); + widget_manager->set_wgt_text(WTOK_QUIT, _("Press to go back")); + widget_manager->activate_wgt(WTOK_QUIT); + +/* m_menu_id = widgetSet -> varray(0); widgetSet -> label(m_menu_id, _("Choose number of laps"), GUI_LRG, GUI_ALL, 0, 0 ); - + widgetSet -> space(m_menu_id); - + lap_label_id = widgetSet -> label(m_menu_id, _("Laps: 3")); widgetSet -> space(m_menu_id); widgetSet -> state(m_menu_id, _("Less"), GUI_MED, 10); @@ -41,37 +101,40 @@ NumLaps::NumLaps() : laps(3) widgetSet -> state(m_menu_id, _("Press to go back"), GUI_SML, -1); widgetSet -> space(m_menu_id); - widgetSet -> layout(m_menu_id, 0, 0); + widgetSet -> layout(m_menu_id, 0, 0);*/ + widget_manager->layout(WGT_AREA_ALL); } // ----------------------------------------------------------------------------- NumLaps::~NumLaps() { - widgetSet -> delete_widget(m_menu_id) ; + widget_manager->delete_wgts(); } // ~NumLaps // ----------------------------------------------------------------------------- void NumLaps::select() { - const int id = widgetSet->click(); - const int n = widgetSet->get_token(id); - switch (n) + const int WGT = widget_manager->get_selected_wgt(); +/* const int id = widgetSet->click(); + const int n = widgetSet->get_token(id);*/ + //TEMP + switch (WGT) { - case 10: + case WTOK_LESS: laps = std::max(1, laps-1); - snprintf(lap_label, MAX_MESSAGE_LENGTH, "Laps: %d", laps); - widgetSet->set_label(lap_label_id, lap_label); - break; - case 20: + snprintf(lap_label, MAX_MESSAGE_LENGTH, "Laps: %d", laps); + widget_manager->set_wgt_text(WTOK_NUMLAPS, lap_label); + break; + case WTOK_MORE: laps = std::min(10, laps+1); - snprintf(lap_label, MAX_MESSAGE_LENGTH, "Laps: %d", laps); - widgetSet->set_label(lap_label_id, lap_label); - break; - case 30: + snprintf(lap_label, MAX_MESSAGE_LENGTH, "Laps: %d", laps); + widget_manager->set_wgt_text(WTOK_NUMLAPS, lap_label); + break; + case WTOK_START: race_manager->setNumLaps(laps); race_manager->start(); break; - case -1: + case WTOK_QUIT: menu_manager->popMenu(); break; } diff --git a/src/gui/num_players.cpp b/src/gui/num_players.cpp index d4c0353db..34f6a5961 100644 --- a/src/gui/num_players.cpp +++ b/src/gui/num_players.cpp @@ -19,7 +19,7 @@ #include "num_players.hpp" #include "race_manager.hpp" -#include "widget_set.hpp" +#include "widget_manager.hpp" #include "menu_manager.hpp" #include "translation.hpp" @@ -32,34 +32,58 @@ enum WidgetTokens { NumPlayers::NumPlayers() { - m_menu_id = widgetSet -> varray(0); - widgetSet -> space(m_menu_id); - widgetSet -> start(m_menu_id, _("Two Players"), GUI_MED, WTOK_PLAYER_2); - widgetSet -> state(m_menu_id, _("Three Players"), GUI_MED, WTOK_PLAYER_3); - widgetSet -> state(m_menu_id, _("Four Players"), GUI_MED, WTOK_PLAYER_4); - widgetSet -> space(m_menu_id); - widgetSet -> state(m_menu_id,_("Press to go back"), GUI_SML, WTOK_BACK); - widgetSet -> space(m_menu_id); + widget_manager->add_wgt(WTOK_PLAYER_2, 35, 7); + widget_manager->show_wgt_rect( WTOK_PLAYER_2 ); + widget_manager->set_wgt_text( WTOK_PLAYER_2, _("Two Players") ); + widget_manager->set_wgt_text_size( WTOK_PLAYER_2, WGT_FNT_MED ); + widget_manager->show_wgt_text( WTOK_PLAYER_2 ); + widget_manager->activate_wgt( WTOK_PLAYER_2 ); + widget_manager->break_line(); - widgetSet -> layout(m_menu_id, 0, 0); + widget_manager->add_wgt(WTOK_PLAYER_3, 35, 7); + widget_manager->show_wgt_rect( WTOK_PLAYER_3 ); + widget_manager->set_wgt_text( WTOK_PLAYER_3, _("Three Players") ); + widget_manager->set_wgt_text_size( WTOK_PLAYER_3, WGT_FNT_MED ); + widget_manager->show_wgt_text( WTOK_PLAYER_3 ); + widget_manager->activate_wgt( WTOK_PLAYER_3); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_PLAYER_4, 35, 7); + widget_manager->show_wgt_rect( WTOK_PLAYER_4 ); + widget_manager->set_wgt_text( WTOK_PLAYER_4, _("Four Players") ); + widget_manager->set_wgt_text_size( WTOK_PLAYER_4, WGT_FNT_MED ); + widget_manager->show_wgt_text( WTOK_PLAYER_4 ); + widget_manager->activate_wgt( WTOK_PLAYER_4 ); + widget_manager->break_line(); + + widget_manager->add_wgt(WidgetManager::WGT_NONE, 35, 7); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_BACK, 35, 7); + widget_manager->show_wgt_rect( WTOK_BACK ); + widget_manager->set_wgt_text( WTOK_BACK, _("Press to go back") ); + widget_manager->set_wgt_text_size( WTOK_BACK, WGT_FNT_SML ); + widget_manager->show_wgt_text( WTOK_BACK ); + widget_manager->activate_wgt( WTOK_BACK ); + + widget_manager->layout(WGT_AREA_ALL); } // ----------------------------------------------------------------------------- NumPlayers::~NumPlayers() { - widgetSet -> delete_widget(m_menu_id) ; + widget_manager->delete_wgts() ; } // ----------------------------------------------------------------------------- void NumPlayers::select() { - const int CLICKED_ID = widgetSet -> get_token (widgetSet -> click()); - switch (CLICKED_ID) + switch ( widget_manager->get_selected_wgt() ) { case WTOK_PLAYER_2: case WTOK_PLAYER_3: case WTOK_PLAYER_4: - race_manager->setNumPlayers(CLICKED_ID); + race_manager->setNumPlayers(widget_manager->get_selected_wgt()); menu_manager->pushMenu(MENUID_GAMEMODE); break; case WTOK_BACK: diff --git a/src/gui/options.cpp b/src/gui/options.cpp index 70e9047c2..07b6f12dd 100644 --- a/src/gui/options.cpp +++ b/src/gui/options.cpp @@ -18,11 +18,12 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "options.hpp" -#include "widget_set.hpp" +#include "widget_manager.hpp" #include "menu_manager.hpp" #include "translation.hpp" enum WidgetTokens { + WTOK_TITLE, WTOK_CONTROLS, WTOK_DISPLAY, WTOK_SOUND, @@ -31,7 +32,7 @@ enum WidgetTokens { Options::Options() { - m_menu_id = widgetSet -> varray(0); +/* m_menu_id = widgetSet -> varray(0); widgetSet -> space(m_menu_id); widgetSet -> space(m_menu_id); @@ -51,26 +52,69 @@ Options::Options() widgetSet -> space(m_menu_id); widgetSet -> state(m_menu_id, _("Press to go back"), GUI_SML, WTOK_BACK); - widgetSet -> layout(m_menu_id, 0, 0); + widgetSet -> layout(m_menu_id, 0, 0);*/ + widget_manager->add_wgt(WTOK_TITLE, 35, 7); + widget_manager->show_wgt_rect( WTOK_TITLE ); + widget_manager->set_wgt_text( WTOK_TITLE, _("Options") ); + widget_manager->set_wgt_text_size( WTOK_TITLE, WGT_FNT_LRG ); + widget_manager->show_wgt_text( WTOK_TITLE ); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_CONTROLS, 35, 7); + widget_manager->show_wgt_rect( WTOK_CONTROLS ); + widget_manager->set_wgt_text( WTOK_CONTROLS, _("Player Config") ); + widget_manager->set_wgt_text_size( WTOK_CONTROLS, WGT_FNT_MED ); + widget_manager->show_wgt_text( WTOK_CONTROLS ); + widget_manager->activate_wgt( WTOK_CONTROLS); + widget_manager->break_line(); + + // Don't display the fullscreen menu when called from within the race. + // The fullscreen mode will reload all textures, reload the models, + // ... basically creating a big mess!! (and all of this only thanks + // to windows, who discards all textures, ...) + if(!menu_manager->isSomewhereOnStack(MENUID_RACE)) + { + widget_manager->add_wgt(WTOK_DISPLAY, 35, 7); + widget_manager->show_wgt_rect( WTOK_DISPLAY ); + widget_manager->set_wgt_text( WTOK_DISPLAY, _("Display") ); + widget_manager->set_wgt_text_size( WTOK_DISPLAY, WGT_FNT_MED ); + widget_manager->show_wgt_text( WTOK_DISPLAY ); + widget_manager->activate_wgt( WTOK_DISPLAY ); + widget_manager->break_line(); + } + + widget_manager->add_wgt(WTOK_SOUND, 35, 7); + widget_manager->show_wgt_rect( WTOK_SOUND ); + widget_manager->set_wgt_text( WTOK_SOUND, _("Sound") ); + widget_manager->set_wgt_text_size( WTOK_SOUND, WGT_FNT_MED ); + widget_manager->show_wgt_text( WTOK_SOUND ); + widget_manager->activate_wgt( WTOK_SOUND ); + widget_manager->break_line(); + + widget_manager->add_wgt(WidgetManager::WGT_NONE, 35, 7); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_BACK, 35, 7); + widget_manager->show_wgt_rect( WTOK_BACK ); + widget_manager->set_wgt_text( WTOK_BACK, _("Press to go back") ); + widget_manager->set_wgt_text_size( WTOK_BACK, WGT_FNT_SML ); + widget_manager->show_wgt_text( WTOK_BACK ); + widget_manager->activate_wgt( WTOK_BACK ); + + widget_manager->layout(WGT_AREA_ALL); } // ----------------------------------------------------------------------------- Options::~Options() { - widgetSet -> delete_widget(m_menu_id) ; -} - -// ----------------------------------------------------------------------------- -void Options::update(float dt) -{ - widgetSet -> timer(m_menu_id, dt) ; - widgetSet -> paint(m_menu_id) ; + widget_manager->delete_wgts() ; } // ----------------------------------------------------------------------------- void Options::select() { - switch ( widgetSet -> get_token (widgetSet -> click()) ) + switch ( widget_manager->get_selected_wgt() ) +// switch ( widgetSet -> get_token (widgetSet -> click()) ) { case WTOK_CONTROLS: menu_manager->pushMenu(MENUID_CONFIG_CONTROLS); diff --git a/src/gui/options.hpp b/src/gui/options.hpp index c724a4d83..9018b8703 100644 --- a/src/gui/options.hpp +++ b/src/gui/options.hpp @@ -28,7 +28,6 @@ public: Options(); ~Options(); - void update(float dt); void select(); }; diff --git a/src/gui/player_controls.cpp b/src/gui/player_controls.cpp index 20c9dbcc8..c74ddcea9 100644 --- a/src/gui/player_controls.cpp +++ b/src/gui/player_controls.cpp @@ -20,7 +20,7 @@ #include #include "player_controls.hpp" -#include "widget_set.hpp" +#include "widget_manager.hpp" #include "user_config.hpp" #include "menu_manager.hpp" #include "translation.hpp" @@ -28,43 +28,94 @@ #include +enum WidgetTokens +{ + WTOK_TITLE, + WTOK_PLYR_NAME0, + WTOK_PLYR_NAME1, + + WTOK_LEFT, + WTOK_RIGHT, + WTOK_ACCEL, + WTOK_BRAKE, + WTOK_WHEELIE, + WTOK_JUMP, + WTOK_RESCUE, + WTOK_FIRE, + WTOK_LOOK_BACK, + + WTOK_KEY0, + WTOK_KEY1, + WTOK_KEY2, + WTOK_KEY3, + WTOK_KEY4, + WTOK_KEY5, + WTOK_KEY6, + WTOK_KEY7, + WTOK_KEY8, + + WTOK_QUIT +}; + const char *sKartAction2String[KC_LAST+1] = {_("Left"), _("Right"), _("Accelerate"), _("Brake"), _("Wheelie"), _("Jump"), _("Rescue"), _("Fire"), _("Look back") }; -PlayerControls::PlayerControls(int whichPlayer): m_player_index(whichPlayer), - m_grab_input(false) +PlayerControls::PlayerControls(int whichPlayer): + m_grab_id(WidgetManager::WGT_NONE), m_player_index(whichPlayer), + m_grab_input(false) { // We need the unicode character here, so enable the translation SDL_EnableUNICODE(1); - m_menu_id = widgetSet -> vstack(0); - - sprintf(m_heading, _("Choose your controls, %s"), + + const bool SHOW_RECT = true; + const bool SHOW_TEXT = true; + widget_manager->set_initial_rect_state(SHOW_RECT, WGT_AREA_ALL, WGT_TRANS_BLACK); + widget_manager->set_initial_text_state(SHOW_TEXT, "", WGT_FNT_MED, Font::ALIGN_CENTER, Font::ALIGN_CENTER ); + + widget_manager->add_wgt( WTOK_TITLE, 60, 7); + sprintf(m_heading, _("Choose your controls, %s"), user_config->m_player[m_player_index].getName().c_str()); - widgetSet -> label(m_menu_id, m_heading, GUI_LRG, GUI_ALL, 0, 0); + widget_manager->set_wgt_text( WTOK_TITLE, m_heading); + widget_manager->break_line(); - const int HA = widgetSet->harray(m_menu_id); - const int CHANGE_ID = widgetSet->varray(HA); - const int LABEL_ID = widgetSet->varray(HA); + widget_manager->add_wgt( WTOK_PLYR_NAME0, 30, 7); + widget_manager->set_wgt_text( WTOK_PLYR_NAME0, _("Player name")); - widgetSet->label(LABEL_ID, _("Player name")); + widget_manager->add_wgt( WTOK_PLYR_NAME1, 30, 7); m_name = user_config->m_player[m_player_index].getName(); - m_name_id = widgetSet->state(CHANGE_ID, m_name.c_str(), GUI_MED, -2); + widget_manager->set_wgt_text( WTOK_PLYR_NAME1, m_name); + widget_manager->activate_wgt( WTOK_PLYR_NAME1); + widget_manager->break_line(); + + KartActions control; for(int i=0; i<=KC_LAST; i++) { - addKeyLabel(CHANGE_ID, (KartActions)i, i==0 ); - widgetSet->label(LABEL_ID, sKartAction2String[i]); + widget_manager->add_wgt( WTOK_KEY0 + i, 30, 7); + widget_manager->set_wgt_text( WTOK_KEY0 + i, sKartAction2String[i]); + + control = (KartActions)i; + m_key_names[control] = user_config->getInputAsString(m_player_index, control); + widget_manager->add_wgt( WTOK_LEFT + i, 30, 7); + widget_manager->set_wgt_text( WTOK_LEFT + i, m_key_names[control].c_str()); + widget_manager->activate_wgt( WTOK_LEFT + i); + + widget_manager->break_line(); } - widgetSet->state(m_menu_id,_("Press to go back"), GUI_SML, -1); - widgetSet -> layout(m_menu_id, 0, 0); + widget_manager->add_wgt( WTOK_QUIT, 60, 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->activate_wgt( WTOK_QUIT); + + widget_manager->layout(WGT_AREA_ALL); } // PlayerControls //----------------------------------------------------------------------------- PlayerControls::~PlayerControls() { - widgetSet -> delete_widget(m_menu_id) ; + widget_manager->delete_wgts(); // The unicode translation is not generally needed, so disable it again. SDL_EnableUNICODE(0); } // ~PlayerControls @@ -74,15 +125,16 @@ void PlayerControls::select() { if (m_grab_input) return; - m_grab_id = widgetSet -> click(); - if(m_grab_id == m_name_id) + m_grab_id = widget_manager->get_selected_wgt(); + if(m_grab_id == WTOK_PLYR_NAME1) { m_grab_input = true; return; } - const int MENU_CHOICE = widgetSet -> get_token (m_grab_id); - if(MENU_CHOICE == -1) + const int MENU_CHOICE = widget_manager->get_selected_wgt() - WTOK_LEFT; + + if(MENU_CHOICE == WTOK_QUIT) { menu_manager->popMenu(); return; @@ -91,7 +143,7 @@ void PlayerControls::select() m_grab_input = true; drv_hidePointer(); - widgetSet->set_label(m_grab_id, _("Press key")); + widget_manager->set_wgt_text(m_grab_id, _("Press key")); } // select //----------------------------------------------------------------------------- @@ -101,7 +153,7 @@ void PlayerControls::input(InputType type, int id0, int id1, int id2, int value) { // Handle input of user name // ------------------------- - if(m_grab_id == m_name_id) + if(m_grab_id == WTOK_PLYR_NAME1) { if(type==IT_KEYBOARD) { @@ -113,13 +165,14 @@ void PlayerControls::input(InputType type, int id0, int id1, int id2, int value) { if(m_name.size()>=1) m_name.erase(m_name.size()-1,1); } - // All other control characters are ignored and will end + // All other control characters are ignored and will end // entering the name else if(id0<32 || id0>255) { m_grab_input = false; + m_grab_id = WidgetManager::WGT_NONE; user_config->m_player[m_player_index].setName(m_name); - BaseGUI::input(type, id0, id1, id2, value); +// BaseGUI::input(type, id0, id1, id2, value); return; } else // Add the character to the name @@ -129,8 +182,8 @@ void PlayerControls::input(InputType type, int id0, int id1, int id2, int value) // take care of upper/lower case etc. m_name = m_name + (char)id1; } - widgetSet->set_label(m_name_id, m_name.c_str()); - } + widget_manager->set_wgt_text(WTOK_PLYR_NAME1, m_name.c_str()); + } else { // Ignore all other events, e.g. when pressing the mouse @@ -147,17 +200,17 @@ void PlayerControls::input(InputType type, int id0, int id1, int id2, int value) // Do not accept pressing ESC as input. if (type != IT_KEYBOARD || id0 != SDLK_ESCAPE) { - // Since unicode translation is enabled, the value of id1 will + // Since unicode translation is enabled, the value of id1 will // be the unicode value. Since unicode is usually not enabled - // in the race we have to set this value to zero (unicode + // in the race we have to set this value to zero (unicode // translation is only enabled here to help entering the name), // otherwise the keys will not be recognised in the race!! - if(type==IT_KEYBOARD) id1=0; - user_config->m_player[m_player_index].setInput(m_edit_action, type, + if(type==IT_KEYBOARD) id1=0; + user_config->m_player[m_player_index].setInput(m_edit_action, type, id0, id1, id2); } - - changeKeyLabel(m_grab_id, m_edit_action); + + widget_manager->set_wgt_text(m_grab_id, m_key_names[m_edit_action].c_str()); } } else @@ -165,7 +218,7 @@ void PlayerControls::input(InputType type, int id0, int id1, int id2, int value) } //----------------------------------------------------------------------------- -void PlayerControls::addKeyLabel(int CHANGE_ID, KartActions control, bool start) +/*void PlayerControls::addKeyLabel(int CHANGE_ID, KartActions control, bool start) { setKeyInfoString(control); @@ -187,5 +240,5 @@ void PlayerControls::changeKeyLabel(int m_grab_id, KartActions control) //----------------------------------------------------------------------------- void PlayerControls::setKeyInfoString(KartActions control) { - m_key_names[control] = user_config->getInputAsString(m_player_index, control); } // setKeyInfoString +*/ diff --git a/src/gui/player_controls.hpp b/src/gui/player_controls.hpp index 501c5b76e..141facd4c 100644 --- a/src/gui/player_controls.hpp +++ b/src/gui/player_controls.hpp @@ -33,14 +33,10 @@ public: void select(); void input(InputType type, int id0, int id1, int id2, int value); - void addKeyLabel(int change_id, KartActions control, bool start); - void changeKeyLabel(int grab_id, KartActions control); - void setKeyInfoString(KartActions control); private: int m_grab_id; int m_player_index; - int m_name_id; bool m_grab_input; KartActions m_edit_action; // Stores the heading - making this an attribute here avoids diff --git a/src/gui/race_gui.cpp b/src/gui/race_gui.cpp index 4c8d8fb66..ee79196d3 100644 --- a/src/gui/race_gui.cpp +++ b/src/gui/race_gui.cpp @@ -22,7 +22,6 @@ #include "user_config.hpp" #include "race_gui.hpp" #include "history.hpp" -#include "widget_set.hpp" #include "track.hpp" #include "material_manager.hpp" #include "menu_manager.hpp" @@ -817,8 +816,7 @@ void RaceGUI::cleanupMessages() void RaceGUI::drawAllMessages(Kart* player_kart, int offset_x, int offset_y, float ratio_x, float ratio_y ) { - int x, y; - x = SCREEN_CENTERED_TEXT; + int y; // First line of text somewhat under the top of the screen. For now // start just under the timer display y = (int)(ratio_y*(user_config->m_height -164)+offset_y); diff --git a/src/gui/race_menu.cpp b/src/gui/race_menu.cpp index e54e8d2ec..0f3253ad4 100644 --- a/src/gui/race_menu.cpp +++ b/src/gui/race_menu.cpp @@ -22,7 +22,7 @@ #include "race_menu.hpp" #include "user_config.hpp" #include "world.hpp" -#include "widget_set.hpp" +#include "widget_manager.hpp" #include "menu_manager.hpp" #include "race_manager.hpp" @@ -30,33 +30,54 @@ #include "translation.hpp" enum WidgetTokens { + WTOK_PAUSE, WTOK_RETURN_RACE, WTOK_OPTIONS, WTOK_HELP, WTOK_RESTART_RACE, WTOK_SETUP_NEW_RACE, - WTOK_EXIT_RACE, + WTOK_QUIT, }; RaceMenu::RaceMenu() { - m_menu_id = widgetSet -> vstack(0); - widgetSet -> label(m_menu_id, _("Paused"), GUI_LRG, GUI_ALL, 0, 0); + const bool SHOW_RECT = true; + const bool SHOW_TEXT = true; + widget_manager->set_initial_rect_state(SHOW_RECT, WGT_AREA_ALL, WGT_TRANS_BLACK); + widget_manager->set_initial_text_state(SHOW_TEXT, "", WGT_FNT_MED, Font::ALIGN_CENTER, Font::ALIGN_CENTER ); - const int VA = widgetSet -> varray(m_menu_id); - widgetSet -> start(VA, _("Return To Race"), GUI_MED, WTOK_RETURN_RACE); - widgetSet -> state(VA, _("Options"), GUI_MED, WTOK_OPTIONS); - widgetSet -> state(VA, _("Help"), GUI_MED, WTOK_HELP); - widgetSet -> state(VA, _("Restart Race"), GUI_MED, WTOK_RESTART_RACE); + widget_manager->add_wgt(WTOK_PAUSE, 30, 7); + widget_manager->set_wgt_text(WTOK_PAUSE, _("Paused")); + widget_manager->break_line(); + + widget_manager->set_initial_activation_state(true); + widget_manager->add_wgt(WTOK_RETURN_RACE, 30, 7); + widget_manager->set_wgt_text(WTOK_RETURN_RACE, _("Return To Race")); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_OPTIONS, 30, 7); + widget_manager->set_wgt_text(WTOK_OPTIONS, _("Options")); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_HELP, 30, 7); + widget_manager->set_wgt_text(WTOK_HELP, _("Help")); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_RESTART_RACE, 30, 7); + widget_manager->set_wgt_text(WTOK_RESTART_RACE, _("Restart Race")); + widget_manager->break_line(); if(world->m_race_setup.m_mode==RaceSetup::RM_QUICK_RACE) { - widgetSet->state(VA, _("Setup New Race"),GUI_MED, WTOK_SETUP_NEW_RACE); + widget_manager->add_wgt(WTOK_SETUP_NEW_RACE, 30, 7); + widget_manager->set_wgt_text(WTOK_SETUP_NEW_RACE, _("Setup New Race")); + widget_manager->break_line(); } - widgetSet -> state(VA, _("Exit Race"), GUI_MED, WTOK_EXIT_RACE); + widget_manager->add_wgt(WTOK_QUIT, 30, 7); + widget_manager->set_wgt_text(WTOK_QUIT, _("Exit Race")); - widgetSet -> layout(m_menu_id, 0, 0); + widget_manager->layout(WGT_AREA_ALL); if(user_config->m_fullscreen) SDL_ShowCursor(SDL_ENABLE); } @@ -64,20 +85,14 @@ RaceMenu::RaceMenu() //----------------------------------------------------------------------------- RaceMenu::~RaceMenu() { - widgetSet -> delete_widget(m_menu_id) ; + widget_manager->delete_wgts(); } -//----------------------------------------------------------------------------- -void RaceMenu::update(float dt) -{ - widgetSet -> timer(m_menu_id, dt) ; - widgetSet -> paint(m_menu_id) ; -} //----------------------------------------------------------------------------- void RaceMenu::select() { - int clicked_token = widgetSet->get_token(widgetSet->click()); + int clicked_token = widget_manager->get_selected_wgt(); switch (clicked_token) { @@ -108,7 +123,7 @@ void RaceMenu::select() menu_manager->pushMenu(MENUID_HELP); break; - case WTOK_EXIT_RACE: + case WTOK_QUIT: world->unpause(); race_manager->exit_race(); break; diff --git a/src/gui/race_menu.hpp b/src/gui/race_menu.hpp index e3279e397..ec7e1a3bd 100644 --- a/src/gui/race_menu.hpp +++ b/src/gui/race_menu.hpp @@ -28,7 +28,6 @@ public: RaceMenu(); ~RaceMenu(); - void update(float dt); void select(); void inputKeyboard(int key, int pressed); }; diff --git a/src/gui/race_results_gui.cpp b/src/gui/race_results_gui.cpp index 91e9becad..9ff40a20c 100644 --- a/src/gui/race_results_gui.cpp +++ b/src/gui/race_results_gui.cpp @@ -21,7 +21,7 @@ #include #include "race_results_gui.hpp" -#include "widget_set.hpp" +#include "widget_manager.hpp" #include "kart_properties.hpp" #include "world.hpp" #include "menu_manager.hpp" @@ -29,24 +29,41 @@ #include "translation.hpp" enum WidgetTokens { + WTOK_TITLE, + WTOK_EMPTY, + WTOK_HIGHSCORES, + WTOK_RESULTS, WTOK_CONTINUE, WTOK_RESTART_RACE, WTOK_SETUP_NEW_RACE, + WTOK_FIRST_RESULT }; RaceResultsGUI::RaceResultsGUI() { - m_menu_id = widgetSet -> vstack(0); - widgetSet -> label(m_menu_id, _("Result"), GUI_LRG, GUI_ALL, 0, 0); - const unsigned int MAX_STR_LEN = 60; - widgetSet -> space(m_menu_id); + const bool SHOW_RECT = true; + const bool SHOW_TEXT = true; + widget_manager->set_initial_rect_state(SHOW_RECT, WGT_AREA_ALL, WGT_TRANS_BLACK); + widget_manager->set_initial_text_state(SHOW_TEXT, "", WGT_FNT_MED, Font::ALIGN_CENTER, Font::ALIGN_CENTER ); + widget_manager->add_wgt(WTOK_TITLE, 60, 7); + widget_manager->set_wgt_text(WTOK_TITLE, _("Result")); + widget_manager->break_line(); - const int HA = widgetSet->harray(m_menu_id); - const int HIGHSCORE_TABLE = widgetSet->varray(HA); - const int RESULT_TABLE = widgetSet->varray(HA); - widgetSet -> label(RESULT_TABLE, _("Race results"),GUI_LRG,GUI_ALL,0,0); - widgetSet -> label(HIGHSCORE_TABLE, _("Highscores"), GUI_LRG,GUI_ALL,0,0); + widget_manager->add_wgt(WTOK_EMPTY, 60, 5); + widget_manager->hide_wgt_rect(WTOK_EMPTY); + widget_manager->hide_wgt_text(WTOK_EMPTY); + widget_manager->break_line(); + + widget_manager->add_wgt(WTOK_RESULTS, 40, 7); + widget_manager->set_wgt_text(WTOK_RESULTS, _("Race results")); + widget_manager->add_wgt(WTOK_HIGHSCORES, 40, 7); + widget_manager->set_wgt_text(WTOK_HIGHSCORES, _("Highscores")); + widget_manager->break_line(); + + + const unsigned int MAX_STR_LEN = 60; const unsigned int NUM_KARTS = world->getNumKarts(); + int* order = new int [NUM_KARTS]; m_score = new char[NUM_KARTS * MAX_STR_LEN]; unsigned int max_name_len = 1; @@ -75,20 +92,22 @@ RaceResultsGUI::RaceResultsGUI() TimeToString(T, sTime); } //This shows position + driver name + time + points earned + total points - if(world->m_race_setup.m_mode==RaceSetup::RM_GRAND_PRIX) - { - sprintf((char*)(m_score + MAX_STR_LEN * i), "%d. %s %s +%d %d", - KART->getPosition(), KART_NAME.c_str(), sTime, - race_manager->getPositionScore(i+1), - race_manager->getKartScore(order[i])); - } - else + if(world->m_race_setup.m_mode==RaceSetup::RM_GRAND_PRIX) { - sprintf((char*)(m_score + MAX_STR_LEN * i), "%d. %s %s", - KART->getPosition(), KART_NAME.c_str(), sTime); - } - widgetSet -> label(RESULT_TABLE, (char*)(m_score + MAX_STR_LEN * i), - GUI_MED, GUI_ALL); + sprintf((char*)(m_score + MAX_STR_LEN * i), "%d. %s %s +%d %d", + KART->getPosition(), KART_NAME.c_str(), sTime, + race_manager->getPositionScore(i+1), + race_manager->getKartScore(order[i])); + } + else + { + sprintf((char*)(m_score + MAX_STR_LEN * i), "%d. %s %s", + KART->getPosition(), KART_NAME.c_str(), sTime); + } + + widget_manager->add_wgt(WTOK_FIRST_RESULT + i, 80, 7); + widget_manager->set_wgt_text(WTOK_FIRST_RESULT + i, + (char*)(m_score + MAX_STR_LEN * i)); } delete[] order; @@ -106,14 +125,15 @@ RaceResultsGUI::RaceResultsGUI() const int TENTHS = (int) floor ( 10.0f * (T - (float)(SECS + 60*MINS))); sprintf((char*)(m_highscores + MAX_STR_LEN * i), "%s: %3d:%02d.%01d", name.c_str(), MINS, SECS, TENTHS); - widgetSet->label(HIGHSCORE_TABLE, (char*)(m_highscores+MAX_STR_LEN*i), - GUI_MED, GUI_ALL); +/* widgetSet->label(HIGHSCORE_TABLE, (char*)(m_highscores+MAX_STR_LEN*i), + GUI_MED, GUI_ALL);*/ } - widgetSet -> space(m_menu_id); +// widgetSet -> space(m_menu_id); // const int VA = widgetSet -> varray(m_menu_id); +#if 0 static int dev_msg_counter = 0; if(dev_msg_counter == 2) { @@ -122,28 +142,31 @@ if you want to help contact us!"), GUI_SML, GUI_ALL, 0, 0); dev_msg_counter = 0; } ++dev_msg_counter; +#endif if(world->m_race_setup.m_mode==RaceSetup::RM_GRAND_PRIX) { - widgetSet -> start(m_menu_id, _("Continue Grand Prix"), GUI_MED, WTOK_CONTINUE); +// widgetSet -> start(m_menu_id, _("Continue Grand Prix"), GUI_MED, WTOK_CONTINUE); } else { - widgetSet -> start(m_menu_id, _("Back to the main menu"), GUI_MED, WTOK_CONTINUE); +// widgetSet -> start(m_menu_id, _("Back to the main menu"), GUI_MED, WTOK_CONTINUE); } - widgetSet -> start(m_menu_id, _("Race in this track again"), GUI_MED, WTOK_RESTART_RACE); +// widgetSet -> start(m_menu_id, _("Race in this track again"), GUI_MED, WTOK_RESTART_RACE); if(world->m_race_setup.m_mode==RaceSetup::RM_QUICK_RACE) { - widgetSet -> start(m_menu_id, _("Setup New Race"), GUI_MED, WTOK_SETUP_NEW_RACE); +// widgetSet -> start(m_menu_id, _("Setup New Race"), GUI_MED, WTOK_SETUP_NEW_RACE); } - widgetSet -> layout(m_menu_id, 0, 0); +// widgetSet -> layout(m_menu_id, 0, 0); + widget_manager->layout(WGT_AREA_ALL); } // RaceResultsGUI //----------------------------------------------------------------------------- RaceResultsGUI::~RaceResultsGUI() { - widgetSet -> delete_widget(m_menu_id) ; + widget_manager->delete_wgts(); + //widgetSet -> delete_widget(m_menu_id) ; delete[] m_score; delete[] m_highscores; } // ~RaceResultsGUI @@ -151,7 +174,7 @@ RaceResultsGUI::~RaceResultsGUI() //----------------------------------------------------------------------------- void RaceResultsGUI::select() { - switch( widgetSet->get_token( widgetSet->click() ) ) + switch( widget_manager->get_selected_wgt() ) { case WTOK_CONTINUE: world->unpause(); diff --git a/src/gui/scrolled_text.cpp b/src/gui/scrolled_text.cpp deleted file mode 100644 index 2685cc0d9..000000000 --- a/src/gui/scrolled_text.cpp +++ /dev/null @@ -1,124 +0,0 @@ -// $Id: credits_menu.cpp 694 2006-08-29 07:42:36Z hiker $ -// -// SuperTuxKart - a fun racing game with go-kart -// Copyright (C) 2006 Joerg Henrichs -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#include -#include "scrolled_text.hpp" -#include "widget_set.hpp" -#include "menu_manager.hpp" -#include "user_config.hpp" -#include "translation.hpp" -#include "font.hpp" - -ScrolledText::ScrolledText() -{ - float r = user_config->m_width/800.0f; - m_x_left = (int)(30.0*r); m_x_right = user_config->m_width -m_x_left; - r = user_config->m_height/600.0f; - m_y_bottom = (int)(50.0*r); m_y_top = user_config->m_height-(int)(50.0f*r); - m_y_speed = 50.0f; - m_font_size = 24; - m_y_pos = m_y_bottom-m_font_size; - m_rect = 0; - m_menu_id = widgetSet -> varray(0); - widgetSet->layout(m_menu_id, 0, 0); -} // ScrolledText - -//----------------------------------------------------------------------------- -ScrolledText::~ScrolledText() -{ - glDeleteLists(m_rect, 1); -} // ~ScrolledText - -//----------------------------------------------------------------------------- -void ScrolledText::setText(StringList const &sl_) -{ - m_string_list=sl_; - if(m_rect) glDeleteLists(m_rect, 1); - m_rect = widgetSet->rect(m_x_left, m_y_bottom, m_x_right-m_x_left, m_y_top-m_y_bottom, - GUI_ALL, 10); -} // setText - -//----------------------------------------------------------------------------- -void ScrolledText::update(float dt) -{ - BaseGUI::update(dt); - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glOrtho(0.0, user_config->m_width, 0.0, user_config->m_height, -1.0, +1.0); - glMatrixMode(GL_MODELVIEW); - glEnable(GL_BLEND); - - glPushMatrix(); - glBindTexture(GL_TEXTURE_2D, 0); - const GLfloat backgroundColour[4] = { 0.3f, 0.3f, 0.3f, 0.5f }; - glColor4fv(backgroundColour); - glCallList(m_rect); - glPopMatrix(); - font_gui->Print(_("Press to go back"), 24, - Font::ALIGN_CENTER, -1, Font::ALIGN_BOTTOM, 20); - glViewport(m_x_left, m_y_bottom, m_x_right-m_x_left, m_y_top-m_y_bottom); - - glScalef(1.0f, user_config->m_width/(m_y_top-m_y_bottom), 1.0f); - - for(unsigned int i=0; i -m_font_size) - font_gui->Print(m_string_list[i].c_str(), 24, - m_x_left,(int)m_y_pos-i*m_font_size); - } - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glViewport(0,0,user_config->m_width, user_config->m_height); - m_y_pos=m_y_pos+dt*m_y_speed; - if(m_y_speed>0 && m_y_pos>m_string_list.size()*m_font_size+m_y_top-m_y_bottom) m_y_pos=-m_font_size; - if(m_y_speed<0 && m_y_pos<0) m_y_pos=m_string_list.size()*m_font_size+m_y_top-m_y_bottom; -} // update - -//----------------------------------------------------------------------------- -void ScrolledText::inputKeyboard(int key, int pressed) -{ - switch(key) - { - case SDLK_PLUS : - case SDLK_UP : m_y_speed -= 10.0f; break; - case SDLK_PAGEUP : m_y_speed -= 50.0f; break; - case SDLK_PAGEDOWN : m_y_speed += 50.0f; break; - case SDLK_MINUS : - case SDLK_DOWN : m_y_speed += 10.0f; break; - case SDLK_ESCAPE : menu_manager->popMenu(); - default : break; - } // switch - - if (m_y_speed > 500.0f) m_y_speed = 500.0f; - if (m_y_speed < -500.0f) m_y_speed = -500.0f; - -} // inputKeyboard - -//----------------------------------------------------------------------------- -void ScrolledText::select() -{ - // must be esc, nothing else is available. So just pop this menu - menu_manager->popMenu(); -} // select - -/* EOF */ diff --git a/src/gui/scrolled_text.hpp b/src/gui/scrolled_text.hpp deleted file mode 100644 index 435dff15e..000000000 --- a/src/gui/scrolled_text.hpp +++ /dev/null @@ -1,51 +0,0 @@ -// $Id: credits_menu.hpp 694 2006-08-29 07:42:36Z hiker $ -// -// SuperTuxKart - a fun racing game with go-kart -// Copyright (C) 2006 Joerg Henrichs -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#ifndef HEADER_SCROLL_TEXT_HPP -#define HEADER_SCROLL_TEXT_HPP - -#include -#include -#include "base_gui.hpp" -#include "player.hpp" - - -class ScrolledText: public BaseGUI -{ -protected: - typedef std::vector StringList; - -private: - int m_x_left, m_x_right, m_y_bottom, m_y_top; - float m_y_pos, m_y_speed; - int m_font_size; - StringList m_string_list; - int m_rect; - -public: - ScrolledText(); - ~ScrolledText(); - void setText (StringList const &sl_); - - void select (); - void update (float dt); - void inputKeyboard (int key, int pressed); -}; - -#endif diff --git a/src/gui/track_sel.cpp b/src/gui/track_sel.cpp index 71dbd1437..8349c7080 100644 --- a/src/gui/track_sel.cpp +++ b/src/gui/track_sel.cpp @@ -18,7 +18,7 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "track_sel.hpp" -#include "widget_set.hpp" +#include "widget_manager.hpp" #include "race_manager.hpp" #include "track_manager.hpp" #include "track.hpp" @@ -30,44 +30,78 @@ #include "translation.hpp" enum WidgetTokens { - WTOK_RETURN, - WTOK_OPTIONS, - WTOK_RESTART, - WTOK_EXIT, + WTOK_TITLE, + + WTOK_TRACK0, + WTOK_TRACK1, + WTOK_TRACK2, + WTOK_TRACK3, + WTOK_TRACK4, + WTOK_TRACK5, + WTOK_TRACK6, + WTOK_TRACK7, + WTOK_TRACK8, + WTOK_TRACK9, + WTOK_TRACK10, + WTOK_TRACK11, + WTOK_TRACK12, + WTOK_TRACK13, + + WTOK_IMG0, + WTOK_IMG1, + + WTOK_AUTHOR }; TrackSel::TrackSel() { - m_menu_id = widgetSet -> vstack(0); + widget_manager->add_wgt( WTOK_TITLE, 40, 7); + widget_manager->show_wgt_rect( WTOK_TITLE ); + widget_manager->set_wgt_text( WTOK_TITLE, _("Choose a track")); + widget_manager->show_wgt_text( WTOK_TITLE ); + widget_manager->break_line(); - widgetSet -> label(m_menu_id, _("Choose a Track"), GUI_LRG, GUI_TOP, 0, 0); - widgetSet -> space(m_menu_id); + widget_manager->add_wgt( WidgetManager::WGT_NONE, 100, 2); + widget_manager->break_line(); - const int HA = widgetSet -> harray(m_menu_id); - - const int COL1 = widgetSet -> varray(HA); - const int COL2 = widgetSet -> varray(HA); - - for (size_t i = 0; i != track_manager->getTrackCount()/2; ++i) - widgetSet -> state(COL1, track_manager->getTrack(i)->getName(), GUI_SML, i, 0); - - for (size_t i = track_manager->getTrackCount()/2; - i != track_manager->getTrackCount(); ++i) + const bool SHOW_RECT = true; + const bool SHOW_TEXT = true; + widget_manager->set_initial_activation_state(true); + widget_manager->set_initial_rect_state(SHOW_RECT, WGT_AREA_ALL, WGT_TRANS_BLACK); + widget_manager->set_initial_text_state(SHOW_TEXT, "", WGT_FNT_SML, Font::ALIGN_CENTER, Font::ALIGN_CENTER ); + for (size_t i = 0; i != track_manager->getTrackCount(); i += 2) { - int tmp = widgetSet -> state(COL2, track_manager->getTrack(i)->getName(), GUI_SML, i, 0); - if (i == track_manager->getTrackCount()/2) - widgetSet -> set_active(tmp); + widget_manager->add_wgt( WTOK_TRACK0 + i, 40, 7); + widget_manager->set_wgt_text( WTOK_TRACK0 + i, track_manager->getTrack(i)->getName()); + widget_manager->add_wgt( WTOK_TRACK0 + i + 1, 40, 7); + widget_manager->set_wgt_text( WTOK_TRACK0 + i + 1, track_manager->getTrack(i+1)->getName()); + widget_manager->break_line(); } - widgetSet -> layout(m_menu_id, 0, 1); - m_rect = widgetSet->rect(10, 10, user_config->m_width-20, 34, GUI_ALL, 10); +//FIXME: Right now, the image and the author's name is not controlled by the widget manager. +#if 0 + widget_manager->set_initial_rect_state(false, WGT_AREA_ALL, WGT_TRANS_BLACK); + widget_manager->set_initial_text_state(false, "", WGT_FNT_MED, Font::ALIGN_CENTER, Font::ALIGN_CENTER ); + widget_manager->set_initial_activation_state(false); + widget_manager->add_wgt( WidgetManager::WGT_NONE, 100, 5); + widget_manager->break_line(); + + widget_manager->set_initial_rect_state(SHOW_RECT, WGT_AREA_ALL, WGT_TRANS_WHITE); + widget_manager->add_wgt( WTOK_IMG0, 40, 30); + widget_manager->add_wgt( WidgetManager::WGT_NONE, 5, 30); + widget_manager->add_wgt( WTOK_IMG0, 40, 30); + widget_manager->break_line(); + + widget_manager->add_wgt( WTOK_AUTHOR, 100, 10); + widget_manager->show_wgt_text( WTOK_AUTHOR ); +#endif + widget_manager->layout(WGT_AREA_TOP); } //----------------------------------------------------------------------------- TrackSel::~TrackSel() { - widgetSet -> delete_widget(m_menu_id); - glDeleteLists(m_rect, 1); + widget_manager->delete_wgts(); } //----------------------------------------------------------------------------- @@ -78,8 +112,9 @@ void TrackSel::update(float dt) glClear(GL_DEPTH_BUFFER_BIT); // draw a track preview of the currently highlighted track menu entry - const int CLICKED_TOKEN = widgetSet->get_token(widgetSet->click()); - const Track* TRACK = track_manager->getTrack(CLICKED_TOKEN); +// const int CLICKED_TOKEN = widgetSet->get_token(widgetSet->click()); + const int CLICKED_TOKEN = widget_manager->get_selected_wgt(); + const Track* TRACK = track_manager->getTrack(CLICKED_TOKEN - WTOK_TRACK0); glMatrixMode(GL_PROJECTION); glPushMatrix(); @@ -136,9 +171,9 @@ void TrackSel::update(float dt) glBindTexture(GL_TEXTURE_2D, 0); const GLfloat backgroundColour[4] = { 0.3f, 0.3f, 0.3f, 0.5f }; glColor4fv(backgroundColour); - glCallList(m_rect); +// glCallList(m_rect); glPopMatrix(); - font_gui->Print(TRACK->getDescription(), GUI_MED, + font_gui->Print(TRACK->getDescription(), WGT_FNT_MED, Font::ALIGN_CENTER, -1, Font::ALIGN_BOTTOM, 10); glDisable(GL_BLEND); @@ -151,8 +186,9 @@ void TrackSel::update(float dt) //----------------------------------------------------------------------------- void TrackSel::select() { - const int CLICKED_TOKEN = widgetSet->get_token(widgetSet->click()); - const Track* TRACK = track_manager->getTrack(CLICKED_TOKEN); + const int CLICKED_TOKEN = widget_manager->get_selected_wgt(); + //const int CLICKED_TOKEN = widgetSet->get_token(widgetSet->click()); + const Track* TRACK = track_manager->getTrack(CLICKED_TOKEN - WTOK_TRACK0); race_manager->setTrack(TRACK->getIdent()); menu_manager->pushMenu(MENUID_NUMLAPS); diff --git a/src/gui/track_sel.hpp b/src/gui/track_sel.hpp index f3f554d5f..c3cc64f8d 100644 --- a/src/gui/track_sel.hpp +++ b/src/gui/track_sel.hpp @@ -24,8 +24,8 @@ class TrackSel: public BaseGUI { -protected: - int m_rect; +/*protected: + int m_rect;*/ public: TrackSel(); ~TrackSel(); diff --git a/src/main.cpp b/src/main.cpp index c2b32b31f..43944b5d2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -48,7 +48,7 @@ #include "race_manager.hpp" #include "loader.hpp" #include "game_manager.hpp" -#include "widget_set.hpp" +#include "widget_manager.hpp" #include "material_manager.hpp" #include "sdldrv.hpp" #include "callback_manager.hpp" @@ -374,7 +374,7 @@ int main(int argc, char *argv[] ) herring_manager -> loadDefaultHerrings(); attachment_manager -> loadModels (); scene = new Scene(); - widgetSet = new WidgetSet; + widget_manager = new WidgetManager; menu_manager->switchToMainMenu(); // Replay a race diff --git a/src/widget.cpp b/src/widget.cpp new file mode 100644 index 000000000..7ad67ab32 --- /dev/null +++ b/src/widget.cpp @@ -0,0 +1,537 @@ +// $Id: widget_set.cpp 1094 2007-05-21 06:49:06Z hiker $ +// +// SuperTuxKart - a fun racing game with go-kart +// This code originally from Neverball copyright (C) 2003 Robert Kooima +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "widget.hpp" + +#include "gui/font.hpp" + +//FIXME: this should be removed when the scrolling is cleaned +#include "user_config.hpp" + +#include +#include + +const GLfloat WGT_WHITE [4] = { 1.0f, 1.0f, 1.0f, 1.0f }; +const GLfloat WGT_GRAY [4] = { 0.5f, 0.5f, 0.5f, 1.0f }; +const GLfloat WGT_BLACK [4] = { 0.0f, 0.0f, 0.0f, 1.0f }; +const GLfloat WGT_YELLOW [4] = { 1.0f, 1.0f, 0.0f, 1.0f }; +const GLfloat WGT_RED [4] = { 1.0f, 0.0f, 0.0f, 1.0f }; +const GLfloat WGT_GREEN [4] = { 0.0f, 1.0f, 0.0f, 1.0f }; +const GLfloat WGT_BLUE [4] = { 0.0f, 0.0f, 1.0f, 1.0f }; +const GLfloat WGT_TRANS_WHITE [4] = { 1.0f, 1.0f, 1.0f, 0.5f }; +const GLfloat WGT_TRANS_GRAY [4] = { 0.5f, 0.5f, 0.5f, 0.5f }; +const GLfloat WGT_TRANS_BLACK [4] = { 0.0f, 0.0f, 0.0f, 0.5f }; +const GLfloat WGT_TRANS_YELLOW [4] = { 1.0f, 1.0f, 0.0f, 0.5f }; +const GLfloat WGT_TRANS_RED [4] = { 1.0f, 0.0f, 0.0f, 0.5f }; +const GLfloat WGT_TRANS_GREEN [4] = { 0.0f, 1.0f, 0.0f, 0.5f }; +const GLfloat WGT_TRANS_BLUE [4] = { 0.0f, 0.0f, 1.0f, 0.5f }; + +//FIXME: I should change 'LIGHT' for 'LIT'. +const GLfloat WGT_LIGHT_GRAY [4] = {1.0f, 1.0f, 1.0f, 1.0f}; +const GLfloat WGT_LIGHT_BLACK [4] = {0.5f, 0.5f, 0.5f, 1.0f}; +const GLfloat WGT_LIGHT_YELLOW [4] = {1.0f, 1.0f, 0.5f, 1.0f}; +const GLfloat WGT_LIGHT_RED [4] = {1.0f, 0.5f, 0.5f, 1.0f}; +const GLfloat WGT_LIGHT_GREEN [4] = {0.5f, 1.0f, 0.5f, 1.0f}; +const GLfloat WGT_LIGHT_BLUE [4] = {0.5f, 0.5f, 1.0f, 1.0f}; +const GLfloat WGT_LIGHT_TRANS_GRAY [4] = {1.0f, 1.0f, 1.0f, 0.8f}; +const GLfloat WGT_LIGHT_TRANS_BLACK [4] = {0.5f, 0.5f, 0.5f, 0.8f}; +const GLfloat WGT_LIGHT_TRANS_YELLOW [4] = {1.0f, 1.0f, 0.5f, 0.8f}; +const GLfloat WGT_LIGHT_TRANS_RED [4] = {1.0f, 0.5f, 0.5f, 0.8f}; +const GLfloat WGT_LIGHT_TRANS_GREEN [4] = {0.5f, 1.0f, 0.5f, 0.5f}; +const GLfloat WGT_LIGHT_TRANS_BLUE [4] = {0.5f, 0.5f, 1.0f, 0.8f}; + +Widget::Widget +( + const int X_, + const int Y_, + const int WIDTH_, + const int HEIGHT_ +) : +//Switch features are not set here to sane defaults because the WidgetManager +//handles that. + m_x(X_), m_y(Y_), + m_width(WIDTH_), m_height(HEIGHT_), + m_rect_list(0), + m_round_corners(WGT_AREA_ALL), + /*m_scroll_pos_x(0),*/ m_scroll_pos_y(0), + /*m_scroll_speed_x(0),*/ m_scroll_speed_y(0), + m_text_scale(1.0f) +{ +} + +//----------------------------------------------------------------------------- +Widget::~Widget() +{ + if(glIsList(m_rect_list)) + { + glDeleteLists(m_rect_list, 1); + } +} + +//----------------------------------------------------------------------------- +void Widget::update(const float DELTA) +{ + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + /*Handle delta time dependant features*/ + if(m_text_scale > MIN_TEXT_SCALE) + { + m_text_scale -= MIN_TEXT_SCALE * DELTA; + if(m_text_scale < MIN_TEXT_SCALE) m_text_scale = MIN_TEXT_SCALE; + } + + /*Handle on/off features*/ + //Draw widget + if(m_enable_texture) + { + glEnable(GL_TEXTURE_2D); + if(glIsTexture(m_texture)) + { + glBindTexture(GL_TEXTURE_2D, m_texture); + } + else + { + std::cerr << "Warning: widget tried to draw null texture.\n"; + std::cerr << "(Did you set the texture?)\n"; + } + } + else + { + //This ensures that a texture from another module doesn't affects the widget + glDisable(GL_TEXTURE_2D); + } + + if(m_enable_rect) + { + if(glIsList(m_rect_list)) + { + glColor4fv(m_rect_color); + glCallList(m_rect_list); + } + else + { + std::cerr << "Warning: widget tried to draw null rect list.\n"; + std::cerr << "(Did you created the rect?)\n"; + } + } + + //For multilines we have to do a *very* ugly workaround for a plib + //bug which causes multiline strings to move to the left, at least + //while centering, and also gives wrong values for the size of the + //text when there are multiple lines. Hopefully this work around will + //be removed when we move away from plib; the scrolling and the other + //text handling should be cleaned. Also, for some reason, different + //positions are needed if the text is centered. Sorry for the mess. + size_t line_end = 0; + int lines = 0; + + do + { + line_end = m_text.find_first_of('\n', line_end + 1); + ++lines; + } while( line_end != std::string::npos ); + + if(m_enable_scroll) + { + //TODO: constrain speed to sane values + /*m_scroll_pos_x += m_scroll_speed_x;*/ + m_scroll_pos_y += m_scroll_speed_y; + + if( m_text_y_alignment == Font::ALIGN_CENTER ) + { + const int LIMIT = lines * m_text_size + m_height; + if(m_scroll_pos_y * 2 > LIMIT) + { + m_scroll_pos_y = -LIMIT / 2; + } + else if(-m_scroll_pos_y * 2 > LIMIT) + { + m_scroll_pos_y = LIMIT / 2; + } + } + else if( m_text_y_alignment == Font::ALIGN_BOTTOM ) + { + const int TEXT_HEIGHT = lines * m_text_size; + if(m_scroll_pos_y > TEXT_HEIGHT / 2) + { + m_scroll_pos_y = -m_height - (TEXT_HEIGHT) / 2; + } + else if(m_scroll_pos_y < - m_height - TEXT_HEIGHT / 2) + { + m_scroll_pos_y = TEXT_HEIGHT / 2 + m_text_size; + } + } + +/* + float left, right; + font_gui->getBBox(m_text.c_str(), m_text_size, false, &left, &right, NULL, NULL); + const int TEXT_WIDTH = (int)(right - left) / m_text_size; + + if( m_text_x_alignment == Font::ALIGN_CENTER ) + { + const int LIMIT = TEXT_WIDTH + m_width; + if(m_scroll_pos_x * 2 > LIMIT) + { + m_scroll_pos_x = -LIMIT / 2; + } + else if(-m_scroll_pos_x * 2 > LIMIT) + { + m_scroll_pos_x = LIMIT / 2; + } + } + else if( m_text_x_alignment == Font::ALIGN_LEFT ) + { + if(m_scroll_pos_x > TEXT_WIDTH / 2) + { + m_scroll_pos_x = -m_width - (TEXT_WIDTH) / 2; + } + else if(m_scroll_pos_x < - m_width - TEXT_WIDTH / 2) + { + m_scroll_pos_x = TEXT_WIDTH / 2 + m_text_size; + } + } +*/ + } + + if(m_enable_text) + { + if(m_text.empty()) + { + std::cerr << "Warning: widget tried to print an empty string.\n"; + std::cerr << "(Did you set the text?)\n"; + } + + int x_pos = m_x;// + m_scroll_pos_x; + int y_pos = m_y - m_scroll_pos_y + ((lines - 1 )* m_text_size) / 2; + + if( m_text_x_alignment == Font::ALIGN_CENTER ) x_pos += m_width / 2; + if( m_text_y_alignment == Font::ALIGN_CENTER ) + { + y_pos += m_height / 2; + } + + size_t line_start = 0; + bool draw; + bool out_of_rect = false; + + glEnable( GL_SCISSOR_TEST ); + do + { + draw = true; + if(y_pos + m_text_size / 2 > m_y + m_height ) + { + if(y_pos - m_text_size / 2 > m_y + m_height) draw = false; + else + { + out_of_rect = true; + glScissor(m_x, m_y, m_width, m_height); + } + } + else if(y_pos - m_text_size / 2 < m_y) + { + if(y_pos + m_text_size / 2 < m_y) draw = false; + else + { + out_of_rect = true; + glScissor(m_x, m_y, m_width, m_height); + } + } + + line_end = m_text.find_first_of('\n', line_start); + if( draw ) + { + font_gui->Print(m_text.substr(line_start, line_end - line_start).c_str(), m_text_size, + m_text_x_alignment, x_pos, m_text_y_alignment, y_pos, + 255, 255, 255, m_text_scale, m_text_scale); + } + + y_pos -= m_text_size; + line_start = line_end + 1; + + if( out_of_rect ) + { + out_of_rect = false; + glScissor(0, 0, user_config->m_width, user_config->m_height); + } + } while( line_end != std::string::npos ); + glDisable( GL_SCISSOR_TEST ); + } + glPopMatrix(); +} + +/** Initialize a display list containing a rectangle that can have rounded + * corners, with texture coordinates to properly apply a texture + * map to the rectangle as though the corners were not rounded . Returns + * false if the call to glGenLists failed, otherwise it returns true. + */ +bool Widget::create_rect(int radius) +{ + //TODO: show warning if text > rect + if(radius > m_width * 0.5) + { + std::cerr << "Warning: widget's radius > half width.\n"; + } + if(radius > m_height * 0.5) + { + std::cerr << "Warning: widget's radius > half height.\n"; + } + if(radius < 1) + { + std::cerr << "Warning: widget's radius < 1, setting to 1.\n"; + radius = 1; + } + + if(m_width == 0) + { + std::cerr << "Warning: creating widget rect with width 0, " << + "setting to 1.\n"; + m_width = 1; + } + if(m_height == 0) + { + std::cerr << "Warning: creating widget rect with height 0, " << + "setting to 1.\n"; + m_height = 1; + } + + if(!glIsList(m_rect_list)) + { + m_rect_list = glGenLists(1); + if(m_rect_list == 0) + { + std::cerr << "Error: could not create a widget's rect list.\n"; + return false; + } + } + + //Calculate the number of quads each side should have. The algorithm + //isn't based on pure logic, instead it's based on the perception of + //roundness and some visual testing. + const int MIN_QUADS = 2; + const float QUAD_RADIUS_RAISE = 0.413f; + const int NUM_QUADS = MIN_QUADS + (int)(pow((float)radius, QUAD_RADIUS_RAISE)); + + int i; + + glNewList(m_rect_list, GL_COMPILE); + { + //To create a rounded rectangle, we generate lines that are + //progressively bigger, which are given as vertex points for each + //quad. + glBegin(GL_QUAD_STRIP); + { + //Draw the left side of a rectangle. + for (i = 0; i <= NUM_QUADS; ++i) + { + //To find the position in the X and Y axis of each point of + //the quads, we use the property of the unit circle (a circle + //with radius = 1) that at any given angle, cos(angle) is the + //position of the unit circle at that angle in the X axis, + //and that sin(angle) is the position of the unit circle at + //that angle in the Y axis. Then the values from cos(angle) + //and sin(angle) are multiplied by the radius. + // + //First we find the angle: since 2 * pi is the number of + //radians in an entire circle, 0.5 * pi is a quarter of the + //circle, which is a corner of the rounded rectangle. Based + //on that, we just split the radians in a corner in NUM_QUADS + //+ 1 parts, and use the angles at those parts to find the + //X and Y position of the points. + const float ANGLE = 0.5f * M_PI * (float)i / (float)NUM_QUADS; + const float CIRCLE_X = radius * cos(ANGLE); + const float CIRCLE_Y = radius * sin(ANGLE); + + //After we generate the positions in circle for the angles, + //we have to position each rounded corner properly depending + //on the position of the rectangle and the radius. The y + //position for the circle is dependant on rect; if a corner + //wasn't given, then the y position is computed as if it was + //for a rectangle without rounder corners. + const float VERTEX_X = m_x + radius - CIRCLE_X; + const float VERTEX_YA = m_y + m_height + + ((m_round_corners & WGT_AREA_NW) ? (CIRCLE_Y - radius) : 0); + const float VERTEX_YB = m_y + ((m_round_corners & WGT_AREA_SW) ? + (radius - CIRCLE_Y) : 0); + + glTexCoord2f((VERTEX_X - m_x) / m_width, + (VERTEX_YA - m_y) / m_height); + glVertex2f(VERTEX_X, VERTEX_YA); + + glTexCoord2f((VERTEX_X - m_x) / m_width, + (VERTEX_YB - m_y) / m_height); + glVertex2f(VERTEX_X, VERTEX_YB); + } + + //Draw the right side of a rectangle + for (i = 0; i <= NUM_QUADS; ++i) + { + const float ANGLE = 0.5f * M_PI * (float) i / (float) NUM_QUADS; + + //By inverting the use of sin and cos we get corners that are + //drawn from left to right instead of right to left + const float CIRCLE_X = radius * sin(ANGLE); + const float CIRCLE_Y = radius * cos(ANGLE); + + float VERTEX_X = m_x + m_width - radius + CIRCLE_X; + float VERTEX_YA = m_y + m_height + ((m_round_corners & + WGT_AREA_NE) ? (CIRCLE_Y - radius) : 0); + float VERTEX_YB = m_y + ((m_round_corners & WGT_AREA_SE) ? + (radius - CIRCLE_Y) : 0); + + glTexCoord2f((VERTEX_X - m_x) / m_width, + (VERTEX_YA - m_y) / m_height); + glVertex2f(VERTEX_X, VERTEX_YA); + + glTexCoord2f((VERTEX_X - m_x) / m_width, + (VERTEX_YB - m_y) / m_height); + glVertex2f(VERTEX_X, VERTEX_YB); + } + + } + glEnd(); + } + glEndList(); + + return true; +} + +//----------------------------------------------------------------------------- +void Widget::resize_to_text() +{ + if( !m_text.empty() ) + { + float left, right, bottom, top; + font_gui->getBBox(m_text.c_str(), m_text_size, false, &left, &right, &bottom, &top); + + const int TEXT_WIDTH = (int)(right - left); + const int TEXT_HEIGHT = (int)(bottom - top); + + if( TEXT_WIDTH > m_width ) m_width = TEXT_WIDTH; + if( TEXT_HEIGHT > m_height ) m_height = TEXT_HEIGHT; + } +} + +//----------------------------------------------------------------------------- +/* Please note that this function only lightens 'non-light' colors */ +void Widget::lighten_color() +{ + if(m_rect_color == WGT_GRAY) + { + m_rect_color = WGT_LIGHT_GRAY; + } + if(m_rect_color == WGT_BLACK) + { + m_rect_color = WGT_LIGHT_BLACK; + } + else if (m_rect_color == WGT_YELLOW) + { + m_rect_color = WGT_LIGHT_YELLOW; + } + else if (m_rect_color == WGT_RED) + { + m_rect_color = WGT_LIGHT_RED; + } + else if (m_rect_color == WGT_GREEN) + { + m_rect_color = WGT_LIGHT_GREEN; + } + else if (m_rect_color == WGT_BLUE) + { + m_rect_color = WGT_LIGHT_BLUE; + } + else if (m_rect_color == WGT_TRANS_GRAY) + { + m_rect_color = WGT_LIGHT_TRANS_GRAY; + } + else if (m_rect_color == WGT_TRANS_BLACK) + { + m_rect_color = WGT_LIGHT_TRANS_BLACK; + } + else if (m_rect_color == WGT_TRANS_YELLOW) + { + m_rect_color = WGT_LIGHT_TRANS_YELLOW; + } + else if (m_rect_color == WGT_TRANS_RED) + { + m_rect_color = WGT_LIGHT_TRANS_RED; + } + else if (m_rect_color == WGT_TRANS_GREEN) + { + m_rect_color = WGT_LIGHT_TRANS_GREEN; + } + else if (m_rect_color == WGT_TRANS_BLUE) + { + m_rect_color = WGT_LIGHT_TRANS_BLUE; + } +} + +//----------------------------------------------------------------------------- +/* Please note that this function only darkens 'light' colors. */ +void Widget::darken_color() +{ + if(m_rect_color == WGT_LIGHT_GRAY) + { + m_rect_color = WGT_GRAY; + } + if(m_rect_color == WGT_LIGHT_BLACK) + { + m_rect_color = WGT_BLACK; + } + else if (m_rect_color == WGT_LIGHT_YELLOW) + { + m_rect_color = WGT_YELLOW; + } + else if (m_rect_color == WGT_LIGHT_RED) + { + m_rect_color = WGT_RED; + } + else if (m_rect_color == WGT_LIGHT_GREEN) + { + m_rect_color = WGT_GREEN; + } + else if (m_rect_color == WGT_LIGHT_BLUE) + { + m_rect_color = WGT_BLUE; + } + else if (m_rect_color == WGT_LIGHT_TRANS_GRAY) + { + m_rect_color = WGT_TRANS_GRAY; + } + else if (m_rect_color == WGT_LIGHT_TRANS_BLACK) + { + m_rect_color = WGT_TRANS_BLACK; + } + else if (m_rect_color == WGT_LIGHT_TRANS_YELLOW) + { + m_rect_color = WGT_TRANS_YELLOW; + } + else if (m_rect_color == WGT_LIGHT_TRANS_RED) + { + m_rect_color = WGT_TRANS_RED; + } + else if (m_rect_color == WGT_LIGHT_TRANS_GREEN) + { + m_rect_color = WGT_TRANS_GREEN; + } + else if (m_rect_color == WGT_LIGHT_TRANS_BLUE) + { + m_rect_color = WGT_TRANS_BLUE; + } +} diff --git a/src/widget.hpp b/src/widget.hpp new file mode 100644 index 000000000..a8a6bda05 --- /dev/null +++ b/src/widget.hpp @@ -0,0 +1,180 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// This code originally from Neverball copyright (C) 2003 Robert Kooima +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/* This file should only be used directly by the widget manager. Also, all + * the coordinates in the widget.* and widget_manager.* are based on OpenGL, + * which means that the 0 in the Y-axis is in the bottom, not the top. + */ + +#ifndef HEADER_WIDGET_H +#define HEADER_WIDGET_H + +#ifdef __APPLE__ +# include +#else +# include +#endif + +#include +#include "gui/font.hpp" + +enum WidgetFontSize { WGT_FNT_SML = 18, WGT_FNT_MED = 24, WGT_FNT_LRG = 30}; + +enum WidgetArea //One of the uses of this, is for rounded corners +{ + WGT_AREA_NONE = 0, + WGT_AREA_NW = 1, WGT_AREA_SW = 2, WGT_AREA_NE = 4, WGT_AREA_SE = 8, + WGT_AREA_LFT = (WGT_AREA_NW | WGT_AREA_SW), + WGT_AREA_RGT = (WGT_AREA_NE | WGT_AREA_SE), + WGT_AREA_TOP = (WGT_AREA_NW | WGT_AREA_NE), + WGT_AREA_BOT = (WGT_AREA_SW | WGT_AREA_SE), + WGT_AREA_ALL = (WGT_AREA_TOP | WGT_AREA_BOT) +}; + +//I suggest that you do not use the white or light colors for the rects in +//most cases, because they don't have lighter versions that can be used to +//highlight those rects and then revert them, for example, when you select a +//widget. For textures, you should use WGT_WHITE usually, thought you can get +//nice effects by using other colors. +extern const GLfloat WGT_WHITE [4]; +extern const GLfloat WGT_GRAY [4]; +extern const GLfloat WGT_BLACK [4]; +extern const GLfloat WGT_YELLOW [4]; +extern const GLfloat WGT_RED [4]; +extern const GLfloat WGT_GREEN [4]; +extern const GLfloat WGT_BLUE [4]; +extern const GLfloat WGT_TRANS_WHITE [4]; +extern const GLfloat WGT_TRANS_GRAY [4]; +extern const GLfloat WGT_TRANS_BLACK [4]; +extern const GLfloat WGT_TRANS_YELLOW [4]; +extern const GLfloat WGT_TRANS_RED [4]; +extern const GLfloat WGT_TRANS_GREEN [4]; +extern const GLfloat WGT_TRANS_BLUE [4]; + +extern const GLfloat WGT_LIGHT_GRAY [4]; +extern const GLfloat WGT_LIGHT_BLACK [4]; +extern const GLfloat WGT_LIGHT_YELLOW [4]; +extern const GLfloat WGT_LIGHT_RED [4]; +extern const GLfloat WGT_LIGHT_GREEN [4]; +extern const GLfloat WGT_LIGHT_BLUE [4]; +extern const GLfloat WGT_LIGHT_TRANS_GRAY [4]; +extern const GLfloat WGT_LIGHT_TRANS_BLACK [4]; +extern const GLfloat WGT_LIGHT_TRANS_YELLOW [4]; +extern const GLfloat WGT_LIGHT_TRANS_RED [4]; +extern const GLfloat WGT_LIGHT_TRANS_GREEN [4]; +extern const GLfloat WGT_LIGHT_TRANS_BLUE [4]; + + +class Widget +{ + friend class WidgetManager; + + /* Basic widget properties that will always be used. */ + int m_x, m_y; + int m_width, m_height; + + /* On/off features, these are not dependant on the delta time and are not + * animated. They are off by default. */ + bool m_enable_rect; + GLuint m_rect_list; //A display list number that draws the rectangle with + //possibly rounded corners. + const GLfloat *m_rect_color; //This const cannot change the value it points to, but it + //can change where it points to. + WidgetArea m_round_corners; + + bool m_enable_texture; + GLuint m_texture; + + bool m_enable_text; + std::string m_text; + WidgetFontSize m_text_size; + Font::FontAlignType m_text_x_alignment; + Font::FontAlignType m_text_y_alignment; + + + bool m_enable_scroll; +/* int m_scroll_pos_x;*/ + int m_scroll_pos_y; +/* int m_scroll_speed_x;*/ + int m_scroll_speed_y; + + /* Delta time dependant features, these deactivate after a certain time, + * and are dependant on the delta time. They have animations. */ + static const float MAX_TEXT_SCALE = 1.2f; + static const float MIN_TEXT_SCALE = 1.0f; + float m_text_scale; //Used for the pulse effect + +/*public:*/ + Widget + ( + const int X_, + const int Y_, + const int WIDTH_, + const int HEIGHT_ + ); + ~Widget(); + + void update(const float DELTA); + +/* int get_x_pos() const { return m_x; } + int get_y_pos() const { return m_y; } + int get_width() const { return m_width; } + int get_height() const { return m_height; } + + void set_x_pos( const int X ) { m_x = X; } + void set_y_pos( const int Y ) { m_y = Y; } + void set_width( const int WIDTH ) { m_width = WIDTH; } + void set_height( const int HEIGHT ) { m_height = HEIGHT; }*/ + void resize_to_text(); //This checks if the widget is smaller than the + //text, and if so, changes the width and height. + bool create_rect(int radius); + + /* Switch features functions. */ +/* void enable_rect() {m_enable_rect = true;} + void disable_rect() {m_enable_rect = false;}*/ +// void toggle_rect() {m_enable_rect = m_enable_rect ? false : true;} +/* void set_rect_color(const GLfloat *COLOR) {m_rect_color = COLOR;} + const GLfloat* get_rect_color() const {return m_rect_color;}*/ + +/* void enable_texture() {m_enable_texture = true;} + void disable_texture() {m_enable_texture = false;}*/ +// void toggle_texture() {m_enable_texture = m_enable_texture ? false : true;} +/* void set_texture(const int TEXTURE) {m_texture = TEXTURE;} + int get_texture () const {return m_texture;}*/ + +/* void enable_text() {m_enable_text = true;} + void disable_text() {m_enable_text = false;} + void toggle_text() {m_enable_text = m_enable_text ? false : true;} + void set_text(const char* TEXT) {m_text.assign(TEXT);} + void set_text(const std::string TEXT) {m_text.assign(TEXT);} + std::string get_text() const {return m_text;} + void set_text_size( const WidgetFontSize SIZE ) { m_text_size = SIZE; } + WidgetFontSize get_text_size() { return m_text_size; }*/ + + /* Time limited features' functions. */ + void pulse() {m_text_scale = MAX_TEXT_SCALE;} + + /* Convenience functions. */ + void lighten_color(); + void darken_color(); + +}; + +#endif + +/* EOF */ diff --git a/src/widget_manager.cpp b/src/widget_manager.cpp new file mode 100644 index 000000000..ef3f181e7 --- /dev/null +++ b/src/widget_manager.cpp @@ -0,0 +1,1152 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// This code originally from Neverball copyright (C) 2003 Robert Kooima +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "widget_manager.hpp" + +#include "user_config.hpp" + +//TODO: this include should not be necesary? +#include + +#include "gui/font.hpp" + +//TEMP +#include +#include +#include +#include + +WidgetManager *widget_manager; + +const int WidgetManager::WGT_NONE = -1; + +WidgetManager::WidgetManager() : +m_x( -1 ), m_y( -1 ), m_selected_wgt_token( WGT_NONE ) +{ + restore_default_states(); + init_fonts(); +} + +//----------------------------------------------------------------------------- +WidgetManager::~WidgetManager() +{ + delete_wgts(); + delete_fonts(); +} + +//----------------------------------------------------------------------------- +bool WidgetManager::add_wgt +( + const int TOKEN, + const int MIN_WIDTH, + const int MIN_HEIGHT +) +{ + if( TOKEN != WGT_NONE && find_id( TOKEN ) != WGT_NONE ) + { + std::cerr << "WARNING: tried to create widget with token " << + TOKEN << " but it is already in use.\n"; + return false; + } + + WidgetID new_id; + new_id.token = TOKEN; + //There is no reason to make a token-less widget active, so if the token + //WGT_NONE, the widget is forced to be inactive, preventing bugs. + new_id.active = TOKEN != WGT_NONE ? m_default_active : false; + new_id.min_width = MIN_WIDTH; + new_id.min_height = MIN_HEIGHT; + + new_id.widget = new Widget(0, 0, 0, 0); + + new_id.widget->m_enable_rect = m_default_show_rect; + new_id.widget->m_rect_color = m_default_rect_color; + + new_id.widget->m_enable_texture = m_default_show_texture; + new_id.widget->m_texture = m_default_texture; + + new_id.widget->m_enable_text = m_default_show_text; + new_id.widget->m_text.assign(m_default_text); + new_id.widget->m_text_size = m_default_text_size; + new_id.widget->m_text_x_alignment = m_default_text_x_alignment; + new_id.widget->m_text_y_alignment = m_default_text_y_alignment; + + new_id.widget->m_enable_scroll = m_default_enable_scroll; +/* new_id.widget->m_scroll_pos_x = m_default_scroll_x_pos;*/ + new_id.widget->m_scroll_pos_y = m_default_scroll_y_pos; +/* new_id.widget->m_scroll_speed_x = m_default_scroll_x_speed;*/ + new_id.widget->m_scroll_speed_y = m_default_scroll_y_speed; + + m_widgets.push_back(new_id); + + return true; +} + +//----------------------------------------------------------------------------- +bool WidgetManager::break_line() +{ + const int LAST_WGT = m_widgets.size() - 1; + + if( LAST_WGT < 0 ) + { + std::cerr << "Warning: tried to add a break before adding any " << + "widgets.\n"; + return false; + } + + const int NUM_BREAKS = m_breaks.size(); + + if( NUM_BREAKS > 0 ) + { + if( !line_breaks(LAST_WGT) ) m_breaks.push_back(LAST_WGT); + else + { + std::cerr << "Warning: tried to add a break twice after " << + "widget with token" << m_widgets[LAST_WGT].token << ".\n"; + return false; + } + } + else + { + m_breaks.push_back(LAST_WGT); + } + + return true; +} + + +//----------------------------------------------------------------------------- +void WidgetManager::delete_wgts() +{ + const int NUM_WIDGETS = m_widgets.size(); + + for(int i = 0; i < NUM_WIDGETS; ++i) + { + delete m_widgets[i].widget; + } + + m_widgets.clear(); +} + +//----------------------------------------------------------------------------- +bool WidgetManager::line_breaks( const int WGT ) const +{ + const int NUM_BREAKS = m_breaks.size(); + + if( NUM_BREAKS > 0) + { + for(int i = 0; i < NUM_BREAKS; ++i ) + { + if( m_breaks[i] == WGT ) return true; + } + } + + return false; +} + +//----------------------------------------------------------------------------- +int WidgetManager::find_id(const int TOKEN) const +{ + const int NUM_WIDGETS = m_widgets.size(); + + for( int i = 0; i < NUM_WIDGETS; ++i ) + { + if( TOKEN == m_widgets[i].token ) + return i; + } + + return WGT_NONE; +} + +//----------------------------------------------------------------------------- +void WidgetManager::update(const float DELTA) +{ + + //Enable 2D rendering + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(0.0, user_config->m_width, 0.0, user_config->m_height, -1.0, 1.0); + glMatrixMode(GL_MODELVIEW); + + + glPushAttrib(GL_LIGHTING_BIT | + GL_COLOR_BUFFER_BIT | + GL_DEPTH_BUFFER_BIT); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_COLOR_MATERIAL); + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE ) ; + + const int NUM_WIDGETS = m_widgets.size(); + for( int i = 0; i < NUM_WIDGETS; ++i) + { + m_widgets[i].widget->update(DELTA); + } + + glPopAttrib(); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + +} + +/** The calc_width() function retrieves the width of the smallest rectangle + * that contains all the widgets being handled by the widget manager. + */ +int WidgetManager::calc_width() const +{ + const int NUM_WIDGETS = m_widgets.size(); + + int wgt_width; + int curr_width = 0; + int total_width = 0; + + for( int i = 0; i < NUM_WIDGETS; ++i ) + { + wgt_width = m_widgets[i].widget->m_width; + curr_width += wgt_width; + + if( line_breaks(i) ) + { + if( curr_width > total_width ) total_width = curr_width; + curr_width = 0; + } + + } + if( curr_width > total_width ) total_width = curr_width; + + return total_width; +} + +/** The calc_height() function retrieves the height of the smallest rectangle + * that contains all the widgets being handled by the widget manager. + */ +int WidgetManager::calc_height() const +{ + const int NUM_WIDGETS = m_widgets.size(); + if( NUM_WIDGETS < 0 ) return 0; + + int total_height = calc_line_height(0); + + for( int i = 1; i < NUM_WIDGETS; ++i ) + { + if( line_breaks(i-1) ) + { + total_height += calc_line_height(i); + } + } + + return total_height; +} + +//----------------------------------------------------------------------------- +bool WidgetManager::layout(const WidgetArea POSITION) +{ + const int NUM_WIDGETS = m_widgets.size(); + if( NUM_WIDGETS < 0 ) return true; + + int SCREEN_WIDTH = user_config->m_width; + int SCREEN_HEIGHT = user_config->m_height; + + int width; + int height; + //Resize the widgets. + for( int i = 0; i < NUM_WIDGETS; ++i ) + { + width = (SCREEN_WIDTH * m_widgets[i].min_width) / 100; + height = (SCREEN_HEIGHT * m_widgets[i].min_height) / 100; + + m_widgets[i].widget->m_width = width; + m_widgets[i].widget->m_height = height; +/* TEMP + * + m_widgets[i].widget->resize_to_text(); +*/ + } + + const int WGTS_WIDTH = calc_width(); + const int WGTS_HEIGHT = calc_height(); + + if( WGTS_WIDTH > SCREEN_WIDTH ) + { + std::cerr << "WARNING: total width of the widgets is bigger than " << + "the screen, because the total minimum width given is bigger " << + "than 100%,\n"; + } + if( WGTS_HEIGHT > SCREEN_HEIGHT ) + { + std::cerr << "WARNING: total height of the widgets is bigger " << + "than the screen, because the total minimum height given is " << + "bigger than 100%.\n"; + } + + //To position things on the screen, remember that with OpenGL, in the + //Y-axis the position 0 is in the bottom of the screen, just like the top + //right quad of a cartesian plane. + switch(POSITION) + { + case WGT_AREA_NW: + m_x = 0; + m_y = SCREEN_HEIGHT; + break; + + case WGT_AREA_SW: + m_x = 0; + m_y = 0; + break; + + case WGT_AREA_NE: + m_x = SCREEN_WIDTH - WGTS_WIDTH; + m_y = SCREEN_HEIGHT; + break; + + case WGT_AREA_SE: + m_x = SCREEN_WIDTH - WGTS_WIDTH; + m_y = 0; + break; + + case WGT_AREA_LFT: + m_x = 0; + m_y = (int)(SCREEN_HEIGHT * 0.5 + WGTS_HEIGHT * 0.5f ); + break; + + case WGT_AREA_RGT: + m_x = SCREEN_WIDTH - WGTS_WIDTH; + m_y = (int)(SCREEN_HEIGHT * 0.5 + WGTS_HEIGHT * 0.5f ); + break; + + case WGT_AREA_TOP: + m_x = (int)(SCREEN_WIDTH * 0.5f - WGTS_WIDTH * 0.5f ); + m_y = SCREEN_HEIGHT; + break; + + case WGT_AREA_BOT: + m_x = (int)(SCREEN_WIDTH * 0.5f - WGTS_WIDTH * 0.5f ); + m_y = 0; + break; + + //A layout of WGT_AREA_NONE should probably just do nothing. + case WGT_AREA_NONE: + case WGT_AREA_ALL: + m_x = (int)(SCREEN_WIDTH * 0.5f - WGTS_WIDTH * 0.5f ); + m_y = (int)(SCREEN_HEIGHT * 0.5 + WGTS_HEIGHT * 0.5f ); + break; + } + + int line_height = calc_line_height(0); + + //m_y should be the bottom value of the widgets, because that's the way + //OpenGL handles the y-axis. + m_y -= line_height; + +//TODO: fix if m_x or m_y is bigger than the screen. + + //This formula seems not to have much theory behind it, we pick the + //smallest from the screen height and width because if we pick the + //biggest one, it might look bad for the smaller one, but it doesn't + //happens the other way around, and it's divided by 60, maybe because + //it results in small enough values to be of use, or maybe because it's + //divided by 60 minutes? + const int RADIUS = ( SCREEN_HEIGHT < SCREEN_WIDTH ? SCREEN_HEIGHT : SCREEN_WIDTH ) / 60; + + //The widgets positions given are for the lower left corner. + int widget_x = m_x + ( WGTS_WIDTH - calc_line_width( 0 )) / 2; + int widget_y = m_y; + for( int i = 0; i < NUM_WIDGETS; ++i ) + { + m_widgets[i].widget->m_x = widget_x; + m_widgets[i].widget->m_y = widget_y + (line_height - m_widgets[i].widget->m_height); + + if( !(m_widgets[i].widget->create_rect(RADIUS)) ) + { + return false; + } + + if( i + 1 < NUM_WIDGETS ) + { + if( line_breaks(i) ) + { + line_height = calc_line_height(i+1); + + widget_y -= line_height; + widget_x = m_x + ( WGTS_WIDTH - calc_line_width( i+1 )) / 2; + } + else + { + widget_x += m_widgets[i].widget->m_width; + } + } + } + + //Always select the first active widget by default + for( int i = 0; i < NUM_WIDGETS; ++i ) + { + if( m_widgets[i].active) m_selected_wgt_token = m_widgets[i].token; + + } + + //Cleanups + m_breaks.clear(); + restore_default_states(); + + return true; +} + +//----------------------------------------------------------------------------- +int WidgetManager::calc_line_width( const int START_WGT ) const +{ + int total_width = 0; + const int NUM_WIDGETS = m_widgets.size(); + + for( int i = START_WGT; i < NUM_WIDGETS; ++i ) + { + total_width += m_widgets[i].widget->m_width; + if( line_breaks(i) ) break; + } + + return total_width; +} + +//----------------------------------------------------------------------------- +int WidgetManager::calc_line_height( const int START_WGT ) const +{ + int line_height = 0; + const int NUM_WIDGETS = m_widgets.size(); + + for( int i = START_WGT; i < NUM_WIDGETS; ++i ) + { + if( line_height < m_widgets[i].widget->m_height ) + { + line_height = m_widgets[i].widget->m_height; + } + if( line_breaks(i) ) break; + } + + return line_height; +} + +//----------------------------------------------------------------------------- +void WidgetManager::set_selected_wgt(const int TOKEN) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) + { + m_selected_wgt_token = TOKEN; + } + else std::cerr << "Tried to select unexistant widget with token " << TOKEN << '\n'; +} + + +//----------------------------------------------------------------------------- +void WidgetManager::set_initial_activation_state( const bool ACTIVE) +{ + m_default_active = ACTIVE; +} + +//----------------------------------------------------------------------------- +void WidgetManager::set_initial_rect_state +( + const bool SHOW, + const WidgetArea ROUND_CORNERS, + const GLfloat* const COLOR +) +{ + m_default_show_rect = SHOW; + m_default_rect_round_corners = ROUND_CORNERS; + m_default_rect_color = COLOR; +} + +//----------------------------------------------------------------------------- +void WidgetManager::set_initial_texture_state +( + const bool SHOW, + const int TEXTURE +) +{ + m_default_show_texture = SHOW; + m_default_texture = TEXTURE; +} + +//----------------------------------------------------------------------------- +void WidgetManager::set_initial_text_state +( + const bool SHOW, + const std::string TEXT, + const WidgetFontSize SIZE, + const Font::FontAlignType X_ALIGN, + const Font::FontAlignType Y_ALIGN +) +{ + m_default_show_text = SHOW; + m_default_text = TEXT; + m_default_text_size = SIZE; + m_default_text_x_alignment = X_ALIGN; + m_default_text_y_alignment = Y_ALIGN; +} + +//----------------------------------------------------------------------------- +void WidgetManager::set_initial_scroll_state +( + const bool ENABLE, +/* const int X_POS,*/ + const int Y_POS, +/* const int X_SPEED,*/ + const int Y_SPEED +) +{ + m_default_enable_scroll = ENABLE; +/* m_default_scroll_x_pos = X_POS;*/ + m_default_scroll_y_pos = Y_POS; +/* m_default_scroll_x_speed = X_SPEED;*/ + m_default_scroll_y_speed = Y_SPEED; +} + +//----------------------------------------------------------------------------- +void WidgetManager::restore_default_states() +{ + m_default_active = false; + m_default_show_rect = false; + m_default_rect_round_corners = WGT_AREA_NONE; + m_default_rect_color = WGT_TRANS_BLACK; + m_default_show_texture = false; + m_default_texture = 0; + m_default_show_text = false; + m_default_text = ""; + m_default_text_size = WGT_FNT_MED; + m_default_text_x_alignment = Font::ALIGN_CENTER; + m_default_text_y_alignment = Font::ALIGN_CENTER; + m_default_enable_scroll = false; +/* m_default_scroll_x_pos = 0;*/ + m_default_scroll_y_pos = 0; +/* m_default_scroll_x_speed = 0;*/ + m_default_scroll_y_speed = 0; +} + +//----------------------------------------------------------------------------- +void WidgetManager::activate_wgt(const int TOKEN) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].active = true; + else std::cerr << "Tried to activate unexistant widget with token " << TOKEN << '\n'; +} + +//----------------------------------------------------------------------------- +void WidgetManager::deactivate_wgt(const int TOKEN) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].active = false; + else std::cerr << "Tried to deactivate unexistant widget with token " << TOKEN << '\n'; +} + +//----------------------------------------------------------------------------- +void WidgetManager::set_wgt_color(const int TOKEN, const GLfloat *COLOR) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].widget->m_rect_color = COLOR; + else std::cerr << "Tried to change the rect color of an unexistant widget with token " << TOKEN << '\n'; +} + +//----------------------------------------------------------------------------- +void WidgetManager::set_wgt_round_corners(const int TOKEN, const WidgetArea CORNERS) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].widget->m_round_corners = CORNERS; + else std::cerr << "Tried to change the round corners of an unexistant widget with token " << TOKEN << '\n'; +} +//----------------------------------------------------------------------------- +void WidgetManager::show_wgt_rect(const int TOKEN) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].widget->m_enable_rect = true; + else std::cerr << "Tried to show the rect of an unexistant widget with token " << TOKEN << '\n'; +} + +//----------------------------------------------------------------------------- +void WidgetManager::hide_wgt_rect(const int TOKEN) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].widget->m_enable_rect = false; + else std::cerr << "Tried to hide the rect of an unexistant widget with token " << TOKEN << '\n'; +} + +//----------------------------------------------------------------------------- +/*void WidgetManager::toggle_wgt_rect(const int TOKEN) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].widget->toggle_rect(); + else std::cerr << "Tried to toggle the rect of an unexistant widget with token " << TOKEN << '\n'; +}*/ + +//----------------------------------------------------------------------------- +void WidgetManager::set_wgt_texture(const int TOKEN, const int TEXTURE) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].widget->m_texture = TEXTURE; + else std::cerr << "Tried to set the texture of an unexistant widget with token " << TOKEN << '\n'; +} + +//----------------------------------------------------------------------------- +void WidgetManager::show_wgt_texture(const int TOKEN) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].widget->m_enable_texture = true; + else std::cerr << "Tried to show the texture of an unexistant widget with token " << TOKEN << '\n'; +} + +//----------------------------------------------------------------------------- +void WidgetManager::hide_wgt_texture(const int TOKEN) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].widget->m_enable_texture = false; + else std::cerr << "Tried to hide the texture of an unexistant widget with token " << TOKEN << '\n'; +} + +//----------------------------------------------------------------------------- +/*void WidgetManager::toggle_wgt_texture(const int TOKEN) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].widget->toggle_texture(); + else std::cerr << "Tried to toggle the texture of an unexistant widget with token " << TOKEN << '\n'; +} +*/ +//----------------------------------------------------------------------------- +void WidgetManager::set_wgt_text( const int TOKEN, const char* TEXT ) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].widget->m_text = TEXT; + else std::cerr << "Tried to set text to an unexistant widget with token " << TOKEN << '\n'; +} + +//----------------------------------------------------------------------------- +void WidgetManager::set_wgt_text( const int TOKEN, const std::string TEXT ) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].widget->m_text = TEXT; + else std::cerr << "Tried to set the text of an unexistant widget with token " << TOKEN << '\n'; +} + +//----------------------------------------------------------------------------- +void WidgetManager::set_wgt_text_size( const int TOKEN, const WidgetFontSize SIZE) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].widget->m_text_size = SIZE; + else std::cerr << "Tried to set the text size of an unexistant widget with token " << TOKEN << '\n'; +} + +//----------------------------------------------------------------------------- +void WidgetManager::show_wgt_text( const int TOKEN ) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].widget->m_enable_text = true; + else std::cerr << "Tried to show the text of an unexistant widget with token " << TOKEN << '\n'; +} + +//----------------------------------------------------------------------------- +void WidgetManager::hide_wgt_text( const int TOKEN ) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].widget->m_enable_text = false; + else std::cerr << "Tried to hide the text of an unexistant widget with token " << TOKEN << '\n'; +} + +//----------------------------------------------------------------------------- +/*void WidgetManager::toggle_wgt_text( const int TOKEN ) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].widget->toggle_text(); + else std::cerr << "Tried to toggle the text of an unexistant widget with token " << TOKEN << '\n'; +}*/ + +//----------------------------------------------------------------------------- +void WidgetManager::set_wgt_text_x_alignment( const int TOKEN, const Font::FontAlignType ALIGN ) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].widget->m_text_x_alignment = ALIGN; + else std::cerr << "Tried to set the X alignment of text of an unexistant widget with token " << TOKEN << '\n'; +} + +//----------------------------------------------------------------------------- +void WidgetManager::set_wgt_text_y_alignment( const int TOKEN, const Font::FontAlignType ALIGN ) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].widget->m_text_y_alignment = ALIGN; + else std::cerr << "Tried to set the Y alignment of text of an unexistant widget with token " << TOKEN << '\n'; +} + +//----------------------------------------------------------------------------- +void WidgetManager::enable_wgt_scroll( const int TOKEN ) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].widget->m_enable_scroll = true; + else std::cerr << "Tried to enable scrolling of an unexistant widget with token " << TOKEN << '\n'; +} + +//----------------------------------------------------------------------------- +void WidgetManager::disable_wgt_scroll( const int TOKEN ) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].widget->m_enable_scroll = false; + else std::cerr << "Tried to disable scrolling of an unexistant widget with token " << TOKEN << '\n'; +} + +//----------------------------------------------------------------------------- +/*void WidgetManager::set_wgt_x_scroll_pos( const int TOKEN, const int POS ) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].widget->m_scroll_pos_x = POS; + else std::cerr << "Tried to set the X scroll position of an unexistant widget with token " << TOKEN << '\n'; +}*/ + +//----------------------------------------------------------------------------- +void WidgetManager::set_wgt_y_scroll_pos( const int TOKEN, const int POS ) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].widget->m_scroll_pos_y = POS; + else std::cerr << "Tried to set the Y scroll position of an unexistant widget with token " << TOKEN << '\n'; +} + +//----------------------------------------------------------------------------- +/*void WidgetManager::set_wgt_x_scroll_speed( const int TOKEN, const int SPEED ) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].widget->m_scroll_speed_x = SPEED; + else std::cerr << "Tried to set the X scroll speed of an unexistant widget with token " << TOKEN << '\n'; +}*/ + +//----------------------------------------------------------------------------- +void WidgetManager::set_wgt_y_scroll_speed( const int TOKEN, const int SPEED ) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].widget->m_scroll_speed_y = SPEED; + else std::cerr << "Tried to set the Y scroll speed of an unexistant widget with token " << TOKEN << '\n'; +} + +/** pulse_widget() passes the pulse order to the right widget. + */ +void WidgetManager::pulse_wgt(const int TOKEN) const +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].widget->pulse(); + else std::cerr << "Tried to pulse unexistant widget with token " << TOKEN << '\n'; +} + +//----------------------------------------------------------------------------- +void WidgetManager::lighten_wgt_color(const int TOKEN) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].widget->lighten_color(); + else std::cerr << "Tried to lighten an unexistant widget with token " << TOKEN << '\n'; +} + +//----------------------------------------------------------------------------- +void WidgetManager::darken_wgt_color(const int TOKEN) +{ + const int ID = find_id(TOKEN); + if( ID != WGT_NONE ) m_widgets[ID].widget->darken_color(); + else std::cerr << "Tried to darken an unexistant widget with token " << TOKEN << '\n'; +} + +/** The handle_mouse() function returns the current widget under the mouse + * pointer, if it's different from the selected widget. If the widget under + * the mouse is the selected widget, it returns WGT_NONE. + */ +int WidgetManager::handle_mouse(const int X, const int Y ) +{ + //Search if the given x and y positions are on top of any widget. Please + //note that the bounding box for each widget is used instead of the + //real widget shape. + + //The search starts with the current selected widget(since it's most + //probable that the mouse is on top of it ) + const int NUM_WIDGETS = m_widgets.size(); + + if( m_selected_wgt_token != WGT_NONE ) + { + const int SELECTED_WGT_ID = find_id(m_selected_wgt_token); + + if(( X > m_widgets[SELECTED_WGT_ID].widget->m_x ) && + ( X < m_widgets[SELECTED_WGT_ID].widget->m_x + m_widgets[SELECTED_WGT_ID].widget->m_width ) && + ( Y > m_widgets[SELECTED_WGT_ID].widget->m_y ) && + ( Y < m_widgets[SELECTED_WGT_ID].widget->m_y + m_widgets[SELECTED_WGT_ID].widget->m_height )) + { + return WGT_NONE; + } + } + + for( int i = 0; i < NUM_WIDGETS; ++i ) + { + if(!(m_widgets[i].active)) continue; + + //Simple bounding box test + if(( X > m_widgets[i].widget->m_x ) && + ( X < m_widgets[i].widget->m_x + m_widgets[i].widget->m_width ) && + ( Y > m_widgets[i].widget->m_y ) && + ( Y < m_widgets[i].widget->m_y + m_widgets[i].widget->m_height )) + { + m_selected_wgt_token = m_widgets[i].token; + return m_selected_wgt_token; + } + } + + return WGT_NONE; +} + +/** The handle_keyboard() function stores the current widget under the cursor + * after receiving input from a key. + */ +int WidgetManager::handle_keyboard(const int KEY) +{ + if( m_selected_wgt_token == WGT_NONE ) return WGT_NONE; + + int next_wgt = find_id(m_selected_wgt_token); + //FIXME: eventually, the keys should not be hard coded + switch (KEY) + { + case SDLK_LEFT: + next_wgt = find_left_widget(find_id(m_selected_wgt_token)); + break; + + case SDLK_RIGHT: + next_wgt = find_right_widget(find_id(m_selected_wgt_token)); + break; + + case SDLK_UP: + next_wgt = find_top_widget(find_id(m_selected_wgt_token)); + break; + + case SDLK_DOWN: + next_wgt = find_bottom_widget(find_id(m_selected_wgt_token)); + break; + + //FIXME: apparently, there are different codes for the + and - + //near the numlock. + case SDLK_PLUS: + { + const int ID = find_id(m_selected_wgt_token); + if( m_widgets[ID].widget->m_enable_scroll ) + { + //FIXME: these increases shouldn't be in pixels, but in percentages. + //This should increase it by 1%, and the page buttons by 5%. + m_widgets[ID].widget->m_scroll_speed_y -= 1; + } + break; + } + + case SDLK_MINUS: + { + const int ID = find_id(m_selected_wgt_token); + if( m_widgets[ID].widget->m_enable_scroll ) + { + m_widgets[ID].widget->m_scroll_speed_y += 1; + } + break; + } + + case SDLK_PAGEUP: + { + const int ID = find_id(m_selected_wgt_token); + if( m_widgets[ID].widget->m_enable_scroll ) + { + m_widgets[ID].widget->m_scroll_speed_y -= 5; + } + break; + } + + case SDLK_PAGEDOWN: + { + const int ID = find_id(m_selected_wgt_token); + if( m_widgets[ID].widget->m_enable_scroll ) + { + m_widgets[ID].widget->m_scroll_speed_y += 5; + } + return WGT_NONE; + } + + default: return WGT_NONE; + } + + if( next_wgt == WGT_NONE) return WGT_NONE; + + m_selected_wgt_token = m_widgets[next_wgt].token; + return m_selected_wgt_token; +} + +/** The handle_joystick() function stores the current widget under the cursor + * after receiving input from the joystick. + */ +//FIXME: shouldn't direction and value be merged? +int WidgetManager::handle_joystick +( + const int axis, + const int direction, + int value +) +{ + if( m_selected_wgt_token == WGT_NONE ) return WGT_NONE; + + int next_wgt = WGT_NONE; //This asignment is to prevent a compiler warning + switch (axis) + { + case 0: + if( direction == 0 ) + { + next_wgt = find_left_widget(find_id(m_selected_wgt_token)); + } + else if( direction == 1 ) + { + next_wgt = find_right_widget(find_id(m_selected_wgt_token)); + } + break; + + case 1: + if( direction == 0 ) + { + next_wgt = find_top_widget(find_id(m_selected_wgt_token)); + } + else if( direction == 1 ) + { + next_wgt = find_bottom_widget(find_id(m_selected_wgt_token)); + } + break; + + default: return WGT_NONE; + } + + if( next_wgt == find_id(m_selected_wgt_token) ) return WGT_NONE; + + m_selected_wgt_token = m_widgets[next_wgt].token; + return m_selected_wgt_token; +} + +/** find_left_widget() returns the closest widget to the left of START_WGT. + */ +int WidgetManager::find_left_widget(const int START_WGT) const +{ + const int NUM_WIDGETS = m_widgets.size(); + int closest_wgt = WGT_NONE; + int closest_dist = user_config->m_width; + for( int i = 0; i < NUM_WIDGETS; ++i ) + { + if(!(m_widgets[i].active)) continue; + + if( m_widgets[i].widget->m_x + m_widgets[i].widget->m_width < m_widgets[START_WGT].widget->m_x + m_widgets[START_WGT].widget->m_width) + { + const int START_WGT_Y_CENTER = m_widgets[START_WGT].widget->m_y + m_widgets[START_WGT].widget->m_height / 2; + const int START_WGT_X_CENTER = m_widgets[START_WGT].widget->m_x + m_widgets[START_WGT].widget->m_width / 2; + const int CURR_WGT_Y_CENTER = m_widgets[i].widget->m_y + m_widgets[i].widget->m_height / 2; + const int CURR_WGT_X_CENTER = m_widgets[i].widget->m_x + m_widgets[i].widget->m_width / 2; + + const int X_DIST = START_WGT_X_CENTER - CURR_WGT_X_CENTER; + if( X_DIST > abs(CURR_WGT_Y_CENTER - START_WGT_Y_CENTER )) + { + if( closest_dist > X_DIST ) + { + closest_dist = X_DIST; + closest_wgt = i; + } + + } + } +#if 0 + //Check if the widget with the id i is to the left of the start widget. + //To do so, simply checking if the X position of the i widget is smaller + //than the start widget(divides the screen in a left and right blocks), + //and that the distance between the two widgets in the X axis is bigger + //than the distance in the Y axis(so that widgets on top and the + //bottom are ignored). + if( m_widgets[i].widget->m_x <= m_widgets[START_WGT].widget->m_x && + m_widgets[START_WGT].widget->m_x - m_widgets[i].widget->m_x >= + abs(m_widgets[START_WGT].widget->m_y - m_widgets[i].widget->m_y )) + { + //FIXME: instead of using plib's routines, we should use functions + //that works on integers that don't depend on external libraries. + sgVec2 a; + a[0] = m_widgets[START_WGT].widget->m_x; + a[1] = m_widgets[START_WGT].widget->m_y; + + sgVec2 b; + b[0] = m_widgets[i].widget->m_x; + b[1] = m_widgets[i].widget->m_y; + //Now that we know that the i widget is to the left, we have + //to find if it's the closest one. + if( closest_dist * closest_dist > sgDistanceSquaredVec2( a,b ) ) + { + closest_dist = (int)sgDistanceSquaredVec2( a,b ); + closest_wgt = i; + } + + } +#endif + } + + return closest_wgt; +} + +/** find_right_widget() returns the closest widget to the right of START_WGT + */ +int WidgetManager::find_right_widget(const int START_WGT) const +{ + const int NUM_WIDGETS = m_widgets.size(); + int closest_wgt = WGT_NONE; + int closest_dist = user_config->m_width; + for( int i = 0; i < NUM_WIDGETS; ++i ) + { + if(!(m_widgets[i].active)) continue; + + //Check if the widget with the id i is on top of the start widget. + //First it is checked if the y value of the i widget is higher than + //the start widget(remember that for the widget manager a higher + //value means that it is more on top). Then we add more precision: + //if the vertical distance of the center of the two widgets is + //smaller than the horizontal distance between the center of the two + //widgets, then the i widget is definitely on top of the START_WGT + //widget. + if( m_widgets[i].widget->m_x > m_widgets[START_WGT].widget->m_x ) + { + const int START_WGT_Y_CENTER = m_widgets[START_WGT].widget->m_y + m_widgets[START_WGT].widget->m_height / 2; + const int START_WGT_X_CENTER = m_widgets[START_WGT].widget->m_x + m_widgets[START_WGT].widget->m_width / 2; + const int CURR_WGT_Y_CENTER = m_widgets[i].widget->m_y + m_widgets[i].widget->m_height / 2; + const int CURR_WGT_X_CENTER = m_widgets[i].widget->m_x + m_widgets[i].widget->m_width / 2; + + const int X_DIST = CURR_WGT_X_CENTER - START_WGT_X_CENTER; + if( X_DIST > abs(CURR_WGT_Y_CENTER - START_WGT_Y_CENTER )) + { + if( closest_dist > X_DIST ) + { + closest_dist = X_DIST; + closest_wgt = i; + } + + } + } +#if 0 + //Check if the widget with the id i is to the right of the start widget. + if( m_widgets[i].widget->m_x >= m_widgets[START_WGT].widget->m_x && + m_widgets[i].widget->m_x - m_widgets[START_WGT].widget->m_x >= + abs(m_widgets[START_WGT].widget->m_y - m_widgets[i].widget->m_y )) + { + //FIXME: instead of using plib's routines, we should use functions + //that works on integers that don't depend on external libraries. + sgVec2 a; + a[0] = m_widgets[START_WGT].widget->m_x; + a[1] = m_widgets[START_WGT].widget->m_y; + + sgVec2 b; + b[0] = m_widgets[i].widget->m_x; + b[1] = m_widgets[i].widget->m_y; + + //Check if the widget found is closer than the closest + //widget we have found + if( closest_dist * closest_dist > sgDistanceSquaredVec2( a,b ) ) + { + closest_dist = (int)sgDistanceSquaredVec2( a,b ); + closest_wgt = i; + } + + } +#endif + } + + return closest_wgt; +} +//FIXME: fix find_left_widget and find_right_widget. +/** find_top_widget() returns the closest widget on top of START_WGT. + * Remember that for the widget manager, the value 0 in the y-axis is in + * the bottom of the screen. + */ +int WidgetManager::find_top_widget(const int START_WGT) const +{ + const int NUM_WIDGETS = m_widgets.size(); + int closest_wgt = WGT_NONE; + int closest_dist = user_config->m_height; + for(int i = 0; i < NUM_WIDGETS; ++i) + { + if(!(m_widgets[i].active)) continue; + + //Check if the widget with the ID i is on top of the start widget. + //First it is checked if the y value of the i widget is higher than + //the start widget(remember that for the widget manager a higher + //value means that it closer to the top of the screen). Then we add + //more precision: if the vertical distance of the center of the two + //widgets is smaller than the horizontal distance between the center + //of the two widgets, then the i widget is definitely on top of the + //START_WGT widget. + if( m_widgets[i].widget->m_y > m_widgets[START_WGT].widget->m_y ) + { + const int START_WGT_Y_CENTER = m_widgets[START_WGT].widget->m_y + m_widgets[START_WGT].widget->m_height / 2; + const int START_WGT_X_CENTER = m_widgets[START_WGT].widget->m_x + m_widgets[START_WGT].widget->m_width / 2; + const int CURR_WGT_Y_CENTER = m_widgets[i].widget->m_y + m_widgets[i].widget->m_height / 2; + const int CURR_WGT_X_CENTER = m_widgets[i].widget->m_x + m_widgets[i].widget->m_width / 2; + + const int Y_DIST = CURR_WGT_Y_CENTER - START_WGT_Y_CENTER; + if( Y_DIST > abs(CURR_WGT_X_CENTER - START_WGT_X_CENTER )) + { + if( closest_dist > Y_DIST ) + { + closest_dist = Y_DIST; + closest_wgt = i; + } + + } + } + } + + return closest_wgt; +} + +/** find_bottom_widget() returns the closest widget under START_WGT. + * Remember that for the widget manager, the value 0 in the y-axis is in + * the bottom of the screen. + */ +int WidgetManager::find_bottom_widget(const int START_WGT) const +{ + const int NUM_WIDGETS = m_widgets.size(); + int closest_wgt = WGT_NONE; + int closest_dist = user_config->m_height; + for(int i = 0; i < NUM_WIDGETS; ++i) + { + if(!(m_widgets[i].active)) continue; + + if( m_widgets[i].widget->m_y + m_widgets[i].widget->m_height < m_widgets[START_WGT].widget->m_y + m_widgets[START_WGT].widget->m_height) + { + const int START_WGT_Y_CENTER = m_widgets[START_WGT].widget->m_y + m_widgets[START_WGT].widget->m_height / 2; + const int START_WGT_X_CENTER = m_widgets[START_WGT].widget->m_x + m_widgets[START_WGT].widget->m_width / 2; + const int CURR_WGT_Y_CENTER = m_widgets[i].widget->m_y + m_widgets[i].widget->m_height / 2; + const int CURR_WGT_X_CENTER = m_widgets[i].widget->m_x + m_widgets[i].widget->m_width / 2; + + const int Y_DIST = START_WGT_Y_CENTER - CURR_WGT_Y_CENTER; + if( Y_DIST > abs(CURR_WGT_X_CENTER - START_WGT_X_CENTER )) + { + if( closest_dist > Y_DIST ) + { + closest_dist = Y_DIST; + closest_wgt = i; + } + + } + } + } + + return closest_wgt; +} + diff --git a/src/widget_manager.hpp b/src/widget_manager.hpp new file mode 100644 index 000000000..7a440a27c --- /dev/null +++ b/src/widget_manager.hpp @@ -0,0 +1,191 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// This code originally from Neverball copyright (C) 2003 Robert Kooima +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HEADER_WIDGET_MANAGER_H +#define HEADER_WIDGET_MANAGER_H + +#include "widget.hpp" + +#include + +/* Here are some big-picture instructions about how to use this widget + * manager: the extern widget_manager is a global interface to the class. Call + * add_wgt() to specify the widgets you want, and for each widget specify the + * details of it with the 'switch features', that can be changed between + * show/hide, the initial setting for all of them is to be hidden. You will + * usually have to call it's set_*() function, then the show_*() functions. + * After you have defined all the widgets in the screen, call layout(), that + * will do the actual work at creating the widgets. Call the activated + * functions during the time the widgets are alive, and make sure that + * update() is called each frame. + * + * You can use set_initial_*state() to avoid setting the state of the same + * switch features with same values over and over; the default states are + * reset when you call layout() or you can use reset_default_states(). + */ + + +class WidgetManager +{ + struct WidgetID + { + int token; + bool active; //If true, then this widget is interactive(though by + //definition, widgets are supposed to be interactive). + + //The percentages of the container this widget takes + int min_width; + int min_height; + + Widget *widget; + }; + + std::vector m_widgets; + std::vector m_breaks; + + int m_x; + int m_y; + + int m_selected_wgt_token; + + //TODO: change 'default' to 'initial' + bool m_default_active; + bool m_default_show_rect; + bool m_default_rect_round_corners; + const GLfloat *m_default_rect_color; + bool m_default_show_texture; + int m_default_texture; + bool m_default_show_text; + std::string m_default_text; + WidgetFontSize m_default_text_size; + Font::FontAlignType m_default_text_x_alignment; + Font::FontAlignType m_default_text_y_alignment; + + bool m_default_enable_scroll; +/* int m_default_scroll_x_pos;*/ + int m_default_scroll_y_pos; +/* int m_default_scroll_x_speed;*/ + int m_default_scroll_y_speed; + + bool line_breaks( const int WGT ) const; + + int find_id(const int TOKEN) const; + int calc_width() const; + int calc_height() const; + int calc_line_width(const int START_WGT) const; + int calc_line_height(const int START_WGT) const; + + int find_left_widget(const int START_WGT) const; + int find_right_widget(const int START_WGT) const; + int find_top_widget(const int START_WGT) const; + int find_bottom_widget(const int START_WGT) const; + +public: + //FIXME: maybe I should get this out of this class? + static const int WGT_NONE; + + WidgetManager(); + ~WidgetManager(); + + bool add_wgt + ( + const int TOKEN, //A number that names the widget. + const int MIN_WIDTH, //These values are percentages not pixels. If + //the widget is inside a container, 100% + //represents container space, otherwise 100% is + //the screen space. + const int MIN_HEIGHT + ); + bool break_line(); + + void delete_wgts(); + + void update(const float DELTA); + + //TODO: WGT_AREA_NONE and WGT_AREA_ALL should have some difference. + //Both WGT_AREA_NONE and WGT_AREA_ALL will produce centered widgets. + bool layout( const WidgetArea POSITION ); + + //TODO: make all get functions const + int get_selected_wgt() const { return m_selected_wgt_token;} + void set_selected_wgt(const int TOKEN); + + /* On/off widget switch features. They are all disabled/hidden initially. */ + void set_initial_activation_state( const bool ACTIVE); + void set_initial_rect_state(const bool SHOW, const WidgetArea ROUND_CORNERS, const GLfloat* const COLOR ); + void set_initial_texture_state(const bool SHOW, const int TEXTURE ); + void set_initial_text_state + ( + const bool SHOW, + const std::string TEXT, + const WidgetFontSize SIZE, + const Font::FontAlignType X_ALIGN, + const Font::FontAlignType Y_ALIGN + ); + void set_initial_scroll_state(const bool ENABLE, /*const int X_POS,*/ const int Y_POS, /*const int X_SPEED, */const int Y_SPEED ); + void restore_default_states(); + + void activate_wgt(const int TOKEN); + void deactivate_wgt(const int TOKEN); + + //FIXME: maybe this should be set_wgt_rect_color ? and put after the other rect funcs? + void set_wgt_color(const int TOKEN, const GLfloat* const COLOR); + void set_wgt_round_corners(const int TOKEN, const WidgetArea CORNERS); + void show_wgt_rect(const int TOKEN); + void hide_wgt_rect(const int TOKEN); +// void toggle_wgt_rect(const int TOKEN); + + void set_wgt_texture(const int TOKEN, const int TEXTURE); + void show_wgt_texture(const int TOKEN); + void hide_wgt_texture(const int TOKEN); +// void toggle_wgt_texture(const int TOKEN); + + void set_wgt_text( const int TOKEN, const char* TEXT ); + void set_wgt_text( const int TOKEN, const std::string TEXT ); + void set_wgt_text_size( const int TOKEN, const WidgetFontSize SIZE); + void show_wgt_text( const int TOKEN ); + void hide_wgt_text( const int TOKEN ); +// void toggle_wgt_text( const int TOKEN ); + void set_wgt_text_x_alignment( const int TOKEN, const Font::FontAlignType ALIGN ); + void set_wgt_text_y_alignment( const int TOKEN, const Font::FontAlignType ALIGN ); + + void enable_wgt_scroll( const int TOKEN ); + void disable_wgt_scroll( const int TOKEN ); +/* void set_wgt_x_scroll_pos( const int TOKEN, const int POS );*/ + void set_wgt_y_scroll_pos( const int TOKEN, const int POS ); +/* void set_wgt_x_scroll_speed( const int TOKEN, const int SPEED );*/ + void set_wgt_y_scroll_speed( const int TOKEN, const int SPEED ); + + /* Activated widget features. */ + void pulse_wgt( const int TOKEN ) const; + + /* Convenience widget functions. */ + void lighten_wgt_color(const int TOKEN); + void darken_wgt_color(const int TOKEN); + + /* Input device handling. */ + int handle_mouse( const int X, const int Y ); + int handle_keyboard( const int KEY ); + int handle_joystick( int axis, int dir, int value ); +}; + +extern WidgetManager *widget_manager; + +#endif + +/* EOF */ diff --git a/src/widget_set.cpp b/src/widget_set.cpp deleted file mode 100644 index 95faafd4f..000000000 --- a/src/widget_set.cpp +++ /dev/null @@ -1,1654 +0,0 @@ -// $Id$ -// -// SuperTuxKart - a fun racing game with go-kart -// This code originally from Neverball copyright (C) 2003 Robert Kooima -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#include - -#include - -#include "constants.hpp" -#include "widget_set.hpp" -#include "loader.hpp" -#include "user_config.hpp" -#include "sound_manager.hpp" -#include "gui/font.hpp" - -WidgetSet *widgetSet; - -WidgetSet::WidgetSet() - : m_active(0), m_pause_id(0), m_paused(0) -{ - const int width = user_config->m_width; - const int height = user_config->m_height; - const int S = (height < width) ? height : width ; - m_radius = S/60; - - init_fonts(); -} - -//----------------------------------------------------------------------------- -WidgetSet::~WidgetSet() -{ - /* Release any remaining widget texture and display list indices. */ - - for (int id = 1; id < MAX_WIDGETS; id++) - { - if (glIsList(m_widgets[id].rect_obj)) - glDeleteLists(m_widgets[id].rect_obj, 1); - - m_widgets[id].type = GUI_FREE; - m_widgets[id].text_img = 0; - m_widgets[id].rect_obj = 0; - m_widgets[id].cdr = 0; - m_widgets[id].car = 0; - } - delete_fonts(); -} - -//----------------------------------------------------------------------------- -void WidgetSet::reInit() -{ - delete_fonts(); - init_fonts(); - -} // reInit - -//----------------------------------------------------------------------------- -int WidgetSet::hot(int id) -{ - return (m_widgets[id].type & GUI_STATE); -} - - -/** Initialize a display list containing a rectangle that can have rounded - * corners, with texture coordinates to properly apply a texture - * map to the rectangle as though the corners were not rounded. - */ -GLuint WidgetSet::rect -( - const int X, - const int Y, - const int WIDTH, - const int HEIGHT, - const int RECT, - const int RADIUS -) -{ - //TODO:Write warning to stderr when radius > half of the height - GLuint list = glGenLists(1); - - const int NUM_QUADS = 8; -#ifdef ENABLE_BORDER - const int NUM_VERTICES = NUM_QUADS * 4 + 4; - float border [NUM_VERTICES][2]; -#endif - - int i; - - glNewList(list, GL_COMPILE); - { - //To create a rounded rectangle, we generate lines that are - //progressively bigger, which are given as vertex points for each - //quad. - glBegin(GL_QUAD_STRIP); - { - //Draw the left side of a rectangle. - for (i = 0; i <= NUM_QUADS; ++i) - { - //To find the position in the X and Y axis of each point of - //the quads, we use the property of the unit circle (a circle - //with radius = 1) that at any given angle, cos(angle) is the - //position of the unit circle at that angle in the X axis, - //and that sin(angle) is the position of the unit circle at - //that angle in the Y axis. Then the values from cos(angle) - //and sin(angle) are multiplied by the radius. - // - //First we find the angle: since 2 * pi is the number of - //radians in an entire circle, 0.5 * pi is a quarter of the - //circle, which is a corner of the rounded rectangle. Based - //on that, we just split the radians in a corner in NUM_QUADS - //+ 1 parts, and use the angles at those parts to find the - //X and Y position of the points. - const float ANGLE = 0.5f * M_PI * (float) i / (float) NUM_QUADS; - const float CIRCLE_X = RADIUS * cos(ANGLE); - const float CIRCLE_Y = RADIUS * sin(ANGLE); - - //After we generate the positions in circle for the angles, - //we have to position each rounded corner properly depending - //on the position of the rectangle and the radius. The y - //position for the circle is dependant on rect; if a corner - //wasn't given, then the y position is computed as if it was - //for a rectangle without rounder corners. - const float VERTEX_X = X + RADIUS - CIRCLE_X; - const float VERTEX_YA = Y + HEIGHT + ((RECT & GUI_NW) ? - (CIRCLE_Y - RADIUS) : 0); - const float VERTEX_YB = Y + ((RECT & GUI_SW) ? - (RADIUS - CIRCLE_Y) : 0); - -#ifdef ENABLE_BORDER - { - //Store the vertex on top from the end to the beginning - //of the array - border [(NUM_VERTICES - 1) - i][0] = VERTEX_X; - border [(NUM_VERTICES - 1) - i][1] = VERTEX_YA; - - //Store the vertex on the bottom from the beginning to - //the end of the array - border [i][0] = VERTEX_X; - border [i][1] = VERTEX_YB; - } -#endif - - glTexCoord2f((VERTEX_X - X) / WIDTH, - 1 - (VERTEX_YA - Y) / HEIGHT); - glVertex2f(VERTEX_X, VERTEX_YA); - - glTexCoord2f((VERTEX_X - X) / WIDTH, - 1 - (VERTEX_YB - Y) / HEIGHT); - glVertex2f(VERTEX_X, VERTEX_YB); - } - - //Draw the right side of a rectangle - for (i = 0; i <= NUM_QUADS; ++i) - { - const float ANGLE = 0.5f * M_PI * (float) i / (float) NUM_QUADS; - - //By inverting the use of sin and cos we get corners that are - //drawn from left to right instead of right to left - const float CIRCLE_X = RADIUS * sin(ANGLE); - const float CIRCLE_Y = RADIUS * cos(ANGLE); - - float VERTEX_X = X + WIDTH - RADIUS + CIRCLE_X; - float VERTEX_YA = Y + HEIGHT + ((RECT & GUI_NE) ? (CIRCLE_Y - RADIUS) : 0); - float VERTEX_YB = Y + ((RECT & GUI_SE) ? (RADIUS - CIRCLE_Y) : 0); - - glTexCoord2f((VERTEX_X - X) / WIDTH, 1 - (VERTEX_YA - Y) / HEIGHT); - glVertex2f(VERTEX_X, VERTEX_YA); - - glTexCoord2f((VERTEX_X - X) / WIDTH, 1 - (VERTEX_YB - Y) / HEIGHT); - glVertex2f(VERTEX_X, VERTEX_YB); - -#ifdef ENABLE_BORDER - { - border [(NUM_QUADS * 3 + 2) - i][0] = VERTEX_X; - border [(NUM_QUADS * 3 + 2) - i][1] = VERTEX_YA; - border [(NUM_QUADS + 1)+i][0] = VERTEX_X; - border [(NUM_QUADS + 1)+i][1] = VERTEX_YB; - } -#endif - } - - } - glEnd(); -#ifdef ENABLE_BORDER - { - float border_width = 10.0; - float vec[2]; - glBegin(GL_QUAD_STRIP); - glColor3i(0,0,0); - for (i = 0; i < NUM_VERTICES; ++i) - { - //Find vector from the center of the corner to the - //border's vertex, depending on the direction. - if( i < NUM_VERTICES / 4) //South west - { - vec[0] = border[i][0] - X - RADIUS; - vec[1] = Y + HEIGHT - RADIUS + border[i][1]; - } - else if( i < NUM_VERTICES / 2) //South east - { - vec[0] = -X - WIDTH + RADIUS + border[i][0]; - vec[1] = Y + HEIGHT - RADIUS + border[i][1]; - } - else if( i < NUM_VERTICES / 4 * 3) //North east - { - vec[0] = -X - WIDTH + RADIUS + border[i][0]; - vec[1] = Y + RADIUS + border[i][1]; - } - else //North west - { - vec[0] = border[i][0] - X - RADIUS; - vec[1] = Y + RADIUS + border[i][1]; - } - - float vector_length = sqrt(vec[0]*vec[0]+vec[1]*vec[1]); - - //Prevent division by zero - if(vector_length == 0) vector_length = 0.0000001; - - //Resize vector to border's width - vec[0] = vec[0] / vector_length * border_width; - vec[1] = vec[1] / vector_length * border_width; - - glVertex2f(border[i][0] + vec[0], border[i][1] + vec[1]); - glVertex2f(border[i][0], border[i][1]); - } - - //Close the border using the last value of vec - glVertex2f(border[0][0] + vec[0], border[0][1] + vec[1]); - glVertex2f(border[0][0], border[0][1]); - glEnd(); - } -#endif - } - glEndList(); - - return list; -} - -//----------------------------------------------------------------------------- -int WidgetSet::add_widget(int parent, int type) -{ - int id; - - /* Find an unused entry in the widget table. */ - - for (id = 1; id < MAX_WIDGETS; id++) - { - if (m_widgets[id].type == GUI_FREE) - { - /* Set the type and default properties. */ - - m_widgets[id].type = type; - m_widgets[id].token = 0; - m_widgets[id].value = 0; - m_widgets[id].size = 0; - m_widgets[id].rect = GUI_ALL; - m_widgets[id].w = 0; - m_widgets[id].h = 0; - m_widgets[id].text_img = 0; - m_widgets[id].rect_obj = 0; - m_widgets[id].color0 = gui_wht; - m_widgets[id].color1 = gui_wht; - m_widgets[id].scale = 1.0f; - m_widgets[id].count_text = ""; - - /* Insert the new widget into the parents's widget list. */ - - if (parent) - { - m_widgets[id].car = 0; - m_widgets[id].cdr = m_widgets[parent].car; - m_widgets[parent].car = id; - } - else - { - m_widgets[id].car = 0; - m_widgets[id].cdr = 0; - } - - return id; - } - } // for i - - fprintf(stderr, "Out of widget IDs\n"); - - return 0; -} - -//----------------------------------------------------------------------------- -int WidgetSet::harray(int parent) { return add_widget(parent, GUI_HARRAY); } -//----------------------------------------------------------------------------- -int WidgetSet::varray(int parent) { return add_widget(parent, GUI_VARRAY); } -//----------------------------------------------------------------------------- -int WidgetSet::hstack(int parent) { return add_widget(parent, GUI_HSTACK); } -//----------------------------------------------------------------------------- -int WidgetSet::vstack(int parent) { return add_widget(parent, GUI_VSTACK); } -//----------------------------------------------------------------------------- -int WidgetSet::filler(int parent) { return add_widget(parent, GUI_FILLER); } - -//----------------------------------------------------------------------------- -void WidgetSet::set_label(int id, const std::string &text) -{ - float l,r,b,t; - font_gui->getBBox(text, m_widgets[id].size, 0.0f, &l, &r, &b, &t); - m_widgets[id].yOffset = (int)b; - m_widgets[id].text_width = (int)(r-l+0.99); - m_widgets[id]._text = text; - // There is a potential bug here: if the label being set is - // larger than the current width, the container (parent) does - // not get wider ... the layout will be broken. Unfortunately, - // that's somewhat difficult to fix, since layout will in turn - // add the radius to width of button (see button_up), ... - // So for now we only print a warning: - if(m_widgets[id].text_width > m_widgets[id].w) - { - fprintf(stderr, - "set_label increased width of parent container, layout will be invalid\n"); - } -} - -//----------------------------------------------------------------------------- -void WidgetSet::set_count(int id, int value) -{ - m_widgets[id].value = value; - std::stringstream ss; - ss << value; - m_widgets[id].count_text = ss.str(); - float l,r,b,t; - font_gui->getBBox(m_widgets[id].count_text, m_widgets[id].size, 0, &l, &r, &b, &t); - m_widgets[id].yOffset = (int)(b); - m_widgets[id].w = (int)(r-l+0.99); - m_widgets[id].h = (int)(t-b+0.99); -} // set_count - -//----------------------------------------------------------------------------- -void WidgetSet::set_clock(int id, int value) -{ - m_widgets[id].value = value; -} - -//----------------------------------------------------------------------------- -void WidgetSet::set_multi(int id, const char *text) -{ - const char *p; - - char s[8][MAX_STR]; - int i, j, jd; - - size_t n = 0; - - /* Copy each delimited string to a line buffer. */ - - for (p = text, j = 0; *p && j < 8; j++) - { - strncpy(s[j], p, (n = strcspn(p, "\\"))); - s[j][n] = 0; - - if (*(p += n) == '\\') p++; - } - - /* Set the label value for each line. */ - - for (i = j - 1, jd = m_widgets[id].car; i >= 0 && jd; i--, jd = m_widgets[jd].cdr) - set_label(jd, s[i]); -} - -//----------------------------------------------------------------------------- -int WidgetSet::image(int parent, int textureId, int w, int h, int rect) -{ - int id; - - if ((id = add_widget(parent, GUI_IMAGE))) - { - m_widgets[id].text_img = textureId; - m_widgets[id].w = w; - m_widgets[id].h = h; - m_widgets[id].rect = rect; - - } - return id; -} - -//----------------------------------------------------------------------------- -int WidgetSet::start(int parent, const std::string &text, int size, int token, int value) -{ - int id; - - if ((id = state(parent, text, size, token, value))) - m_active = id; - - return id; -} - -//----------------------------------------------------------------------------- -int WidgetSet::state(int parent, const std::string &text, int size, int token, int value) -{ - int id; - - if ((id = add_widget(parent, GUI_STATE))) - { - m_widgets[id]._text = text; - float l,r,b,t; - font_gui->getBBox(text, size, 0, &l, &r, &b, &t); - // Apparently the font system allows charater to be - // under the y=0 line (e.g the character g, p, y) - // Since the text will not be centered because of this, - // the distance to the baseline y=0 is saved and during - // output added to the y location. - m_widgets[id].w = (int)(r-l+0.99); - m_widgets[id].text_width = m_widgets[id].w; - m_widgets[id].h = (int)(t-b+0.99); - m_widgets[id].yOffset = (int)b - m_widgets[id].h/4 ; - m_widgets[id].size = size; - m_widgets[id].token = token; - m_widgets[id].value = value; - } - return id; -} - -//----------------------------------------------------------------------------- -int WidgetSet::label(int parent, const std::string &text, int size, int rect, const float *c0, - const float *c1) -{ - int id; - - if ((id = add_widget(parent, GUI_LABEL))) - { - m_widgets[id]._text = text; - float l,r,b,t; - font_gui->getBBox(text, size, 0, &l, &r, &b, &t); - m_widgets[id].yOffset = (int)(b); - m_widgets[id].w = (int)(r-l+0.99); - m_widgets[id].h = (int)(t-b+0.99); - m_widgets[id].text_width = m_widgets[id].w; - m_widgets[id].size = size; - m_widgets[id].color0 = c0 ? c0 : gui_yel; - m_widgets[id].color1 = c1 ? c1 : gui_red; - m_widgets[id].rect = rect; - } - return id; -} - -//----------------------------------------------------------------------------- -int WidgetSet::count(int parent, int value, int size, int rect) -{ - int id; - - if ((id = add_widget(parent, GUI_COUNT))) - { - m_widgets[id].value = value; - m_widgets[id].size = size; - m_widgets[id].color0 = gui_yel; - m_widgets[id].color1 = gui_red; - m_widgets[id].rect = rect; - std::stringstream ss; - ss << value; - m_widgets[id].count_text = ss.str(); - float l,r,b,t; - font_gui->getBBox(m_widgets[id].count_text, size, 0, &l, &r, &b, &t); - m_widgets[id].yOffset = (int)(b); - m_widgets[id].w = (int)(r-l+0.99); - m_widgets[id].h = (int)(t-b+0.99); - } - return id; -} // count - -//----------------------------------------------------------------------------- -int WidgetSet::clock(int parent, int value, int size, int rect) -{ - int id; - - if ((id = add_widget(parent, GUI_CLOCK))) - { - printf("clock: FIXME\n"); - //m_widgets[id].w = digit_w[size][0] * 6; - //m_widgets[id].h = digit_h[size][0]; - m_widgets[id].value = value; - m_widgets[id].size = size; - m_widgets[id].color0 = gui_yel; - m_widgets[id].color1 = gui_red; - m_widgets[id].rect = rect; - } - return id; -} - -//----------------------------------------------------------------------------- -int WidgetSet::space(int parent) -{ - int id; - - if ((id = add_widget(parent, GUI_SPACE))) - { - m_widgets[id].w = 0; - m_widgets[id].h = 0; - } - return id; -} - -//----------------------------------------------------------------------------- -int WidgetSet::pause(int parent) -{ - int id; - - if ((id = add_widget(parent, GUI_PAUSE))) - { - m_widgets[id].value = 0; - m_widgets[id].rect = GUI_ALL; - } - return id; -} - -/** Create a multi-line text box using a vertical array of labels. - * Parse the text for '\' characters and treat them as line-breaks. - * Preserve the rect specifation across the entire array. - */ -int WidgetSet::multi(int parent, const char *text, int size, int rect, const float *c0, - const float *c1) -{ - int id = 0; - - if (text && (id = varray(parent))) - { - const char *p; -#define MAX_NUMBER_OF_LINES 20 - // Important; this s must be static, otherwise the strings will be - // lost when returning --> garbage will be displayed. - static char s[MAX_NUMBER_OF_LINES][MAX_STR]; - int r[MAX_NUMBER_OF_LINES]; - int i, j; - - size_t n = 0; - - /* Copy each delimited string to a line buffer. */ - - for (p = text, j = 0; *p && j < MAX_NUMBER_OF_LINES; j++) - { - strncpy(s[j], p, (n = strcspn(p, "\n"))); - s[j][n] = 0; - r[j] = 0; - - if (*(p += n) == '\n') p++; - } - - /* Set the curves for the first and last lines. */ - - if (j > 0) - { - r[0] |= rect & (GUI_NW | GUI_NE); - r[j - 1] |= rect & (GUI_SW | GUI_SE); - } - - /* Create a label widget for each line. */ - - for (i = 0; i < j; i++) - label(id, s[i], size, r[i], c0, c1); - } - return id; -} - -/** The bottom-up pass determines the area of all widgets. The minimum - * width and height of a leaf widget is given by the size of its - * contents. Array and stack widths and heights are computed - * recursively from these. - */ -void WidgetSet::harray_up(int id) -{ - int jd, c = 0; - - /* Find the widest child width and the highest child height. */ - - for (jd = m_widgets[id].car; jd; jd = m_widgets[jd].cdr) - { - widget_up(jd); - - if (m_widgets[id].h < m_widgets[jd].h) - m_widgets[id].h = m_widgets[jd].h; - if (m_widgets[id].w < m_widgets[jd].w) - m_widgets[id].w = m_widgets[jd].w; - c++; - } - - /* Total width is the widest child width times the child count. */ - - m_widgets[id].w *= c; -} - -//----------------------------------------------------------------------------- -void WidgetSet::varray_up(int id) -{ - int jd, c = 0; - - /* Find the widest child width and the highest child height. */ - - for (jd = m_widgets[id].car; jd; jd = m_widgets[jd].cdr) - { - widget_up(jd); - - if (m_widgets[id].h < m_widgets[jd].h) - m_widgets[id].h = m_widgets[jd].h; - if (m_widgets[id].w < m_widgets[jd].w) - m_widgets[id].w = m_widgets[jd].w; - - c++; - } - - /* Total height is the highest child height times the child count. */ - - m_widgets[id].h *= c; -} - -//----------------------------------------------------------------------------- -void WidgetSet::hstack_up(int id) -{ - int jd; - - /* Find the highest child height. Sum the child widths. */ - - for (jd = m_widgets[id].car; jd; jd = m_widgets[jd].cdr) - { - widget_up(jd); - - if (m_widgets[id].h < m_widgets[jd].h) - m_widgets[id].h = m_widgets[jd].h; - - m_widgets[id].w += m_widgets[jd].w; - } -} - -//----------------------------------------------------------------------------- -void WidgetSet::vstack_up(int id) -{ - int jd; - - /* Find the widest child width. Sum the child heights. */ - - for (jd = m_widgets[id].car; jd; jd = m_widgets[jd].cdr) - { - widget_up(jd); - - if (m_widgets[id].w < m_widgets[jd].w) - m_widgets[id].w = m_widgets[jd].w; - - m_widgets[id].h += m_widgets[jd].h; - } -} - -//----------------------------------------------------------------------------- -void WidgetSet::paused_up(int id) -{ - /* Store width and height for later use in text rendering. */ - - m_widgets[id].x = m_widgets[id].w; - m_widgets[id].y = m_widgets[id].h; - - /* The pause widget fills the screen. */ - - m_widgets[id].w = user_config->m_width; - m_widgets[id].h = user_config->m_height; -} - -//----------------------------------------------------------------------------- -void WidgetSet::button_up(int id) -{ - /* Store width and height for later use in text rendering. */ - - m_widgets[id].x = m_widgets[id].w; - m_widgets[id].y = m_widgets[id].h; - - if (m_widgets[id].w < m_widgets[id].h && m_widgets[id].w > 0) - m_widgets[id].w = m_widgets[id].h; - -//TODO: check if we really want padded text elements - /* Padded text elements look a little nicer. */ - - if (m_widgets[id].w < user_config->m_width) - m_widgets[id].w += m_radius; - if (m_widgets[id].h < user_config->m_height) - m_widgets[id].h += m_radius; -} - -//----------------------------------------------------------------------------- -void WidgetSet::widget_up(int id) -{ - if (id) - switch (m_widgets[id].type & GUI_TYPE) - { - case GUI_HARRAY: harray_up(id); break; - case GUI_VARRAY: varray_up(id); break; - case GUI_HSTACK: hstack_up(id); break; - case GUI_VSTACK: vstack_up(id); break; - case GUI_PAUSE: paused_up(id); break; - default: button_up(id); break; - } -} - -/** The top-down layout pass distributes available area as computed - * during the bottom-up pass. Widgets use their area and position to - * initialize rendering state. - */ -void WidgetSet::harray_dn(int id, int x, int y, int w, int h) -{ - int jd, i = 0, c = 0; - - m_widgets[id].x = x; - m_widgets[id].y = y; - m_widgets[id].w = w; - m_widgets[id].h = h; - - /* Count children. */ - - for (jd = m_widgets[id].car; jd; jd = m_widgets[jd].cdr) - c += 1; - - /* Distribute horizontal space evenly to all children. */ - - for (jd = m_widgets[id].car; jd; jd = m_widgets[jd].cdr, i++) - { - int x0 = x + i * w / c; - int x1 = x + (i + 1) * w / c; - - widget_dn(jd, x0, y, x1 - x0, h); - } -} - -//----------------------------------------------------------------------------- -void WidgetSet::varray_dn(int id, int x, int y, int w, int h) -{ - int jd, i = 0, c = 0; - - m_widgets[id].x = x; - m_widgets[id].y = y; - m_widgets[id].w = w; - m_widgets[id].h = h; - - /* Count children. */ - - for (jd = m_widgets[id].car; jd; jd = m_widgets[jd].cdr) - c += 1; - - /* Distribute vertical space evenly to all children. */ - - for (jd = m_widgets[id].car; jd; jd = m_widgets[jd].cdr, i++) - { - int y0 = y + i * h / c; - int y1 = y + (i + 1) * h / c; - - widget_dn(jd, x, y0, w, y1 - y0); - } -} - -//----------------------------------------------------------------------------- -void WidgetSet::hstack_dn(int id, int x, int y, int w, int h) -{ - int jd, jx = x, jw = 0, c = 0; - - m_widgets[id].x = x; - m_widgets[id].y = y; - m_widgets[id].w = w; - m_widgets[id].h = h; - - /* Measure the total width requested by non-filler children. */ - - for (jd = m_widgets[id].car; jd; jd = m_widgets[jd].cdr) - if ((m_widgets[jd].type & GUI_TYPE) == GUI_FILLER) - c += 1; - else - jw += m_widgets[jd].w; - - /* Give non-filler children their requested space. */ - /* Distribute the rest evenly among filler children. */ - - for (jd = m_widgets[id].car; jd; jd = m_widgets[jd].cdr) - { - if ((m_widgets[jd].type & GUI_TYPE) == GUI_FILLER) - widget_dn(jd, jx, y, (w - jw) / c, h); - else - widget_dn(jd, jx, y, m_widgets[jd].w, h); - - jx += m_widgets[jd].w; - } -} - -//----------------------------------------------------------------------------- -void WidgetSet::vstack_dn(int id, int x, int y, int w, int h) -{ - int jd, jy = y, jh = 0, c = 0; - - m_widgets[id].x = x; - m_widgets[id].y = y; - m_widgets[id].w = w; - m_widgets[id].h = h; - - /* Measure the total height requested by non-filler children. */ - - for (jd = m_widgets[id].car; jd; jd = m_widgets[jd].cdr) - if ((m_widgets[jd].type & GUI_TYPE) == GUI_FILLER) - c += 1; - else - jh += m_widgets[jd].h; - - /* Give non-filler children their requested space. */ - /* Distribute the rest evenly among filler children. */ - - for (jd = m_widgets[id].car; jd; jd = m_widgets[jd].cdr) - { - if ((m_widgets[jd].type & GUI_TYPE) == GUI_FILLER) - widget_dn(jd, x, jy, w, (h - jh) / c); - else - widget_dn(jd, x, jy, w, m_widgets[jd].h); - - jy += m_widgets[jd].h; - } -} - -//----------------------------------------------------------------------------- -void WidgetSet::filler_dn(int id, int x, int y, int w, int h) -{ - /* Filler expands to whatever size it is given. */ - - m_widgets[id].x = x; - m_widgets[id].y = y; - m_widgets[id].w = w; - m_widgets[id].h = h; -} - -//----------------------------------------------------------------------------- -void WidgetSet::button_dn(int id, int x, int y, int w, int h) -{ - /* Recall stored width and height for text rendering. */ - - int rect = m_widgets[id].rect; - int r = ((m_widgets[id].type & GUI_TYPE) == GUI_PAUSE ? m_radius * 4 : m_radius); - - m_widgets[id].x = x; - m_widgets[id].y = y; - m_widgets[id].w = w; - m_widgets[id].h = h; - /* Create display lists for the text area and rounded rectangle. */ - - m_widgets[id].rect_obj = this->rect(-w / 2, -h / 2, w, h, rect, r); -} - -//----------------------------------------------------------------------------- -void WidgetSet::widget_dn(int id, int x, int y, int w, int h) -{ - if (id) - switch (m_widgets[id].type & GUI_TYPE) - { - case GUI_HARRAY: harray_dn(id, x, y, w, h); break; - case GUI_VARRAY: varray_dn(id, x, y, w, h); break; - case GUI_HSTACK: hstack_dn(id, x, y, w, h); break; - case GUI_VSTACK: vstack_dn(id, x, y, w, h); break; - case GUI_FILLER: filler_dn(id, x, y, w, h); break; - case GUI_SPACE: filler_dn(id, x, y, w, h); break; - default: button_dn(id, x, y, w, h); break; - } -} - -/** During GUI layout, we make a bottom-up pass to determine total area - * requirements for the widget tree. We position this area to the - * sides or center of the screen. Finally, we make a top-down pass to - * distribute this area to each widget. - */ -void WidgetSet::layout(int id, int xd, int yd) -{ - int x, y; - - const int W = user_config->m_width; - const int H = user_config->m_height; - int w = W; - int h = W; - - widget_up(id); - - w = m_widgets[id].w; - h = m_widgets[id].h; - if (xd < 0) x = 0; - else if (xd > 0) x = (W - w); - else x = (W - w) / 2; - - if (yd < 0) y = 0; - else if (yd > 0) y = (H - h); - else y = (H - h) / 2; - - widget_dn(id, x, y, w, h); - - /* Hilite the widget under the cursor, if any. */ - - point(id, -1, -1); -} - -//----------------------------------------------------------------------------- -int WidgetSet::search(int id, int x, int y) -{ - int jd, kd; - assert(id < MAX_WIDGETS); - - /* Search the hierarchy for the widget containing the given point. */ - - if (id && (m_widgets[id].x <= x && x < m_widgets[id].x + m_widgets[id].w && - m_widgets[id].y <= y && y < m_widgets[id].y + m_widgets[id].h)) - { - if (hot(id)) - return id; - - for (jd = m_widgets[id].car; jd; jd = m_widgets[jd].cdr) - if ((kd = search(jd, x, y))) - return kd; - } - return 0; -} - -/** Activate a widget, allowing it to behave as a normal state widget. - * This may be used to create image buttons, or cause an array of - * widgets to behave as a single state widget. - */ -int WidgetSet::activate_widget(int id, int token, int value) -{ - m_widgets[id].type |= GUI_STATE; - m_widgets[id].token = token; - m_widgets[id].value = value; - - return id; -} - -//----------------------------------------------------------------------------- -int WidgetSet::delete_widget(int id) -{ - if (id) - { - /* Recursively delete all subwidgets. */ - - delete_widget(m_widgets[id].cdr); - delete_widget(m_widgets[id].car); - - /* Release any GL resources held by this widget. */ - - if (glIsList(m_widgets[id].rect_obj)) - glDeleteLists(m_widgets[id].rect_obj, 1); - - /* Mark this widget unused. */ - m_widgets[id].type = GUI_FREE; - m_widgets[id].text_img = 0; - m_widgets[id].rect_obj = 0; - m_widgets[id].cdr = 0; - m_widgets[id].car = 0; - } - return 0; -} - -//----------------------------------------------------------------------------- -void WidgetSet::paint_rect(int id, int st) -{ -#ifdef SNIP - static const GLfloat back[4][4] = - { - { 0.1f, 0.1f, 0.1f, 0.5f } - , /* off and inactive */ - { 0.3f, 0.3f, 0.3f, 0.5f }, /* off and active */ - { 0.7f, 0.3f, 0.0f, 0.5f }, /* on and inactive */ - { 1.0f, 0.7f, 0.3f, 0.5f }, /* on and active */ - }; -#endif - static const GLfloat back[4][4] = - { - { 0.1f, 0.1f, 0.1f, 0.5f } - , /* off and inactive */ - { 0.5f, 0.5f, 0.5f, 0.8f }, /* off and active */ - { 1.0f, 0.7f, 0.3f, 0.5f }, /* on and inactive */ - { 1.0f, 0.7f, 0.3f, 0.8f }, /* on and active */ - }; - - int jd, i = 0; - - /* Use the widget status to determine the background color. */ - - if (hot(id)) - i = st | (((m_widgets[id].value) ? 2 : 0) | - ((id == m_active) ? 1 : 0)); - switch (m_widgets[id].type & GUI_TYPE) - { - case GUI_IMAGE: - case GUI_SPACE: - case GUI_FILLER: - break; - - case GUI_HARRAY: - case GUI_VARRAY: - case GUI_HSTACK: - case GUI_VSTACK: - - /* Recursively paint all subwidgets. */ - - for (jd = m_widgets[id].car; jd; jd = m_widgets[jd].cdr) - paint_rect(jd, i); - - break; - - default: - - /* Draw a leaf's background, colored by widget state. */ - glPushMatrix(); - { - glTranslatef((GLfloat) (m_widgets[id].x + m_widgets[id].w / 2), - (GLfloat) (m_widgets[id].y + m_widgets[id].h / 2), 0.f); - - glColor4fv(back[i]); - glCallList(m_widgets[id].rect_obj); - } - glPopMatrix(); - - break; - } -} - -//----------------------------------------------------------------------------- -void WidgetSet::paint_array(int id) -{ - int jd; - - glPushMatrix(); - { - GLfloat cx = m_widgets[id].x + m_widgets[id].w / 2.0f; - GLfloat cy = m_widgets[id].y + m_widgets[id].h / 2.0f; - GLfloat ck = m_widgets[id].scale; - - glTranslatef(+cx, +cy, 0.0f); - glScalef(ck, ck, ck); - glTranslatef(-cx, -cy, 0.0f); - - /* Recursively paint all subwidgets. */ - - for (jd = m_widgets[id].car; jd; jd = m_widgets[jd].cdr) - paint_text(jd); - } - glPopMatrix(); -} - -//----------------------------------------------------------------------------- -void WidgetSet::paint_image(int id) -{ - /* Draw the widget rect, textured using the image. */ - - glPushMatrix(); - { - glTranslatef((GLfloat) (m_widgets[id].x + m_widgets[id].w / 2), - (GLfloat) (m_widgets[id].y + m_widgets[id].h / 2), 0.f); - /* For whatever reasons the icons are upside down, - so we mirror them back to the right orientation */ - glScalef(m_widgets[id].scale, - -m_widgets[id].scale, - m_widgets[id].scale); - - glBindTexture(GL_TEXTURE_2D, m_widgets[id].text_img); - glColor4fv(gui_wht); - glCallList(m_widgets[id].rect_obj); - } - glPopMatrix(); -} - -//----------------------------------------------------------------------------- -void WidgetSet::paint_count(int id) -{ - font_gui->Print(m_widgets[id].count_text, m_widgets[id].size, - m_widgets[id].x, m_widgets[id].y ); - return; -} // paint_count - -//----------------------------------------------------------------------------- -void WidgetSet::paint_clock(int id) -{ - //int i = m_widgets[id].size; - const int MT = (m_widgets[id].value / 6000) / 10; - //int mo = (m_widgets[id].value / 6000) % 10; - //int st = ((m_widgets[id].value % 6000) / 100) / 10; - //int so = ((m_widgets[id].value % 6000) / 100) % 10; - //int ht = ((m_widgets[id].value % 6000) % 100) / 10; - //int ho = ((m_widgets[id].value % 6000) % 100) % 10; - - GLfloat dx_large=1.0f;// FIXME = (GLfloat) digit_w[i][0]; - GLfloat dx_small=0.1f;// = (GLfloat) digit_w[i][0] * 0.75f; - - printf("paint_clock: FIXME\n"); - glPushMatrix(); - { - glColor4fv(gui_wht); - - /* Translate to the widget center, and apply the pulse scale. */ - - glTranslatef((GLfloat) (m_widgets[id].x + m_widgets[id].w / 2), - (GLfloat) (m_widgets[id].y + m_widgets[id].h / 2), 0.f); - - glScalef(m_widgets[id].scale, - m_widgets[id].scale, - m_widgets[id].scale); - - /* Translate left by half the total width of the rendered value. */ - - if (MT > 0) - glTranslatef(-2.25f * dx_large, 0.0f, 0.0f); - else - glTranslatef(-1.75f * dx_large, 0.0f, 0.0f); - - /* Render the minutes counter. */ - - if (MT > 0) - { - //glBindTexture(GL_TEXTURE_2D, digit_text[i][MT]); - // glCallList(digit_list[i][MT]); - // glTranslatef(dx_large, 0.0f, 0.0f); - } - - //glBindTexture(GL_TEXTURE_2D, digit_text[i][mo]); - //glCallList(digit_list[i][mo]); - glTranslatef(dx_small, 0.0f, 0.0f); - - /* Render the colon. */ - - //glBindTexture(GL_TEXTURE_2D, digit_text[i][10]); - //glCallList(digit_list[i][10]); - glTranslatef(dx_small, 0.0f, 0.0f); - - /* Render the seconds counter. */ - - //glBindTexture(GL_TEXTURE_2D, digit_text[i][st]); - //glCallList(digit_list[i][st]); - glTranslatef(dx_large, 0.0f, 0.0f); - - //glBindTexture(GL_TEXTURE_2D, digit_text[i][so]); - //glCallList(digit_list[i][so]); - glTranslatef(dx_small, 0.0f, 0.0f); - - /* Render hundredths counter half size. */ - - glScalef(0.5f, 0.5f, 1.0f); - - //glBindTexture(GL_TEXTURE_2D, digit_text[i][ht]); - //glCallList(digit_list[i][ht]); - glTranslatef(dx_large, 0.0f, 0.0f); - - //glBindTexture(GL_TEXTURE_2D, digit_text[i][ho]); - //glCallList(digit_list[i][ho]); - } - glPopMatrix(); -} - -//----------------------------------------------------------------------------- -void WidgetSet::paint_label(int id) -{ - /* Draw the widget text box, textured using the glyph. */ - - font_gui->Print(m_widgets[id]._text, m_widgets[id].size, - Font::ALIGN_CENTER, m_widgets[id].x + m_widgets[id].w/2, - Font::ALIGN_BOTTOM, m_widgets[id].y + - (m_widgets[id].h-m_radius)/2, - 255, 255, 255, m_widgets[id].scale, m_widgets[id].scale); - -} - -//----------------------------------------------------------------------------- -void WidgetSet::paint_text(int id) -{ - switch (m_widgets[id].type & GUI_TYPE) - { - case GUI_SPACE: break; - case GUI_FILLER: break; - case GUI_HARRAY: paint_array(id); break; - case GUI_VARRAY: paint_array(id); break; - case GUI_HSTACK: paint_array(id); break; - case GUI_VSTACK: paint_array(id); break; - case GUI_IMAGE: paint_image(id); break; - case GUI_COUNT: paint_count(id); break; - case GUI_CLOCK: paint_clock(id); break; - default: paint_label(id); break; - } -} - -//----------------------------------------------------------------------------- -void WidgetSet::paint(int id) -{ - if (id) - { - glPushAttrib(GL_LIGHTING_BIT | - GL_COLOR_BUFFER_BIT | - GL_DEPTH_BUFFER_BIT); - config_push_ortho(); - - glEnable(GL_BLEND); - glEnable(GL_COLOR_MATERIAL); - glDisable(GL_LIGHTING); - glDisable(GL_DEPTH_TEST); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable(GL_CULL_FACE ) ; - - glPushAttrib(GL_TEXTURE_BIT); - { - glDisable(GL_TEXTURE_2D); - paint_rect(id, 0); - } - glPopAttrib(); - - // Makes the font white ... not sure how to get - if(m_widgets[id].color0) - { - glColor4fv(m_widgets[id].color0); - } - else - { -#ifdef WIN32 - // This appears to be a visual c++ bug - GLfloat dummy5[4]={ 1.f, 1.f, 1.f, .5f }; - glColor4fv(dummy5); - GLfloat dummy1[4]={ 1.f, 1.f, 1.f, 1.f }; - glColor4fv(dummy1); -#else - glColor4fv((GLfloat[4]){ 1.f, 1.f, 1.f, .5f } - ); - glColor4fv((GLfloat[4]){ 1.f, 1.f, 1.f, 1.f } - ); -#endif - - } - paint_text(id); - - config_pop_matrix(); - glPopAttrib(); - } -} - -//----------------------------------------------------------------------------- -void WidgetSet::dump(int id, int d) -{ - int jd, i; - - if (id) - { - const char *type = "?"; - - switch (m_widgets[id].type & GUI_TYPE) - { - case GUI_HARRAY: type = "harray"; break; - case GUI_VARRAY: type = "varray"; break; - case GUI_HSTACK: type = "hstack"; break; - case GUI_VSTACK: type = "vstack"; break; - case GUI_FILLER: type = "filler"; break; - case GUI_IMAGE: type = "image"; break; - case GUI_LABEL: type = "label"; break; - case GUI_COUNT: type = "count"; break; - case GUI_CLOCK: type = "clock"; break; - } - - for (i = 0; i < d; i++) - printf(" "); - - printf("%04d %s\n", id, type); - - for (jd = m_widgets[id].car; jd; jd = m_widgets[jd].cdr) - dump(jd, d + 1); - } -} - -//----------------------------------------------------------------------------- -void WidgetSet::pulse(int id, float k) -{ - if (id) - { - m_widgets[id].scale = k; - sound_manager->playSfx(SOUND_MOVE_MENU); - } -} - -//----------------------------------------------------------------------------- -void WidgetSet::timer(int id, float dt) -{ - int jd; - - if (id) - { - for (jd = m_widgets[id].car; jd; jd = m_widgets[jd].cdr) - timer(jd, dt); - - if (m_widgets[id].scale - 1.0f < dt) - m_widgets[id].scale = 1.0f; - else - m_widgets[id].scale -= dt; - } -} - -//----------------------------------------------------------------------------- -int WidgetSet::point(int id, int x, int y) -{ - static int x_cache = 0; - static int y_cache = 0; - - int jd; - - /* Reuse the last coordinates if (x,y) == (-1,-1) */ - - if (x < 0 && y < 0) - return point(id, x_cache, y_cache); - - x_cache = x; - y_cache = y; - - /* Short-circuit check the current active widget. */ - - jd = search(m_active, x, y); - - /* If not still active, search the hierarchy for a new active widget. */ - - if (jd == 0) - jd = search(id, x, y); - - /* If the active widget has changed, return the new active id. */ - - if (jd == 0 || jd == m_active) - return 0; - else - return m_active = jd; -} - -//----------------------------------------------------------------------------- -int WidgetSet::click(void) -{ - return m_active; -} - -//----------------------------------------------------------------------------- -int WidgetSet::get_token(int id) const -{ - return id ? m_widgets[id].token : 0; -} - -//----------------------------------------------------------------------------- -int WidgetSet::get_value(int id) const -{ - return id ? m_widgets[id].value : 0; -} - -//----------------------------------------------------------------------------- -void WidgetSet::toggle(int id) -{ - m_widgets[id].value = m_widgets[id].value ? 0 : 1; -} - -//----------------------------------------------------------------------------- -int WidgetSet::vert_test(int id, int jd) -{ - /* Determine whether widget id is in vertical contact with widget jd. */ - - if (id && (m_widgets[id].type&(GUI_STATE|GUI_SPACE)) && - jd && (m_widgets[jd].type&(GUI_STATE|GUI_SPACE)) ) - { - const int I0 = m_widgets[id].x; - const int I1 = m_widgets[id].x + m_widgets[id].w; - const int J0 = m_widgets[jd].x; - const int J1 = m_widgets[jd].x + m_widgets[jd].w; - - /* Is widget id's top edge is in contact with jd's bottom edge? */ - - if (m_widgets[id].y + m_widgets[id].h == m_widgets[jd].y) - { - /* Do widgets id and jd overlap horizontally? */ - - if (J0 <= I0 && I0 < J1) return 1; - if (J0 < I1 && I1 <= J1) return 1; - if (I0 <= J0 && J0 < I1) return 1; - if (I0 < J1 && J1 <= I1) return 1; - } - } - return 0; -} - -//----------------------------------------------------------------------------- -int WidgetSet::horz_test(int id, int jd) -{ - /* Determine whether widget id is in horizontal contact with widget jd. */ - - if (id && hot(id) && jd && hot(jd)) - { - const int I0 = m_widgets[id].y; - const int I1 = m_widgets[id].y + m_widgets[id].h; - const int J0 = m_widgets[jd].y; - const int J1 = m_widgets[jd].y + m_widgets[jd].h; - - /* Is widget id's right edge in contact with jd's left edge? */ - - if (m_widgets[id].x + m_widgets[id].w == m_widgets[jd].x) - { - /* Do m_widgets id and jd overlap vertically? */ - - if (J0 <= I0 && I0 < J1) return 1; - if (J0 < I1 && I1 <= J1) return 1; - if (I0 <= J0 && J0 < I1) return 1; - if (I0 < J1 && J1 <= I1) return 1; - } - } - return 0; -} - -//----------------------------------------------------------------------------- -int WidgetSet::stick_L(int id, int dd) -{ - int jd, kd; - - /* Find a widget to the left of widget dd. */ - - if (horz_test(id, dd)) - return id; - - for (jd = m_widgets[id].car; jd; jd = m_widgets[jd].cdr) - if ((kd = stick_L(jd, dd))) - return kd; - - return 0; -} - -//----------------------------------------------------------------------------- -int WidgetSet::stick_R(int id, int dd) -{ - int jd, kd; - - /* Find a widget to the right of widget dd. */ - - if (horz_test(dd, id)) - return id; - - for (jd = m_widgets[id].car; jd; jd = m_widgets[jd].cdr) - if ((kd = stick_R(jd, dd))) - return kd; - - return 0; -} - -//----------------------------------------------------------------------------- -int WidgetSet::stick_D(int id, int dd) -{ - int jd, kd; - - /* Find a widget below widget dd. */ - - if (vert_test(id, dd)) - return id; - - for (jd = m_widgets[id].car; jd; jd = m_widgets[jd].cdr) - if ((kd = stick_D(jd, dd))) - return kd; - - return 0; -} - -//----------------------------------------------------------------------------- -int WidgetSet::stick_U(int id, int dd) -{ - int jd, kd; - - /* Find a widget above widget dd. */ - - if (vert_test(dd, id)) - { - return id; - } - for (jd = m_widgets[id].car; jd; jd = m_widgets[jd].cdr) - { - if ((kd = stick_U(jd, dd))) - { - return kd; - } - } - return 0; -} - -//----------------------------------------------------------------------------- -int WidgetSet::stick(int id, int axis, int dir, int value) -{ - /* Flag the axes to prevent uncontrolled scrolling. */ - - static int x_not_pressed = 1; - static int y_not_pressed = 1; - - int jd = 0; - - /* Find a new active widget in the direction of joystick motion. */ - - if (axis == 0) - { - if(!value) x_not_pressed = 1; - else if(dir == 0 && x_not_pressed) - { - jd = stick_L(id, m_active); - x_not_pressed = 0; - } - else if (dir == 1 && x_not_pressed) - { - jd = stick_R(id, m_active); - x_not_pressed = 0; - } - } - else if(axis == 1) - { - if(!value) y_not_pressed = 1; - else if(dir == 0 && y_not_pressed) - { - { - jd = stick_U(id, m_active); - // Skip over GUI_SPACE - while(jd && !hot(jd)) jd = stick_U(id, jd); - y_not_pressed = 0; - } - } - else if (dir == 1 && y_not_pressed) - { - jd = stick_D(id, m_active); - // Skip over GUI_SPACE - while(jd && !hot(jd)) jd = stick_D(id, jd); - y_not_pressed = 0; - } - } - - /* If the active widget has changed, return the new active id. */ - - if (jd == 0 || jd == m_active) - return 0; - else - return m_active = jd; -} - -//----------------------------------------------------------------------------- -int WidgetSet::cursor(int id, int key) -{ - int jd = 0; - - switch (key) - { - case SDLK_LEFT: jd = stick_L(id, m_active); break; - case SDLK_RIGHT: jd = stick_R(id, m_active); break; - case SDLK_UP: jd = stick_U(id, m_active); - // Skip over GUI_SPACE - while( jd && !hot(jd)) jd = stick_U(id, jd); - break; - case SDLK_DOWN: jd = stick_D(id, m_active); - // Skip over GUI_SPACE - while (jd && !hot(jd)) jd = stick_D(id, jd); - break; - default: return 0; - } - - /* If the active widget has changed, return the new active id. */ - - if (jd == 0 || jd == m_active) - return 0; - else - return m_active = jd; -} - -//----------------------------------------------------------------------------- -void WidgetSet::set_active(int id) -{ - m_active = id; -} - -//----------------------------------------------------------------------------- -void WidgetSet::tgl_paused() -{ - if (m_paused) - { - sound_manager -> resumeMusic() ; - m_paused = false; - } - else - { - sound_manager -> pauseMusic() ; - m_paused = true; - } -} - -//----------------------------------------------------------------------------- -void WidgetSet::config_push_persp(float fov, float n, float f) -{ - GLdouble m[4][4]; - - const GLdouble R = fov / 2 * M_PI / 180; - const GLdouble S = sin(R); - const GLdouble C = cos(R) / S; - - const GLdouble A = (GLdouble)user_config->m_width/(GLdouble)user_config->m_height; - - glMatrixMode(GL_PROJECTION); - { - glPushMatrix(); - glLoadIdentity(); - - m[0][0] = C/A; - m[0][1] = 0.0; - m[0][2] = 0.0; - m[0][3] = 0.0; - m[1][0] = 0.0; - m[1][1] = C; - m[1][2] = 0.0; - m[1][3] = 0.0; - m[2][0] = 0.0; - m[2][1] = 0.0; - m[2][2] = -(f + n) / (f - n); - m[2][3] = -1.0; - m[3][0] = 0.0; - m[3][1] = 0.0; - m[3][2] = -2.0 * n * f / (f - n); - m[3][3] = 0.0; - - glMultMatrixd(&m[0][0]); - } - glMatrixMode(GL_MODELVIEW); -} - -//----------------------------------------------------------------------------- -void WidgetSet::config_push_ortho() -{ - const GLdouble W = (GLdouble) user_config->m_width; - const GLdouble H = (GLdouble) user_config->m_height; - - glMatrixMode(GL_PROJECTION); - { - glPushMatrix(); - glLoadIdentity(); - glOrtho(0.0, W, 0.0, H, -1.0, +1.0); - } - glMatrixMode(GL_MODELVIEW); -} - -//----------------------------------------------------------------------------- -void WidgetSet::config_pop_matrix() -{ - glMatrixMode(GL_PROJECTION); - { - glPopMatrix(); - } - glMatrixMode(GL_MODELVIEW); -} - diff --git a/src/widget_set.hpp b/src/widget_set.hpp deleted file mode 100644 index 9610a945e..000000000 --- a/src/widget_set.hpp +++ /dev/null @@ -1,339 +0,0 @@ -// $Id$ -// -// SuperTuxKart - a fun racing game with go-kart -// This code originally from Neverball copyright (C) 2003 Robert Kooima -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#ifndef HEADER_WIDGETSET_H -#define HEADER_WIDGETSET_H - -#ifdef __APPLE__ -#include -#else -#ifdef WIN32 -# include -#endif -#include -#endif -#include - -/*---------------------------------------------------------------------------*/ - -enum WidgetFontSize { GUI_SML = 18, GUI_MED = 24, GUI_LRG = 30}; - -enum WidgetArea //One of the uses of this, is to say which corners are rounded -{ - GUI_NONE = 0, - GUI_NW = 1, GUI_SW = 2, GUI_NE = 4, GUI_SE = 8, - GUI_LFT = (GUI_NW | GUI_SW), - GUI_RGT = (GUI_NE | GUI_SE), - GUI_TOP = (GUI_NW | GUI_NE), - GUI_BOT = (GUI_SW | GUI_SE), - GUI_ALL = (GUI_TOP | GUI_BOT) -}; - -enum WidgetValue { GUI_OFF = 0, GUI_ON = 1 }; //For the widget values, for - // on / off switch. - -#define SCREEN_CENTERED_TEXT -10000 - - -/*---------------------------------------------------------------------------*/ - -#define MAX_WIDGETS 256 - -#define GUI_TYPE 0xFFFE - -enum GuiType -{ - GUI_FREE = 0, //Unused widget - - GUI_STATE = 1, //Button that has a state assigned. - - GUI_HARRAY = 2, //Horizantal container for groups of other types, all with - //the same size. - - GUI_VARRAY = 4, //Vertical container for groups of other types, all with - //the same. - - GUI_HSTACK = 8, //Horizontal container for groups of other types, each one - //on top of the other, with individual sizes. - - GUI_VSTACK = 16, //Vertical container for groups of other types, each one - //on top the other, with individual sizes. - - GUI_FILLER = 32, //Empty space, cannot be traveled through - - GUI_IMAGE = 64, //Image widget using an OpenGL texture - - GUI_LABEL = 128, //Single line text - - GUI_COUNT = 256, - - GUI_CLOCK = 512, - GUI_SPACE = 1024,//Empty space, can be traveled through - GUI_PAUSE = 2048 -}; - -/*---------------------------------------------------------------------------*/ - -//previously in config.h: - -#define MAX_STR 256 - -/*---------------------------------------------------------------------------*/ - -//TODO:fix widget set colors, it seems only white works. -const GLfloat gui_wht[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; -const GLfloat gui_yel[4] = { 1.0f, 1.0f, 0.0f, 1.0f }; -const GLfloat gui_red[4] = { 1.0f, 0.0f, 0.0f, 1.0f }; -const GLfloat gui_grn[4] = { 0.0f, 1.0f, 0.0f, 1.0f }; -const GLfloat gui_blu[4] = { 0.0f, 0.0f, 1.0f, 1.0f }; -const GLfloat gui_blk[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; -const GLfloat gui_gry[4] = { 0.3f, 0.3f, 0.3f, 1.0f }; - -struct Widget -{ - Widget() : - type(0), token(0), value(0), size(0), rect(0), x(0), y(0), w(0), h(0), - yOffset(0), car(0), cdr(0), _text(""), count_text(""), text_width(0), - text_img(0), rect_obj(0), color0(NULL), color1(NULL), scale(0.0f) {} - - int type; - int token;//The token is a number supplied by the programmer to name - //recognize a widget. You could also store the id, but - //that wouldn't let you use a switch/enum combination. - int value;//On/Off switch using the WidgetValue. - int size; - int rect; //This uses the WidgetAreas, and determines which corners - //are rounded, GUI_ALL rounds all corners. - int x, y; - int w, h; - int yOffset; - int car; - int cdr; - - std::string _text; - std::string count_text; - int text_width; - GLuint text_img; - GLuint rect_obj; - - const GLfloat *color0; - const GLfloat *color1; - - GLfloat scale; -}; - -class WidgetSet -{ -public: - /* - * Initialization/deinitialization functions - */ - WidgetSet(); - ~WidgetSet(); - void reInit(); // necessary in case of fullscreen/window mode change on windows - - /* - * Get/set functions - */ - void set_label(int id, const std::string&); - void set_multi(int id, const char *); - void set_count(int id, int); - void set_clock(int id, int); - - const std::string& get_label(int id) { return m_widgets[id]._text; } - int get_token(int id) const; - int get_value(int id) const; - - - /* - * Creation functions, the first argument is the parent id of the new - * widget (0 if no parent) - */ - //arrays, these are used to setup the layout of your widgets - int harray(int parent); - int varray(int parent); - int hstack(int parent); - int vstack(int parent); - - //fills up space - int filler(int parent); - - //a widget that consists of a texture (which must be completely - //handled by the application) - int image(int parent, int, int, int, int rect=GUI_ALL); - - //a normal text menu entry, except that it is automatically immediately activated - int start(int parent, const std::string&, int, int, int value=GUI_OFF); - - //a normal text menu entry - int state(int parent, const std::string&, int, int, int value=GUI_OFF); - - //a text label (cannot be selected). c0 and c1 are two colours that the text is shaded with - int label(int parent, const std::string &text, int size=GUI_MED, int rect=GUI_ALL, - const float *c0=0, const float *c1=0); - - //Create a multi-line text box using a vertical array of labels. - //Parse the text for '\' characters and treat them as line-breaks. - //Preserve the rect specifation across the entire array. - int multi(int parent, const char *, int size=GUI_MED, int rect=GUI_ALL, - const float *c0=0, const float *c1=0); - - //widget is a single number - e.g. an fps counter or whatever - int count(int parent, int, int, int); - - //widget consists of a time in minutes and seconds - int clock(int parent, int, int, int); - - //just a blank space - int space(int parent); - - /*---------------------------------------------------------------------------*/ - - /* prints out debugging info */ - void dump(int id, int); - - /* Use this after you have first created your widgets to set their - * positioning xd and yd have possible values of 1(right/top), 0(center), - * -1(left/bottom). - */ - void layout(int id, int xd, int yd); - - int search(int id, int, int); - - /* - * Activate a widget, allowing it to behave as a normal state widget. - * This may be used to create image buttons, or cause an array of - * widgets to behave as a single state widget. - */ - int activate_widget(int id, int, int); - - /* you only need to call this for parents, children will automatically be deleted by their parents */ - int delete_widget(int id); - - /*---------------------------------------------------------------------------*/ - - /* call once a frame to update your widgets on the screen - You only need to call this for parents, children will automatically be painted by their parents */ - void paint(int id); - - /* call "gui_pulse(gui_point(id, x, y), 1.2f);" whenever the mouse moves to make widgets pulse when the mouse goes over them */ - void pulse(int id, float); - - /* call once a frame, passing on the value given to BaseGUI::update(int) - You only need to call this for parents, children will automatically be updated by their parents */ - void timer(int id, float); - - /* mouse movement */ - int point(int id, int x, int y); - - /* joystick movement */ - int stick(int id, int axis, int dir, int value); - - /* keyboard cursors */ - int cursor(int id, int key); - - /* mouse click */ - int click(); - - /* where id's value is being used as a bool, this toggles it */ - void toggle(int id); - - //force id to be the current active widget - void set_active(int id); - - /*---------------------------------------------------------------------------*/ - - void tgl_paused(); - bool get_paused() const { return m_paused; } - GLuint rect - ( - const int X, - const int Y, - const int WIDTH, - const int HEIGHT, - const int RECT, - const int RADIUS - ); - -private: - int hot(int id); - - GLuint list(int x, int y, int w, int h, const float *c0, const float *c1); - int add_widget(int parent, int type); - - int pause(int parent); - - /*---------------------------------------------------------------------------*/ - - void widget_up(int id); - void harray_up(int id); - void varray_up(int id); - void hstack_up(int id); - void vstack_up(int id); - void paused_up(int id); - void button_up(int id); - - void widget_dn(int id, int x, int y, int w, int h); - void harray_dn(int id, int x, int y, int w, int h); - void varray_dn(int id, int x, int y, int w, int h); - void hstack_dn(int id, int x, int y, int w, int h); - void vstack_dn(int id, int x, int y, int w, int h); - void filler_dn(int id, int x, int y, int w, int h); - void button_dn(int id, int x, int y, int w, int h); - - /*---------------------------------------------------------------------------*/ - - void paint_rect(int id, int st); - void paint_text(int id);; - void paint_array(int id); - void paint_image(int id); - void paint_count(int id); - void paint_clock(int id); - void paint_label(int id); - - /*---------------------------------------------------------------------------*/ - - int vert_test(int id, int jd); - int horz_test(int id, int jd); - - int stick_L(int id, int dd); - int stick_R(int id, int dd); - int stick_D(int id, int dd); - int stick_U(int id, int dd); - - /*---------------------------------------------------------------------------*/ - - void config_push_persp(float, float, float); - void config_push_ortho(); - void config_pop_matrix(); - - /*---------------------------------------------------------------------------*/ - - Widget m_widgets[MAX_WIDGETS]; - int m_active; - int m_radius; - - int m_pause_id; - bool m_paused; -}; - -extern WidgetSet *widgetSet; -#endif - -/* EOF */