diff --git a/src/online/messages.cpp b/src/online/messages.cpp index 3b9bf2298..9bdfce9b9 100644 --- a/src/online/messages.cpp +++ b/src/online/messages.cpp @@ -85,6 +85,12 @@ namespace Online return irr::core::stringw(_("Processing")) + loadingDots(); } + // ------------------------------------------------------------------------ + /** Convenience function to type less in calls. */ + irr::core::stringw loadingDots(const wchar_t *s) + { + return irr::core::stringw(s)+loadingDots(); + } // ------------------------------------------------------------------------ /** * Shows a increasing number of dots. diff --git a/src/online/messages.hpp b/src/online/messages.hpp index c2f4fbc5c..9349caf91 100644 --- a/src/online/messages.hpp +++ b/src/online/messages.hpp @@ -31,6 +31,7 @@ namespace Online namespace Messages { irr::core::stringw loadingDots (float interval = 0.5f, int max_dots = 3); + irr::core::stringw loadingDots (const wchar_t *s); irr::core::stringw signingIn (); irr::core::stringw signingOut (); irr::core::stringw validatingInfo (); diff --git a/src/online/online_player_profile.cpp b/src/online/online_player_profile.cpp index 582be02cc..6ffe7928a 100644 --- a/src/online/online_player_profile.cpp +++ b/src/online/online_player_profile.cpp @@ -27,11 +27,11 @@ #include "online/online_profile.hpp" #include "online/profile_manager.hpp" #include "online/servers_manager.hpp" -#include "states_screens/login_screen.hpp" +#include "states_screens/story_mode_lobby.hpp" #include "states_screens/online_profile_friends.hpp" #include "states_screens/dialogs/change_password_dialog.hpp" -#include "states_screens/dialogs/user_info_dialog.hpp" #include "states_screens/dialogs/notification_dialog.hpp" +#include "states_screens/dialogs/user_info_dialog.hpp" #include "utils/log.hpp" #include "utils/translation.hpp" @@ -143,7 +143,7 @@ namespace Online { PlayerManager::getCurrentPlayer()->signIn(isSuccess(), getXMLData()); GUIEngine::Screen *screen = GUIEngine::getCurrentScreen(); - LoginScreen *login = dynamic_cast(screen); + StoryModeLobbyScreen *login = dynamic_cast(screen); if(login) { if(isSuccess()) diff --git a/src/states_screens/login_screen.cpp b/src/states_screens/login_screen.cpp index 8f6e39e70..219fb04fd 100644 --- a/src/states_screens/login_screen.cpp +++ b/src/states_screens/login_screen.cpp @@ -103,30 +103,6 @@ void LoginScreen::login() } } // login -// ----------------------------------------------------------------------------- -/** Called from the login request when it was successfully exected. - */ -void LoginScreen::loginSuccessful() -{ - // The callback is done from the main thread, so no need to sync - // access to m_success - m_success = true; -} // loginSuccessful - -// ----------------------------------------------------------------------------- -/** Called from the login request when the login was not successful. - * \param error_message The error message from the server (or curl). - */ -void LoginScreen::loginError(const irr::core::stringw & error_message) -{ - sfx_manager->quickSound("anvil"); - LabelWidget *info_widget = getWidget("info"); - info_widget->setErrorColor(); - info_widget->setText(error_message, false); - - m_options_widget->setActivated(); -} // loginError - // ----------------------------------------------------------------------------- /** Called in each frame. If a successful login is detected, the online screen * will be displayed. diff --git a/src/states_screens/login_screen.hpp b/src/states_screens/login_screen.hpp index b86fd5c57..bf739f037 100644 --- a/src/states_screens/login_screen.hpp +++ b/src/states_screens/login_screen.hpp @@ -56,8 +56,6 @@ public: const std::string& name, const int playerID) OVERRIDE; - void loginSuccessful(); - void loginError(const irr::core::stringw & error_message); }; // class LoginScreen #endif diff --git a/src/states_screens/main_menu_screen.cpp b/src/states_screens/main_menu_screen.cpp index 98927d034..b0404954a 100644 --- a/src/states_screens/main_menu_screen.cpp +++ b/src/states_screens/main_menu_screen.cpp @@ -41,11 +41,11 @@ #include "states_screens/credits.hpp" #include "states_screens/grand_prix_editor_screen.hpp" #include "states_screens/help_screen_1.hpp" -#include "states_screens/login_screen.hpp" #include "states_screens/offline_kart_selection.hpp" #include "states_screens/online_screen.hpp" #include "states_screens/options_screen_video.hpp" #include "states_screens/state_manager.hpp" +#include "states_screens/story_mode_lobby.hpp" #if DEBUG_MENU_ITEM #include "states_screens/feature_unlocked.hpp" #include "states_screens/grand_prix_lose.hpp" @@ -408,7 +408,11 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name, if (PlayerManager::getCurrentOnlineId()) StateManager::get()->pushScreen(OnlineScreen::getInstance()); else - StateManager::get()->pushScreen(LoginScreen::getInstance()); + { + StoryModeLobbyScreen *login = StoryModeLobbyScreen::getInstance(); + login->setIsPopup(true); + StateManager::get()->pushScreen(login); + } } else if (selection == "addons") { diff --git a/src/states_screens/story_mode_lobby.cpp b/src/states_screens/story_mode_lobby.cpp index 8d4b64722..6afe56df8 100644 --- a/src/states_screens/story_mode_lobby.cpp +++ b/src/states_screens/story_mode_lobby.cpp @@ -25,6 +25,7 @@ #include "guiengine/widgets/dynamic_ribbon_widget.hpp" #include "guiengine/widgets/label_widget.hpp" #include "guiengine/widgets/list_widget.hpp" +#include "online/messages.hpp" #include "states_screens/dialogs/enter_player_name_dialog.hpp" #include "states_screens/main_menu_screen.hpp" #include "states_screens/state_manager.hpp" @@ -38,6 +39,7 @@ DEFINE_SCREEN_SINGLETON( StoryModeLobbyScreen ); StoryModeLobbyScreen::StoryModeLobbyScreen() : Screen("story_mode_lobby.stkgui") { + m_is_popup_window = false; } // StoryModeLobbyScreen // ---------------------------------------------------------------------------- @@ -51,6 +53,7 @@ void StoryModeLobbyScreen::loadedFromFile() void StoryModeLobbyScreen::init() { + m_login_successful = false; m_online_cb = getWidget("online"); assert(m_online_cb); m_username_tb = getWidget("username"); @@ -60,13 +63,17 @@ void StoryModeLobbyScreen::init() m_password_tb->setPasswordBox(true, L'*'); m_players = getWidget("players"); assert(m_players); + m_options_widget = getWidget("options"); + assert(m_options_widget); + m_info_widget = getWidget("message"); + assert(m_info_widget); Screen::init(); PlayerProfile *player = PlayerManager::getCurrentPlayer(); - if (player) + if (player && !m_is_popup_window) { - //StateManager::get()->resetAndGoToScreen(MainMenuScreen::getInstance()); - //return; + StateManager::get()->resetAndGoToScreen(MainMenuScreen::getInstance()); + return; } m_players->clearItems(); @@ -103,6 +110,11 @@ void StoryModeLobbyScreen::selectUser(int index) { PlayerProfile *profile = PlayerManager::get()->getPlayer(index); assert(profile); + PlayerProfile *cp = PlayerManager::getCurrentPlayer(); + // If the current user is logged in, a logout is required now. + if(profile!=cp && cp && cp->isLoggedIn()) + cp->requestSignOut(); + getWidget("username")->setText(profile ->getLastOnlineName()); m_players->setSelection(StringUtils::toString(index), 0, /*focusIt*/true); @@ -117,6 +129,7 @@ void StoryModeLobbyScreen::selectUser(int index) } // Now last use was with online --> Display the saved data + m_online_cb->setState(true); makeEntryFieldsVisible(true); m_username_tb->setText(profile->getLastOnlineName()); @@ -141,7 +154,7 @@ void StoryModeLobbyScreen::makeEntryFieldsVisible(bool online) m_username_tb->setVisible(online); getWidget("label_password")->setVisible(online); m_password_tb->setVisible(online); -} // update +} // makeEntryFieldsVisible // ---------------------------------------------------------------------------- /** Called when the user selects anything on the screen. @@ -150,18 +163,18 @@ void StoryModeLobbyScreen::eventCallback(Widget* widget, const std::string& name, const int player_id) { - LabelWidget *info = getWidget("message"); - info->setText("", true); - info->setErrorColor(); + // Clean any error message still shown + m_info_widget->setText("", true); + m_info_widget->setErrorColor(); if (name == "players") { // Clicked on a name --> Find the corresponding online data // and display them - const std::string &s_index = getWidget("players") - ->getSelectionIDString(player_id); - if (s_index == "") return; // can happen if the list is empty - + const std::string &s_index = getWidget("players") + ->getSelectionIDString(player_id); + if (s_index == "") return; // can happen if the list is empty + unsigned int id; if (StringUtils::fromString(s_index, id)) selectUser(id); @@ -173,7 +186,7 @@ void StoryModeLobbyScreen::eventCallback(Widget* widget, if (m_online_cb->getState() && UserConfigParams::m_internet_status == Online::RequestManager::IPERM_NOT_ALLOWED) { - info->setText( + m_info_widget->setText( "Internet access is disabled, please enable it in the options", true); sfx_manager->quickSound( "anvil" ); @@ -183,77 +196,126 @@ void StoryModeLobbyScreen::eventCallback(Widget* widget, } else if (name == "options") { - const std::string &button = - getWidget("options")->getSelectionIDString(player_id); + const std::string &button = + m_options_widget->getSelectionIDString(player_id); if (button == "ok" || button == "ok_and_save") { if (m_online_cb->getState() && m_password_tb->getText() == "") { - info->setText(_("You need to enter a password."),true); - sfx_manager->quickSound( "anvil" ); + m_info_widget->setText(_("You need to enter a password."), true); + sfx_manager->quickSound("anvil"); return; } - - const std::string &name = m_players->getSelectionIDString(player_id); - - unsigned int id; - StringUtils::fromString(name, id); - PlayerProfile *profile = PlayerManager::get()->getPlayer(id); - PlayerManager::get()->setCurrentPlayer(profile, button=="ok_and_save"); - StateManager::get()->pushScreen(MainMenuScreen::getInstance()); - return; + login(button=="ok_and_save"); } // button==ok || ok_and_save else if (button == "new_user") { new EnterPlayerNameDialog(this, 0.5f, 0.4f); } + else if (button == "cancel") + { + PlayerProfile *cp = PlayerManager::getCurrentPlayer(); + if(cp && cp->isLoggedIn()) + cp->requestSignOut(); + StateManager::get()->popMenu(); + } } // options return; - - if (name == "back") - { - StateManager::get()->escapePressed(); - } - else if (name == "gameslots") - { - ListWidget* list = getWidget("gameslots"); - - bool slot_found = false; - - for (unsigned int n=0; ngetNumPlayers(); n++) - { - PlayerProfile *player = PlayerManager::get()->getPlayer(n); - if (list->getSelectionLabel() == player->getName()) - { - PlayerManager::get()->setCurrentPlayer(player, false); - slot_found = true; - break; - } - } - - if (!slot_found) - { - Log::error("StoryModeLobby", - "Cannot find player corresponding to slot '%s'.", - core::stringc(list->getSelectionLabel().c_str()).c_str()); - } - else - { -// CheckBoxWidget* cb = getWidget("rememberme"); -// if (cb->getState()) - { -// UserConfigParams::m_default_player = list->getSelectionLabel(); - } - } - - StateManager::get()->resetAndGoToScreen(MainMenuScreen::getInstance()); - } } // eventCallback // ---------------------------------------------------------------------------- +/** Called when OK or OK-and-save is clicked. + * This will trigger the actual login (if requested) etc. + * \param remember_me True if the login details should be remembered, + * so that next time this menu can be skipped. + */ +void StoryModeLobbyScreen::login(bool remember_me) +{ + m_options_widget->setDeactivated(); + const std::string &s_id = m_players->getSelectionIDString(0); + unsigned int n_id; + StringUtils::fromString(s_id, n_id); + PlayerProfile *profile = PlayerManager::get()->getPlayer(n_id); + PlayerManager::get()->setCurrentPlayer(profile, remember_me); + assert(profile); + + // If no online login requested, go straight to the main menu screen. + if(!m_online_cb->getState()) + { + if(profile->isLoggedIn()) + { + // The player is logged in, but online is now disabled, + // so log the player out. There is no error handling of + // a failed logout request + profile->requestSignOut(); + } + m_login_successful = true; + // This will trigger replacing this screen with the main menu screen. + onUpdate(0.0f); + return; + } + + // If the user is not already logged in, start a login request + if (!profile->isLoggedIn()) + { + if (profile->hasSavedSession()) + profile->requestSavedSession(); + else + profile->requestSignIn(m_username_tb->getText(), + m_password_tb->getText(), + remember_me); + } + return; +} // login + +// ---------------------------------------------------------------------------- +/** Called once every frame. It will replace this screen with the main menu + * screen if a successful login happened. + */ +void StoryModeLobbyScreen::onUpdate(float dt) +{ + if (!m_options_widget->isActivated()) + m_info_widget->setText(Online::Messages::loadingDots( _("Signing in")), + false); + + if(m_online_cb->getState() && m_login_successful) + { + StateManager::get()->resetAndGoToScreen(MainMenuScreen::getInstance()); + return; + } + + + PlayerProfile *cp = PlayerManager::getCurrentPlayer(); + if (cp && cp->isLoggedIn()) + cp->requestSignOut(); +} // onUpdate + +// ---------------------------------------------------------------------------- +/** Callback from player profile if login was successful. + */ +void StoryModeLobbyScreen::loginSuccessful() +{ + // The callback is done from the main thread, so no need to sync + // access to m_success + m_login_successful = true; +} // loginSuccessful + +// ---------------------------------------------------------------------------- +/** Callback from player profile if login was unsuccessful. + * \param error_message Contains the error message. + */ +void StoryModeLobbyScreen::loginError(const irr::core::stringw & error_message) +{ + sfx_manager->quickSound("anvil"); + m_info_widget->setErrorColor(); + m_info_widget->setText(error_message, false); + m_options_widget->setActivated(); +} // loginError + +// ---------------------------------------------------------------------------- void StoryModeLobbyScreen::unloaded() { } // unloaded diff --git a/src/states_screens/story_mode_lobby.hpp b/src/states_screens/story_mode_lobby.hpp index 5c97634f2..996c58538 100644 --- a/src/states_screens/story_mode_lobby.hpp +++ b/src/states_screens/story_mode_lobby.hpp @@ -43,6 +43,15 @@ class StoryModeLobbyScreen : public GUIEngine::Screen, StoryModeLobbyScreen(); private: + + /** True if this window is a popup window, which means it will not + * immediately go to the main menu if a current player is defined. */ + bool m_is_popup_window; + + /** Set in the callback from the login request to indicate that this + * window can be closed. */ + bool m_login_successful; + /** Online check box. */ GUIEngine::CheckBoxWidget *m_online_cb; @@ -52,12 +61,21 @@ private: /** Password widget. */ GUIEngine::TextBoxWidget *m_password_tb; + /** Label field for warning and error messages. */ + GUIEngine::LabelWidget * m_info_widget; + + /** The ribbon with all buttons. */ + GUIEngine::RibbonWidget *m_options_widget; + /** The dynamic ribbon containing all players. */ GUIEngine::DynamicRibbonWidget* m_players; void selectUser(int index); void makeEntryFieldsVisible(bool online); + void login(bool remember_me); virtual void onDialogClose(); + virtual void onUpdate(float dt) OVERRIDE; + public: friend class GUIEngine::ScreenSingleton; @@ -78,6 +96,13 @@ public: /** \brief implement callback from EnterPlayerNameDialog::INewPlayerListener */ virtual void onNewPlayerWithName(const irr::core::stringw& newName); -}; + + void loginSuccessful(); + void loginError(const irr::core::stringw & error_message); + // ------------------------------------------------------------------------ + /** True if this window is a popup window (i.e. it should not exit even if + * the current player exists. */ + void setIsPopup(bool popup) { m_is_popup_window = popup; } +}; // class StoryModeLobby #endif