"pause-menu",
"menu-select",
"menu-back",
+ "cheat-menu",
"console",
"peek-left",
"peek-right",
MENU_SELECT,
MENU_BACK,
+ CHEAT_MENU,
CONSOLE,
PEEK_LEFT,
break;
case SDL_CONTROLLER_BUTTON_BACK:
+ set_control(Controller::CONSOLE, ev.state);
break;
case SDL_CONTROLLER_BUTTON_GUIDE:
- set_control(Controller::CONSOLE, ev.state);
+ set_control(Controller::CHEAT_MENU, ev.state);
break;
case SDL_CONTROLLER_BUTTON_START:
keymap[SDLK_PAGEDOWN] = Controller::PEEK_RIGHT;
keymap[SDLK_HOME] = Controller::PEEK_UP;
keymap[SDLK_END] = Controller::PEEK_DOWN;
+ keymap[SDLK_TAB] = Controller::CHEAT_MENU;
}
KeyboardManager::~KeyboardManager()
static const float MENU_REPEAT_RATE = 0.1f;
Menu::Menu() :
- hit_item(),
pos(),
- menuaction(),
delete_character(),
mn_input_char(),
menu_repeat_time(),
arrange_left(),
active_item()
{
- hit_item = -1;
- menuaction = MENU_ACTION_NONE;
delete_character = 0;
mn_input_char = '\0';
active_item = -1;
}
-/* Process actions done on the menu */
void
Menu::process_input()
{
pos.y = SCREEN_HEIGHT/2 - scroll_offset * ((float(active_item) / (items.size()-1)) - 0.5f) * 2.0f;
}
+ MenuAction menuaction = MENU_ACTION_NONE;
Controller* controller = g_input_manager->get_controller();
/** check main input controller... */
if(controller->pressed(Controller::UP)) {
menuaction = MENU_ACTION_BACK;
}
- hit_item = -1;
if(items.size() == 0)
return;
+ // The menu_action() call can pop() the menu from the stack and thus
+ // delete it, so it's important that no further member variables are
+ // accessed after this call
+ process_action(menuaction);
+}
+
+void
+Menu::process_action(MenuAction menuaction)
+{
int last_active_item = active_item;
switch(menuaction) {
case MENU_ACTION_UP:
break;
case MENU_ACTION_HIT: {
- hit_item = active_item;
switch (items[active_item]->kind) {
case MN_GOTO:
assert(items[active_item]->target_menu != 0);
case MENU_ACTION_NONE:
break;
}
- menuaction = MENU_ACTION_NONE;
-
- assert(active_item < int(items.size()));
-}
-
-int
-Menu::check()
-{
- 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;
- return id;
- }
- else
- return -1;
}
void
-Menu::menu_action(MenuItem* )
-{}
-
-void
Menu::draw_item(DrawingContext& context, int index)
{
float menu_height = get_height();
get_item_by_id(id).toggled = toggled;
}
-/* Check for menu event */
void
Menu::event(const SDL_Event& event)
{
y > pos.y - get_height()/2 &&
y < pos.y + get_height()/2)
{
- menuaction = MENU_ACTION_HIT;
+ process_action(MENU_ACTION_HIT);
}
}
break;
class DrawingContext;
class MenuItem;
-bool confirm_dialog(Surface* background, std::string text);
-
class Menu
{
static Color default_color;
const std::string& mapping = "");
MenuItem* add_string_select(int id, const std::string& text);
- virtual void menu_action(MenuItem* item);
+ virtual void menu_action(MenuItem* item) = 0;
void process_input();
/** Remove all entries from the menu */
void clear();
- virtual void check_menu() =0;
-
MenuItem& get_item(int index)
{
return *(items[index]);
virtual void on_window_resize();
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);
private:
+ void process_action(MenuAction menuaction);
void check_controlfield_change_event(const SDL_Event& event);
void draw_item(DrawingContext& context, int index);
private:
- /** Number of the item that got 'hit' (ie. pressed) in the last
- event()/update() call, -1 if none */
- int hit_item;
-
// position of the menu (ie. center of the menu, not top/left)
Vector pos;
- /** input event for the menu (up, down, left, right, etc.) */
- MenuAction menuaction;
-
/* input implementation variables */
int delete_character;
char mn_input_char;
}
}
-bool
-MenuManager::check_menu()
-{
- if (current())
- {
- current()->check_menu();
- return true;
- }
- else
- {
- return false;
- }
-}
-
void
MenuManager::push_menu(int id)
{
{
transition(m_menu_stack.empty() ? nullptr : m_menu_stack.back().get(),
menu.get());
+ m_menu_stack.clear();
m_menu_stack.push_back(std::move(menu));
}
else
void refresh();
void draw(DrawingContext& context);
- bool check_menu();
void set_menu(int id);
void set_menu(std::unique_ptr<Menu> menu);
GameSession::toggle_pause()
{
// pause
- if(!game_pause) {
+ if (!game_pause && !MenuManager::instance().is_active())
+ {
speed_before_pause = g_screen_manager->get_speed();
g_screen_manager->set_speed(0);
MenuManager::instance().set_menu(MenuStorage::GAME_MENU);
{
// handle controller
if(g_input_manager->get_controller()->pressed(Controller::PAUSE_MENU))
+ {
on_escape_press();
+ }
+
+ if(g_input_manager->get_controller()->pressed(Controller::CHEAT_MENU))
+ {
+ if (!MenuManager::instance().is_active())
+ {
+ game_pause = true;
+ MenuManager::instance().set_menu(MenuStorage::CHEAT_MENU);
+ }
+ }
process_events();
- MenuManager::instance().check_menu();
// Unpause the game if the menu has been closed
if (game_pause && !MenuManager::instance().is_active()) {
#include "addon/addon.hpp"
#include "addon/addon_manager.hpp"
+#include "gui/menu.hpp"
+#include "gui/menu_item.hpp"
#include "util/gettext.hpp"
namespace {
}
void
-AddonMenu::check_menu()
+AddonMenu::menu_action(MenuItem* item)
{
- int index = check();
+ int index = item->id;
if (index == -1)
{
AddonMenu();
void refresh();
- void check_menu();
+ void menu_action(MenuItem* item) override;
private:
AddonMenu(const AddonMenu&);
--- /dev/null
+// SuperTux
+// Copyright (C) 2014 Ingo Ruhnke <grumbel@gmail.com>
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+
+#include "supertux/menu/cheat_menu.hpp"
+
+#include "gui/menu_item.hpp"
+#include "gui/menu_manager.hpp"
+#include "object/player.hpp"
+#include "supertux/game_session.hpp"
+#include "supertux/player_status.hpp"
+#include "supertux/sector.hpp"
+#include "util/gettext.hpp"
+
+CheatMenu::CheatMenu()
+{
+ add_label(_("Cheats"));
+ add_hl();
+ add_entry(MNID_GROW, _("Bonus: Grow"));
+ add_entry(MNID_FIRE, _("Bonus: Fire"));
+ add_entry(MNID_ICE, _("Bonus: Ice"));
+ add_entry(MNID_STAR, _("Bonus: Star"));
+ add_entry(MNID_SHRINK, _("Shrink Tux"));
+ add_entry(MNID_KILL, _("Kill Tux"));
+ add_entry(MNID_FINISH, _("Finish Level"));
+ add_hl();
+ add_back(_("Back"));
+}
+
+void
+CheatMenu::menu_action(MenuItem* item)
+{
+ if (Sector::current())
+ {
+ std::vector<Player*> players = Sector::current()->get_players();
+ Player* player = players.empty() ? nullptr : players[0];
+
+ switch(item->id)
+ {
+ case MNID_GROW:
+ if (player)
+ {
+ player->set_bonus(GROWUP_BONUS);
+ }
+ break;
+
+ case MNID_FIRE:
+ if (player)
+ {
+ player->set_bonus(FIRE_BONUS);
+ }
+ break;
+
+ case MNID_ICE:
+ if (player)
+ {
+ player->set_bonus(ICE_BONUS);
+ }
+ break;
+
+ case MNID_STAR:
+ if (player)
+ {
+ player->make_invincible();
+ }
+ break;
+
+ case MNID_SHRINK:
+ if (player)
+ {
+ player->kill(false);
+ }
+ break;
+
+ case MNID_KILL:
+ if (player)
+ {
+ player->kill(true);
+ }
+ break;
+
+ case MNID_FINISH:
+ if (GameSession::current())
+ {
+ GameSession::current()->finish(true);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ MenuManager::instance().clear_menu_stack();
+}
+
+/* EOF */
--- /dev/null
+// SuperTux
+// Copyright (C) 2014 Ingo Ruhnke <grumbel@gmail.com>
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+
+#ifndef HEADER_SUPERTUX_SUPERTUX_MENU_CHEAT_MENU_HPP
+#define HEADER_SUPERTUX_SUPERTUX_MENU_CHEAT_MENU_HPP
+
+#include "gui/menu.hpp"
+
+class CheatMenu : public Menu
+{
+private:
+ enum MenuIDs {
+ MNID_GROW,
+ MNID_FIRE,
+ MNID_ICE,
+ MNID_STAR,
+ MNID_SHRINK,
+ MNID_KILL,
+ MNID_FINISH
+ };
+
+public:
+ CheatMenu();
+
+ void menu_action(MenuItem* item) override;
+
+private:
+ CheatMenu(const CheatMenu&) = delete;
+ CheatMenu& operator=(const CheatMenu&) = delete;
+};
+
+#endif
+
+/* EOF */
}
void
-ContribLevelsetMenu::check_menu()
+ContribLevelsetMenu::menu_action(MenuItem* item)
{
- int index = check();
- if (index != -1)
+ if (item->kind == MN_ACTION)
{
- if (get_item_by_id(index).kind == MN_ACTION)
- {
- sound_manager->stop_music();
+ sound_manager->stop_music();
- // reload the World so that we have something that we can safely
- // std::move() around without wreaking the ContribMenu
- std::unique_ptr<World> world = World::load(m_world->get_basedir());
- GameManager::current()->start_level(std::move(world), m_levelset->get_level_filename(index));
- }
+ // reload the World so that we have something that we can safely
+ // std::move() around without wreaking the ContribMenu
+ std::unique_ptr<World> world = World::load(m_world->get_basedir());
+ GameManager::current()->start_level(std::move(world), m_levelset->get_level_filename(item->id));
}
}
public:
ContribLevelsetMenu(std::unique_ptr<World> current_world);
- void check_menu();
+ void menu_action(MenuItem* item) override;
private:
ContribLevelsetMenu(const ContribLevelsetMenu&);
#include <physfs.h>
#include <sstream>
+#include "gui/menu_item.hpp"
#include "gui/menu_manager.hpp"
#include "supertux/game_manager.hpp"
#include "supertux/gameconfig.hpp"
}
void
-ContribMenu::check_menu()
+ContribMenu::menu_action(MenuItem* item)
{
- int index = check();
+ int index = item->id;
if (index != -1)
{
// reload the World so that we have something that we can safely
ContribMenu();
~ContribMenu();
- void check_menu();
+ void menu_action(MenuItem* item) override;
private:
ContribMenu(const ContribMenu&);
#include "supertux/menu/game_menu.hpp"
+#include "gui/menu.hpp"
+#include "gui/menu_item.hpp"
#include "gui/menu_manager.hpp"
#include "supertux/game_session.hpp"
-#include "supertux/screen_manager.hpp"
#include "supertux/level.hpp"
#include "supertux/menu/menu_storage.hpp"
#include "supertux/menu/options_menu.hpp"
+#include "supertux/screen_manager.hpp"
#include "util/gettext.hpp"
GameMenu::GameMenu()
}
void
-GameMenu::check_menu()
+GameMenu::menu_action(MenuItem* item)
{
- switch (check())
+ switch (item->id)
{
case MNID_CONTINUE:
MenuManager::instance().clear_menu_stack();
public:
GameMenu();
- void check_menu() override;
+ void menu_action(MenuItem* item) override;
private:
GameMenu(const GameMenu&);
void refresh_menu_item(Controller::Control id);
std::string get_button_name(int button);
- virtual void menu_action(MenuItem* item);
- void check_menu() {}
+ void menu_action(MenuItem* item) override;
private:
void recreate_menu();
void refresh();
std::string get_key_name(SDL_Keycode key);
- virtual void menu_action(MenuItem* item);
+ void menu_action(MenuItem* item) override;
InputManager* controller;
- void check_menu() {}
+
private:
KeyboardMenu(const KeyboardMenu&);
KeyboardMenu& operator=(const KeyboardMenu&);
public:
LanguageMenu();
- void menu_action(MenuItem* item);
- void check_menu() {}
+ void menu_action(MenuItem* item) override;
};
#endif
#include "supertux/menu/main_menu.hpp"
#include "audio/sound_manager.hpp"
+#include "gui/menu_item.hpp"
#include "gui/menu_manager.hpp"
#include "supertux/fadeout.hpp"
#include "supertux/game_manager.hpp"
}
void
-MainMenu::check_menu()
+MainMenu::menu_action(MenuItem* item)
{
- switch (check())
+ switch (item->id)
{
case MNID_STARTGAME:
{
MainMenu();
void on_window_resize() override;
- void check_menu();
+ void menu_action(MenuItem* item) override;
private:
MainMenu(const MainMenu&);
#include "supertux/globals.hpp"
#include "supertux/menu/addon_menu.hpp"
+#include "supertux/menu/cheat_menu.hpp"
#include "supertux/menu/contrib_menu.hpp"
#include "supertux/menu/game_menu.hpp"
#include "supertux/menu/joystick_menu.hpp"
#include "supertux/menu/options_menu.hpp"
#include "supertux/menu/profile_menu.hpp"
#include "supertux/menu/worldmap_menu.hpp"
+#include "supertux/menu/worldmap_cheat_menu.hpp"
MenuStorage* MenuStorage::s_instance = 0;
case WORLDMAP_MENU:
return std::unique_ptr<Menu>(new WorldmapMenu);
+ case WORLDMAP_CHEAT_MENU:
+ return std::unique_ptr<Menu>(new WorldmapCheatMenu);
+
case GAME_MENU:
return std::unique_ptr<Menu>(new GameMenu);
+ case CHEAT_MENU:
+ return std::unique_ptr<Menu>(new CheatMenu);
+
case CONTRIB_MENU:
return std::unique_ptr<Menu>(new ContribMenu);
KEYBOARD_MENU,
JOYSTICK_MENU,
WORLDMAP_MENU,
- GAME_MENU
+ WORLDMAP_CHEAT_MENU,
+ GAME_MENU,
+ CHEAT_MENU
};
public:
OptionsMenu(bool complete);
virtual ~OptionsMenu();
- void menu_action(MenuItem* item);
+ void menu_action(MenuItem* item) override;
void check_menu();
};
public:
ProfileMenu();
- void menu_action(MenuItem* item);
+ void menu_action(MenuItem* item) override;
void check_menu() {}
};
--- /dev/null
+// SuperTux
+// Copyright (C) 2014 Ingo Ruhnke <grumbel@gmail.com>
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+
+#include "supertux/menu/worldmap_cheat_menu.hpp"
+
+#include "gui/menu_item.hpp"
+#include "gui/menu_manager.hpp"
+#include "supertux/player_status.hpp"
+#include "supertux/savegame.hpp"
+#include "util/gettext.hpp"
+#include "worldmap/level.hpp"
+#include "worldmap/worldmap.hpp"
+
+WorldmapCheatMenu::WorldmapCheatMenu()
+{
+ add_label(_("Cheats"));
+ add_hl();
+ add_entry(MNID_GROW, _("Bonus: Grow"));
+ add_entry(MNID_FIRE, _("Bonus: Fire"));
+ add_entry(MNID_ICE, _("Bonus: Ice"));
+ add_entry(MNID_SHRINK, _("Bonus: None"));
+ add_hl();
+ add_entry(MNID_FINISH_LEVEL, _("Finish Level"));
+ add_entry(MNID_RESET_LEVEL, _("Reset Level"));
+ add_hl();
+ add_entry(MNID_FINISH_WORLDMAP, _("Finish WorldMap"));
+ add_entry(MNID_RESET_WORLDMAP, _("Reset WorldMap"));
+ add_hl();
+ add_back(_("Back"));
+}
+
+void
+WorldmapCheatMenu::menu_action(MenuItem* item)
+{
+ worldmap::WorldMap* worldmap = worldmap::WorldMap::current();
+ if (!worldmap)
+ {
+ log_warning << "couldn't access WorldMap::current()" << std::endl;
+ }
+ else
+ {
+ PlayerStatus* status = worldmap->get_savegame().get_player_status();
+
+ switch(item->id)
+ {
+ case MNID_GROW:
+ status->bonus = GROWUP_BONUS;
+ break;
+
+ case MNID_FIRE:
+ status->bonus = FIRE_BONUS;
+ break;
+
+ case MNID_ICE:
+ status->bonus = ICE_BONUS;
+ break;
+
+ case MNID_SHRINK:
+ status->bonus = NO_BONUS;
+ break;
+
+ case MNID_FINISH_LEVEL:
+ {
+ worldmap::LevelTile* level_tile = worldmap->at_level();
+ if (level_tile)
+ {
+ level_tile->set_solved(true);
+ level_tile->set_perfect(false);
+ }
+ }
+ break;
+
+ case MNID_RESET_LEVEL:
+ {
+ worldmap::LevelTile* level_tile = worldmap->at_level();
+ if (level_tile)
+ {
+ level_tile->set_solved(false);
+ level_tile->set_perfect(false);
+ }
+ }
+ break;
+
+ case MNID_FINISH_WORLDMAP:
+ worldmap->set_levels_solved(true, false);
+ break;
+
+ case MNID_RESET_WORLDMAP:
+ worldmap->set_levels_solved(false, false);
+ break;
+ }
+ }
+
+ MenuManager::instance().clear_menu_stack();
+}
+
+/* EOF */
--- /dev/null
+// SuperTux
+// Copyright (C) 2014 Ingo Ruhnke <grumbel@gmail.com>
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+
+#ifndef HEADER_SUPERTUX_SUPERTUX_MENU_WORLDMAP_CHEAT_MENU_HPP
+#define HEADER_SUPERTUX_SUPERTUX_MENU_WORLDMAP_CHEAT_MENU_HPP
+
+#include "gui/menu.hpp"
+
+class WorldmapCheatMenu : public Menu
+{
+private:
+private:
+ enum MenuIDs {
+ MNID_GROW,
+ MNID_FIRE,
+ MNID_ICE,
+ MNID_SHRINK,
+ MNID_FINISH_LEVEL,
+ MNID_RESET_LEVEL,
+ MNID_FINISH_WORLDMAP,
+ MNID_RESET_WORLDMAP
+ };
+
+public:
+ WorldmapCheatMenu();
+
+ void menu_action(MenuItem* item) override;
+
+private:
+ WorldmapCheatMenu(const WorldmapCheatMenu&) = delete;
+ WorldmapCheatMenu& operator=(const WorldmapCheatMenu&) = delete;
+};
+
+#endif
+
+/* EOF */
#include "supertux/menu/worldmap_menu.hpp"
+#include "gui/menu_item.hpp"
#include "gui/menu_manager.hpp"
#include "supertux/menu/menu_storage.hpp"
#include "supertux/menu/options_menu.hpp"
}
void
-WorldmapMenu::check_menu()
+WorldmapMenu::menu_action(MenuItem* item)
{
- switch (check())
+ switch (item->id)
{
case MNID_RETURNWORLDMAP:
MenuManager::instance().clear_menu_stack();
public:
WorldmapMenu();
- void check_menu() override;
+ void menu_action(MenuItem* item) override;
private:
WorldmapMenu(const WorldmapMenu&);
make_tux_jump();
- MenuManager::instance().check_menu();
-
// reopen menu if user closed it (so that the app doesn't close when user
// accidently hit ESC)
if(!MenuManager::instance().is_active() && !g_screen_manager->has_pending_fadeout())
{
}
+void
+LevelTile::update_sprite_action()
+{
+ if (perfect)
+ {
+ sprite->set_action("perfect");
+ }
+ else if (solved)
+ {
+ sprite->set_action("perfect");
+ }
+ else
+ {
+ sprite->set_action("default");
+ }
+}
+
+void
+LevelTile::set_solved(bool v)
+{
+ solved = v;
+ update_sprite_action();
+}
+
+void
+LevelTile::set_perfect(bool v)
+{
+ perfect = v;
+ update_sprite_action();
+}
+
} // namespace worldmap
/* EOF */
#include <string>
#include "math/vector.hpp"
+#include "sprite/sprite_ptr.hpp"
#include "supertux/game_object.hpp"
#include "supertux/statistics.hpp"
#include "video/surface.hpp"
virtual void draw(DrawingContext& context);
virtual void update(float elapsed_time);
+ void set_solved(bool v);
+ void set_perfect(bool v);
+
+private:
+ void update_sprite_action();
+
public:
Vector pos;
std::string title;
void
WorldMap::update(float delta)
{
- if(!in_level) {
- if (MenuManager::instance().check_menu())
- {
- return;
- }
-
+ if (!in_level && !MenuManager::instance().is_active())
+ {
// update GameObjects
for(size_t i = 0; i < game_objects.size(); ++i) {
GameObject* object = game_objects[i];
enter_level = true;
}
if(controller->pressed(Controller::PAUSE_MENU))
+ {
on_escape_press();
+ }
+
+ if(controller->pressed(Controller::CHEAT_MENU))
+ {
+ MenuManager::instance().set_menu(MenuStorage::WORLDMAP_CHEAT_MENU);
+ }
// check for teleporters
Teleporter* teleporter = at_teleporter(tux->get_tile_pos());
}
void
+WorldMap::set_levels_solved(bool solved, bool perfect)
+{
+ for(auto& level : levels)
+ {
+ level->set_solved(solved);
+ level->set_perfect(perfect);
+ }
+}
+
+void
WorldMap::save_state()
{
using namespace scripting;
*/
float get_height() const;
+ /**
+ * Mark all levels as solved or unsolved
+ */
+ void set_levels_solved(bool solved, bool perfect);
+
private:
void get_level_title(LevelTile& level);
void get_level_target_time(LevelTile& level);