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
|
||||
"NoteData.cpp"
|
||||
"NoteDataUtil.cpp"
|
||||
"NoteDataWithScoring.cpp")
|
||||
"NoteDataWithScoring.cpp"
|
||||
"ColumnCues.cpp")
|
||||
|
||||
list(APPEND SM_DATA_NOTEDATA_HPP
|
||||
"NoteData.h"
|
||||
"NoteDataUtil.h"
|
||||
"NoteDataWithScoring.h")
|
||||
"NoteDataWithScoring.h"
|
||||
"ColumnCues.h")
|
||||
|
||||
source_group("Data Structures\\\\Note Data"
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
#include "LuaBinding.h"
|
||||
@@ -799,6 +813,50 @@ public:
|
||||
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()
|
||||
{
|
||||
ADD_METHOD( GetAuthorCredit );
|
||||
@@ -824,6 +882,7 @@ public:
|
||||
ADD_METHOD( IsDisplayBpmRandom );
|
||||
ADD_METHOD( PredictMeter );
|
||||
ADD_METHOD( GetDisplayBPMType );
|
||||
ADD_METHOD( GetColumnCues );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "Difficulty.h"
|
||||
#include "RageUtil_AutoPtr.h"
|
||||
#include "TimingData.h"
|
||||
#include "ColumnCues.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
@@ -210,6 +211,8 @@ public:
|
||||
{
|
||||
return join(":", this->m_sAttackString);
|
||||
}
|
||||
|
||||
std::vector<ColumnCue> GetColumnCues(float minDuration);
|
||||
|
||||
private:
|
||||
inline const Steps *Real() const { return parent ? parent : this; }
|
||||
|
||||
Reference in New Issue
Block a user