Merge branch 'konstin-a'

This commit is contained in:
hiker 2014-07-07 17:01:48 +10:00
commit 09a9863a72
17 changed files with 615 additions and 204 deletions

View File

@ -376,8 +376,7 @@ void ChallengeData::setRace(RaceManager::Difficulty d) const
else if(m_mode==CM_GRAND_PRIX)
{
race_manager->setMinorMode(m_minor);
const GrandPrixData *gp = grand_prix_manager->getGrandPrix(m_gp_id);
race_manager->setGrandPrix(*gp);
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);

View File

@ -160,7 +160,7 @@ void SpinnerWidget::add()
{
label->setText(m_labels[m_value].c_str() );
}
}
@ -174,7 +174,7 @@ void SpinnerWidget::add()
m_children[2].m_id = m_children[2].m_element->getID();
// refresh display
setValue(m_value);
}
@ -333,7 +333,7 @@ void SpinnerWidget::setValue(const int new_value)
assert(new_value >= 0);
assert(new_value < (int)m_labels.size());
m_children[1].m_element->setText(m_labels[new_value].c_str() );
m_children[1].m_element->setText(m_labels[new_value].c_str());
}
else if (m_text.size() > 0 && m_children.size() > 0)
{

View File

@ -847,14 +847,14 @@ int handleCmdLine()
if(CommandLine::has("--gp", &s))
{
race_manager->setMajorMode(RaceManager::MAJOR_MODE_GRAND_PRIX);
const GrandPrixData *gp = grand_prix_manager->getGrandPrix(s);
GrandPrixData *gp = grand_prix_manager->getGrandPrix(s);
if (!gp)
{
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))

View File

@ -3,6 +3,8 @@
#include "race/race_manager.hpp"
#include "utils/log.hpp"
#include <stdexcept>
/** \brief Gets the element with the highest count in a std::map<S,int>.
* \param histogram : A pointer to the histogram.
* \return The key of type S that has the highest second value.

View File

@ -24,13 +24,15 @@
#include "config/player_manager.hpp"
#include "io/file_manager.hpp"
#include "io/utf_writer.hpp"
#include "states_screens/dialogs/random_gp_dialog.hpp"
#include "tracks/track_manager.hpp"
#include "tracks/track.hpp"
#include "utils/string_utils.hpp"
#include <iostream>
#include <memory>
#include <algorithm>
#include <cassert>
#include <cstdlib>
#include <memory>
#include <stdexcept>
@ -44,6 +46,94 @@ GrandPrixData::GrandPrixData(const std::string& filename)
reload();
}
// ----------------------------------------------------------------------------
GrandPrixData::GrandPrixData(const unsigned int number_of_tracks,
const std::string& track_group,
const RandomGPInfoDialog::REVERSED use_reverse)
{
m_filename = "Random GP - Not loaded from a file!";
m_id = "random";
m_name = "Random Grand Prix";
m_editable = false;
m_tracks.reserve(number_of_tracks);
m_laps.reserve(number_of_tracks);
m_reversed.reserve(number_of_tracks);
changeTrackNumber(number_of_tracks, track_group);
changeReverse(use_reverse);
}
// ----------------------------------------------------------------------------
void GrandPrixData::changeTrackNumber(const unsigned int number_of_tracks,
const std::string& track_group)
{
// The problem with the track groups is that "all" isn't a track group
// TODO: Add "all" to the track groups and rewrite this more elegant
std::vector<int> track_indices;
size_t available_tracks;
if (track_group == "all")
{
available_tracks = track_manager->getNumberOfTracks();
}
else
{
track_indices = track_manager->getTracksInGroup(track_group);
available_tracks = track_indices.size();
}
assert(number_of_tracks <= available_tracks);
// add or remove the right number of tracks
if (m_tracks.size() < number_of_tracks)
{
while (m_tracks.size() < number_of_tracks)
{
int index = (track_group == "all") ?
rand() % available_tracks :
track_indices[rand() % available_tracks];
std::string id = track_manager->getTrack(index)->getIdent();
// Avoid duplicate tracks
if (std::find(m_tracks.begin(), m_tracks.end(), id) != m_tracks.end())
continue;
m_tracks.push_back(id);
m_laps.push_back(3); // TODO: Take the default number from the track
m_reversed.push_back(false); // This will be changed later
}
}
else if (m_tracks.size() > number_of_tracks)
{
while (m_tracks.size() > number_of_tracks)
{
m_tracks.pop_back();
m_laps.pop_back();
m_reversed.pop_back();
}
}
assert(m_tracks.size() == m_laps.size() );
assert(m_laps.size() == m_reversed.size());
}
// ----------------------------------------------------------------------------
void GrandPrixData::changeReverse(const RandomGPInfoDialog::REVERSED use_reverse)
{
for (unsigned int i = 0; i < m_tracks.size(); i++)
{
if (use_reverse == RandomGPInfoDialog::NO_REVERSE)
m_reversed[i] = false;
else if (use_reverse == RandomGPInfoDialog::MIXED)
if (track_manager->getTrack(m_tracks[i])->reverseAvailable())
m_reversed[i] = (rand() % 2!=0);
else
m_reversed[i] = false;
else // all reversed
m_reversed[i] = true;
}
}
// ----------------------------------------------------------------------------
void GrandPrixData::setId(const std::string& id)
{

View File

@ -20,14 +20,15 @@
#ifndef HEADER_GRAND_PRIX_DATA_HPP
#define HEADER_GRAND_PRIX_DATA_HPP
#include <irrString.h>
#include <string>
#include <vector>
#include <cassert>
#include <irrString.h>
#include <stdexcept>
#include "states_screens/dialogs/random_gp_dialog.hpp"
#include "utils/translation.hpp"
using irr::core::stringw;
class Track;
/** Simple class that hold the data relevant to a 'grand_prix', aka. a number
@ -76,6 +77,13 @@ public:
GrandPrixData(const std::string& filename);
/** Needed for simple creation of an instance of GrandPrixData */
GrandPrixData() {};
/** Creates a new random GP */
GrandPrixData(const unsigned int number_of_tracks,
const std::string& track_group,
const RandomGPInfoDialog::REVERSED use_reverse);
void changeTrackNumber(const unsigned int number_of_tracks,
const std::string& track_group);
void changeReverse(const RandomGPInfoDialog::REVERSED use_reverse);
// Methods for the GP editor
void setId(const std::string& id);
@ -117,7 +125,6 @@ public:
// ------------------------------------------------------------------------
/** Returns the filename of the grand prix xml file. */
const std::string& getFilename() const { return m_filename; }
}; // GrandPrixData
#endif

