From 13024bf6ef67c37e97d04c90da5eab0e2bf284e5 Mon Sep 17 00:00:00 2001 From: hiker Date: Wed, 30 Apr 2014 08:42:43 +1000 Subject: [PATCH] On first time start the player is automatically asked to create a new player with a sensible default name. --- src/config/player_profile.cpp | 19 +++--- .../dialogs/enter_player_name_dialog.cpp | 62 +++++++++---------- src/states_screens/story_mode_lobby.cpp | 30 ++++++++- src/states_screens/story_mode_lobby.hpp | 1 + 4 files changed, 65 insertions(+), 47 deletions(-) diff --git a/src/config/player_profile.cpp b/src/config/player_profile.cpp index 9cebfedb1..bdf6224ac 100644 --- a/src/config/player_profile.cpp +++ b/src/config/player_profile.cpp @@ -49,13 +49,7 @@ PlayerProfile::PlayerProfile(const core::stringw& name, bool is_guest) m_saved_token = ""; m_saved_user_id = 0; m_last_online_name = ""; - if (unlock_manager && AchievementsManager::get()) - initRemainingData(); - else - { - m_achievements_status = NULL; - m_story_mode_status = NULL; - } + initRemainingData(); } // PlayerProfile //------------------------------------------------------------------------------ @@ -65,11 +59,12 @@ PlayerProfile::PlayerProfile(const core::stringw& name, bool is_guest) * that the achievement and story mode data depends on other data to be * read first (challenges and achievement files), which in turn can only be * created later in the startup process (they depend on e.g. all tracks to - * be known). On the other hand, automatic login needs to happen asap - * (i.e. as soon as the network thread is started), which needs the main - * player data (i.e. the default player, and saved session data). So the - * constructor only reads this data, the rest of the player data is handled - * in loadRemainingData later in the initialisation process. + * be known). On the other hand, automatic login needs to happen asap (i.e. + * as soon as the network thread is started) to avoid the player having to + * wait for the login to finish , which needs the main player data (i.e. + * the default player, and saved session data). So the constructor only + * reads this data, the rest of the player data is handled in + * loadRemainingData later in the initialisation process. * \param node The XML node representing this player. */ PlayerProfile::PlayerProfile(const XMLNode* node) diff --git a/src/states_screens/dialogs/enter_player_name_dialog.cpp b/src/states_screens/dialogs/enter_player_name_dialog.cpp index 0647a5cbf..e711f1ccd 100644 --- a/src/states_screens/dialogs/enter_player_name_dialog.cpp +++ b/src/states_screens/dialogs/enter_player_name_dialog.cpp @@ -47,37 +47,35 @@ EnterPlayerNameDialog::EnterPlayerNameDialog(INewPlayerListener* listener, m_self_destroy = false; loadFromFile("enter_player_name_dialog.stkgui"); - TextBoxWidget* textCtrl = getWidget("textfield"); - assert(textCtrl != NULL); - textCtrl->setFocusForPlayer(PLAYER_ID_GAME_MASTER); + TextBoxWidget* text_field = getWidget("textfield"); + assert(text_field != NULL); + text_field->setFocusForPlayer(PLAYER_ID_GAME_MASTER); - //if (translations->isRTLLanguage()) textCtrl->addListener(this); -} + std::string username = ""; + + // If there is no player (i.e. first start of STK), try to pick + // a good default name + if (PlayerManager::get()->getNumPlayers() == 0) + { + if (getenv("USERNAME") != NULL) // for windows + username = getenv("USERNAME"); + else if (getenv("USER") != NULL) // Linux, Macs + username = getenv("USER"); + else if (getenv("LOGNAME") != NULL) // Linux, Macs + username = getenv("LOGNAME"); + } + text_field->setText(username.c_str()); +} // EnterPlayerNameDialog // ----------------------------------------------------------------------------- EnterPlayerNameDialog::~EnterPlayerNameDialog() { - // FIXME: what is this code for? - TextBoxWidget* textCtrl = getWidget("textfield"); - textCtrl->getIrrlichtElement()->remove(); - textCtrl->clearListeners(); -} +} // ~EnterPlayerNameDialog // ----------------------------------------------------------------------------- - -/* -void EnterPlayerNameDialog::onTextUpdated() -{ - TextBoxWidget* textCtrl = getWidget("textfield"); - LabelWidget* lbl = getWidget("preview"); - - lbl->setText( core::stringw(translations->fribidize(textCtrl->getText())), false ); -} -*/ -// ----------------------------------------------------------------------------- - -GUIEngine::EventPropagation EnterPlayerNameDialog::processEvent(const std::string& eventSource) +GUIEngine::EventPropagation + EnterPlayerNameDialog::processEvent(const std::string& eventSource) { if (eventSource == "cancel") { @@ -85,10 +83,9 @@ GUIEngine::EventPropagation EnterPlayerNameDialog::processEvent(const std::strin return GUIEngine::EVENT_BLOCK; } return GUIEngine::EVENT_LET; -} +} // processEvent // ----------------------------------------------------------------------------- - void EnterPlayerNameDialog::onEnterPressedInternal() { // ---- Cancel button pressed @@ -102,8 +99,8 @@ void EnterPlayerNameDialog::onEnterPressedInternal() } // ---- Otherwise, see if we can accept the new name - TextBoxWidget* textCtrl = getWidget("textfield"); - stringw player_name = textCtrl->getText().trim(); + TextBoxWidget* text_field = getWidget("textfield"); + stringw player_name = text_field->getText().trim(); if (StringUtils::notEmpty(player_name)) { // check for duplicates @@ -133,21 +130,20 @@ void EnterPlayerNameDialog::onEnterPressedInternal() label->setText(_("Cannot add a player with this name."), false); sfx_manager->quickSound( "anvil" ); } -} +} // onEnterPressedInternal // ----------------------------------------------------------------------------- - void EnterPlayerNameDialog::onUpdate(float dt) { // It's unsafe to delete from inside the event handler so we do it here if (m_self_destroy) { - TextBoxWidget* textCtrl = getWidget("textfield"); - stringw player_name = textCtrl->getText().trim(); + TextBoxWidget* text_field = getWidget("textfield"); + stringw player_name = text_field->getText().trim(); // irrLicht is too stupid to remove focus from deleted widgets // so do it by hand - GUIEngine::getGUIEnv()->removeFocus( textCtrl->getIrrlichtElement() ); + GUIEngine::getGUIEnv()->removeFocus( text_field->getIrrlichtElement() ); GUIEngine::getGUIEnv()->removeFocus( m_irrlicht_window ); // we will destroy the dialog before notifying the listener to be safer. @@ -159,4 +155,4 @@ void EnterPlayerNameDialog::onUpdate(float dt) if (listener != NULL) listener->onNewPlayerWithName( player_name ); } -} +} // onUpdate diff --git a/src/states_screens/story_mode_lobby.cpp b/src/states_screens/story_mode_lobby.cpp index a3451a457..f37577b3d 100644 --- a/src/states_screens/story_mode_lobby.cpp +++ b/src/states_screens/story_mode_lobby.cpp @@ -81,11 +81,10 @@ void StoryModeLobbyScreen::init() m_players->updateItemDisplay(); // Select the first user (the list of users is sorted by usage, so it - // is the most frequently used user). + // is the most frequently used user). if (PlayerManager::get()->getNumPlayers()>0) selectUser(0); - } // init // ---------------------------------------------------------------------------- @@ -242,6 +241,33 @@ void StoryModeLobbyScreen::unloaded() { } // unloaded +// ---------------------------------------------------------------------------- +/** Gets called when a dialog closes. At a first time start of STK the + * internet dialog is shown first. Only when this dialog closes is it possible + * to open the next dialog, which is the one to create a new player (which + * is conventient on a first start). + */ +void StoryModeLobbyScreen::onDialogClose() +{ + // To allow players to exit the game without creating a player, we count + // how often this function was called. The first time is after the + // internet allowed dialog, the 2nd time + static int number_of_calls = 0; + number_of_calls++; + if(PlayerManager::get()->getNumPlayers() == 0) + { + // Still 0 players after the enter player dialog was shown + // --> User wanted to abort, so pop this menu, which will + // trigger the end of STK. + if (number_of_calls > 1) + { + StateManager::get()->popMenu(); + return; + } + new EnterPlayerNameDialog(this, 0.5f, 0.4f); + } // getNumPlayers == 0 +} // onDialogClose + // ---------------------------------------------------------------------------- /** This is a callback from the new user dialog. */ diff --git a/src/states_screens/story_mode_lobby.hpp b/src/states_screens/story_mode_lobby.hpp index ce506f97f..5c97634f2 100644 --- a/src/states_screens/story_mode_lobby.hpp +++ b/src/states_screens/story_mode_lobby.hpp @@ -57,6 +57,7 @@ private: void selectUser(int index); void makeEntryFieldsVisible(bool online); + virtual void onDialogClose(); public: friend class GUIEngine::ScreenSingleton;