delete_character(),
mn_input_char(),
menu_repeat_time(),
- close(false),
items(),
- effect_progress(),
- effect_start_time(),
arrange_left(),
active_item()
{
- MenuManager::instance().m_all_menus.push_back(this);
-
hit_item = -1;
menuaction = MENU_ACTION_NONE;
delete_character = 0;
pos.y = SCREEN_HEIGHT/2;
arrange_left = 0;
active_item = -1;
-
- effect_progress = 0.0f;
- effect_start_time = 0.0f;
}
Menu::~Menu()
{
- MenuManager::instance().m_all_menus.remove(this);
-
- if (MenuManager::instance().m_current == this)
- MenuManager::instance().m_current = nullptr;
-
- if (MenuManager::instance().m_previous == this)
- MenuManager::instance().m_previous = nullptr;
}
void
-Menu::set_pos(float x, float y, float rw, float rh)
+Menu::set_pos(float x, float y)
{
- pos.x = x + get_width() * rw;
- pos.y = y + get_height() * rh;
+ pos.x = x;
+ pos.y = y;
}
/* Add an item to a menu */
pos.y = SCREEN_HEIGHT/2 - scroll_offset * ((float(active_item) / (items.size()-1)) - 0.5f) * 2.0f;
}
- effect_progress = (real_time - effect_start_time) * 6.0f;
-
- if(effect_progress >= 1.0f) {
- effect_progress = 1.0f;
-
- if (close) {
- MenuManager::instance().m_current = 0;
- close = false;
- }
- }
- else if (effect_progress <= 0.0f) {
- effect_progress = 0.0f;
- }
-
Controller* controller = g_input_manager->get_controller();
/** check main input controller... */
if(controller->pressed(Controller::UP)) {
switch (items[active_item]->kind) {
case MN_GOTO:
assert(items[active_item]->target_menu != 0);
- MenuManager::instance().push_current(items[active_item]->target_menu);
+ MenuManager::instance().push_menu(items[active_item]->target_menu);
break;
case MN_TOGGLE:
break;
case MN_BACK:
- MenuManager::instance().pop_current();
+ MenuManager::instance().pop_menu();
break;
default:
break;
break;
case MENU_ACTION_BACK:
- MenuManager::instance().pop_current();
+ MenuManager::instance().pop_menu();
break;
case MENU_ACTION_NONE:
void
Menu::draw(DrawingContext& context)
{
- if(MouseCursor::current()) {
- MouseCursor::current()->draw(context);
- }
-
- float menu_width = get_width();
- float menu_height = get_height();
-
- if (effect_progress != 1.0f)
- {
- if (close)
- {
- menu_width *= 1.0f - effect_progress;
- menu_height *= 1.0f - effect_progress;
- }
- else if (MenuManager::instance().m_previous)
- {
- menu_width = (menu_width * effect_progress) + (MenuManager::instance().m_previous->get_width() * (1.0f - effect_progress));
- menu_height = (menu_height * effect_progress) + (MenuManager::instance().m_previous->get_height() * (1.0f - effect_progress));
- //std::cout << effect_progress << " " << this << " " << last_menus.back() << std::endl;
- }
- else
- {
- menu_width *= effect_progress;
- menu_height *= effect_progress;
- }
- }
-
- /* Draw a transparent background */
- context.draw_filled_rect(Rectf(Vector(pos.x - menu_width/2-4, pos.y - menu_height/2 - 10-4),
- Vector(pos.x + menu_width/2+4, pos.y - menu_height/2 + 10 + menu_height+4)),
- Color(0.2f, 0.3f, 0.4f, 0.8f),
- 20.0f,
- LAYER_GUI-10);
-
- context.draw_filled_rect(Rectf(Vector(pos.x - menu_width/2, pos.y - menu_height/2 - 10),
- Vector(pos.x + menu_width/2, pos.y - menu_height/2 + 10 + menu_height)),
- Color(0.6f, 0.7f, 0.8f, 0.5f),
- 16.0f,
- LAYER_GUI-10);
-
if (!items[active_item]->help.empty())
{
int text_width = (int) Resources::normal_font->get_text_width(items[active_item]->help);
ALIGN_CENTER, LAYER_GUI);
}
- if (effect_progress == 1.0f)
- for(unsigned int i = 0; i < items.size(); ++i)
- {
- draw_item(context, i);
- }
+ for(unsigned int i = 0; i < items.size(); ++i)
+ {
+ draw_item(context, i);
+ }
}
MenuItem&
void
Menu::event(const SDL_Event& event)
{
- if(effect_progress != 1.0f)
- return;
-
switch(event.type) {
case SDL_MOUSEBUTTONDOWN:
if(event.button.button == SDL_BUTTON_LEFT)
void set_active_item(int id);
void draw(DrawingContext& context);
- void set_pos(float x, float y, float rw = 0, float rh = 0);
+ Vector get_pos() const { return pos; }
+ void set_pos(float x, float y);
void event(const SDL_Event& event);
bool is_toggled(int id) const;
void set_toggled(int id, bool toggled);
+ float get_width() const;
+ float get_height() const;
+
protected:
/** Return the index of the menu item that was 'hit' (ie. the user
clicked on it) in the last event() call */
int check ();
MenuItem* add_item(std::unique_ptr<MenuItem> menu_item);
- float get_width() const;
- float get_height() const;
private:
void check_controlfield_change_event(const SDL_Event& event);
float menu_repeat_time;
public:
- bool close;
-
std::vector<std::unique_ptr<MenuItem> > items;
-public:
- float effect_progress;
- float effect_start_time;
-
private:
int arrange_left;
int active_item;
#include "control/input_manager.hpp"
#include "gui/menu.hpp"
+#include "gui/mousecursor.hpp"
#include "supertux/globals.hpp"
#include "supertux/menu/menu_storage.hpp"
#include "supertux/timer.hpp"
+#include "video/drawing_context.hpp"
MenuManager* MenuManager::s_instance = 0;
}
MenuManager::MenuManager() :
- m_last_menus(),
- m_all_menus(),
- m_previous(),
- m_current()
+ m_menu_stack()
{
s_instance = this;
}
void
MenuManager::draw(DrawingContext& context)
{
- if (m_current)
+ if (current())
{
- m_current->draw(context);
+ Vector pos = current()->get_pos();
+ float menu_width = current()->get_width();
+ float menu_height = current()->get_height();
+
+ // draw menu background rectangles
+ context.draw_filled_rect(Rectf(Vector(pos.x - menu_width/2-4, pos.y - menu_height/2 - 10-4),
+ Vector(pos.x + menu_width/2+4, pos.y - menu_height/2 + 10 + menu_height+4)),
+ Color(0.2f, 0.3f, 0.4f, 0.8f),
+ 20.0f,
+ LAYER_GUI-10);
+
+ context.draw_filled_rect(Rectf(Vector(pos.x - menu_width/2, pos.y - menu_height/2 - 10),
+ Vector(pos.x + menu_width/2, pos.y - menu_height/2 + 10 + menu_height)),
+ Color(0.6f, 0.7f, 0.8f, 0.5f),
+ 16.0f,
+ LAYER_GUI-10);
+
+ current()->draw(context);
+
+ if (MouseCursor::current())
+ {
+ MouseCursor::current()->draw(context);
+ }
+ }
+
+#ifdef GRUMBEL
+ if (effect_progress != 1.0f)
+ {
+ if (close)
+ {
+ menu_width *= 1.0f - effect_progress;
+ menu_height *= 1.0f - effect_progress;
+ }
+ else if (MenuManager::instance().m_previous)
+ {
+ menu_width = (menu_width * effect_progress) + (MenuManager::instance().m_previous->get_width() * (1.0f - effect_progress));
+ menu_height = (menu_height * effect_progress) + (MenuManager::instance().m_previous->get_height() * (1.0f - effect_progress));
+ //std::cout << effect_progress << " " << this << " " << last_menus.back() << std::endl;
+ }
+ else
+ {
+ menu_width *= effect_progress;
+ menu_height *= effect_progress;
+ }
}
+
+ //update
+ effect_progress = (real_time - effect_start_time) * 6.0f;
+
+ if(effect_progress >= 1.0f) {
+ effect_progress = 1.0f;
+
+ if (close) {
+ MenuManager::instance().m_current = 0;
+ close = false;
+ }
+ }
+ else if (effect_progress <= 0.0f) {
+ effect_progress = 0.0f;
+ }
+
+ // only pass events in non-anim states
+ if(effect_progress != 1.0f)
+ return;
+
+#endif
}
bool
MenuManager::check_menu()
{
- if (m_current)
+ if (current())
{
- m_current->check_menu();
+ current()->check_menu();
return true;
}
else
}
void
-MenuManager::push_current(int id)
+MenuManager::push_menu(int id)
{
- Menu* menu = MenuStorage::instance().create(static_cast<MenuStorage::MenuId>(id));
- push_current_(menu);
+ push_menu(MenuStorage::instance().create(static_cast<MenuStorage::MenuId>(id)));
}
void
-MenuManager::push_current_(Menu* menu)
+MenuManager::push_menu(std::unique_ptr<Menu> menu)
{
- m_previous = m_current;
+ m_menu_stack.push_back(std::move(menu));
- if (m_current)
- {
- m_last_menus.push_back(m_current);
- }
-
- m_current = menu;
- m_current->effect_start_time = real_time;
- m_current->effect_progress = 0.0f;
+ //current()->effect_start_time = real_time;
+ //current()->effect_progress = 0.0f;
}
void
-MenuManager::pop_current()
+MenuManager::pop_menu()
{
- m_previous = m_current;
-
- if (m_last_menus.size() >= 1)
+ if (!m_menu_stack.empty())
{
- m_current = m_last_menus.back();
- m_current->effect_start_time = real_time;
- m_current->effect_progress = 0.0f;
- m_last_menus.pop_back();
+ m_menu_stack.pop_back();
+ //current()->effect_start_time = real_time;
+ //current()->effect_progress = 0.0f;
}
else
{
- set_current(MenuStorage::NO_MENU);
+ set_menu(MenuStorage::NO_MENU);
}
}
void
-MenuManager::set_current(int id)
+MenuManager::clear_menu_stack()
+{
+ set_menu(MenuStorage::NO_MENU);
+}
+
+void
+MenuManager::set_menu(int id)
{
- Menu* menu = MenuStorage::instance().create(static_cast<MenuStorage::MenuId>(id));
- set_current_ptr(menu);
+ set_menu(MenuStorage::instance().create(static_cast<MenuStorage::MenuId>(id)));
}
void
-MenuManager::set_current_ptr(Menu* menu)
+MenuManager::set_menu(std::unique_ptr<Menu> menu)
{
- if (m_current && m_current->close == true)
+ if (menu)
{
- // do nothing
+ m_menu_stack.push_back(std::move(menu));
+ //current()->effect_start_time = real_time;
+ //current()->effect_progress = 0.0f;
}
else
{
- m_previous = m_current;
-
- if (menu)
- {
- menu->effect_start_time = real_time;
- menu->effect_progress = 0.0f;
- m_current = menu;
- }
- else if (m_current)
- {
- m_last_menus.clear(); //NULL new menu pointer => close all menus
- m_current->effect_start_time = real_time;
- m_current->effect_progress = 0.0f;
- m_current->close = true;
- }
-
- // just to be sure...
- g_input_manager->reset();
+ m_menu_stack.clear();
+ //current()->effect_start_time = real_time;
+ //current()->effect_progress = 0.0f;
+ //current()->close = true;
}
+
+ // just to be sure...
+ g_input_manager->reset();
}
void
MenuManager::recalc_pos()
{
- if (m_current)
- m_current->set_pos(SCREEN_WIDTH/2, SCREEN_HEIGHT/2);
-
- for(auto i = m_all_menus.begin(); i != m_all_menus.end(); ++i)
+ for(auto i = m_menu_stack.begin(); i != m_menu_stack.end(); ++i)
{
// FIXME: This is of course not quite right, since it ignores any previous set_pos() calls
(*i)->set_pos(SCREEN_WIDTH/2, SCREEN_HEIGHT/2);
#include <vector>
#include <list>
+#include <memory>
class Menu;
class DrawingContext;
static MenuManager& instance();
public:
- std::vector<Menu*> m_last_menus;
- std::list<Menu*> m_all_menus;
+ std::vector<std::unique_ptr<Menu> > m_menu_stack;
- /** Used only for transition effects */
- Menu* m_previous;
-
- Menu* m_current;
+ bool close;
+ float effect_progress;
+ float effect_start_time;
friend class Menu;
void draw(DrawingContext& context);
bool check_menu();
- /** Set the current menu, if pmenu is NULL, hide the current menu */
- void set_current_ptr(Menu* menu);
- void set_current(int id);
+ void set_menu(int id);
+ void clear_menu_stack();
- void push_current(int id);
- void push_current_(Menu* menu);
- void pop_current();
+ void push_menu(std::unique_ptr<Menu> menu);
+ void push_menu(int id);
+ void pop_menu();
void recalc_pos();
/** Return the current active menu or NULL if none is active */
Menu* current() const
{
- return m_current;
+ if (m_menu_stack.empty())
+ {
+ return nullptr;
+ }
+ else
+ {
+ return m_menu_stack.back().get();
+ }
}
bool is_active() const
{
- return m_current != nullptr;
+ return !m_menu_stack.empty();
}
private:
+ /** Set the current menu, if pmenu is NULL, hide the current menu */
+ void set_menu(std::unique_ptr<Menu> menu);
+
+private:
MenuManager(const MenuManager&);
MenuManager& operator=(const MenuManager&);
};
if(!game_pause) {
speed_before_pause = g_screen_manager->get_speed();
g_screen_manager->set_speed(0);
- MenuManager::instance().set_current(MenuStorage::GAME_MENU);
+ MenuManager::instance().set_menu(MenuStorage::GAME_MENU);
game_pause = true;
}
void
GameSession::abort_level()
{
- MenuManager::instance().set_current(MenuStorage::NO_MENU);
+ MenuManager::instance().clear_menu_stack();
g_screen_manager->exit_screen();
currentsector->player->set_bonus(bonus_at_start);
PlayerStatus *currentStatus = get_player_status();
#include <physfs.h>
#include "gui/menu_manager.hpp"
+#include "supertux/menu/contrib_world_menu.hpp"
#include "supertux/menu/menu_storage.hpp"
#include "supertux/title_screen.hpp"
#include "supertux/world.hpp"
add_hl();
add_back(_("Back"));
+
+ std::cout << "ContribMenu" << std::endl;
}
ContribMenu::~ContribMenu()
{
+ std::cout << "~ContribMenu" << std::endl;
}
void
}
else
{
-#ifdef GRUMBEL
- m_contrib_world_menu.reset(new ContribWorldMenu(*world));
- MenuManager::instance().push_current(MenuStorage::CONTRIB_WORLD_MENU);
-#endif
+ MenuManager::instance().push_menu(std::unique_ptr<Menu>(new ContribWorldMenu(*world)));
}
}
}
switch (check())
{
case MNID_CONTINUE:
- MenuManager::instance().set_current(0);
+ MenuManager::instance().clear_menu_stack();
GameSession::current()->toggle_pause();
break;
dictionary_manager->set_language(language); // set currently detected language
g_config->locale = ""; // do auto detect every time on startup
g_config->save();
- MenuManager::instance().pop_current();
+ MenuManager::instance().pop_menu();
}
else if (item->id == MNID_LANGUAGE_ENGLISH) // english
{
g_config->locale = "en";
dictionary_manager->set_language(tinygettext::Language::from_name(g_config->locale));
g_config->save();
- MenuManager::instance().pop_current();
+ MenuManager::instance().pop_menu();
}
else
{
g_config->locale = i->str();
dictionary_manager->set_language(*i);
g_config->save();
- MenuManager::instance().pop_current();
+ MenuManager::instance().pop_menu();
break;
}
}
#include "util/gettext.hpp"
MainMenu::MainMenu() :
- m_addon_menu(),
- m_contrib_menu(),
m_main_world()
{
set_pos(SCREEN_WIDTH/2, SCREEN_HEIGHT/2 + 35);
switch (check())
{
case MNID_STARTGAME:
- if (m_main_world.get() == NULL)
{
- m_main_world.reset(new World());
- m_main_world->load("levels/world1/info");
+ std::unique_ptr<World> world(new World);
+ world->load("levels/world1/info");
+ TitleScreen::start_game(std::move(world));
}
- TitleScreen::start_game(m_main_world.get());
break;
case MNID_LEVELS_CONTRIB:
// Contrib Menu
- m_contrib_menu.reset(new ContribMenu());
- MenuManager::instance().push_current(MenuStorage::CONTRIB_MENU);
+ MenuManager::instance().push_menu(MenuStorage::CONTRIB_MENU);
break;
case MNID_ADDONS:
// Add-ons Menu
- m_addon_menu.reset(new AddonMenu());
- MenuManager::instance().push_current(MenuStorage::ADDON_MENU);
+ MenuManager::instance().push_menu(MenuStorage::ADDON_MENU);
break;
case MNID_CREDITS:
- MenuManager::instance().set_current(MenuStorage::NO_MENU);
+ MenuManager::instance().clear_menu_stack();
g_screen_manager->push_screen(std::unique_ptr<Screen>(new TextScroller("credits.txt")),
std::unique_ptr<ScreenFade>(new FadeOut(0.5)));
break;
class MainMenu : public Menu
{
-private:
- std::unique_ptr<AddonMenu> m_addon_menu;
- std::unique_ptr<ContribMenu> m_contrib_menu;
- std::unique_ptr<World> m_main_world;
-
public:
MainMenu();
s_instance = nullptr;
}
-Menu*
+std::unique_ptr<Menu>
MenuStorage::create(MenuId menu_id)
{
switch(menu_id)
{
case MAIN_MENU:
- return new MainMenu;
+ return std::unique_ptr<Menu>(new MainMenu);
case LANGUAGE_MENU:
- return new LanguageMenu;
+ return std::unique_ptr<Menu>(new LanguageMenu);
case OPTIONS_MENU:
- return new OptionsMenu;
+ return std::unique_ptr<Menu>(new OptionsMenu);
case PROFILE_MENU:
- return new ProfileMenu;
+ return std::unique_ptr<Menu>(new ProfileMenu);
case KEYBOARD_MENU:
- return new KeyboardMenu(g_input_manager);
+ return std::unique_ptr<Menu>(new KeyboardMenu(g_input_manager));
case JOYSTICK_MENU:
- return new JoystickMenu(g_input_manager);
+ return std::unique_ptr<Menu>(new JoystickMenu(g_input_manager));
case WORLDMAP_MENU:
- return new WorldmapMenu;
+ return std::unique_ptr<Menu>(new WorldmapMenu);
case GAME_MENU:
- return new GameMenu;
+ return std::unique_ptr<Menu>(new GameMenu);
case CONTRIB_MENU:
- return new ContribMenu;
+ return std::unique_ptr<Menu>(new ContribMenu);
case CONTRIB_WORLD_MENU:
return 0; //return new ContribWorldMenu();
case ADDON_MENU:
- return new AddonMenu;
+ return std::unique_ptr<Menu>(new AddonMenu);
+
+ case NO_MENU:
+ return std::unique_ptr<Menu>();
default:
assert(!"unknown MenuId provided");
MenuStorage();
~MenuStorage();
- Menu* create(MenuId menu_id);
+ std::unique_ptr<Menu> create(MenuId menu_id);
// FIXME
JoystickMenu* get_joystick_options_menu();
ProfileMenu::menu_action(MenuItem* item)
{
g_config->profile = item->id;
- MenuManager::instance().set_current(0);
+ MenuManager::instance().clear_menu_stack();
}
/*
{
switch (check())
{
- case MNID_RETURNWORLDMAP: // Return to game
- MenuManager::instance().set_current(0);
+ case MNID_RETURNWORLDMAP:
+ MenuManager::instance().clear_menu_stack();
break;
- case MNID_QUITWORLDMAP: // Quit Worldmap
+ case MNID_QUITWORLDMAP:
g_screen_manager->exit_screen();
break;
}
sector->activate(sector->player->get_pos());
}
- MenuManager::instance().set_current(MenuStorage::MAIN_MENU);
+ MenuManager::instance().set_menu(MenuStorage::MAIN_MENU);
}
void
{
Sector* sector = titlesession->get_current_sector();
sector->deactivate();
- MenuManager::instance().set_current(MenuStorage::NO_MENU);
+ MenuManager::instance().clear_menu_stack();
}
void
// accidently hit ESC)
if(!MenuManager::instance().is_active() && g_screen_manager->has_no_pending_fadeout())
{
- MenuManager::instance().set_current(MenuStorage::MAIN_MENU);
+ MenuManager::instance().set_menu(MenuStorage::MAIN_MENU);
}
}
void
-TitleScreen::start_game(World* world)
+TitleScreen::start_game(std::unique_ptr<World> world)
{
- MenuManager::instance().set_current(MenuStorage::NO_MENU);
+ MenuManager::instance().clear_menu_stack();
std::string basename = world->get_basedir();
basename = basename.substr(0, basename.length()-1);
virtual void update(float elapsed_time);
public:
- static void start_game(World* world);
+ static void start_game(std::unique_ptr<World> world);
private:
void make_tux_jump();
{
// Show or hide the menu
if(!MenuManager::instance().is_active()) {
- MenuManager::instance().set_current(MenuStorage::WORLDMAP_MENU);
+ MenuManager::instance().set_menu(MenuStorage::WORLDMAP_MENU);
tux->set_direction(D_NONE); // stop tux movement when menu is called
} else {
- MenuManager::instance().set_current(MenuStorage::NO_MENU);
+ MenuManager::instance().clear_menu_stack();
}
}
WorldMap::setup()
{
sound_manager->play_music(music);
- MenuManager::instance().set_current(MenuStorage::NO_MENU);
+ MenuManager::instance().clear_menu_stack();
current_ = this;
load_state();