// SuperTux
-// Copyright (C) 2009 Ingo Ruhnke <grumbel@gmx.de>
+// Copyright (C) 2009 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
#include <assert.h>
#include "control/input_manager.hpp"
+#include "gui/dialog.hpp"
#include "gui/menu.hpp"
#include "gui/mousecursor.hpp"
+#include "math/sizef.hpp"
#include "supertux/globals.hpp"
#include "supertux/menu/menu_storage.hpp"
#include "supertux/timer.hpp"
+#include "util/gettext.hpp"
#include "util/log.hpp"
#include "video/drawing_context.hpp"
Rectf menu2rect(const Menu& menu)
{
- return Rectf(menu.get_pos().x,
- menu.get_pos().y,
- menu.get_pos().x + menu.get_width(),
- menu.get_pos().y + menu.get_height());
-}
-
-Rectf pos2rect(const Menu& menu)
-{
- return Rectf(menu.get_pos().x,
- menu.get_pos().y,
- menu.get_pos().x,
- menu.get_pos().y);
+ return Rectf(menu.get_center_pos().x - menu.get_width() / 2,
+ menu.get_center_pos().y - menu.get_height() / 2,
+ menu.get_center_pos().x + menu.get_width() / 2,
+ menu.get_center_pos().y + menu.get_height() / 2);
}
} // namespace
Rectf m_from_rect;
Rectf m_to_rect;
- bool m_closing_animation;
float m_effect_progress;
float m_effect_start_time;
bool m_is_active;
+
public:
MenuTransition() :
+ m_from_rect(),
+ m_to_rect(),
+ m_effect_progress(1.0f),
+ m_effect_start_time(),
m_is_active(false)
{
}
- void start(const Rectf& to_rect)
- {
- m_to_rect = to_rect;
- }
-
void start(const Rectf& from_rect,
const Rectf& to_rect)
{
m_is_active = true;
}
- void update()
+ void set(const Rectf& rect)
{
- m_effect_progress = (real_time - m_effect_start_time) * 6.0f;
+ m_to_rect = m_from_rect = rect;
+ }
- if (m_effect_progress >= 1.0f) {
- m_effect_progress = 1.0f;
+ void update()
+ {
+ if (m_is_active)
+ {
+ m_effect_progress = (real_time - m_effect_start_time) * 6.0f;
- /* if (close)
+ if (m_effect_progress > 1.0f)
{
- MenuManager::instance().m_current = 0;
- close = false;
- }*/
- }
- else if (m_effect_progress <= 0.0f)
- {
- m_effect_progress = 0.0f;
+ m_effect_progress = 1.0f;
+ m_is_active = false;
+ }
}
}
void draw(DrawingContext& context)
{
-#ifdef GRUMBEL
- Vector pos = current()->get_pos();
- float menu_width = current()->get_width();
- float menu_height = current()->get_height();
-
float p = m_effect_progress;
- if (p != 1.0f)
+
+ Rectf rect = m_to_rect;
+ if (m_is_active)
{
- if (close)
- {
- menu_width *= 1.0f - p;
- menu_height *= 1.0f - p;
- }
- else if (MenuManager::instance().m_previous)
- {
- menu_width = (menu_width * p) + (MenuManager::instance().m_previous->get_width() * (1.0f - p));
- menu_height = (menu_height * p) + (MenuManager::instance().m_previous->get_height() * (1.0f - p));
- //std::cout << p << " " << this << " " << last_menus.back() << std::endl;
- }
- else
- {
- menu_width *= p;
- menu_height *= p;
- }
+ rect.p1.x = (m_to_rect.p1.x * p) + (m_from_rect.p1.x * (1.0f - p));
+ rect.p1.y = (m_to_rect.p1.y * p) + (m_from_rect.p1.y * (1.0f - p));
+ rect.p2.x = (m_to_rect.p2.x * p) + (m_from_rect.p2.x * (1.0f - p));
+ rect.p2.y = (m_to_rect.p2.y * p) + (m_from_rect.p2.y * (1.0f - p));
}
// 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)),
+ context.draw_filled_rect(Rectf(rect.p1.x - 4, rect.p1.y - 10-4,
+ rect.p2.x + 4, rect.p2.y + 10 + 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)),
+ context.draw_filled_rect(Rectf(rect.p1.x, rect.p1.y - 10,
+ rect.p2.x, rect.p2.y + 10),
Color(0.6f, 0.7f, 0.8f, 0.5f),
16.0f,
LAYER_GUI-10);
-#endif
}
bool is_active()
};
MenuManager::MenuManager() :
+ m_dialog(),
+ m_has_next_dialog(false),
+ m_next_dialog(),
m_menu_stack(),
m_transition(new MenuTransition)
{
}
void
-MenuManager::update()
+MenuManager::refresh()
{
- if (current())
+ for(auto i = m_menu_stack.begin(); i != m_menu_stack.end(); ++i)
{
- current()->update();
- }
+ (*i)->refresh();
+ }
}
void
-MenuManager::event(const SDL_Event& event)
+MenuManager::process_input()
{
- if (current())
+ if (m_dialog)
{
- current()->event(event);
+ m_dialog->process_input(*InputManager::current()->get_controller());
+ }
+ else if (current_menu())
+ {
+ current_menu()->process_input();
}
}
void
-MenuManager::draw(DrawingContext& context)
+MenuManager::event(const SDL_Event& ev)
{
- if (!current())
+ if (!m_transition->is_active())
{
- return;
+ if (m_dialog)
+ {
+ m_dialog->event(ev);
+ }
+ else if (current_menu())
+ {
+ // only pass events when the menu is fully visible and not in a
+ // transition animation
+ current_menu()->event(ev);
+ }
}
+}
- m_transition->update();
- m_transition->draw(context);
+void
+MenuManager::draw(DrawingContext& context)
+{
+ if (m_has_next_dialog)
+ {
+ m_dialog = std::move(m_next_dialog);
+ m_has_next_dialog = false;
+ }
-#ifdef GRUMBEL
- // only pass events in non-anim states
- if(m_effect_progress != 1.0f)
- return;
-#endif
+ if (m_transition->is_active())
+ {
+ m_transition->update();
+ m_transition->draw(context);
+ }
+ else
+ {
+ if (m_dialog)
+ {
+ m_dialog->update();
+ m_dialog->draw(context);
+ }
+ else if (current_menu())
+ {
+ // brute force the transition into the right shape in case the
+ // menu has changed sizes
+ m_transition->set(menu2rect(*current_menu()));
+ m_transition->draw(context);
- current()->draw(context);
+ current_menu()->draw(context);
+ }
+ }
- if (MouseCursor::current())
+ if (current_menu() && MouseCursor::current())
{
MouseCursor::current()->draw(context);
}
}
-bool
-MenuManager::check_menu()
+void
+MenuManager::set_dialog(std::unique_ptr<Dialog> dialog)
{
- if (current())
- {
- current()->check_menu();
- return true;
- }
- else
- {
- return false;
- }
+ // delay reseting m_dialog to a later point, as otherwise the Dialog
+ // can't unset itself without ending up with "delete this" problems
+ m_next_dialog = std::move(dialog);
+ m_has_next_dialog = true;
}
void
}
void
+MenuManager::set_menu(int id)
+{
+ set_menu(MenuStorage::instance().create(static_cast<MenuStorage::MenuId>(id)));
+}
+
+void
MenuManager::push_menu(std::unique_ptr<Menu> menu)
{
- //start_transition_effect();
+ assert(menu);
+ transition(m_menu_stack.empty() ? nullptr : m_menu_stack.back().get(),
+ menu.get());
m_menu_stack.push_back(std::move(menu));
}
}
else
{
+ transition(m_menu_stack.back().get(),
+ (m_menu_stack.size() >= 2)
+ ? m_menu_stack[m_menu_stack.size() - 2].get()
+ : nullptr);
+
m_menu_stack.pop_back();
- //start_transition_effect();
}
}
void
-MenuManager::clear_menu_stack()
-{
- m_menu_stack.clear();
-}
-
-void
-MenuManager::set_menu(int id)
-{
- set_menu(MenuStorage::instance().create(static_cast<MenuStorage::MenuId>(id)));
-}
-
-void
MenuManager::set_menu(std::unique_ptr<Menu> menu)
{
if (menu)
{
- m_transition->start(pos2rect(*menu), menu2rect(*menu));
+ 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
{
+ transition(m_menu_stack.empty() ? nullptr : m_menu_stack.back().get(),
+ nullptr);
m_menu_stack.clear();
}
// just to be sure...
- g_input_manager->reset();
+ InputManager::current()->reset();
}
void
-MenuManager::recalc_pos()
+MenuManager::clear_menu_stack()
+{
+ transition(m_menu_stack.empty() ? nullptr : m_menu_stack.back().get(),
+ nullptr);
+ m_menu_stack.clear();
+}
+
+void
+MenuManager::on_window_resize()
{
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);
+ (*i)->on_window_resize();
}
}
Menu*
-MenuManager::current() const
+MenuManager::current_menu() const
{
if (m_menu_stack.empty())
{
}
}
+void
+MenuManager::transition(Menu* from, Menu* to)
+{
+ if (!from && !to)
+ {
+ return;
+ }
+ else
+ {
+ Rectf from_rect;
+ if (from)
+ {
+ from_rect = menu2rect(*from);
+ }
+ else
+ {
+ from_rect = Rectf(to->get_center_pos(), Sizef(0, 0));
+ }
+
+ Rectf to_rect;
+ if (to)
+ {
+ to_rect = menu2rect(*to);
+ }
+ else
+ {
+ to_rect = Rectf(from->get_center_pos(), Sizef(0, 0));
+ }
+
+ m_transition->start(from_rect, to_rect);
+ }
+}
+
/* EOF */