Add sorting support in ghost replay selection screen

This commit is contained in:
Benau 2016-02-15 01:12:13 +08:00
parent 4ea6ea8ea6
commit 05093852bc
7 changed files with 118 additions and 26 deletions

View File

@ -34,19 +34,6 @@ class ReplayBase : public NoCopy
// Needs access to KartReplayEvent
friend class GhostKart;
public:
class ReplayData
{
public:
std::string m_filename;
bool m_reverse;
std::vector<std::string> m_kart_list;
unsigned int m_difficulty;
std::string m_track_name;
unsigned int m_laps;
float m_min_time;
}; // ReplayData
protected:
/** Stores a transform event, i.e. a position and rotation of a kart
* at a certain time. */

View File

@ -30,6 +30,7 @@
#include <stdio.h>
#include <string>
ReplayPlay::SortOrder ReplayPlay::m_sort_order = ReplayPlay::SO_DEFAULT;
ReplayPlay *ReplayPlay::m_replay_play = NULL;
//-----------------------------------------------------------------------------
@ -155,7 +156,8 @@ void ReplayPlay::loadAllReplayFile()
fclose(fd);
m_replay_file_list.push_back(rd);
}
}
} // loadAllReplayFile
//-----------------------------------------------------------------------------
void ReplayPlay::load()
{

View File

@ -23,6 +23,7 @@
#include "replay/replay_base.hpp"
#include "utils/ptr_vector.hpp"
#include <algorithm>
#include <string>
#include <vector>
@ -33,9 +34,63 @@ class GhostKart;
*/
class ReplayPlay : public ReplayBase
{
public:
/** Order of sort for ReplayData */
enum SortOrder
{
SO_DEFAULT,
SO_TRACK = SO_DEFAULT,
SO_REV,
SO_KART_NUM,
SO_DIFF,
SO_LAPS,
SO_TIME
};
class ReplayData
{
public:
std::string m_filename;
std::string m_track_name;
std::vector<std::string> m_kart_list;
bool m_reverse;
unsigned int m_difficulty;
unsigned int m_laps;
float m_min_time;
bool operator < (const ReplayData& r) const
{
switch (m_sort_order)
{
case SO_TRACK:
return m_track_name < r.m_track_name;
break;
case SO_KART_NUM:
return m_kart_list.size() < r.m_kart_list.size();
break;
case SO_REV:
return m_reverse < r.m_reverse;
break;
case SO_DIFF:
return m_difficulty < r.m_difficulty;
break;
case SO_LAPS:
return m_laps < r.m_laps;
break;
case SO_TIME:
return m_min_time < r.m_min_time;
break;
} // switch
return true;
} // operator <
}; // ReplayData
private:
static ReplayPlay *m_replay_play;
static SortOrder m_sort_order;
unsigned int m_current_replay_file;
std::vector<ReplayData> m_replay_file_list;
@ -51,6 +106,15 @@ public:
void load();
void loadAllReplayFile();
// ------------------------------------------------------------------------
static void setSortOrder(SortOrder so) { m_sort_order = so; }
// ------------------------------------------------------------------------
void sortReplay(bool reverse)
{
(reverse ? std::sort(m_replay_file_list.rbegin(),
m_replay_file_list.rend()) : std::sort(m_replay_file_list.begin(),
m_replay_file_list.end()));
}
// ------------------------------------------------------------------------
void setReplayFile(unsigned int n)
{ m_current_replay_file = n; }
// ------------------------------------------------------------------------

View File

@ -109,7 +109,6 @@ void GhostReplayInfoDialog::onUpdate(float dt)
if (m_self_destroy)
{
ModalDialog::dismiss();
GhostReplaySelection::getInstance()->refresh();
return;
}
} // onUpdate

View File

@ -22,7 +22,7 @@
#include "guiengine/modaldialog.hpp"
#include "guiengine/widgets/icon_button_widget.hpp"
#include "guiengine/widgets/ribbon_widget.hpp"
#include "replay/replay_base.hpp"
#include "replay/replay_play.hpp"
/** \brief Dialog that allows a user to do action with ghost replay file
* \ingroup states_screens
@ -35,7 +35,7 @@ private:
bool m_self_destroy;
const unsigned int m_replay_id;
ReplayBase::ReplayData m_rd;
ReplayPlay::ReplayData m_rd;
GUIEngine::RibbonWidget* m_action_widget;
GUIEngine::IconButtonWidget* m_back_widget;

View File

@ -18,7 +18,6 @@
#include "states_screens/ghost_replay_selection.hpp"
#include "replay/replay_play.hpp"
#include "states_screens/dialogs/ghost_replay_info_dialog.hpp"
#include "states_screens/state_manager.hpp"
#include "tracks/track.hpp"
@ -35,6 +34,7 @@ DEFINE_SCREEN_SINGLETON( GhostReplaySelection );
GhostReplaySelection::GhostReplaySelection() : Screen("ghost_replay_selection.stkgui")
{
m_file_to_be_deleted = "";
m_sort_desc = true;
} // GhostReplaySelection
// ----------------------------------------------------------------------------
@ -47,9 +47,10 @@ GhostReplaySelection::~GhostReplaySelection()
// ----------------------------------------------------------------------------
/** Triggers a refresh of the replay file list.
*/
void GhostReplaySelection::refresh()
void GhostReplaySelection::refresh(bool forced_update)
{
ReplayPlay::get()->loadAllReplayFile();
if (ReplayPlay::get()->getNumReplayFile() == 0 || forced_update)
ReplayPlay::get()->loadAllReplayFile();
loadList();
} // refresh
@ -81,7 +82,7 @@ void GhostReplaySelection::beforeAddingWidget()
void GhostReplaySelection::init()
{
Screen::init();
refresh();
refresh(/*forced_update*/false);
} // init
// ----------------------------------------------------------------------------
@ -90,10 +91,11 @@ void GhostReplaySelection::init()
*/
void GhostReplaySelection::loadList()
{
ReplayPlay::get()->sortReplay(m_sort_desc);
m_replay_list_widget->clear();
for (unsigned int i = 0; i < ReplayPlay::get()->getNumReplayFile() ; i++)
{
const ReplayBase::ReplayData& rd = ReplayPlay::get()->getReplayData(i);
const ReplayPlay::ReplayData& rd = ReplayPlay::get()->getReplayData(i);
std::vector<GUIEngine::ListWidget::ListCell> row;
Track* t = track_manager->getTrack(rd.m_track_name);
@ -133,8 +135,8 @@ void GhostReplaySelection::eventCallback(GUIEngine::Widget* widget,
unsigned int selected_index = m_replay_list_widget->getSelectionID();
// This can happen e.g. when the list is empty and the user
// clicks somewhere.
if(selected_index >= ReplayPlay::get()->getNumReplayFile() ||
selected_index < 0 )
if (selected_index >= ReplayPlay::get()->getNumReplayFile() ||
selected_index < 0 )
{
return;
}
@ -162,3 +164,40 @@ void GhostReplaySelection::onConfirm()
ModalDialog::dismiss();
GhostReplaySelection::getInstance()->refresh();
} // onConfirm
// ----------------------------------------------------------------------------
/** Change the sort order if a column was clicked.
* \param column_id ID of the column that was clicked.
*/
void GhostReplaySelection::onColumnClicked(int column_id)
{
switch (column_id)
{
case 0:
ReplayPlay::setSortOrder(ReplayPlay::SO_TRACK);
break;
case 1:
ReplayPlay::setSortOrder(ReplayPlay::SO_KART_NUM);
break;
case 2:
ReplayPlay::setSortOrder(ReplayPlay::SO_REV);
break;
case 3:
ReplayPlay::setSortOrder(ReplayPlay::SO_DIFF);
break;
case 4:
ReplayPlay::setSortOrder(ReplayPlay::SO_LAPS);
break;
case 5:
ReplayPlay::setSortOrder(ReplayPlay::SO_TIME);
break;
default:
assert(0);
break;
} // switch
/** \brief Toggle the sort order after column click **/
m_sort_desc = !m_sort_desc;
loadList();
} // onColumnClicked
// ----------------------------------------------------------------------------

View File

@ -43,10 +43,11 @@ private:
GUIEngine::ListWidget* m_replay_list_widget;
std::string m_file_to_be_deleted;
bool m_sort_desc;
public:
void refresh();
void refresh(bool forced_update = true);
/** Load the addons into the main list.*/
void loadList();
@ -63,7 +64,7 @@ public:
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void beforeAddingWidget() OVERRIDE;
virtual void onColumnClicked(int columnId) {};
virtual void onColumnClicked(int columnId);
virtual void init() OVERRIDE;