stage 3 of TimingData changes: changed external interface, enforce encapsulation more strictly

This commit is contained in:
Mark Cannon
2011-09-15 03:28:58 +00:00
parent c85f1f7053
commit 8099e25dcc
21 changed files with 1248 additions and 1720 deletions
+50 -53
View File
@@ -267,28 +267,29 @@ void AdjustSync::AutosyncTempo()
GAMESTATE->m_pCurSong->m_SongTiming.m_fBeat0OffsetInSeconds += fIntercept; GAMESTATE->m_pCurSong->m_SongTiming.m_fBeat0OffsetInSeconds += fIntercept;
const float fScaleBPM = 1.0f/(1.0f - fSlope); const float fScaleBPM = 1.0f/(1.0f - fSlope);
TimingData &timing = GAMESTATE->m_pCurSong->m_SongTiming; TimingData &timing = GAMESTATE->m_pCurSong->m_SongTiming;
vector<TimingSegment *> &bpms = timing.m_avpTimingSegments[SEGMENT_BPM];
const vector<TimingSegment *> &bpms = timing.GetTimingSegments(SEGMENT_BPM);
for (unsigned i = 0; i < bpms.size(); i++) for (unsigned i = 0; i < bpms.size(); i++)
{ {
BPMSegment *b = static_cast<BPMSegment *>(bpms[i]); const BPMSegment *b = ToBPM( bpms[i] );
b->SetBPM(b->GetBPM() * fScaleBPM); timing.AddSegment( BPMSegment(b->GetRow(), b->GetBPM() * fScaleBPM) );
} }
/* We assume that the stops were measured as a number of beats. /* We assume that the stops were measured as a number of beats.
* Therefore, if we change the bpms, we need to make a similar * Therefore, if we change the bpms, we need to make a similar
* change to the stops. */ * change to the stops. */
vector<TimingSegment *> &stops = timing.m_avpTimingSegments[SEGMENT_STOP]; const vector<TimingSegment *> &stops = timing.GetTimingSegments(SEGMENT_STOP);
for (unsigned i = 0; i < stops.size(); i++) for (unsigned i = 0; i < stops.size(); i++)
{ {
StopSegment *s = static_cast<StopSegment *>(stops[i]); const StopSegment *s = ToStop( stops[i] );
s->SetPause(s->GetPause() * (1.0f - fSlope)); timing.AddSegment( StopSegment(s->GetRow(), s->GetPause() * (1.0f - fSlope)) );
} }
// Do the same for delays. // Do the same for delays.
vector<TimingSegment *> &delays = timing.m_avpTimingSegments[SEGMENT_DELAY]; const vector<TimingSegment *> &delays = timing.GetTimingSegments(SEGMENT_DELAY);
for (unsigned i = 0; i < delays.size(); i++) for (unsigned i = 0; i < delays.size(); i++)
{ {
DelaySegment *s = static_cast<DelaySegment *>(delays[i]); const DelaySegment *s = ToDelay( delays[i] );
s->SetPause(s->GetPause() * (1.0f - fSlope)); timing.AddSegment( DelaySegment(s->GetRow(), s->GetPause() * (1.0f - fSlope)) );
} }
SCREENMAN->SystemMessage( AUTOSYNC_CORRECTION_APPLIED.GetValue() ); SCREENMAN->SystemMessage( AUTOSYNC_CORRECTION_APPLIED.GetValue() );
@@ -336,12 +337,13 @@ void AdjustSync::GetSyncChangeTextGlobal( vector<RString> &vsAddTo )
} }
} }
// XXX: needs cleanup still -- vyhd
void AdjustSync::GetSyncChangeTextSong( vector<RString> &vsAddTo ) void AdjustSync::GetSyncChangeTextSong( vector<RString> &vsAddTo )
{ {
if( GAMESTATE->m_pCurSong.Get() ) if( GAMESTATE->m_pCurSong.Get() )
{ {
unsigned int iOriginalSize = vsAddTo.size(); unsigned int iOriginalSize = vsAddTo.size();
TimingData original = s_vpTimingDataOriginal[0]; TimingData &original = s_vpTimingDataOriginal[0];
TimingData &testing = GAMESTATE->m_pCurSong->m_SongTiming; TimingData &testing = GAMESTATE->m_pCurSong->m_SongTiming;
{ {
@@ -359,79 +361,74 @@ void AdjustSync::GetSyncChangeTextSong( vector<RString> &vsAddTo )
} }
} }
vector<TimingSegment *> &bpmTest = testing.m_avpTimingSegments[SEGMENT_BPM]; const vector<TimingSegment *> &bpmTest = testing.GetTimingSegments(SEGMENT_BPM);
vector<TimingSegment *> &bpmOrig = original.m_avpTimingSegments[SEGMENT_BPM]; const vector<TimingSegment *> &bpmOrig = original.GetTimingSegments(SEGMENT_BPM);
for( unsigned i=0; i< bpmTest.size(); i++ ) for( unsigned i=0; i< bpmTest.size(); i++ )
{ {
BPMSegment *bT = static_cast<BPMSegment *>(bpmTest[i]); float fNew = Quantize( ToBPM(bpmTest[i])->GetBPM(), 0.001f );
BPMSegment *bO = static_cast<BPMSegment *>(bpmOrig[i]); float fOld = Quantize( ToBPM(bpmOrig[i])->GetBPM(), 0.001f );
float fOld = Quantize( bO->GetBPM(), 0.001f );
float fNew = Quantize( bT->GetBPM(), 0.001f ); if( fabsf(fNew - fOld) < 1e-4 )
float fDelta = fNew - fOld; continue;
if( fabsf(fDelta) > 0.0001f )
{
if ( i >= 4 ) if ( i >= 4 )
{ {
vsAddTo.push_back(ETC.GetValue()); vsAddTo.push_back(ETC.GetValue());
break; break;
} }
vsAddTo.push_back( ssprintf(
TEMPO_SEGMENT_FROM.GetValue(), RString s = ssprintf( TEMPO_SEGMENT_FROM.GetValue(),
FormatNumberAndSuffix(i+1).c_str(), FormatNumberAndSuffix(i+1).c_str(), fOld, fNew );
fOld,
fNew ) ); vsAddTo.push_back( s );
}
} }
vector<TimingSegment *> &stopTest = testing.m_avpTimingSegments[SEGMENT_STOP]; const vector<TimingSegment *> &stopTest = testing.GetTimingSegments(SEGMENT_STOP);
vector<TimingSegment *> &stopOrig = original.m_avpTimingSegments[SEGMENT_STOP]; const vector<TimingSegment *> &stopOrig = original.GetTimingSegments(SEGMENT_STOP);
for( unsigned i=0; i< stopTest.size(); i++ ) for( unsigned i=0; i< stopTest.size(); i++ )
{ {
StopSegment *sT = static_cast<StopSegment *>(stopTest[i]); float fOld = Quantize( ToStop(stopOrig[i])->GetPause(), 0.001f );
StopSegment *sO = static_cast<StopSegment *>(stopOrig[i]); float fNew = Quantize( ToStop(stopTest[i])->GetPause(), 0.001f );
float fOld = Quantize( sO->GetPause(), 0.001f );
float fNew = Quantize( sT->GetPause(), 0.001f );
float fDelta = fNew - fOld; float fDelta = fNew - fOld;
if( fabsf(fDelta) > 0.0001f ) if( fabsf(fDelta) < 1e-4 )
{ continue;
if ( i >= 4 ) if ( i >= 4 )
{ {
vsAddTo.push_back(ETC.GetValue()); vsAddTo.push_back(ETC.GetValue());
break; break;
} }
vsAddTo.push_back( ssprintf(
CHANGED_STOP.GetValue(), RString s = ssprintf( CHANGED_STOP.GetValue(), i+1, fOld, fNew, fDelta );
i+1, vsAddTo.push_back( s );
fOld,
fNew ) );
}
} }
vector<TimingSegment *> &delyTest = testing.m_avpTimingSegments[SEGMENT_DELAY]; const vector<TimingSegment *> &delyTest = testing.GetTimingSegments(SEGMENT_DELAY);
vector<TimingSegment *> &delyOrig = original.m_avpTimingSegments[SEGMENT_DELAY]; const vector<TimingSegment *> &delyOrig = original.GetTimingSegments(SEGMENT_DELAY);
for( unsigned i=0; i< delyTest.size(); i++ ) for( unsigned i=0; i< delyTest.size(); i++ )
{ {
DelaySegment *sT = static_cast<DelaySegment *>(delyTest[i]); if( delyTest[i] == delyOrig[i] )
DelaySegment *sO = static_cast<DelaySegment *>(delyOrig[i]); continue;
float fOld = Quantize( sO->GetPause(), 0.001f );
float fNew = Quantize( sT->GetPause(), 0.001f ); float fOld = Quantize( ToDelay(delyOrig[i])->GetPause(), 0.001f );
float fNew = Quantize( ToDelay(delyTest[i])->GetPause(), 0.001f );
float fDelta = fNew - fOld; float fDelta = fNew - fOld;
if( fabsf(fDelta) > 0.0001f ) if( fabsf(fDelta) < 1e-4 )
{ continue;
if ( i >= 4 ) if ( i >= 4 )
{ {
vsAddTo.push_back(ETC.GetValue()); vsAddTo.push_back(ETC.GetValue());
break; break;
} }
vsAddTo.push_back( ssprintf(
CHANGED_STOP.GetValue(), RString s = ssprintf( CHANGED_STOP.GetValue(),
i+1, i+1, fOld, fNew, fDelta );
fOld, vsAddTo.push_back( s );
fNew ) );
}
} }
if( vsAddTo.size() > iOriginalSize && s_fAverageError > 0.0f ) if( vsAddTo.size() > iOriginalSize && s_fAverageError > 0.0f )
+2 -2
View File
@@ -421,7 +421,7 @@ void BackgroundImpl::LoadFromRandom( float fFirstBeat, float fEndBeat, const Bac
const TimingData &timing = m_pSong->m_SongTiming; const TimingData &timing = m_pSong->m_SongTiming;
// change BG every time signature change or 4 measures // change BG every time signature change or 4 measures
const vector<TimingSegment *> &tSigs = timing.m_avpTimingSegments[SEGMENT_TIME_SIG]; const vector<TimingSegment *> &tSigs = timing.GetTimingSegments(SEGMENT_TIME_SIG);
for (unsigned i = 0; i < tSigs.size(); i++) for (unsigned i = 0; i < tSigs.size(); i++)
{ {
@@ -448,7 +448,7 @@ void BackgroundImpl::LoadFromRandom( float fFirstBeat, float fEndBeat, const Bac
} }
// change BG every BPM change that is at the beginning of a measure // change BG every BPM change that is at the beginning of a measure
const vector<TimingSegment *> &bpms = timing.m_avpTimingSegments[SEGMENT_BPM]; const vector<TimingSegment *> &bpms = timing.GetTimingSegments(SEGMENT_BPM);
for( unsigned i=0; i<bpms.size(); i++ ) for( unsigned i=0; i<bpms.size(); i++ )
{ {
bool bAtBeginningOfMeasure = false; bool bAtBeginningOfMeasure = false;
+2 -2
View File
@@ -60,8 +60,8 @@ struct MusicPlaying
RageSound *m_Music; RageSound *m_Music;
MusicPlaying( RageSound *Music ) MusicPlaying( RageSound *Music )
{ {
m_Timing.AddSegment( SEGMENT_BPM, new BPMSegment(0,120) ); m_Timing.AddSegment( BPMSegment(0,120) );
m_NewTiming.AddSegment( SEGMENT_BPM, new BPMSegment(0,120) ); m_NewTiming.AddSegment( BPMSegment(0,120) );
m_bHasTiming = false; m_bHasTiming = false;
m_bTimingDelayed = false; m_bTimingDelayed = false;
m_bApplyMusicRate = false; m_bApplyMusicRate = false;
+29 -25
View File
@@ -822,16 +822,20 @@ void NoteField::DrawPrimitives()
} }
const TimingData *pTiming = &m_pPlayerState->GetDisplayedTiming(); const TimingData *pTiming = &m_pPlayerState->GetDisplayedTiming();
const vector<TimingSegment *> *segs = pTiming->m_avpTimingSegments; const vector<TimingSegment*>* segs[NUM_TimingSegmentType];
FOREACH_TimingSegmentType( tst )
segs[tst] = &(pTiming->GetTimingSegments(tst));
unsigned i = 0; unsigned i = 0;
// Draw beat bars // Draw beat bars
if( ( GAMESTATE->IsEditing() || SHOW_BEAT_BARS ) && pTiming != NULL ) if( ( GAMESTATE->IsEditing() || SHOW_BEAT_BARS ) && pTiming != NULL )
{ {
const vector<TimingSegment *> &tSigs = segs[SEGMENT_TIME_SIG]; const vector<TimingSegment *> &tSigs = *segs[SEGMENT_TIME_SIG];
int iMeasureIndex = 0; int iMeasureIndex = 0;
for (i = 0; i < tSigs.size(); i++) for (i = 0; i < tSigs.size(); i++)
{ {
TimeSignatureSegment *ts = static_cast<TimeSignatureSegment *>(tSigs[i]); const TimeSignatureSegment *ts = ToTimeSignature(tSigs[i]);
int iSegmentEndRow = (i + 1 == tSigs.size()) ? iLastRowToDraw : tSigs[i+1]->GetRow(); int iSegmentEndRow = (i + 1 == tSigs.size()) ? iLastRowToDraw : tSigs[i+1]->GetRow();
// beat bars every 16th note // beat bars every 16th note
@@ -874,9 +878,9 @@ void NoteField::DrawPrimitives()
// Scroll text // Scroll text
if( GAMESTATE->m_bIsUsingStepTiming ) if( GAMESTATE->m_bIsUsingStepTiming )
{ {
for (i = 0; i < segs[SEGMENT_SCROLL].size(); i++) for (i = 0; i < segs[SEGMENT_SCROLL]->size(); i++)
{ {
ScrollSegment *seg = static_cast<ScrollSegment *>(segs[SEGMENT_SCROLL][i]); ScrollSegment *seg = ToScroll( segs[SEGMENT_SCROLL]->at(i) );
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw ) if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
{ {
float fBeat = seg->GetBeat(); float fBeat = seg->GetBeat();
@@ -887,9 +891,9 @@ void NoteField::DrawPrimitives()
} }
// BPM text // BPM text
for (i = 0; i < segs[SEGMENT_BPM].size(); i++) for (i = 0; i < segs[SEGMENT_BPM]->size(); i++)
{ {
BPMSegment *seg = static_cast<BPMSegment *>(segs[SEGMENT_BPM][i]); const BPMSegment *seg = ToBPM( segs[SEGMENT_BPM]->at(i) );
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw ) if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
{ {
float fBeat = seg->GetBeat(); float fBeat = seg->GetBeat();
@@ -899,9 +903,9 @@ void NoteField::DrawPrimitives()
} }
// Freeze text // Freeze text
for (i = 0; i < segs[SEGMENT_STOP].size(); i++) for (i = 0; i < segs[SEGMENT_STOP]->size(); i++)
{ {
StopSegment *seg = static_cast<StopSegment *>(segs[SEGMENT_STOP][i]); const StopSegment *seg = ToStop( segs[SEGMENT_STOP]->at(i) );
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw ) if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
{ {
float fBeat = seg->GetBeat(); float fBeat = seg->GetBeat();
@@ -911,9 +915,9 @@ void NoteField::DrawPrimitives()
} }
// Delay text // Delay text
for (i = 0; i < segs[SEGMENT_DELAY].size(); i++) for (i = 0; i < segs[SEGMENT_DELAY]->size(); i++)
{ {
DelaySegment *seg = static_cast<DelaySegment *>(segs[SEGMENT_DELAY][i]); const DelaySegment *seg = ToDelay( segs[SEGMENT_DELAY]->at(i) );
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw ) if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
{ {
float fBeat = seg->GetBeat(); float fBeat = seg->GetBeat();
@@ -923,9 +927,9 @@ void NoteField::DrawPrimitives()
} }
// Warp text // Warp text
for (i = 0; i < segs[SEGMENT_WARP].size(); i++) for (i = 0; i < segs[SEGMENT_WARP]->size(); i++)
{ {
WarpSegment *seg = static_cast<WarpSegment *>(segs[SEGMENT_WARP][i]); const WarpSegment *seg = ToWarp( segs[SEGMENT_WARP]->at(i) );
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw ) if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
{ {
float fBeat = seg->GetBeat(); float fBeat = seg->GetBeat();
@@ -935,9 +939,9 @@ void NoteField::DrawPrimitives()
} }
// Time Signature text // Time Signature text
for (i = 0; i < segs[SEGMENT_TIME_SIG].size(); i++) for (i = 0; i < segs[SEGMENT_TIME_SIG]->size(); i++)
{ {
TimeSignatureSegment *seg = static_cast<TimeSignatureSegment *>(segs[SEGMENT_TIME_SIG][i]); const TimeSignatureSegment *seg = ToTimeSignature( segs[SEGMENT_TIME_SIG]->at(i) );
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw ) if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
{ {
float fBeat = seg->GetBeat(); float fBeat = seg->GetBeat();
@@ -947,9 +951,9 @@ void NoteField::DrawPrimitives()
} }
// Tickcount text // Tickcount text
for (i = 0; i < segs[SEGMENT_TICKCOUNT].size(); i++) for (i = 0; i < segs[SEGMENT_TICKCOUNT]->size(); i++)
{ {
TickcountSegment *seg = static_cast<TickcountSegment *>(segs[SEGMENT_TICKCOUNT][i]); const TickcountSegment *seg = ToTickcount( segs[SEGMENT_TICKCOUNT]->at(i) );
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw ) if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
{ {
float fBeat = seg->GetBeat(); float fBeat = seg->GetBeat();
@@ -959,9 +963,9 @@ void NoteField::DrawPrimitives()
} }
// Combo text // Combo text
for (i = 0; i < segs[SEGMENT_COMBO].size(); i++) for (i = 0; i < segs[SEGMENT_COMBO]->size(); i++)
{ {
ComboSegment *seg = static_cast<ComboSegment *>(segs[SEGMENT_COMBO][i]); const ComboSegment *seg = ToCombo( segs[SEGMENT_COMBO]->at(i) );
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw ) if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
{ {
float fBeat = seg->GetBeat(); float fBeat = seg->GetBeat();
@@ -971,9 +975,9 @@ void NoteField::DrawPrimitives()
} }
// Label text // Label text
for (i = 0; i < segs[SEGMENT_LABEL].size(); i++) for (i = 0; i < segs[SEGMENT_LABEL]->size(); i++)
{ {
LabelSegment *seg = static_cast<LabelSegment *>(segs[SEGMENT_LABEL][i]); const LabelSegment *seg = ToLabel( segs[SEGMENT_LABEL]->at(i) );
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw ) if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
{ {
float fBeat = seg->GetBeat(); float fBeat = seg->GetBeat();
@@ -983,9 +987,9 @@ void NoteField::DrawPrimitives()
} }
// Speed text // Speed text
for (i = 0; i < segs[SEGMENT_SPEED].size(); i++) for (i = 0; i < segs[SEGMENT_SPEED]->size(); i++)
{ {
SpeedSegment *seg = static_cast<SpeedSegment *>(segs[SEGMENT_SPEED][i]); const SpeedSegment *seg = ToSpeed( segs[SEGMENT_SPEED]->at(i) );
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw ) if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
{ {
float fBeat = seg->GetBeat(); float fBeat = seg->GetBeat();
@@ -996,9 +1000,9 @@ void NoteField::DrawPrimitives()
} }
// Fake text // Fake text
for (i = 0; i < segs[SEGMENT_FAKE].size(); i++) for (i = 0; i < segs[SEGMENT_FAKE]->size(); i++)
{ {
FakeSegment *seg = static_cast<FakeSegment *>(segs[SEGMENT_FAKE][i]); const FakeSegment *seg = ToFake( segs[SEGMENT_FAKE]->at(i) );
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw ) if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
{ {
float fBeat = seg->GetBeat(); float fBeat = seg->GetBeat();
+9 -18
View File
@@ -586,19 +586,15 @@ bool DWILoader::LoadFromDir( const RString &sPath_, Song &out, set<RString> &Bla
{ {
const float fBPM = StringToFloat( sParams[1] ); const float fBPM = StringToFloat( sParams[1] );
if( PREFSMAN->m_bQuirksMode ) if( unlikely(fBPM <= 0.0f && !PREFSMAN->m_bQuirksMode) )
{ {
out.m_SongTiming.AddSegment( SEGMENT_BPM, new BPMSegment(0, fBPM) ); LOG->UserLog("Song file", sPath, "has an invalid BPM change at beat %f, BPM %f.",
}
else{
if( fBPM > 0.0f )
out.m_SongTiming.AddSegment( SEGMENT_BPM, new BPMSegment(0, fBPM) );
else
LOG->UserLog("Song file",
sPath,
"has an invalid BPM change at beat %f, BPM %f.",
0.0f, fBPM ); 0.0f, fBPM );
} }
else
{
out.m_SongTiming.AddSegment( BPMSegment(0, fBPM) );
}
} }
else if( sValueName.EqualsNoCase("DISPLAYBPM") ) else if( sValueName.EqualsNoCase("DISPLAYBPM") )
{ {
@@ -626,7 +622,7 @@ bool DWILoader::LoadFromDir( const RString &sPath_, Song &out, set<RString> &Bla
else if( sValueName.EqualsNoCase("GAP") ) else if( sValueName.EqualsNoCase("GAP") )
// the units of GAP is 1/1000 second // the units of GAP is 1/1000 second
out.m_SongTiming.m_fBeat0OffsetInSeconds = -StringToInt( sParams[1] ) / 1000.0f; out.m_SongTiming.m_fBeat0OffsetInSeconds = -StringToInt(sParams[1]) / 1000.0f;
else if( sValueName.EqualsNoCase("SAMPLESTART") ) else if( sValueName.EqualsNoCase("SAMPLESTART") )
out.m_fMusicSampleStartSeconds = ParseBrokenDWITimestamp(sParams[1], sParams[2], sParams[3]); out.m_fMusicSampleStartSeconds = ParseBrokenDWITimestamp(sParams[1], sParams[2], sParams[3]);
@@ -651,7 +647,7 @@ bool DWILoader::LoadFromDir( const RString &sPath_, Song &out, set<RString> &Bla
int iFreezeRow = BeatToNoteRow( StringToFloat(arrayFreezeValues[0]) / 4.0f ); int iFreezeRow = BeatToNoteRow( StringToFloat(arrayFreezeValues[0]) / 4.0f );
float fFreezeSeconds = StringToFloat( arrayFreezeValues[1] ) / 1000.0f; float fFreezeSeconds = StringToFloat( arrayFreezeValues[1] ) / 1000.0f;
out.m_SongTiming.AddSegment( SEGMENT_STOP, new StopSegment(iFreezeRow, fFreezeSeconds) ); out.m_SongTiming.AddSegment( StopSegment(iFreezeRow, fFreezeSeconds) );
// LOG->Trace( "Adding a freeze segment: beat: %f, seconds = %f", fFreezeBeat, fFreezeSeconds ); // LOG->Trace( "Adding a freeze segment: beat: %f, seconds = %f", fFreezeBeat, fFreezeSeconds );
} }
} }
@@ -674,17 +670,12 @@ bool DWILoader::LoadFromDir( const RString &sPath_, Song &out, set<RString> &Bla
int iStartIndex = BeatToNoteRow( StringToFloat(arrayBPMChangeValues[0]) / 4.0f ); int iStartIndex = BeatToNoteRow( StringToFloat(arrayBPMChangeValues[0]) / 4.0f );
float fBPM = StringToFloat( arrayBPMChangeValues[1] ); float fBPM = StringToFloat( arrayBPMChangeValues[1] );
if( fBPM > 0.0f ) if( fBPM > 0.0f )
{ out.m_SongTiming.AddSegment( BPMSegment(iStartIndex, fBPM) );
BPMSegment * bs = new BPMSegment( iStartIndex, fBPM );
out.m_SongTiming.AddSegment( SEGMENT_BPM, bs );
}
else else
{
LOG->UserLog( "Song file", sPath, "has an invalid BPM change at beat %f, BPM %f.", LOG->UserLog( "Song file", sPath, "has an invalid BPM change at beat %f, BPM %f.",
NoteRowToBeat(iStartIndex), fBPM ); NoteRowToBeat(iStartIndex), fBPM );
} }
} }
}
else if( sValueName.EqualsNoCase("SINGLE") || else if( sValueName.EqualsNoCase("SINGLE") ||
sValueName.EqualsNoCase("DOUBLE") || sValueName.EqualsNoCase("DOUBLE") ||
+27 -8
View File
@@ -15,13 +15,9 @@ void NotesLoaderJson::GetApplicableFiles( const RString &sPath, vector<RString>
GetDirListing( sPath + RString("*.json"), out ); GetDirListing( sPath + RString("*.json"), out );
} }
static void Deserialize(TimingSegment &seg_, const Json::Value &root) static void Deserialize( TimingSegment *seg, const Json::Value &root )
{ {
TimingSegment *seg = &seg_; switch( seg->GetType() )
float fBeat = root["Beat"].asDouble();
seg->SetBeat(fBeat);
switch (seg->GetType())
{ {
case SEGMENT_BPM: case SEGMENT_BPM:
{ {
@@ -39,10 +35,33 @@ static void Deserialize(TimingSegment &seg_, const Json::Value &root)
} }
} }
static void Deserialize(BPMSegment &seg, const Json::Value &root)
{
Deserialize( static_cast<TimingSegment*>(&seg), root );
}
static void Deserialize(StopSegment &seg, const Json::Value &root)
{
Deserialize( static_cast<TimingSegment*>(&seg), root );
}
static void Deserialize(TimingData &td, const Json::Value &root) static void Deserialize(TimingData &td, const Json::Value &root)
{ {
JsonUtil::DeserializeVectorPointers( td.m_avpTimingSegments[SEGMENT_BPM], Deserialize, root["BpmSegments"] ); vector<BPMSegment*> vBPMs;
JsonUtil::DeserializeVectorPointers( td.m_avpTimingSegments[SEGMENT_STOP], Deserialize, root["StopSegments"] ); vector<StopSegment*> vStops;
JsonUtil::DeserializeVectorPointers( vBPMs, Deserialize, root["BpmSegments"] );
JsonUtil::DeserializeVectorPointers( vStops, Deserialize, root["StopSegments"] );
for( unsigned i = 0; i < vBPMs.size(); ++i )
{
td.AddSegment( *vBPMs[i] );
delete vBPMs[i];
}
for( unsigned i = 0; i < vStops.size(); ++i )
{
td.AddSegment( *vStops[i] );
delete vStops[i];
}
} }
static void Deserialize(LyricSegment &o, const Json::Value &root) static void Deserialize(LyricSegment &o, const Json::Value &root)
+14 -12
View File
@@ -17,7 +17,7 @@ static void HandleBunki( TimingData &timing, const float fEarlyBPM,
const float beat = (fPos + fGap) * BeatsPerSecond; const float beat = (fPos + fGap) * BeatsPerSecond;
LOG->Trace( "BPM %f, BPS %f, BPMPos %f, beat %f", LOG->Trace( "BPM %f, BPS %f, BPMPos %f, beat %f",
fEarlyBPM, BeatsPerSecond, fPos, beat ); fEarlyBPM, BeatsPerSecond, fPos, beat );
timing.AddSegment( SEGMENT_BPM, new BPMSegment(BeatToNoteRow(beat), fCurBPM) ); timing.AddSegment( BPMSegment(BeatToNoteRow(beat), fCurBPM) );
} }
static bool LoadFromKSFFile( const RString &sPath, Steps &out, Song &song, bool bKIUCompliant ) static bool LoadFromKSFFile( const RString &sPath, Steps &out, Song &song, bool bKIUCompliant )
@@ -59,7 +59,7 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, Song &song, bool
else if( sValueName=="BPM" ) else if( sValueName=="BPM" )
{ {
BPM1 = StringToFloat(sParams[1]); BPM1 = StringToFloat(sParams[1]);
stepsTiming.AddSegment( SEGMENT_BPM, new BPMSegment(0, BPM1) ); stepsTiming.AddSegment( BPMSegment(0, BPM1) );
} }
else if( sValueName=="BPM2" ) else if( sValueName=="BPM2" )
{ {
@@ -136,7 +136,7 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, Song &song, bool
LOG->UserLog( "Song file", sPath, "has an invalid tick count: %d.", iTickCount ); LOG->UserLog( "Song file", sPath, "has an invalid tick count: %d.", iTickCount );
return false; return false;
} }
stepsTiming.AddSegment( SEGMENT_TICKCOUNT, new TickcountSegment(0, iTickCount)); stepsTiming.AddSegment( TickcountSegment(0, iTickCount));
} }
else if( sValueName=="DIFFICULTY" ) else if( sValueName=="DIFFICULTY" )
@@ -367,7 +367,8 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, Song &song, bool
else if (BeginsWith(sRowString, "|M") || BeginsWith(sRowString, "|C")) else if (BeginsWith(sRowString, "|M") || BeginsWith(sRowString, "|C"))
{ {
// multipliers/combo // multipliers/combo
stepsTiming.SetHitComboAtBeat( fCurBeat, static_cast<int>(numTemp) ); ComboSegment seg( BeatToNoteRow(fCurBeat), int(numTemp) );
stepsTiming.AddSegment( seg );
} }
else if (BeginsWith(sRowString, "|S")) else if (BeginsWith(sRowString, "|S"))
{ {
@@ -380,7 +381,8 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, Song &song, bool
else if (BeginsWith(sRowString, "|X")) else if (BeginsWith(sRowString, "|X"))
{ {
// scroll segments // scroll segments
stepsTiming.SetScrollAtBeat( fCurBeat, numTemp ); ScrollSegment seg = ScrollSegment( BeatToNoteRow(fCurBeat), numTemp );
stepsTiming.AddSegment( seg );
//return true; //return true;
} }
@@ -511,12 +513,12 @@ static void ProcessTickcounts( const RString & value, int & ticks, TimingData &
* and stops. It will be called again in LoadFromKSFFile for the * and stops. It will be called again in LoadFromKSFFile for the
* actual steps. */ * actual steps. */
ticks = StringToInt( value ); ticks = StringToInt( value );
ticks = ticks > 0 ? ticks : 4; CLAMP( ticks, 0, ROWS_PER_BEAT );
// add a tickcount for those using the [Player]
// CheckpointsUseTimeSignatures metric. -aj if( ticks == 0 )
// It's not with timesigs now -DaisuMaster ticks = TickcountSegment::DEFAULT_TICK_COUNT;
TickcountSegment * tcs = new TickcountSegment(0, ticks > ROWS_PER_BEAT ? ROWS_PER_BEAT : ticks);
timing.AddSegment( SEGMENT_TICKCOUNT, tcs ); timing.AddSegment( TickcountSegment(0, ticks) );
} }
static bool LoadGlobalData( const RString &sPath, Song &out, bool &bKIUCompliant ) static bool LoadGlobalData( const RString &sPath, Song &out, bool &bKIUCompliant )
@@ -557,7 +559,7 @@ static bool LoadGlobalData( const RString &sPath, Song &out, bool &bKIUCompliant
else if( sValueName=="BPM" ) else if( sValueName=="BPM" )
{ {
BPM1 = StringToFloat(sParams[1]); BPM1 = StringToFloat(sParams[1]);
out.m_SongTiming.AddSegment( SEGMENT_BPM, new BPMSegment(0, BPM1) ); out.m_SongTiming.AddSegment( BPMSegment(0, BPM1) );
} }
else if( sValueName=="BPM2" ) else if( sValueName=="BPM2" )
{ {
+7 -12
View File
@@ -592,7 +592,7 @@ static void ReadGlobalTags( const RString &sPath, const NameToData_t &mapNameToD
if( fBPM > 0.0f ) if( fBPM > 0.0f )
{ {
out.m_SongTiming.AddSegment( SEGMENT_BPM, new BPMSegment(0, fBPM) ); out.m_SongTiming.AddSegment( BPMSegment(0, fBPM) );
LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", NoteRowToBeat(0), fBPM ); LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", NoteRowToBeat(0), fBPM );
} }
else else
@@ -697,9 +697,8 @@ static void ReadGlobalTags( const RString &sPath, const NameToData_t &mapNameToD
if( fBPM > 0.0f ) if( fBPM > 0.0f )
{ {
BPMSegment * newSeg = new BPMSegment( BeatToNoteRow(fBeat), fBPM ); out.m_SongTiming.AddSegment( BPMSegment(BeatToNoteRow(fBeat), fBPM) );
out.m_SongTiming.AddSegment( SEGMENT_BPM, newSeg ); LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", fBeat, fBPM );
LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", fBeat, newSeg->GetBPM() );
} }
else else
{ {
@@ -724,9 +723,8 @@ static void ReadGlobalTags( const RString &sPath, const NameToData_t &mapNameToD
float fBeats = StringToFloat( sBeats ) / 48.0f; float fBeats = StringToFloat( sBeats ) / 48.0f;
float fFreezeSecs = fBeats / fBPS; float fFreezeSecs = fBeats / fBPS;
StopSegment * newSeg = new StopSegment( BeatToNoteRow(fBeat), fFreezeSecs ); out.m_SongTiming.AddSegment( StopSegment(BeatToNoteRow(fBeat), fFreezeSecs) );
out.m_SongTiming.AddSegment( SEGMENT_STOP, newSeg ); LOG->Trace( "Inserting new Freeze at beat %f, secs %f", fBeat, fFreezeSecs );
LOG->Trace( "Inserting new Freeze at beat %f, secs %f", fBeat, newSeg->GetPause() );
} }
else else
{ {
@@ -753,12 +751,9 @@ static void ReadGlobalTags( const RString &sPath, const NameToData_t &mapNameToD
if( fBPM > 0.0f ) if( fBPM > 0.0f )
{ {
BPMSegment * newSeg = new BPMSegment( iStepIndex, fBPM ); out.m_SongTiming.AddSegment( BPMSegment(iStepIndex, fBPM) );
out.m_SongTiming.AddSegment( SEGMENT_BPM, newSeg );
LOG->Trace("Inserting new BPM change at beat %f, BPM %f", LOG->Trace("Inserting new BPM change at beat %f, BPM %f",
newSeg->GetBeat(), NoteRowToBeat(iStepIndex), fBPM );
newSeg->GetBPM() );
} }
else else
{ {
+26 -47
View File
@@ -244,8 +244,7 @@ bool SMLoader::ProcessBPMs( TimingData &out, const RString line, const int rowsP
if( negBPM < 0 ) if( negBPM < 0 )
{ {
float endBeat = fBeat + (fNewBPM / -negBPM) * (fBeat - negBeat); float endBeat = fBeat + (fNewBPM / -negBPM) * (fBeat - negBeat);
out.AddSegment(SEGMENT_WARP, out.AddSegment( WarpSegment(BeatToNoteRow(negBeat), endBeat - negBeat) );
new WarpSegment(BeatToNoteRow(negBeat), endBeat - negBeat));
negBeat = -1; negBeat = -1;
negBPM = 1; negBPM = 1;
@@ -260,13 +259,11 @@ bool SMLoader::ProcessBPMs( TimingData &out, const RString line, const int rowsP
// add in a warp. // add in a warp.
if( highspeedBeat > 0 ) if( highspeedBeat > 0 )
{ {
out.AddSegment(SEGMENT_WARP, out.AddSegment( WarpSegment(BeatToNoteRow(highspeedBeat), fBeat - highspeedBeat) );
new WarpSegment(BeatToNoteRow(highspeedBeat), fBeat - highspeedBeat) );
highspeedBeat = -1; highspeedBeat = -1;
} }
{ {
out.AddSegment(SEGMENT_BPM, out.AddSegment( BPMSegment(BeatToNoteRow(fBeat), fNewBPM) );
new BPMSegment(BeatToNoteRow(fBeat), fNewBPM));
} }
} }
} }
@@ -303,14 +300,14 @@ void SMLoader::ProcessStops( TimingData &out, const RString line, const int rows
// Process the prior stop. // Process the prior stop.
if( negPause > 0 ) if( negPause > 0 )
{ {
BPMSegment * oldBPM = out.GetBPMSegmentAtRow(BeatToNoteRow(negBeat)); float oldBPM = out.GetBPMAtRow(BeatToNoteRow(negBeat));
float fSecondsPerBeat = 60 / oldBPM->GetBPM(); float fSecondsPerBeat = 60 / oldBPM;
float fSkipBeats = negPause / fSecondsPerBeat; float fSkipBeats = negPause / fSecondsPerBeat;
if( negBeat + fSkipBeats > fFreezeBeat ) if( negBeat + fSkipBeats > fFreezeBeat )
fSkipBeats = fFreezeBeat - negBeat; fSkipBeats = fFreezeBeat - negBeat;
out.AddSegment(SEGMENT_WARP, new WarpSegment(BeatToNoteRow(negBeat), fSkipBeats)); out.AddSegment( WarpSegment(BeatToNoteRow(negBeat), fSkipBeats));
negBeat = -1; negBeat = -1;
negPause = 0; negPause = 0;
@@ -323,20 +320,18 @@ void SMLoader::ProcessStops( TimingData &out, const RString line, const int rows
} }
else if( fFreezeSeconds > 0.0f ) else if( fFreezeSeconds > 0.0f )
{ {
out.AddSegment(SEGMENT_STOP, out.AddSegment( StopSegment(BeatToNoteRow(fFreezeBeat), fFreezeSeconds) );
new StopSegment(BeatToNoteRow(fFreezeBeat), fFreezeSeconds));
} }
} }
// Process the prior stop if there was one. // Process the prior stop if there was one.
if( negPause > 0 ) if( negPause > 0 )
{ {
BPMSegment * oldBPM = out.GetBPMSegmentAtBeat(negBeat); float oldBPM = out.GetBPMAtBeat(negBeat);
float fSecondsPerBeat = 60 / oldBPM->GetBPM(); float fSecondsPerBeat = 60 / oldBPM;
float fSkipBeats = negPause / fSecondsPerBeat; float fSkipBeats = negPause / fSecondsPerBeat;
out.AddSegment(SEGMENT_WARP, new WarpSegment(BeatToNoteRow(negBeat), fSkipBeats)); out.AddSegment( WarpSegment(BeatToNoteRow(negBeat), fSkipBeats) );
} }
} }
@@ -357,17 +352,12 @@ void SMLoader::ProcessDelays( TimingData &out, const RString line, const int row
arrayDelayExpressions[f].c_str() ); arrayDelayExpressions[f].c_str() );
continue; continue;
} }
const float fFreezeBeat = RowToBeat( arrayDelayValues[0], rowsPerBeat ); const float fFreezeBeat = RowToBeat( arrayDelayValues[0], rowsPerBeat );
const float fFreezeSeconds = StringToFloat( arrayDelayValues[1] ); const float fFreezeSeconds = StringToFloat( arrayDelayValues[1] );
DelaySegment * new_seg = new DelaySegment(BeatToNoteRow(fFreezeBeat),
fFreezeSeconds);
// LOG->Trace( "Adding a delay segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds ); // LOG->Trace( "Adding a delay segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds );
if(fFreezeSeconds > 0.0f) if(fFreezeSeconds > 0.0f)
out.AddSegment( SEGMENT_DELAY, new_seg ); out.AddSegment( DelaySegment(BeatToNoteRow(fFreezeBeat), fFreezeSeconds) );
else else
LOG->UserLog( LOG->UserLog(
"Song file", "Song file",
@@ -397,11 +387,8 @@ void SMLoader::ProcessTimeSignatures( TimingData &out, const RString line, const
} }
const float fBeat = RowToBeat( vs2[0], rowsPerBeat ); const float fBeat = RowToBeat( vs2[0], rowsPerBeat );
const int iNumerator = StringToInt( vs2[1] );
TimeSignatureSegment * seg = const int iDenominator = StringToInt( vs2[2] );
new TimeSignatureSegment( BeatToNoteRow(fBeat),
StringToInt( vs2[1] ),
StringToInt( vs2[2] ));
if( fBeat < 0 ) if( fBeat < 0 )
{ {
@@ -412,25 +399,25 @@ void SMLoader::ProcessTimeSignatures( TimingData &out, const RString line, const
continue; continue;
} }
if( seg->GetNum() < 1 ) if( iNumerator < 1 )
{ {
LOG->UserLog("Song file", LOG->UserLog("Song file",
this->GetSongTitle(), this->GetSongTitle(),
"has an invalid time signature change with beat %f, iNumerator %i.", "has an invalid time signature change with beat %f, iNumerator %i.",
fBeat, seg->GetNum() ); fBeat, iNumerator );
continue; continue;
} }
if( seg->GetDen() < 1 ) if( iDenominator < 1 )
{ {
LOG->UserLog("Song file", LOG->UserLog("Song file",
this->GetSongTitle(), this->GetSongTitle(),
"has an invalid time signature change with beat %f, iDenominator %i.", "has an invalid time signature change with beat %f, iDenominator %i.",
fBeat, seg->GetDen() ); fBeat, iDenominator );
continue; continue;
} }
out.AddSegment( SEGMENT_TIME_SIG, seg ); out.AddSegment( TimeSignatureSegment(BeatToNoteRow(fBeat), iNumerator, iDenominator) );
} }
} }
@@ -455,8 +442,7 @@ void SMLoader::ProcessTickcounts( TimingData &out, const RString line, const int
const float fTickcountBeat = RowToBeat( arrayTickcountValues[0], rowsPerBeat ); const float fTickcountBeat = RowToBeat( arrayTickcountValues[0], rowsPerBeat );
int iTicks = clamp(atoi( arrayTickcountValues[1] ), 0, ROWS_PER_BEAT); int iTicks = clamp(atoi( arrayTickcountValues[1] ), 0, ROWS_PER_BEAT);
out.AddSegment( SEGMENT_TICKCOUNT, out.AddSegment( TickcountSegment(BeatToNoteRow(fTickcountBeat), iTicks) );
new TickcountSegment(BeatToNoteRow(fTickcountBeat), iTicks) );
} }
} }
@@ -490,18 +476,14 @@ void SMLoader::ProcessSpeeds( TimingData &out, const RString line, const int row
} }
const float fBeat = RowToBeat( vs2[0], rowsPerBeat ); const float fBeat = RowToBeat( vs2[0], rowsPerBeat );
const float fRatio = StringToFloat( vs2[1] );
SpeedSegment * seg = new SpeedSegment( BeatToNoteRow(fBeat), const float fDelay = StringToFloat( vs2[2] );
StringToFloat( vs2[1] ),
StringToFloat( vs2[2] ));
// XXX: ugly... // XXX: ugly...
int iUnit = StringToInt(vs2[3]); int iUnit = StringToInt(vs2[3]);
SpeedSegment::BaseUnit unit = (iUnit == 0) ? SpeedSegment::BaseUnit unit = (iUnit == 0) ?
SpeedSegment::UNIT_BEATS : SpeedSegment::UNIT_SECONDS; SpeedSegment::UNIT_BEATS : SpeedSegment::UNIT_SECONDS;
seg->SetUnit( unit );
if( fBeat < 0 ) if( fBeat < 0 )
{ {
LOG->UserLog("Song file", LOG->UserLog("Song file",
@@ -511,16 +493,16 @@ void SMLoader::ProcessSpeeds( TimingData &out, const RString line, const int row
continue; continue;
} }
if( seg->GetDelay() < 0 ) if( fDelay < 0 )
{ {
LOG->UserLog("Song file", LOG->UserLog("Song file",
this->GetSongTitle(), this->GetSongTitle(),
"has an speed change with beat %f, length %f.", "has an speed change with beat %f, length %f.",
fBeat, seg->GetDelay() ); fBeat, fDelay );
continue; continue;
} }
out.AddSegment( SEGMENT_SPEED, seg ); out.AddSegment( SpeedSegment(BeatToNoteRow(fBeat), fRatio, fDelay, unit) );
} }
} }
@@ -546,7 +528,7 @@ void SMLoader::ProcessFakes( TimingData &out, const RString line, const int rows
const float fNewBeat = StringToFloat( arrayFakeValues[1] ); const float fNewBeat = StringToFloat( arrayFakeValues[1] );
if(fNewBeat > 0) if(fNewBeat > 0)
out.AddSegment( SEGMENT_FAKE, new FakeSegment(BeatToNoteRow(fBeat), fNewBeat) ); out.AddSegment( FakeSegment(BeatToNoteRow(fBeat), fNewBeat) );
else else
{ {
LOG->UserLog("Song file", LOG->UserLog("Song file",
@@ -798,7 +780,6 @@ bool SMLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCache
ProcessTickcounts(out.m_SongTiming, sParams[1]); ProcessTickcounts(out.m_SongTiming, sParams[1]);
} }
else if( sValueName=="INSTRUMENTTRACK" ) else if( sValueName=="INSTRUMENTTRACK" )
{ {
ProcessInstrumentTracks( out, sParams[1] ); ProcessInstrumentTracks( out, sParams[1] );
@@ -933,8 +914,7 @@ bool SMLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCache
} }
// Ensure all warps from negative time changes are in order. // Ensure all warps from negative time changes are in order.
vector<TimingSegment *> &warps = out.m_SongTiming.m_avpTimingSegments[SEGMENT_WARP]; out.m_SongTiming.SortSegments( SEGMENT_WARP );
sort(warps.begin(), warps.end());
TidyUpData( out, bFromCache ); TidyUpData( out, bFromCache );
return true; return true;
} }
@@ -1105,7 +1085,6 @@ void SMLoader::TidyUpData( Song &song, bool bFromCache )
if( !IsAFile( song.GetBackgroundPath() ) ) if( !IsAFile( song.GetBackgroundPath() ) )
break; break;
bg.push_back( BackgroundChange(lastBeat,song.m_sBackgroundFile) ); bg.push_back( BackgroundChange(lastBeat,song.m_sBackgroundFile) );
} while(0); } while(0);
} }
+10 -16
View File
@@ -38,8 +38,7 @@ void SMALoader::ProcessMultipliers( TimingData &out, const int iRowsPerBeat, con
const int iMisses = (size == 2 || size == 4 ? const int iMisses = (size == 2 || size == 4 ?
iCombos : iCombos :
StringToInt(arrayMultiplierValues[2])); StringToInt(arrayMultiplierValues[2]));
out.AddSegment(SEGMENT_COMBO, out.AddSegment( ComboSegment(BeatToNoteRow(fComboBeat), iCombos, iMisses) );
new ComboSegment( BeatToNoteRow(fComboBeat), iCombos, iMisses ));
} }
} }
@@ -62,11 +61,7 @@ void SMALoader::ProcessBeatsPerMeasure( TimingData &out, const RString sParam )
continue; continue;
} }
const float fBeat = StringToFloat( vs2[0] ); const float fBeat = StringToFloat( vs2[0] );
const int iNumerator = StringToInt( vs2[1] );
TimeSignatureSegment * seg = new TimeSignatureSegment(
BeatToNoteRow(fBeat),
StringToInt(vs2[1]),
4 );
if( fBeat < 0 ) if( fBeat < 0 )
{ {
@@ -76,17 +71,16 @@ void SMALoader::ProcessBeatsPerMeasure( TimingData &out, const RString sParam )
fBeat ); fBeat );
continue; continue;
} }
if( iNumerator < 1 )
if( seg->GetNum() < 1 )
{ {
LOG->UserLog("Song file", LOG->UserLog("Song file",
this->GetSongTitle(), this->GetSongTitle(),
"has an invalid time signature change with beat %f, iNumerator %i.", "has an invalid time signature change with beat %f, iNumerator %i.",
fBeat, seg->GetNum() ); fBeat, iNumerator );
continue; continue;
} }
out.AddSegment( SEGMENT_TIME_SIG, seg ); out.AddSegment( TimeSignatureSegment(BeatToNoteRow(fBeat), iNumerator) );
} }
} }
@@ -123,12 +117,12 @@ void SMALoader::ProcessSpeeds( TimingData &out, const RString line, const int ro
Trim(vs2[2], "s"); Trim(vs2[2], "s");
Trim(vs2[2], "S"); Trim(vs2[2], "S");
const float fRatio = StringToFloat( vs2[1] );
const float fDelay = StringToFloat( vs2[2] );
SpeedSegment::BaseUnit unit = ((backup != vs2[2]) ? SpeedSegment::BaseUnit unit = ((backup != vs2[2]) ?
SpeedSegment::UNIT_SECONDS : SpeedSegment::UNIT_BEATS); SpeedSegment::UNIT_SECONDS : SpeedSegment::UNIT_BEATS);
SpeedSegment * seg = new SpeedSegment( BeatToNoteRow(fBeat),
StringToFloat( vs2[1] ), StringToFloat(vs2[2]), unit);
if( fBeat < 0 ) if( fBeat < 0 )
{ {
@@ -139,16 +133,16 @@ void SMALoader::ProcessSpeeds( TimingData &out, const RString line, const int ro
continue; continue;
} }
if( seg->GetDelay() < 0 ) if( fDelay < 0 )
{ {
LOG->UserLog("Song file", LOG->UserLog("Song file",
this->GetSongTitle(), this->GetSongTitle(),
"has an speed change with beat %f, length %f.", "has an speed change with beat %f, length %f.",
fBeat, seg->GetDelay() ); fBeat, fDelay );
continue; continue;
} }
out.AddSegment( SEGMENT_SPEED, seg ); out.AddSegment( SpeedSegment(BeatToNoteRow(fBeat), fRatio, fDelay, unit) );
} }
} }
+6 -7
View File
@@ -37,10 +37,10 @@ void SSCLoader::ProcessWarps( TimingData &out, const RString sParam, const float
// Early versions were absolute in beats. They should be relative. // Early versions were absolute in beats. They should be relative.
if( ( fVersion < VERSION_SPLIT_TIMING && fNewBeat > fBeat ) ) if( ( fVersion < VERSION_SPLIT_TIMING && fNewBeat > fBeat ) )
{ {
out.AddSegment( SEGMENT_WARP, new WarpSegment(BeatToNoteRow(fBeat), fNewBeat - fBeat) ); out.AddSegment( WarpSegment(BeatToNoteRow(fBeat), fNewBeat - fBeat) );
} }
else if( fNewBeat > 0 ) else if( fNewBeat > 0 )
out.AddSegment( SEGMENT_WARP, new WarpSegment(BeatToNoteRow(fBeat), fNewBeat) ); out.AddSegment( WarpSegment(BeatToNoteRow(fBeat), fNewBeat) );
else else
{ {
LOG->UserLog("Song file", LOG->UserLog("Song file",
@@ -73,7 +73,7 @@ void SSCLoader::ProcessLabels( TimingData &out, const RString sParam )
RString sLabel = arrayLabelValues[1]; RString sLabel = arrayLabelValues[1];
TrimRight(sLabel); TrimRight(sLabel);
if( fBeat >= 0.0f ) if( fBeat >= 0.0f )
out.AddSegment( SEGMENT_LABEL, new LabelSegment(BeatToNoteRow(fBeat), sLabel) ); out.AddSegment( LabelSegment(BeatToNoteRow(fBeat), sLabel) );
else else
{ {
LOG->UserLog("Song file", LOG->UserLog("Song file",
@@ -106,7 +106,7 @@ void SSCLoader::ProcessCombos( TimingData &out, const RString line, const int ro
const float fComboBeat = StringToFloat( arrayComboValues[0] ); const float fComboBeat = StringToFloat( arrayComboValues[0] );
const int iCombos = StringToInt( arrayComboValues[1] ); const int iCombos = StringToInt( arrayComboValues[1] );
const int iMisses = (size == 2 ? iCombos : StringToInt(arrayComboValues[2])); const int iMisses = (size == 2 ? iCombos : StringToInt(arrayComboValues[2]));
out.AddSegment( SEGMENT_COMBO, new ComboSegment( BeatToNoteRow(fComboBeat), iCombos, iMisses ) ); out.AddSegment( ComboSegment( BeatToNoteRow(fComboBeat), iCombos, iMisses ) );
} }
} }
@@ -130,8 +130,7 @@ void SSCLoader::ProcessScrolls( TimingData &out, const RString sParam )
} }
const float fBeat = StringToFloat( vs2[0] ); const float fBeat = StringToFloat( vs2[0] );
const float fRatio = StringToFloat( vs2[1] );
ScrollSegment * seg = new ScrollSegment(BeatToNoteRow(fBeat), StringToFloat( vs2[1] ) );
if( fBeat < 0 ) if( fBeat < 0 )
{ {
@@ -142,7 +141,7 @@ void SSCLoader::ProcessScrolls( TimingData &out, const RString sParam )
continue; continue;
} }
out.AddSegment( SEGMENT_SCROLL, seg ); out.AddSegment( ScrollSegment(BeatToNoteRow(fBeat), fRatio) );
} }
} }
+2 -3
View File
@@ -354,8 +354,7 @@ bool NotesWriterDWI::Write( RString sPath, const Song &out )
f.PutLine( ssprintf("#TITLE:%s;", DwiEscape(out.GetTranslitFullTitle()).c_str()) ); f.PutLine( ssprintf("#TITLE:%s;", DwiEscape(out.GetTranslitFullTitle()).c_str()) );
f.PutLine( ssprintf("#ARTIST:%s;", DwiEscape(out.GetTranslitArtist()).c_str()) ); f.PutLine( ssprintf("#ARTIST:%s;", DwiEscape(out.GetTranslitArtist()).c_str()) );
const vector<TimingSegment *> &bpms = out.m_SongTiming.m_avpTimingSegments[SEGMENT_BPM]; const vector<TimingSegment *> &bpms = out.m_SongTiming.GetTimingSegments(SEGMENT_BPM);
ASSERT_M(bpms[0]->GetRow() == 0, ASSERT_M(bpms[0]->GetRow() == 0,
ssprintf("The first BPM Segment must be defined at row 0, not %d!", bpms[0]->GetRow()) ); ssprintf("The first BPM Segment must be defined at row 0, not %d!", bpms[0]->GetRow()) );
f.PutLine( ssprintf("#FILE:%s;", DwiEscape(out.m_sMusicFile).c_str()) ); f.PutLine( ssprintf("#FILE:%s;", DwiEscape(out.m_sMusicFile).c_str()) );
@@ -382,7 +381,7 @@ bool NotesWriterDWI::Write( RString sPath, const Song &out )
} }
// TODO: Also check for delays, add them as stops minus one row? // TODO: Also check for delays, add them as stops minus one row?
const vector<TimingSegment *> &stops = out.m_SongTiming.m_avpTimingSegments[SEGMENT_STOP]; const vector<TimingSegment *> &stops = out.m_SongTiming.GetTimingSegments(SEGMENT_STOP);
if( !stops.empty() ) if( !stops.empty() )
{ {
f.Write( "#FREEZE:" ); f.Write( "#FREEZE:" );
+2 -2
View File
@@ -24,8 +24,8 @@ static void Serialize(const TimingSegment &seg, Json::Value &root)
static void Serialize(const TimingData &td, Json::Value &root) static void Serialize(const TimingData &td, Json::Value &root)
{ {
JsonUtil::SerializeVectorPointers( td.m_avpTimingSegments[SEGMENT_BPM], Serialize, root["BpmSegments"] ); JsonUtil::SerializeVectorPointers( td.GetTimingSegments(SEGMENT_BPM), Serialize, root["BpmSegments"] );
JsonUtil::SerializeVectorPointers( td.m_avpTimingSegments[SEGMENT_STOP], Serialize, root["StopSegments"] ); JsonUtil::SerializeVectorPointers( td.GetTimingSegments(SEGMENT_STOP), Serialize, root["StopSegments"] );
} }
static void Serialize(const LyricSegment &o, Json::Value &root) static void Serialize(const LyricSegment &o, Json::Value &root)
+16 -17
View File
@@ -75,10 +75,10 @@ static void WriteGlobalTags( RageFile &f, Song &out )
f.Write( "#BPMS:" ); f.Write( "#BPMS:" );
vector<TimingSegment *> &bpms = timing.m_avpTimingSegments[SEGMENT_BPM]; const vector<TimingSegment *> &bpms = timing.GetTimingSegments(SEGMENT_BPM);
for( unsigned i=0; i<bpms.size(); i++ ) for( unsigned i=0; i<bpms.size(); i++ )
{ {
const BPMSegment *bs = static_cast<BPMSegment *>(bpms[i]); const BPMSegment *bs = ToBPM(bpms[i]);
f.PutLine( ssprintf( "%.3f=%.3f", bs->GetBeat(), bs->GetBPM() ) ); f.PutLine( ssprintf( "%.3f=%.3f", bs->GetBeat(), bs->GetBPM() ) );
if( i != bpms.size()-1 ) if( i != bpms.size()-1 )
@@ -86,7 +86,7 @@ static void WriteGlobalTags( RageFile &f, Song &out )
} }
f.PutLine( ";" ); f.PutLine( ";" );
vector<TimingSegment *> &warps = timing.m_avpTimingSegments[SEGMENT_WARP]; const vector<TimingSegment *> &warps = timing.GetTimingSegments(SEGMENT_WARP);
unsigned wSize = warps.size(); unsigned wSize = warps.size();
if( wSize > 0 ) if( wSize > 0 )
{ {
@@ -96,32 +96,31 @@ static void WriteGlobalTags( RageFile &f, Song &out )
int iRow = ws->GetRow(); int iRow = ws->GetRow();
float fBPS = 60 / out.m_SongTiming.GetBPMAtRow(iRow); float fBPS = 60 / out.m_SongTiming.GetBPMAtRow(iRow);
float fSkip = fBPS * ws->GetLength(); float fSkip = fBPS * ws->GetLength();
out.m_SongTiming.AddSegment(SEGMENT_STOP, out.m_SongTiming.AddSegment( StopSegment(iRow, -fSkip) );
new StopSegment(iRow, -fSkip) );
} }
} }
// TODO: make Delays into Stops that start one row before. // TODO: make Delays into Stops that start one row before.
vector<TimingSegment *> &stops = timing.m_avpTimingSegments[SEGMENT_STOP]; const vector<TimingSegment *> &stops = timing.GetTimingSegments(SEGMENT_STOP);
vector<TimingSegment *> &delays = timing.m_avpTimingSegments[SEGMENT_DELAY]; const vector<TimingSegment *> &delays = timing.GetTimingSegments(SEGMENT_DELAY);
map<float, float> allPauses; map<float, float> allPauses;
for( unsigned i=0; i<stops.size(); i++ ) for( unsigned i=0; i<stops.size(); i++ )
{ {
const StopSegment *fs = static_cast<StopSegment *>(stops[i]); const StopSegment *fs = ToStop( stops[i] );
allPauses.insert(pair<float, float>(fs->GetBeat(),
fs->GetPause())); allPauses.insert(pair<float, float>(fs->GetBeat(), fs->GetPause()));
// erase stops with negative length
if( fs->GetPause() < 0 ) if( fs->GetPause() < 0 )
{ timing.AddSegment( StopSegment(fs->GetRow(), 0) );
stops.erase(stops.begin()+i,stops.begin()+i+1 );
i--;
}
} }
// Delays can't be negative: thus, no effect. // Delays can't be negative: thus, no effect.
FOREACH(TimingSegment *, delays, ss) FOREACH_CONST(TimingSegment *, delays, ss)
{ {
allPauses.insert(pair<float, float>(NoteRowToBeat((*ss)->GetRow() - 1), float fBeat = NoteRowToBeat( (*ss)->GetRow()-1 );
static_cast<DelaySegment *>(*ss)->GetPause())); float fPause = ToDelay(*ss)->GetPause();
allPauses.insert( pair<float,float>(fBeat, fPause) );
} }
f.Write( "#STOPS:" ); f.Write( "#STOPS:" );
+23 -23
View File
@@ -60,75 +60,75 @@ struct TimingTagWriter {
}; };
static void GetTimingTags( vector<RString> &lines, TimingData timing, bool bIsSong = false ) static void GetTimingTags( vector<RString> &lines, const TimingData &timing, bool bIsSong = false )
{ {
TimingTagWriter w ( &lines ); TimingTagWriter w ( &lines );
timing.TidyUpData(); // timing.TidyUpData(); // UGLY: done via const_cast. do we really -need- this here?
unsigned i = 0; unsigned i = 0;
w.Init( "BPMS" ); w.Init( "BPMS" );
vector<TimingSegment *> &bpms = timing.m_avpTimingSegments[SEGMENT_BPM]; const vector<TimingSegment *> &bpms = timing.GetTimingSegments(SEGMENT_BPM);
for (; i < bpms.size(); i++) for (; i < bpms.size(); i++)
{ {
BPMSegment *bs = static_cast<BPMSegment *>(bpms[i]); const BPMSegment *bs = ToBPM( bpms[i] );
w.Write( bs->GetRow(), bs->GetBPM() ); w.Write( bs->GetRow(), bs->GetBPM() );
} }
w.Finish(); w.Finish();
w.Init( "STOPS" ); w.Init( "STOPS" );
vector<TimingSegment *> &stops = timing.m_avpTimingSegments[SEGMENT_STOP]; const vector<TimingSegment *> &stops = timing.GetTimingSegments(SEGMENT_STOP);
for (i = 0; i < stops.size(); i++) for (i = 0; i < stops.size(); i++)
{ {
StopSegment *ss = static_cast<StopSegment *>(stops[i]); const StopSegment *ss = ToStop( stops[i] );
w.Write( ss->GetRow(), ss->GetPause() ); w.Write( ss->GetRow(), ss->GetPause() );
} }
w.Finish(); w.Finish();
w.Init( "DELAYS" ); w.Init( "DELAYS" );
vector<TimingSegment *> &delays = timing.m_avpTimingSegments[SEGMENT_DELAY]; const vector<TimingSegment *> &delays = timing.GetTimingSegments(SEGMENT_DELAY);
for (i = 0; i < delays.size(); i++) for (i = 0; i < delays.size(); i++)
{ {
DelaySegment *ss = static_cast<DelaySegment *>(delays[i]); const DelaySegment *ss = ToDelay( delays[i] );
w.Write( ss->GetRow(), ss->GetPause() ); w.Write( ss->GetRow(), ss->GetPause() );
} }
w.Finish(); w.Finish();
w.Init( "WARPS" ); w.Init( "WARPS" );
vector<TimingSegment *> &warps = timing.m_avpTimingSegments[SEGMENT_WARP]; const vector<TimingSegment *> &warps = timing.GetTimingSegments(SEGMENT_WARP);
for (i = 0; i < warps.size(); i++) for (i = 0; i < warps.size(); i++)
{ {
WarpSegment *ws = static_cast<WarpSegment *>(warps[i]); const WarpSegment *ws = ToWarp( warps[i] );
w.Write( ws->GetRow(), ws->GetLength() ); w.Write( ws->GetRow(), ws->GetLength() );
} }
w.Finish(); w.Finish();
vector<TimingSegment *> &tSigs = timing.m_avpTimingSegments[SEGMENT_TIME_SIG]; const vector<TimingSegment *> &tSigs = timing.GetTimingSegments(SEGMENT_TIME_SIG);
ASSERT( !tSigs.empty() ); ASSERT( !tSigs.empty() );
w.Init( "TIMESIGNATURES" ); w.Init( "TIMESIGNATURES" );
for (i = 0; i < tSigs.size(); i++) for (i = 0; i < tSigs.size(); i++)
{ {
TimeSignatureSegment *ts = static_cast<TimeSignatureSegment *>(tSigs[i]); const TimeSignatureSegment *ts = ToTimeSignature( tSigs[i] );
w.Write( ts->GetRow(), ts->GetNum(), ts->GetDen() ); w.Write( ts->GetRow(), ts->GetNum(), ts->GetDen() );
} }
w.Finish(); w.Finish();
vector<TimingSegment *> &ticks = timing.m_avpTimingSegments[SEGMENT_TICKCOUNT]; const vector<TimingSegment *> &ticks = timing.GetTimingSegments(SEGMENT_TICKCOUNT);
ASSERT( !ticks.empty() ); ASSERT( !ticks.empty() );
w.Init( "TICKCOUNTS" ); w.Init( "TICKCOUNTS" );
for (i = 0; i < ticks.size(); i++) for (i = 0; i < ticks.size(); i++)
{ {
TickcountSegment *ts = static_cast<TickcountSegment *>(ticks[i]); const TickcountSegment *ts = ToTickcount( ticks[i] );
w.Write( ts->GetRow(), ts->GetTicks() ); w.Write( ts->GetRow(), ts->GetTicks() );
} }
w.Finish(); w.Finish();
vector<TimingSegment *> &combos = timing.m_avpTimingSegments[SEGMENT_COMBO]; const vector<TimingSegment *> &combos = timing.GetTimingSegments(SEGMENT_COMBO);
ASSERT( !combos.empty() ); ASSERT( !combos.empty() );
w.Init( "COMBOS" ); w.Init( "COMBOS" );
for (i = 0; i < combos.size(); i++) for (i = 0; i < combos.size(); i++)
{ {
ComboSegment *cs = static_cast<ComboSegment *>(combos[i]); const ComboSegment *cs = ToCombo( combos[i] );
if (cs->GetCombo() == cs->GetMissCombo()) if (cs->GetCombo() == cs->GetMissCombo())
w.Write( cs->GetRow(), cs->GetCombo() ); w.Write( cs->GetRow(), cs->GetCombo() );
else else
@@ -137,38 +137,38 @@ static void GetTimingTags( vector<RString> &lines, TimingData timing, bool bIsSo
w.Finish(); w.Finish();
// Song Timing should only have the initial value. // Song Timing should only have the initial value.
vector<TimingSegment *> &speeds = timing.m_avpTimingSegments[SEGMENT_SPEED]; const vector<TimingSegment *> &speeds = timing.GetTimingSegments(SEGMENT_SPEED);
w.Init( "SPEEDS" ); w.Init( "SPEEDS" );
for (i = 0; i < speeds.size(); i++) for (i = 0; i < speeds.size(); i++)
{ {
SpeedSegment *ss = static_cast<SpeedSegment *>(speeds[i]); SpeedSegment *ss = ToSpeed( speeds[i] );
w.Write( ss->GetRow(), ss->GetRatio(), ss->GetDelay(), ss->GetUnit() ); w.Write( ss->GetRow(), ss->GetRatio(), ss->GetDelay(), ss->GetUnit() );
} }
w.Finish(); w.Finish();
w.Init( "SCROLLS" ); w.Init( "SCROLLS" );
vector<TimingSegment *> &scrolls = timing.m_avpTimingSegments[SEGMENT_SCROLL]; const vector<TimingSegment *> &scrolls = timing.GetTimingSegments(SEGMENT_SCROLL);
for (i = 0; i < scrolls.size(); i++) for (i = 0; i < scrolls.size(); i++)
{ {
ScrollSegment *ss = static_cast<ScrollSegment *>(scrolls[i]); ScrollSegment *ss = ToScroll( scrolls[i] );
w.Write( ss->GetRow(), ss->GetRatio() ); w.Write( ss->GetRow(), ss->GetRatio() );
} }
w.Finish(); w.Finish();
if( !bIsSong ) if( !bIsSong )
{ {
vector<TimingSegment *> &fakes = timing.m_avpTimingSegments[SEGMENT_FAKE]; const vector<TimingSegment *> &fakes = timing.GetTimingSegments(SEGMENT_FAKE);
w.Init( "FAKES" ); w.Init( "FAKES" );
for (i = 0; i < fakes.size(); i++) for (i = 0; i < fakes.size(); i++)
{ {
FakeSegment *fs = static_cast<FakeSegment *>(fakes[i]); FakeSegment *fs = ToFake( fakes[i] );
w.Write( fs->GetRow(), fs->GetLength() ); w.Write( fs->GetRow(), fs->GetLength() );
} }
w.Finish(); w.Finish();
} }
w.Init( "LABELS" ); w.Init( "LABELS" );
vector<TimingSegment *> &labels = timing.m_avpTimingSegments[SEGMENT_LABEL]; const vector<TimingSegment *> &labels = timing.GetTimingSegments(SEGMENT_LABEL);
for (i = 0; i < labels.size(); i++) for (i = 0; i < labels.size(); i++)
{ {
LabelSegment *ls = static_cast<LabelSegment *>(labels[i]); LabelSegment *ls = static_cast<LabelSegment *>(labels[i]);
+3 -4
View File
@@ -755,21 +755,20 @@ static void GenerateCacheDataStructure(PlayerState *pPlayerState, NoteData &note
pPlayerState->m_CacheDisplayedBeat.clear(); pPlayerState->m_CacheDisplayedBeat.clear();
const vector<TimingSegment *> *segs = pPlayerState->GetDisplayedTiming().m_avpTimingSegments; const vector<TimingSegment*> vScrolls = pPlayerState->GetDisplayedTiming().GetTimingSegments( SEGMENT_SCROLL );
float displayedBeat = 0.0f; float displayedBeat = 0.0f;
float lastRealBeat = 0.0f; float lastRealBeat = 0.0f;
float lastRatio = 1.0f; float lastRatio = 1.0f;
for ( unsigned i = 0; i < segs[SEGMENT_SCROLL].size(); i++ ) for ( unsigned i = 0; i < vScrolls.size(); i++ )
{ {
ScrollSegment *seg = static_cast<ScrollSegment *>(segs[SEGMENT_SCROLL][i]); ScrollSegment *seg = ToScroll( vScrolls[i] );
displayedBeat += ( seg->GetBeat() - lastRealBeat ) * lastRatio; displayedBeat += ( seg->GetBeat() - lastRealBeat ) * lastRatio;
lastRealBeat = seg->GetBeat(); lastRealBeat = seg->GetBeat();
lastRatio = seg->GetRatio(); lastRatio = seg->GetRatio();
CacheDisplayedBeat c = { seg->GetBeat(), displayedBeat, seg->GetRatio() }; CacheDisplayedBeat c = { seg->GetBeat(), displayedBeat, seg->GetRatio() };
pPlayerState->m_CacheDisplayedBeat.push_back( c ); pPlayerState->m_CacheDisplayedBeat.push_back( c );
} }
} }
void Player::Update( float fDeltaTime ) void Player::Update( float fDeltaTime )
+60 -96
View File
@@ -1893,19 +1893,21 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
fDelta *= 40; fDelta *= 40;
} }
unsigned i; unsigned i;
vector<TimingSegment *> &stops = GetAppropriateTiming().m_avpTimingSegments[SEGMENT_STOP];
for( i=0; i<stops.size(); i++ )
{
if( stops[i]->GetRow() == GetRow() )
break;
}
#if 0
// is there a StopSegment on the current row?
const StopSegment *seg = GetAppropriateTiming().GetStopSegmentAtRow( GetRow() );
// a stop already exists here; change its value by the delta
if( seg->GetRow() == GetRow() )
{
float fSeconds = seg->GetPause() + fDelta;
GetAppropriateTiming().AddSegment
if( i == stops.size() ) // there is no StopSegment at the current beat if( i == stops.size() ) // there is no StopSegment at the current beat
{ {
// create a new StopSegment // create a new StopSegment
if( fDelta > 0 ) if( fDelta > 0 )
GetAppropriateTiming().AddSegment(SEGMENT_STOP, GetAppropriateTiming().AddSegment( StopSegment(GetRow(), fDelta) );
new StopSegment( GetRow(), fDelta) );
} }
else // StopSegment being modified is m_SongTiming.m_StopSegments[i] else // StopSegment being modified is m_SongTiming.m_StopSegments[i]
{ {
@@ -1914,6 +1916,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
if( s->GetPause() <= 0 ) if( s->GetPause() <= 0 )
stops.erase( stops.begin()+i, stops.begin()+i+1); stops.erase( stops.begin()+i, stops.begin()+i+1);
} }
#endif
(fDelta>0 ? m_soundValueIncrease : m_soundValueDecrease).Play(); (fDelta>0 ? m_soundValueIncrease : m_soundValueDecrease).Play();
SetDirty( true ); SetDirty( true );
} }
@@ -2962,59 +2965,67 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM )
else if( SM == SM_BackFromBPMChange && !ScreenTextEntry::s_bCancelledLast ) else if( SM == SM_BackFromBPMChange && !ScreenTextEntry::s_bCancelledLast )
{ {
float fBPM = StringToFloat( ScreenTextEntry::s_sLastAnswer ); float fBPM = StringToFloat( ScreenTextEntry::s_sLastAnswer );
if( fBPM > 0 ) if( fBPM > 0 )
GetAppropriateTiming().SetBPMAtBeat( GetBeat(), fBPM ); GetAppropriateTiming().AddSegment( BPMSegment(GetRow(), fBPM) );
SetDirty( true ); SetDirty( true );
} }
else if( SM == SM_BackFromStopChange && !ScreenTextEntry::s_bCancelledLast ) else if( SM == SM_BackFromStopChange && !ScreenTextEntry::s_bCancelledLast )
{ {
float fStop = StringToFloat( ScreenTextEntry::s_sLastAnswer ); float fStop = StringToFloat( ScreenTextEntry::s_sLastAnswer );
if( fStop >= 0 ) if( fStop >= 0 )
GetAppropriateTiming().SetStopAtBeat( GetBeat(), fStop ); GetAppropriateTiming().AddSegment( StopSegment(GetRow(), fStop) );
SetDirty( true ); SetDirty( true );
} }
else if( SM == SM_BackFromDelayChange && !ScreenTextEntry::s_bCancelledLast ) else if( SM == SM_BackFromDelayChange && !ScreenTextEntry::s_bCancelledLast )
{ {
float fDelay = StringToFloat( ScreenTextEntry::s_sLastAnswer ); float fDelay = StringToFloat( ScreenTextEntry::s_sLastAnswer );
if( fDelay >= 0 ) if( fDelay >= 0 )
GetAppropriateTiming().SetDelayAtBeat( GetBeat(), fDelay ); GetAppropriateTiming().AddSegment( DelaySegment(GetRow(), fDelay) );
SetDirty( true ); SetDirty( true );
} }
else if( SM == SM_BackFromTimeSignatureChange && !ScreenTextEntry::s_bCancelledLast ) else if( SM == SM_BackFromTimeSignatureChange && !ScreenTextEntry::s_bCancelledLast )
{ {
int iNum, iDen; int iNum, iDen;
if( sscanf( ScreenTextEntry::s_sLastAnswer.c_str(), " %d / %d ", &iNum, &iDen ) == 2 ) if( sscanf( ScreenTextEntry::s_sLastAnswer.c_str(), " %d / %d ", &iNum, &iDen ) == 2 )
{ GetAppropriateTiming().AddSegment( TimeSignatureSegment(GetRow(), iNum, iDen) );
GetAppropriateTiming().SetTimeSignatureAtBeat( GetBeat(), iNum, iDen );
}
SetDirty( true ); SetDirty( true );
} }
else if ( SM == SM_BackFromTickcountChange && !ScreenTextEntry::s_bCancelledLast ) else if ( SM == SM_BackFromTickcountChange && !ScreenTextEntry::s_bCancelledLast )
{ {
int iTick = StringToInt( ScreenTextEntry::s_sLastAnswer ); int iTick = StringToInt( ScreenTextEntry::s_sLastAnswer );
if ( iTick >= 0 && iTick <= ROWS_PER_BEAT ) if ( iTick >= 0 && iTick <= ROWS_PER_BEAT )
{ GetAppropriateTiming().AddSegment( TickcountSegment( GetRow(), iTick) );
GetAppropriateTiming().SetTickcountAtBeat( GetBeat(), iTick );
}
SetDirty( true ); SetDirty( true );
} }
else if ( SM == SM_BackFromComboChange && !ScreenTextEntry::s_bCancelledLast ) else if ( SM == SM_BackFromComboChange && !ScreenTextEntry::s_bCancelledLast )
{ {
int iCombo, iMiss; int iCombo, iMiss;
if (sscanf(ScreenTextEntry::s_sLastAnswer.c_str(), " %d / %d ", &iCombo, &iMiss) == 2) if (sscanf(ScreenTextEntry::s_sLastAnswer.c_str(), " %d / %d ", &iCombo, &iMiss) == 2)
{ GetAppropriateTiming().AddSegment( ComboSegment(GetRow(), iCombo, iMiss) );
GetAppropriateTiming().SetComboAtBeat( GetBeat(), iCombo, iMiss );
}
SetDirty( true ); SetDirty( true );
} }
else if ( SM == SM_BackFromLabelChange && !ScreenTextEntry::s_bCancelledLast ) else if ( SM == SM_BackFromLabelChange && !ScreenTextEntry::s_bCancelledLast )
{ {
RString sLabel = ScreenTextEntry::s_sLastAnswer; RString sLabel = ScreenTextEntry::s_sLastAnswer;
if ( !GetAppropriateTiming().DoesLabelExist(sLabel) ) if ( !GetAppropriateTiming().DoesLabelExist(sLabel) )
{ {
// XXX: these should be in the NotesWriters where they're needed.
sLabel.Replace("=", "_"); sLabel.Replace("=", "_");
sLabel.Replace(",", "_"); sLabel.Replace(",", "_");
GetAppropriateTiming().SetLabelAtBeat( GetBeat(), sLabel ); GetAppropriateTiming().AddSegment( LabelSegment(GetRow(), sLabel) );
SetDirty( true ); SetDirty( true );
} }
} }
@@ -3074,7 +3085,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM )
float fFake = StringToFloat( ScreenTextEntry::s_sLastAnswer ); float fFake = StringToFloat( ScreenTextEntry::s_sLastAnswer );
if( fFake >= 0 ) // allow 0 to kill a warp. if( fFake >= 0 ) // allow 0 to kill a warp.
{ {
GetAppropriateTiming().SetFakeAtBeat( GetBeat(), fFake ); GetAppropriateTiming().AddSegment( FakeSegment(GetRow(), fFake) );
SetDirty( true ); SetDirty( true );
} }
} }
@@ -3476,8 +3487,9 @@ static void ChangeBeat0Offset( const RString &sNew )
GAMESTATE->m_pCurSteps[PLAYER_1]->m_Timing : GAMESTATE->m_pCurSteps[PLAYER_1]->m_Timing :
GAMESTATE->m_pCurSong->m_SongTiming); GAMESTATE->m_pCurSong->m_SongTiming);
float old = timing.m_fBeat0OffsetInSeconds; float old = timing.m_fBeat0OffsetInSeconds;
timing.m_fBeat0OffsetInSeconds = StringToFloat( sNew ); timing.m_fBeat0OffsetInSeconds = StringToFloat(sNew);
float delta = timing.m_fBeat0OffsetInSeconds - old; float delta = timing.m_fBeat0OffsetInSeconds - old;
if (GAMESTATE->m_bIsUsingStepTiming) if (GAMESTATE->m_bIsUsingStepTiming)
{ {
GAMESTATE->m_pCurSteps[PLAYER_1]->m_Attacks.UpdateStartTimes(delta); GAMESTATE->m_pCurSteps[PLAYER_1]->m_Attacks.UpdateStartTimes(delta);
@@ -3583,9 +3595,14 @@ void ScreenEdit::DisplayTimingMenu()
g_TimingDataInformation.rows[bpm].SetOneUnthemedChoice( ssprintf("%.6f", pTime.GetBPMAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[bpm].SetOneUnthemedChoice( ssprintf("%.6f", pTime.GetBPMAtBeat( fBeat ) ) );
g_TimingDataInformation.rows[stop].SetOneUnthemedChoice( ssprintf("%.6f", pTime.GetStopAtBeat( fBeat ) ) ) ; g_TimingDataInformation.rows[stop].SetOneUnthemedChoice( ssprintf("%.6f", pTime.GetStopAtBeat( fBeat ) ) ) ;
g_TimingDataInformation.rows[delay].SetOneUnthemedChoice( ssprintf("%.6f", pTime.GetDelayAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[delay].SetOneUnthemedChoice( ssprintf("%.6f", pTime.GetDelayAtBeat( fBeat ) ) );
g_TimingDataInformation.rows[time_signature].SetOneUnthemedChoice(ssprintf("%d / %d",
pTime.GetTimeSignatureNumeratorAtBeat( fBeat ), g_TimingDataInformation.rows[time_signature].SetOneUnthemedChoice(
pTime.GetTimeSignatureDenominatorAtBeat( fBeat ) ) ); ssprintf( "%d / %d",
pTime.GetTimeSignatureSegmentAtBeat(fBeat)->GetNum(),
pTime.GetTimeSignatureSegmentAtBeat(fBeat)->GetDen()
)
);
g_TimingDataInformation.rows[label].SetOneUnthemedChoice( pTime.GetLabelAtBeat( fBeat ).c_str() ); g_TimingDataInformation.rows[label].SetOneUnthemedChoice( pTime.GetLabelAtBeat( fBeat ).c_str() );
g_TimingDataInformation.rows[tickcount].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTickcountAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[tickcount].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTickcountAtBeat( fBeat ) ) );
g_TimingDataInformation.rows[combo].SetOneUnthemedChoice( ssprintf("%d / %d", g_TimingDataInformation.rows[combo].SetOneUnthemedChoice( ssprintf("%d / %d",
@@ -4167,9 +4184,9 @@ void ScreenEdit::HandleAlterMenuChoice(AlterMenuChoice c, const vector<int> &iAn
} }
case convert_to_fake: case convert_to_fake:
{ {
float startBeat = NoteRowToBeat(m_NoteFieldEdit.m_iBeginMarker); int startRow = m_NoteFieldEdit.m_iBeginMarker;
float lengthBeat = NoteRowToBeat(m_NoteFieldEdit.m_iEndMarker) - startBeat; float lengthBeat = NoteRowToBeat(m_NoteFieldEdit.m_iEndMarker) - NoteRowToBeat(startRow);
GetAppropriateTiming().SetFakeAtBeat(startBeat,lengthBeat); GetAppropriateTiming().AddSegment( FakeSegment(startRow,lengthBeat) );
SetDirty(true); SetDirty(true);
break; break;
} }
@@ -4302,82 +4319,28 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector<int> &iAns
break; break;
case paste_partial_timing_at_beat: case paste_partial_timing_at_beat:
{ {
#if 0
int firstRow = BeatToNoteRow(GetAppropriatePosition().m_fSongBeat); int firstRow = BeatToNoteRow(GetAppropriatePosition().m_fSongBeat);
FOREACH_ENUM(TimingSegmentType, tst)
FOREACH_TimingSegmentType( tst )
{ {
/* TODO: Maybe wipe out the already there timing data first? /* TODO: Maybe wipe out the already there timing data first?
* We need to identify the max row within the timing data first. */ * We need to identify the max row within the timing data first. */
for (unsigned i = 0; i < this->clipboardTiming.m_avpTimingSegments[tst].size(); i++) const vector<TimingSegment*> &vSegs = clipboardTiming.GetTimingSegments(tst);
{
// TODO: This REALLY needs improving.
TimingSegment * org = this->clipboardTiming.m_avpTimingSegments[tst][i];
TimingSegment * cpy;
switch (tst) /* TODO: this is an exact dupe of TimingData::CopyRange... */
for (unsigned i = 0; i < vSegs.size(); i++)
{ {
case SEGMENT_BPM: const TimingSegment *seg = vSegs[i];
{ TimingSegment *cpy = seg->Copy();
cpy = new BPMSegment(*(static_cast<BPMSegment *>(org)));
break; int oldRow = cpy->GetRow() + firstRow;
}
case SEGMENT_STOP:
{
cpy = new StopSegment(*(static_cast<StopSegment *>(org)));
break;
}
case SEGMENT_DELAY:
{
cpy = new DelaySegment(*(static_cast<DelaySegment *>(org)));
break;
}
case SEGMENT_TIME_SIG:
{
cpy = new TimeSignatureSegment(*(static_cast<TimeSignatureSegment *>(org)));
break;
}
case SEGMENT_WARP:
{
cpy = new WarpSegment(*(static_cast<WarpSegment *>(org)));
break;
}
case SEGMENT_LABEL:
{
cpy = new LabelSegment(*(static_cast<LabelSegment *>(org)));
break;
}
case SEGMENT_TICKCOUNT:
{
cpy = new TickcountSegment(*(static_cast<TickcountSegment *>(org)));
break;
}
case SEGMENT_COMBO:
{
cpy = new ComboSegment(*(static_cast<ComboSegment *>(org)));
break;
}
case SEGMENT_SPEED:
{
cpy = new SpeedSegment(*(static_cast<SpeedSegment *>(org)));
break;
}
case SEGMENT_SCROLL:
{
cpy = new ScrollSegment(*(static_cast<ScrollSegment *>(org)));
break;
}
case SEGMENT_FAKE:
{
cpy = new FakeSegment(*(static_cast<FakeSegment *>(org)));
break;
}
default: FAIL_M(ssprintf("An unknown timing segment type %d can't be copied over!", tst));
}
int oldRow = cpy->GetRow();
int newRow = oldRow + firstRow; int newRow = oldRow + firstRow;
cpy->SetRow(newRow); cpy->SetRow(newRow);
GetAppropriateTiming().AddSegment(tst, cpy); GetAppropriateTiming().AddSegment( cpy );
} }
} }
#endif
break; break;
} }
case insert_and_shift: case insert_and_shift:
@@ -4991,7 +4954,8 @@ void ScreenEdit::CheckNumberOfNotesAndUndo()
if( EDIT_MODE.GetValue() != EditMode_Home ) if( EDIT_MODE.GetValue() != EditMode_Home )
return; return;
const TimeSignatureSegment * curTime = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat ); const float fBeat = GAMESTATE->m_pPlayerState[PLAYER_1]->m_Position.m_fSongBeat;
const TimeSignatureSegment * curTime = GAMESTATE->m_pCurSong->m_SongTiming.GetTimeSignatureSegmentAtBeat( fBeat );
int rowsPerMeasure = curTime->GetDen() * curTime->GetNum(); int rowsPerMeasure = curTime->GetDen() * curTime->GetNum();
for( int row=0; row<=m_NoteDataEdit.GetLastRow(); row+=rowsPerMeasure ) for( int row=0; row<=m_NoteDataEdit.GetLastRow(); row+=rowsPerMeasure )
+243 -680
View File
File diff suppressed because it is too large Load Diff
+172 -520
View File
@@ -10,16 +10,29 @@ struct lua_State;
/** @brief Compare a TimingData segment's properties with one another. */ /** @brief Compare a TimingData segment's properties with one another. */
#define COMPARE(x) if(this->x!=other.x) return false; #define COMPARE(x) if(this->x!=other.x) return false;
/* convenience functions to handle static casting */ /* convenience functions to handle static casting */
template<class T> T* ToDerived( TimingSegment *t, TimingSegmentType tst ) template<class T>
inline T ToDerived( const TimingSegment *t, TimingSegmentType tst )
{ {
ASSERT( t->GetType() == tst ); // type checking ASSERT_M( t && tst == t->GetType(),
return static_cast<T*>( t ); ssprintf("type mismatch (expected %s, got %s)",
TimingSegmentTypeToString(tst).c_str(),
TimingSegmentTypeToString(t->GetType()).c_str() ) );
return static_cast<T>( t );
} }
#define TimingSegmentToXWithName(Seg, SegName, SegType) \ #define TimingSegmentToXWithName(Seg, SegName, SegType) \
inline Seg* To##SegName( TimingSegment *t ) { return ToDerived<Seg>(t, SegType); } inline const Seg* To##SegName( const TimingSegment *t ) \
{ \
ASSERT( t->GetType() == SegType ); \
return static_cast<const Seg*>( t ); \
} \
inline Seg* To##SegName( TimingSegment *t ) \
{ \
ASSERT( t->GetType() == SegType ); \
return static_cast<Seg*>( t ); \
}
#define TimingSegmentToX(Seg, SegType) \ #define TimingSegmentToX(Seg, SegType) \
TimingSegmentToXWithName(Seg##Segment, Seg, SEGMENT_##SegType) TimingSegmentToXWithName(Seg##Segment, Seg, SEGMENT_##SegType)
@@ -46,10 +59,25 @@ TimingSegmentToX( Fake, FAKE );
class TimingData class TimingData
{ {
public: public:
void AddSegment(TimingSegmentType tst, TimingSegment * seg); /**
* @brief Sets up initial timing data with a defined offset.
* @param fOffset the offset from the 0th beat. */
TimingData( float fOffset = 0 );
~TimingData();
unsigned GetSegmentIndexAtRow(TimingSegmentType tst, int row) const; TimingData( const TimingData& rhs ) : m_sFile(rhs.m_sFile),
unsigned GetSegmentIndexAtBeat(TimingSegmentType tst, float beat) const m_fBeat0OffsetInSeconds(rhs.m_fBeat0OffsetInSeconds)
{
const vector<TimingSegment*>* avpSegs = rhs.m_avpTimingSegments;
// deep-copy the TimingSegment pointers
FOREACH_TimingSegmentType( tst )
for( unsigned i = 0; i < avpSegs[tst].size(); ++i )
m_avpTimingSegments[tst].push_back( avpSegs[tst][i]->Copy() );
}
int GetSegmentIndexAtRow(TimingSegmentType tst, int row) const;
int GetSegmentIndexAtBeat(TimingSegmentType tst, float beat) const
{ {
return GetSegmentIndexAtRow( tst, BeatToNoteRow(beat) ); return GetSegmentIndexAtRow( tst, BeatToNoteRow(beat) );
} }
@@ -68,12 +96,6 @@ public:
bool empty() const; bool empty() const;
/**
* @brief Sets up initial timing data with a defined offset.
* @param fOffset the offset from the 0th beat. */
TimingData(float fOffset = 0);
~TimingData();
TimingData CopyRange(int startRow, int endRow) const; TimingData CopyRange(int startRow, int endRow) const;
/** /**
* @brief Gets the actual BPM of the song, * @brief Gets the actual BPM of the song,
@@ -85,30 +107,6 @@ public:
* @param highest the highest allowed max BPM. * @param highest the highest allowed max BPM.
*/ */
void GetActualBPM( float &fMinBPMOut, float &fMaxBPMOut, float highest = FLT_MAX ) const; void GetActualBPM( float &fMinBPMOut, float &fMaxBPMOut, float highest = FLT_MAX ) const;
/**
* @brief Retrieve the BPM at the given row.
* @param iNoteRow the row in question.
* @return the BPM.
*/
float GetBPMAtRow( int iNoteRow ) const;
/**
* @brief Retrieve the BPM at the given beat.
* @param fBeat the beat in question.
* @return the BPM.
*/
float GetBPMAtBeat( float fBeat ) const { return GetBPMAtRow( BeatToNoteRow(fBeat)); }
/**
* @brief Set the row to have the new BPM.
* @param iNoteRow the row to have the new BPM.
* @param fBPM the BPM.
*/
void SetBPMAtRow( int iNoteRow, float fBPM );
/**
* @brief Set the beat to have the new BPM.
* @param fBeat the beat to have the new BPM.
* @param fBPM the BPM.
*/
void SetBPMAtBeat( float fBeat, float fBPM ) { SetBPMAtRow( BeatToNoteRow(fBeat), fBPM ); }
/** /**
* @brief Retrieve the TimingSegment at the specified row. * @brief Retrieve the TimingSegment at the specified row.
@@ -116,6 +114,7 @@ public:
* @param tst the TimingSegmentType requested. * @param tst the TimingSegmentType requested.
* @return the segment in question. * @return the segment in question.
*/ */
const TimingSegment* GetSegmentAtRow( int iNoteRow, TimingSegmentType tst ) const;
TimingSegment* GetSegmentAtRow( int iNoteRow, TimingSegmentType tst ); TimingSegment* GetSegmentAtRow( int iNoteRow, TimingSegmentType tst );
/** /**
@@ -124,509 +123,174 @@ public:
* @param tst the TimingSegmentType requested. * @param tst the TimingSegmentType requested.
* @return the segment in question. * @return the segment in question.
*/ */
TimingSegment* GetSegmentAtBeat( float fBeat, TimingSegmentType tst ) const TimingSegment* GetSegmentAtBeat( float fBeat, TimingSegmentType tst ) const
{ {
return GetSegmentAtRow( BeatToNoteRow(fBeat), tst ); return GetSegmentAtRow( BeatToNoteRow(fBeat), tst );
} }
TimingSegment* GetSegmentAtBeat( float fBeat, TimingSegmentType tst )
{
return const_cast<TimingSegment*>( GetSegmentAtBeat(fBeat, tst) );
}
void SetTimingSegmentAtRow( TimingSegment *seg, int iNoteRow ); #define DefineSegmentWithName(Seg, SegName, SegType) \
const Seg* Get##Seg##AtRow( int iNoteRow ) const \
{ \
/* XXX: convenience shortcuts. We should get rid of these later. */ const TimingSegment *t = GetSegmentAtRow( iNoteRow, SegType ); \
#define GetAndSetSegmentWithName(Seg, SegName, SegType) \ return To##SegName( t ); \
} \
Seg* Get##Seg##AtRow( int iNoteRow ) \ Seg* Get##Seg##AtRow( int iNoteRow ) \
{ \ { \
TimingSegment *t = GetSegmentAtRow( iNoteRow, SegType ); \ return const_cast<Seg*> (((const TimingData*)this)->Get##Seg##AtRow(iNoteRow) ); \
return To##SegName( t ); \ } \
const Seg* Get##Seg##AtBeat( float fBeat ) const \
{ \
return Get##Seg##AtRow( BeatToNoteRow(fBeat) ); \
} \ } \
Seg* Get##Seg##AtBeat( float fBeat ) \ Seg* Get##Seg##AtBeat( float fBeat ) \
{ \ { \
TimingSegment *t = GetSegmentAtBeat( fBeat, SegType ); \ return const_cast<Seg*> (((const TimingData*)this)->Get##Seg##AtBeat(fBeat) ); \
return To##SegName( t ); \
} \ } \
void Set##SegName##AtRow( Seg &seg, int iNoteRow ) \ void AddSegment( const Seg &seg ) \
{ \ { \
SetTimingSegmentAtRow( &seg, iNoteRow ); \ AddSegment( &seg ); \
} }
// "XXX: this comment (and quote mark) exists so nano won't
// display the rest of this file as one giant string
// (TimeSignature,TIME_SIG) -> (TimeSignatureSegment,SEGMENT_TIME_SIG) // (TimeSignature,TIME_SIG) -> (TimeSignatureSegment,SEGMENT_TIME_SIG)
#define GetAndSetSegment(Seg, SegType ) \ #define DefineSegment(Seg, SegType ) \
GetAndSetSegmentWithName( Seg##Segment, Seg, SEGMENT_##SegType ) DefineSegmentWithName( Seg##Segment, Seg, SEGMENT_##SegType )
GetAndSetSegment( BPM, BPM ); DefineSegment( BPM, BPM );
GetAndSetSegment( Stop, STOP ); DefineSegment( Stop, STOP );
GetAndSetSegment( Delay, DELAY ); DefineSegment( Delay, DELAY );
GetAndSetSegment( Warp, WARP ); DefineSegment( Warp, WARP );
GetAndSetSegment( Label, LABEL ); DefineSegment( Label, LABEL );
GetAndSetSegment( Tickcount, TICKCOUNT ); DefineSegment( Tickcount, TICKCOUNT );
GetAndSetSegment( Combo, COMBO ); DefineSegment( Combo, COMBO );
GetAndSetSegment( Speed, SPEED ); DefineSegment( Speed, SPEED );
GetAndSetSegment( Scroll, SCROLL ); DefineSegment( Scroll, SCROLL );
GetAndSetSegment( Fake, FAKE ); DefineSegment( Fake, FAKE );
GetAndSetSegment( TimeSignature, TIME_SIG ); DefineSegment( TimeSignature, TIME_SIG );
#undef GetAndSetSegmentWithName #undef DefineSegmentWithName
#undef GetAndSetSegment #undef DefineSegment
/* convenience aliases (Set functions are deprecated) */
float GetBPMAtRow( int iNoteRow ) const { return GetBPMSegmentAtRow(iNoteRow)->GetBPM(); }
float GetBPMAtBeat( float fBeat ) const { return GetBPMAtRow( BeatToNoteRow(fBeat) ); }
void SetBPMAtRow( int iNoteRow, float fBPM ) { AddSegment( BPMSegment(iNoteRow, fBPM) ); }
void SetBPMAtBeat( float fBeat, float fBPM ) { SetBPMAtRow( BeatToNoteRow(fBeat), fBPM ); }
/** float GetStopAtRow( int iNoteRow ) const { return GetStopSegmentAtRow(iNoteRow)->GetPause(); }
* @brief Retrieve the stop time at the given row.
* @param iNoteRow the row in question.
* @return the stop time.
*/
float GetStopAtRow( int iNoteRow ) const;
/**
* @brief Retrieve the stop time at the given beat.
* @param fBeat the beat in question.
* @return the stop time.
*/
float GetStopAtBeat( float fBeat ) const { return GetStopAtRow( BeatToNoteRow(fBeat) ); } float GetStopAtBeat( float fBeat ) const { return GetStopAtRow( BeatToNoteRow(fBeat) ); }
void SetStopAtRow( int iNoteRow, float fSeconds ) { AddSegment( StopSegment(iNoteRow, fSeconds) ); }
void SetStopAtBeat( float fBeat, float fSeconds ) { SetStopAtRow( BeatToNoteRow(fBeat), fSeconds ); }
/** float GetDelayAtRow( int iNoteRow ) const { return GetDelaySegmentAtRow(iNoteRow)->GetPause(); }
* @brief Set the row to have the new stop time.
* @param iNoteRow the row to have the new stop time.
* @param fSeconds the new stop time.
*/
void SetStopAtRow( int iNoteRow, float fSeconds );
/**
* @brief Set the beat to have the new stop time.
* @param fBeat to have the new stop time.
* @param fSeconds the new stop time.
*/
void SetStopAtBeat( float fBeat, float fSeconds ) { SetStopAtRow( BeatToNoteRow(fBeat), fSeconds); }
/**
* @brief Retrieve the delay time at the given row.
* @param iNoteRow the row in question.
* @return the delay time.
*/
float GetDelayAtRow( int iNoteRow ) const;
/**
* @brief Retrieve the delay time at the given beat.
* @param fBeat the beat in question.
* @return the delay time.
*/
float GetDelayAtBeat( float fBeat ) const { return GetDelayAtRow( BeatToNoteRow(fBeat) ); } float GetDelayAtBeat( float fBeat ) const { return GetDelayAtRow( BeatToNoteRow(fBeat) ); }
void SetDelayAtRow( int iNoteRow, float fSeconds ) { AddSegment( DelaySegment(iNoteRow, fSeconds) ); }
void SetDelayAtBeat( float fBeat, float fSeconds ) { SetDelayAtRow( BeatToNoteRow(fBeat), fSeconds ); }
/** void SetTimeSignatureAtRow( int iNoteRow, int iNum, int iDen )
* @brief Set the row to have the new delay time. {
* AddSegment( TimeSignatureSegment(iNoteRow, iNum, iDen) );
* This function was added specifically for sm-ssc. }
* @param iNoteRow the row to have the new delay time.
* @param fSeconds the new delay time.
*/
void SetDelayAtRow( int iNoteRow, float fSeconds );
/**
* @brief Set the beat to have the new delay time.
*
* This function was added specifically for sm-ssc.
* @param fBeat the beat to have the new delay time.
* @param fSeconds the new delay time.
*/
void SetDelayAtBeat( float fBeat, float fSeconds ) { SetDelayAtRow( BeatToNoteRow(fBeat), fSeconds); }
/** void SetTimeSignatureAtBeat( float fBeat, int iNum, int iDen )
* @brief Retrieve the Time Signature's numerator at the given row. {
* @param iNoteRow the row in question. SetTimeSignatureAtRow( BeatToNoteRow(fBeat), iNum, iDen );
* @return the numerator. }
*/
int GetTimeSignatureNumeratorAtRow( int iNoteRow );
/**
* @brief Retrieve the Time Signature's numerator at the given beat.
* @param fBeat the beat in question.
* @return the numerator.
*/
int GetTimeSignatureNumeratorAtBeat( float fBeat ) { return GetTimeSignatureNumeratorAtRow( BeatToNoteRow(fBeat) ); }
/**
* @brief Retrieve the Time Signature's denominator at the given row.
* @param iNoteRow the row in question.
* @return the denominator.
*/
int GetTimeSignatureDenominatorAtRow( int iNoteRow );
/**
* @brief Retrieve the Time Signature's denominator at the given beat.
* @param fBeat the beat in question.
* @return the denominator.
*/
int GetTimeSignatureDenominatorAtBeat( float fBeat ) { return GetTimeSignatureDenominatorAtRow( BeatToNoteRow(fBeat) ); }
/**
* @brief Set the row to have the new Time Signature.
* @param iNoteRow the row to have the new Time Signature.
* @param iNumerator the numerator.
* @param iDenominator the denominator.
*/
void SetTimeSignatureAtRow( int iNoteRow, int iNumerator, int iDenominator );
/**
* @brief Set the beat to have the new Time Signature.
* @param fBeat the beat to have the new Time Signature.
* @param iNumerator the numerator.
* @param iDenominator the denominator.
*/
void SetTimeSignatureAtBeat( float fBeat, int iNumerator, int iDenominator ) { SetTimeSignatureAtRow( BeatToNoteRow(fBeat), iNumerator, iDenominator ); }
/**
* @brief Set the row to have the new Time Signature numerator.
* @param iNoteRow the row to have the new Time Signature numerator.
* @param iNumerator the numerator.
*/
void SetTimeSignatureNumeratorAtRow( int iNoteRow, int iNumerator );
/**
* @brief Set the beat to have the new Time Signature numerator.
* @param fBeat the beat to have the new Time Signature numerator.
* @param iNumerator the numerator.
*/
void SetTimeSignatureNumeratorAtBeat( float fBeat, int iNumerator ) { SetTimeSignatureNumeratorAtRow( BeatToNoteRow(fBeat), iNumerator); }
/**
* @brief Set the row to have the new Time Signature denominator.
* @param iNoteRow the row to have the new Time Signature denominator.
* @param iDenominator the denominator.
*/
void SetTimeSignatureDenominatorAtRow( int iNoteRow, int iDenominator );
/**
* @brief Set the beat to have the new Time Signature denominator.
* @param fBeat the beat to have the new Time Signature denominator.
* @param iDenominator the denominator.
*/
void SetTimeSignatureDenominatorAtBeat( float fBeat, int iDenominator ) { SetTimeSignatureDenominatorAtRow( BeatToNoteRow(fBeat), iDenominator); }
/** float GetWarpAtRow( int iNoteRow ) const { return GetWarpSegmentAtRow(iNoteRow)->GetLength(); }
* @brief Determine the beat to warp to. float GetWarpAtBeat( float fBeat ) const { return GetWarpAtRow( BeatToNoteRow(fBeat) ); }
* @param iRow The row you start on. /* Note: fLength is in beats, not rows */
* @return the beat you warp to. void SetWarpAtRow( int iRow, float fLength ) { AddSegment( WarpSegment(iRow, fLength) ); }
*/ void SetWarpAtBeat( float fBeat, float fLength ) { AddSegment( WarpSegment(BeatToNoteRow(fBeat), fLength) ); }
float GetWarpAtRow( int iRow ) const;
/**
* @brief Determine the beat to warp to.
* @param fBeat The beat you start on.
* @return the beat you warp to.
*/
float GetWarpAtBeat( float fBeat ) const { return GetWarpAtRow( BeatToNoteRow( fBeat ) ); }
/**
* @brief Set the beat to warp to given a starting row.
* @param iRow The row to start on.
* @param fNew The destination beat.
*/
void SetWarpAtRow( int iRow, float fNew );
/**
* @brief Set the beat to warp to given a starting beat.
* @param fBeat The beat to start on.
* @param fNew The destination beat.
*/
void SetWarpAtBeat( float fBeat, float fNew ) { SetWarpAtRow( BeatToNoteRow( fBeat ), fNew ); }
/** int GetTickcountAtRow( int iNoteRow ) const { return GetTickcountSegmentAtRow(iNoteRow)->GetTicks(); }
* @brief Checks if the row is inside a warp.
* @param iRow the row to focus on.
* @return true if the row is inside a warp, false otherwise.
*/
bool IsWarpAtRow( int iRow ) const;
/**
* @brief Checks if the beat is inside a warp.
* @param fBeat the beat to focus on.
* @return true if the row is inside a warp, false otherwise.
*/
bool IsWarpAtBeat( float fBeat ) const { return IsWarpAtRow( BeatToNoteRow( fBeat ) ); }
/**
* @brief Retrieve the Tickcount at the given row.
* @param iNoteRow the row in question.
* @return the Tickcount.
*/
int GetTickcountAtRow( int iNoteRow ) const;
/**
* @brief Retrieve the Tickcount at the given beat.
* @param fBeat the beat in question.
* @return the Tickcount.
*/
int GetTickcountAtBeat( float fBeat ) const { return GetTickcountAtRow( BeatToNoteRow(fBeat) ); } int GetTickcountAtBeat( float fBeat ) const { return GetTickcountAtRow( BeatToNoteRow(fBeat) ); }
/** void SetTickcountAtRow( int iNoteRow, int iTicks ) { AddSegment( TickcountSegment(iNoteRow, iTicks) ); }
* @brief Set the row to have the new tickcount.
* @param iNoteRow the row to have the new tickcount.
* @param iTicks the tickcount.
*/
void SetTickcountAtRow( int iNoteRow, int iTicks );
/**
* @brief Set the beat to have the new tickcount.
* @param fBeat the beat to have the new tickcount.
* @param iTicks the tickcount.
*/
void SetTickcountAtBeat( float fBeat, int iTicks ) { SetTickcountAtRow( BeatToNoteRow( fBeat ), iTicks ); } void SetTickcountAtBeat( float fBeat, int iTicks ) { SetTickcountAtRow( BeatToNoteRow( fBeat ), iTicks ); }
/** int GetComboAtRow( int iNoteRow ) const { return GetComboSegmentAtRow(iNoteRow)->GetCombo(); }
* @brief Retrieve the Combo at the given row.
* @param iNoteRow the row in question.
* @return the Combo.
*/
int GetComboAtRow( int iNoteRow ) const;
/**
* @brief Retrieve the Combo at the given beat.
* @param fBeat the beat in question.
* @return the Combo.
*/
int GetComboAtBeat( float fBeat ) const { return GetComboAtRow( BeatToNoteRow(fBeat) ); } int GetComboAtBeat( float fBeat ) const { return GetComboAtRow( BeatToNoteRow(fBeat) ); }
/** int GetMissComboAtRow( int iNoteRow ) const { return GetComboSegmentAtRow(iNoteRow)->GetMissCombo(); }
* @brief Retrieve the Miss Combo at the given row.
* @param iNoteRow the row in question.
* @return the Miss Combo.
*/
int GetMissComboAtRow( int iNoteRow ) const;
/**
* @brief Retrieve the Miss Combo at the given beat.
* @param fBeat the beat in question.
* @return the Miss Combo.
*/
int GetMissComboAtBeat( float fBeat ) const { return GetMissComboAtRow( BeatToNoteRow(fBeat) ); } int GetMissComboAtBeat( float fBeat ) const { return GetMissComboAtRow( BeatToNoteRow(fBeat) ); }
/**
* @brief Set the row to have the new Combo.
* @param iNoteRow the row to have the new Combo.
* @param iCombo the Combo.
*/
void SetComboAtRow( int iNoteRow, int iCombo );
/**
* @brief Set the beat to have the new Combo.
* @param fBeat the beat to have the new Combo.
* @param iCombo the Combo.
*/
void SetComboAtBeat( float fBeat, int iCombo ) { SetComboAtRow( BeatToNoteRow( fBeat ), iCombo ); }
/**
* @brief Set the row to have the new Combo and Miss Combo.
* @param iNoteRow the row to have the new Combo and Miss Combo.
* @param iCombo the Combo.
* @param iMiss the Miss Combo.
*/
void SetComboAtRow( int iNoteRow, int iCombo, int iMiss );
/**
* @brief Set the beat to have the new Combo and Miss Combo.
* @param fBeat the beat to have the new Combo and Miss Combo.
* @param iCombo the Combo.
* @param iMiss the Miss Combo.
*/
void SetComboAtBeat( float fBeat, int iCombo, int iMiss ) { SetComboAtRow( BeatToNoteRow( fBeat ), iCombo, iMiss ); }
/**
* @brief Set the row to have the new Combo.
* @param iNoteRow the row to have the new Combo.
* @param iCombo the Combo.
*/
void SetHitComboAtRow( int iNoteRow, int iCombo );
/**
* @brief Set the beat to have the new Combo.
* @param fBeat the beat to have the new Combo.
* @param iCombo the Combo.
*/
void SetHitComboAtBeat( float fBeat, int iCombo ) { SetHitComboAtRow( BeatToNoteRow( fBeat ), iCombo ); }
/**
* @brief Set the row to have the new Miss Combo.
* @param iNoteRow the row to have the new Miss Combo.
* @param iCombo the Miss Combo.
*/
void SetMissComboAtRow( int iNoteRow, int iCombo );
/**
* @brief Set the beat to have the new Miss Combo.
* @param fBeat the beat to have the new Miss Combo.
* @param iCombo the Miss Combo.
*/
void SetMissComboAtBeat( float fBeat, int iCombo ) { SetMissComboAtRow( BeatToNoteRow( fBeat ), iCombo ); }
/** const RString& GetLabelAtRow( int iNoteRow ) const { return GetLabelSegmentAtRow(iNoteRow)->GetLabel(); }
* @brief Retrieve the Label at the given row. const RString& GetLabelAtBeat( float fBeat ) const { return GetLabelAtRow( BeatToNoteRow(fBeat) ); }
* @param iNoteRow the row in question. void SetLabelAtRow( int iNoteRow, const RString& sLabel ) { AddSegment( LabelSegment(iNoteRow,sLabel) ); }
* @return the Label.
*/
RString GetLabelAtRow( int iNoteRow ) const;
/**
* @brief Retrieve the Label at the given beat.
* @param fBeat the beat in question.
* @return the Label.
*/
RString GetLabelAtBeat( float fBeat ) const { return GetLabelAtRow( BeatToNoteRow(fBeat) ); }
/**
* @brief Set the row to have the new Label.
* @param iNoteRow the row to have the new Label.
* @param sLabel the Label.
*/
void SetLabelAtRow( int iNoteRow, const RString sLabel );
/**
* @brief Set the beat to have the new Label.
* @param fBeat the beat to have the new Label.
* @param sLabel the Label.
*/
void SetLabelAtBeat( float fBeat, const RString sLabel ) { SetLabelAtRow( BeatToNoteRow( fBeat ), sLabel ); } void SetLabelAtBeat( float fBeat, const RString sLabel ) { SetLabelAtRow( BeatToNoteRow( fBeat ), sLabel ); }
bool DoesLabelExist( const RString& sLabel ) const;
/** float GetSpeedPercentAtRow( int iNoteRow ) { return GetSpeedSegmentAtRow(iNoteRow)->GetRatio(); }
* @brief Determine if the requisite label already exists.
* @param sLabel the label to check.
* @return true if it exists, false otherwise. */
bool DoesLabelExist( RString sLabel ) const;
/**
* @brief Retrieve the Speed's percent at the given row.
* @param iNoteRow the row in question.
* @return the percent.
*/
float GetSpeedPercentAtRow( int iNoteRow );
/**
* @brief Retrieve the Speed's percent at the given beat.
* @param fBeat the beat in question.
* @return the percent.
*/
float GetSpeedPercentAtBeat( float fBeat ) { return GetSpeedPercentAtRow( BeatToNoteRow(fBeat) ); } float GetSpeedPercentAtBeat( float fBeat ) { return GetSpeedPercentAtRow( BeatToNoteRow(fBeat) ); }
/**
* @brief Retrieve the Speed's wait at the given row. float GetSpeedWaitAtRow( int iNoteRow ) { return GetSpeedSegmentAtRow(iNoteRow)->GetDelay(); }
* @param iNoteRow the row in question.
* @return the wait.
*/
float GetSpeedWaitAtRow( int iNoteRow );
/**
* @brief Retrieve the Speed's wait at the given beat.
* @param fBeat the beat in question.
* @return the wait.
*/
float GetSpeedWaitAtBeat( float fBeat ) { return GetSpeedWaitAtRow( BeatToNoteRow(fBeat) ); } float GetSpeedWaitAtBeat( float fBeat ) { return GetSpeedWaitAtRow( BeatToNoteRow(fBeat) ); }
/**
* @brief Retrieve the Speed's mode at the given row. // XXX: is there any point to having specific unit types?
* @param iNoteRow the row in question. SpeedSegment::BaseUnit GetSpeedModeAtRow( int iNoteRow ) const { return GetSpeedSegmentAtRow(iNoteRow)->GetUnit(); }
* @return the mode.
*/
SpeedSegment::BaseUnit GetSpeedModeAtRow( int iNoteRow );
/**
* @brief Retrieve the Speed's mode at the given beat.
* @param fBeat the beat in question.
* @return the mode.
*/
SpeedSegment::BaseUnit GetSpeedModeAtBeat( float fBeat ) { return GetSpeedModeAtRow( BeatToNoteRow(fBeat) ); } SpeedSegment::BaseUnit GetSpeedModeAtBeat( float fBeat ) { return GetSpeedModeAtRow( BeatToNoteRow(fBeat) ); }
/**
* @brief Set the row to have the new Speed. void SetSpeedAtRow( int iNoteRow, float fPercent, float fWait, SpeedSegment::BaseUnit unit )
* @param iNoteRow the row to have the new Speed. {
* @param fPercent the percent. AddSegment( SpeedSegment(iNoteRow, fPercent, fWait, unit) );
* @param fWait the wait. }
* @param usMode the mode.
*/ void SetSpeedAtBeat( float fBeat, float fPercent, float fWait, SpeedSegment::BaseUnit unit )
void SetSpeedAtRow( int iNoteRow, float fPercent, float fWait, SpeedSegment::BaseUnit unit ); {
/** SetSpeedAtRow( BeatToNoteRow(fBeat), fPercent, fWait, unit );
* @brief Set the beat to have the new Speed. }
* @param fBeat the beat to have the new Speed.
* @param fPercent the percent. void SetSpeedPercentAtRow( int iNoteRow, float fPercent )
* @param fWait the wait. {
* @param usMode the mode. const SpeedSegment* seg = GetSpeedSegmentAtRow(iNoteRow);
*/ SetSpeedAtRow( iNoteRow, fPercent, seg->GetDelay(), seg->GetUnit() );
void SetSpeedAtBeat( float fBeat, float fPercent, float fWait, SpeedSegment::BaseUnit unit ) { SetSpeedAtRow( BeatToNoteRow(fBeat), fPercent, fWait, unit ); } }
/**
* @brief Set the row to have the new Speed percent. void SetSpeedWaitAtRow( int iNoteRow, float fWait )
* @param iNoteRow the row to have the new Speed percent. {
* @param fPercent the percent. const SpeedSegment* seg = GetSpeedSegmentAtRow(iNoteRow);
*/ SetSpeedAtRow( iNoteRow, seg->GetRatio(), fWait, seg->GetUnit() );
void SetSpeedPercentAtRow( int iNoteRow, float fPercent ); }
/**
* @brief Set the beat to have the new Speed percent. void SetSpeedModeAtRow( int iNoteRow, SpeedSegment::BaseUnit unit )
* @param fBeat the beat to have the new Speed percent. {
* @param fPercent the percent. const SpeedSegment* seg = GetSpeedSegmentAtRow(iNoteRow);
*/ SetSpeedAtRow( iNoteRow, seg->GetRatio(), seg->GetDelay(), unit );
}
void SetSpeedPercentAtBeat( float fBeat, float fPercent ) { SetSpeedPercentAtRow( BeatToNoteRow(fBeat), fPercent); } void SetSpeedPercentAtBeat( float fBeat, float fPercent ) { SetSpeedPercentAtRow( BeatToNoteRow(fBeat), fPercent); }
/**
* @brief Set the row to have the new Speed wait.
* @param iNoteRow the row to have the new Speed wait.
* @param fWait the wait.
*/
void SetSpeedWaitAtRow( int iNoteRow, float fWait );
/**
* @brief Set the beat to have the new Speed wait.
* @param fBeat the beat to have the new Speed wait.
* @param fWait the wait.
*/
void SetSpeedWaitAtBeat( float fBeat, float fWait ) { SetSpeedWaitAtRow( BeatToNoteRow(fBeat), fWait); } void SetSpeedWaitAtBeat( float fBeat, float fWait ) { SetSpeedWaitAtRow( BeatToNoteRow(fBeat), fWait); }
/**
* @brief Set the row to have the new Speed mode.
* @param iNoteRow the row to have the new Speed mode.
* @param usMode the mode.
*/
void SetSpeedModeAtRow( int iNoteRow, SpeedSegment::BaseUnit unit );
/**
* @brief Set the beat to have the new Speed mode.
* @param fBeat the beat to have the new Speed mode.
* @param usMode the mode.
*/
void SetSpeedModeAtBeat( float fBeat, SpeedSegment::BaseUnit unit ) { SetSpeedModeAtRow( BeatToNoteRow(fBeat), unit); } void SetSpeedModeAtBeat( float fBeat, SpeedSegment::BaseUnit unit ) { SetSpeedModeAtRow( BeatToNoteRow(fBeat), unit); }
float GetDisplayedSpeedPercent( float fBeat, float fMusicSeconds ) const; float GetDisplayedSpeedPercent( float fBeat, float fMusicSeconds ) const;
/**
* @brief Retrieve the scrolling factor at the given row. float GetScrollAtRow( int iNoteRow ) const { return GetScrollSegmentAtRow(iNoteRow)->GetRatio(); }
* @param iNoteRow the row in question.
* @return the percent.
*/
float GetScrollAtRow( int iNoteRow );
/**
* @brief Retrieve the scrolling factor at the given beat.
* @param fBeat the beat in question.
* @return the percent.
*/
float GetScrollAtBeat( float fBeat ) { return GetScrollAtRow( BeatToNoteRow(fBeat) ); } float GetScrollAtBeat( float fBeat ) { return GetScrollAtRow( BeatToNoteRow(fBeat) ); }
/** void SetScrollAtRow( int iNoteRow, float fPercent ) { AddSegment( ScrollSegment(iNoteRow, fPercent) ); }
* @brief Set the row to have the new Scrolling factor.
* @param iNoteRow the row to have the new Speed.
* @param fPercent the scrolling factor.
*/
void SetScrollAtRow( int iNoteRow, float fPercent );
/**
* @brief Set the row to have the new Scrolling factor.
* @param iNoteRow the row to have the new Speed.
* @param fPercent the scrolling factor.
*/
void SetScrollAtBeat( float fBeat, float fPercent ) { SetScrollAtRow( BeatToNoteRow(fBeat), fPercent ); } void SetScrollAtBeat( float fBeat, float fPercent ) { SetScrollAtRow( BeatToNoteRow(fBeat), fPercent ); }
/** float GetFakeAtRow( int iRow ) const { return GetFakeSegmentAtRow(iRow)->GetLength(); }
* @brief Determine when the fakes end.
* @param iRow The row you start on.
* @return the time when the fakes end.
*/
float GetFakeAtRow( int iRow ) const;
/**
* @brief Determine when the fakes end.
* @param fBeat The beat you start on.
* @return the time when the fakes end.
*/
float GetFakeAtBeat( float fBeat ) const { return GetFakeAtRow( BeatToNoteRow( fBeat ) ); } float GetFakeAtBeat( float fBeat ) const { return GetFakeAtRow( BeatToNoteRow( fBeat ) ); }
/**
* @brief Set the beat to indicate when the FakeSegment ends.
* @param iRow The row to start on.
* @param fNew The destination beat.
*/
void SetFakeAtRow( int iRow, float fNew );
/**
* @brief Set the beat to indicate when the FakeSegment ends.
* @param fBeat The beat to start on.
* @param fNew The destination beat.
*/
void SetFakeAtBeat( float fBeat, float fNew ) { SetFakeAtRow( BeatToNoteRow( fBeat ), fNew ); }
/** bool IsWarpAtRow( int iRow ) const;
* @brief Checks if the row is inside a fake. bool IsWarpAtBeat( float fBeat ) const { return IsWarpAtRow( BeatToNoteRow( fBeat ) ); }
* @param iRow the row to focus on.
* @return true if the row is inside a fake, false otherwise.
*/
bool IsFakeAtRow( int iRow ) const; bool IsFakeAtRow( int iRow ) const;
/**
* @brief Checks if the beat is inside a fake.
* @param fBeat the beat to focus on.
* @return true if the row is inside a fake, false otherwise.
*/
bool IsFakeAtBeat( float fBeat ) const { return IsFakeAtRow( BeatToNoteRow( fBeat ) ); } bool IsFakeAtBeat( float fBeat ) const { return IsFakeAtRow( BeatToNoteRow( fBeat ) ); }
/** /**
* @brief Determine if this notes on this row can be judged. * @brief Determine if this notes on this row can be judged.
* @param row the row to focus on. * @param row the row to focus on.
* @return true if the row can be judged, false otherwise. */ * @return true if the row can be judged, false otherwise. */
bool IsJudgableAtRow( int row ) const bool IsJudgableAtRow( int row ) const { return !IsWarpAtRow(row) && !IsFakeAtRow(row); }
{
return !(IsWarpAtRow(row) || IsFakeAtRow(row));
}
/**
* @brief Determine if this notes on this beat can be judged.
* @param beat the beat to focus on.
* @return true if the row can be judged, false otherwise. */
bool IsJudgableAtBeat( float beat ) const { return IsJudgableAtRow( BeatToNoteRow( beat ) ); } bool IsJudgableAtBeat( float beat ) const { return IsJudgableAtRow( BeatToNoteRow( beat ) ); }
void MultiplyBPMInBeatRange( int iStartIndex, int iEndIndex, float fFactor ); void MultiplyBPMInBeatRange( int iStartIndex, int iEndIndex, float fFactor );
void NoteRowToMeasureAndBeat( int iNoteRow, int &iMeasureIndexOut, int &iBeatIndexOut, int &iRowsRemainder ) const; void NoteRowToMeasureAndBeat( int iNoteRow, int &iMeasureIndexOut, int &iBeatIndexOut, int &iRowsRemainder ) const;
@@ -653,38 +317,16 @@ public:
} }
float GetElapsedTimeFromBeatNoOffset( float fBeat ) const; float GetElapsedTimeFromBeatNoOffset( float fBeat ) const;
float GetDisplayedBeat( float fBeat ) const; float GetDisplayedBeat( float fBeat ) const;
/**
* @brief View the TimingData to see if a song changes its BPM at any point. bool HasBpmChanges() const { return GetTimingSegments(SEGMENT_BPM).size() > 1; }
* @return true if there is at least one change, false otherwise. bool HasStops() const { return !GetTimingSegments(SEGMENT_STOP).empty(); }
*/ bool HasDelays() const { return !GetTimingSegments(SEGMENT_DELAY).empty(); }
bool HasBpmChanges() const; bool HasWarps() const { return !GetTimingSegments(SEGMENT_WARP).empty(); }
/** bool HasFakes() const { return !GetTimingSegments(SEGMENT_FAKE).empty(); }
* @brief View the TimingData to see if there is at least one stop at any point.
* @return true if there is at least one stop, false otherwise.
*/
bool HasStops() const;
/**
* @brief View the TimingData to see if there is at least one delay at any point.
* @return true if there is at least one delay, false otherwise.
*/
bool HasDelays() const;
/**
* @brief View the TimingData to see if there is at least one warp at any point.
* @return true if there is at least one warp, false otherwise.
*/
bool HasWarps() const;
/**
* @brief View the TimingData to see if there is at least one fake segment involved.
* @return true if there is at least one fake segment, false otherwise. */
bool HasFakes() const;
/**
* @brief View the TimingData to see if a song changes its speed scrolling at any point.
* @return true if there is at least one change, false otherwise. */
bool HasSpeedChanges() const; bool HasSpeedChanges() const;
/**
* @brief View the TimingData to see if a song changes its speed scrolling at any point.
* @return true if there is at least one change, false otherwise. */
bool HasScrollChanges() const; bool HasScrollChanges() const;
/** /**
* @brief Compare two sets of timing data to see if they are equal. * @brief Compare two sets of timing data to see if they are equal.
* @param other the other TimingData. * @param other the other TimingData.
@@ -720,6 +362,13 @@ public:
void InsertRows( int iStartRow, int iRowsToAdd ); void InsertRows( int iStartRow, int iRowsToAdd );
void DeleteRows( int iStartRow, int iRowsToDelete ); void DeleteRows( int iStartRow, int iRowsToDelete );
void SortSegments( TimingSegmentType tst );
const vector<TimingSegment*> &GetTimingSegments( TimingSegmentType tst ) const
{
return m_avpTimingSegments[tst];
}
/** /**
* @brief Tidy up the timing data, e.g. provide default BPMs, labels, tickcounts. * @brief Tidy up the timing data, e.g. provide default BPMs, labels, tickcounts.
*/ */
@@ -727,6 +376,7 @@ public:
// Lua // Lua
void PushSelf( lua_State *L ); void PushSelf( lua_State *L );
/** /**
* @brief The file of the song/steps that use this TimingData. * @brief The file of the song/steps that use this TimingData.
* *
@@ -734,15 +384,17 @@ public:
*/ */
RString m_sFile; RString m_sFile;
// All of the following vectors must be sorted before gameplay. /** @brief The initial offset of a song. */
vector<TimingSegment *> m_avpTimingSegments[NUM_TimingSegmentType];
/**
* @brief The initial offset of a song.
*/
float m_fBeat0OffsetInSeconds; float m_fBeat0OffsetInSeconds;
// XXX: this breaks encapsulation. get rid of it ASAP
vector<RString> ToVectorString(TimingSegmentType tst, int dec = 6) const; vector<RString> ToVectorString(TimingSegmentType tst, int dec = 6) const;
protected:
// don't call this directly; use the derived-type overloads.
void AddSegment( const TimingSegment *seg );
// All of the following vectors must be sorted before gameplay.
vector<TimingSegment *> m_avpTimingSegments[NUM_TimingSegmentType];
}; };
#undef COMPARE #undef COMPARE
+93
View File
@@ -24,6 +24,99 @@ void TimingSegment::Scale( int start, int length, int newLength )
SetRow( ScalePosition( start, length, newLength, this->GetRow() ) ); SetRow( ScalePosition( start, length, newLength, this->GetRow() ) );
} }
void TimingSegment::DebugPrint() const
{
LOG->Trace( "\tTimingSegment(%d [%f])", GetRow(), GetBeat() );
}
void BPMSegment::DebugPrint() const
{
LOG->Trace( "\t%s(%d [%f], %f)",
TimingSegmentTypeToString(GetType()).c_str(),
GetRow(), GetBeat(), GetBPM()
);
}
void StopSegment::DebugPrint() const
{
LOG->Trace( "\t%s(%d [%f], %f)",
TimingSegmentTypeToString(GetType()).c_str(),
GetRow(), GetBeat(), GetPause()
);
}
void DelaySegment::DebugPrint() const
{
LOG->Trace( "\t%s(%d [%f], %f)",
TimingSegmentTypeToString(GetType()).c_str(),
GetRow(), GetBeat(), GetPause()
);
}
void TimeSignatureSegment::DebugPrint() const
{
LOG->Trace( "\t%s(%d [%f], %d/%d)",
TimingSegmentTypeToString(GetType()).c_str(),
GetRow(), GetBeat(), GetNum(), GetDen()
);
}
void WarpSegment::DebugPrint() const
{
LOG->Trace( "\t%s(%d [%f], %d [%f])",
TimingSegmentTypeToString(GetType()).c_str(),
GetRow(), GetBeat(), GetLengthRows(), GetLengthBeats()
);
}
void LabelSegment::DebugPrint() const
{
LOG->Trace( "\t%s(%d [%f], %s)",
TimingSegmentTypeToString(GetType()).c_str(),
GetRow(), GetBeat(), GetLabel().c_str()
);
}
void TickcountSegment::DebugPrint() const
{
LOG->Trace( "\t%s(%d [%f], %d)",
TimingSegmentTypeToString(GetType()).c_str(),
GetRow(), GetBeat(), GetTicks()
);
}
void ComboSegment::DebugPrint() const
{
LOG->Trace( "\t%s(%d [%f], %d, %d)",
TimingSegmentTypeToString(GetType()).c_str(),
GetRow(), GetBeat(), GetCombo(), GetMissCombo()
);
}
void SpeedSegment::DebugPrint() const
{
LOG->Trace( "\t%s(%d [%f], %f, %f, %d)",
TimingSegmentTypeToString(GetType()).c_str(),
GetRow(), GetBeat(), GetRatio(), GetDelay(), GetUnit()
);
}
void ScrollSegment::DebugPrint() const
{
LOG->Trace( "\t%s(%d [%f], %f)",
TimingSegmentTypeToString(GetType()).c_str(),
GetRow(), GetBeat(), GetRatio()
);
}
void FakeSegment::DebugPrint() const
{
LOG->Trace( "\t%s(%d [%f], %d [%f])",
TimingSegmentTypeToString(GetType()).c_str(),
GetRow(), GetBeat(), GetLengthRows(), GetLengthBeats()
);
}
RString FakeSegment::ToString(int dec) const RString FakeSegment::ToString(int dec) const
{ {
RString str = "%.0" + IntToString(dec) RString str = "%.0" + IntToString(dec)
+288 -9
View File
@@ -20,26 +20,48 @@ enum TimingSegmentType
TimingSegmentType_Invalid, TimingSegmentType_Invalid,
}; };
// XXX: dumb names
enum SegmentEffectType
{
SegmentEffectType_Row, // takes effect on a single row
SegmentEffectType_Range, // takes effect for a definite amount of rows
SegmentEffectType_Indefinite, // takes effect until the next segment of its type
NUM_SegmentEffectType,
SegmentEffectType_Invalid,
};
#define FOREACH_TimingSegmentType(tst) FOREACH_ENUM(TimingSegmentType, tst)
const RString& TimingSegmentTypeToString( TimingSegmentType tst ); const RString& TimingSegmentTypeToString( TimingSegmentType tst );
const int ROW_INVALID = -1; const int ROW_INVALID = -1;
#define COMPARE(x) if( this->x!=other.x ) return false
#define COMPARE_FLOAT(x) if( fabsf(this->x - other.x) > EPSILON ) return false
/** /**
* @brief The base timing segment for make glorious benefit wolfman * @brief The base timing segment for make glorious benefit wolfman
* XXX: this should be an abstract class.
*/ */
struct TimingSegment struct TimingSegment
{ {
virtual TimingSegmentType GetType() const virtual TimingSegmentType GetType() const { return TimingSegmentType_Invalid; }
{ virtual SegmentEffectType GetEffectType() const { return SegmentEffectType_Invalid; }
return TimingSegmentType_Invalid; virtual TimingSegment* Copy() const = 0;
}
virtual bool IsNotable() const = 0;
virtual void DebugPrint() const;
// don't allow base TimingSegments to be instantiated directly
TimingSegment( int iRow = ROW_INVALID ) : m_iStartRow(iRow) { } TimingSegment( int iRow = ROW_INVALID ) : m_iStartRow(iRow) { }
TimingSegment( float fBeat ) : m_iStartRow(ToNoteRow(fBeat)) { } TimingSegment( float fBeat ) : m_iStartRow(ToNoteRow(fBeat)) { }
TimingSegment(const TimingSegment &other) : TimingSegment(const TimingSegment &other) :
m_iStartRow( other.GetRow() ) { } m_iStartRow( other.GetRow() ) { }
// for our purposes, two floats within this level of error are equal
static const double EPSILON = 1e-4f;
virtual ~TimingSegment() { } virtual ~TimingSegment() { }
/** /**
@@ -66,14 +88,17 @@ struct TimingSegment
return GetRow() < other.GetRow(); return GetRow() < other.GetRow();
} }
// overloads should not call this base version; derived classes
// should only compare contents, and this compares position.
virtual bool operator==( const TimingSegment &other ) const virtual bool operator==( const TimingSegment &other ) const
{ {
LOG->Trace( __PRETTY_FUNCTION__ );
return GetRow() == other.GetRow(); return GetRow() == other.GetRow();
} }
virtual bool operator!=( const TimingSegment &other ) const virtual bool operator!=( const TimingSegment &other ) const
{ {
return !operator==(other); return !this->operator==(other);
} }
private: private:
@@ -95,6 +120,12 @@ private:
struct FakeSegment : public TimingSegment struct FakeSegment : public TimingSegment
{ {
TimingSegmentType GetType() const { return SEGMENT_FAKE; } TimingSegmentType GetType() const { return SEGMENT_FAKE; }
SegmentEffectType GetEffectType() const { return SegmentEffectType_Range; }
TimingSegment* Copy() const { return new FakeSegment(*this); }
bool IsNotable() const { return m_iLengthRows > 0; }
void DebugPrint() const;
FakeSegment() : TimingSegment(), m_iLengthRows(-1) { } FakeSegment() : TimingSegment(), m_iLengthRows(-1) { }
@@ -118,6 +149,23 @@ struct FakeSegment : public TimingSegment
void Scale( int start, int length, int newLength ); void Scale( int start, int length, int newLength );
RString ToString( int dec ) const; RString ToString( int dec ) const;
bool operator==( const FakeSegment &other ) const
{
LOG->Trace( __PRETTY_FUNCTION__ );
COMPARE( m_iLengthRows );
return true;
}
bool operator==( const TimingSegment &other ) const
{
LOG->Trace( __PRETTY_FUNCTION__ );
if( GetType() != other.GetType() )
return false;
return operator==( static_cast<const FakeSegment&>(other) );
}
private: private:
/** @brief The number of rows the FakeSegment is alive for. */ /** @brief The number of rows the FakeSegment is alive for. */
int m_iLengthRows; int m_iLengthRows;
@@ -133,6 +181,11 @@ private:
struct WarpSegment : public TimingSegment struct WarpSegment : public TimingSegment
{ {
TimingSegmentType GetType() const { return SEGMENT_WARP; } TimingSegmentType GetType() const { return SEGMENT_WARP; }
SegmentEffectType GetEffectType() const { return SegmentEffectType_Range; }
TimingSegment* Copy() const { return new WarpSegment(*this); }
bool IsNotable() const { return m_iLengthRows > 0; }
void DebugPrint() const;
WarpSegment() : TimingSegment(), m_iLengthRows(0) { } WarpSegment() : TimingSegment(), m_iLengthRows(0) { }
@@ -154,8 +207,24 @@ struct WarpSegment : public TimingSegment
void SetLength( float fBeats ) { m_iLengthRows = ToNoteRow(fBeats); } void SetLength( float fBeats ) { m_iLengthRows = ToNoteRow(fBeats); }
void Scale( int start, int length, int newLength ); void Scale( int start, int length, int newLength );
RString ToString( int dec ) const; RString ToString( int dec ) const;
bool operator==( const WarpSegment &other ) const
{
LOG->Trace( __PRETTY_FUNCTION__ );
COMPARE( m_iLengthRows );
return true;
}
bool operator==( const TimingSegment &other ) const
{
LOG->Trace( __PRETTY_FUNCTION__ );
if( GetType() != other.GetType() )
return false;
return operator==( static_cast<const WarpSegment&>(other) );
}
private: private:
/** @brief The number of rows the WarpSegment will warp past. */ /** @brief The number of rows the WarpSegment will warp past. */
int m_iLengthRows; int m_iLengthRows;
@@ -170,12 +239,19 @@ private:
* represent how many ticks can be counted in one beat. * represent how many ticks can be counted in one beat.
*/ */
/** @brief The default amount of ticks per beat. */
const unsigned DEFAULT_TICK_COUNT = 4;
struct TickcountSegment : public TimingSegment struct TickcountSegment : public TimingSegment
{ {
/** @brief The default amount of ticks per beat. */
static const unsigned DEFAULT_TICK_COUNT = 4;
TimingSegmentType GetType() const { return SEGMENT_TICKCOUNT; } TimingSegmentType GetType() const { return SEGMENT_TICKCOUNT; }
SegmentEffectType GetEffectType() const { return SegmentEffectType_Indefinite; }
bool IsNotable() const { return true; } // indefinite segments are always true
void DebugPrint() const;
TimingSegment* Copy() const { return new TickcountSegment(*this); }
TickcountSegment( int iStartRow = ROW_INVALID, int iTicks = DEFAULT_TICK_COUNT ) : TickcountSegment( int iStartRow = ROW_INVALID, int iTicks = DEFAULT_TICK_COUNT ) :
TimingSegment(iStartRow), m_iTicksPerBeat(iTicks) { } TimingSegment(iStartRow), m_iTicksPerBeat(iTicks) { }
@@ -188,6 +264,22 @@ struct TickcountSegment : public TimingSegment
void SetTicks( int iTicks ) { m_iTicksPerBeat = iTicks; } void SetTicks( int iTicks ) { m_iTicksPerBeat = iTicks; }
RString ToString( int dec ) const; RString ToString( int dec ) const;
bool operator==( const TickcountSegment &other ) const
{
LOG->Trace( __PRETTY_FUNCTION__ );
COMPARE( m_iTicksPerBeat );
return true;
}
bool operator==( const TimingSegment &other ) const
{
LOG->Trace( __PRETTY_FUNCTION__ );
if( GetType() != other.GetType() )
return false;
return operator==( static_cast<const TickcountSegment&>(other) );
}
private: private:
/** @brief The amount of hold checkpoints counted per beat */ /** @brief The amount of hold checkpoints counted per beat */
int m_iTicksPerBeat; int m_iTicksPerBeat;
@@ -202,6 +294,12 @@ private:
struct ComboSegment : public TimingSegment struct ComboSegment : public TimingSegment
{ {
TimingSegmentType GetType() const { return SEGMENT_COMBO; } TimingSegmentType GetType() const { return SEGMENT_COMBO; }
SegmentEffectType GetEffectType() const { return SegmentEffectType_Indefinite; }
bool IsNotable() const { return true; } // indefinite segments are always true
void DebugPrint() const;
TimingSegment* Copy() const { return new ComboSegment(*this); }
ComboSegment( int iStartRow = ROW_INVALID, int iCombo = 1, int iMissCombo = 1 ) : ComboSegment( int iStartRow = ROW_INVALID, int iCombo = 1, int iMissCombo = 1 ) :
TimingSegment(iStartRow), m_iCombo(iCombo), TimingSegment(iStartRow), m_iCombo(iCombo),
@@ -219,6 +317,23 @@ struct ComboSegment : public TimingSegment
void SetMissCombo( int iCombo ) { m_iMissCombo = iCombo; } void SetMissCombo( int iCombo ) { m_iMissCombo = iCombo; }
RString ToString( int dec ) const; RString ToString( int dec ) const;
bool operator==( const ComboSegment &other ) const
{
LOG->Trace( __PRETTY_FUNCTION__ );
COMPARE( m_iCombo );
COMPARE( m_iMissCombo );
return true;
}
bool operator==( const TimingSegment &other ) const
{
LOG->Trace( __PRETTY_FUNCTION__ );
if( GetType() != other.GetType() )
return false;
return operator==( static_cast<const ComboSegment&>(other) );
}
private: private:
/** @brief The amount the combo increases at this point. */ /** @brief The amount the combo increases at this point. */
int m_iCombo; int m_iCombo;
@@ -237,6 +352,12 @@ private:
struct LabelSegment : public TimingSegment struct LabelSegment : public TimingSegment
{ {
TimingSegmentType GetType() const { return SEGMENT_LABEL; } TimingSegmentType GetType() const { return SEGMENT_LABEL; }
SegmentEffectType GetEffectType() const { return SegmentEffectType_Indefinite; }
bool IsNotable() const { return true; } // indefinite segments are always true
void DebugPrint() const;
TimingSegment* Copy() const { return new LabelSegment(*this); }
LabelSegment( int iStartRow = ROW_INVALID, const RString& sLabel = RString() ) : LabelSegment( int iStartRow = ROW_INVALID, const RString& sLabel = RString() ) :
TimingSegment(iStartRow), m_sLabel(sLabel) { } TimingSegment(iStartRow), m_sLabel(sLabel) { }
@@ -249,6 +370,22 @@ struct LabelSegment : public TimingSegment
void SetLabel( const RString& sLabel ) { m_sLabel.assign(sLabel); } void SetLabel( const RString& sLabel ) { m_sLabel.assign(sLabel); }
RString ToString( int dec ) const; RString ToString( int dec ) const;
bool operator==( const LabelSegment &other ) const
{
LOG->Trace( __PRETTY_FUNCTION__ );
COMPARE( m_sLabel );
return true;
}
bool operator==( const TimingSegment &other ) const
{
LOG->Trace( __PRETTY_FUNCTION__ );
if( GetType() != other.GetType() )
return false;
return operator==( static_cast<const LabelSegment&>(other) );
}
private: private:
/** @brief The label/section name for this point. */ /** @brief The label/section name for this point. */
RString m_sLabel; RString m_sLabel;
@@ -260,6 +397,12 @@ private:
struct BPMSegment : public TimingSegment struct BPMSegment : public TimingSegment
{ {
TimingSegmentType GetType() const { return SEGMENT_BPM; } TimingSegmentType GetType() const { return SEGMENT_BPM; }
SegmentEffectType GetEffectType() const { return SegmentEffectType_Indefinite; }
bool IsNotable() const { return true; } // indefinite segments are always true
void DebugPrint() const;
TimingSegment* Copy() const { return new BPMSegment(*this); }
// note that this takes a BPM, not a BPS (compatibility) // note that this takes a BPM, not a BPS (compatibility)
BPMSegment( int iStartRow = ROW_INVALID, float fBPM = 0.0f ) : BPMSegment( int iStartRow = ROW_INVALID, float fBPM = 0.0f ) :
@@ -276,6 +419,23 @@ struct BPMSegment : public TimingSegment
void SetBPM( float fBPM ) { m_fBPS = fBPM / 60.0f; } void SetBPM( float fBPM ) { m_fBPS = fBPM / 60.0f; }
RString ToString( int dec ) const; RString ToString( int dec ) const;
bool operator==( const BPMSegment &other ) const
{
LOG->Trace( __PRETTY_FUNCTION__ );
COMPARE_FLOAT( m_fBPS );
return true;
}
bool operator==( const TimingSegment &other ) const
{
LOG->Trace( __PRETTY_FUNCTION__ );
if( GetType() != other.GetType() )
return false;
return operator==( static_cast<const BPMSegment&>(other) );
}
private: private:
/** @brief The number of beats per second within this BPMSegment. */ /** @brief The number of beats per second within this BPMSegment. */
float m_fBPS; float m_fBPS;
@@ -291,6 +451,12 @@ private:
struct TimeSignatureSegment : public TimingSegment struct TimeSignatureSegment : public TimingSegment
{ {
TimingSegmentType GetType() const { return SEGMENT_TIME_SIG; } TimingSegmentType GetType() const { return SEGMENT_TIME_SIG; }
SegmentEffectType GetEffectType() const { return SegmentEffectType_Indefinite; }
bool IsNotable() const { return true; } // indefinite segments are always true
void DebugPrint() const;
TimingSegment* Copy() const { return new TimeSignatureSegment(*this); }
TimeSignatureSegment( int iStartRow = ROW_INVALID, TimeSignatureSegment( int iStartRow = ROW_INVALID,
int iNum = 4, int iDenom = 4 ) : int iNum = 4, int iDenom = 4 ) :
@@ -308,6 +474,8 @@ struct TimeSignatureSegment : public TimingSegment
int GetDen() const { return m_iDenominator; } int GetDen() const { return m_iDenominator; }
void SetDen( int den ) { m_iDenominator = den; } void SetDen( int den ) { m_iDenominator = den; }
void Set( int num, int den ) { m_iNumerator = num; m_iDenominator = den; }
RString ToString( int dec ) const; RString ToString( int dec ) const;
/** /**
@@ -325,6 +493,23 @@ struct TimeSignatureSegment : public TimingSegment
return BeatToNoteRow(1) * 4 * m_iNumerator / m_iDenominator; return BeatToNoteRow(1) * 4 * m_iNumerator / m_iDenominator;
} }
bool operator==( const TimeSignatureSegment &other ) const
{
LOG->Trace( __PRETTY_FUNCTION__ );
COMPARE( m_iNumerator );
COMPARE( m_iDenominator );
return true;
}
bool operator==( const TimingSegment &other ) const
{
LOG->Trace( __PRETTY_FUNCTION__ );
if( GetType() != other.GetType() )
return false;
return operator==( static_cast<const TimeSignatureSegment&>(other) );
}
private: private:
int m_iNumerator, m_iDenominator; int m_iNumerator, m_iDenominator;
}; };
@@ -342,6 +527,12 @@ private:
struct SpeedSegment : public TimingSegment struct SpeedSegment : public TimingSegment
{ {
TimingSegmentType GetType() const { return SEGMENT_SPEED; } TimingSegmentType GetType() const { return SEGMENT_SPEED; }
SegmentEffectType GetEffectType() const { return SegmentEffectType_Indefinite; }
bool IsNotable() const { return true; } // indefinite segments are always true
void DebugPrint() const;
TimingSegment* Copy() const { return new SpeedSegment(*this); }
/** @brief The type of unit used for segment scaling. */ /** @brief The type of unit used for segment scaling. */
enum BaseUnit { UNIT_BEATS, UNIT_SECONDS }; enum BaseUnit { UNIT_BEATS, UNIT_SECONDS };
@@ -369,6 +560,25 @@ struct SpeedSegment : public TimingSegment
void Scale( int start, int length, int newLength ); void Scale( int start, int length, int newLength );
RString ToString( int dec ) const; RString ToString( int dec ) const;
bool operator==( const SpeedSegment &other ) const
{
LOG->Trace( __PRETTY_FUNCTION__ );
COMPARE_FLOAT( m_fRatio );
COMPARE_FLOAT( m_fDelay );
COMPARE( m_Unit );
return true;
}
bool operator==( const TimingSegment &other ) const
{
LOG->Trace( __PRETTY_FUNCTION__ );
if( GetType() != other.GetType() )
return false;
return operator==( static_cast<const SpeedSegment&>(other) );
}
private: private:
/** @brief The percentage by which the Player's BPM is multiplied. */ /** @brief The percentage by which the Player's BPM is multiplied. */
float m_fRatio; float m_fRatio;
@@ -393,6 +603,12 @@ private:
struct ScrollSegment : public TimingSegment struct ScrollSegment : public TimingSegment
{ {
TimingSegmentType GetType() const { return SEGMENT_SCROLL; } TimingSegmentType GetType() const { return SEGMENT_SCROLL; }
SegmentEffectType GetEffectType() const { return SegmentEffectType_Indefinite; }
bool IsNotable() const { return true; } // indefinite segments are always true
void DebugPrint() const;
TimingSegment* Copy() const { return new ScrollSegment(*this); }
ScrollSegment( int iStartRow = ROW_INVALID, float fRatio = 1.0f ) : ScrollSegment( int iStartRow = ROW_INVALID, float fRatio = 1.0f ) :
TimingSegment(iStartRow), m_fRatio(fRatio) { } TimingSegment(iStartRow), m_fRatio(fRatio) { }
@@ -405,6 +621,23 @@ struct ScrollSegment : public TimingSegment
void SetRatio( float fRatio ) { m_fRatio = fRatio; } void SetRatio( float fRatio ) { m_fRatio = fRatio; }
RString ToString( int dec ) const; RString ToString( int dec ) const;
bool operator==( const ScrollSegment &other ) const
{
LOG->Trace( __PRETTY_FUNCTION__ );
COMPARE_FLOAT( m_fRatio );
return true;
}
bool operator==( const TimingSegment &other ) const
{
LOG->Trace( __PRETTY_FUNCTION__ );
if( GetType() != other.GetType() )
return false;
return operator==( static_cast<const ScrollSegment&>(other) );
}
private: private:
/** @brief The percentage by which the chart's scroll rate is multiplied. */ /** @brief The percentage by which the chart's scroll rate is multiplied. */
float m_fRatio; float m_fRatio;
@@ -416,6 +649,12 @@ private:
struct StopSegment : public TimingSegment struct StopSegment : public TimingSegment
{ {
TimingSegmentType GetType() const { return SEGMENT_STOP; } TimingSegmentType GetType() const { return SEGMENT_STOP; }
SegmentEffectType GetEffectType() const { return SegmentEffectType_Row; }
bool IsNotable() const { return m_fSeconds > 0; }
void DebugPrint() const;
TimingSegment* Copy() const { return new StopSegment(*this); }
StopSegment( int iStartRow = ROW_INVALID, float fSeconds = 0.0f ) : StopSegment( int iStartRow = ROW_INVALID, float fSeconds = 0.0f ) :
TimingSegment(iStartRow), m_fSeconds(fSeconds) { } TimingSegment(iStartRow), m_fSeconds(fSeconds) { }
@@ -428,6 +667,22 @@ struct StopSegment : public TimingSegment
void SetPause( float fSeconds ) { m_fSeconds = fSeconds; } void SetPause( float fSeconds ) { m_fSeconds = fSeconds; }
RString ToString( int dec ) const; RString ToString( int dec ) const;
bool operator==( const StopSegment &other ) const
{
LOG->Trace( __PRETTY_FUNCTION__ );
COMPARE_FLOAT( m_fSeconds );
return true;
}
bool operator==( const TimingSegment &other ) const
{
LOG->Trace( __PRETTY_FUNCTION__ );
if( GetType() != other.GetType() )
return false;
return operator==( static_cast<const StopSegment&>(other) );
}
private: private:
/** @brief The number of seconds to pause at the segment's row. */ /** @brief The number of seconds to pause at the segment's row. */
float m_fSeconds; float m_fSeconds;
@@ -439,8 +694,14 @@ private:
struct DelaySegment : public TimingSegment struct DelaySegment : public TimingSegment
{ {
TimingSegmentType GetType() const { return SEGMENT_DELAY; } TimingSegmentType GetType() const { return SEGMENT_DELAY; }
SegmentEffectType GetEffectType() const { return SegmentEffectType_Row; }
DelaySegment( int iStartRow, float fSeconds ) : bool IsNotable() const { return m_fSeconds > 0; }
void DebugPrint() const;
TimingSegment* Copy() const { return new DelaySegment(*this); }
DelaySegment( int iStartRow = ROW_INVALID, float fSeconds = 0 ) :
TimingSegment(iStartRow), m_fSeconds(fSeconds) { } TimingSegment(iStartRow), m_fSeconds(fSeconds) { }
DelaySegment( const DelaySegment &other ) : DelaySegment( const DelaySegment &other ) :
@@ -451,11 +712,29 @@ struct DelaySegment : public TimingSegment
void SetPause( float fSeconds ) { m_fSeconds = fSeconds; } void SetPause( float fSeconds ) { m_fSeconds = fSeconds; }
RString ToString( int dec ) const; RString ToString( int dec ) const;
bool operator==( const DelaySegment &other ) const
{
LOG->Trace( __PRETTY_FUNCTION__ );
COMPARE_FLOAT( m_fSeconds );
return true;
}
bool operator==( const TimingSegment &other ) const
{
LOG->Trace( __PRETTY_FUNCTION__ );
if( GetType() != other.GetType() )
return false;
return operator==( static_cast<const DelaySegment&>(other) );
}
private: private:
/** @brief The number of seconds to pause at the segment's row. */ /** @brief The number of seconds to pause at the segment's row. */
float m_fSeconds; float m_fSeconds;
}; };
#undef COMPARE
#undef COMPARE_FLOAT
#endif #endif