// if console is open: send key there
process_console_key_event(event);
}
- else if (MenuManager::current())
+ else if (MenuManager::instance().current())
{
// if menu mode: send key there
process_menu_key_event(event);
arrange_left(),
active_item()
{
- MenuManager::all_menus.push_back(this);
-
hit_item = -1;
menuaction = MENU_ACTION_NONE;
delete_character = 0;
Menu::~Menu()
{
- MenuManager::all_menus.remove(this);
-
- for(std::vector<MenuItem*>::iterator i = items.begin();
- i != items.end(); ++i)
- {
- delete *i;
- }
-
- if (MenuManager::current_ == this)
- MenuManager::current_ = NULL;
-
- if (MenuManager::previous == this)
- MenuManager::previous = NULL;
}
void
}
/* Add an item to a menu */
-void
-Menu::additem(MenuItem* item)
+MenuItem*
+Menu::add_item(std::unique_ptr<MenuItem> new_item)
{
- items.push_back(item);
+ items.push_back(std::move(new_item));
+ MenuItem* item = items.back().get();
/* If a new menu is being built, the active item shouldn't be set to
* something that isn't selectable. Set the active_item to the first
if (active_item == -1
&& item->kind != MN_HL
&& item->kind != MN_LABEL
- && item->kind != MN_INACTIVE) {
+ && item->kind != MN_INACTIVE)
+ {
active_item = items.size() - 1;
}
+
+ return item;
}
MenuItem*
Menu::add_hl()
{
- MenuItem* item = new MenuItem(MN_HL);
- additem(item);
- return item;
+ std::unique_ptr<MenuItem> item(new MenuItem(MN_HL));
+ return add_item(std::move(item));
}
MenuItem*
Menu::add_label(const std::string& text)
{
- MenuItem* item = new MenuItem(MN_LABEL);
+ std::unique_ptr<MenuItem> item(new MenuItem(MN_LABEL));
item->text = text;
- additem(item);
- return item;
+ return add_item(std::move(item));
}
MenuItem*
Menu::add_controlfield(int id, const std::string& text,
const std::string& mapping)
{
- MenuItem* item = new MenuItem(MN_CONTROLFIELD, id);
+ std::unique_ptr<MenuItem> item(new MenuItem(MN_CONTROLFIELD, id));
item->change_text(text);
item->change_input(mapping);
- additem(item);
- return item;
+ return add_item(std::move(item));
}
MenuItem*
Menu::add_entry(int id, const std::string& text)
{
- MenuItem* item = new MenuItem(MN_ACTION, id);
+ std::unique_ptr<MenuItem> item(new MenuItem(MN_ACTION, id));
item->text = text;
- additem(item);
- return item;
+ return add_item(std::move(item));
}
MenuItem*
Menu::add_inactive(int id, const std::string& text)
{
- MenuItem* item = new MenuItem(MN_INACTIVE, id);
+ std::unique_ptr<MenuItem> item(new MenuItem(MN_INACTIVE, id));
item->text = text;
- additem(item);
- return item;
+ return add_item(std::move(item));
}
MenuItem*
Menu::add_toggle(int id, const std::string& text, bool toogled)
{
- MenuItem* item = new MenuItem(MN_TOGGLE, id);
+ std::unique_ptr<MenuItem> item(new MenuItem(MN_TOGGLE, id));
item->text = text;
item->toggled = toogled;
- additem(item);
- return item;
+ return add_item(std::move(item));
}
MenuItem*
Menu::add_string_select(int id, const std::string& text)
{
- MenuItem* item = new MenuItem(MN_STRINGSELECT, id);
+ std::unique_ptr<MenuItem> item(new MenuItem(MN_STRINGSELECT, id));
item->text = text;
- additem(item);
- return item;
+ return add_item(std::move(item));
}
MenuItem*
Menu::add_back(const std::string& text)
{
- MenuItem* item = new MenuItem(MN_BACK);
+ std::unique_ptr<MenuItem> item(new MenuItem(MN_BACK));
item->text = text;
- additem(item);
- return item;
+ return add_item(std::move(item));
}
MenuItem*
Menu::add_submenu(const std::string& text, Menu* submenu, int id)
{
- MenuItem* item = new MenuItem(MN_GOTO, id);
+ std::unique_ptr<MenuItem> item(new MenuItem(MN_GOTO, id));
item->text = text;
item->target_menu = submenu;
- additem(item);
- return item;
+ return add_item(std::move(item));
}
void
Menu::clear()
{
- for(std::vector<MenuItem*>::iterator i = items.begin();
- i != items.end(); ++i) {
- delete *i;
- }
items.clear();
active_item = -1;
}
effect_progress = 1.0f;
if (close) {
- MenuManager::current_ = 0;
+ MenuManager::instance().current(0);
close = false;
}
}
items[active_item]->selected--;
else
items[active_item]->selected = items[active_item]->list.size()-1;
-
- menu_action(items[active_item]);
+
+ menu_action(items[active_item].get());
}
break;
items[active_item]->selected++;
else
items[active_item]->selected = 0;
-
- menu_action(items[active_item]);
+
+ menu_action(items[active_item].get());
}
break;
switch (items[active_item]->kind) {
case MN_GOTO:
assert(items[active_item]->target_menu != 0);
- MenuManager::push_current(items[active_item]->target_menu);
+ MenuManager::instance().push_current(items[active_item]->target_menu);
break;
case MN_TOGGLE:
items[active_item]->toggled = !items[active_item]->toggled;
- menu_action(items[active_item]);
+ menu_action(items[active_item].get());
break;
case MN_CONTROLFIELD:
- menu_action(items[active_item]);
+ menu_action(items[active_item].get());
break;
case MN_ACTION:
- menu_action(items[active_item]);
+ menu_action(items[active_item].get());
break;
case MN_STRINGSELECT:
else
items[active_item]->selected = 0;
- menu_action(items[active_item]);
+ menu_action(items[active_item].get());
break;
case MN_TEXTFIELD:
break;
case MN_BACK:
- MenuManager::pop_current();
+ MenuManager::instance().pop_current();
break;
default:
break;
break;
case MENU_ACTION_BACK:
- MenuManager::pop_current();
+ MenuManager::instance().pop_current();
break;
case MENU_ACTION_NONE:
int
Menu::check()
{
- if (hit_item != -1)
+ if (hit_item != -1)
{
int id = items[hit_item]->id;
// Clear event when checked out.. (we would end up in a loop when we try to leave "fake" submenu like Addons or Contrib)
- hit_item = -1;
+ hit_item = -1;
return id;
}
else
w += 32;
if (items[i]->kind == MN_STRINGSELECT)
w += font->get_text_width(items[i]->list[items[i]->selected]) + 32;
-
+
if(w > menu_width)
menu_width = w;
{
if (close)
{
- menu_width = (MenuManager::current_->get_width() * (1.0f - effect_progress));
- menu_height = (MenuManager::current_->get_height() * (1.0f - effect_progress));
+ menu_width = (MenuManager::instance().current()->get_width() * (1.0f - effect_progress));
+ menu_height = (MenuManager::instance().current()->get_height() * (1.0f - effect_progress));
}
- else if (MenuManager::previous)
+ else if (MenuManager::instance().get_previous())
{
- menu_width = (menu_width * effect_progress) + (MenuManager::previous->get_width() * (1.0f - effect_progress));
- menu_height = (menu_height * effect_progress) + (MenuManager::previous->get_height() * (1.0f - effect_progress));
+ menu_width = (menu_width * effect_progress) + (MenuManager::instance().get_previous()->get_width() * (1.0f - effect_progress));
+ menu_height = (menu_height * effect_progress) + (MenuManager::instance().get_previous()->get_height() * (1.0f - effect_progress));
//std::cout << effect_progress << " " << this << " " << last_menus.back() << std::endl;
}
else
/* 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),
+ 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),
+ Color(0.6f, 0.7f, 0.8f, 0.5f),
16.0f,
LAYER_GUI-10);
{
int text_width = (int) Resources::normal_font->get_text_width(items[active_item]->help);
int text_height = (int) Resources::normal_font->get_text_height(items[active_item]->help);
-
- Rectf text_rect(pos.x - text_width/2 - 8,
+
+ Rectf text_rect(pos.x - text_width/2 - 8,
SCREEN_HEIGHT - 48 - text_height/2 - 4,
- pos.x + text_width/2 + 8,
+ pos.x + text_width/2 + 8,
SCREEN_HEIGHT - 48 + text_height/2 + 4);
-
+
context.draw_filled_rect(Rectf(text_rect.p1 - Vector(4,4),
text_rect.p2 + Vector(4,4)),
- Color(0.2f, 0.3f, 0.4f, 0.8f),
+ Color(0.2f, 0.3f, 0.4f, 0.8f),
16.0f,
LAYER_GUI-10);
-
+
context.draw_filled_rect(text_rect,
- Color(0.6f, 0.7f, 0.8f, 0.5f),
+ Color(0.6f, 0.7f, 0.8f, 0.5f),
16.0f,
LAYER_GUI-10);
MenuItem&
Menu::get_item_by_id(int id)
{
- for(std::vector<MenuItem*>::iterator i = items.begin();
- i != items.end(); ++i) {
- MenuItem& item = **i;
-
- if(item.id == id)
- return item;
+ for (const auto& item : items)
+ {
+ if (item->id == id)
+ {
+ return *item;
+ }
}
throw std::runtime_error("MenuItem not found");
const MenuItem&
Menu::get_item_by_id(int id) const
{
- for(std::vector<MenuItem*>::const_iterator i = items.begin();
- i != items.end(); ++i) {
- const MenuItem& item = **i;
-
- if(item.id == id)
- return item;
+ for (const auto& item : items)
+ {
+ if (item->id == id)
+ {
+ return *item;
+ }
}
throw std::runtime_error("MenuItem not found");
get_item_by_id(id).toggled = toggled;
}
-Menu*
-Menu::get_parent() const
-{
- if (MenuManager::last_menus.empty())
- return 0;
- else
- return MenuManager::last_menus.back();
-}
-
/* Check for menu event */
void
Menu::event(const SDL_Event& event)
Menu::set_active_item(int id)
{
for(size_t i = 0; i < items.size(); ++i) {
- MenuItem* item = items[i];
- if(item->id == id) {
+ if(items[i]->id == id) {
active_item = i;
break;
}
static Color inactive_color;
static Color label_color;
static Color field_color;
+
private:
/* Action done on the menu */
enum MenuAction {
bool is_toggled(int id) const;
void set_toggled(int id, bool toggled);
- Menu* get_parent() const;
-
protected:
- void additem(MenuItem* pmenu_item);
+ MenuItem* add_item(std::unique_ptr<MenuItem> menu_item);
float get_width() const;
float get_height() const;
public:
bool close;
- std::vector<MenuItem*> items;
+ std::vector<std::unique_ptr<MenuItem> > items;
public:
float effect_progress;
#include "gui/menu_manager.hpp"
+#include <assert.h>
+
#include "control/input_manager.hpp"
#include "gui/menu.hpp"
#include "supertux/globals.hpp"
#include "supertux/timer.hpp"
-std::vector<Menu*> MenuManager::last_menus;
-std::list<Menu*> MenuManager::all_menus;
-Menu* MenuManager::current_ = 0;
-Menu* MenuManager::previous = 0;
+MenuManager* MenuManager::s_instance = 0;
+
+MenuManager&
+MenuManager::instance()
+{
+ assert(s_instance);
+ return *s_instance;
+}
+
+MenuManager::MenuManager() :
+ m_last_menus(),
+ m_all_menus(),
+ m_previous(),
+ m_current()
+{
+ s_instance = this;
+}
+
+MenuManager::~MenuManager()
+{
+ s_instance = nullptr;
+}
void
-MenuManager::push_current(Menu* pmenu)
+MenuManager::push_current(Menu* menu)
{
- previous = current_;
+ m_previous = m_current;
- if (current_)
- last_menus.push_back(current_);
+ if (m_current)
+ {
+ m_last_menus.push_back(m_current);
+ }
- current_ = pmenu;
- current_->effect_start_time = real_time;
- current_->effect_progress = 0.0f;
+ m_current = menu;
+ m_current->effect_start_time = real_time;
+ m_current->effect_progress = 0.0f;
}
void
MenuManager::pop_current()
{
- previous = current_;
-
- if (last_menus.size() >= 1) {
- current_ = last_menus.back();
- current_->effect_start_time = real_time;
- current_->effect_progress = 0.0f;
- last_menus.pop_back();
- } else {
- set_current(NULL);
+ m_previous = m_current;
+
+ if (m_last_menus.size() >= 1)
+ {
+ m_current = m_last_menus.back();
+ m_current->effect_start_time = real_time;
+ m_current->effect_progress = 0.0f;
+ m_last_menus.pop_back();
+ }
+ else
+ {
+ set_current(nullptr);
}
}
void
MenuManager::set_current(Menu* menu)
{
- if (current_ && current_->close == true)
- return;
+ if (m_current && m_current->close == true)
+ {
+ // do nothing
+ }
+ else
+ {
+ m_previous = m_current;
- previous = 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;
+ }
- if (menu) {
- menu->effect_start_time = real_time;
- menu->effect_progress = 0.0f;
- current_ = menu;
+ // just to be sure...
+ g_input_manager->reset();
}
- else if (current_) {
- last_menus.clear(); //NULL new menu pointer => close all menus
- 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 (current_)
- current_->set_pos(SCREEN_WIDTH/2, SCREEN_HEIGHT/2);
+ if (m_current)
+ m_current->set_pos(SCREEN_WIDTH/2, SCREEN_HEIGHT/2);
- for(std::list<Menu*>::iterator i = all_menus.begin(); i != all_menus.end(); ++i)
+ for(auto i = m_all_menus.begin(); i != m_all_menus.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);
class MenuManager
{
+private:
+ static MenuManager* s_instance;
public:
- static std::vector<Menu*> last_menus;
- static Menu* previous;
- static Menu* current_;
+ static MenuManager& instance();
public:
- /** Pointers to all currently available menus, used to handle repositioning on window resize */
- static std::list<Menu*> all_menus;
+ std::vector<Menu*> m_last_menus;
+ std::vector<Menu*> m_all_menus;
+
+ Menu* m_previous;
+ Menu* m_current;
public:
+ MenuManager();
+ ~MenuManager();
+
/** Set the current menu, if pmenu is NULL, hide the current menu */
- static void set_current(Menu* pmenu);
+ void set_current(Menu* pmenu);
- static void push_current(Menu* pmenu);
- static void pop_current();
+ void push_current(Menu* pmenu);
+ void pop_current();
+
+ void recalc_pos();
+
+ Menu* get_previous()
+ {
+ return m_previous;
+ }
+
+ /** Return the current active menu or NULL if none is active */
+ Menu* current()
+ {
+ return m_current;
+ }
- static void recalc_pos();
/** Return the current active menu or NULL if none is active */
- static Menu* current()
+ void current(Menu* menu)
{
- return current_;
+ m_current = menu;
}
private:
if(!game_pause) {
speed_before_pause = g_screen_manager->get_speed();
g_screen_manager->set_speed(0);
- MenuManager::set_current(game_menu.get());
+ MenuManager::instance().set_current(game_menu.get());
game_menu->set_active_item(MNID_CONTINUE);
game_pause = true;
}
void
GameSession::process_menu()
{
- Menu* menu = MenuManager::current();
+ Menu* menu = MenuManager::instance().current();
if(menu) {
if(menu == game_menu.get()) {
switch (game_menu->check()) {
case MNID_CONTINUE:
- MenuManager::set_current(0);
+ MenuManager::instance().set_current(0);
toggle_pause();
break;
case MNID_ABORTLEVEL:
- MenuManager::set_current(0);
+ MenuManager::instance().set_current(0);
g_screen_manager->exit_screen();
currentsector->player->set_bonus(bonus_at_start);
PlayerStatus *currentStatus = get_player_status();
process_menu();
// Unpause the game if the menu has been closed
- if (game_pause && !MenuManager::current()) {
+ if (game_pause && !MenuManager::instance().current()) {
g_screen_manager->set_speed(speed_before_pause);
game_pause = false;
}
else
{
m_contrib_world_menu.reset(new ContribWorldMenu(*world));
- MenuManager::push_current(m_contrib_world_menu.get());
+ MenuManager::instance().push_current(m_contrib_world_menu.get());
}
}
}
dictionary_manager->set_language(language); // set currently detected language
g_config->locale = ""; // do auto detect every time on startup
g_config->save();
- MenuManager::pop_current();
+ MenuManager::instance().pop_current();
}
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::pop_current();
+ MenuManager::instance().pop_current();
}
else
{
g_config->locale = i->str();
dictionary_manager->set_language(*i);
g_config->save();
- MenuManager::pop_current();
+ MenuManager::instance().pop_current();
break;
}
}
case MNID_LEVELS_CONTRIB:
// Contrib Menu
m_contrib_menu.reset(new ContribMenu());
- MenuManager::push_current(m_contrib_menu.get());
+ MenuManager::instance().push_current(m_contrib_menu.get());
break;
case MNID_ADDONS:
// Add-ons Menu
m_addon_menu.reset(new AddonMenu());
- MenuManager::push_current(m_addon_menu.get());
+ MenuManager::instance().push_current(m_addon_menu.get());
break;
case MNID_CREDITS:
- MenuManager::set_current(NULL);
+ MenuManager::instance().set_current(NULL);
g_screen_manager->push_screen(new TextScroller("credits.txt"),
new FadeOut(0.5));
break;
{
g_config->aspect_size = Size(0, 0); // Magic values
Renderer::instance()->apply_config();
- MenuManager::recalc_pos();
+ MenuManager::instance().recalc_pos();
}
else if (sscanf(item->list[item->selected].c_str(), "%d:%d",
&g_config->aspect_size.width, &g_config->aspect_size.height) == 2)
{
Renderer::instance()->apply_config();
- MenuManager::recalc_pos();
+ MenuManager::instance().recalc_pos();
}
else
{
g_config->magnification /= 100.0f;
}
Renderer::instance()->apply_config();
- MenuManager::recalc_pos();
+ MenuManager::instance().recalc_pos();
break;
case MNID_FULLSCREEN_RESOLUTION:
if(g_config->use_fullscreen != is_toggled(MNID_FULLSCREEN)) {
g_config->use_fullscreen = !g_config->use_fullscreen;
Renderer::instance()->apply_config();
- MenuManager::recalc_pos();
+ MenuManager::instance().recalc_pos();
g_config->save();
}
break;
ProfileMenu::menu_action(MenuItem* item)
{
g_config->profile = item->id;
- MenuManager::set_current(0);
+ MenuManager::instance().set_current(0);
}
/*
ScreenManager::ScreenManager() :
waiting_threads(),
+ m_menu_manager(new MenuManager),
running(),
speed(1.0),
nextpop(false),
static int frame_count = 0;
current_screen->draw(context);
- if(MenuManager::current() != NULL)
- MenuManager::current()->draw(context);
+ if(MenuManager::instance().current() != NULL)
+ MenuManager::instance().current()->draw(context);
if(screen_fade.get() != NULL)
screen_fade->draw(context);
Console::instance->draw(context);
scripting::update_debugger();
scripting::TimeScheduler::instance->update(game_time);
current_screen->update(elapsed_time);
- if (MenuManager::current() != NULL)
- MenuManager::current()->update();
+ if (MenuManager::instance().current() != NULL)
+ MenuManager::instance().current()->update();
if(screen_fade.get() != NULL)
screen_fade->update(elapsed_time);
Console::instance->update(elapsed_time);
{
g_input_manager->process_event(event);
- if(MenuManager::current() != NULL)
- MenuManager::current()->event(event);
+ if(MenuManager::instance().current() != NULL)
+ MenuManager::instance().current()->event(event);
switch(event.type)
{
case SDL_WINDOWEVENT_RESIZED:
Renderer::instance()->resize(event.window.data1,
event.window.data2);
- MenuManager::recalc_pos();
+ MenuManager::instance().recalc_pos();
break;
}
break;
{
g_config->use_fullscreen = !g_config->use_fullscreen;
Renderer::instance()->apply_config();
- MenuManager::recalc_pos();
+ MenuManager::instance().recalc_pos();
}
else if (event.key.keysym.sym == SDLK_PRINTSCREEN ||
event.key.keysym.sym == SDLK_F12)
#include "scripting/thread_queue.hpp"
-class Screen;
class Console;
-class ScreenFade;
class DrawingContext;
+class MenuManager;
+class Screen;
+class ScreenFade;
/**
* Manages, updates and draws all Screens, Controllers, Menus and the Console.
void handle_screen_switch();
private:
+ std::unique_ptr<MenuManager> m_menu_manager;
bool running;
float speed;
bool nextpop;
sector->activate(sector->player->get_pos());
}
- MenuManager::set_current(main_menu.get());
+ MenuManager::instance().set_current(main_menu.get());
}
void
{
Sector* sector = titlesession->get_current_sector();
sector->deactivate();
- MenuManager::set_current(NULL);
+ MenuManager::instance().set_current(nullptr);
}
void
make_tux_jump();
- if (Menu* menu = MenuManager::current())
+ if (Menu* menu = MenuManager::instance().current())
{
menu->check_menu();
}
// reopen menu if user closed it (so that the app doesn't close when user
// accidently hit ESC)
- if(MenuManager::current() == 0 && g_screen_manager->has_no_pending_fadeout())
+ if(MenuManager::instance().current() == 0 && g_screen_manager->has_no_pending_fadeout())
{
- MenuManager::set_current(main_menu.get());
+ MenuManager::instance().set_current(main_menu.get());
}
}
void
TitleScreen::start_game(World* world)
{
- MenuManager::set_current(NULL);
+ MenuManager::instance().set_current(NULL);
std::string basename = world->get_basedir();
basename = basename.substr(0, basename.length()-1);
stream << "profile" << g_config->profile << "/" << worlddirname << ".stsg";
std::string slotfile = stream.str();
- try
+ try
{
world->set_savegame_filename(slotfile);
world->run();
- }
- catch(std::exception& e)
+ }
+ catch(std::exception& e)
{
log_fatal << "Couldn't start world: " << e.what() << std::endl;
}
WorldMap::on_escape_press()
{
// Show or hide the menu
- if(!MenuManager::current()) {
- MenuManager::set_current(worldmap_menu.get());
+ if(!MenuManager::instance().current()) {
+ MenuManager::instance().set_current(worldmap_menu.get());
tux->set_direction(D_NONE); // stop tux movement when menu is called
} else {
- MenuManager::set_current(NULL);
+ MenuManager::instance().set_current(NULL);
}
}
WorldMap::update(float delta)
{
if(!in_level) {
- Menu* menu = MenuManager::current();
+ Menu* menu = MenuManager::instance().current();
if(menu != NULL) {
if(menu == worldmap_menu.get()) {
switch (worldmap_menu->check())
{
case MNID_RETURNWORLDMAP: // Return to game
- MenuManager::set_current(0);
+ MenuManager::instance().set_current(0);
break;
case MNID_QUITWORLDMAP: // Quit Worldmap
g_screen_manager->exit_screen();
WorldMap::setup()
{
sound_manager->play_music(music);
- MenuManager::set_current(NULL);
+ MenuManager::instance().set_current(NULL);
current_ = this;
load_state();