-
-
-
-
-
+
diff --git a/data/gui/random_gp_info.stkgui b/data/gui/random_gp_info.stkgui
new file mode 100644
index 000000000..871a97546
--- /dev/null
+++ b/data/gui/random_gp_info.stkgui
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/challenges/challenge_data.cpp b/src/challenges/challenge_data.cpp
index a65131611..6d0d0514a 100644
--- a/src/challenges/challenge_data.cpp
+++ b/src/challenges/challenge_data.cpp
@@ -376,7 +376,7 @@ void ChallengeData::setRace(RaceManager::Difficulty d) const
else if(m_mode==CM_GRAND_PRIX)
{
race_manager->setMinorMode(m_minor);
- race_manager->setGrandPrix(grand_prix_manager->getGrandPrix(m_gp_id));
+ race_manager->setGrandPrix(*grand_prix_manager->getGrandPrix(m_gp_id));
race_manager->setDifficulty(d);
race_manager->setNumKarts(m_num_karts[d]);
race_manager->setNumLocalPlayers(1);
diff --git a/src/main.cpp b/src/main.cpp
index 924590261..05131c01b 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -854,7 +854,7 @@ int handleCmdLine()
Log::warn("main", "There is no GP named '%s'.", s.c_str());
return 0;
}
- race_manager->setGrandPrix(gp);
+ race_manager->setGrandPrix(*gp);
} // --gp
if(CommandLine::has("--numkarts", &n) ||CommandLine::has("-k", &n))
diff --git a/src/race/race_manager.cpp b/src/race/race_manager.cpp
index 92e4e29fc..07362e7c8 100644
--- a/src/race/race_manager.cpp
+++ b/src/race/race_manager.cpp
@@ -762,12 +762,9 @@ void RaceManager::rerunRace()
//-----------------------------------------------------------------------------
-void RaceManager::startGP(const GrandPrixData* gp, bool from_overworld,
+void RaceManager::startGP(const GrandPrixData &gp, bool from_overworld,
bool continue_saved_gp)
{
- assert(gp != NULL);
- //std::cout << gp->getId();
-
StateManager::get()->enterGameState();
setGrandPrix(gp);
setCoinTarget( 0 ); // Might still be set from a previous challenge
diff --git a/src/race/race_manager.hpp b/src/race/race_manager.hpp
index 2a0f4b3cf..1dbb9a7ee 100644
--- a/src/race/race_manager.hpp
+++ b/src/race/race_manager.hpp
@@ -411,9 +411,9 @@ public:
void setDifficulty(Difficulty diff);
// ------------------------------------------------------------------------
- void setGrandPrix(const GrandPrixData *gp)
+ void setGrandPrix(const GrandPrixData &gp)
{
- m_grand_prix = *gp;
+ m_grand_prix = gp;
m_coin_target = 0;
}
// ------------------------------------------------------------------------
@@ -683,7 +683,7 @@ public:
* \brief Higher-level method to start a GP without having to care about
* the exact startup sequence
*/
- void startGP(const GrandPrixData* gp, bool from_overworld,
+ void startGP(const GrandPrixData &gp, bool from_overworld,
bool continue_saved_gp);
/**
diff --git a/src/states_screens/dialogs/gp_info_dialog.cpp b/src/states_screens/dialogs/gp_info_dialog.cpp
index 79ad221ca..dc411c69c 100644
--- a/src/states_screens/dialogs/gp_info_dialog.cpp
+++ b/src/states_screens/dialogs/gp_info_dialog.cpp
@@ -254,7 +254,7 @@ void GPInfoDialog::onEnterPressedInternal()
ModalDialog::dismiss();
// Disable accidentally unlocking of a challenge
PlayerManager::getCurrentPlayer()->setCurrentChallenge("");
- race_manager->startGP(grand_prix_manager->getGrandPrix(gp_id), false, false);
+ race_manager->startGP(*grand_prix_manager->getGrandPrix(gp_id), false, false);
}
// ----------------------------------------------------------------------------
@@ -270,8 +270,8 @@ GUIEngine::EventPropagation GPInfoDialog::processEvent(const std::string& event_
// becomes invalid!
std::string save_source = event_source;
ModalDialog::dismiss();
- race_manager->startGP(grand_prix_manager->getGrandPrix(gp_id), false,
- (save_source == "continue"));
+ //race_manager->startGP(grand_prix_manager->getGrandPrix(gp_id), false,
+ // (save_source == "continue"));
return GUIEngine::EVENT_BLOCK;
}
diff --git a/src/states_screens/dialogs/random_gp_dialog.cpp b/src/states_screens/dialogs/random_gp_dialog.cpp
index 848d01834..690afda1d 100644
--- a/src/states_screens/dialogs/random_gp_dialog.cpp
+++ b/src/states_screens/dialogs/random_gp_dialog.cpp
@@ -143,7 +143,7 @@ GUIEngine::EventPropagation RandomGPInfoDialog::processEvent(
// Save GP data, since dismiss will delete this object.
GrandPrixData gp = m_gp;
ModalDialog::dismiss();
- race_manager->startGP(&gp, false, false);
+ race_manager->startGP(gp, false, false);
return GUIEngine::EVENT_BLOCK;
}
else if (eventSource == "Number of tracks")
diff --git a/src/states_screens/gp_info_screen.cpp b/src/states_screens/gp_info_screen.cpp
index 8966f836c..fe04d1268 100644
--- a/src/states_screens/gp_info_screen.cpp
+++ b/src/states_screens/gp_info_screen.cpp
@@ -1,5 +1,6 @@
// SuperTuxKart - a fun racing game with go-kart
-// Copyright (C) 2009-2013 Marianne Gagnon
+// Copyright (C) 2009-2014 Marianne Gagnon
+// 2014 Joerg Henrichs, konstin
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@@ -29,6 +30,7 @@
#include "guiengine/widgets/label_widget.hpp"
#include "guiengine/widgets/list_widget.hpp"
#include "guiengine/widgets/ribbon_widget.hpp"
+#include "guiengine/widgets/spinner_widget.hpp"
#include "io/file_manager.hpp"
#include "race/grand_prix_manager.hpp"
#include "race/grand_prix_data.hpp"
@@ -42,88 +44,177 @@
#include
#include
+#include
+
using irr::gui::IGUIStaticText;
using GUIEngine::PROP_ID;
using namespace GUIEngine;
DEFINE_SCREEN_SINGLETON( GPInfoScreen );
+DEFINE_SCREEN_SINGLETON( RandomGPInfoScreen );
-GPInfoScreen::GPInfoScreen() : Screen("gp_info.stkgui")
+BaseGPInfoScreen::BaseGPInfoScreen(const std::string &name) : Screen(name.c_str())
{
- m_gp = NULL;
m_curr_time = 0.0f;
-} // GPInfoScreen
+ // Necessary to test if loadedFroMFile() was executed (in setGP)
+ m_reverse_spinner = NULL;
+} // BaseGPInfoScreen
// ----------------------------------------------------------------------------
-GPInfoScreen::~GPInfoScreen()
+BaseGPInfoScreen::~BaseGPInfoScreen()
{
-} // ~GPInfoScreen
+} // ~BaseGPInfoScreen
// ----------------------------------------------------------------------------
-/** Sets the GP to be displayed.
+void BaseGPInfoScreen::loadedFromFile()
+{
+ // The group spinner is filled in init every time the screen is shown
+ // (since the groups can change if addons are added/deleted).
+ m_group_spinner = getWidget("group-spinner");
+
+ m_reverse_spinner = getWidget("reverse-spinner");
+ m_reverse_spinner->addLabel(_("No"));
+ m_reverse_spinner->addLabel(_("Yes"));
+ m_reverse_spinner->addLabel(_("Random"));
+ m_reverse_spinner->setValue(0);
+
+ m_num_tracks_spinner = getWidget("track-spinner");
+ // Only init the number of tracks here, this way the previously selected
+ // number of tracks will be the default.
+ m_num_tracks_spinner->setValue(4);
+ int number_of_tracks = m_num_tracks_spinner->getValue();
+} // loadedFromFile
+
+// ----------------------------------------------------------------------------
+/** Sets the GP to be displayed. If the identifier is 'random', no gp info
+ * will be loaded.
*/
-void GPInfoScreen::setGP(const std::string &gp_ident)
+void BaseGPInfoScreen::setGP(const std::string &gp_ident)
{
- m_gp = grand_prix_manager->getGrandPrix(gp_ident);
+ if(gp_ident!="random")
+ m_gp = *grand_prix_manager->getGrandPrix(gp_ident);
+ else
+ {
+ // Doesn't matter what kind of GP we create, it just gets the
+ // right id ("random").
+ m_gp.createRandomGP(1, "standard",
+ m_reverse_spinner ? getReverse()
+ : GrandPrixData::GP_NO_REVERSE);
+ }
} // setGP
// ----------------------------------------------------------------------------
-void GPInfoScreen::init()
+GrandPrixData::GPReverseType BaseGPInfoScreen::getReverse() const
+{
+ switch (m_reverse_spinner->getValue())
+ {
+ case 0: return GrandPrixData::GP_NO_REVERSE; break;
+ case 1: return GrandPrixData::GP_ALL_REVERSE; break;
+ case 2: return GrandPrixData::GP_RANDOM_REVERSE; break;
+ default: assert(false);
+ } // switch
+ // Avoid compiler warning
+ return GrandPrixData::GP_NO_REVERSE;
+} // getReverse
+
+// ----------------------------------------------------------------------------
+void BaseGPInfoScreen::init()
{
Screen::init();
m_curr_time = 0.0f;
- getWidget("name")->setText(m_gp->getName(), false);
+ bool random = m_gp.getId()=="random";
- m_gp->checkConsistency();
+ SpinnerWidget *reverse_spinner = getWidget("reverse-spinner");
+ getWidget("track-text" )->setVisible(random);
+ m_num_tracks_spinner->setVisible(random);
+ getWidget("group-text" )->setVisible(random);
+ m_group_spinner->setVisible(random);
- m_over_body = UserConfigParams::m_height/7;
- m_lower_bound = UserConfigParams::m_height*6/7;
+
+ if(random)
+ {
+ getWidget("name")->setText(_("Random Grand Prix"), false);
+ getWidget("continue")->setVisible(false);
+
+ // We have to recreate the group spinner, but a new group might have
+ // been added or deleted since the last time this screen was shown.
+ m_group_spinner->clearLabels();
+ m_group_spinner->addLabel("all");
+ int index_standard;
+ const std::vector& groups = track_manager->getAllTrackGroups();
+ for (unsigned int i = 0; i < groups.size(); i++)
+ {
+ m_group_spinner->addLabel(stringw(groups[i].c_str()));
+ if (groups[i] == "standard")
+ index_standard = i + 1;
+ }
+ // Try to keep a previously selected group value
+ if(m_group_spinner->getValue() >= (int)groups.size())
+ {
+ m_group_spinner->setValue(index_standard);
+ m_group_name = "standard";
+ }
+ else
+ m_group_name = stringc(m_group_spinner->getStringValue().c_str()).c_str();
+
+ // If there are more tracks selected atm as in the group (which can
+ // happen if the group has been changed since last time this screen
+ // was shown), adjust it:
+ int max_num_tracks =
+ m_group_name=="all" ? track_manager->getNumberOfTracks()
+ : track_manager->getTracksInGroup(m_group_name).size();
+ if(m_num_tracks_spinner->getValue() > max_num_tracks)
+ {
+ m_num_tracks_spinner->setValue(max_num_tracks);
+ }
+
+ // Now create the random GP:
+ m_gp.createRandomGP(m_num_tracks_spinner->getValue(),
+ m_group_name, getReverse(), true);
+ }
+ else
+ {
+ getWidget("name")->setText(m_gp.getName(), false);
+ m_gp.checkConsistency();
+
+ // Check if there is a saved GP:
+ SavedGrandPrix* saved_gp =
+ SavedGrandPrix::getSavedGP(StateManager::get()
+ ->getActivePlayerProfile(0)->getUniqueID(),
+ m_gp.getId(),
+ race_manager->getDifficulty(),
+ race_manager->getNumberOfKarts(),
+ race_manager->getNumLocalPlayers());
+
+ getWidget("continue")->setVisible(saved_gp != NULL);
+ }
addTracks();
addScreenshot();
-
- CheckBoxWidget *reverse = getWidget("reverse");
- reverse->setState(false);
-
- // Check if there is a saved GP:
- SavedGrandPrix* saved_gp =
- SavedGrandPrix::getSavedGP(StateManager::get()
- ->getActivePlayerProfile(0)->getUniqueID(),
- m_gp->getId(),
- race_manager->getDifficulty(),
- race_manager->getNumberOfKarts(),
- race_manager->getNumLocalPlayers());
-
- getWidget("continue")->setVisible(saved_gp!=NULL);
} // init
// ----------------------------------------------------------------------------
-void GPInfoScreen::loadedFromFile()
-{
-} // loadedFromFile
-// ----------------------------------------------------------------------------
-
-void GPInfoScreen::addTracks()
+void BaseGPInfoScreen::addTracks()
{
- const std::vector tracks = m_gp->getTrackNames();
+ const std::vector tracks = m_gp.getTrackNames();
ListWidget *list = getWidget("tracks");
list->clear();
- for(unsigned int i=0; igetTrack(tracks[i]);
std::string s = StringUtils::toString(i);
- list->addItem(s, translations->fribidize(track->getName()) );
+ list->addItem(s, translations->fribidize(track->getName()));
}
} // addTracks
// ----------------------------------------------------------------------------
-void GPInfoScreen::addScreenshot()
+void BaseGPInfoScreen::addScreenshot()
{
Widget* screenshot_div = getWidget("screenshot_div");
@@ -143,7 +234,7 @@ void GPInfoScreen::addScreenshot()
m_screenshot_widget->m_properties[PROP_ICON] = "gui/main_help.png";
m_screenshot_widget->add();
- const Track *track = track_manager->getTrack(m_gp->getTrackId(0));
+ const Track *track = track_manager->getTrack(m_gp.getTrackId(0));
video::ITexture* screenshot = irr_driver->getTexture(track->getScreenshotFile(),
"While loading screenshot for track '%s':",
track->getFilename() );
@@ -154,19 +245,39 @@ void GPInfoScreen::addScreenshot()
// ----------------------------------------------------------------------------
-void GPInfoScreen::onEnterPressedInternal()
+void BaseGPInfoScreen::onEnterPressedInternal()
{
// Save the GP id because dismiss() will destroy this instance
- std::string gp_id = m_gp->getId();
-//FIXME ModalDialog::dismiss();
+ GrandPrixData gp_data = m_gp;
// Disable accidentally unlocking of a challenge
PlayerManager::getCurrentPlayer()->setCurrentChallenge("");
- race_manager->startGP(grand_prix_manager->getGrandPrix(gp_id), false, false);
+ race_manager->startGP(m_gp, false, false);
}
// ----------------------------------------------------------------------------
+void BaseGPInfoScreen::updateRandomGP()
+{
+ // First get the right track group to use
+ const std::vector& groups = track_manager->getAllTrackGroups();
-void GPInfoScreen::eventCallback(GUIEngine::Widget *, const std::string &name,
+ int n = m_group_spinner->getValue();
+ std::string track_group;
+ if(n>=0 && n < (int)groups.size())
+ {
+ track_group = groups[m_group_spinner->getValue()];
+ }
+ else
+ {
+ m_group_spinner->setValue(0);
+ track_group = groups[0];
+ }
+
+ int number_of_tracks = getWidget("track-spinner")->getValue();
+} // updateRandomGP
+
+// ----------------------------------------------------------------------------
+
+void BaseGPInfoScreen::eventCallback(GUIEngine::Widget *, const std::string &name,
const int player_id)
{
if(name=="buttons")
@@ -177,22 +288,49 @@ void GPInfoScreen::eventCallback(GUIEngine::Widget *, const std::string &name,
if (button == "start" || button=="continue")
{
// Save GP identifier, since dismiss will delete this object.
- std::string gp_id = m_gp->getId();
+ GrandPrixData gp_data = m_gp;
// Also create a copy of the string: it is a reference to data
// in a widget in the dialog - so if we call dismiss, this reference
// becomes invalid!
std::string save_source = name;
// FIXME ModalDialog::dismiss();
- race_manager->startGP(grand_prix_manager->getGrandPrix(gp_id), false,
- (save_source == "continue"));
+ race_manager->startGP(gp_data, false, (save_source == "continue"));
}
} // name=="buttons"
+ else if (name=="group-spinner")
+ {
+ m_group_name = stringc(m_group_spinner->getStringValue()).c_str();
+
+ // Update the maximum for the number of tracks since it's depending on
+ // the current track. The current value in the Number-of-tracks-spinner
+ // has to be updated, since otherwise the displayed (and used) value
+ // can be bigger than the maximum. (Might be a TODO to fix this)
+ unsigned int max = (m_group_name == "all") ?
+ track_manager->getNumberOfTracks() :
+ track_manager->getTracksInGroup(m_group_name).size();
+ m_num_tracks_spinner->setMax(max);
+ int number_of_tracks = std::min((int)max, m_num_tracks_spinner->getValue());
+ if (m_num_tracks_spinner->getValue() > (signed)max)
+ m_num_tracks_spinner->setValue(max);
+ // Create a new (i.e. with new tracks) random gp, since the old
+ // tracks might not all belong to the newly selected group.
+
+ m_gp.createRandomGP(m_num_tracks_spinner->getValue(), m_group_name,
+ getReverse(), /*new_tracks*/true);
+ addTracks();
+
+ }
+ else if (name=="track-spinner")
+ {
+ m_gp.changeTrackNumber(m_num_tracks_spinner->getValue(), m_group_name);
+ addTracks();
+ }
} // eventCallback
// ----------------------------------------------------------------------------
-void GPInfoScreen::onUpdate(float dt)
+void BaseGPInfoScreen::onUpdate(float dt)
{
if (dt == 0)
return; // if nothing changed, return right now
@@ -200,7 +338,7 @@ void GPInfoScreen::onUpdate(float dt)
m_curr_time += dt;
int frameAfter = (int)(m_curr_time / 1.5f);
- const std::vector tracks = m_gp->getTrackNames();
+ const std::vector tracks = m_gp.getTrackNames();
if (frameAfter >= (int)tracks.size())
{
frameAfter = 0;
diff --git a/src/states_screens/gp_info_screen.hpp b/src/states_screens/gp_info_screen.hpp
index 976d2c2b4..1e8a0f5e9 100644
--- a/src/states_screens/gp_info_screen.hpp
+++ b/src/states_screens/gp_info_screen.hpp
@@ -21,32 +21,36 @@
#define HEADER_GP_INFO_SCREEN_HPP
#include "guiengine/screen.hpp"
+#include "race/grand_prix_data.hpp"
class GrandPrixData;
namespace GUIEngine
{
class IconButtonWidget;
+ class SpinnerWidget;
}
/**
* \brief Dialog that shows information about a specific grand prix
* \ingroup states_screens
*/
-class GPInfoScreen : public GUIEngine::Screen,
- public GUIEngine::ScreenSingleton
+class BaseGPInfoScreen : public GUIEngine::Screen
{
-protected: // Necessary for RandomGPInfoScreen
+private:
+ GUIEngine::SpinnerWidget *m_group_spinner;
+ GUIEngine::SpinnerWidget *m_reverse_spinner;
+ GUIEngine::SpinnerWidget *m_num_tracks_spinner;
+
+ /** The currently selected group name. */
+ std::string m_group_name;
+
+protected: // Necessary for RandomBaseGPInfoScreen
GUIEngine::IconButtonWidget* m_screenshot_widget;
float m_curr_time;
/** The grand prix data. */
- GrandPrixData *m_gp;
-
- /** height of the separator over the body */
- int m_over_body;
- /** height of the seperator over the buttons */
- int m_lower_bound;
+ GrandPrixData m_gp;
/** \brief display all the tracks according to the current gp
* For a normal gp info dialog, it just creates a label for every track.
@@ -54,12 +58,14 @@ protected: // Necessary for RandomGPInfoScreen
* labels as possible by just changing their text. */
void addTracks();
void addScreenshot();
+ void updateRandomGP();
+ GrandPrixData::GPReverseType getReverse() const;
public:
- GPInfoScreen();
+ BaseGPInfoScreen(const std::string &name);
/** Places the focus back on the selected GP, in the case that the dialog
* was cancelled and we're returning to the track selection screen */
- virtual ~GPInfoScreen();
+ virtual ~BaseGPInfoScreen();
void onEnterPressedInternal();
virtual void eventCallback(GUIEngine::Widget *, const std::string &name,
@@ -70,6 +76,28 @@ public:
virtual void onUpdate(float dt);
void setGP(const std::string &gp_ident);
-};
+}; // BaseGPInfoScreen
+
+// ============================================================================
+class GPInfoScreen: public BaseGPInfoScreen,
+ public GUIEngine::ScreenSingleton
+{
+private:
+ GPInfoScreen() : BaseGPInfoScreen("gp_info.stkgui")
+ {};
+public:
+ friend class GUIEngine::ScreenSingleton;
+}; // class GPInfoScreen
+
+// ============================================================================
+class RandomGPInfoScreen: public BaseGPInfoScreen,
+ public GUIEngine::ScreenSingleton
+{
+private:
+ RandomGPInfoScreen() : BaseGPInfoScreen("random_gp_info.stkgui")
+ {};
+public:
+ friend class GUIEngine::ScreenSingleton;
+}; // class RandomGPInfoScreen
#endif
diff --git a/src/states_screens/tracks_screen.cpp b/src/states_screens/tracks_screen.cpp
index ba4865c07..2491176c5 100644
--- a/src/states_screens/tracks_screen.cpp
+++ b/src/states_screens/tracks_screen.cpp
@@ -116,7 +116,11 @@ void TracksScreen::eventCallback(Widget* widget, const std::string& name,
else
{
if (selection == "Random Grand Prix")
- new RandomGPInfoDialog();
+ {
+ RandomGPInfoScreen *gpis = RandomGPInfoScreen::getInstance();
+ gpis->setGP("random");
+ StateManager::get()->pushScreen(gpis);
+ }
else
{
GPInfoScreen *gpis = GPInfoScreen::getInstance();