diff --git a/src/config/player_manager.cpp b/src/config/player_manager.cpp index ed1b04bccce..55e061b012e 100644 --- a/src/config/player_manager.cpp +++ b/src/config/player_manager.cpp @@ -241,6 +241,10 @@ void PlayerManager::initRemainingData() // Sort player by frequency m_all_players.insertionSort(/*start*/0, /*desc*/true); + + // Load favorite tracks for the current player + if (m_current_player) + m_current_player->setFavoriteTracks(); } // initRemainingData // ---------------------------------------------------------------------------- @@ -480,7 +484,10 @@ void PlayerManager::setCurrentPlayer(PlayerProfile *player) m_current_player = player; if(m_current_player) + { m_current_player->computeActive(); + m_current_player->setFavoriteTracks(); + } if (player_has_changed) story_mode_timer->playerHasChanged(); diff --git a/src/config/player_profile.cpp b/src/config/player_profile.cpp index 980f805bee0..f84382bbb8b 100644 --- a/src/config/player_profile.cpp +++ b/src/config/player_profile.cpp @@ -27,6 +27,7 @@ #include "karts/kart_properties.hpp" #include "karts/kart_properties_manager.hpp" #include "online/online_player_profile.hpp" +#include "tracks/track_manager.hpp" #include "utils/string_utils.hpp" //------------------------------------------------------------------------------ @@ -78,6 +79,7 @@ PlayerProfile::PlayerProfile(const XMLNode* node) m_remember_password = false; m_story_mode_status = NULL; m_achievements_status = NULL; + m_favorite_tracks.clear(); m_default_kart_color = 0.0f; m_icon_filename = ""; @@ -111,9 +113,8 @@ PlayerProfile::~PlayerProfile() //------------------------------------------------------------------------------ -/** This function loads the achievement and story mode data. These can only - * be loaded after the UnlockManager is created, which needs the karts - * and tracks to be loaded first. +/** This function loads the achievement, story mode and favorites data. + * These can only be loaded after the karts and tracks. */ void PlayerProfile::loadRemainingData(const XMLNode *node) { @@ -123,6 +124,24 @@ void PlayerProfile::loadRemainingData(const XMLNode *node) const XMLNode *xml_achievements = node->getNode("achievements"); m_achievements_status = AchievementsManager::get() ->createAchievementsStatus(xml_achievements, m_unique_id == 1); + + // We first load the list of all favorite tracks + // Some favorites may correspond to uninstalled addons, so we do not sanitize the strings + // TODO : handle Arena and Soccer fields + const XMLNode *xml_favorites = node->getNode("favorites"); + std::vector xml_favorite_tracks; + xml_favorites->getNodes("track", xml_favorite_tracks); + for (unsigned int i = 0; i < xml_favorite_tracks.size(); i++) + { + std::string temp_string; + xml_favorite_tracks[i]->get("ident", &temp_string); + m_favorite_tracks.push_back(temp_string); + } + // Deduplicate the list just in case. + std::sort(m_favorite_tracks.begin(), m_favorite_tracks.end()); + auto it = std::unique(m_favorite_tracks.begin(), m_favorite_tracks.end()); + m_favorite_tracks.erase(it, m_favorite_tracks.end()); + // Fix up any potentially missing icons. addIcon(); } // initRemainingData @@ -139,6 +158,16 @@ void PlayerProfile::initRemainingData() addIcon(); } // initRemainingData +void PlayerProfile::setFavoriteTracks() +{ + // Update the group data from the Track Manager + track_manager->clearFavoriteTracks(); + for (unsigned int i = 0; i < m_favorite_tracks.size(); i++) + { + track_manager->addFavoriteTrack(m_favorite_tracks[i]); + } +} // setFavoriteTracks + //------------------------------------------------------------------------------ /** Creates an icon for a player if non exist so far. It takes the unique * player id modulo the number of karts to pick an icon from the karts. It @@ -201,6 +230,8 @@ const std::string PlayerProfile::getIconFilename() const */ void PlayerProfile::save(UTFWriter &out) { + //m_favorite_tracks.push_back("cornfield_crossing"); + out << " save(out); + + out << " \n"; + for (unsigned int i=0; i < m_favorite_tracks.size(); i++) + { + out << " \n"; + } + out << " \n"; } out << " \n"; } // save diff --git a/src/config/player_profile.hpp b/src/config/player_profile.hpp index f70c5fe99e6..84de69910e2 100644 --- a/src/config/player_profile.hpp +++ b/src/config/player_profile.hpp @@ -111,8 +111,12 @@ class PlayerProfile : public NoCopy /** The complete challenge state. */ StoryModeStatus *m_story_mode_status; + /** The complete achievement data. */ AchievementsStatus *m_achievements_status; + /** The list of identifiers of favorite tracks .*/ + std::vector m_favorite_tracks; + public: PlayerProfile(const core::stringw &name, bool is_guest = false); @@ -121,6 +125,7 @@ class PlayerProfile : public NoCopy void save(UTFWriter &out); void loadRemainingData(const XMLNode *node); void initRemainingData(); + void setFavoriteTracks(); void incrementUseFrequency(); int getUseFrequency() const { return m_use_frequency; } bool operator<(const PlayerProfile &other); diff --git a/src/states_screens/tracks_and_gp_screen.cpp b/src/states_screens/tracks_and_gp_screen.cpp index 97e1b6205ec..6569d2cfbb4 100644 --- a/src/states_screens/tracks_and_gp_screen.cpp +++ b/src/states_screens/tracks_and_gp_screen.cpp @@ -156,6 +156,8 @@ void TracksAndGPScreen::beforeAddingWidget() //I18N: track group name FOR_GETTEXT_ONLY( _("All") ) //I18N: track group name + FOR_GETTEXT_ONLY( _("Favorites") ) + //I18N: track group name FOR_GETTEXT_ONLY( _("Standard") ) //I18N: track group name FOR_GETTEXT_ONLY( _("Add-Ons") ) @@ -250,8 +252,8 @@ void TracksAndGPScreen::init() } // init // ----------------------------------------------------------------------------- -/** Rebuild the list of tracks and GPs. This need to be recomputed e.g. to - * take unlocked tracks into account. +/** Rebuild the list of tracks and GPs. This need to be recomputed to + * take unlocked tracks into account, when changing the current track group, etc. */ void TracksAndGPScreen::buildTrackList() { diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index e2219c50812..86ad0e2d7e5 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -258,6 +258,14 @@ core::stringw Track::getSortName() const */ bool Track::isInGroup(const std::string &group_name) { + if (group_name == "Favorites") + { + int index = track_manager->getTrackIndexByIdent(m_ident); + std::vector favorite_list = track_manager->getTracksInGroup("Favorites"); + return std::find(favorite_list.begin(), favorite_list.end(), index) + != favorite_list.end(); + } + return std::find(m_groups.begin(), m_groups.end(), group_name) != m_groups.end(); } // isInGroup diff --git a/src/tracks/track_manager.cpp b/src/tracks/track_manager.cpp index aae7cd80d30..41a82da33d3 100644 --- a/src/tracks/track_manager.cpp +++ b/src/tracks/track_manager.cpp @@ -164,6 +164,9 @@ void TrackManager::loadTrackList() delete track; m_tracks.clear(); + // Add the special favorites group + m_track_group_names.push_back("Favorites"); + for(unsigned int i=0; iisInternal()) return; + //TODO : ignore self-declarations from tracks as being in the "favorites" group const std::vector& new_groups = track->getGroups(); Group2Indices &group_2_indices = @@ -335,6 +339,26 @@ void TrackManager::updateGroups(const Track* track) } } // updateGroups +// ---------------------------------------------------------------------------- +/** \brief Adds a track to the favorite track group + */ +void TrackManager::addFavoriteTrack(const std::string& ident) +{ + // TODO : check if the ident corresponds to a race-track + int index = getTrackIndexByIdent(ident); + if (index >= 0) // index is negative if a track matching the index is missing + m_track_groups["Favorites"].push_back(index); +} // addFavoriteTrack + +// ---------------------------------------------------------------------------- +/** \brief Clears the list of active favorite tracks, used e.g. when switching + * between player profiles. + */ +void TrackManager::clearFavoriteTracks() +{ + m_track_groups["Favorites"].clear(); +} // clearFavoriteTracks + // ---------------------------------------------------------------------------- int TrackManager::getTrackIndexByIdent(const std::string& ident) const { diff --git a/src/tracks/track_manager.hpp b/src/tracks/track_manager.hpp index 2328b0baafa..b0d49ee0bac 100644 --- a/src/tracks/track_manager.hpp +++ b/src/tracks/track_manager.hpp @@ -44,13 +44,13 @@ class TrackManager Tracks m_tracks; typedef std::map > Group2Indices; - /** List of all racing track groups. */ + /** List of all track indexes for each racing track group. */ Group2Indices m_track_groups; - /** List of all arena groups. */ + /** List of all arena indexes for each arena group. */ Group2Indices m_arena_groups; - /** List of all soccer arena groups. */ + /** List of all soccer arena indexes for each soccer arena group. */ Group2Indices m_soccer_arena_groups; /** List of the names of all groups containing tracks */ @@ -74,6 +74,14 @@ class TrackManager ~TrackManager(); static void removeTrackSearchDirs(); static void addTrackSearchDir(const std::string &dir); + + /** Adds a track to the special group of favorite tracks. + * We need a special treatment, because the list of tracks in this group + * depends on the player-profile, not on the track data. */ + void addFavoriteTrack(const std::string& ident); + + void clearFavoriteTracks(); + /** Returns a list of all track identifiers. */ std::vector getAllTrackIdentifiers();