Add ColumnCues calculations, exposed to themes via Lua function on Steps object
This commit is contained in:
@@ -52,12 +52,14 @@ source_group("Data Structures\\\\Courses and Trails"
|
|||||||
list(APPEND SM_DATA_NOTEDATA_SRC
|
list(APPEND SM_DATA_NOTEDATA_SRC
|
||||||
"NoteData.cpp"
|
"NoteData.cpp"
|
||||||
"NoteDataUtil.cpp"
|
"NoteDataUtil.cpp"
|
||||||
"NoteDataWithScoring.cpp")
|
"NoteDataWithScoring.cpp"
|
||||||
|
"ColumnCues.cpp")
|
||||||
|
|
||||||
list(APPEND SM_DATA_NOTEDATA_HPP
|
list(APPEND SM_DATA_NOTEDATA_HPP
|
||||||
"NoteData.h"
|
"NoteData.h"
|
||||||
"NoteDataUtil.h"
|
"NoteDataUtil.h"
|
||||||
"NoteDataWithScoring.h")
|
"NoteDataWithScoring.h"
|
||||||
|
"ColumnCues.h")
|
||||||
|
|
||||||
source_group("Data Structures\\\\Note Data"
|
source_group("Data Structures\\\\Note Data"
|
||||||
FILES
|
FILES
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
#include "global.h"
|
||||||
|
#include "ColumnCues.h"
|
||||||
|
#include "GameState.h"
|
||||||
|
#include "NoteData.h"
|
||||||
|
#include "TimingData.h"
|
||||||
|
|
||||||
|
void ColumnCue::CalculateColumnCues(const NoteData &in, std::vector<ColumnCue> &out, float minDuration)
|
||||||
|
{
|
||||||
|
TimingData *timing = GAMESTATE->GetProcessedTimingData();
|
||||||
|
NoteData::all_tracks_const_iterator curr_note = in.GetTapNoteRangeAllTracks(0, MAX_NOTE_ROW);
|
||||||
|
int curr_row = -1;
|
||||||
|
|
||||||
|
std::vector<ColumnCue> allColumnCues;
|
||||||
|
ColumnCue currentCue = ColumnCue();
|
||||||
|
|
||||||
|
while (!curr_note.IsAtEnd())
|
||||||
|
{
|
||||||
|
if(curr_note.Row() != curr_row)
|
||||||
|
{
|
||||||
|
if (currentCue.startTime != -1 )
|
||||||
|
{
|
||||||
|
allColumnCues.push_back(currentCue);
|
||||||
|
}
|
||||||
|
currentCue = ColumnCue();
|
||||||
|
currentCue.startTime = timing->GetElapsedTimeFromBeat(NoteRowToBeat(curr_note.Row()));
|
||||||
|
curr_row = curr_note.Row();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (curr_note->type == TapNoteType_Tap || curr_note->type == TapNoteType_HoldHead)
|
||||||
|
{
|
||||||
|
currentCue.columns.push_back(ColumnCueColumn(curr_note.Track() + 1, false));
|
||||||
|
}
|
||||||
|
else if(curr_note->type == TapNoteType_Mine)
|
||||||
|
{
|
||||||
|
currentCue.columns.push_back(ColumnCueColumn(curr_note.Track() + 1, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
++curr_note;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there's a remaining columnCue from the last row, add it
|
||||||
|
if( currentCue.startTime != -1)
|
||||||
|
{
|
||||||
|
allColumnCues.push_back(currentCue);
|
||||||
|
}
|
||||||
|
|
||||||
|
float previousCueTime = 0;
|
||||||
|
std::vector<ColumnCue> columnCues;
|
||||||
|
for( ColumnCue columnCue : allColumnCues )
|
||||||
|
{
|
||||||
|
float duration = columnCue.startTime - previousCueTime;
|
||||||
|
if( duration > minDuration || previousCueTime == 0)
|
||||||
|
{
|
||||||
|
columnCues.push_back(ColumnCue(previousCueTime, duration, columnCue.columns));
|
||||||
|
}
|
||||||
|
previousCueTime = columnCue.startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.clear();
|
||||||
|
out.assign(columnCues.begin(), columnCues.end());
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
#ifndef COLUMN_CUES_H
|
||||||
|
#define COLUMN_CUES_H
|
||||||
|
|
||||||
|
#include "GameConstantsAndTypes.h"
|
||||||
|
class NoteData;
|
||||||
|
|
||||||
|
/* ColumnCues are used to indicate to the player which column the next note will occur
|
||||||
|
after a long gap in the stepchart.
|
||||||
|
This info is made available to the theme via lua functions in Steps.cpp
|
||||||
|
*/
|
||||||
|
struct ColumnCueColumn
|
||||||
|
{
|
||||||
|
int colNum;
|
||||||
|
bool isMine;
|
||||||
|
ColumnCueColumn()
|
||||||
|
{
|
||||||
|
colNum = 0;
|
||||||
|
isMine = false;
|
||||||
|
}
|
||||||
|
ColumnCueColumn(int c, bool m)
|
||||||
|
{
|
||||||
|
colNum = c;
|
||||||
|
isMine = m;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ColumnCue
|
||||||
|
{
|
||||||
|
float startTime;
|
||||||
|
float duration;
|
||||||
|
std::vector<ColumnCueColumn> columns;
|
||||||
|
|
||||||
|
ColumnCue()
|
||||||
|
{
|
||||||
|
startTime = -1;
|
||||||
|
duration = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnCue(float s, float d, std::vector<ColumnCueColumn> c)
|
||||||
|
{
|
||||||
|
startTime = s;
|
||||||
|
duration = d;
|
||||||
|
columns.assign(c.begin(), c.end());
|
||||||
|
}
|
||||||
|
/** @brief Calculates the set of ColumnCues for the given NoteData. Each "cue" is for any note that has a
|
||||||
|
* minimum of minDuration seconds between it and the previous note on that same column.
|
||||||
|
*/
|
||||||
|
static void CalculateColumnCues(const NoteData &in, std::vector<ColumnCue> &out, float minDuration);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -701,6 +701,20 @@ RString Steps::GenerateChartKey(NoteData &nd, TimingData *td)
|
|||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<ColumnCue> Steps::GetColumnCues(float minDuration)
|
||||||
|
{
|
||||||
|
// TODO: Should we worry about getting the right steps per player?
|
||||||
|
// It seems like this is only necessary when dealing with Couples charts
|
||||||
|
|
||||||
|
std::vector<ColumnCue> cues;
|
||||||
|
NoteData noteData;
|
||||||
|
this->GetNoteData( noteData );
|
||||||
|
GAMESTATE->SetProcessedTimingData(this->GetTimingData());
|
||||||
|
ColumnCue::CalculateColumnCues(noteData, cues, minDuration);
|
||||||
|
GAMESTATE->SetProcessedTimingData(nullptr);
|
||||||
|
return cues;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// lua start
|
// lua start
|
||||||
#include "LuaBinding.h"
|
#include "LuaBinding.h"
|
||||||
@@ -799,6 +813,50 @@ public:
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int GetColumnCues(T *p, lua_State*L)
|
||||||
|
{
|
||||||
|
float minDuration = 1.5;
|
||||||
|
if (lua_isnumber(L, 1))
|
||||||
|
{
|
||||||
|
minDuration = lua_tonumber(L, 1);
|
||||||
|
}
|
||||||
|
std::vector<ColumnCue> cues = p->GetColumnCues(minDuration);
|
||||||
|
lua_createtable(L, cues.size(), 0);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < cues.size(); i++)
|
||||||
|
{
|
||||||
|
lua_newtable(L);
|
||||||
|
lua_pushstring(L, "startTime");
|
||||||
|
lua_pushnumber(L, cues[i].startTime);
|
||||||
|
lua_settable(L, -3);
|
||||||
|
|
||||||
|
lua_pushstring(L, "duration");
|
||||||
|
lua_pushnumber(L, cues[i].duration);
|
||||||
|
lua_settable(L, -3);
|
||||||
|
|
||||||
|
lua_pushstring(L, "columns");
|
||||||
|
lua_createtable(L, cues[i].columns.size(), 0);
|
||||||
|
|
||||||
|
for (unsigned c = 0; c < cues[i].columns.size(); c++)
|
||||||
|
{
|
||||||
|
lua_newtable(L);
|
||||||
|
lua_pushstring(L, "colNum");
|
||||||
|
lua_pushinteger(L, cues[i].columns[c].colNum);
|
||||||
|
lua_settable(L, -3);
|
||||||
|
|
||||||
|
lua_pushstring(L, "isMine");
|
||||||
|
lua_pushboolean(L, cues[i].columns[c].isMine);
|
||||||
|
lua_settable(L, -3);
|
||||||
|
|
||||||
|
lua_rawseti(L, -2, c + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_settable(L, -3);
|
||||||
|
lua_rawseti(L, -2, i + 1);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
LunaSteps()
|
LunaSteps()
|
||||||
{
|
{
|
||||||
ADD_METHOD( GetAuthorCredit );
|
ADD_METHOD( GetAuthorCredit );
|
||||||
@@ -824,6 +882,7 @@ public:
|
|||||||
ADD_METHOD( IsDisplayBpmRandom );
|
ADD_METHOD( IsDisplayBpmRandom );
|
||||||
ADD_METHOD( PredictMeter );
|
ADD_METHOD( PredictMeter );
|
||||||
ADD_METHOD( GetDisplayBPMType );
|
ADD_METHOD( GetDisplayBPMType );
|
||||||
|
ADD_METHOD( GetColumnCues );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "Difficulty.h"
|
#include "Difficulty.h"
|
||||||
#include "RageUtil_AutoPtr.h"
|
#include "RageUtil_AutoPtr.h"
|
||||||
#include "TimingData.h"
|
#include "TimingData.h"
|
||||||
|
#include "ColumnCues.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -211,6 +212,8 @@ public:
|
|||||||
return join(":", this->m_sAttackString);
|
return join(":", this->m_sAttackString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<ColumnCue> GetColumnCues(float minDuration);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline const Steps *Real() const { return parent ? parent : this; }
|
inline const Steps *Real() const { return parent ? parent : this; }
|
||||||
void DeAutogen( bool bCopyNoteData = true ); /* If this Steps is autogenerated, make it a real Steps. */
|
void DeAutogen( bool bCopyNoteData = true ); /* If this Steps is autogenerated, make it a real Steps. */
|
||||||
|
|||||||
Reference in New Issue
Block a user