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
+61 -64
View File
@@ -267,28 +267,29 @@ void AdjustSync::AutosyncTempo()
GAMESTATE->m_pCurSong->m_SongTiming.m_fBeat0OffsetInSeconds += fIntercept;
const float fScaleBPM = 1.0f/(1.0f - fSlope);
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++)
{
BPMSegment *b = static_cast<BPMSegment *>(bpms[i]);
b->SetBPM(b->GetBPM() * fScaleBPM);
const BPMSegment *b = ToBPM( bpms[i] );
timing.AddSegment( BPMSegment(b->GetRow(), b->GetBPM() * fScaleBPM) );
}
/* We assume that the stops were measured as a number of beats.
* Therefore, if we change the bpms, we need to make a similar
* 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++)
{
StopSegment *s = static_cast<StopSegment *>(stops[i]);
s->SetPause(s->GetPause() * (1.0f - fSlope));
const StopSegment *s = ToStop( stops[i] );
timing.AddSegment( StopSegment(s->GetRow(), s->GetPause() * (1.0f - fSlope)) );
}
// 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++)
{
DelaySegment *s = static_cast<DelaySegment *>(delays[i]);
s->SetPause(s->GetPause() * (1.0f - fSlope));
const DelaySegment *s = ToDelay( delays[i] );
timing.AddSegment( DelaySegment(s->GetRow(), s->GetPause() * (1.0f - fSlope)) );
}
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 )
{
if( GAMESTATE->m_pCurSong.Get() )
{
unsigned int iOriginalSize = vsAddTo.size();
TimingData original = s_vpTimingDataOriginal[0];
TimingData &original = s_vpTimingDataOriginal[0];
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];
vector<TimingSegment *> &bpmOrig = original.m_avpTimingSegments[SEGMENT_BPM];
const vector<TimingSegment *> &bpmTest = testing.GetTimingSegments(SEGMENT_BPM);
const vector<TimingSegment *> &bpmOrig = original.GetTimingSegments(SEGMENT_BPM);
for( unsigned i=0; i< bpmTest.size(); i++ )
{
BPMSegment *bT = static_cast<BPMSegment *>(bpmTest[i]);
BPMSegment *bO = static_cast<BPMSegment *>(bpmOrig[i]);
float fOld = Quantize( bO->GetBPM(), 0.001f );
float fNew = Quantize( bT->GetBPM(), 0.001f );
float fDelta = fNew - fOld;
float fNew = Quantize( ToBPM(bpmTest[i])->GetBPM(), 0.001f );
float fOld = Quantize( ToBPM(bpmOrig[i])->GetBPM(), 0.001f );
if( fabsf(fDelta) > 0.0001f )
if( fabsf(fNew - fOld) < 1e-4 )
continue;
if ( i >= 4 )
{
if ( i >= 4 )
{
vsAddTo.push_back(ETC.GetValue());
break;
}
vsAddTo.push_back( ssprintf(
TEMPO_SEGMENT_FROM.GetValue(),
FormatNumberAndSuffix(i+1).c_str(),
fOld,
fNew ) );
vsAddTo.push_back(ETC.GetValue());
break;
}
RString s = ssprintf( TEMPO_SEGMENT_FROM.GetValue(),
FormatNumberAndSuffix(i+1).c_str(), fOld, fNew );
vsAddTo.push_back( s );
}
vector<TimingSegment *> &stopTest = testing.m_avpTimingSegments[SEGMENT_STOP];
vector<TimingSegment *> &stopOrig = original.m_avpTimingSegments[SEGMENT_STOP];
const vector<TimingSegment *> &stopTest = testing.GetTimingSegments(SEGMENT_STOP);
const vector<TimingSegment *> &stopOrig = original.GetTimingSegments(SEGMENT_STOP);
for( unsigned i=0; i< stopTest.size(); i++ )
{
StopSegment *sT = static_cast<StopSegment *>(stopTest[i]);
StopSegment *sO = static_cast<StopSegment *>(stopOrig[i]);
float fOld = Quantize( sO->GetPause(), 0.001f );
float fNew = Quantize( sT->GetPause(), 0.001f );
float fOld = Quantize( ToStop(stopOrig[i])->GetPause(), 0.001f );
float fNew = Quantize( ToStop(stopTest[i])->GetPause(), 0.001f );
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());
break;
}
vsAddTo.push_back( ssprintf(
CHANGED_STOP.GetValue(),
i+1,
fOld,
fNew ) );
vsAddTo.push_back(ETC.GetValue());
break;
}
RString s = ssprintf( CHANGED_STOP.GetValue(), i+1, fOld, fNew, fDelta );
vsAddTo.push_back( s );
}
vector<TimingSegment *> &delyTest = testing.m_avpTimingSegments[SEGMENT_DELAY];
vector<TimingSegment *> &delyOrig = original.m_avpTimingSegments[SEGMENT_DELAY];
const vector<TimingSegment *> &delyTest = testing.GetTimingSegments(SEGMENT_DELAY);
const vector<TimingSegment *> &delyOrig = original.GetTimingSegments(SEGMENT_DELAY);
for( unsigned i=0; i< delyTest.size(); i++ )
{
DelaySegment *sT = static_cast<DelaySegment *>(delyTest[i]);
DelaySegment *sO = static_cast<DelaySegment *>(delyOrig[i]);
float fOld = Quantize( sO->GetPause(), 0.001f );
float fNew = Quantize( sT->GetPause(), 0.001f );
if( delyTest[i] == delyOrig[i] )
continue;
float fOld = Quantize( ToDelay(delyOrig[i])->GetPause(), 0.001f );
float fNew = Quantize( ToDelay(delyTest[i])->GetPause(), 0.001f );
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());
break;
}
vsAddTo.push_back( ssprintf(
CHANGED_STOP.GetValue(),
i+1,
fOld,
fNew ) );
vsAddTo.push_back(ETC.GetValue());
break;
}
RString s = ssprintf( CHANGED_STOP.GetValue(),
i+1, fOld, fNew, fDelta );
vsAddTo.push_back( s );
}
if( vsAddTo.size() > iOriginalSize && s_fAverageError > 0.0f )
+3 -3
View File
@@ -421,8 +421,8 @@ void BackgroundImpl::LoadFromRandom( float fFirstBeat, float fEndBeat, const Bac
const TimingData &timing = m_pSong->m_SongTiming;
// 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++)
{
TimeSignatureSegment *ts = static_cast<TimeSignatureSegment *>(tSigs[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
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++ )
{
bool bAtBeginningOfMeasure = false;
+2 -2
View File
@@ -60,8 +60,8 @@ struct MusicPlaying
RageSound *m_Music;
MusicPlaying( RageSound *Music )
{
m_Timing.AddSegment( SEGMENT_BPM, new BPMSegment(0,120) );
m_NewTiming.AddSegment( SEGMENT_BPM, new BPMSegment(0,120) );
m_Timing.AddSegment( BPMSegment(0,120) );
m_NewTiming.AddSegment( BPMSegment(0,120) );
m_bHasTiming = false;
m_bTimingDelayed = false;
m_bApplyMusicRate = false;
+32 -28
View File
@@ -822,16 +822,20 @@ void NoteField::DrawPrimitives()
}
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;
// Draw beat bars
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;
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();
// beat bars every 16th note
@@ -874,9 +878,9 @@ void NoteField::DrawPrimitives()
// Scroll text
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 )
{
float fBeat = seg->GetBeat();
@@ -887,9 +891,9 @@ void NoteField::DrawPrimitives()
}
// 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 )
{
float fBeat = seg->GetBeat();
@@ -899,9 +903,9 @@ void NoteField::DrawPrimitives()
}
// 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 )
{
float fBeat = seg->GetBeat();
@@ -911,9 +915,9 @@ void NoteField::DrawPrimitives()
}
// 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 )
{
float fBeat = seg->GetBeat();
@@ -923,9 +927,9 @@ void NoteField::DrawPrimitives()
}
// 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 )
{
float fBeat = seg->GetBeat();
@@ -935,9 +939,9 @@ void NoteField::DrawPrimitives()
}
// 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 )
{
float fBeat = seg->GetBeat();
@@ -947,9 +951,9 @@ void NoteField::DrawPrimitives()
}
// 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 )
{
float fBeat = seg->GetBeat();
@@ -957,11 +961,11 @@ void NoteField::DrawPrimitives()
DrawTickcountText( fBeat, seg->GetTicks() );
}
}
// 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 )
{
float fBeat = seg->GetBeat();
@@ -971,9 +975,9 @@ void NoteField::DrawPrimitives()
}
// 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 )
{
float fBeat = seg->GetBeat();
@@ -983,9 +987,9 @@ void NoteField::DrawPrimitives()
}
// 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 )
{
float fBeat = seg->GetBeat();
@@ -994,11 +998,11 @@ void NoteField::DrawPrimitives()
seg->GetDelay(), seg->GetUnit() );
}
}
// 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 )
{
float fBeat = seg->GetBeat();
@@ -1088,7 +1092,7 @@ void NoteField::DrawPrimitives()
ASSERT( iter[j] == GAMESTATE->m_pCurSong->GetBackgroundChanges(j).end() );
break;
}
if( IS_ON_SCREEN(fLowestBeat) )
{
vector<RString> vsBGChanges;
+13 -22
View File
@@ -585,24 +585,20 @@ bool DWILoader::LoadFromDir( const RString &sPath_, Song &out, set<RString> &Bla
else if( sValueName.EqualsNoCase("BPM") )
{
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.",
0.0f, fBPM );
}
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 );
else
{
out.m_SongTiming.AddSegment( BPMSegment(0, fBPM) );
}
}
else if( sValueName.EqualsNoCase("DISPLAYBPM") )
{
// #DISPLAYBPM:[xxx..xxx]|[xxx]|[*];
// #DISPLAYBPM:[xxx..xxx]|[xxx]|[*];
int iMin, iMax;
/* We can't parse this as a float with sscanf, since '.' is a valid
* character in a float. (We could do it with a regex, but it's not
@@ -626,7 +622,7 @@ bool DWILoader::LoadFromDir( const RString &sPath_, Song &out, set<RString> &Bla
else if( sValueName.EqualsNoCase("GAP") )
// 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") )
out.m_fMusicSampleStartSeconds = ParseBrokenDWITimestamp(sParams[1], sParams[2], sParams[3]);
@@ -650,8 +646,8 @@ bool DWILoader::LoadFromDir( const RString &sPath_, Song &out, set<RString> &Bla
}
int iFreezeRow = BeatToNoteRow( StringToFloat(arrayFreezeValues[0]) / 4.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 );
}
}
@@ -670,19 +666,14 @@ bool DWILoader::LoadFromDir( const RString &sPath_, Song &out, set<RString> &Bla
LOG->UserLog( "Song file", sPath, "has an invalid CHANGEBPM: '%s'.", arrayBPMChangeExpressions[b].c_str() );
continue;
}
int iStartIndex = BeatToNoteRow( StringToFloat(arrayBPMChangeValues[0]) / 4.0f );
float fBPM = StringToFloat( arrayBPMChangeValues[1] );
if( fBPM > 0.0f )
{
BPMSegment * bs = new BPMSegment( iStartIndex, fBPM );
out.m_SongTiming.AddSegment( SEGMENT_BPM, bs );
}
out.m_SongTiming.AddSegment( BPMSegment(iStartIndex, fBPM) );
else
{
LOG->UserLog( "Song file", sPath, "has an invalid BPM change at beat %f, BPM %f.",
NoteRowToBeat(iStartIndex), fBPM );
}
}
}
+27 -8
View File
@@ -15,13 +15,9 @@ void NotesLoaderJson::GetApplicableFiles( const RString &sPath, vector<RString>
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_;
float fBeat = root["Beat"].asDouble();
seg->SetBeat(fBeat);
switch (seg->GetType())
switch( seg->GetType() )
{
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)
{
JsonUtil::DeserializeVectorPointers( td.m_avpTimingSegments[SEGMENT_BPM], Deserialize, root["BpmSegments"] );
JsonUtil::DeserializeVectorPointers( td.m_avpTimingSegments[SEGMENT_STOP], Deserialize, root["StopSegments"] );
vector<BPMSegment*> vBPMs;
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)
+16 -14
View File
@@ -17,7 +17,7 @@ static void HandleBunki( TimingData &timing, const float fEarlyBPM,
const float beat = (fPos + fGap) * BeatsPerSecond;
LOG->Trace( "BPM %f, BPS %f, BPMPos %f, beat %f",
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 )
@@ -59,7 +59,7 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, Song &song, bool
else if( sValueName=="BPM" )
{
BPM1 = StringToFloat(sParams[1]);
stepsTiming.AddSegment( SEGMENT_BPM, new BPMSegment(0, BPM1) );
stepsTiming.AddSegment( BPMSegment(0, BPM1) );
}
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 );
return false;
}
stepsTiming.AddSegment( SEGMENT_TICKCOUNT, new TickcountSegment(0, iTickCount));
stepsTiming.AddSegment( TickcountSegment(0, iTickCount));
}
else if( sValueName=="DIFFICULTY" )
@@ -332,7 +332,7 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, Song &song, bool
// be 0. if the tickcount is non a stepmania standard then it will be adapted, a scroll
// segment will then be added based on approximations. -DaisuMaster
// eh better do it considering the tickcount (high tickcounts)
// I'm making some experiments, please spare me...
//continue;
@@ -367,7 +367,8 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, Song &song, bool
else if (BeginsWith(sRowString, "|M") || BeginsWith(sRowString, "|C"))
{
// multipliers/combo
stepsTiming.SetHitComboAtBeat( fCurBeat, static_cast<int>(numTemp) );
ComboSegment seg( BeatToNoteRow(fCurBeat), int(numTemp) );
stepsTiming.AddSegment( seg );
}
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"))
{
// scroll segments
stepsTiming.SetScrollAtBeat( fCurBeat, numTemp );
ScrollSegment seg = ScrollSegment( BeatToNoteRow(fCurBeat), numTemp );
stepsTiming.AddSegment( seg );
//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
* actual steps. */
ticks = StringToInt( value );
ticks = ticks > 0 ? ticks : 4;
// add a tickcount for those using the [Player]
// CheckpointsUseTimeSignatures metric. -aj
// It's not with timesigs now -DaisuMaster
TickcountSegment * tcs = new TickcountSegment(0, ticks > ROWS_PER_BEAT ? ROWS_PER_BEAT : ticks);
timing.AddSegment( SEGMENT_TICKCOUNT, tcs );
CLAMP( ticks, 0, ROWS_PER_BEAT );
if( ticks == 0 )
ticks = TickcountSegment::DEFAULT_TICK_COUNT;
timing.AddSegment( TickcountSegment(0, ticks) );
}
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" )
{
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" )
{
@@ -584,7 +586,7 @@ static bool LoadGlobalData( const RString &sPath, Song &out, bool &bKIUCompliant
SMGap1 = -StringToFloat( sParams[1] )/100;
out.m_SongTiming.m_fBeat0OffsetInSeconds = SMGap1;
}
// This is currently required for more accurate KIU BPM changes.
// This is currently required for more accurate KIU BPM changes.
else if( sValueName=="STARTTIME2" )
{
bKIUCompliant = true;
+7 -12
View File
@@ -592,7 +592,7 @@ static void ReadGlobalTags( const RString &sPath, const NameToData_t &mapNameToD
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 );
}
else
@@ -697,9 +697,8 @@ static void ReadGlobalTags( const RString &sPath, const NameToData_t &mapNameToD
if( fBPM > 0.0f )
{
BPMSegment * newSeg = new BPMSegment( BeatToNoteRow(fBeat), fBPM );
out.m_SongTiming.AddSegment( SEGMENT_BPM, newSeg );
LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", fBeat, newSeg->GetBPM() );
out.m_SongTiming.AddSegment( BPMSegment(BeatToNoteRow(fBeat), fBPM) );
LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", fBeat, fBPM );
}
else
{
@@ -724,9 +723,8 @@ static void ReadGlobalTags( const RString &sPath, const NameToData_t &mapNameToD
float fBeats = StringToFloat( sBeats ) / 48.0f;
float fFreezeSecs = fBeats / fBPS;
StopSegment * newSeg = new StopSegment( BeatToNoteRow(fBeat), fFreezeSecs );
out.m_SongTiming.AddSegment( SEGMENT_STOP, newSeg );
LOG->Trace( "Inserting new Freeze at beat %f, secs %f", fBeat, newSeg->GetPause() );
out.m_SongTiming.AddSegment( StopSegment(BeatToNoteRow(fBeat), fFreezeSecs) );
LOG->Trace( "Inserting new Freeze at beat %f, secs %f", fBeat, fFreezeSecs );
}
else
{
@@ -753,12 +751,9 @@ static void ReadGlobalTags( const RString &sPath, const NameToData_t &mapNameToD
if( fBPM > 0.0f )
{
BPMSegment * newSeg = new BPMSegment( iStepIndex, fBPM );
out.m_SongTiming.AddSegment( SEGMENT_BPM, newSeg );
out.m_SongTiming.AddSegment( BPMSegment(iStepIndex, fBPM) );
LOG->Trace("Inserting new BPM change at beat %f, BPM %f",
newSeg->GetBeat(),
newSeg->GetBPM() );
NoteRowToBeat(iStepIndex), fBPM );
}
else
{
+65 -86
View File
@@ -227,12 +227,12 @@ bool SMLoader::ProcessBPMs( TimingData &out, const RString line, const int rowsP
arrayBPMChangeExpressions[b].c_str() );
continue;
}
bNotEmpty = true;
const float fBeat = RowToBeat( arrayBPMChangeValues[0], rowsPerBeat );
const float fNewBPM = StringToFloat( arrayBPMChangeValues[1] );
if( fNewBPM < 0.0f )
{
negBeat = fBeat;
@@ -244,9 +244,8 @@ bool SMLoader::ProcessBPMs( TimingData &out, const RString line, const int rowsP
if( negBPM < 0 )
{
float endBeat = fBeat + (fNewBPM / -negBPM) * (fBeat - negBeat);
out.AddSegment(SEGMENT_WARP,
new WarpSegment(BeatToNoteRow(negBeat), endBeat - negBeat));
out.AddSegment( WarpSegment(BeatToNoteRow(negBeat), endBeat - negBeat) );
negBeat = -1;
negBPM = 1;
}
@@ -260,18 +259,16 @@ bool SMLoader::ProcessBPMs( TimingData &out, const RString line, const int rowsP
// add in a warp.
if( highspeedBeat > 0 )
{
out.AddSegment(SEGMENT_WARP,
new WarpSegment(BeatToNoteRow(highspeedBeat), fBeat - highspeedBeat) );
out.AddSegment( WarpSegment(BeatToNoteRow(highspeedBeat), fBeat - highspeedBeat) );
highspeedBeat = -1;
}
{
out.AddSegment(SEGMENT_BPM,
new BPMSegment(BeatToNoteRow(fBeat), fNewBPM));
out.AddSegment( BPMSegment(BeatToNoteRow(fBeat), fNewBPM) );
}
}
}
}
return bNotEmpty;
}
@@ -283,7 +280,7 @@ void SMLoader::ProcessStops( TimingData &out, const RString line, const int rows
// Prepare variables for negative stop conversion.
float negBeat = -1;
float negPause = 0;
for( unsigned f=0; f<arrayFreezeExpressions.size(); f++ )
{
vector<RString> arrayFreezeValues;
@@ -296,26 +293,26 @@ void SMLoader::ProcessStops( TimingData &out, const RString line, const int rows
arrayFreezeExpressions[f].c_str() );
continue;
}
const float fFreezeBeat = RowToBeat( arrayFreezeValues[0], rowsPerBeat );
const float fFreezeSeconds = StringToFloat( arrayFreezeValues[1] );
// Process the prior stop.
if( negPause > 0 )
{
BPMSegment * oldBPM = out.GetBPMSegmentAtRow(BeatToNoteRow(negBeat));
float fSecondsPerBeat = 60 / oldBPM->GetBPM();
float oldBPM = out.GetBPMAtRow(BeatToNoteRow(negBeat));
float fSecondsPerBeat = 60 / oldBPM;
float fSkipBeats = negPause / fSecondsPerBeat;
if( negBeat + fSkipBeats > fFreezeBeat )
fSkipBeats = fFreezeBeat - negBeat;
out.AddSegment(SEGMENT_WARP, new WarpSegment(BeatToNoteRow(negBeat), fSkipBeats));
out.AddSegment( WarpSegment(BeatToNoteRow(negBeat), fSkipBeats));
negBeat = -1;
negPause = 0;
}
if( fFreezeSeconds < 0.0f )
{
negBeat = fFreezeBeat;
@@ -323,20 +320,18 @@ void SMLoader::ProcessStops( TimingData &out, const RString line, const int rows
}
else if( fFreezeSeconds > 0.0f )
{
out.AddSegment(SEGMENT_STOP,
new StopSegment(BeatToNoteRow(fFreezeBeat), fFreezeSeconds));
out.AddSegment( StopSegment(BeatToNoteRow(fFreezeBeat), fFreezeSeconds) );
}
}
// Process the prior stop if there was one.
if( negPause > 0 )
{
BPMSegment * oldBPM = out.GetBPMSegmentAtBeat(negBeat);
float fSecondsPerBeat = 60 / oldBPM->GetBPM();
float oldBPM = out.GetBPMAtBeat(negBeat);
float fSecondsPerBeat = 60 / oldBPM;
float fSkipBeats = negPause / fSecondsPerBeat;
out.AddSegment(SEGMENT_WARP, new WarpSegment(BeatToNoteRow(negBeat), fSkipBeats));
out.AddSegment( WarpSegment(BeatToNoteRow(negBeat), fSkipBeats) );
}
}
@@ -344,7 +339,7 @@ void SMLoader::ProcessDelays( TimingData &out, const RString line, const int row
{
vector<RString> arrayDelayExpressions;
split( line, ",", arrayDelayExpressions );
for( unsigned f=0; f<arrayDelayExpressions.size(); f++ )
{
vector<RString> arrayDelayValues;
@@ -357,17 +352,12 @@ void SMLoader::ProcessDelays( TimingData &out, const RString line, const int row
arrayDelayExpressions[f].c_str() );
continue;
}
const float fFreezeBeat = RowToBeat( arrayDelayValues[0], rowsPerBeat );
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 );
if(fFreezeSeconds > 0.0f)
out.AddSegment( SEGMENT_DELAY, new_seg );
out.AddSegment( DelaySegment(BeatToNoteRow(fFreezeBeat), fFreezeSeconds) );
else
LOG->UserLog(
"Song file",
@@ -397,11 +387,8 @@ void SMLoader::ProcessTimeSignatures( TimingData &out, const RString line, const
}
const float fBeat = RowToBeat( vs2[0], rowsPerBeat );
TimeSignatureSegment * seg =
new TimeSignatureSegment( BeatToNoteRow(fBeat),
StringToInt( vs2[1] ),
StringToInt( vs2[2] ));
const int iNumerator = StringToInt( vs2[1] );
const int iDenominator = StringToInt( vs2[2] );
if( fBeat < 0 )
{
@@ -411,26 +398,26 @@ void SMLoader::ProcessTimeSignatures( TimingData &out, const RString line, const
fBeat );
continue;
}
if( seg->GetNum() < 1 )
if( iNumerator < 1 )
{
LOG->UserLog("Song file",
this->GetSongTitle(),
"has an invalid time signature change with beat %f, iNumerator %i.",
fBeat, seg->GetNum() );
fBeat, iNumerator );
continue;
}
if( seg->GetDen() < 1 )
if( iDenominator < 1 )
{
LOG->UserLog("Song file",
this->GetSongTitle(),
"has an invalid time signature change with beat %f, iDenominator %i.",
fBeat, seg->GetDen() );
fBeat, iDenominator );
continue;
}
out.AddSegment( SEGMENT_TIME_SIG, seg );
out.AddSegment( TimeSignatureSegment(BeatToNoteRow(fBeat), iNumerator, iDenominator) );
}
}
@@ -438,7 +425,7 @@ void SMLoader::ProcessTickcounts( TimingData &out, const RString line, const int
{
vector<RString> arrayTickcountExpressions;
split( line, ",", arrayTickcountExpressions );
for( unsigned f=0; f<arrayTickcountExpressions.size(); f++ )
{
vector<RString> arrayTickcountValues;
@@ -451,12 +438,11 @@ void SMLoader::ProcessTickcounts( TimingData &out, const RString line, const int
arrayTickcountExpressions[f].c_str() );
continue;
}
const float fTickcountBeat = RowToBeat( arrayTickcountValues[0], rowsPerBeat );
int iTicks = clamp(atoi( arrayTickcountValues[1] ), 0, ROWS_PER_BEAT);
out.AddSegment( SEGMENT_TICKCOUNT,
new TickcountSegment(BeatToNoteRow(fTickcountBeat), iTicks) );
out.AddSegment( TickcountSegment(BeatToNoteRow(fTickcountBeat), iTicks) );
}
}
@@ -464,22 +450,22 @@ void SMLoader::ProcessSpeeds( TimingData &out, const RString line, const int row
{
vector<RString> vs1;
split( line, ",", vs1 );
FOREACH_CONST( RString, vs1, s1 )
{
vector<RString> vs2;
split( *s1, "=", vs2 );
if( vs2[0] == 0 && vs2.size() == 2 ) // First one always seems to have 2.
{
vs2.push_back("0");
}
if( vs2.size() == 3 ) // use beats by default.
{
vs2.push_back("0");
}
if( vs2.size() < 4 )
{
LOG->UserLog("Song file",
@@ -488,39 +474,35 @@ void SMLoader::ProcessSpeeds( TimingData &out, const RString line, const int row
static_cast<int>(vs2.size()) );
continue;
}
const float fBeat = RowToBeat( vs2[0], rowsPerBeat );
SpeedSegment * seg = new SpeedSegment( BeatToNoteRow(fBeat),
StringToFloat( vs2[1] ),
StringToFloat( vs2[2] ));
const float fRatio = StringToFloat( vs2[1] );
const float fDelay = StringToFloat( vs2[2] );
// XXX: ugly...
int iUnit = StringToInt(vs2[3]);
SpeedSegment::BaseUnit unit = (iUnit == 0) ?
SpeedSegment::UNIT_BEATS : SpeedSegment::UNIT_SECONDS;
seg->SetUnit( unit );
if( fBeat < 0 )
{
LOG->UserLog("Song file",
this->GetSongTitle(),
"has an speed change with beat %f.",
"has an speed change with beat %f.",
fBeat );
continue;
}
if( seg->GetDelay() < 0 )
if( fDelay < 0 )
{
LOG->UserLog("Song file",
this->GetSongTitle(),
"has an speed change with beat %f, length %f.",
fBeat, seg->GetDelay() );
fBeat, fDelay );
continue;
}
out.AddSegment( SEGMENT_SPEED, seg );
out.AddSegment( SpeedSegment(BeatToNoteRow(fBeat), fRatio, fDelay, unit) );
}
}
@@ -528,7 +510,7 @@ void SMLoader::ProcessFakes( TimingData &out, const RString line, const int rows
{
vector<RString> arrayFakeExpressions;
split( line, ",", arrayFakeExpressions );
for( unsigned b=0; b<arrayFakeExpressions.size(); b++ )
{
vector<RString> arrayFakeValues;
@@ -541,12 +523,12 @@ void SMLoader::ProcessFakes( TimingData &out, const RString line, const int rows
arrayFakeExpressions[b].c_str() );
continue;
}
const float fBeat = RowToBeat( arrayFakeValues[0], rowsPerBeat );
const float fNewBeat = StringToFloat( arrayFakeValues[1] );
if(fNewBeat > 0)
out.AddSegment( SEGMENT_FAKE, new FakeSegment(BeatToNoteRow(fBeat), fNewBeat) );
out.AddSegment( FakeSegment(BeatToNoteRow(fBeat), fNewBeat) );
else
{
LOG->UserLog("Song file",
@@ -777,28 +759,27 @@ bool SMLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCache
{
ProcessBPMs(out.m_SongTiming, sParams[1]);
}
else if( sValueName=="STOPS" || sValueName=="FREEZES" )
{
ProcessStops(out.m_SongTiming, sParams[1]);
}
else if( sValueName=="DELAYS" )
{
ProcessDelays(out.m_SongTiming, sParams[1]);
}
else if( sValueName=="TIMESIGNATURES" )
{
ProcessTimeSignatures(out.m_SongTiming, sParams[1]);
}
else if( sValueName=="TICKCOUNTS" )
{
ProcessTickcounts(out.m_SongTiming, sParams[1]);
}
else if( sValueName=="INSTRUMENTTRACK" )
{
ProcessInstrumentTracks( out, sParams[1] );
@@ -931,10 +912,9 @@ bool SMLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCache
else
LOG->UserLog( "Song file", sPath, "has an unexpected value named \"%s\".", sValueName.c_str() );
}
// Ensure all warps from negative time changes are in order.
vector<TimingSegment *> &warps = out.m_SongTiming.m_avpTimingSegments[SEGMENT_WARP];
sort(warps.begin(), warps.end());
out.m_SongTiming.SortSegments( SEGMENT_WARP );
TidyUpData( out, bFromCache );
return true;
}
@@ -1105,7 +1085,6 @@ void SMLoader::TidyUpData( Song &song, bool bFromCache )
if( !IsAFile( song.GetBackgroundPath() ) )
break;
bg.push_back( BackgroundChange(lastBeat,song.m_sBackgroundFile) );
} while(0);
}
+39 -45
View File
@@ -38,8 +38,7 @@ void SMALoader::ProcessMultipliers( TimingData &out, const int iRowsPerBeat, con
const int iMisses = (size == 2 || size == 4 ?
iCombos :
StringToInt(arrayMultiplierValues[2]));
out.AddSegment(SEGMENT_COMBO,
new ComboSegment( BeatToNoteRow(fComboBeat), iCombos, iMisses ));
out.AddSegment( ComboSegment(BeatToNoteRow(fComboBeat), iCombos, iMisses) );
}
}
@@ -62,31 +61,26 @@ void SMALoader::ProcessBeatsPerMeasure( TimingData &out, const RString sParam )
continue;
}
const float fBeat = StringToFloat( vs2[0] );
TimeSignatureSegment * seg = new TimeSignatureSegment(
BeatToNoteRow(fBeat),
StringToInt(vs2[1]),
4 );
const int iNumerator = StringToInt( vs2[1] );
if( fBeat < 0 )
{
LOG->UserLog("Song file",
this->GetSongTitle(),
this->GetSongTitle(),
"has an invalid time signature change with beat %f.",
fBeat );
continue;
}
if( seg->GetNum() < 1 )
if( iNumerator < 1 )
{
LOG->UserLog("Song file",
this->GetSongTitle(),
"has an invalid time signature change with beat %f, iNumerator %i.",
fBeat, seg->GetNum() );
fBeat, iNumerator );
continue;
}
out.AddSegment( SEGMENT_TIME_SIG, seg );
out.AddSegment( TimeSignatureSegment(BeatToNoteRow(fBeat), iNumerator) );
}
}
@@ -116,19 +110,19 @@ void SMALoader::ProcessSpeeds( TimingData &out, const RString line, const int ro
static_cast<int>(vs2.size()) );
continue;
}
const float fBeat = RowToBeat( vs2[0], rowsPerBeat );
RString backup = vs2[2];
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::UNIT_SECONDS : SpeedSegment::UNIT_BEATS);
SpeedSegment * seg = new SpeedSegment( BeatToNoteRow(fBeat),
StringToFloat( vs2[1] ), StringToFloat(vs2[2]), unit);
if( fBeat < 0 )
{
@@ -138,17 +132,17 @@ void SMALoader::ProcessSpeeds( TimingData &out, const RString line, const int ro
fBeat );
continue;
}
if( seg->GetDelay() < 0 )
if( fDelay < 0 )
{
LOG->UserLog("Song file",
this->GetSongTitle(),
"has an speed change with beat %f, length %f.",
fBeat, seg->GetDelay() );
fBeat, fDelay );
continue;
}
out.AddSegment( SEGMENT_SPEED, seg );
out.AddSegment( SpeedSegment(BeatToNoteRow(fBeat), fRatio, fDelay, unit) );
}
}
@@ -348,7 +342,7 @@ bool SMALoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCach
{
vector<RString> aFGChangeExpressions;
split( sParams[1], ",", aFGChangeExpressions );
for( unsigned b=0; b<aFGChangeExpressions.size(); b++ )
{
BackgroundChange change;
@@ -356,82 +350,82 @@ bool SMALoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCach
out.AddForegroundChange( change );
}
}
else if( sValueName=="OFFSET" )
{
TimingData &timing = (state == SMA_GETTING_STEP_INFO
TimingData &timing = (state == SMA_GETTING_STEP_INFO
? pNewNotes->m_Timing : out.m_SongTiming);
timing.m_fBeat0OffsetInSeconds = StringToFloat( sParams[1] );
}
else if( sValueName=="BPMS" )
{
TimingData &timing = (state == SMA_GETTING_STEP_INFO
TimingData &timing = (state == SMA_GETTING_STEP_INFO
? pNewNotes->m_Timing : out.m_SongTiming);
ProcessBPMs( timing, sParams[1], iRowsPerBeat );
}
else if( sValueName=="STOPS" || sValueName=="FREEZES" )
{
TimingData &timing = (state == SMA_GETTING_STEP_INFO
TimingData &timing = (state == SMA_GETTING_STEP_INFO
? pNewNotes->m_Timing : out.m_SongTiming);
ProcessStops( timing, sParams[1], iRowsPerBeat );
}
else if( sValueName=="DELAYS" )
{
TimingData &timing = (state == SMA_GETTING_STEP_INFO
TimingData &timing = (state == SMA_GETTING_STEP_INFO
? pNewNotes->m_Timing : out.m_SongTiming);
ProcessDelays( timing, sParams[1], iRowsPerBeat );
}
else if( sValueName=="TICKCOUNT" )
{
TimingData &timing = (state == SMA_GETTING_STEP_INFO
TimingData &timing = (state == SMA_GETTING_STEP_INFO
? pNewNotes->m_Timing : out.m_SongTiming);
ProcessTickcounts( timing, sParams[1], iRowsPerBeat );
}
else if( sValueName=="SPEED" )
{
TimingData &timing = (state == SMA_GETTING_STEP_INFO
TimingData &timing = (state == SMA_GETTING_STEP_INFO
? pNewNotes->m_Timing : out.m_SongTiming);
RString tmp = sParams[1];
Trim( tmp );
ProcessSpeeds( timing, tmp, iRowsPerBeat );
}
else if( sValueName=="MULTIPLIER" )
{
TimingData &timing = (state == SMA_GETTING_STEP_INFO
TimingData &timing = (state == SMA_GETTING_STEP_INFO
? pNewNotes->m_Timing : out.m_SongTiming);
ProcessMultipliers( timing, iRowsPerBeat, sParams[1] );
}
else if( sValueName=="FAKES" )
{
TimingData &timing = (state == SMA_GETTING_STEP_INFO
TimingData &timing = (state == SMA_GETTING_STEP_INFO
? pNewNotes->m_Timing : out.m_SongTiming);
ProcessFakes( timing, sParams[1], iRowsPerBeat );
}
else if( sValueName=="METERTYPE" )
{
; // We don't use this...yet.
}
else if( sValueName=="KEYSOUNDS" )
{
split( sParams[1], ",", out.m_vsKeysoundFile );
}
// Attacks loaded from file
else if( sValueName=="ATTACKS" )
{
ProcessAttackString(out.m_sAttackString, sParams);
ProcessAttacks(out.m_Attacks, sParams);
}
else if( sValueName=="NOTES" || sValueName=="NOTES2" )
{
if( iNumParams < 7 )
@@ -442,7 +436,7 @@ bool SMALoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCach
iNumParams );
continue;
}
LoadFromTokens(
sParams[1],
sParams[2],
+11 -12
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.
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 )
out.AddSegment( SEGMENT_WARP, new WarpSegment(BeatToNoteRow(fBeat), fNewBeat) );
out.AddSegment( WarpSegment(BeatToNoteRow(fBeat), fNewBeat) );
else
{
LOG->UserLog("Song file",
@@ -73,7 +73,7 @@ void SSCLoader::ProcessLabels( TimingData &out, const RString sParam )
RString sLabel = arrayLabelValues[1];
TrimRight(sLabel);
if( fBeat >= 0.0f )
out.AddSegment( SEGMENT_LABEL, new LabelSegment(BeatToNoteRow(fBeat), sLabel) );
out.AddSegment( LabelSegment(BeatToNoteRow(fBeat), sLabel) );
else
{
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 int iCombos = StringToInt( arrayComboValues[1] );
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 ) );
}
}
@@ -128,11 +128,10 @@ void SSCLoader::ProcessScrolls( TimingData &out, const RString sParam )
static_cast<int>(vs2.size()) );
continue;
}
const float fBeat = StringToFloat( vs2[0] );
ScrollSegment * seg = new ScrollSegment(BeatToNoteRow(fBeat), StringToFloat( vs2[1] ) );
const float fRatio = StringToFloat( vs2[1] );
if( fBeat < 0 )
{
LOG->UserLog("Song file",
@@ -141,8 +140,8 @@ void SSCLoader::ProcessScrolls( TimingData &out, const RString sParam )
fBeat );
continue;
}
out.AddSegment( SEGMENT_SCROLL, seg );
out.AddSegment( ScrollSegment(BeatToNoteRow(fBeat), fRatio) );
}
}
@@ -741,7 +740,7 @@ bool SSCLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCach
ProcessAttacks(pNewNotes->m_Attacks, sParams);
}
}
else if( sValueName=="OFFSET" )
{
if (out.m_fVersion >= VERSION_SPLIT_TIMING)
@@ -750,7 +749,7 @@ bool SSCLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCach
bHasOwnTiming = true;
}
}
else if( sValueName=="DISPLAYBPM" )
{
// #DISPLAYBPM:[xxx][xxx:xxx]|[*];
+3 -4
View File
@@ -353,9 +353,8 @@ bool NotesWriterDWI::Write( RString sPath, const Song &out )
/* Write transliterations, if we have them, since DWI doesn't support UTF-8. */
f.PutLine( ssprintf("#TITLE:%s;", DwiEscape(out.GetTranslitFullTitle()).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,
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()) );
@@ -382,7 +381,7 @@ bool NotesWriterDWI::Write( RString sPath, const Song &out )
}
// 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() )
{
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)
{
JsonUtil::SerializeVectorPointers( td.m_avpTimingSegments[SEGMENT_BPM], Serialize, root["BpmSegments"] );
JsonUtil::SerializeVectorPointers( td.m_avpTimingSegments[SEGMENT_STOP], Serialize, root["StopSegments"] );
JsonUtil::SerializeVectorPointers( td.GetTimingSegments(SEGMENT_BPM), Serialize, root["BpmSegments"] );
JsonUtil::SerializeVectorPointers( td.GetTimingSegments(SEGMENT_STOP), Serialize, root["StopSegments"] );
}
static void Serialize(const LyricSegment &o, Json::Value &root)
+20 -21
View File
@@ -75,18 +75,18 @@ static void WriteGlobalTags( RageFile &f, Song &out )
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++ )
{
const BPMSegment *bs = static_cast<BPMSegment *>(bpms[i]);
const BPMSegment *bs = ToBPM(bpms[i]);
f.PutLine( ssprintf( "%.3f=%.3f", bs->GetBeat(), bs->GetBPM() ) );
if( i != bpms.size()-1 )
f.Write( "," );
}
f.PutLine( ";" );
vector<TimingSegment *> &warps = timing.m_avpTimingSegments[SEGMENT_WARP];
const vector<TimingSegment *> &warps = timing.GetTimingSegments(SEGMENT_WARP);
unsigned wSize = warps.size();
if( wSize > 0 )
{
@@ -96,34 +96,33 @@ static void WriteGlobalTags( RageFile &f, Song &out )
int iRow = ws->GetRow();
float fBPS = 60 / out.m_SongTiming.GetBPMAtRow(iRow);
float fSkip = fBPS * ws->GetLength();
out.m_SongTiming.AddSegment(SEGMENT_STOP,
new StopSegment(iRow, -fSkip) );
out.m_SongTiming.AddSegment( StopSegment(iRow, -fSkip) );
}
}
// TODO: make Delays into Stops that start one row before.
vector<TimingSegment *> &stops = timing.m_avpTimingSegments[SEGMENT_STOP];
vector<TimingSegment *> &delays = timing.m_avpTimingSegments[SEGMENT_DELAY];
const vector<TimingSegment *> &stops = timing.GetTimingSegments(SEGMENT_STOP);
const vector<TimingSegment *> &delays = timing.GetTimingSegments(SEGMENT_DELAY);
map<float, float> allPauses;
for( unsigned i=0; i<stops.size(); i++ )
{
const StopSegment *fs = static_cast<StopSegment *>(stops[i]);
allPauses.insert(pair<float, float>(fs->GetBeat(),
fs->GetPause()));
const StopSegment *fs = ToStop( stops[i] );
allPauses.insert(pair<float, float>(fs->GetBeat(), fs->GetPause()));
// erase stops with negative length
if( fs->GetPause() < 0 )
{
stops.erase(stops.begin()+i,stops.begin()+i+1 );
i--;
}
timing.AddSegment( StopSegment(fs->GetRow(), 0) );
}
// 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),
static_cast<DelaySegment *>(*ss)->GetPause()));
float fBeat = NoteRowToBeat( (*ss)->GetRow()-1 );
float fPause = ToDelay(*ss)->GetPause();
allPauses.insert( pair<float,float>(fBeat, fPause) );
}
f.Write( "#STOPS:" );
vector<RString> stopLines;
FOREACHM(float, float, allPauses, ap)
@@ -133,7 +132,7 @@ static void WriteGlobalTags( RageFile &f, Song &out )
f.PutLine(join(",\n", stopLines));
f.PutLine( ";" );
FOREACH_BackgroundLayer( b )
{
if( b==0 )
+36 -36
View File
@@ -60,115 +60,115 @@ 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 );
timing.TidyUpData();
// timing.TidyUpData(); // UGLY: done via const_cast. do we really -need- this here?
unsigned i = 0;
w.Init( "BPMS" );
vector<TimingSegment *> &bpms = timing.m_avpTimingSegments[SEGMENT_BPM];
const vector<TimingSegment *> &bpms = timing.GetTimingSegments(SEGMENT_BPM);
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.Finish();
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++)
{
StopSegment *ss = static_cast<StopSegment *>(stops[i]);
const StopSegment *ss = ToStop( stops[i] );
w.Write( ss->GetRow(), ss->GetPause() );
}
w.Finish();
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++)
{
DelaySegment *ss = static_cast<DelaySegment *>(delays[i]);
const DelaySegment *ss = ToDelay( delays[i] );
w.Write( ss->GetRow(), ss->GetPause() );
}
w.Finish();
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++)
{
WarpSegment *ws = static_cast<WarpSegment *>(warps[i]);
const WarpSegment *ws = ToWarp( warps[i] );
w.Write( ws->GetRow(), ws->GetLength() );
}
w.Finish();
vector<TimingSegment *> &tSigs = timing.m_avpTimingSegments[SEGMENT_TIME_SIG];
const vector<TimingSegment *> &tSigs = timing.GetTimingSegments(SEGMENT_TIME_SIG);
ASSERT( !tSigs.empty() );
w.Init( "TIMESIGNATURES" );
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.Finish();
vector<TimingSegment *> &ticks = timing.m_avpTimingSegments[SEGMENT_TICKCOUNT];
const vector<TimingSegment *> &ticks = timing.GetTimingSegments(SEGMENT_TICKCOUNT);
ASSERT( !ticks.empty() );
w.Init( "TICKCOUNTS" );
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.Finish();
vector<TimingSegment *> &combos = timing.m_avpTimingSegments[SEGMENT_COMBO];
const vector<TimingSegment *> &combos = timing.GetTimingSegments(SEGMENT_COMBO);
ASSERT( !combos.empty() );
w.Init( "COMBOS" );
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())
w.Write( cs->GetRow(), cs->GetCombo() );
else
w.Write( cs->GetRow(), cs->GetCombo(), cs->GetMissCombo() );
}
w.Finish();
// 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" );
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.Finish();
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++)
{
ScrollSegment *ss = static_cast<ScrollSegment *>(scrolls[i]);
ScrollSegment *ss = ToScroll( scrolls[i] );
w.Write( ss->GetRow(), ss->GetRatio() );
}
w.Finish();
if( !bIsSong )
{
vector<TimingSegment *> &fakes = timing.m_avpTimingSegments[SEGMENT_FAKE];
{
const vector<TimingSegment *> &fakes = timing.GetTimingSegments(SEGMENT_FAKE);
w.Init( "FAKES" );
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.Finish();
}
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++)
{
LabelSegment *ls = static_cast<LabelSegment *>(labels[i]);
@@ -344,7 +344,7 @@ static RString GetSSCNoteData( const Song &song, const Steps &in, bool bSavingCa
lines.push_back( ssprintf( "#RADARVALUES:%s;", join(",",asRadarValues).c_str() ) );
lines.push_back( ssprintf( "#CREDIT:%s;", SmEscape(in.GetCredit()).c_str() ) );
// XXX: Is there a better way to write this?
if (const_cast<TimingData &>(song.m_SongTiming) != in.m_Timing)
{
@@ -353,7 +353,7 @@ static RString GetSSCNoteData( const Song &song, const Steps &in, bool bSavingCa
}
if (song.GetAttackString() != in.GetAttackString())
lines.push_back( ssprintf("#ATTACKS:%s;", in.GetAttackString().c_str()));
switch( in.GetDisplayBPM() )
{
case DISPLAY_BPM_ACTUAL:
+6 -7
View File
@@ -752,24 +752,23 @@ void Player::SendComboMessages( int iOldCombo, int iOldMissCombo )
}
static void GenerateCacheDataStructure(PlayerState *pPlayerState, NoteData &notes) {
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 lastRealBeat = 0.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;
lastRealBeat = seg->GetBeat();
lastRatio = seg->GetRatio();
CacheDisplayedBeat c = { seg->GetBeat(), displayedBeat, seg->GetRatio() };
pPlayerState->m_CacheDisplayedBeat.push_back( c );
}
}
void Player::Update( float fDeltaTime )
+72 -108
View File
@@ -1864,7 +1864,7 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
else
fDelta *= 40;
}
float fNewBPM = fBPM + fDelta;
GetAppropriateTiming().SetBPMAtBeat( GetBeat(), fNewBPM );
(fDelta>0 ? m_soundValueIncrease : m_soundValueDecrease).Play();
@@ -1893,19 +1893,21 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
fDelta *= 40;
}
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
{
// create a new StopSegment
if( fDelta > 0 )
GetAppropriateTiming().AddSegment(SEGMENT_STOP,
new StopSegment( GetRow(), fDelta) );
GetAppropriateTiming().AddSegment( StopSegment(GetRow(), fDelta) );
}
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 )
stops.erase( stops.begin()+i, stops.begin()+i+1);
}
#endif
(fDelta>0 ? m_soundValueIncrease : m_soundValueDecrease).Play();
SetDirty( true );
}
@@ -2962,59 +2965,67 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM )
else if( SM == SM_BackFromBPMChange && !ScreenTextEntry::s_bCancelledLast )
{
float fBPM = StringToFloat( ScreenTextEntry::s_sLastAnswer );
if( fBPM > 0 )
GetAppropriateTiming().SetBPMAtBeat( GetBeat(), fBPM );
GetAppropriateTiming().AddSegment( BPMSegment(GetRow(), fBPM) );
SetDirty( true );
}
else if( SM == SM_BackFromStopChange && !ScreenTextEntry::s_bCancelledLast )
{
float fStop = StringToFloat( ScreenTextEntry::s_sLastAnswer );
if( fStop >= 0 )
GetAppropriateTiming().SetStopAtBeat( GetBeat(), fStop );
GetAppropriateTiming().AddSegment( StopSegment(GetRow(), fStop) );
SetDirty( true );
}
else if( SM == SM_BackFromDelayChange && !ScreenTextEntry::s_bCancelledLast )
{
float fDelay = StringToFloat( ScreenTextEntry::s_sLastAnswer );
if( fDelay >= 0 )
GetAppropriateTiming().SetDelayAtBeat( GetBeat(), fDelay );
GetAppropriateTiming().AddSegment( DelaySegment(GetRow(), fDelay) );
SetDirty( true );
}
else if( SM == SM_BackFromTimeSignatureChange && !ScreenTextEntry::s_bCancelledLast )
{
int iNum, iDen;
if( sscanf( ScreenTextEntry::s_sLastAnswer.c_str(), " %d / %d ", &iNum, &iDen ) == 2 )
{
GetAppropriateTiming().SetTimeSignatureAtBeat( GetBeat(), iNum, iDen );
}
GetAppropriateTiming().AddSegment( TimeSignatureSegment(GetRow(), iNum, iDen) );
SetDirty( true );
}
else if ( SM == SM_BackFromTickcountChange && !ScreenTextEntry::s_bCancelledLast )
{
int iTick = StringToInt( ScreenTextEntry::s_sLastAnswer );
if ( iTick >= 0 && iTick <= ROWS_PER_BEAT )
{
GetAppropriateTiming().SetTickcountAtBeat( GetBeat(), iTick );
}
GetAppropriateTiming().AddSegment( TickcountSegment( GetRow(), iTick) );
SetDirty( true );
}
else if ( SM == SM_BackFromComboChange && !ScreenTextEntry::s_bCancelledLast )
{
int iCombo, iMiss;
if (sscanf(ScreenTextEntry::s_sLastAnswer.c_str(), " %d / %d ", &iCombo, &iMiss) == 2)
{
GetAppropriateTiming().SetComboAtBeat( GetBeat(), iCombo, iMiss );
}
GetAppropriateTiming().AddSegment( ComboSegment(GetRow(), iCombo, iMiss) );
SetDirty( true );
}
else if ( SM == SM_BackFromLabelChange && !ScreenTextEntry::s_bCancelledLast )
{
RString sLabel = ScreenTextEntry::s_sLastAnswer;
if ( !GetAppropriateTiming().DoesLabelExist(sLabel) )
{
// XXX: these should be in the NotesWriters where they're needed.
sLabel.Replace("=", "_");
sLabel.Replace(",", "_");
GetAppropriateTiming().SetLabelAtBeat( GetBeat(), sLabel );
GetAppropriateTiming().AddSegment( LabelSegment(GetRow(), sLabel) );
SetDirty( true );
}
}
@@ -3074,7 +3085,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM )
float fFake = StringToFloat( ScreenTextEntry::s_sLastAnswer );
if( fFake >= 0 ) // allow 0 to kill a warp.
{
GetAppropriateTiming().SetFakeAtBeat( GetBeat(), fFake );
GetAppropriateTiming().AddSegment( FakeSegment(GetRow(), fFake) );
SetDirty( true );
}
}
@@ -3472,12 +3483,13 @@ static void ChangeArtistTranslit( const RString &sNew )
static void ChangeBeat0Offset( const RString &sNew )
{
TimingData &timing = (GAMESTATE->m_bIsUsingStepTiming ?
GAMESTATE->m_pCurSteps[PLAYER_1]->m_Timing :
TimingData &timing = (GAMESTATE->m_bIsUsingStepTiming ?
GAMESTATE->m_pCurSteps[PLAYER_1]->m_Timing :
GAMESTATE->m_pCurSong->m_SongTiming);
float old = timing.m_fBeat0OffsetInSeconds;
timing.m_fBeat0OffsetInSeconds = StringToFloat( sNew );
timing.m_fBeat0OffsetInSeconds = StringToFloat(sNew);
float delta = timing.m_fBeat0OffsetInSeconds - old;
if (GAMESTATE->m_bIsUsingStepTiming)
{
GAMESTATE->m_pCurSteps[PLAYER_1]->m_Attacks.UpdateStartTimes(delta);
@@ -3578,14 +3590,19 @@ void ScreenEdit::DisplayTimingMenu()
float fBeat = GetBeat();
TimingData &pTime = GetAppropriateTiming();
bool bHasSpeedOnThisRow = pTime.GetSpeedSegmentAtBeat( fBeat )->GetBeat() == fBeat;
g_TimingDataInformation.rows[beat_0_offset].SetOneUnthemedChoice( ssprintf("%.6f", pTime.m_fBeat0OffsetInSeconds) );
g_TimingDataInformation.rows[bpm].SetOneUnthemedChoice( ssprintf("%.6f", pTime.GetBPMAtBeat( fBeat ) ) );
g_TimingDataInformation.rows[stop].SetOneUnthemedChoice( ssprintf("%.6f", pTime.GetStopAtBeat( fBeat ) ) ) ;
g_TimingDataInformation.rows[delay].SetOneUnthemedChoice( ssprintf("%.6f", pTime.GetDelayAtBeat( fBeat ) ) );
g_TimingDataInformation.rows[time_signature].SetOneUnthemedChoice(ssprintf("%d / %d",
pTime.GetTimeSignatureNumeratorAtBeat( fBeat ),
pTime.GetTimeSignatureDenominatorAtBeat( fBeat ) ) );
g_TimingDataInformation.rows[time_signature].SetOneUnthemedChoice(
ssprintf( "%d / %d",
pTime.GetTimeSignatureSegmentAtBeat(fBeat)->GetNum(),
pTime.GetTimeSignatureSegmentAtBeat(fBeat)->GetDen()
)
);
g_TimingDataInformation.rows[label].SetOneUnthemedChoice( pTime.GetLabelAtBeat( fBeat ).c_str() );
g_TimingDataInformation.rows[tickcount].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTickcountAtBeat( fBeat ) ) );
g_TimingDataInformation.rows[combo].SetOneUnthemedChoice( ssprintf("%d / %d",
@@ -3594,16 +3611,16 @@ void ScreenEdit::DisplayTimingMenu()
g_TimingDataInformation.rows[warp].SetOneUnthemedChoice( ssprintf("%.6f", pTime.GetWarpAtBeat( fBeat ) ) );
g_TimingDataInformation.rows[speed_percent].SetOneUnthemedChoice( bHasSpeedOnThisRow ? ssprintf("%.6f", pTime.GetSpeedPercentAtBeat( fBeat ) ) : "---" );
g_TimingDataInformation.rows[speed_wait].SetOneUnthemedChoice( bHasSpeedOnThisRow ? ssprintf("%.6f", pTime.GetSpeedWaitAtBeat( fBeat ) ) : "---" );
RString starting = ( pTime.GetSpeedModeAtBeat( fBeat ) == 1 ? "Seconds" : "Beats" );
g_TimingDataInformation.rows[speed_mode].SetOneUnthemedChoice( starting.c_str() );
g_TimingDataInformation.rows[scroll].SetOneUnthemedChoice( ssprintf("%.6f", pTime.GetScrollAtBeat( fBeat ) ) );
g_TimingDataInformation.rows[fake].SetOneUnthemedChoice( ssprintf("%.6f", pTime.GetFakeAtBeat( fBeat ) ) );
g_TimingDataInformation.rows[speed_wait].bEnabled = bHasSpeedOnThisRow;
g_TimingDataInformation.rows[speed_mode].bEnabled = bHasSpeedOnThisRow;
EditMiniMenu( &g_TimingDataInformation, SM_BackFromTimingDataInformation );
}
@@ -4167,9 +4184,9 @@ void ScreenEdit::HandleAlterMenuChoice(AlterMenuChoice c, const vector<int> &iAn
}
case convert_to_fake:
{
float startBeat = NoteRowToBeat(m_NoteFieldEdit.m_iBeginMarker);
float lengthBeat = NoteRowToBeat(m_NoteFieldEdit.m_iEndMarker) - startBeat;
GetAppropriateTiming().SetFakeAtBeat(startBeat,lengthBeat);
int startRow = m_NoteFieldEdit.m_iBeginMarker;
float lengthBeat = NoteRowToBeat(m_NoteFieldEdit.m_iEndMarker) - NoteRowToBeat(startRow);
GetAppropriateTiming().AddSegment( FakeSegment(startRow,lengthBeat) );
SetDirty(true);
break;
}
@@ -4279,7 +4296,7 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector<int> &iAns
switch( c )
{
DEFAULT_FAIL( c );
case paste_at_current_beat:
case paste_at_begin_marker:
{
@@ -4302,82 +4319,28 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector<int> &iAns
break;
case paste_partial_timing_at_beat:
{
#if 0
int firstRow = BeatToNoteRow(GetAppropriatePosition().m_fSongBeat);
FOREACH_ENUM(TimingSegmentType, tst)
FOREACH_TimingSegmentType( tst )
{
/* TODO: Maybe wipe out the already there 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 is an exact dupe of TimingData::CopyRange... */
for (unsigned i = 0; i < vSegs.size(); i++)
{
// TODO: This REALLY needs improving.
TimingSegment * org = this->clipboardTiming.m_avpTimingSegments[tst][i];
TimingSegment * cpy;
switch (tst)
{
case SEGMENT_BPM:
{
cpy = new BPMSegment(*(static_cast<BPMSegment *>(org)));
break;
}
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();
const TimingSegment *seg = vSegs[i];
TimingSegment *cpy = seg->Copy();
int oldRow = cpy->GetRow() + firstRow;
int newRow = oldRow + firstRow;
cpy->SetRow(newRow);
GetAppropriateTiming().AddSegment(tst, cpy);
GetAppropriateTiming().AddSegment( cpy );
}
}
#endif
break;
}
case insert_and_shift:
@@ -4410,9 +4373,9 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector<int> &iAns
TimingData &timing = GetAppropriateTiming();
float pause = timing.GetDelayAtRow(GetRow());
timing.SetDelayAtRow(GetRow(), 0);
float pauseBeats = pause * timing.GetBPMAtBeat(GetBeat()) / 60;
NoteDataUtil::InsertRows(m_NoteDataEdit, GetRow(), BeatToNoteRow(pauseBeats));
timing.InsertRows(GetRow(), BeatToNoteRow(pauseBeats));
break;
@@ -4991,7 +4954,8 @@ void ScreenEdit::CheckNumberOfNotesAndUndo()
if( EDIT_MODE.GetValue() != EditMode_Home )
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();
for( int row=0; row<=m_NoteDataEdit.GetLastRow(); row+=rowsPerMeasure )
+276 -713
View File
File diff suppressed because it is too large Load Diff
+176 -524
View File
@@ -10,16 +10,29 @@ struct lua_State;
/** @brief Compare a TimingData segment's properties with one another. */
#define COMPARE(x) if(this->x!=other.x) return false;
/* 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
return static_cast<T*>( t );
ASSERT_M( t && tst == t->GetType(),
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) \
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) \
TimingSegmentToXWithName(Seg##Segment, Seg, SEGMENT_##SegType)
@@ -46,10 +59,25 @@ TimingSegmentToX( Fake, FAKE );
class TimingData
{
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;
unsigned GetSegmentIndexAtBeat(TimingSegmentType tst, float beat) const
TimingData( const TimingData& rhs ) : m_sFile(rhs.m_sFile),
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) );
}
@@ -68,12 +96,6 @@ public:
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;
/**
* @brief Gets the actual BPM of the song,
@@ -85,30 +107,6 @@ public:
* @param highest the highest allowed max BPM.
*/
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.
@@ -116,6 +114,7 @@ public:
* @param tst the TimingSegmentType requested.
* @return the segment in question.
*/
const TimingSegment* GetSegmentAtRow( int iNoteRow, TimingSegmentType tst ) const;
TimingSegment* GetSegmentAtRow( int iNoteRow, TimingSegmentType tst );
/**
@@ -124,511 +123,176 @@ public:
* @param tst the TimingSegmentType requested.
* @return the segment in question.
*/
TimingSegment* GetSegmentAtBeat( float fBeat, TimingSegmentType tst )
const TimingSegment* GetSegmentAtBeat( float fBeat, TimingSegmentType tst ) const
{
return GetSegmentAtRow( BeatToNoteRow(fBeat), tst );
}
TimingSegment* GetSegmentAtBeat( float fBeat, TimingSegmentType tst )
{
return const_cast<TimingSegment*>( GetSegmentAtBeat(fBeat, tst) );
}
void SetTimingSegmentAtRow( TimingSegment *seg, int iNoteRow );
/* XXX: convenience shortcuts. We should get rid of these later. */
#define GetAndSetSegmentWithName(Seg, SegName, SegType) \
#define DefineSegmentWithName(Seg, SegName, SegType) \
const Seg* Get##Seg##AtRow( int iNoteRow ) const \
{ \
const TimingSegment *t = GetSegmentAtRow( iNoteRow, SegType ); \
return To##SegName( t ); \
} \
Seg* Get##Seg##AtRow( int iNoteRow ) \
{ \
TimingSegment *t = GetSegmentAtRow( iNoteRow, SegType ); \
return To##SegName( t ); \
return const_cast<Seg*> (((const TimingData*)this)->Get##Seg##AtRow(iNoteRow) ); \
} \
const Seg* Get##Seg##AtBeat( float fBeat ) const \
{ \
return Get##Seg##AtRow( BeatToNoteRow(fBeat) ); \
} \
Seg* Get##Seg##AtBeat( float fBeat ) \
{ \
TimingSegment *t = GetSegmentAtBeat( fBeat, SegType ); \
return To##SegName( t ); \
return const_cast<Seg*> (((const TimingData*)this)->Get##Seg##AtBeat(fBeat) ); \
} \
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)
#define GetAndSetSegment(Seg, SegType ) \
GetAndSetSegmentWithName( Seg##Segment, Seg, SEGMENT_##SegType )
#define DefineSegment(Seg, SegType ) \
DefineSegmentWithName( Seg##Segment, Seg, SEGMENT_##SegType )
GetAndSetSegment( BPM, BPM );
GetAndSetSegment( Stop, STOP );
GetAndSetSegment( Delay, DELAY );
GetAndSetSegment( Warp, WARP );
GetAndSetSegment( Label, LABEL );
GetAndSetSegment( Tickcount, TICKCOUNT );
GetAndSetSegment( Combo, COMBO );
GetAndSetSegment( Speed, SPEED );
GetAndSetSegment( Scroll, SCROLL );
GetAndSetSegment( Fake, FAKE );
GetAndSetSegment( TimeSignature, TIME_SIG );
DefineSegment( BPM, BPM );
DefineSegment( Stop, STOP );
DefineSegment( Delay, DELAY );
DefineSegment( Warp, WARP );
DefineSegment( Label, LABEL );
DefineSegment( Tickcount, TICKCOUNT );
DefineSegment( Combo, COMBO );
DefineSegment( Speed, SPEED );
DefineSegment( Scroll, SCROLL );
DefineSegment( Fake, FAKE );
DefineSegment( TimeSignature, TIME_SIG );
#undef GetAndSetSegmentWithName
#undef GetAndSetSegment
#undef DefineSegmentWithName
#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 ); }
/**
* @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 GetStopAtRow( int iNoteRow ) const { return GetStopSegmentAtRow(iNoteRow)->GetPause(); }
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 ); }
/**
* @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 GetDelayAtRow( int iNoteRow ) const { return GetDelaySegmentAtRow(iNoteRow)->GetPause(); }
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 ); }
/**
* @brief Set the row to have the new delay time.
*
* 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 SetTimeSignatureAtRow( int iNoteRow, int iNum, int iDen )
{
AddSegment( TimeSignatureSegment(iNoteRow, iNum, iDen) );
}
/**
* @brief Retrieve the Time Signature's numerator at the given row.
* @param iNoteRow the row in question.
* @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); }
void SetTimeSignatureAtBeat( float fBeat, int iNum, int iDen )
{
SetTimeSignatureAtRow( BeatToNoteRow(fBeat), iNum, iDen );
}
/**
* @brief Determine the beat to warp to.
* @param iRow The row you start on.
* @return the beat you warp to.
*/
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 ); }
float GetWarpAtRow( int iNoteRow ) const { return GetWarpSegmentAtRow(iNoteRow)->GetLength(); }
float GetWarpAtBeat( float fBeat ) const { return GetWarpAtRow( BeatToNoteRow(fBeat) ); }
/* Note: fLength is in beats, not rows */
void SetWarpAtRow( int iRow, float fLength ) { AddSegment( WarpSegment(iRow, fLength) ); }
void SetWarpAtBeat( float fBeat, float fLength ) { AddSegment( WarpSegment(BeatToNoteRow(fBeat), fLength) ); }
/**
* @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 GetTickcountAtRow( int iNoteRow ) const { return GetTickcountSegmentAtRow(iNoteRow)->GetTicks(); }
int GetTickcountAtBeat( float fBeat ) const { return GetTickcountAtRow( BeatToNoteRow(fBeat) ); }
/**
* @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 SetTickcountAtRow( int iNoteRow, int iTicks ) { AddSegment( TickcountSegment(iNoteRow, iTicks) ); }
void SetTickcountAtBeat( float fBeat, int iTicks ) { SetTickcountAtRow( BeatToNoteRow( fBeat ), iTicks ); }
/**
* @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 GetComboAtRow( int iNoteRow ) const { return GetComboSegmentAtRow(iNoteRow)->GetCombo(); }
int GetComboAtBeat( float fBeat ) const { return GetComboAtRow( BeatToNoteRow(fBeat) ); }
/**
* @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 GetMissComboAtRow( int iNoteRow ) const { return GetComboSegmentAtRow(iNoteRow)->GetMissCombo(); }
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 ); }
/**
* @brief Retrieve the Label at the given row.
* @param iNoteRow the row in question.
* @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.
*/
const RString& GetLabelAtRow( int iNoteRow ) const { return GetLabelSegmentAtRow(iNoteRow)->GetLabel(); }
const RString& GetLabelAtBeat( float fBeat ) const { return GetLabelAtRow( BeatToNoteRow(fBeat) ); }
void SetLabelAtRow( int iNoteRow, const RString& sLabel ) { AddSegment( LabelSegment(iNoteRow,sLabel) ); }
void SetLabelAtBeat( float fBeat, const RString sLabel ) { SetLabelAtRow( BeatToNoteRow( fBeat ), sLabel ); }
bool DoesLabelExist( const RString& sLabel ) const;
/**
* @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 GetSpeedPercentAtRow( int iNoteRow ) { return GetSpeedSegmentAtRow(iNoteRow)->GetRatio(); }
float GetSpeedPercentAtBeat( float fBeat ) { return GetSpeedPercentAtRow( BeatToNoteRow(fBeat) ); }
/**
* @brief Retrieve the Speed's wait at the given row.
* @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 GetSpeedWaitAtRow( int iNoteRow ) { return GetSpeedSegmentAtRow(iNoteRow)->GetDelay(); }
float GetSpeedWaitAtBeat( float fBeat ) { return GetSpeedWaitAtRow( BeatToNoteRow(fBeat) ); }
/**
* @brief Retrieve the Speed's mode at the given row.
* @param iNoteRow the row in question.
* @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.
*/
// XXX: is there any point to having specific unit types?
SpeedSegment::BaseUnit GetSpeedModeAtRow( int iNoteRow ) const { return GetSpeedSegmentAtRow(iNoteRow)->GetUnit(); }
SpeedSegment::BaseUnit GetSpeedModeAtBeat( float fBeat ) { return GetSpeedModeAtRow( BeatToNoteRow(fBeat) ); }
/**
* @brief Set the row to have the new Speed.
* @param iNoteRow the row to have the new Speed.
* @param fPercent the percent.
* @param fWait the wait.
* @param usMode the mode.
*/
void SetSpeedAtRow( int iNoteRow, float fPercent, float fWait, SpeedSegment::BaseUnit unit );
/**
* @brief Set the beat to have the new Speed.
* @param fBeat the beat to have the new Speed.
* @param fPercent the percent.
* @param fWait the wait.
* @param usMode the mode.
*/
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.
* @param iNoteRow the row to have the new Speed percent.
* @param fPercent the percent.
*/
void SetSpeedPercentAtRow( int iNoteRow, float fPercent );
/**
* @brief Set the beat to have the new Speed percent.
* @param fBeat the beat to have the new Speed percent.
* @param fPercent the percent.
*/
void SetSpeedAtRow( int iNoteRow, float fPercent, float fWait, SpeedSegment::BaseUnit unit )
{
AddSegment( SpeedSegment(iNoteRow, fPercent, fWait, unit) );
}
void SetSpeedAtBeat( float fBeat, float fPercent, float fWait, SpeedSegment::BaseUnit unit )
{
SetSpeedAtRow( BeatToNoteRow(fBeat), fPercent, fWait, unit );
}
void SetSpeedPercentAtRow( int iNoteRow, float fPercent )
{
const SpeedSegment* seg = GetSpeedSegmentAtRow(iNoteRow);
SetSpeedAtRow( iNoteRow, fPercent, seg->GetDelay(), seg->GetUnit() );
}
void SetSpeedWaitAtRow( int iNoteRow, float fWait )
{
const SpeedSegment* seg = GetSpeedSegmentAtRow(iNoteRow);
SetSpeedAtRow( iNoteRow, seg->GetRatio(), fWait, seg->GetUnit() );
}
void SetSpeedModeAtRow( int iNoteRow, SpeedSegment::BaseUnit unit )
{
const SpeedSegment* seg = GetSpeedSegmentAtRow(iNoteRow);
SetSpeedAtRow( iNoteRow, seg->GetRatio(), seg->GetDelay(), unit );
}
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); }
/**
* @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); }
float GetDisplayedSpeedPercent( float fBeat, float fMusicSeconds ) const;
/**
* @brief Retrieve the scrolling factor at the given row.
* @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 GetScrollAtRow( int iNoteRow ) const { return GetScrollSegmentAtRow(iNoteRow)->GetRatio(); }
float GetScrollAtBeat( float fBeat ) { return GetScrollAtRow( BeatToNoteRow(fBeat) ); }
/**
* @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 SetScrollAtRow( int iNoteRow, float fPercent ) { AddSegment( ScrollSegment(iNoteRow, fPercent) ); }
void SetScrollAtBeat( float fBeat, float fPercent ) { SetScrollAtRow( BeatToNoteRow(fBeat), fPercent ); }
/**
* @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 GetFakeAtRow( int iRow ) const { return GetFakeSegmentAtRow(iRow)->GetLength(); }
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 ); }
/**
* @brief Checks if the row is inside a fake.
* @param iRow the row to focus on.
* @return true if the row is inside a fake, false otherwise.
*/
bool IsWarpAtRow( int iRow ) const;
bool IsWarpAtBeat( float fBeat ) const { return IsWarpAtRow( BeatToNoteRow( fBeat ) ); }
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 ) ); }
/**
* @brief Determine if this notes on this row can be judged.
* @param row the row to focus on.
* @return true if the row can be judged, false otherwise. */
bool IsJudgableAtRow( int row ) const
{
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 IsJudgableAtRow( int row ) const { return !IsWarpAtRow(row) && !IsFakeAtRow(row); }
bool IsJudgableAtBeat( float beat ) const { return IsJudgableAtRow( BeatToNoteRow( beat ) ); }
void MultiplyBPMInBeatRange( int iStartIndex, int iEndIndex, float fFactor );
void NoteRowToMeasureAndBeat( int iNoteRow, int &iMeasureIndexOut, int &iBeatIndexOut, int &iRowsRemainder ) const;
void GetBeatAndBPSFromElapsedTime( float fElapsedTime, float &fBeatOut, float &fBPSOut, bool &bFreezeOut, bool &bDelayOut, int &iWarpBeginOut, float &fWarpLengthOut ) const;
@@ -653,38 +317,16 @@ public:
}
float GetElapsedTimeFromBeatNoOffset( float fBeat ) const;
float GetDisplayedBeat( float fBeat ) const;
/**
* @brief View the TimingData to see if a song changes its BPM at any point.
* @return true if there is at least one change, false otherwise.
*/
bool HasBpmChanges() const;
/**
* @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 HasBpmChanges() const { return GetTimingSegments(SEGMENT_BPM).size() > 1; }
bool HasStops() const { return !GetTimingSegments(SEGMENT_STOP).empty(); }
bool HasDelays() const { return !GetTimingSegments(SEGMENT_DELAY).empty(); }
bool HasWarps() const { return !GetTimingSegments(SEGMENT_WARP).empty(); }
bool HasFakes() const { return !GetTimingSegments(SEGMENT_FAKE).empty(); }
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;
/**
* @brief Compare two sets of timing data to see if they are equal.
* @param other the other TimingData.
@@ -720,6 +362,13 @@ public:
void InsertRows( int iStartRow, int iRowsToAdd );
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.
*/
@@ -727,6 +376,7 @@ public:
// Lua
void PushSelf( lua_State *L );
/**
* @brief The file of the song/steps that use this TimingData.
*
@@ -734,15 +384,17 @@ public:
*/
RString m_sFile;
// All of the following vectors must be sorted before gameplay.
vector<TimingSegment *> m_avpTimingSegments[NUM_TimingSegmentType];
/**
* @brief The initial offset of a song.
*/
/** @brief The initial offset of a song. */
float m_fBeat0OffsetInSeconds;
// XXX: this breaks encapsulation. get rid of it ASAP
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
@@ -751,7 +403,7 @@ public:
/**
* @file
* @author Chris Danford, Glenn Maynard (c) 2001-2004
* @author Chris Danford, Glenn Maynard (c) 2001-2004
* @section LICENSE
* All rights reserved.
*
+93
View File
@@ -24,6 +24,99 @@ void TimingSegment::Scale( int start, int length, int newLength )
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 str = "%.0" + IntToString(dec)
+288 -9
View File
@@ -20,26 +20,48 @@ enum TimingSegmentType
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 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
* XXX: this should be an abstract class.
*/
struct TimingSegment
{
virtual TimingSegmentType GetType() const
{
return TimingSegmentType_Invalid;
}
virtual TimingSegmentType GetType() const { return TimingSegmentType_Invalid; }
virtual SegmentEffectType GetEffectType() const { return SegmentEffectType_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( float fBeat ) : m_iStartRow(ToNoteRow(fBeat)) { }
TimingSegment(const TimingSegment &other) :
m_iStartRow( other.GetRow() ) { }
// for our purposes, two floats within this level of error are equal
static const double EPSILON = 1e-4f;
virtual ~TimingSegment() { }
/**
@@ -66,14 +88,17 @@ struct TimingSegment
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
{
LOG->Trace( __PRETTY_FUNCTION__ );
return GetRow() == other.GetRow();
}
virtual bool operator!=( const TimingSegment &other ) const
{
return !operator==(other);
return !this->operator==(other);
}
private:
@@ -95,6 +120,12 @@ private:
struct FakeSegment : public TimingSegment
{
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) { }
@@ -118,6 +149,23 @@ struct FakeSegment : public TimingSegment
void Scale( int start, int length, int newLength );
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:
/** @brief The number of rows the FakeSegment is alive for. */
int m_iLengthRows;
@@ -133,6 +181,11 @@ private:
struct WarpSegment : public TimingSegment
{
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) { }
@@ -154,8 +207,24 @@ struct WarpSegment : public TimingSegment
void SetLength( float fBeats ) { m_iLengthRows = ToNoteRow(fBeats); }
void Scale( int start, int length, int newLength );
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:
/** @brief The number of rows the WarpSegment will warp past. */
int m_iLengthRows;
@@ -170,12 +239,19 @@ private:
* 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
{
/** @brief The default amount of ticks per beat. */
static const unsigned DEFAULT_TICK_COUNT = 4;
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 ) :
TimingSegment(iStartRow), m_iTicksPerBeat(iTicks) { }
@@ -188,6 +264,22 @@ struct TickcountSegment : public TimingSegment
void SetTicks( int iTicks ) { m_iTicksPerBeat = iTicks; }
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:
/** @brief The amount of hold checkpoints counted per beat */
int m_iTicksPerBeat;
@@ -202,6 +294,12 @@ private:
struct ComboSegment : public TimingSegment
{
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 ) :
TimingSegment(iStartRow), m_iCombo(iCombo),
@@ -219,6 +317,23 @@ struct ComboSegment : public TimingSegment
void SetMissCombo( int iCombo ) { m_iMissCombo = iCombo; }
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:
/** @brief The amount the combo increases at this point. */
int m_iCombo;
@@ -237,6 +352,12 @@ private:
struct LabelSegment : public TimingSegment
{
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() ) :
TimingSegment(iStartRow), m_sLabel(sLabel) { }
@@ -249,6 +370,22 @@ struct LabelSegment : public TimingSegment
void SetLabel( const RString& sLabel ) { m_sLabel.assign(sLabel); }
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:
/** @brief The label/section name for this point. */
RString m_sLabel;
@@ -260,6 +397,12 @@ private:
struct BPMSegment : public TimingSegment
{
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)
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; }
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:
/** @brief The number of beats per second within this BPMSegment. */
float m_fBPS;
@@ -291,6 +451,12 @@ private:
struct TimeSignatureSegment : public TimingSegment
{
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,
int iNum = 4, int iDenom = 4 ) :
@@ -308,6 +474,8 @@ struct TimeSignatureSegment : public TimingSegment
int GetDen() const { return m_iDenominator; }
void SetDen( int den ) { m_iDenominator = den; }
void Set( int num, int den ) { m_iNumerator = num; m_iDenominator = den; }
RString ToString( int dec ) const;
/**
@@ -325,6 +493,23 @@ struct TimeSignatureSegment : public TimingSegment
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:
int m_iNumerator, m_iDenominator;
};
@@ -342,6 +527,12 @@ private:
struct SpeedSegment : public TimingSegment
{
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. */
enum BaseUnit { UNIT_BEATS, UNIT_SECONDS };
@@ -369,6 +560,25 @@ struct SpeedSegment : public TimingSegment
void Scale( int start, int length, int newLength );
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:
/** @brief The percentage by which the Player's BPM is multiplied. */
float m_fRatio;
@@ -393,6 +603,12 @@ private:
struct ScrollSegment : public TimingSegment
{
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 ) :
TimingSegment(iStartRow), m_fRatio(fRatio) { }
@@ -405,6 +621,23 @@ struct ScrollSegment : public TimingSegment
void SetRatio( float fRatio ) { m_fRatio = fRatio; }
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:
/** @brief The percentage by which the chart's scroll rate is multiplied. */
float m_fRatio;
@@ -416,6 +649,12 @@ private:
struct StopSegment : public TimingSegment
{
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 ) :
TimingSegment(iStartRow), m_fSeconds(fSeconds) { }
@@ -428,6 +667,22 @@ struct StopSegment : public TimingSegment
void SetPause( float fSeconds ) { m_fSeconds = fSeconds; }
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:
/** @brief The number of seconds to pause at the segment's row. */
float m_fSeconds;
@@ -439,8 +694,14 @@ private:
struct DelaySegment : public TimingSegment
{
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) { }
DelaySegment( const DelaySegment &other ) :
@@ -451,11 +712,29 @@ struct DelaySegment : public TimingSegment
void SetPause( float fSeconds ) { m_fSeconds = fSeconds; }
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:
/** @brief The number of seconds to pause at the segment's row. */
float m_fSeconds;
};
#undef COMPARE
#undef COMPARE_FLOAT
#endif