View File

@ -31,6 +31,24 @@ GrandPrixManager *grand_prix_manager = NULL;
const char* GrandPrixManager::SUFFIX = ".grandprix";
// ----------------------------------------------------------------------------
GrandPrixManager::GrandPrixManager()
{
m_random_gp = NULL; // better do it explicitly and avoid weird stuff
loadFiles();
}
// ----------------------------------------------------------------------------
GrandPrixManager::~GrandPrixManager()
{
for(unsigned int i=0; i<m_gp_data.size(); i++)
{
delete m_gp_data[i];
}
delete m_random_gp;
}
// ----------------------------------------------------------------------------
void GrandPrixManager::loadFiles()
{
@ -130,21 +148,6 @@ bool GrandPrixManager::existsName(const irr::core::stringw& name) const
return false;
}
// ----------------------------------------------------------------------------
GrandPrixManager::GrandPrixManager()
{
loadFiles();
}
// ----------------------------------------------------------------------------
GrandPrixManager::~GrandPrixManager()
{
for(unsigned int i=0; i<m_gp_data.size(); i++)
{
delete m_gp_data[i];
}
}
// ----------------------------------------------------------------------------
GrandPrixData* GrandPrixManager::getGrandPrix(const std::string& s) const
{
@ -154,6 +157,9 @@ GrandPrixData* GrandPrixManager::getGrandPrix(const std::string& s) const
// ----------------------------------------------------------------------------
GrandPrixData* GrandPrixManager::editGrandPrix(const std::string& s) const
{
if (s == "random")
return m_random_gp;
for(unsigned int i=0; i<m_gp_data.size(); i++)
{
if(m_gp_data[i]->getId() == s)

View File

@ -47,6 +47,10 @@ private:
bool existsName(const irr::core::stringw& name) const;
public:
/** saved here by a random GP dialog to avoid dangling pinters or
* memory leaks */
GrandPrixData* m_random_gp;
GrandPrixManager();
~GrandPrixManager();
void reload();

View File

@ -283,9 +283,9 @@ void RaceManager::startNew(bool from_overworld)
if(m_major_mode==MAJOR_MODE_GRAND_PRIX)
{
// GP: get tracks, laps and reverse info from grand prix
m_tracks = m_grand_prix.getTrackNames();
m_num_laps = m_grand_prix.getLaps();
m_reverse_track = m_grand_prix.getReverse();
m_tracks = m_grand_prix->getTrackNames();
m_num_laps = m_grand_prix->getLaps();
m_reverse_track = m_grand_prix->getReverse();
}
//assert(m_player_karts.size() > 0);
@ -348,7 +348,7 @@ void RaceManager::startNew(bool from_overworld)
SavedGrandPrix* gp = SavedGrandPrix::getSavedGP( StateManager::get()
->getActivePlayerProfile(0)
->getUniqueID(),
m_grand_prix.getId(),
m_grand_prix->getId(),
m_difficulty,
m_num_karts,
m_player_karts.size());
@ -499,7 +499,7 @@ void RaceManager::next()
SavedGrandPrix::getSavedGP(StateManager::get()
->getActivePlayerProfile(0)
->getUniqueID(),
m_grand_prix.getId(),
m_grand_prix->getId(),
m_difficulty,
m_num_karts,
m_player_karts.size());
@ -516,7 +516,7 @@ void RaceManager::next()
new SavedGrandPrix(
StateManager::get()->getActivePlayerProfile(0)
->getUniqueID(),
m_grand_prix.getId(),
m_grand_prix->getId(),
m_difficulty,
m_player_karts.size(),
m_track_number,
@ -635,7 +635,7 @@ void RaceManager::exitRace(bool delete_world)
SavedGrandPrix::getSavedGP(StateManager::get()
->getActivePlayerProfile(0)
->getUniqueID(),
m_grand_prix.getId(),
m_grand_prix->getId(),
m_difficulty,
m_num_karts,
m_player_karts.size());
@ -767,13 +767,14 @@ void RaceManager::rerunRace()
//-----------------------------------------------------------------------------
void RaceManager::startGP(const GrandPrixData* gp, bool from_overworld,
void RaceManager::startGP(GrandPrixData* gp, bool from_overworld,
bool continue_saved_gp)
{
assert(gp != NULL);
//std::cout << gp->getId();
StateManager::get()->enterGameState();
setGrandPrix(*gp);
setGrandPrix(gp);
setCoinTarget( 0 ); // Might still be set from a previous challenge
race_manager->setupPlayerKartInfo();
m_continue_saved_gp = continue_saved_gp;

View File

@ -324,14 +324,14 @@ private:
* same list of AIs is used for all tracks of a GP. */
std::vector<std::string> m_ai_kart_list;
int m_track_number;
GrandPrixData m_grand_prix;
GrandPrixData* m_grand_prix;
int m_num_karts;
unsigned int m_num_finished_karts;
unsigned int m_num_finished_players;
int m_coin_target;
bool m_has_time_target;
float m_time_target;
int m_goal_target;
int m_goal_target;
void startNextRace(); // start a next race
@ -344,7 +344,7 @@ private:
bool m_have_kart_last_position_on_overworld;
Vec3 m_kart_last_position_on_overworld;
/** Determines if saved GP should be continued or not*/
bool m_continue_saved_gp;
@ -410,7 +410,7 @@ public:
void setDifficulty(Difficulty diff);
// ------------------------------------------------------------------------
void setGrandPrix(const GrandPrixData &gp)
void setGrandPrix(GrandPrixData* gp)
{
m_grand_prix = gp;
m_coin_target = 0;
@ -525,7 +525,7 @@ public:
// ------------------------------------------------------------------------
const std::string& getTrackName() const { return m_tracks[m_track_number];}
// ------------------------------------------------------------------------
const GrandPrixData *getGrandPrix() const { return &m_grand_prix; }
GrandPrixData* getGrandPrix() const { return m_grand_prix; }
// ------------------------------------------------------------------------
unsigned int getFinishedKarts() const { return m_num_finished_karts; }
// ------------------------------------------------------------------------
@ -682,7 +682,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(GrandPrixData* gp, bool from_overworld,
bool continue_saved_gp);
/**

View File

@ -81,7 +81,7 @@ void EnterGPNameDialog::onEnterPressedInternal()
TextBoxWidget* textCtrl = getWidget<TextBoxWidget>("textfield");
assert(textCtrl != NULL);
stringw name = textCtrl->getText().trim();
if (name.size() > 0)
if (name.size() > 0 && name != "Random Grand Prix")
{
// check for duplicate names
for (unsigned int i = 0; i < grand_prix_manager->getNumberOfGrandPrix(); i++)

View File

@ -28,6 +28,7 @@
#include "guiengine/widgets/label_widget.hpp"
#include "io/file_manager.hpp"
#include "race/grand_prix_manager.hpp"
#include "race/grand_prix_data.hpp"
#include "race/race_manager.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/tracks_screen.hpp"
@ -35,143 +36,190 @@
#include "tracks/track_manager.hpp"
#include "utils/translation.hpp"
#include <iostream>
#include <IGUIEnvironment.h>
#include <IGUIStaticText.h>
using namespace irr::gui;
using namespace irr::video;
using namespace irr::core;
using namespace GUIEngine;
using irr::gui::IGUIStaticText;
using GUIEngine::PROP_ID;
// ------------------------------------------------------------------------------------------------------
typedef GUIEngine::LabelWidget Label;
GPInfoDialog::GPInfoDialog(const std::string& gpIdent, const float w, const float h) : ModalDialog(w, h)
const float GPInfoDialog::PERCENT_WIDTH = 0.8f;
const float GPInfoDialog::PERCENT_HEIGHT = 0.7f;
GPInfoDialog::GPInfoDialog(const std::string& gp_ident)
: ModalDialog(PERCENT_WIDTH, PERCENT_HEIGHT)
{
doInit();
m_curr_time = 0.0f;
const int y1 = m_area.getHeight()/7;
const int y2 = m_area.getHeight()*6/7;
m_gp = grand_prix_manager->getGrandPrix(gp_ident);
m_gp->checkConsistency();
m_gp_ident = gpIdent;
m_under_title = m_area.getHeight()/7;
m_over_body = m_area.getHeight()/7;
m_lower_bound = m_area.getHeight()*6/7;
const GrandPrixData* gp = grand_prix_manager->getGrandPrix(gpIdent);
assert (gp != NULL);
addTitle();
addTracks();
addScreenshot();
addButtons();
}
// ---- GP Name
core::rect< s32 > area_top(0, 0, m_area.getWidth(), y1);
IGUIStaticText* title = GUIEngine::getGUIEnv()->addStaticText( translations->fribidize(gp->getName()),
area_top, false, true, // border, word wrap
m_irrlicht_window);
// ----------------------------------------------------------------------------
GPInfoDialog::~GPInfoDialog()
{
GUIEngine::Screen* curr_screen = GUIEngine::getCurrentScreen();
if (curr_screen->getName() == "tracks.stkgui")
static_cast<TracksScreen*>(curr_screen)->setFocusOnGP(m_gp->getId());
}
// ----------------------------------------------------------------------------
void GPInfoDialog::addTitle()
{
core::rect< s32 > area_top(0, 0, m_area.getWidth(), m_under_title);
IGUIStaticText* title = GUIEngine::getGUIEnv()->addStaticText(
translations->fribidize(m_gp->getName()),
area_top, false, true, // border, word wrap
m_irrlicht_window);
title->setTabStop(false);
title->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER);
title->setTextAlignment(irr::gui::EGUIA_CENTER, irr::gui::EGUIA_CENTER);
}
// ----------------------------------------------------------------------------
// ---- Track listings
const std::vector<std::string> tracks = gp->getTrackNames();
const int trackAmount = tracks.size();
void GPInfoDialog::addTracks()
{
const std::vector<std::string> tracks = m_gp->getTrackNames();
const unsigned int track_amount = tracks.size();
int height_of_one_line = (y2 - y1)/(trackAmount+1);
const int textHeight = GUIEngine::getFontHeight();
if (height_of_one_line > (int)(textHeight*1.5f)) height_of_one_line = (int)(textHeight*1.5f);
int height_of_one_line = std::min((m_lower_bound - m_over_body)/(track_amount+1),
(unsigned int)(GUIEngine::getFontHeight()*1.5f));
bool gp_ok = true;
for (int t=0; t<trackAmount; t++)
// Count the number of label already existing labels representing a track
unsigned int existing = 0;
for (unsigned int i = 0; i < m_widgets.size(); i++)
{
const int from_y = y1 + height_of_one_line*(t+1);
Track* track = track_manager->getTrack(tracks[t]);
stringw lineText;
if (track == NULL)
{
lineText = L"MISSING : ";
lineText.append( stringw(tracks[t].c_str()) );
gp_ok = false;
}
else
{
lineText = track->getName();
}
LabelWidget* widget = new LabelWidget();
widget->setText(translations->fribidize(lineText), false);
widget->m_x = 20;
widget->m_y = from_y;
widget->m_w = m_area.getWidth()/2 - 20;
widget->m_h = height_of_one_line;
widget->setParent(m_irrlicht_window);
m_widgets.push_back(widget);
widget->add();
// IGUIStaticText* line = GUIEngine::getGUIEnv()->addStaticText( lineText.c_str(),
// entry_area, false , true , // border, word wrap
// m_irrlicht_window);
if (m_widgets.get(i)->m_properties[PROP_ID] == "Track label")
existing++;
}
// ---- Track screenshot
unsigned int reuse = std::min(existing, track_amount);
// m_widgets has the type PtrVector<Widget, HOLD>
unsigned int widgets_iter = 0;
for (unsigned int i = 0; i < reuse; i++)
{
Track* track = track_manager->getTrack(tracks[i]);
m_screenshot_widget = new IconButtonWidget(IconButtonWidget::SCALE_MODE_KEEP_CUSTOM_ASPECT_RATIO,
false /* tab stop */, false /* focusable */,
IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE /* Track gives us absolute paths */);
// Find the next widget that is a track label
while (m_widgets.get(widgets_iter)->m_properties[PROP_ID] != "Track label")
widgets_iter++;
Label* widget = dynamic_cast<Label*>(m_widgets.get(widgets_iter));
widget->setText(translations->fribidize(track->getName()), false);
widget->move(20, m_over_body + height_of_one_line*(i+1),
m_area.getWidth()/2 - 20, height_of_one_line);
widgets_iter++;
}
if (existing < track_amount)
{
// There are not enough labels for all the track names, so we have to
// add some more
for (unsigned int i = reuse; i < track_amount; i++)
{
Track* track = track_manager->getTrack(tracks[i]);
assert(track != NULL);
Label* widget = new Label();
widget->m_properties[PROP_ID] = "Track label";
widget->setText(translations->fribidize(track->getName()), false);
widget->setParent(m_irrlicht_window);
m_widgets.push_back(widget);
widget->add();
widget->move(20, m_over_body + height_of_one_line*(i+1),
m_area.getWidth()/2 - 20, height_of_one_line);
}
}
else if (existing > track_amount)
{
// There are label which are not necessary anymore so they're deleted
for (unsigned int i = widgets_iter; i < m_widgets.size(); i++)
{
if (m_widgets.get(i)->m_properties[PROP_ID] == "Track label")
{
m_irrlicht_window->removeChild(m_widgets.get(i)->getIrrlichtElement());
m_widgets.remove(i);
i--;
}
}
}
}
// ----------------------------------------------------------------------------
void GPInfoDialog::addScreenshot()
{
m_screenshot_widget = new GUIEngine::IconButtonWidget(
GUIEngine::IconButtonWidget::SCALE_MODE_KEEP_CUSTOM_ASPECT_RATIO,
false, false, GUIEngine::IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE);
// images are saved squared, but must be stretched to 4:3
m_screenshot_widget->setCustomAspectRatio(4.0f / 3.0f);
m_screenshot_widget->m_x = m_area.getWidth()/2;
m_screenshot_widget->m_y = y1;
m_screenshot_widget->m_w = m_area.getWidth()/2;
m_screenshot_widget->m_h = y2 - y1 - 10;
m_screenshot_widget->m_x = m_area.getWidth()/2-20;
m_screenshot_widget->m_y = m_over_body + 10;
Track* track = (tracks.size() == 0 ? NULL : track_manager->getTrack(tracks[0]));
// Scale the picture to the biggest possible size without an overflow
if (m_lower_bound - m_over_body - 20 < m_area.getWidth()/2*3/4)
{
m_screenshot_widget->m_w = (m_lower_bound - m_over_body - 30)*4/3;
m_screenshot_widget->m_h = m_lower_bound - m_over_body - 30;
}
else
{
m_screenshot_widget->m_w = m_area.getWidth()/2;
m_screenshot_widget->m_h = m_area.getWidth()*3/8; // *(3/4)*(1/2)
}
m_screenshot_widget->m_properties[PROP_ICON] = (track != NULL ?
track->getScreenshotFile().c_str() :
file_manager->getAsset(FileManager::GUI,"main_help.png"));
Track* track = track_manager->getTrack(m_gp->getTrackNames()[0]);
m_screenshot_widget->m_properties[GUIEngine::PROP_ICON] = (track->getScreenshotFile().c_str());
m_screenshot_widget->setParent(m_irrlicht_window);
m_screenshot_widget->add();
m_widgets.push_back(m_screenshot_widget);
}
// ----------------------------------------------------------------------------
void GPInfoDialog::addButtons()
{
// ---- Start button
ButtonWidget* okBtn = new ButtonWidget();
ButtonWidget* continueBtn = new ButtonWidget();
GUIEngine::ButtonWidget* okBtn = new GUIEngine::ButtonWidget();
GUIEngine::ButtonWidget* continueBtn = new GUIEngine::ButtonWidget();
SavedGrandPrix* saved_gp = SavedGrandPrix::getSavedGP( StateManager::get()
->getActivePlayerProfile(0)
->getUniqueID(),
gpIdent,
m_gp->getId(),
race_manager->getDifficulty(),
race_manager->getNumberOfKarts(),
race_manager->getNumLocalPlayers());
if (tracks.size() == 0)
{
okBtn->m_properties[PROP_ID] = "cannot_start";
okBtn->setText(_("Sorry, no tracks available"));
}
else if (gp_ok)
{
okBtn->m_properties[PROP_ID] = "start";
okBtn->setText(_("Start Grand Prix"));
okBtn->m_properties[PROP_ID] = "start";
okBtn->setText(_("Start Grand Prix"));
continueBtn->m_properties[PROP_ID] = "continue";
continueBtn->setText(_("Continue"));
}
else
{
okBtn->m_properties[PROP_ID] = "cannot_start";
okBtn->setText(_("This Grand Prix is broken!"));
okBtn->setBadge(BAD_BADGE);
}
continueBtn->m_properties[PROP_ID] = "continue";
continueBtn->setText(_("Continue"));
if (saved_gp && gp_ok)
if (saved_gp)
{
continueBtn->m_x = m_area.getWidth()/2 + 110;
continueBtn->m_y = y2;
continueBtn->m_y = m_lower_bound;
continueBtn->m_w = 200;
continueBtn->m_h = m_area.getHeight() - y2 - 15;
continueBtn->m_h = m_area.getHeight() - m_lower_bound - 15;
continueBtn->setParent(m_irrlicht_window);
m_widgets.push_back(continueBtn);
continueBtn->add();
@ -185,9 +233,9 @@ GPInfoDialog::GPInfoDialog(const std::string& gpIdent, const float w, const floa
okBtn->m_x = m_area.getWidth()/2 - 200;
}
okBtn->m_y = y2;
okBtn->m_y = m_lower_bound;
okBtn->m_w = 400;
okBtn->m_h = m_area.getHeight() - y2 - 15;
okBtn->m_h = m_area.getHeight() - m_lower_bound - 15;
okBtn->setParent(m_irrlicht_window);
m_widgets.push_back(okBtn);
okBtn->add();
@ -195,87 +243,57 @@ GPInfoDialog::GPInfoDialog(const std::string& gpIdent, const float w, const floa
okBtn->getIrrlichtElement()->setTabGroup(false);
okBtn->setFocusForPlayer( PLAYER_ID_GAME_MASTER );
}
// ------------------------------------------------------------------------------------------------------
GPInfoDialog::~GPInfoDialog()
{
// Place focus back on selected GP, in case the dialog was cancelled and we're back to
// the track selection screen after
Screen* curr_screen = GUIEngine::getCurrentScreen();
if (curr_screen->getName() == "tracks.stkgui")
{
((TracksScreen*)curr_screen)->setFocusOnGP(m_gp_ident);
}
}
// ------------------------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------
void GPInfoDialog::onEnterPressedInternal()
{
// Save the gp identifier, since dismiss will delete this object.
std::string gp_id = m_gp_ident;
// Save the GP id because dismiss() will destroy this instance
std::string gp_id = m_gp->getId();
ModalDialog::dismiss();
// Disable accidentally unlocking of a challenge
PlayerManager::getCurrentPlayer()->setCurrentChallenge("");
race_manager->startGP(grand_prix_manager->getGrandPrix(gp_id), false, false);
}
// ------------------------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------
GUIEngine::EventPropagation GPInfoDialog::processEvent(const std::string& eventSource)
{
if (eventSource == "start")
if (eventSource == "start" || eventSource == "continue")
{
// Save GP identifier, since dismiss will delete this object.
std::string gp_id = m_gp_ident;
std::string gp_id = m_gp->getId();
ModalDialog::dismiss();
race_manager->startGP(grand_prix_manager->getGrandPrix(gp_id), false, false);
race_manager->startGP(grand_prix_manager->getGrandPrix(gp_id), false,
(eventSource == "continue"));
return GUIEngine::EVENT_BLOCK;
}
if (eventSource == "continue")
{
// Save GP identifier, since dismiss will delete this object.
std::string gp_id = m_gp_ident;
ModalDialog::dismiss();
race_manager->startGP(grand_prix_manager->getGrandPrix(gp_id), false, true);
return GUIEngine::EVENT_BLOCK;
}
else if (eventSource == "cannot_start")
{
sfx_manager->quickSound( "anvil" );
}
return GUIEngine::EVENT_LET;
}
// ------------------------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------
void GPInfoDialog::onUpdate(float dt)
{
const int frameBefore = (int)(m_curr_time / 1.5f);
if (dt == 0)
return; // if nothing changed, return right now
m_curr_time += dt;
int frameAfter = (int)(m_curr_time / 1.5f);
if (frameAfter == frameBefore) return; // if nothing changed, return right now
const GrandPrixData* gp = grand_prix_manager->getGrandPrix(m_gp_ident);
assert(gp != NULL);
const std::vector<std::string> tracks = gp->getTrackNames();
const std::vector<std::string> tracks = m_gp->getTrackNames();
if (frameAfter >= (int)tracks.size())
{
frameAfter = 0;
m_curr_time = 0;
}
Track* track = (tracks.size() == 0 ? NULL :
track_manager->getTrack(tracks[frameAfter]));
std::string fn = track ? track->getScreenshotFile()
: file_manager->getAsset(FileManager::GUI, "main_help.png");
m_screenshot_widget->setImage(fn.c_str(), IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE);
Track* track = track_manager->getTrack(tracks[frameAfter]);
std::string file = track->getScreenshotFile();
typedef GUIEngine::IconButtonWidget Icon;
m_screenshot_widget->setImage(file.c_str(), Icon::ICON_PATH_TYPE_ABSOLUTE);
}
// ------------------------------------------------------------------------------------------------------

View File

@ -20,6 +20,10 @@
#define HEADER_GP_INFO_DIALOG_HPP
#include "guiengine/modaldialog.hpp"
// Don't include grand_prix_data.hpp here or the compilation will fail
class GrandPrixData;
namespace GUIEngine
{
@ -32,23 +36,46 @@ namespace GUIEngine
*/
class GPInfoDialog : public GUIEngine::ModalDialog
{
std::string m_gp_ident;
protected: // Necessary for RandomGPInfoDialog
GUIEngine::IconButtonWidget* m_screenshot_widget;
float m_curr_time;
GrandPrixData* m_gp;
/** height of the separator over the body */
int m_over_body;
/** height of the separator under the titlebar, which is equal to
* m_over_body in a normal GPInfoDialo and lower in RandomGPInfoDialog. */
int m_under_title;
/** height of the seperator over the buttons */
int m_lower_bound;
void addTitle();
/** \brief display all the tracks according to the current gp
* For a normal gp info dialog, it just creates a label for every track.
* But with a random gp info dialog, it tries to reuse as many
* labels as possible by just changing their text. */
void addTracks();
void addScreenshot();
/** display a ok-button and eventually a continue-button */
void addButtons();
/** only used for track_screen.cpp */
GPInfoDialog() : ModalDialog(PERCENT_WIDTH, PERCENT_HEIGHT) {}
private:
static const float PERCENT_WIDTH;
static const float PERCENT_HEIGHT;
public:
/**
* Creates a modal dialog with given percentage of screen width and height
*/
GPInfoDialog(const std::string& gpIdent, const float percentWidth, const float percentHeight);
GPInfoDialog(const std::string& gpIdent);
/** 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 ~GPInfoDialog();
void onEnterPressedInternal();
GUIEngine::EventPropagation processEvent(const std::string& eventSource);
virtual void onUpdate(float dt);
virtual void onUpdate(float dt);
};
#endif

View File

@ -0,0 +1,195 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2014 konstin
//
// 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, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "guiengine/engine.hpp"
#include "guiengine/widgets/icon_button_widget.hpp"
#include "guiengine/widgets/spinner_widget.hpp"
#include "race/grand_prix_manager.hpp"
#include "race/race_manager.hpp"
#include "states_screens/dialogs/random_gp_dialog.hpp"
#include "tracks/track_manager.hpp"
#include <IGUIEnvironment.h>
#include <IGUIStaticText.h>
using irr::core::stringc;
using irr::core::stringw;
using irr::gui::IGUIStaticText;
typedef GUIEngine::SpinnerWidget Spinner;
RandomGPInfoDialog::RandomGPInfoDialog()
{
// Defaults - loading selection from last time frrom a file would be better
m_number_of_tracks = 2; // We can assume that there are at least 2 standard tracks
m_trackgroup = "standard";
m_use_reverse = NO_REVERSE;
doInit();
m_curr_time = 0.0f;
m_under_title = m_area.getHeight()/7;
m_over_body = m_area.getHeight()/7 + SPINNER_HEIGHT + 10; // 10px space
m_lower_bound = m_area.getHeight()*6/7;
// The GP manager is be used to make the GP live longer than this dialog
if (grand_prix_manager->m_random_gp)
{
delete grand_prix_manager->m_random_gp;
grand_prix_manager->m_random_gp = NULL;
}
m_gp = new GrandPrixData(m_number_of_tracks, m_trackgroup, m_use_reverse);
grand_prix_manager->m_random_gp = m_gp;
addTitle();
addSpinners();
addTracks();
addScreenshot();
addButtons();
addRestartButton();
}
// ----------------------------------------------------------------------------
void RandomGPInfoDialog::addSpinners()
{
const int trackgroup_width = 200, laps_with = 150, reverse_width = 200;
const int left = (m_area.getWidth() - trackgroup_width - 150 - 250)/2;
// Trackgroup chooser
Spinner* spinner = new Spinner(false);
spinner->m_properties[GUIEngine::PROP_ID] = "Trackgroup";
spinner->m_properties[GUIEngine::PROP_WRAP_AROUND] = "true";
spinner->setParent(m_irrlicht_window);
m_widgets.push_back(spinner);
spinner->add();
spinner->move(left, m_under_title, trackgroup_width, SPINNER_HEIGHT);
// Fill it with all the track group names
spinner->addLabel("all");
int index_standard;
const std::vector<std::string>& groups = track_manager->getAllTrackGroups();
for (unsigned int i = 0; i < groups.size(); i++)
{
// FIXME: The NULL check is necessary until #1348 on github is fixed
if (groups[i].c_str() != NULL)
{
spinner->addLabel(stringw(groups[i].c_str()));
if(groups[i] == "standard")
index_standard = i+1;
}
}
// The value can only be set here because SpinnerWidget resets the value
// every time a label is added
spinner->setValue(index_standard);
// Number of laps chooser
spinner = new Spinner(false);
spinner->setValue(m_number_of_tracks);
spinner->setMin(1);
spinner->setMax(track_manager->getTracksInGroup("standard").size());
spinner->setParent(m_irrlicht_window);
spinner->m_properties[GUIEngine::PROP_ID] = "Number of tracks";
spinner->m_properties[GUIEngine::PROP_WRAP_AROUND] = "true";
m_widgets.push_back(spinner);
spinner->add();
spinner->move(left + trackgroup_width + 10, m_under_title, laps_with, SPINNER_HEIGHT);
// reverse choose
spinner = new Spinner(false);
spinner->setParent(m_irrlicht_window);
spinner->m_properties[GUIEngine::PROP_ID] = "reverse";
spinner->m_properties[GUIEngine::PROP_WRAP_AROUND] = "true";
m_widgets.push_back(spinner);
spinner->add();
spinner->move(left + trackgroup_width + laps_with + 10, m_under_title, reverse_width, SPINNER_HEIGHT);
spinner->addLabel("no reverse");
spinner->addLabel("all reverse");
spinner->addLabel("mixed");
}
// ----------------------------------------------------------------------------
void RandomGPInfoDialog::addRestartButton()
{
GUIEngine::IconButtonWidget* button = new GUIEngine::IconButtonWidget();
button->setImage("gui/restart.png");
button->setParent(m_irrlicht_window);
button->m_properties[GUIEngine::PROP_ID] = "reload";
m_widgets.push_back(button);
button->add();
button->move(m_area.getWidth() - 20 - 32, 20, 32, 32);
}
// ----------------------------------------------------------------------------
GUIEngine::EventPropagation RandomGPInfoDialog::processEvent(
const std::string& eventSource)
{
if (eventSource == "start")
{
ModalDialog::dismiss();
race_manager->startGP(grand_prix_manager->m_random_gp, false, false);
return GUIEngine::EVENT_BLOCK;
}
else if (eventSource == "Number of tracks")
{
// The old gp can be reused because there's only track deletion/adding
m_number_of_tracks = getWidget<Spinner>("Number of tracks")->getValue();
m_gp->changeTrackNumber(m_number_of_tracks, m_trackgroup);
addTracks();
}
else if (eventSource == "Trackgroup")
{
Spinner* t = getWidget<Spinner>("Trackgroup");
Spinner* s = getWidget<Spinner>("Number of tracks");
m_trackgroup = stringc(t->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_trackgroup == "all") ?
track_manager->getNumberOfTracks() :
track_manager->getTracksInGroup(m_trackgroup).size();
m_number_of_tracks = std::min(max, m_number_of_tracks);
s->setMax(max);
if (s->getValue() > (signed)max)
s->setValue(max);
delete m_gp;
m_gp = new GrandPrixData(m_number_of_tracks, m_trackgroup, m_use_reverse);
grand_prix_manager->m_random_gp = m_gp;
addTracks();
}
else if (eventSource == "reverse")
{
Spinner* r = getWidget<Spinner>("reverse");
m_use_reverse = static_cast<REVERSED>(r->getValue());
m_gp->changeReverse(m_use_reverse);
}
else if (eventSource == "reload")
{
delete m_gp;
m_gp = new GrandPrixData(m_number_of_tracks, m_trackgroup, m_use_reverse);
grand_prix_manager->m_random_gp = m_gp;
addTracks();
}
return GUIEngine::EVENT_LET;
}

View File

@ -0,0 +1,53 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2014 konstin
//
// 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, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_RANDOM_GP_INFO_DIALOG_HPP
#define HEADER_RANDOM_GP_INFO_DIALOG_HPP
#include "states_screens/dialogs/gp_info_dialog.hpp"
#include <string>
class RandomGPInfoDialog : public GPInfoDialog
{
public:
enum REVERSED
{
NO_REVERSE = 0,
ALL_REVERSE = 1,
MIXED = 2
};
private:
unsigned int m_number_of_tracks;
std::string m_trackgroup;
REVERSED m_use_reverse;
public:
static const int SPINNER_HEIGHT = 40;
RandomGPInfoDialog();
/** Adds a SpinnerWidgets to choose the track groups, one to choose the
* number of tracks and one to choose if the tracks should be raced in
* reverse. The Spinners are centered. */
void addSpinners();
void addRestartButton();
GUIEngine::EventPropagation processEvent(const std::string& eventSource);
};
#endif

View File

@ -29,6 +29,7 @@
#include "race/grand_prix_manager.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/dialogs/gp_info_dialog.hpp"
#include "states_screens/dialogs/random_gp_dialog.hpp"
#include "states_screens/dialogs/track_info_dialog.hpp"
#include "tracks/track.hpp"
#include "tracks/track_manager.hpp"
@ -121,9 +122,16 @@ void TracksScreen::eventCallback(Widget* widget, const std::string& name,
gps_widget->getSelectionIDString(PLAYER_ID_GAME_MASTER);
if (selection == "locked")
{
unlock_manager->playLockSound();
}
else
new GPInfoDialog(selection, 0.8f, 0.7f);
{
if (selection == "Random Grand Prix")
new RandomGPInfoDialog();
else
new GPInfoDialog(selection);
}
}
else if (name == "trackgroups")
{
@ -214,12 +222,13 @@ void TracksScreen::init()
}
}
/*// Random GP - not finished yet
// Random GP
std::vector<std::string> screenshots;
screenshots.push_back("gui/main_help.png");
gps_widget->addAnimatedItem(translations->fribidize("Random"), "Random",
screenshots.push_back(file_manager->getAsset(FileManager::GUI, "main_help.png"));
gps_widget->addAnimatedItem(translations->fribidize("Random Grand Prix"),
"Random Grand Prix",
screenshots, 1.5f, 0,
IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE);*/
IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE);
gps_widget->updateItemDisplay();

View File

@ -521,10 +521,10 @@ void Track::loadTrackInfo()
delete root;
std::string dir = StringUtils::getPath(m_filename);
std::string easter_name = dir+"/easter_eggs.xml";
std::string easter_name = dir + "/easter_eggs.xml";
XMLNode *easter = file_manager->createXMLTree(easter_name);
if(easter)
{
for(unsigned int i=0; i<easter->getNumNodes(); i++)
@ -932,7 +932,7 @@ bool Track::loadMainTrack(const XMLNode &root)
{
mesh = irr_driver->getMesh(full_path);
}
if(!mesh)
{
Log::fatal("track",
@ -1960,7 +1960,7 @@ void Track::loadObjects(const XMLNode* root, const std::string& path, ModelDefin
libroot = library_nodes[name];
create_lod_definitions = false; // LOD definitions are already created, don't create them again
}
scene::ISceneNode* parent = irr_driver->getSceneManager()->addEmptySceneNode();
parent->setPosition(xyz);
parent->setRotation(hpr);