Direct Move support has now been enabled. Minor touch-ups were also done.
This commit is contained in:
@@ -13,8 +13,6 @@
|
|||||||
/* Global variables aren't the best way to go about this, but this
|
/* Global variables aren't the best way to go about this, but this
|
||||||
* will be required to start implementing the Direct Move syntax. */
|
* will be required to start implementing the Direct Move syntax. */
|
||||||
|
|
||||||
bool KIUComplient;
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
void KSFLoader::RemoveHoles( NoteData &out, const Song &song )
|
void KSFLoader::RemoveHoles( NoteData &out, const Song &song )
|
||||||
{
|
{
|
||||||
@@ -72,8 +70,7 @@ bool KSFLoader::LoadFromKSFFile( const RString &sPath, Steps &out, const Song &s
|
|||||||
if( !msd.ReadFile( sPath ) )
|
if( !msd.ReadFile( sPath ) )
|
||||||
RageException::Throw( "Error opening file '%s'.", sPath.c_str() );
|
RageException::Throw( "Error opening file '%s'.", sPath.c_str() );
|
||||||
|
|
||||||
int iTickCount = -1; // this is the value we read for TICKCOUNT
|
m_bTickCount = -1; // this is the value we read for TICKCOUNT
|
||||||
vector<RString> asRows;
|
|
||||||
|
|
||||||
for( unsigned i=0; i<msd.GetNumValues(); i++ )
|
for( unsigned i=0; i<msd.GetNumValues(); i++ )
|
||||||
{
|
{
|
||||||
@@ -83,19 +80,17 @@ bool KSFLoader::LoadFromKSFFile( const RString &sPath, Steps &out, const Song &s
|
|||||||
// handle the data
|
// handle the data
|
||||||
if( 0==stricmp(sValueName,"TICKCOUNT") )
|
if( 0==stricmp(sValueName,"TICKCOUNT") )
|
||||||
{
|
{
|
||||||
iTickCount = atoi( sParams[1] );
|
m_bTickCount = atoi( sParams[1] );
|
||||||
if( iTickCount <= 0 )
|
if( m_bTickCount <= 0 )
|
||||||
{
|
{
|
||||||
// XXX need a place for user warnings.
|
// XXX need a place for user warnings.
|
||||||
LOG->Warn( "Invalid tick count: %d", iTickCount );
|
LOG->Warn( "Invalid tick count: %d", m_bTickCount );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( 0==stricmp(sValueName,"STEP") )
|
else if( 0==stricmp(sValueName,"STEP") )
|
||||||
{
|
{
|
||||||
RString step = sParams[1];
|
continue; //This was handled in LoadGlobalData: no need to repeat.
|
||||||
TrimLeft( step );
|
|
||||||
split( step, "\n", asRows, true );
|
|
||||||
}
|
}
|
||||||
else if( 0==stricmp(sValueName,"DIFFICULTY") )
|
else if( 0==stricmp(sValueName,"DIFFICULTY") )
|
||||||
{
|
{
|
||||||
@@ -103,10 +98,10 @@ bool KSFLoader::LoadFromKSFFile( const RString &sPath, Steps &out, const Song &s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( iTickCount == -1 )
|
if( m_bTickCount == -1 )
|
||||||
{
|
{
|
||||||
iTickCount = 2;
|
m_bTickCount = 2;
|
||||||
LOG->Warn( "\"%s\": TICKCOUNT not found; defaulting to %i", sPath.c_str(), iTickCount );
|
LOG->Warn( "\"%s\": TICKCOUNT not found; defaulting to %i", sPath.c_str(), m_bTickCount );
|
||||||
}
|
}
|
||||||
|
|
||||||
NoteData notedata; // read it into here
|
NoteData notedata; // read it into here
|
||||||
@@ -117,12 +112,13 @@ bool KSFLoader::LoadFromKSFFile( const RString &sPath, Steps &out, const Song &s
|
|||||||
sFName.MakeLower();
|
sFName.MakeLower();
|
||||||
|
|
||||||
out.SetDescription(sFName);
|
out.SetDescription(sFName);
|
||||||
if( sFName.find("crazy") != string::npos )
|
if( sFName.find("crazy") != string::npos || sFName.find("nightmare") != string::npos ||
|
||||||
|
sFName.find("crazydouble") != string::npos )
|
||||||
{
|
{
|
||||||
out.SetDifficulty( DIFFICULTY_HARD );
|
out.SetDifficulty( DIFFICULTY_HARD );
|
||||||
if( !out.GetMeter() ) out.SetMeter( 8 );
|
if( !out.GetMeter() ) out.SetMeter( 8 );
|
||||||
}
|
}
|
||||||
else if( sFName.find("hard") != string::npos )
|
else if( sFName.find("hard") != string::npos || sFName.find("freestyle") != string::npos )
|
||||||
{
|
{
|
||||||
out.SetDifficulty( DIFFICULTY_MEDIUM );
|
out.SetDifficulty( DIFFICULTY_MEDIUM );
|
||||||
if( !out.GetMeter() ) out.SetMeter( 5 );
|
if( !out.GetMeter() ) out.SetMeter( 5 );
|
||||||
@@ -161,59 +157,82 @@ bool KSFLoader::LoadFromKSFFile( const RString &sPath, Steps &out, const Song &s
|
|||||||
}
|
}
|
||||||
|
|
||||||
int iHoldStartRow[13];
|
int iHoldStartRow[13];
|
||||||
for( int t=0; t<13; t++ )
|
for( int y=0; y<13; y++ )
|
||||||
iHoldStartRow[t] = -1;
|
iHoldStartRow[y] = -1;
|
||||||
|
|
||||||
// LOG->Trace("Getting steps from %s now: 500", sPath.c_str());
|
m_bTickChangeNeeded = false;
|
||||||
|
int newTick = -1;
|
||||||
for( unsigned r=0; r<asRows.size(); r++ )
|
m_bCurBeat = 0.0f;
|
||||||
|
float prevBeat = 0.0f; // Used for hold tails.
|
||||||
|
for( unsigned r=0; r<m_bNoteRows.size(); r++ )
|
||||||
{
|
{
|
||||||
RString& sRowString = asRows[r];
|
RString& sRowString = m_bNoteRows[r];
|
||||||
StripCrnl( sRowString );
|
StripCrnl( sRowString );
|
||||||
|
|
||||||
if( sRowString == "" )
|
if( sRowString == "" )
|
||||||
continue; // skip
|
continue; // skip
|
||||||
|
|
||||||
/* All 2s indicates the end of the song. */
|
// All 2s indicates the end of the song.
|
||||||
|
/* In retrospect, we shouldn't break right away; there could be a hold
|
||||||
|
* that ends right before the terminal row. Perhaps that will be
|
||||||
|
* added in the future. */
|
||||||
if( sRowString == "2222222222222" )
|
if( sRowString == "2222222222222" )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if( sRowString.size() != 13 )
|
if( sRowString.size() != 13 )
|
||||||
{
|
{
|
||||||
if( BeginsWith(sRowString, "|T") || BeginsWith(sRowString, "|B") || BeginsWith(sRowString, "|D") )
|
if (m_bKIUCompliant)
|
||||||
{
|
{
|
||||||
LOG->Warn("File %s had Direct Move syntax %s which is currently unsupported; said part ignored",
|
LOG->Warn("File %s had Direct Move syntax (\"%s\") which can't be in KIU complient files.",
|
||||||
sPath.c_str(), sRowString.c_str());
|
sPath.c_str(), sRowString.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if( BeginsWith(sRowString, "|B") || BeginsWith(sRowString, "|D") )
|
||||||
|
{
|
||||||
|
// These don't have to be worried about here: the changes and stops were already added.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( BeginsWith(sRowString, "|T") )
|
||||||
|
{
|
||||||
|
RString temp = sRowString.substr(2,sRowString.size()-3);
|
||||||
|
newTick = atoi(temp);
|
||||||
|
m_bTickChangeNeeded = true;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG->Warn("File %s had a RowString with an improper length (\"%s\"); corrupt notes ignored",
|
LOG->Warn("File %s had a RowString with an improper length (\"%s\"); corrupt notes ignored",
|
||||||
sPath.c_str(), sRowString.c_str());
|
sPath.c_str(), sRowString.c_str());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Half-doubles is offset; "0011111100000". */
|
/* Half-doubles is offset; "0011111100000". */
|
||||||
if( out.m_StepsType == STEPS_TYPE_PUMP_HALFDOUBLE )
|
if( out.m_StepsType == STEPS_TYPE_PUMP_HALFDOUBLE )
|
||||||
sRowString.erase( 0, 2 );
|
sRowString.erase( 0, 2 );
|
||||||
|
|
||||||
// the length of a note in a row depends on TICKCOUNT
|
// Update TICKCOUNT for Direct Move files.
|
||||||
int row = (r * ROWS_PER_BEAT) / iTickCount;
|
if (m_bTickChangeNeeded)
|
||||||
|
{
|
||||||
|
m_bTickCount = newTick;
|
||||||
|
m_bTickChangeNeeded = false;
|
||||||
|
}
|
||||||
|
|
||||||
for( int t=0; t < notedata.GetNumTracks(); t++ )
|
for( int t=0; t < notedata.GetNumTracks(); t++ )
|
||||||
{
|
{
|
||||||
if( sRowString[t] == '4' )
|
if( sRowString[t] == '4' )
|
||||||
{
|
{
|
||||||
/* Remember when each hold starts; ignore the middle. */
|
/* Remember when each hold starts; ignore the middle. */
|
||||||
if( iHoldStartRow[t] == -1 )
|
if( iHoldStartRow[t] == -1 )
|
||||||
iHoldStartRow[t] = row;
|
iHoldStartRow[t] = BeatToNoteRow(m_bCurBeat);
|
||||||
|
//iHoldStartRow[t] = row;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( iHoldStartRow[t] != -1 ) // this ends the hold
|
if( iHoldStartRow[t] != -1 ) // this ends the hold
|
||||||
{
|
{
|
||||||
int iEndKSFRow = r-1;
|
int iEndRow = BeatToNoteRow(prevBeat);
|
||||||
int iEndRow = (iEndKSFRow * ROWS_PER_BEAT) / iTickCount;
|
|
||||||
if( iHoldStartRow[t] == iEndRow )
|
if( iHoldStartRow[t] == iEndRow )
|
||||||
notedata.SetTapNote( t, iHoldStartRow[t], TAP_ORIGINAL_TAP );
|
notedata.SetTapNote( t, iHoldStartRow[t], TAP_ORIGINAL_TAP );
|
||||||
else
|
else
|
||||||
@@ -232,8 +251,12 @@ bool KSFLoader::LoadFromKSFFile( const RString &sPath, Steps &out, const Song &s
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
notedata.SetTapNote(t, row, tap);
|
//notedata.SetTapNote(t, row, tap);
|
||||||
|
notedata.SetTapNote(t, BeatToNoteRow(m_bCurBeat), tap); // More accurate for taps.
|
||||||
}
|
}
|
||||||
|
prevBeat = m_bCurBeat;
|
||||||
|
m_bCurBeat = prevBeat + 1.0f / m_bTickCount;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We need to remove holes where the BPM increases. */
|
/* We need to remove holes where the BPM increases. */
|
||||||
@@ -264,7 +287,8 @@ void KSFLoader::LoadTags( const RString &str, Song &out )
|
|||||||
!stricmp(asBits[2], "easy") ||
|
!stricmp(asBits[2], "easy") ||
|
||||||
!stricmp(asBits[2], "normal") ||
|
!stricmp(asBits[2], "normal") ||
|
||||||
!stricmp(asBits[2], "hard") ||
|
!stricmp(asBits[2], "hard") ||
|
||||||
!stricmp(asBits[2], "crazy")) )
|
!stricmp(asBits[2], "crazy") ||
|
||||||
|
!stricmp(asBits[2], "nightmare")) )
|
||||||
{
|
{
|
||||||
asBits.erase( asBits.begin()+2, asBits.begin()+3 );
|
asBits.erase( asBits.begin()+2, asBits.begin()+3 );
|
||||||
}
|
}
|
||||||
@@ -299,9 +323,9 @@ bool KSFLoader::LoadGlobalData( const RString &sPath, Song &out )
|
|||||||
RageException::Throw( "Error opening file \"%s\": %s", sPath.c_str(), msd.GetError().c_str() );
|
RageException::Throw( "Error opening file \"%s\": %s", sPath.c_str(), msd.GetError().c_str() );
|
||||||
|
|
||||||
float SMGap1 = 0, SMGap2 = 0, BPM1 = -1, BPMPos2 = -1, BPM2 = -1, BPMPos3 = -1, BPM3 = -1;
|
float SMGap1 = 0, SMGap2 = 0, BPM1 = -1, BPMPos2 = -1, BPM2 = -1, BPMPos3 = -1, BPM3 = -1;
|
||||||
KIUComplient = false;
|
int m_bTickCount = -1;
|
||||||
|
m_bKIUCompliant = false;
|
||||||
// LOG->Trace("Getting tags for %s now: 300", sPath.c_str());
|
RString theSteps;
|
||||||
|
|
||||||
for( unsigned i=0; i < msd.GetNumValues(); i++ )
|
for( unsigned i=0; i < msd.GetNumValues(); i++ )
|
||||||
{
|
{
|
||||||
@@ -318,22 +342,22 @@ bool KSFLoader::LoadGlobalData( const RString &sPath, Song &out )
|
|||||||
}
|
}
|
||||||
else if( 0==stricmp(sValueName,"BPM2") )
|
else if( 0==stricmp(sValueName,"BPM2") )
|
||||||
{
|
{
|
||||||
KIUComplient = true;
|
m_bKIUCompliant = true;
|
||||||
BPM2 = StringToFloat( sParams[1] );
|
BPM2 = StringToFloat( sParams[1] );
|
||||||
}
|
}
|
||||||
else if( 0==stricmp(sValueName,"BPM3") )
|
else if( 0==stricmp(sValueName,"BPM3") )
|
||||||
{
|
{
|
||||||
KIUComplient = true;
|
m_bKIUCompliant = true;
|
||||||
BPM3 = StringToFloat( sParams[1] );
|
BPM3 = StringToFloat( sParams[1] );
|
||||||
}
|
}
|
||||||
else if( 0==stricmp(sValueName,"BUNKI") )
|
else if( 0==stricmp(sValueName,"BUNKI") )
|
||||||
{
|
{
|
||||||
KIUComplient = true;
|
m_bKIUCompliant = true;
|
||||||
BPMPos2 = StringToFloat( sParams[1] ) / 100.0f;
|
BPMPos2 = StringToFloat( sParams[1] ) / 100.0f;
|
||||||
}
|
}
|
||||||
else if( 0==stricmp(sValueName,"BUNKI2") )
|
else if( 0==stricmp(sValueName,"BUNKI2") )
|
||||||
{
|
{
|
||||||
KIUComplient = true;
|
m_bKIUCompliant = true;
|
||||||
BPMPos3 = StringToFloat( sParams[1] ) / 100.0f;
|
BPMPos3 = StringToFloat( sParams[1] ) / 100.0f;
|
||||||
}
|
}
|
||||||
else if( 0==stricmp(sValueName,"STARTTIME") )
|
else if( 0==stricmp(sValueName,"STARTTIME") )
|
||||||
@@ -341,23 +365,36 @@ bool KSFLoader::LoadGlobalData( const RString &sPath, Song &out )
|
|||||||
SMGap1 = -StringToFloat( sParams[1] )/100;
|
SMGap1 = -StringToFloat( sParams[1] )/100;
|
||||||
out.m_Timing.m_fBeat0OffsetInSeconds = SMGap1;
|
out.m_Timing.m_fBeat0OffsetInSeconds = SMGap1;
|
||||||
}
|
}
|
||||||
// This is currently required for more accurate BPM changes.
|
// This is currently required for more accurate KIU BPM changes.
|
||||||
else if( 0==stricmp(sValueName,"STARTTIME2") )
|
else if( 0==stricmp(sValueName,"STARTTIME2") )
|
||||||
{
|
{
|
||||||
KIUComplient = true;
|
m_bKIUCompliant = true;
|
||||||
SMGap2 = -StringToFloat( sParams[1] )/100;
|
SMGap2 = -StringToFloat( sParams[1] )/100;
|
||||||
}
|
}
|
||||||
else if ( 0==stricmp(sValueName,"STARTTIME3") )
|
else if ( 0==stricmp(sValueName,"STARTTIME3") )
|
||||||
{
|
{
|
||||||
// STARTTIME3 only ensures this is a KIU complient simfile.
|
// STARTTIME3 only ensures this is a KIU complient simfile.
|
||||||
KIUComplient = true;
|
m_bKIUCompliant = true;
|
||||||
}
|
}
|
||||||
else if( 0==stricmp(sValueName,"TICKCOUNT") ||
|
else if ( 0==stricmp(sValueName,"TICKCOUNT") )
|
||||||
0==stricmp(sValueName,"STEP") ||
|
|
||||||
0==stricmp(sValueName,"DIFFICULTY"))
|
|
||||||
{
|
{
|
||||||
/* TICKCOUNT, STEP, and DIFFICULTY are handled in LoadFromKSFFile.
|
/* TICKCOUNT is will be used if there are DM complient BPM changes and stops.
|
||||||
* Do not warn for them. */
|
* It will be called again in LoadFromKSFFile for the actual steps. */
|
||||||
|
m_bTickCount = atoi( sParams[1] );
|
||||||
|
m_bTickCount = m_bTickCount > 0 ? m_bTickCount : 2;
|
||||||
|
}
|
||||||
|
else if ( 0==stricmp(sValueName,"STEP") )
|
||||||
|
{
|
||||||
|
/* STEP will always be the last header in a KSF file by design. Due to
|
||||||
|
* the Direct Move syntax, it is best to get the rows of notes here. */
|
||||||
|
theSteps = sParams[1];
|
||||||
|
TrimLeft( theSteps );
|
||||||
|
split( theSteps, "\n", m_bNoteRows, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
else if( 0==stricmp(sValueName,"DIFFICULTY"))
|
||||||
|
{
|
||||||
|
/* DIFFICULTY is handled only in LoadFromKSFFile. Ignore it here. */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -370,7 +407,7 @@ bool KSFLoader::LoadGlobalData( const RString &sPath, Song &out )
|
|||||||
* syntax. Unfortunately, they will require a further scan in order to determine
|
* syntax. Unfortunately, they will require a further scan in order to determine
|
||||||
* whether or not there are changes, or even stops, within the file. That will be
|
* whether or not there are changes, or even stops, within the file. That will be
|
||||||
* implemented later. */
|
* implemented later. */
|
||||||
if (KIUComplient)
|
if (m_bKIUCompliant)
|
||||||
{
|
{
|
||||||
if( BPM2 > 0 && BPMPos2 > 0 )
|
if( BPM2 > 0 && BPMPos2 > 0 )
|
||||||
{
|
{
|
||||||
@@ -392,6 +429,90 @@ bool KSFLoader::LoadGlobalData( const RString &sPath, Song &out )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int tickToChange = m_bTickCount;
|
||||||
|
m_bCurBeat = 0.0f;
|
||||||
|
float speedToChange = 0.0f, timeToStop = 0.0f;
|
||||||
|
m_bDMRequired = m_bBPMChangeNeeded = m_bBPMStopNeeded = m_bTickChangeNeeded = false;
|
||||||
|
|
||||||
|
for (unsigned i=0; i < m_bNoteRows.size(); i++)
|
||||||
|
{
|
||||||
|
RString& NoteRowString = m_bNoteRows[i];
|
||||||
|
StripCrnl( NoteRowString );
|
||||||
|
|
||||||
|
if( NoteRowString == "" )
|
||||||
|
continue; // Empty rows do us no good.
|
||||||
|
|
||||||
|
if( NoteRowString == "2222222222222" ) // Row of 2s = end. Confirm KIUCompliency here.
|
||||||
|
{
|
||||||
|
if (!m_bDMRequired)
|
||||||
|
m_bKIUCompliant = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is where the DMRequired test will take place. */
|
||||||
|
if( NoteRowString.size() != 13)
|
||||||
|
{
|
||||||
|
if (BeginsWith(NoteRowString, "|T") ||
|
||||||
|
BeginsWith(NoteRowString, "|B") || BeginsWith(NoteRowString, "|D") )
|
||||||
|
{
|
||||||
|
m_bDMRequired = true;
|
||||||
|
RString temp = NoteRowString.substr(2,NoteRowString.size()-3);
|
||||||
|
float numTemp = StringToFloat(temp);
|
||||||
|
if (BeginsWith(NoteRowString, "|T"))
|
||||||
|
{
|
||||||
|
m_bTickChangeNeeded = true;
|
||||||
|
tickToChange = (int)numTemp;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (BeginsWith(NoteRowString, "|B"))
|
||||||
|
{
|
||||||
|
m_bBPMChangeNeeded = true;
|
||||||
|
speedToChange = numTemp;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_bBPMStopNeeded = true;
|
||||||
|
timeToStop = numTemp / 1000.0f;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Quit while we're ahead if any bad syntax is spotted. */
|
||||||
|
LOG->Warn("File %s has a RowString which matches no known syntax rules (\"%s\"); bad file",
|
||||||
|
sPath.c_str(), NoteRowString.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_bTickChangeNeeded)
|
||||||
|
{
|
||||||
|
m_bTickCount = tickToChange;
|
||||||
|
m_bTickChangeNeeded = false;
|
||||||
|
}
|
||||||
|
if (m_bBPMChangeNeeded)
|
||||||
|
{
|
||||||
|
out.AddBPMSegment(BPMSegment(BeatToNoteRow(m_bCurBeat),speedToChange));
|
||||||
|
m_bBPMChangeNeeded = false;
|
||||||
|
}
|
||||||
|
if (m_bBPMStopNeeded)
|
||||||
|
{
|
||||||
|
out.AddStopSegment(StopSegment(BeatToNoteRow(m_bCurBeat),timeToStop));
|
||||||
|
m_bBPMStopNeeded = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_bCurBeat += 1.0f / m_bTickCount;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//if (m_bDMRequired)
|
||||||
|
// LOG->Warn("%s uses the Direct Move syntax; at this point, mileage may vary.", sPath.c_str());
|
||||||
|
|
||||||
/* Try to fill in missing bits of information from the pathname. */
|
/* Try to fill in missing bits of information from the pathname. */
|
||||||
{
|
{
|
||||||
vector<RString> asBits;
|
vector<RString> asBits;
|
||||||
|
|||||||
@@ -20,6 +20,16 @@ public:
|
|||||||
void GetApplicableFiles( const RString &sPath, vector<RString> &out );
|
void GetApplicableFiles( const RString &sPath, vector<RString> &out );
|
||||||
bool LoadFromDir( const RString &sDir, Song &out );
|
bool LoadFromDir( const RString &sDir, Song &out );
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_bKIUCompliant;
|
||||||
|
bool m_bDMRequired;
|
||||||
|
bool m_bBPMChangeNeeded;
|
||||||
|
bool m_bBPMStopNeeded;
|
||||||
|
bool m_bTickChangeNeeded;
|
||||||
|
int m_bTickCount;
|
||||||
|
float m_bCurBeat;
|
||||||
|
vector<RString> m_bNoteRows;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user