From 4484bd961ab826cf0fc1511b9370cea34b07e29e Mon Sep 17 00:00:00 2001 From: Alayan-stk-2 Date: Sat, 25 Aug 2018 01:34:42 +0200 Subject: [PATCH] Add kart icons to the ghost replay list (#3392) * Add a hide multiplayer replays checkbox * Hide player number column ; add kart icon column Enabling the icon display creates issues in the list widget layout, however. * Fix formatting issue when an icon is displayed in only some cells * Display "?" icon when kart model is unknown This can happen with uninstalled addons, old replays with removed official karts, etc * Add helper functions for icons in replay info dialog * Add kart icons to replay info dialog * Delete m_icon_bank in tearDown --- data/gui/ghost_replay_selection.stkgui | 7 +- src/guiengine/widgets/CGUISTKListBox.cpp | 4 +- .../dialogs/ghost_replay_info_dialog.cpp | 32 +++++- src/states_screens/ghost_replay_selection.cpp | 103 +++++++++++++++--- src/states_screens/ghost_replay_selection.hpp | 12 ++ 5 files changed, 141 insertions(+), 17 deletions(-) diff --git a/data/gui/ghost_replay_selection.stkgui b/data/gui/ghost_replay_selection.stkgui index 1b2f9abbf..e16e1d255 100644 --- a/data/gui/ghost_replay_selection.stkgui +++ b/data/gui/ghost_replay_selection.stkgui @@ -38,9 +38,14 @@
- +
+
+ + +
diff --git a/src/guiengine/widgets/CGUISTKListBox.cpp b/src/guiengine/widgets/CGUISTKListBox.cpp index c49850b0a..f9c56dc4d 100644 --- a/src/guiengine/widgets/CGUISTKListBox.cpp +++ b/src/guiengine/widgets/CGUISTKListBox.cpp @@ -572,7 +572,8 @@ void CGUISTKListBox::draw() Items[i].m_contents[x].m_center, true, &clientClip); } //Position back to inital pos - textRect.UpperLeftCorner.X -= ItemsIconWidth+6; + if (IconBank && (Items[i].m_contents[x].m_icon > -1)) + textRect.UpperLeftCorner.X -= ItemsIconWidth+6; //Calculate new beginning textRect.UpperLeftCorner.X += Items[i].m_contents[x].m_proportion * part_size; } @@ -780,4 +781,3 @@ void CGUISTKListBox::setDrawBackground(bool draw) } // end namespace gui } // end namespace irr - diff --git a/src/states_screens/dialogs/ghost_replay_info_dialog.cpp b/src/states_screens/dialogs/ghost_replay_info_dialog.cpp index 00e17f68d..cf377ed7a 100644 --- a/src/states_screens/dialogs/ghost_replay_info_dialog.cpp +++ b/src/states_screens/dialogs/ghost_replay_info_dialog.cpp @@ -19,7 +19,10 @@ #include "states_screens/dialogs/ghost_replay_info_dialog.hpp" #include "config/player_manager.hpp" +#include "guiengine/CGUISpriteBank.hpp" #include "graphics/stk_tex_manager.hpp" +#include "karts/kart_properties.hpp" +#include "karts/kart_properties_manager.hpp" #include "replay/replay_play.hpp" #include "states_screens/ghost_replay_selection.hpp" #include "states_screens/state_manager.hpp" @@ -32,7 +35,7 @@ using namespace irr::core; // ----------------------------------------------------------------------------- GhostReplayInfoDialog::GhostReplayInfoDialog(unsigned int replay_id, uint64_t compare_replay_uid, bool compare_ghost) - : ModalDialog(0.85f,0.65f), m_replay_id(replay_id) + : ModalDialog(0.9f,0.75f), m_replay_id(replay_id) { m_self_destroy = false; m_record_race = false; @@ -70,6 +73,11 @@ GhostReplayInfoDialog::GhostReplayInfoDialog(unsigned int replay_id, m_replay_info_widget = getWidget("current_replay_info"); assert(m_replay_info_widget != NULL); + /* Used to display kart icons for the selected replay(s) */ + irr::gui::STKModifiedSpriteBank *icon_bank = GhostReplaySelection::getInstance()->getIconBank(); + int icon_height = getHeight()/18.0f; + m_replay_info_widget->setIcons(icon_bank, (int)icon_height); + updateReplayDisplayedInfo(); LabelWidget *name = getWidget("name"); @@ -140,6 +148,8 @@ void GhostReplayInfoDialog::updateReplayDisplayedInfo() (_("Laps"), -1, 3, true)); row.push_back(GUIEngine::ListWidget::ListCell (_("Time"), -1, 4, true)); + row.push_back(GUIEngine::ListWidget::ListCell + (_("Kart"), -1, 1, true)); row.push_back(GUIEngine::ListWidget::ListCell (_("User"), -1, 5, true)); row.push_back(GUIEngine::ListWidget::ListCell @@ -164,6 +174,24 @@ void GhostReplayInfoDialog::updateReplayDisplayedInfo() const ReplayPlay::ReplayData& rd = ReplayPlay::get()->getReplayData(id); + int icon = -1; + + for(unsigned int i=0; igetNumberOfKarts(); i++) + { + const KartProperties* prop = kart_properties_manager->getKartById(i); + if (rd.m_kart_list[0] == prop->getIdent()) + { + icon = i; + break; + } + } + + if (icon == -1) + { + icon = GhostReplaySelection::getInstance()->getUnknownKartIcon(); + Log::warn("GhostReplayInfoDialog", "Kart not found, using default icon."); + } + if (is_linear) row.push_back(GUIEngine::ListWidget::ListCell (rd.m_reverse ? _("Yes") : _("No"), -1, 3, true)); @@ -176,6 +204,8 @@ void GhostReplayInfoDialog::updateReplayDisplayedInfo() (StringUtils::toWString(rd.m_laps), -1, 3, true)); row.push_back(GUIEngine::ListWidget::ListCell (StringUtils::toWString(rd.m_min_time) + L"s", -1, 4, true)); + row.push_back(GUIEngine::ListWidget::ListCell + ("", icon, 1, true)); row.push_back(GUIEngine::ListWidget::ListCell (rd.m_user_name.empty() ? " " : rd.m_user_name, -1, 5, true)); row.push_back(GUIEngine::ListWidget::ListCell diff --git a/src/states_screens/ghost_replay_selection.cpp b/src/states_screens/ghost_replay_selection.cpp index b9313f879..29b8ab033 100644 --- a/src/states_screens/ghost_replay_selection.cpp +++ b/src/states_screens/ghost_replay_selection.cpp @@ -18,6 +18,10 @@ #include "states_screens/ghost_replay_selection.hpp" +#include "graphics/material.hpp" +#include "guiengine/CGUISpriteBank.hpp" +#include "karts/kart_properties.hpp" +#include "karts/kart_properties_manager.hpp" #include "states_screens/dialogs/ghost_replay_info_dialog.hpp" #include "states_screens/state_manager.hpp" #include "states_screens/tracks_screen.hpp" @@ -43,6 +47,13 @@ GhostReplaySelection::~GhostReplaySelection() { } // GhostReplaySelection +// ---------------------------------------------------------------------------- +void GhostReplaySelection::tearDown() +{ + delete m_icon_bank; + m_icon_bank = NULL; +} + // ---------------------------------------------------------------------------- /** Triggers a refresh of the replay file list. */ @@ -79,6 +90,11 @@ void GhostReplaySelection::loadedFromFile() m_replay_difficulty_toggle_widget->setState(/* default value */ true); m_same_difficulty = m_replay_difficulty_toggle_widget->getState(); + m_replay_multiplayer_toggle_widget = + getWidget("replay_multiplayer_toggle"); + m_replay_multiplayer_toggle_widget->setState(/* default value */ true /* hide */); + m_multiplayer = !m_replay_multiplayer_toggle_widget->getState(); + m_replay_version_toggle_widget = getWidget("replay_version_toggle"); m_replay_version_toggle_widget->setState(/* default value */ true); @@ -107,7 +123,6 @@ void GhostReplaySelection::loadedFromFile() void GhostReplaySelection::beforeAddingWidget() { m_replay_list_widget->addColumn( _("Track"), 9 ); - m_replay_list_widget->addColumn( _("Players"), 3); if (m_active_mode_is_linear) m_replay_list_widget->addColumn( _("Reverse"), 3); if (!m_same_difficulty) @@ -115,7 +130,10 @@ void GhostReplaySelection::beforeAddingWidget() if (m_active_mode_is_linear) m_replay_list_widget->addColumn( _("Laps"), 3); m_replay_list_widget->addColumn( _("Time"), 4); + m_replay_list_widget->addColumn( _("Kart"), 1); m_replay_list_widget->addColumn( _("User"), 5); + if (m_multiplayer) + m_replay_list_widget->addColumn( _("Players"), 3); if (!m_same_version) m_replay_list_widget->addColumn( _("Version"), 3); @@ -127,6 +145,27 @@ void GhostReplaySelection::init() { Screen::init(); m_cur_difficulty = race_manager->getDifficulty(); + + m_icon_bank = new irr::gui::STKModifiedSpriteBank( GUIEngine::getGUIEnv()); + + for(unsigned int i=0; igetNumberOfKarts(); i++) + { + const KartProperties* prop = kart_properties_manager->getKartById(i); + m_icon_bank->addTextureAsSprite(prop->getIconMaterial()->getTexture()); + } + + video::ITexture* kart_not_found = irr_driver->getTexture( file_manager->getAsset(FileManager::GUI, + "main_help.png" )); + + m_icon_unknown_kart = m_icon_bank->addTextureAsSprite(kart_not_found); + + int icon_height = getHeight()/24.0f; + // 128 is the height of the image file + //FIXME : this isn't guaranteed + // Amanda's icon is 300x300 + m_icon_bank->setScale(icon_height/128.0f); + m_replay_list_widget->setIcons(m_icon_bank, (int)icon_height); + refresh(/*reload replay files*/ false, /* update columns */ true); } // init @@ -164,6 +203,9 @@ void GhostReplaySelection::loadList() if (m_same_version && current_version != rd.m_stk_version) continue; + if (!m_multiplayer && (rd.m_kart_list.size() > 1)) + continue; + Track* track = track_manager->getTrack(rd.m_track_name); if (track == NULL) @@ -268,6 +310,9 @@ void GhostReplaySelection::loadList() if (m_same_version && current_version != rd.m_stk_version) continue; + if (!m_multiplayer && (rd.m_kart_list.size() > 1)) + continue; + // Only display replays comparable with the replay selected for comparison if (m_is_comparing) { @@ -300,12 +345,28 @@ void GhostReplaySelection::loadList() if (track == NULL) continue; + int icon = -1; + + for(unsigned int i=0; igetNumberOfKarts(); i++) + { + const KartProperties* prop = kart_properties_manager->getKartById(i); + if (rd.m_kart_list[0] == prop->getIdent()) + { + icon = i; + break; + } + } + + if (icon == -1) + { + icon = m_icon_unknown_kart; + Log::warn("GhostReplaySelection", "Kart not found, using default icon."); + } + std::vector row; //The third argument should match the numbers used in beforeAddingWidget row.push_back(GUIEngine::ListWidget::ListCell (translations->fribidize(track->getName()) , -1, 9)); - row.push_back(GUIEngine::ListWidget::ListCell - (StringUtils::toWString(rd.m_kart_list.size()), -1, 3, true)); if (m_active_mode_is_linear) row.push_back(GUIEngine::ListWidget::ListCell (rd.m_reverse ? _("Yes") : _("No"), -1, 3, true)); @@ -319,8 +380,13 @@ void GhostReplaySelection::loadList() (StringUtils::toWString(rd.m_laps), -1, 3, true)); row.push_back(GUIEngine::ListWidget::ListCell (StringUtils::toWString(rd.m_min_time) + L"s", -1, 4, true)); + row.push_back(GUIEngine::ListWidget::ListCell + ("", icon, 1, true)); row.push_back(GUIEngine::ListWidget::ListCell (rd.m_user_name.empty() ? " " : rd.m_user_name, -1, 5, true)); + if (m_multiplayer) + row.push_back(GUIEngine::ListWidget::ListCell + (StringUtils::toWString(rd.m_kart_list.size()), -1, 3, true)); if (!m_same_version) row.push_back(GUIEngine::ListWidget::ListCell (rd.m_stk_version.empty() ? " " : rd.m_stk_version, -1, 3, true)); @@ -381,6 +447,11 @@ void GhostReplaySelection::eventCallback(GUIEngine::Widget* widget, m_same_difficulty = m_replay_difficulty_toggle_widget->getState(); refresh(/*reload replay files*/ false, /* update columns */ true); } + else if (name == "replay_multiplayer_toggle") + { + m_multiplayer = !m_replay_multiplayer_toggle_widget->getState(); + refresh(/*reload replay files*/ false, /* update columns */ true); + } else if (name == "replay_version_toggle") { m_same_version = m_replay_version_toggle_widget->getState(); @@ -436,31 +507,37 @@ void GhostReplaySelection::onColumnClicked(int column_id, bool sort_desc, bool s int diff_difficulty = m_same_difficulty ? 1 : 0; int diff_linear = m_active_mode_is_linear ? 0 : 1; + int diff_multiplayer = m_multiplayer ? 0 : 1; + + if (column_id >= 1) + column_id += diff_linear; if (column_id >= 2) - column_id += diff_linear; - - if (column_id >= 3) column_id += diff_difficulty; - if (column_id >= 4) + if (column_id >= 3) column_id += diff_linear; + if (column_id >= 7) + column_id += diff_multiplayer; + if (column_id == 0) ReplayPlay::setSortOrder(ReplayPlay::SO_TRACK); else if (column_id == 1) - ReplayPlay::setSortOrder(ReplayPlay::SO_KART_NUM); - else if (column_id == 2) ReplayPlay::setSortOrder(ReplayPlay::SO_REV); - else if (column_id == 3) + else if (column_id == 2) ReplayPlay::setSortOrder(ReplayPlay::SO_DIFF); - else if (column_id == 4) + else if (column_id == 3) ReplayPlay::setSortOrder(ReplayPlay::SO_LAPS); - else if (column_id == 5) + else if (column_id == 4) ReplayPlay::setSortOrder(ReplayPlay::SO_TIME); + else if (column_id == 5) + return; // no sorting by kart icon (yet ?) else if (column_id == 6) ReplayPlay::setSortOrder(ReplayPlay::SO_USER); - else if (column_id == 7) + else if (column_id == 7) + ReplayPlay::setSortOrder(ReplayPlay::SO_KART_NUM); + else if (column_id == 8) ReplayPlay::setSortOrder(ReplayPlay::SO_VERSION); else assert(0); diff --git a/src/states_screens/ghost_replay_selection.hpp b/src/states_screens/ghost_replay_selection.hpp index d34f9acf6..8438ecd91 100644 --- a/src/states_screens/ghost_replay_selection.hpp +++ b/src/states_screens/ghost_replay_selection.hpp @@ -44,6 +44,7 @@ private: GUIEngine::ListWidget* m_replay_list_widget; GUIEngine::CheckBoxWidget* m_replay_difficulty_toggle_widget; + GUIEngine::CheckBoxWidget* m_replay_multiplayer_toggle_widget; GUIEngine::CheckBoxWidget* m_replay_version_toggle_widget; GUIEngine::CheckBoxWidget* m_best_times_toggle_widget; GUIEngine::CheckBoxWidget* m_compare_toggle_widget; @@ -53,6 +54,7 @@ private: std::vector m_best_times_index; bool m_same_difficulty; bool m_same_version; + bool m_multiplayer; bool m_best_times; bool m_is_comparing; bool m_active_mode_is_linear; @@ -61,9 +63,17 @@ private: // Using the UID guarantees exact matchess uint64_t m_replay_to_compare_uid; + irr::gui::STKModifiedSpriteBank *m_icon_bank; + + /** Icon for unknown karts */ + int m_icon_unknown_kart; + void defaultSort(); public: + irr::gui::STKModifiedSpriteBank* getIconBank() { return m_icon_bank; } + + int getUnknownKartIcon() { return m_icon_unknown_kart; } void setCompareReplayUid(uint64_t uid) { m_replay_to_compare_uid = uid; } void setCompare(bool compare) { m_is_comparing = compare; } @@ -93,6 +103,8 @@ public: virtual void init() OVERRIDE; + virtual void tearDown() OVERRIDE; + virtual bool onEscapePressed() OVERRIDE; /** \brief Implement IConfirmDialogListener callback */